Show More
@@ -50,26 +50,28 b' from rhodecode.model import meta' | |||||
50 | from rhodecode.model.user import UserModel |
|
50 | from rhodecode.model.user import UserModel | |
51 | from rhodecode.model.db import Permission |
|
51 | from rhodecode.model.db import Permission | |
52 |
|
52 | |||
|
53 | log = logging.getLogger(__name__) | |||
53 |
|
54 | |||
54 | log = logging.getLogger(__name__) |
|
|||
55 |
|
55 | |||
56 | class PasswordGenerator(object): |
|
56 | class PasswordGenerator(object): | |
57 | """This is a simple class for generating password from |
|
57 | """This is a simple class for generating password from | |
58 | different sets of characters |
|
58 | different sets of characters | |
59 | usage: |
|
59 | usage: | |
60 | passwd_gen = PasswordGenerator() |
|
60 | passwd_gen = PasswordGenerator() | |
61 |
#print 8-letter password containing only big and small letters |
|
61 | #print 8-letter password containing only big and small letters | |
|
62 | of alphabet | |||
62 | print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL) |
|
63 | print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL) | |
63 | """ |
|
64 | """ | |
64 |
ALPHABETS_NUM = r'''1234567890''' |
|
65 | ALPHABETS_NUM = r'''1234567890''' | |
65 |
ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm''' |
|
66 | ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm''' | |
66 |
ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM''' |
|
67 | ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM''' | |
67 |
ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' |
|
68 | ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?''' | |
68 |
ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL |
|
69 | ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL \ | |
69 | ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM#[5] |
|
70 | + ALPHABETS_NUM + ALPHABETS_SPECIAL | |
|
71 | ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM | |||
70 | ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL |
|
72 | ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL | |
71 |
ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM |
|
73 | ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM | |
72 |
ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM |
|
74 | ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM | |
73 |
|
75 | |||
74 | def __init__(self, passwd=''): |
|
76 | def __init__(self, passwd=''): | |
75 | self.passwd = passwd |
|
77 | self.passwd = passwd | |
@@ -78,6 +80,7 b' class PasswordGenerator(object):' | |||||
78 | self.passwd = ''.join([random.choice(type) for _ in xrange(len)]) |
|
80 | self.passwd = ''.join([random.choice(type) for _ in xrange(len)]) | |
79 | return self.passwd |
|
81 | return self.passwd | |
80 |
|
82 | |||
|
83 | ||||
81 | class RhodeCodeCrypto(object): |
|
84 | class RhodeCodeCrypto(object): | |
82 |
|
85 | |||
83 | @classmethod |
|
86 | @classmethod | |
@@ -93,7 +96,8 b' class RhodeCodeCrypto(object):' | |||||
93 | elif __platform__ in PLATFORM_OTHERS: |
|
96 | elif __platform__ in PLATFORM_OTHERS: | |
94 | return bcrypt.hashpw(str_, bcrypt.gensalt(10)) |
|
97 | return bcrypt.hashpw(str_, bcrypt.gensalt(10)) | |
95 | else: |
|
98 | else: | |
96 |
raise Exception('Unknown or unsupported platform %s' |
|
99 | raise Exception('Unknown or unsupported platform %s' \ | |
|
100 | % __platform__) | |||
97 |
|
101 | |||
98 | @classmethod |
|
102 | @classmethod | |
99 | def hash_check(cls, password, hashed): |
|
103 | def hash_check(cls, password, hashed): | |
@@ -110,21 +114,25 b' class RhodeCodeCrypto(object):' | |||||
110 | elif __platform__ in PLATFORM_OTHERS: |
|
114 | elif __platform__ in PLATFORM_OTHERS: | |
111 | return bcrypt.hashpw(password, hashed) == hashed |
|
115 | return bcrypt.hashpw(password, hashed) == hashed | |
112 | else: |
|
116 | else: | |
113 |
raise Exception('Unknown or unsupported platform %s' |
|
117 | raise Exception('Unknown or unsupported platform %s' \ | |
|
118 | % __platform__) | |||
114 |
|
119 | |||
115 |
|
120 | |||
116 | def get_crypt_password(password): |
|
121 | def get_crypt_password(password): | |
117 | return RhodeCodeCrypto.hash_string(password) |
|
122 | return RhodeCodeCrypto.hash_string(password) | |
118 |
|
123 | |||
|
124 | ||||
119 | def check_password(password, hashed): |
|
125 | def check_password(password, hashed): | |
120 | return RhodeCodeCrypto.hash_check(password, hashed) |
|
126 | return RhodeCodeCrypto.hash_check(password, hashed) | |
121 |
|
127 | |||
|
128 | ||||
122 | def generate_api_key(username, salt=None): |
|
129 | def generate_api_key(username, salt=None): | |
123 | if salt is None: |
|
130 | if salt is None: | |
124 | salt = _RandomNameSequence().next() |
|
131 | salt = _RandomNameSequence().next() | |
125 |
|
132 | |||
126 | return hashlib.sha1(username + salt).hexdigest() |
|
133 | return hashlib.sha1(username + salt).hexdigest() | |
127 |
|
134 | |||
|
135 | ||||
128 | def authfunc(environ, username, password): |
|
136 | def authfunc(environ, username, password): | |
129 | """Dummy authentication function used in Mercurial/Git/ and access control, |
|
137 | """Dummy authentication function used in Mercurial/Git/ and access control, | |
130 |
|
138 | |||
@@ -147,13 +155,13 b' def authenticate(username, password):' | |||||
147 | log.debug('Authenticating user using RhodeCode account') |
|
155 | log.debug('Authenticating user using RhodeCode account') | |
148 | if user is not None and not user.ldap_dn: |
|
156 | if user is not None and not user.ldap_dn: | |
149 | if user.active: |
|
157 | if user.active: | |
150 |
|
||||
151 | if user.username == 'default' and user.active: |
|
158 | if user.username == 'default' and user.active: | |
152 | log.info('user %s authenticated correctly as anonymous user', |
|
159 | log.info('user %s authenticated correctly as anonymous user', | |
153 | username) |
|
160 | username) | |
154 | return True |
|
161 | return True | |
155 |
|
162 | |||
156 |
elif user.username == username and check_password(password, |
|
163 | elif user.username == username and check_password(password, | |
|
164 | user.password): | |||
157 | log.info('user %s authenticated correctly', username) |
|
165 | log.info('user %s authenticated correctly', username) | |
158 | return True |
|
166 | return True | |
159 | else: |
|
167 | else: | |
@@ -177,31 +185,36 b' def authenticate(username, password):' | |||||
177 | if str2bool(ldap_settings.get('ldap_active')): |
|
185 | if str2bool(ldap_settings.get('ldap_active')): | |
178 | log.debug("Authenticating user using ldap") |
|
186 | log.debug("Authenticating user using ldap") | |
179 | kwargs = { |
|
187 | kwargs = { | |
180 | 'server':ldap_settings.get('ldap_host', ''), |
|
188 | 'server': ldap_settings.get('ldap_host', ''), | |
181 | 'base_dn':ldap_settings.get('ldap_base_dn', ''), |
|
189 | 'base_dn': ldap_settings.get('ldap_base_dn', ''), | |
182 | 'port':ldap_settings.get('ldap_port'), |
|
190 | 'port': ldap_settings.get('ldap_port'), | |
183 | 'bind_dn':ldap_settings.get('ldap_dn_user'), |
|
191 | 'bind_dn': ldap_settings.get('ldap_dn_user'), | |
184 | 'bind_pass':ldap_settings.get('ldap_dn_pass'), |
|
192 | 'bind_pass': ldap_settings.get('ldap_dn_pass'), | |
185 | 'use_ldaps':str2bool(ldap_settings.get('ldap_ldaps')), |
|
193 | 'use_ldaps': str2bool(ldap_settings.get('ldap_ldaps')), | |
186 | 'tls_reqcert':ldap_settings.get('ldap_tls_reqcert'), |
|
194 | 'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'), | |
187 | 'ldap_filter':ldap_settings.get('ldap_filter'), |
|
195 | 'ldap_filter': ldap_settings.get('ldap_filter'), | |
188 | 'search_scope':ldap_settings.get('ldap_search_scope'), |
|
196 | 'search_scope': ldap_settings.get('ldap_search_scope'), | |
189 | 'attr_login':ldap_settings.get('ldap_attr_login'), |
|
197 | 'attr_login': ldap_settings.get('ldap_attr_login'), | |
190 | 'ldap_version':3, |
|
198 | 'ldap_version': 3, | |
191 | } |
|
199 | } | |
192 | log.debug('Checking for ldap authentication') |
|
200 | log.debug('Checking for ldap authentication') | |
193 | try: |
|
201 | try: | |
194 | aldap = AuthLdap(**kwargs) |
|
202 | aldap = AuthLdap(**kwargs) | |
195 |
(user_dn, ldap_attrs) = aldap.authenticate_ldap(username, |
|
203 | (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, | |
|
204 | password) | |||
196 | log.debug('Got ldap DN response %s', user_dn) |
|
205 | log.debug('Got ldap DN response %s', user_dn) | |
197 |
|
206 | |||
198 | user_attrs = { |
|
207 | user_attrs = { | |
199 |
'name' |
|
208 | 'name': ldap_attrs[ldap_settings\ | |
200 |
|
|
209 | .get('ldap_attr_firstname')][0], | |
201 |
' |
|
210 | 'lastname': ldap_attrs[ldap_settings\ | |
|
211 | .get('ldap_attr_lastname')][0], | |||
|
212 | 'email': ldap_attrs[ldap_settings\ | |||
|
213 | .get('ldap_attr_email')][0], | |||
202 | } |
|
214 | } | |
203 |
|
215 | |||
204 |
if user_model.create_ldap(username, password, user_dn, |
|
216 | if user_model.create_ldap(username, password, user_dn, | |
|
217 | user_attrs): | |||
205 | log.info('created new ldap user %s', username) |
|
218 | log.info('created new ldap user %s', username) | |
206 |
|
219 | |||
207 | return True |
|
220 | return True | |
@@ -212,6 +225,7 b' def authenticate(username, password):' | |||||
212 | pass |
|
225 | pass | |
213 | return False |
|
226 | return False | |
214 |
|
227 | |||
|
228 | ||||
215 | class AuthUser(object): |
|
229 | class AuthUser(object): | |
216 | """ |
|
230 | """ | |
217 | A simple object that handles all attributes of user in RhodeCode |
|
231 | A simple object that handles all attributes of user in RhodeCode | |
@@ -237,7 +251,6 b' class AuthUser(object):' | |||||
237 | self._api_key = api_key |
|
251 | self._api_key = api_key | |
238 | self.propagate_data() |
|
252 | self.propagate_data() | |
239 |
|
253 | |||
240 |
|
||||
241 | def propagate_data(self): |
|
254 | def propagate_data(self): | |
242 | user_model = UserModel() |
|
255 | user_model = UserModel() | |
243 | self.anonymous_user = user_model.get_by_username('default', cache=True) |
|
256 | self.anonymous_user = user_model.get_by_username('default', cache=True) | |
@@ -247,11 +260,13 b' class AuthUser(object):' | |||||
247 | user_model.fill_data(self, api_key=self._api_key) |
|
260 | user_model.fill_data(self, api_key=self._api_key) | |
248 | else: |
|
261 | else: | |
249 | log.debug('Auth User lookup by USER ID %s', self.user_id) |
|
262 | log.debug('Auth User lookup by USER ID %s', self.user_id) | |
250 |
if self.user_id is not None |
|
263 | if self.user_id is not None \ | |
|
264 | and self.user_id != self.anonymous_user.user_id: | |||
251 | user_model.fill_data(self, user_id=self.user_id) |
|
265 | user_model.fill_data(self, user_id=self.user_id) | |
252 | else: |
|
266 | else: | |
253 | if self.anonymous_user.active is True: |
|
267 | if self.anonymous_user.active is True: | |
254 |
user_model.fill_data(self, |
|
268 | user_model.fill_data(self, | |
|
269 | user_id=self.anonymous_user.user_id) | |||
255 | #then we set this user is logged in |
|
270 | #then we set this user is logged in | |
256 | self.is_authenticated = True |
|
271 | self.is_authenticated = True | |
257 | else: |
|
272 | else: | |
@@ -294,9 +309,10 b' def set_available_permissions(config):' | |||||
294 |
|
309 | |||
295 | config['available_permissions'] = [x.permission_name for x in all_perms] |
|
310 | config['available_permissions'] = [x.permission_name for x in all_perms] | |
296 |
|
311 | |||
297 | #=============================================================================== |
|
312 | ||
|
313 | #============================================================================== | |||
298 | # CHECK DECORATORS |
|
314 | # CHECK DECORATORS | |
299 |
#============================================================================== |
|
315 | #============================================================================== | |
300 | class LoginRequired(object): |
|
316 | class LoginRequired(object): | |
301 | """ |
|
317 | """ | |
302 | Must be logged in to execute this function else |
|
318 | Must be logged in to execute this function else | |
@@ -335,6 +351,7 b' class LoginRequired(object):' | |||||
335 | log.debug('redirecting to login page with %s', p) |
|
351 | log.debug('redirecting to login page with %s', p) | |
336 | return redirect(url('login_home', came_from=p)) |
|
352 | return redirect(url('login_home', came_from=p)) | |
337 |
|
353 | |||
|
354 | ||||
338 | class NotAnonymous(object): |
|
355 | class NotAnonymous(object): | |
339 | """Must be logged in to execute this function else |
|
356 | """Must be logged in to execute this function else | |
340 | redirect to login page""" |
|
357 | redirect to login page""" | |
@@ -360,12 +377,14 b' class NotAnonymous(object):' | |||||
360 | p += '?' + request.environ.get('QUERY_STRING') |
|
377 | p += '?' + request.environ.get('QUERY_STRING') | |
361 |
|
378 | |||
362 | import rhodecode.lib.helpers as h |
|
379 | import rhodecode.lib.helpers as h | |
363 |
h.flash(_('You need to be a registered user to |
|
380 | h.flash(_('You need to be a registered user to ' | |
|
381 | 'perform this action'), | |||
364 | category='warning') |
|
382 | category='warning') | |
365 | return redirect(url('login_home', came_from=p)) |
|
383 | return redirect(url('login_home', came_from=p)) | |
366 | else: |
|
384 | else: | |
367 | return func(*fargs, **fkwargs) |
|
385 | return func(*fargs, **fkwargs) | |
368 |
|
386 | |||
|
387 | ||||
369 | class PermsDecorator(object): |
|
388 | class PermsDecorator(object): | |
370 | """Base class for controller decorators""" |
|
389 | """Base class for controller decorators""" | |
371 |
|
390 | |||
@@ -380,7 +399,6 b' class PermsDecorator(object):' | |||||
380 | def __call__(self, func): |
|
399 | def __call__(self, func): | |
381 | return decorator(self.__wrapper, func) |
|
400 | return decorator(self.__wrapper, func) | |
382 |
|
401 | |||
383 |
|
||||
384 | def __wrapper(self, func, *fargs, **fkwargs): |
|
402 | def __wrapper(self, func, *fargs, **fkwargs): | |
385 | cls = fargs[0] |
|
403 | cls = fargs[0] | |
386 | self.user = cls.rhodecode_user |
|
404 | self.user = cls.rhodecode_user | |
@@ -398,12 +416,11 b' class PermsDecorator(object):' | |||||
398 | #redirect with forbidden ret code |
|
416 | #redirect with forbidden ret code | |
399 | return abort(403) |
|
417 | return abort(403) | |
400 |
|
418 | |||
401 |
|
||||
402 |
|
||||
403 | def check_permissions(self): |
|
419 | def check_permissions(self): | |
404 | """Dummy function for overriding""" |
|
420 | """Dummy function for overriding""" | |
405 | raise Exception('You have to write this function in child class') |
|
421 | raise Exception('You have to write this function in child class') | |
406 |
|
422 | |||
|
423 | ||||
407 | class HasPermissionAllDecorator(PermsDecorator): |
|
424 | class HasPermissionAllDecorator(PermsDecorator): | |
408 | """Checks for access permission for all given predicates. All of them |
|
425 | """Checks for access permission for all given predicates. All of them | |
409 | have to be meet in order to fulfill the request |
|
426 | have to be meet in order to fulfill the request | |
@@ -425,6 +442,7 b' class HasPermissionAnyDecorator(PermsDec' | |||||
425 | return True |
|
442 | return True | |
426 | return False |
|
443 | return False | |
427 |
|
444 | |||
|
445 | ||||
428 | class HasRepoPermissionAllDecorator(PermsDecorator): |
|
446 | class HasRepoPermissionAllDecorator(PermsDecorator): | |
429 | """Checks for access permission for all given predicates for specific |
|
447 | """Checks for access permission for all given predicates for specific | |
430 | repository. All of them have to be meet in order to fulfill the request |
|
448 | repository. All of them have to be meet in order to fulfill the request | |
@@ -456,10 +474,11 b' class HasRepoPermissionAnyDecorator(Perm' | |||||
456 | if self.required_perms.intersection(user_perms): |
|
474 | if self.required_perms.intersection(user_perms): | |
457 | return True |
|
475 | return True | |
458 | return False |
|
476 | return False | |
459 | #=============================================================================== |
|
477 | ||
|
478 | ||||
|
479 | #============================================================================== | |||
460 | # CHECK FUNCTIONS |
|
480 | # CHECK FUNCTIONS | |
461 |
#============================================================================== |
|
481 | #============================================================================== | |
462 |
|
||||
463 | class PermsFunction(object): |
|
482 | class PermsFunction(object): | |
464 | """Base function for other check functions""" |
|
483 | """Base function for other check functions""" | |
465 |
|
484 | |||
@@ -497,18 +516,21 b' class PermsFunction(object):' | |||||
497 | """Dummy function for overriding""" |
|
516 | """Dummy function for overriding""" | |
498 | raise Exception('You have to write this function in child class') |
|
517 | raise Exception('You have to write this function in child class') | |
499 |
|
518 | |||
|
519 | ||||
500 | class HasPermissionAll(PermsFunction): |
|
520 | class HasPermissionAll(PermsFunction): | |
501 | def check_permissions(self): |
|
521 | def check_permissions(self): | |
502 | if self.required_perms.issubset(self.user_perms.get('global')): |
|
522 | if self.required_perms.issubset(self.user_perms.get('global')): | |
503 | return True |
|
523 | return True | |
504 | return False |
|
524 | return False | |
505 |
|
525 | |||
|
526 | ||||
506 | class HasPermissionAny(PermsFunction): |
|
527 | class HasPermissionAny(PermsFunction): | |
507 | def check_permissions(self): |
|
528 | def check_permissions(self): | |
508 | if self.required_perms.intersection(self.user_perms.get('global')): |
|
529 | if self.required_perms.intersection(self.user_perms.get('global')): | |
509 | return True |
|
530 | return True | |
510 | return False |
|
531 | return False | |
511 |
|
532 | |||
|
533 | ||||
512 | class HasRepoPermissionAll(PermsFunction): |
|
534 | class HasRepoPermissionAll(PermsFunction): | |
513 |
|
535 | |||
514 | def __call__(self, repo_name=None, check_Location=''): |
|
536 | def __call__(self, repo_name=None, check_Location=''): | |
@@ -520,8 +542,8 b' class HasRepoPermissionAll(PermsFunction' | |||||
520 | self.repo_name = get_repo_slug(request) |
|
542 | self.repo_name = get_repo_slug(request) | |
521 |
|
543 | |||
522 | try: |
|
544 | try: | |
523 |
self.user_perms = set([self.user_perms['reposit |
|
545 | self.user_perms = set([self.user_perms['reposit' | |
524 | [self.repo_name]]) |
|
546 | 'ories'][self.repo_name]]) | |
525 | except KeyError: |
|
547 | except KeyError: | |
526 | return False |
|
548 | return False | |
527 | self.granted_for = self.repo_name |
|
549 | self.granted_for = self.repo_name | |
@@ -529,6 +551,7 b' class HasRepoPermissionAll(PermsFunction' | |||||
529 | return True |
|
551 | return True | |
530 | return False |
|
552 | return False | |
531 |
|
553 | |||
|
554 | ||||
532 | class HasRepoPermissionAny(PermsFunction): |
|
555 | class HasRepoPermissionAny(PermsFunction): | |
533 |
|
556 | |||
534 | def __call__(self, repo_name=None, check_Location=''): |
|
557 | def __call__(self, repo_name=None, check_Location=''): | |
@@ -540,8 +563,8 b' class HasRepoPermissionAny(PermsFunction' | |||||
540 | self.repo_name = get_repo_slug(request) |
|
563 | self.repo_name = get_repo_slug(request) | |
541 |
|
564 | |||
542 | try: |
|
565 | try: | |
543 |
self.user_perms = set([self.user_perms['reposi |
|
566 | self.user_perms = set([self.user_perms['reposi' | |
544 | [self.repo_name]]) |
|
567 | 'tories'][self.repo_name]]) | |
545 | except KeyError: |
|
568 | except KeyError: | |
546 | return False |
|
569 | return False | |
547 | self.granted_for = self.repo_name |
|
570 | self.granted_for = self.repo_name | |
@@ -549,10 +572,10 b' class HasRepoPermissionAny(PermsFunction' | |||||
549 | return True |
|
572 | return True | |
550 | return False |
|
573 | return False | |
551 |
|
574 | |||
552 | #=============================================================================== |
|
575 | ||
|
576 | #============================================================================== | |||
553 | # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH |
|
577 | # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH | |
554 |
#============================================================================== |
|
578 | #============================================================================== | |
555 |
|
||||
556 | class HasPermissionAnyMiddleware(object): |
|
579 | class HasPermissionAnyMiddleware(object): | |
557 | def __init__(self, *perms): |
|
580 | def __init__(self, *perms): | |
558 | self.required_perms = set(perms) |
|
581 | self.required_perms = set(perms) |
General Comments 0
You need to be logged in to leave comments.
Login now