##// END OF EJS Templates
added debug message for ldap auth
marcink -
r749:fcd4fb51 beta
parent child Browse files
Show More
@@ -1,536 +1,537
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # authentication and permission libraries
3 # authentication and permission libraries
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 4, 2010
21 Created on April 4, 2010
22
22
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from pylons import config, session, url, request
25 from pylons import config, session, url, request
26 from pylons.controllers.util import abort, redirect
26 from pylons.controllers.util import abort, redirect
27 from rhodecode.lib.exceptions import *
27 from rhodecode.lib.exceptions import *
28 from rhodecode.lib.utils import get_repo_slug
28 from rhodecode.lib.utils import get_repo_slug
29 from rhodecode.lib.auth_ldap import AuthLdap
29 from rhodecode.lib.auth_ldap import AuthLdap
30 from rhodecode.model import meta
30 from rhodecode.model import meta
31 from rhodecode.model.user import UserModel
31 from rhodecode.model.user import UserModel
32 from rhodecode.model.caching_query import FromCache
32 from rhodecode.model.caching_query import FromCache
33 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
33 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
34 UserToPerm
34 UserToPerm
35 import bcrypt
35 import bcrypt
36 from decorator import decorator
36 from decorator import decorator
37 import logging
37 import logging
38 import random
38 import random
39 import traceback
39 import traceback
40
40
41 log = logging.getLogger(__name__)
41 log = logging.getLogger(__name__)
42
42
43 class PasswordGenerator(object):
43 class PasswordGenerator(object):
44 """This is a simple class for generating password from
44 """This is a simple class for generating password from
45 different sets of characters
45 different sets of characters
46 usage:
46 usage:
47 passwd_gen = PasswordGenerator()
47 passwd_gen = PasswordGenerator()
48 #print 8-letter password containing only big and small letters of alphabet
48 #print 8-letter password containing only big and small letters of alphabet
49 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
49 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
50 """
50 """
51 ALPHABETS_NUM = r'''1234567890'''#[0]
51 ALPHABETS_NUM = r'''1234567890'''#[0]
52 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
52 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''#[1]
53 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
53 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''#[2]
54 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
54 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' #[3]
55 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
55 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM + ALPHABETS_SPECIAL#[4]
56 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
56 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5]
57 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
57 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
58 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
58 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM#[6]
59 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
59 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM#[7]
60
60
61 def __init__(self, passwd=''):
61 def __init__(self, passwd=''):
62 self.passwd = passwd
62 self.passwd = passwd
63
63
64 def gen_password(self, len, type):
64 def gen_password(self, len, type):
65 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
65 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
66 return self.passwd
66 return self.passwd
67
67
68
68
69 def get_crypt_password(password):
69 def get_crypt_password(password):
70 """Cryptographic function used for password hashing based on sha1
70 """Cryptographic function used for password hashing based on sha1
71 :param password: password to hash
71 :param password: password to hash
72 """
72 """
73 return bcrypt.hashpw(password, bcrypt.gensalt(10))
73 return bcrypt.hashpw(password, bcrypt.gensalt(10))
74
74
75 def check_password(password, hashed):
75 def check_password(password, hashed):
76 return bcrypt.hashpw(password, hashed) == hashed
76 return bcrypt.hashpw(password, hashed) == hashed
77
77
78 def authfunc(environ, username, password):
78 def authfunc(environ, username, password):
79 """
79 """
80 Authentication function used in Mercurial/Git/ and access control,
80 Authentication function used in Mercurial/Git/ and access control,
81 firstly checks for db authentication then if ldap is enabled for ldap
81 firstly checks for db authentication then if ldap is enabled for ldap
82 authentication, also creates ldap user if not in database
82 authentication, also creates ldap user if not in database
83
83
84 :param environ: needed only for using in Basic auth, can be None
84 :param environ: needed only for using in Basic auth, can be None
85 :param username: username
85 :param username: username
86 :param password: password
86 :param password: password
87 """
87 """
88 user_model = UserModel()
88 user_model = UserModel()
89 user = user_model.get_by_username(username, cache=False)
89 user = user_model.get_by_username(username, cache=False)
90
90
91 if user is not None and user.is_ldap is False:
91 if user is not None and user.is_ldap is False:
92 if user.active:
92 if user.active:
93
93
94 if user.username == 'default' and user.active:
94 if user.username == 'default' and user.active:
95 log.info('user %s authenticated correctly', username)
95 log.info('user %s authenticated correctly', username)
96 return True
96 return True
97
97
98 elif user.username == username and check_password(password, user.password):
98 elif user.username == username and check_password(password, user.password):
99 log.info('user %s authenticated correctly', username)
99 log.info('user %s authenticated correctly', username)
100 return True
100 return True
101 else:
101 else:
102 log.error('user %s is disabled', username)
102 log.error('user %s is disabled', username)
103
103
104
104
105 else:
105 else:
106
106
107 #since ldap is searching in case insensitive check if this user is still
107 #since ldap is searching in case insensitive check if this user is still
108 #not in our system
108 #not in our system
109 username = username.lower()
109 username = username.lower()
110 user_obj = user_model.get_by_username(username, cache=False,
110 user_obj = user_model.get_by_username(username, cache=False,
111 case_insensitive=True)
111 case_insensitive=True)
112 if user_obj is not None and user_obj.is_ldap is False:
112 if user_obj is not None and user_obj.is_ldap is False:
113 log.debug('this user already exists as non ldap')
113 return False
114 return False
114
115
115 from rhodecode.model.settings import SettingsModel
116 from rhodecode.model.settings import SettingsModel
116 ldap_settings = SettingsModel().get_ldap_settings()
117 ldap_settings = SettingsModel().get_ldap_settings()
117
118
118 #======================================================================
119 #======================================================================
119 # FALLBACK TO LDAP AUTH IN ENABLE
120 # FALLBACK TO LDAP AUTH IN ENABLE
120 #======================================================================
121 #======================================================================
121 if ldap_settings.get('ldap_active', False):
122 if ldap_settings.get('ldap_active', False):
122
123
123 kwargs = {
124 kwargs = {
124 'server':ldap_settings.get('ldap_host', ''),
125 'server':ldap_settings.get('ldap_host', ''),
125 'base_dn':ldap_settings.get('ldap_base_dn', ''),
126 'base_dn':ldap_settings.get('ldap_base_dn', ''),
126 'port':ldap_settings.get('ldap_port'),
127 'port':ldap_settings.get('ldap_port'),
127 'bind_dn':ldap_settings.get('ldap_dn_user'),
128 'bind_dn':ldap_settings.get('ldap_dn_user'),
128 'bind_pass':ldap_settings.get('ldap_dn_pass'),
129 'bind_pass':ldap_settings.get('ldap_dn_pass'),
129 'use_ldaps':ldap_settings.get('ldap_ldaps'),
130 'use_ldaps':ldap_settings.get('ldap_ldaps'),
130 'ldap_version':3,
131 'ldap_version':3,
131 }
132 }
132 log.debug('Checking for ldap authentication')
133 log.debug('Checking for ldap authentication')
133 try:
134 try:
134 aldap = AuthLdap(**kwargs)
135 aldap = AuthLdap(**kwargs)
135 res = aldap.authenticate_ldap(username, password)
136 res = aldap.authenticate_ldap(username, password)
136
137
137 authenticated = res[1]['uid'][0] == username
138 authenticated = res[1]['uid'][0] == username
138
139
139 if authenticated and user_model.create_ldap(username, password):
140 if authenticated and user_model.create_ldap(username, password):
140 log.info('created new ldap user')
141 log.info('created new ldap user')
141
142
142 return authenticated
143 return authenticated
143 except (LdapUsernameError, LdapPasswordError):
144 except (LdapUsernameError, LdapPasswordError):
144 return False
145 return False
145 except:
146 except:
146 log.error(traceback.format_exc())
147 log.error(traceback.format_exc())
147 return False
148 return False
148 return False
149 return False
149
150
150 class AuthUser(object):
151 class AuthUser(object):
151 """
152 """
152 A simple object that handles a mercurial username for authentication
153 A simple object that handles a mercurial username for authentication
153 """
154 """
154 def __init__(self):
155 def __init__(self):
155 self.username = 'None'
156 self.username = 'None'
156 self.name = ''
157 self.name = ''
157 self.lastname = ''
158 self.lastname = ''
158 self.email = ''
159 self.email = ''
159 self.user_id = None
160 self.user_id = None
160 self.is_authenticated = False
161 self.is_authenticated = False
161 self.is_admin = False
162 self.is_admin = False
162 self.permissions = {}
163 self.permissions = {}
163
164
164 def __repr__(self):
165 def __repr__(self):
165 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
166 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
166
167
167 def set_available_permissions(config):
168 def set_available_permissions(config):
168 """
169 """
169 This function will propagate pylons globals with all available defined
170 This function will propagate pylons globals with all available defined
170 permission given in db. We don't wannt to check each time from db for new
171 permission given in db. We don't wannt to check each time from db for new
171 permissions since adding a new permission also requires application restart
172 permissions since adding a new permission also requires application restart
172 ie. to decorate new views with the newly created permission
173 ie. to decorate new views with the newly created permission
173 :param config:
174 :param config:
174 """
175 """
175 log.info('getting information about all available permissions')
176 log.info('getting information about all available permissions')
176 try:
177 try:
177 sa = meta.Session()
178 sa = meta.Session()
178 all_perms = sa.query(Permission).all()
179 all_perms = sa.query(Permission).all()
179 except:
180 except:
180 pass
181 pass
181 finally:
182 finally:
182 meta.Session.remove()
183 meta.Session.remove()
183
184
184 config['available_permissions'] = [x.permission_name for x in all_perms]
185 config['available_permissions'] = [x.permission_name for x in all_perms]
185
186
186 def set_base_path(config):
187 def set_base_path(config):
187 config['base_path'] = config['pylons.app_globals'].base_path
188 config['base_path'] = config['pylons.app_globals'].base_path
188
189
189
190
190 def fill_perms(user):
191 def fill_perms(user):
191 """
192 """
192 Fills user permission attribute with permissions taken from database
193 Fills user permission attribute with permissions taken from database
193 :param user:
194 :param user:
194 """
195 """
195
196
196 sa = meta.Session()
197 sa = meta.Session()
197 user.permissions['repositories'] = {}
198 user.permissions['repositories'] = {}
198 user.permissions['global'] = set()
199 user.permissions['global'] = set()
199
200
200 #===========================================================================
201 #===========================================================================
201 # fetch default permissions
202 # fetch default permissions
202 #===========================================================================
203 #===========================================================================
203 default_user = UserModel().get_by_username('default', cache=True)
204 default_user = UserModel().get_by_username('default', cache=True)
204
205
205 default_perms = sa.query(RepoToPerm, Repository, Permission)\
206 default_perms = sa.query(RepoToPerm, Repository, Permission)\
206 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
207 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
207 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
208 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
208 .filter(RepoToPerm.user == default_user).all()
209 .filter(RepoToPerm.user == default_user).all()
209
210
210 if user.is_admin:
211 if user.is_admin:
211 #=======================================================================
212 #=======================================================================
212 # #admin have all default rights set to admin
213 # #admin have all default rights set to admin
213 #=======================================================================
214 #=======================================================================
214 user.permissions['global'].add('hg.admin')
215 user.permissions['global'].add('hg.admin')
215
216
216 for perm in default_perms:
217 for perm in default_perms:
217 p = 'repository.admin'
218 p = 'repository.admin'
218 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
219 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
219
220
220 else:
221 else:
221 #=======================================================================
222 #=======================================================================
222 # set default permissions
223 # set default permissions
223 #=======================================================================
224 #=======================================================================
224
225
225 #default global
226 #default global
226 default_global_perms = sa.query(UserToPerm)\
227 default_global_perms = sa.query(UserToPerm)\
227 .filter(UserToPerm.user == sa.query(User)\
228 .filter(UserToPerm.user == sa.query(User)\
228 .filter(User.username == 'default').one())
229 .filter(User.username == 'default').one())
229
230
230 for perm in default_global_perms:
231 for perm in default_global_perms:
231 user.permissions['global'].add(perm.permission.permission_name)
232 user.permissions['global'].add(perm.permission.permission_name)
232
233
233 #default repositories
234 #default repositories
234 for perm in default_perms:
235 for perm in default_perms:
235 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
236 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
236 #disable defaults for private repos,
237 #disable defaults for private repos,
237 p = 'repository.none'
238 p = 'repository.none'
238 elif perm.Repository.user_id == user.user_id:
239 elif perm.Repository.user_id == user.user_id:
239 #set admin if owner
240 #set admin if owner
240 p = 'repository.admin'
241 p = 'repository.admin'
241 else:
242 else:
242 p = perm.Permission.permission_name
243 p = perm.Permission.permission_name
243
244
244 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
245 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
245
246
246 #=======================================================================
247 #=======================================================================
247 # #overwrite default with user permissions if any
248 # #overwrite default with user permissions if any
248 #=======================================================================
249 #=======================================================================
249 user_perms = sa.query(RepoToPerm, Permission, Repository)\
250 user_perms = sa.query(RepoToPerm, Permission, Repository)\
250 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
251 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
251 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
252 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
252 .filter(RepoToPerm.user_id == user.user_id).all()
253 .filter(RepoToPerm.user_id == user.user_id).all()
253
254
254 for perm in user_perms:
255 for perm in user_perms:
255 if perm.Repository.user_id == user.user_id:#set admin if owner
256 if perm.Repository.user_id == user.user_id:#set admin if owner
256 p = 'repository.admin'
257 p = 'repository.admin'
257 else:
258 else:
258 p = perm.Permission.permission_name
259 p = perm.Permission.permission_name
259 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
260 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
260 meta.Session.remove()
261 meta.Session.remove()
261 return user
262 return user
262
263
263 def get_user(session):
264 def get_user(session):
264 """
265 """
265 Gets user from session, and wraps permissions into user
266 Gets user from session, and wraps permissions into user
266 :param session:
267 :param session:
267 """
268 """
268 user = session.get('rhodecode_user', AuthUser())
269 user = session.get('rhodecode_user', AuthUser())
269 #if the user is not logged in we check for anonymous access
270 #if the user is not logged in we check for anonymous access
270 #if user is logged and it's a default user check if we still have anonymous
271 #if user is logged and it's a default user check if we still have anonymous
271 #access enabled
272 #access enabled
272 if user.user_id is None or user.username == 'default':
273 if user.user_id is None or user.username == 'default':
273 anonymous_user = UserModel().get_by_username('default', cache=True)
274 anonymous_user = UserModel().get_by_username('default', cache=True)
274 if anonymous_user.active is True:
275 if anonymous_user.active is True:
275 #then we set this user is logged in
276 #then we set this user is logged in
276 user.is_authenticated = True
277 user.is_authenticated = True
277 user.user_id = anonymous_user.user_id
278 user.user_id = anonymous_user.user_id
278 else:
279 else:
279 user.is_authenticated = False
280 user.is_authenticated = False
280
281
281 if user.is_authenticated:
282 if user.is_authenticated:
282 user = UserModel().fill_data(user)
283 user = UserModel().fill_data(user)
283
284
284 user = fill_perms(user)
285 user = fill_perms(user)
285 session['rhodecode_user'] = user
286 session['rhodecode_user'] = user
286 session.save()
287 session.save()
287 return user
288 return user
288
289
289 #===============================================================================
290 #===============================================================================
290 # CHECK DECORATORS
291 # CHECK DECORATORS
291 #===============================================================================
292 #===============================================================================
292 class LoginRequired(object):
293 class LoginRequired(object):
293 """Must be logged in to execute this function else redirect to login page"""
294 """Must be logged in to execute this function else redirect to login page"""
294
295
295 def __call__(self, func):
296 def __call__(self, func):
296 return decorator(self.__wrapper, func)
297 return decorator(self.__wrapper, func)
297
298
298 def __wrapper(self, func, *fargs, **fkwargs):
299 def __wrapper(self, func, *fargs, **fkwargs):
299 user = session.get('rhodecode_user', AuthUser())
300 user = session.get('rhodecode_user', AuthUser())
300 log.debug('Checking login required for user:%s', user.username)
301 log.debug('Checking login required for user:%s', user.username)
301 if user.is_authenticated:
302 if user.is_authenticated:
302 log.debug('user %s is authenticated', user.username)
303 log.debug('user %s is authenticated', user.username)
303 return func(*fargs, **fkwargs)
304 return func(*fargs, **fkwargs)
304 else:
305 else:
305 log.warn('user %s not authenticated', user.username)
306 log.warn('user %s not authenticated', user.username)
306
307
307 p = ''
308 p = ''
308 if request.environ.get('SCRIPT_NAME') != '/':
309 if request.environ.get('SCRIPT_NAME') != '/':
309 p += request.environ.get('SCRIPT_NAME')
310 p += request.environ.get('SCRIPT_NAME')
310
311
311 p += request.environ.get('PATH_INFO')
312 p += request.environ.get('PATH_INFO')
312 if request.environ.get('QUERY_STRING'):
313 if request.environ.get('QUERY_STRING'):
313 p += '?' + request.environ.get('QUERY_STRING')
314 p += '?' + request.environ.get('QUERY_STRING')
314
315
315 log.debug('redirecting to login page with %s', p)
316 log.debug('redirecting to login page with %s', p)
316 return redirect(url('login_home', came_from=p))
317 return redirect(url('login_home', came_from=p))
317
318
318 class PermsDecorator(object):
319 class PermsDecorator(object):
319 """Base class for decorators"""
320 """Base class for decorators"""
320
321
321 def __init__(self, *required_perms):
322 def __init__(self, *required_perms):
322 available_perms = config['available_permissions']
323 available_perms = config['available_permissions']
323 for perm in required_perms:
324 for perm in required_perms:
324 if perm not in available_perms:
325 if perm not in available_perms:
325 raise Exception("'%s' permission is not defined" % perm)
326 raise Exception("'%s' permission is not defined" % perm)
326 self.required_perms = set(required_perms)
327 self.required_perms = set(required_perms)
327 self.user_perms = None
328 self.user_perms = None
328
329
329 def __call__(self, func):
330 def __call__(self, func):
330 return decorator(self.__wrapper, func)
331 return decorator(self.__wrapper, func)
331
332
332
333
333 def __wrapper(self, func, *fargs, **fkwargs):
334 def __wrapper(self, func, *fargs, **fkwargs):
334 # _wrapper.__name__ = func.__name__
335 # _wrapper.__name__ = func.__name__
335 # _wrapper.__dict__.update(func.__dict__)
336 # _wrapper.__dict__.update(func.__dict__)
336 # _wrapper.__doc__ = func.__doc__
337 # _wrapper.__doc__ = func.__doc__
337 self.user = session.get('rhodecode_user', AuthUser())
338 self.user = session.get('rhodecode_user', AuthUser())
338 self.user_perms = self.user.permissions
339 self.user_perms = self.user.permissions
339 log.debug('checking %s permissions %s for %s %s',
340 log.debug('checking %s permissions %s for %s %s',
340 self.__class__.__name__, self.required_perms, func.__name__,
341 self.__class__.__name__, self.required_perms, func.__name__,
341 self.user)
342 self.user)
342
343
343 if self.check_permissions():
344 if self.check_permissions():
344 log.debug('Permission granted for %s %s', func.__name__, self.user)
345 log.debug('Permission granted for %s %s', func.__name__, self.user)
345
346
346 return func(*fargs, **fkwargs)
347 return func(*fargs, **fkwargs)
347
348
348 else:
349 else:
349 log.warning('Permission denied for %s %s', func.__name__, self.user)
350 log.warning('Permission denied for %s %s', func.__name__, self.user)
350 #redirect with forbidden ret code
351 #redirect with forbidden ret code
351 return abort(403)
352 return abort(403)
352
353
353
354
354
355
355 def check_permissions(self):
356 def check_permissions(self):
356 """Dummy function for overriding"""
357 """Dummy function for overriding"""
357 raise Exception('You have to write this function in child class')
358 raise Exception('You have to write this function in child class')
358
359
359 class HasPermissionAllDecorator(PermsDecorator):
360 class HasPermissionAllDecorator(PermsDecorator):
360 """Checks for access permission for all given predicates. All of them
361 """Checks for access permission for all given predicates. All of them
361 have to be meet in order to fulfill the request
362 have to be meet in order to fulfill the request
362 """
363 """
363
364
364 def check_permissions(self):
365 def check_permissions(self):
365 if self.required_perms.issubset(self.user_perms.get('global')):
366 if self.required_perms.issubset(self.user_perms.get('global')):
366 return True
367 return True
367 return False
368 return False
368
369
369
370
370 class HasPermissionAnyDecorator(PermsDecorator):
371 class HasPermissionAnyDecorator(PermsDecorator):
371 """Checks for access permission for any of given predicates. In order to
372 """Checks for access permission for any of given predicates. In order to
372 fulfill the request any of predicates must be meet
373 fulfill the request any of predicates must be meet
373 """
374 """
374
375
375 def check_permissions(self):
376 def check_permissions(self):
376 if self.required_perms.intersection(self.user_perms.get('global')):
377 if self.required_perms.intersection(self.user_perms.get('global')):
377 return True
378 return True
378 return False
379 return False
379
380
380 class HasRepoPermissionAllDecorator(PermsDecorator):
381 class HasRepoPermissionAllDecorator(PermsDecorator):
381 """Checks for access permission for all given predicates for specific
382 """Checks for access permission for all given predicates for specific
382 repository. All of them have to be meet in order to fulfill the request
383 repository. All of them have to be meet in order to fulfill the request
383 """
384 """
384
385
385 def check_permissions(self):
386 def check_permissions(self):
386 repo_name = get_repo_slug(request)
387 repo_name = get_repo_slug(request)
387 try:
388 try:
388 user_perms = set([self.user_perms['repositories'][repo_name]])
389 user_perms = set([self.user_perms['repositories'][repo_name]])
389 except KeyError:
390 except KeyError:
390 return False
391 return False
391 if self.required_perms.issubset(user_perms):
392 if self.required_perms.issubset(user_perms):
392 return True
393 return True
393 return False
394 return False
394
395
395
396
396 class HasRepoPermissionAnyDecorator(PermsDecorator):
397 class HasRepoPermissionAnyDecorator(PermsDecorator):
397 """Checks for access permission for any of given predicates for specific
398 """Checks for access permission for any of given predicates for specific
398 repository. In order to fulfill the request any of predicates must be meet
399 repository. In order to fulfill the request any of predicates must be meet
399 """
400 """
400
401
401 def check_permissions(self):
402 def check_permissions(self):
402 repo_name = get_repo_slug(request)
403 repo_name = get_repo_slug(request)
403
404
404 try:
405 try:
405 user_perms = set([self.user_perms['repositories'][repo_name]])
406 user_perms = set([self.user_perms['repositories'][repo_name]])
406 except KeyError:
407 except KeyError:
407 return False
408 return False
408 if self.required_perms.intersection(user_perms):
409 if self.required_perms.intersection(user_perms):
409 return True
410 return True
410 return False
411 return False
411 #===============================================================================
412 #===============================================================================
412 # CHECK FUNCTIONS
413 # CHECK FUNCTIONS
413 #===============================================================================
414 #===============================================================================
414
415
415 class PermsFunction(object):
416 class PermsFunction(object):
416 """Base function for other check functions"""
417 """Base function for other check functions"""
417
418
418 def __init__(self, *perms):
419 def __init__(self, *perms):
419 available_perms = config['available_permissions']
420 available_perms = config['available_permissions']
420
421
421 for perm in perms:
422 for perm in perms:
422 if perm not in available_perms:
423 if perm not in available_perms:
423 raise Exception("'%s' permission in not defined" % perm)
424 raise Exception("'%s' permission in not defined" % perm)
424 self.required_perms = set(perms)
425 self.required_perms = set(perms)
425 self.user_perms = None
426 self.user_perms = None
426 self.granted_for = ''
427 self.granted_for = ''
427 self.repo_name = None
428 self.repo_name = None
428
429
429 def __call__(self, check_Location=''):
430 def __call__(self, check_Location=''):
430 user = session.get('rhodecode_user', False)
431 user = session.get('rhodecode_user', False)
431 if not user:
432 if not user:
432 return False
433 return False
433 self.user_perms = user.permissions
434 self.user_perms = user.permissions
434 self.granted_for = user.username
435 self.granted_for = user.username
435 log.debug('checking %s %s %s', self.__class__.__name__,
436 log.debug('checking %s %s %s', self.__class__.__name__,
436 self.required_perms, user)
437 self.required_perms, user)
437
438
438 if self.check_permissions():
439 if self.check_permissions():
439 log.debug('Permission granted for %s @ %s %s', self.granted_for,
440 log.debug('Permission granted for %s @ %s %s', self.granted_for,
440 check_Location, user)
441 check_Location, user)
441 return True
442 return True
442
443
443 else:
444 else:
444 log.warning('Permission denied for %s @ %s %s', self.granted_for,
445 log.warning('Permission denied for %s @ %s %s', self.granted_for,
445 check_Location, user)
446 check_Location, user)
446 return False
447 return False
447
448
448 def check_permissions(self):
449 def check_permissions(self):
449 """Dummy function for overriding"""
450 """Dummy function for overriding"""
450 raise Exception('You have to write this function in child class')
451 raise Exception('You have to write this function in child class')
451
452
452 class HasPermissionAll(PermsFunction):
453 class HasPermissionAll(PermsFunction):
453 def check_permissions(self):
454 def check_permissions(self):
454 if self.required_perms.issubset(self.user_perms.get('global')):
455 if self.required_perms.issubset(self.user_perms.get('global')):
455 return True
456 return True
456 return False
457 return False
457
458
458 class HasPermissionAny(PermsFunction):
459 class HasPermissionAny(PermsFunction):
459 def check_permissions(self):
460 def check_permissions(self):
460 if self.required_perms.intersection(self.user_perms.get('global')):
461 if self.required_perms.intersection(self.user_perms.get('global')):
461 return True
462 return True
462 return False
463 return False
463
464
464 class HasRepoPermissionAll(PermsFunction):
465 class HasRepoPermissionAll(PermsFunction):
465
466
466 def __call__(self, repo_name=None, check_Location=''):
467 def __call__(self, repo_name=None, check_Location=''):
467 self.repo_name = repo_name
468 self.repo_name = repo_name
468 return super(HasRepoPermissionAll, self).__call__(check_Location)
469 return super(HasRepoPermissionAll, self).__call__(check_Location)
469
470
470 def check_permissions(self):
471 def check_permissions(self):
471 if not self.repo_name:
472 if not self.repo_name:
472 self.repo_name = get_repo_slug(request)
473 self.repo_name = get_repo_slug(request)
473
474
474 try:
475 try:
475 self.user_perms = set([self.user_perms['repositories']\
476 self.user_perms = set([self.user_perms['repositories']\
476 [self.repo_name]])
477 [self.repo_name]])
477 except KeyError:
478 except KeyError:
478 return False
479 return False
479 self.granted_for = self.repo_name
480 self.granted_for = self.repo_name
480 if self.required_perms.issubset(self.user_perms):
481 if self.required_perms.issubset(self.user_perms):
481 return True
482 return True
482 return False
483 return False
483
484
484 class HasRepoPermissionAny(PermsFunction):
485 class HasRepoPermissionAny(PermsFunction):
485
486
486 def __call__(self, repo_name=None, check_Location=''):
487 def __call__(self, repo_name=None, check_Location=''):
487 self.repo_name = repo_name
488 self.repo_name = repo_name
488 return super(HasRepoPermissionAny, self).__call__(check_Location)
489 return super(HasRepoPermissionAny, self).__call__(check_Location)
489
490
490 def check_permissions(self):
491 def check_permissions(self):
491 if not self.repo_name:
492 if not self.repo_name:
492 self.repo_name = get_repo_slug(request)
493 self.repo_name = get_repo_slug(request)
493
494
494 try:
495 try:
495 self.user_perms = set([self.user_perms['repositories']\
496 self.user_perms = set([self.user_perms['repositories']\
496 [self.repo_name]])
497 [self.repo_name]])
497 except KeyError:
498 except KeyError:
498 return False
499 return False
499 self.granted_for = self.repo_name
500 self.granted_for = self.repo_name
500 if self.required_perms.intersection(self.user_perms):
501 if self.required_perms.intersection(self.user_perms):
501 return True
502 return True
502 return False
503 return False
503
504
504 #===============================================================================
505 #===============================================================================
505 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
506 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
506 #===============================================================================
507 #===============================================================================
507
508
508 class HasPermissionAnyMiddleware(object):
509 class HasPermissionAnyMiddleware(object):
509 def __init__(self, *perms):
510 def __init__(self, *perms):
510 self.required_perms = set(perms)
511 self.required_perms = set(perms)
511
512
512 def __call__(self, user, repo_name):
513 def __call__(self, user, repo_name):
513 usr = AuthUser()
514 usr = AuthUser()
514 usr.user_id = user.user_id
515 usr.user_id = user.user_id
515 usr.username = user.username
516 usr.username = user.username
516 usr.is_admin = user.admin
517 usr.is_admin = user.admin
517
518
518 try:
519 try:
519 self.user_perms = set([fill_perms(usr)\
520 self.user_perms = set([fill_perms(usr)\
520 .permissions['repositories'][repo_name]])
521 .permissions['repositories'][repo_name]])
521 except:
522 except:
522 self.user_perms = set()
523 self.user_perms = set()
523 self.granted_for = ''
524 self.granted_for = ''
524 self.username = user.username
525 self.username = user.username
525 self.repo_name = repo_name
526 self.repo_name = repo_name
526 return self.check_permissions()
527 return self.check_permissions()
527
528
528 def check_permissions(self):
529 def check_permissions(self):
529 log.debug('checking mercurial protocol '
530 log.debug('checking mercurial protocol '
530 'permissions for user:%s repository:%s',
531 'permissions for user:%s repository:%s',
531 self.username, self.repo_name)
532 self.username, self.repo_name)
532 if self.required_perms.intersection(self.user_perms):
533 if self.required_perms.intersection(self.user_perms):
533 log.debug('permission granted')
534 log.debug('permission granted')
534 return True
535 return True
535 log.debug('permission denied')
536 log.debug('permission denied')
536 return False
537 return False
General Comments 0
You need to be logged in to leave comments. Login now