##// END OF EJS Templates
added some fixes to LDAP form re-submition, new simples ldap-settings getter....
marcink -
r1292:c0335c1d beta
parent child Browse files
Show More
@@ -143,14 +143,14 b' Setting up LDAP support'
143 143 -----------------------
144 144
145 145 RhodeCode starting from version 1.1 supports ldap authentication. In order
146 to use LDAP, you have to install the python-ldap_ package. This package is available
147 via pypi, so you can install it by running
146 to use LDAP, you have to install the python-ldap_ package. This package is
147 available via pypi, so you can install it by running
148 148
149 ::
149 using easy_install::
150 150
151 151 easy_install python-ldap
152 152
153 ::
153 using pip::
154 154
155 155 pip install python-ldap
156 156
@@ -168,7 +168,7 b" Here's a typical ldap setup::"
168 168 Port = 389
169 169 Account = <account>
170 170 Password = <password>
171 Enable LDAPS = checked
171 Connection Security = LDAPS connection
172 172 Certificate Checks = DEMAND
173 173
174 174 Search settings
@@ -212,11 +212,19 b' Password : optional'
212 212
213 213 .. _Enable LDAPS:
214 214
215 Enable LDAPS : optional
216 Check this if SSL encryption is necessary for communication with the
217 LDAP server - it will likely require `Port`_ to be set to a different
218 value (standard LDAPS port is 636). When LDAPS is enabled then
219 `Certificate Checks`_ is required.
215 Connection Security : required
216 Defines the connection to LDAP server
217
218 No encryption
219 Plain non encrypted connection
220
221 LDAPS connection
222 Enable ldaps connection. It will likely require `Port`_ to be set to
223 a different value (standard LDAPS port is 636). When LDAPS is enabled
224 then `Certificate Checks`_ is required.
225
226 START_TLS on LDAP connection
227 START TLS connection
220 228
221 229 .. _Certificate Checks:
222 230
@@ -32,13 +32,14 b' from pylons import request, response, se'
32 32 from pylons.controllers.util import abort, redirect
33 33 from pylons.i18n.translation import _
34 34
35 from sqlalchemy.exc import DatabaseError
36
35 37 from rhodecode.lib.base import BaseController, render
36 38 from rhodecode.lib import helpers as h
37 39 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
38 from rhodecode.lib.auth_ldap import LdapImportError
39 from rhodecode.model.settings import SettingsModel
40 from rhodecode.lib.exceptions import LdapImportError
40 41 from rhodecode.model.forms import LdapSettingsForm
41 from sqlalchemy.exc import DatabaseError
42 from rhodecode.model.db import RhodeCodeSettings
42 43
43 44 log = logging.getLogger(__name__)
44 45
@@ -74,10 +75,15 b' class LdapSettingsController(BaseControl'
74 75 c.search_scope_choices = self.search_scope_choices
75 76 c.tls_reqcert_choices = self.tls_reqcert_choices
76 77 c.tls_kind_choices = self.tls_kind_choices
78
79 c.search_scope_cur = self.search_scope_default
80 c.tls_reqcert_cur = self.tls_reqcert_default
81 c.tls_kind_cur = self.tls_kind_default
82
77 83 super(LdapSettingsController, self).__before__()
78 84
79 85 def index(self):
80 defaults = SettingsModel().get_ldap_settings()
86 defaults = RhodeCodeSettings.get_ldap_settings()
81 87 c.search_scope_cur = defaults.get('ldap_search_scope')
82 88 c.tls_reqcert_cur = defaults.get('ldap_tls_reqcert')
83 89 c.tls_kind_cur = defaults.get('ldap_tls_kind')
@@ -91,7 +97,6 b' class LdapSettingsController(BaseControl'
91 97 def ldap_settings(self):
92 98 """POST ldap create and store ldap settings"""
93 99
94 settings_model = SettingsModel()
95 100 _form = LdapSettingsForm([x[0] for x in self.tls_reqcert_choices],
96 101 [x[0] for x in self.search_scope_choices],
97 102 [x[0] for x in self.tls_kind_choices])()
@@ -102,7 +107,7 b' class LdapSettingsController(BaseControl'
102 107
103 108 for k, v in form_result.items():
104 109 if k.startswith('ldap_'):
105 setting = settings_model.get(k)
110 setting = RhodeCodeSettings.get_by_name(k)
106 111 setting.app_settings_value = v
107 112 self.sa.add(setting)
108 113
@@ -116,14 +121,13 b' class LdapSettingsController(BaseControl'
116 121 'is missing.'), category='warning')
117 122
118 123 except formencode.Invalid, errors:
124 e = errors.error_dict or {}
119 125
120 c.search_scope_cur = self.search_scope_default
121 c.tls_reqcert_cur = self.search_scope_default
122 126
123 127 return htmlfill.render(
124 128 render('admin/ldap/ldap.html'),
125 129 defaults=errors.value,
126 errors=errors.error_dict or {},
130 errors=e,
127 131 prefix_error=False,
128 132 encoding="UTF-8")
129 133 except Exception:
@@ -40,11 +40,11 b' from rhodecode.lib.base import BaseContr'
40 40 from rhodecode.lib.celerylib import tasks, run_task
41 41 from rhodecode.lib.utils import repo2db_mapper, invalidate_cache, \
42 42 set_rhodecode_config, repo_name_slug
43 from rhodecode.model.db import RhodeCodeUi, Repository, Group
43 from rhodecode.model.db import RhodeCodeUi, Repository, Group, \
44 RhodeCodeSettings
44 45 from rhodecode.model.forms import UserForm, ApplicationSettingsForm, \
45 46 ApplicationUiSettingsForm
46 47 from rhodecode.model.scm import ScmModel
47 from rhodecode.model.settings import SettingsModel
48 48 from rhodecode.model.user import UserModel
49 49
50 50 log = logging.getLogger(__name__)
@@ -68,7 +68,7 b' class SettingsController(BaseController)'
68 68 """GET /admin/settings: All items in the collection"""
69 69 # url('admin_settings')
70 70
71 defaults = SettingsModel().get_app_settings()
71 defaults = RhodeCodeSettings.get_app_settings()
72 72 defaults.update(self.get_hg_ui_settings())
73 73 return htmlfill.render(
74 74 render('admin/settings/settings.html'),
@@ -121,18 +121,17 b' class SettingsController(BaseController)'
121 121 application_form = ApplicationSettingsForm()()
122 122 try:
123 123 form_result = application_form.to_python(dict(request.POST))
124 settings_model = SettingsModel()
125 124
126 125 try:
127 hgsettings1 = settings_model.get('title')
126 hgsettings1 = RhodeCodeSettings.get_by_name('title')
128 127 hgsettings1.app_settings_value = \
129 128 form_result['rhodecode_title']
130 129
131 hgsettings2 = settings_model.get('realm')
130 hgsettings2 = RhodeCodeSettings.get_by_name('realm')
132 131 hgsettings2.app_settings_value = \
133 132 form_result['rhodecode_realm']
134 133
135 hgsettings3 = settings_model.get('ga_code')
134 hgsettings3 = RhodeCodeSettings.get_by_name('ga_code')
136 135 hgsettings3.app_settings_value = \
137 136 form_result['rhodecode_ga_code']
138 137
@@ -48,7 +48,7 b' from rhodecode.lib.auth_ldap import Auth'
48 48
49 49 from rhodecode.model import meta
50 50 from rhodecode.model.user import UserModel
51 from rhodecode.model.db import Permission
51 from rhodecode.model.db import Permission, RhodeCodeSettings
52 52
53 53 log = logging.getLogger(__name__)
54 54
@@ -149,6 +149,7 b' def authenticate(username, password):'
149 149 :param username: username
150 150 :param password: password
151 151 """
152
152 153 user_model = UserModel()
153 154 user = user_model.get_by_username(username, cache=False)
154 155
@@ -176,9 +177,7 b' def authenticate(username, password):'
176 177 log.debug('this user already exists as non ldap')
177 178 return False
178 179
179 from rhodecode.model.settings import SettingsModel
180 ldap_settings = SettingsModel().get_ldap_settings()
181
180 ldap_settings = RhodeCodeSettings.get_ldap_settings()
182 181 #======================================================================
183 182 # FALLBACK TO LDAP AUTH IF ENABLE
184 183 #======================================================================
@@ -204,13 +203,13 b' def authenticate(username, password):'
204 203 password)
205 204 log.debug('Got ldap DN response %s', user_dn)
206 205
206 get_ldap_attr = lambda k:ldap_attrs.get(ldap_settings\
207 .get(k), [''])[0]
208
207 209 user_attrs = {
208 'name': ldap_attrs.get(ldap_settings\
209 .get('ldap_attr_firstname'), [''])[0],
210 'lastname': ldap_attrs.get(ldap_settings\
211 .get('ldap_attr_lastname'),[''])[0],
212 'email': ldap_attrs.get(ldap_settings\
213 .get('ldap_attr_email'), [''])[0],
210 'name': get_ldap_attr('ldap_attr_firstname'),
211 'lastname': get_ldap_attr('ldap_attr_lastname'),
212 'email': get_ldap_attr('ldap_attr_email'),
214 213 }
215 214
216 215 if user_model.create_ldap(username, password, user_dn,
@@ -1,8 +1,15 b''
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # ldap authentication lib
4 # Copyright (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
5 #
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.controllers.changelog
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 RhodeCode authentication library for LDAP
7
8 :created_on: Created on Nov 17, 2010
9 :author: marcink
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
6 13 # This program is free software: you can redistribute it and/or modify
7 14 # it under the terms of the GNU General Public License as published by
8 15 # the Free Software Foundation, either version 3 of the License, or
@@ -15,26 +22,26 b''
15 22 #
16 23 # You should have received a copy of the GNU General Public License
17 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 """
19 Created on Nov 17, 2010
20 25
21 @author: marcink
22 """
23
24 from rhodecode.lib.exceptions import *
25 26 import logging
26 27
28 from rhodecode.lib.exceptions import LdapConnectionError, LdapUsernameError, \
29 LdapPasswordError
30
27 31 log = logging.getLogger(__name__)
28 32
33
29 34 try:
30 35 import ldap
31 36 except ImportError:
37 # means that python-ldap is not installed
32 38 pass
33 39
40
34 41 class AuthLdap(object):
35 42
36 43 def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
37 tls_kind = 'PLAIN', tls_reqcert='DEMAND', ldap_version=3,
44 tls_kind='PLAIN', tls_reqcert='DEMAND', ldap_version=3,
38 45 ldap_filter='(&(objectClass=user)(!(objectClass=computer)))',
39 46 search_scope='SUBTREE',
40 47 attr_login='uid'):
@@ -64,7 +71,6 b' class AuthLdap(object):'
64 71 self.SEARCH_SCOPE = ldap.__dict__['SCOPE_' + search_scope]
65 72 self.attr_login = attr_login
66 73
67
68 74 def authenticate_ldap(self, username, password):
69 75 """Authenticate a user via LDAP and return his/her LDAP properties.
70 76
@@ -102,7 +108,8 b' class AuthLdap(object):'
102 108 if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
103 109 server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
104 110
105 filt = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login, username)
111 filt = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login,
112 username)
106 113 log.debug("Authenticating %r filt %s at %s", self.BASE_DN,
107 114 filt, self.LDAP_SERVER)
108 115 lobjects = server.search_ext_s(self.BASE_DN, self.SEARCH_SCOPE,
@@ -114,7 +121,8 b' class AuthLdap(object):'
114 121 for (dn, _attrs) in lobjects:
115 122 try:
116 123 server.simple_bind_s(dn, password)
117 attrs = server.search_ext_s(dn, ldap.SCOPE_BASE, '(objectClass=*)')[0][1]
124 attrs = server.search_ext_s(dn, ldap.SCOPE_BASE,
125 '(objectClass=*)')[0][1]
118 126 break
119 127
120 128 except ldap.INVALID_CREDENTIALS, e:
@@ -130,6 +138,7 b' class AuthLdap(object):'
130 138 log.debug("LDAP says no such user '%s' (%s)", uid, username)
131 139 raise LdapUsernameError()
132 140 except ldap.SERVER_DOWN, e:
133 raise LdapConnectionError("LDAP can't access authentication server")
141 raise LdapConnectionError("LDAP can't access "
142 "authentication server")
134 143
135 144 return (dn, attrs)
@@ -44,7 +44,8 b' from vcs.utils.lazy import LazyProperty'
44 44
45 45 from rhodecode.model import meta
46 46 from rhodecode.model.caching_query import FromCache
47 from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog, Group
47 from rhodecode.model.db import Repository, User, RhodeCodeUi, UserLog, Group, \
48 RhodeCodeSettings
48 49 from rhodecode.model.repo import RepoModel
49 50 from rhodecode.model.user import UserModel
50 51
@@ -287,8 +288,7 b' def set_rhodecode_config(config):'
287 288
288 289 :param config:
289 290 """
290 from rhodecode.model.settings import SettingsModel
291 hgsettings = SettingsModel().get_app_settings()
291 hgsettings = RhodeCodeSettings.get_app_settings()
292 292
293 293 for k, v in hgsettings.items():
294 294 config[k] = v
@@ -65,6 +65,11 b' class RhodeCodeSettings(Base):'
65 65
66 66
67 67 @classmethod
68 def get_by_name(cls, ldap_key):
69 return Session.query(cls)\
70 .filter(cls.app_settings_name == ldap_key).scalar()
71
72 @classmethod
68 73 def get_app_settings(cls, cache=False):
69 74
70 75 ret = Session.query(cls)
@@ -88,7 +93,7 b' class RhodeCodeSettings(Base):'
88 93 .all()
89 94 fd = {}
90 95 for row in ret:
91 fd.update({row.app_settings_name:str2bool(row.app_settings_value)})
96 fd.update({row.app_settings_name:row.app_settings_value})
92 97 return fd
93 98
94 99
@@ -3,5 +3,19 b' from rhodecode.tests import *'
3 3 class TestLdapSettingsController(TestController):
4 4
5 5 def test_index(self):
6 response = self.app.get(url(controller='admin/ldap_settings', action='index'))
6 self.log_user()
7 response = self.app.get(url(controller='admin/ldap_settings',
8 action='index'))
7 9 # Test response...
10
11 def test_ldap_save_settings(self):
12 pass
13
14 def test_ldap_error_form(self):
15 pass
16
17 def test_ldap_login(self):
18 pass
19
20 def test_ldap_login_incorrect(self):
21 pass
@@ -1,7 +1,6 b''
1 1 from rhodecode.lib.auth import get_crypt_password, check_password
2 from rhodecode.model.db import User
2 from rhodecode.model.db import User, RhodeCodeSettings
3 3 from rhodecode.tests import *
4 from rhodecode.model.settings import SettingsModel
5 4
6 5 class TestAdminSettingsController(TestController):
7 6
@@ -60,7 +59,7 b' class TestAdminSettingsController(TestCo'
60 59 ))
61 60
62 61 assert 'Updated application settings' in response.session['flash'][0][1], 'no flash message about success of change'
63 assert SettingsModel(self.sa).get_app_settings()['rhodecode_ga_code'] == new_ga_code, 'change not in database'
62 assert RhodeCodeSettings.get_app_settings()['rhodecode_ga_code'] == new_ga_code, 'change not in database'
64 63
65 64 response = response.follow()
66 65 assert """_gaq.push(['_setAccount', '%s']);""" % new_ga_code in response.body
@@ -79,7 +78,7 b' class TestAdminSettingsController(TestCo'
79 78 ))
80 79
81 80 assert 'Updated application settings' in response.session['flash'][0][1], 'no flash message about success of change'
82 assert SettingsModel(self.sa).get_app_settings()['rhodecode_ga_code'] == new_ga_code, 'change not in database'
81 assert RhodeCodeSettings.get_app_settings()['rhodecode_ga_code'] == new_ga_code, 'change not in database'
83 82
84 83 response = response.follow()
85 84 assert """_gaq.push(['_setAccount', '%s']);""" % new_ga_code not in response.body
@@ -100,7 +99,7 b' class TestAdminSettingsController(TestCo'
100 99
101 100
102 101 assert 'Updated application settings' in response.session['flash'][0][1], 'no flash message about success of change'
103 assert SettingsModel(self.sa).get_app_settings()['rhodecode_title'] == new_title, 'change not in database'
102 assert RhodeCodeSettings.get_app_settings()['rhodecode_title'] == new_title, 'change not in database'
104 103
105 104 response = response.follow()
106 105 assert """<h1><a href="/">%s</a></h1>""" % new_title in response.body
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now