##// END OF EJS Templates
added optional password type in password generator
marcink -
r1993:4d3179d2 beta
parent child Browse files
Show More
@@ -1,779 +1,781 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.auth
4 4 ~~~~~~~~~~~~~~~~~~
5 5
6 6 authentication and permission libraries
7 7
8 8 :created_on: Apr 4, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import random
27 27 import logging
28 28 import traceback
29 29 import hashlib
30 30
31 31 from tempfile import _RandomNameSequence
32 32 from decorator import decorator
33 33
34 34 from pylons import config, url, request
35 35 from pylons.controllers.util import abort, redirect
36 36 from pylons.i18n.translation import _
37 37
38 38 from rhodecode import __platform__, PLATFORM_WIN, PLATFORM_OTHERS
39 39 from rhodecode.model.meta import Session
40 40
41 41 if __platform__ in PLATFORM_WIN:
42 42 from hashlib import sha256
43 43 if __platform__ in PLATFORM_OTHERS:
44 44 import bcrypt
45 45
46 46 from rhodecode.lib import str2bool, safe_unicode
47 47 from rhodecode.lib.exceptions import LdapPasswordError, LdapUsernameError
48 48 from rhodecode.lib.utils import get_repo_slug, get_repos_group_slug
49 49 from rhodecode.lib.auth_ldap import AuthLdap
50 50
51 51 from rhodecode.model import meta
52 52 from rhodecode.model.user import UserModel
53 53 from rhodecode.model.db import Permission, RhodeCodeSetting, User
54 54
55 55 log = logging.getLogger(__name__)
56 56
57 57
58 58 class PasswordGenerator(object):
59 59 """
60 60 This is a simple class for generating password from different sets of
61 61 characters
62 62 usage::
63 63
64 64 passwd_gen = PasswordGenerator()
65 65 #print 8-letter password containing only big and small letters
66 66 of alphabet
67 67 print passwd_gen.gen_password(8, passwd_gen.ALPHABETS_BIG_SMALL)
68 68 """
69 69 ALPHABETS_NUM = r'''1234567890'''
70 70 ALPHABETS_SMALL = r'''qwertyuiopasdfghjklzxcvbnm'''
71 71 ALPHABETS_BIG = r'''QWERTYUIOPASDFGHJKLZXCVBNM'''
72 72 ALPHABETS_SPECIAL = r'''`-=[]\;',./~!@#$%^&*()_+{}|:"<>?'''
73 73 ALPHABETS_FULL = ALPHABETS_BIG + ALPHABETS_SMALL \
74 74 + ALPHABETS_NUM + ALPHABETS_SPECIAL
75 75 ALPHABETS_ALPHANUM = ALPHABETS_BIG + ALPHABETS_SMALL + ALPHABETS_NUM
76 76 ALPHABETS_BIG_SMALL = ALPHABETS_BIG + ALPHABETS_SMALL
77 77 ALPHABETS_ALPHANUM_BIG = ALPHABETS_BIG + ALPHABETS_NUM
78 78 ALPHABETS_ALPHANUM_SMALL = ALPHABETS_SMALL + ALPHABETS_NUM
79 79
80 80 def __init__(self, passwd=''):
81 81 self.passwd = passwd
82 82
83 def gen_password(self, length, type_):
83 def gen_password(self, length, type_=None):
84 if type_ is None:
85 type_ = self.ALPHABETS_FULL
84 86 self.passwd = ''.join([random.choice(type_) for _ in xrange(length)])
85 87 return self.passwd
86 88
87 89
88 90 class RhodeCodeCrypto(object):
89 91
90 92 @classmethod
91 93 def hash_string(cls, str_):
92 94 """
93 95 Cryptographic function used for password hashing based on pybcrypt
94 96 or pycrypto in windows
95 97
96 98 :param password: password to hash
97 99 """
98 100 if __platform__ in PLATFORM_WIN:
99 101 return sha256(str_).hexdigest()
100 102 elif __platform__ in PLATFORM_OTHERS:
101 103 return bcrypt.hashpw(str_, bcrypt.gensalt(10))
102 104 else:
103 105 raise Exception('Unknown or unsupported platform %s' \
104 106 % __platform__)
105 107
106 108 @classmethod
107 109 def hash_check(cls, password, hashed):
108 110 """
109 111 Checks matching password with it's hashed value, runs different
110 112 implementation based on platform it runs on
111 113
112 114 :param password: password
113 115 :param hashed: password in hashed form
114 116 """
115 117
116 118 if __platform__ in PLATFORM_WIN:
117 119 return sha256(password).hexdigest() == hashed
118 120 elif __platform__ in PLATFORM_OTHERS:
119 121 return bcrypt.hashpw(password, hashed) == hashed
120 122 else:
121 123 raise Exception('Unknown or unsupported platform %s' \
122 124 % __platform__)
123 125
124 126
125 127 def get_crypt_password(password):
126 128 return RhodeCodeCrypto.hash_string(password)
127 129
128 130
129 131 def check_password(password, hashed):
130 132 return RhodeCodeCrypto.hash_check(password, hashed)
131 133
132 134
133 135 def generate_api_key(str_, salt=None):
134 136 """
135 137 Generates API KEY from given string
136 138
137 139 :param str_:
138 140 :param salt:
139 141 """
140 142
141 143 if salt is None:
142 144 salt = _RandomNameSequence().next()
143 145
144 146 return hashlib.sha1(str_ + salt).hexdigest()
145 147
146 148
147 149 def authfunc(environ, username, password):
148 150 """
149 151 Dummy authentication wrapper function used in Mercurial and Git for
150 152 access control.
151 153
152 154 :param environ: needed only for using in Basic auth
153 155 """
154 156 return authenticate(username, password)
155 157
156 158
157 159 def authenticate(username, password):
158 160 """
159 161 Authentication function used for access control,
160 162 firstly checks for db authentication then if ldap is enabled for ldap
161 163 authentication, also creates ldap user if not in database
162 164
163 165 :param username: username
164 166 :param password: password
165 167 """
166 168
167 169 user_model = UserModel()
168 170 user = User.get_by_username(username)
169 171
170 172 log.debug('Authenticating user using RhodeCode account')
171 173 if user is not None and not user.ldap_dn:
172 174 if user.active:
173 175 if user.username == 'default' and user.active:
174 176 log.info('user %s authenticated correctly as anonymous user',
175 177 username)
176 178 return True
177 179
178 180 elif user.username == username and check_password(password,
179 181 user.password):
180 182 log.info('user %s authenticated correctly' % username)
181 183 return True
182 184 else:
183 185 log.warning('user %s is disabled' % username)
184 186
185 187 else:
186 188 log.debug('Regular authentication failed')
187 189 user_obj = User.get_by_username(username, case_insensitive=True)
188 190
189 191 if user_obj is not None and not user_obj.ldap_dn:
190 192 log.debug('this user already exists as non ldap')
191 193 return False
192 194
193 195 ldap_settings = RhodeCodeSetting.get_ldap_settings()
194 196 #======================================================================
195 197 # FALLBACK TO LDAP AUTH IF ENABLE
196 198 #======================================================================
197 199 if str2bool(ldap_settings.get('ldap_active')):
198 200 log.debug("Authenticating user using ldap")
199 201 kwargs = {
200 202 'server': ldap_settings.get('ldap_host', ''),
201 203 'base_dn': ldap_settings.get('ldap_base_dn', ''),
202 204 'port': ldap_settings.get('ldap_port'),
203 205 'bind_dn': ldap_settings.get('ldap_dn_user'),
204 206 'bind_pass': ldap_settings.get('ldap_dn_pass'),
205 207 'tls_kind': ldap_settings.get('ldap_tls_kind'),
206 208 'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'),
207 209 'ldap_filter': ldap_settings.get('ldap_filter'),
208 210 'search_scope': ldap_settings.get('ldap_search_scope'),
209 211 'attr_login': ldap_settings.get('ldap_attr_login'),
210 212 'ldap_version': 3,
211 213 }
212 214 log.debug('Checking for ldap authentication')
213 215 try:
214 216 aldap = AuthLdap(**kwargs)
215 217 (user_dn, ldap_attrs) = aldap.authenticate_ldap(username,
216 218 password)
217 219 log.debug('Got ldap DN response %s' % user_dn)
218 220
219 221 get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\
220 222 .get(k), [''])[0]
221 223
222 224 user_attrs = {
223 225 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')),
224 226 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')),
225 227 'email': get_ldap_attr('ldap_attr_email'),
226 228 }
227 229
228 230 # don't store LDAP password since we don't need it. Override
229 231 # with some random generated password
230 232 _password = PasswordGenerator().gen_password(length=8)
231 233 # create this user on the fly if it doesn't exist in rhodecode
232 234 # database
233 235 if user_model.create_ldap(username, _password, user_dn,
234 236 user_attrs):
235 237 log.info('created new ldap user %s' % username)
236 238
237 239 Session.commit()
238 240 return True
239 241 except (LdapUsernameError, LdapPasswordError,):
240 242 pass
241 243 except (Exception,):
242 244 log.error(traceback.format_exc())
243 245 pass
244 246 return False
245 247
246 248
247 249 def login_container_auth(username):
248 250 user = User.get_by_username(username)
249 251 if user is None:
250 252 user_attrs = {
251 253 'name': username,
252 254 'lastname': None,
253 255 'email': None,
254 256 }
255 257 user = UserModel().create_for_container_auth(username, user_attrs)
256 258 if not user:
257 259 return None
258 260 log.info('User %s was created by container authentication' % username)
259 261
260 262 if not user.active:
261 263 return None
262 264
263 265 user.update_lastlogin()
264 266 Session.commit()
265 267
266 268 log.debug('User %s is now logged in by container authentication',
267 269 user.username)
268 270 return user
269 271
270 272
271 273 def get_container_username(environ, config):
272 274 username = None
273 275
274 276 if str2bool(config.get('container_auth_enabled', False)):
275 277 from paste.httpheaders import REMOTE_USER
276 278 username = REMOTE_USER(environ)
277 279
278 280 if not username and str2bool(config.get('proxypass_auth_enabled', False)):
279 281 username = environ.get('HTTP_X_FORWARDED_USER')
280 282
281 283 if username:
282 284 # Removing realm and domain from username
283 285 username = username.partition('@')[0]
284 286 username = username.rpartition('\\')[2]
285 287 log.debug('Received username %s from container' % username)
286 288
287 289 return username
288 290
289 291
290 292 class AuthUser(object):
291 293 """
292 294 A simple object that handles all attributes of user in RhodeCode
293 295
294 296 It does lookup based on API key,given user, or user present in session
295 297 Then it fills all required information for such user. It also checks if
296 298 anonymous access is enabled and if so, it returns default user as logged
297 299 in
298 300 """
299 301
300 302 def __init__(self, user_id=None, api_key=None, username=None):
301 303
302 304 self.user_id = user_id
303 305 self.api_key = None
304 306 self.username = username
305 307
306 308 self.name = ''
307 309 self.lastname = ''
308 310 self.email = ''
309 311 self.is_authenticated = False
310 312 self.admin = False
311 313 self.permissions = {}
312 314 self._api_key = api_key
313 315 self.propagate_data()
314 316 self._instance = None
315 317
316 318 def propagate_data(self):
317 319 user_model = UserModel()
318 320 self.anonymous_user = User.get_by_username('default', cache=True)
319 321 is_user_loaded = False
320 322
321 323 # try go get user by api key
322 324 if self._api_key and self._api_key != self.anonymous_user.api_key:
323 325 log.debug('Auth User lookup by API KEY %s' % self._api_key)
324 326 is_user_loaded = user_model.fill_data(self, api_key=self._api_key)
325 327 # lookup by userid
326 328 elif (self.user_id is not None and
327 329 self.user_id != self.anonymous_user.user_id):
328 330 log.debug('Auth User lookup by USER ID %s' % self.user_id)
329 331 is_user_loaded = user_model.fill_data(self, user_id=self.user_id)
330 332 # lookup by username
331 333 elif self.username and \
332 334 str2bool(config.get('container_auth_enabled', False)):
333 335
334 336 log.debug('Auth User lookup by USER NAME %s' % self.username)
335 337 dbuser = login_container_auth(self.username)
336 338 if dbuser is not None:
337 339 for k, v in dbuser.get_dict().items():
338 340 setattr(self, k, v)
339 341 self.set_authenticated()
340 342 is_user_loaded = True
341 343
342 344 if not is_user_loaded:
343 345 # if we cannot authenticate user try anonymous
344 346 if self.anonymous_user.active is True:
345 347 user_model.fill_data(self, user_id=self.anonymous_user.user_id)
346 348 # then we set this user is logged in
347 349 self.is_authenticated = True
348 350 else:
349 351 self.user_id = None
350 352 self.username = None
351 353 self.is_authenticated = False
352 354
353 355 if not self.username:
354 356 self.username = 'None'
355 357
356 358 log.debug('Auth User is now %s' % self)
357 359 user_model.fill_perms(self)
358 360
359 361 @property
360 362 def is_admin(self):
361 363 return self.admin
362 364
363 365 def __repr__(self):
364 366 return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
365 367 self.is_authenticated)
366 368
367 369 def set_authenticated(self, authenticated=True):
368 370 if self.user_id != self.anonymous_user.user_id:
369 371 self.is_authenticated = authenticated
370 372
371 373 def get_cookie_store(self):
372 374 return {'username': self.username,
373 375 'user_id': self.user_id,
374 376 'is_authenticated': self.is_authenticated}
375 377
376 378 @classmethod
377 379 def from_cookie_store(cls, cookie_store):
378 380 user_id = cookie_store.get('user_id')
379 381 username = cookie_store.get('username')
380 382 api_key = cookie_store.get('api_key')
381 383 return AuthUser(user_id, api_key, username)
382 384
383 385
384 386 def set_available_permissions(config):
385 387 """
386 388 This function will propagate pylons globals with all available defined
387 389 permission given in db. We don't want to check each time from db for new
388 390 permissions since adding a new permission also requires application restart
389 391 ie. to decorate new views with the newly created permission
390 392
391 393 :param config: current pylons config instance
392 394
393 395 """
394 396 log.info('getting information about all available permissions')
395 397 try:
396 398 sa = meta.Session
397 399 all_perms = sa.query(Permission).all()
398 400 except Exception:
399 401 pass
400 402 finally:
401 403 meta.Session.remove()
402 404
403 405 config['available_permissions'] = [x.permission_name for x in all_perms]
404 406
405 407
406 408 #==============================================================================
407 409 # CHECK DECORATORS
408 410 #==============================================================================
409 411 class LoginRequired(object):
410 412 """
411 413 Must be logged in to execute this function else
412 414 redirect to login page
413 415
414 416 :param api_access: if enabled this checks only for valid auth token
415 417 and grants access based on valid token
416 418 """
417 419
418 420 def __init__(self, api_access=False):
419 421 self.api_access = api_access
420 422
421 423 def __call__(self, func):
422 424 return decorator(self.__wrapper, func)
423 425
424 426 def __wrapper(self, func, *fargs, **fkwargs):
425 427 cls = fargs[0]
426 428 user = cls.rhodecode_user
427 429
428 430 api_access_ok = False
429 431 if self.api_access:
430 432 log.debug('Checking API KEY access for %s' % cls)
431 433 if user.api_key == request.GET.get('api_key'):
432 434 api_access_ok = True
433 435 else:
434 436 log.debug("API KEY token not valid")
435 437
436 438 log.debug('Checking if %s is authenticated @ %s' % (user.username, cls))
437 439 if user.is_authenticated or api_access_ok:
438 440 log.debug('user %s is authenticated' % user.username)
439 441 return func(*fargs, **fkwargs)
440 442 else:
441 443 log.warn('user %s NOT authenticated' % user.username)
442 444 p = url.current()
443 445
444 446 log.debug('redirecting to login page with %s' % p)
445 447 return redirect(url('login_home', came_from=p))
446 448
447 449
448 450 class NotAnonymous(object):
449 451 """
450 452 Must be logged in to execute this function else
451 453 redirect to login page"""
452 454
453 455 def __call__(self, func):
454 456 return decorator(self.__wrapper, func)
455 457
456 458 def __wrapper(self, func, *fargs, **fkwargs):
457 459 cls = fargs[0]
458 460 self.user = cls.rhodecode_user
459 461
460 462 log.debug('Checking if user is not anonymous @%s' % cls)
461 463
462 464 anonymous = self.user.username == 'default'
463 465
464 466 if anonymous:
465 467 p = url.current()
466 468
467 469 import rhodecode.lib.helpers as h
468 470 h.flash(_('You need to be a registered user to '
469 471 'perform this action'),
470 472 category='warning')
471 473 return redirect(url('login_home', came_from=p))
472 474 else:
473 475 return func(*fargs, **fkwargs)
474 476
475 477
476 478 class PermsDecorator(object):
477 479 """Base class for controller decorators"""
478 480
479 481 def __init__(self, *required_perms):
480 482 available_perms = config['available_permissions']
481 483 for perm in required_perms:
482 484 if perm not in available_perms:
483 485 raise Exception("'%s' permission is not defined" % perm)
484 486 self.required_perms = set(required_perms)
485 487 self.user_perms = None
486 488
487 489 def __call__(self, func):
488 490 return decorator(self.__wrapper, func)
489 491
490 492 def __wrapper(self, func, *fargs, **fkwargs):
491 493 cls = fargs[0]
492 494 self.user = cls.rhodecode_user
493 495 self.user_perms = self.user.permissions
494 496 log.debug('checking %s permissions %s for %s %s',
495 497 self.__class__.__name__, self.required_perms, cls,
496 498 self.user)
497 499
498 500 if self.check_permissions():
499 501 log.debug('Permission granted for %s %s' % (cls, self.user))
500 502 return func(*fargs, **fkwargs)
501 503
502 504 else:
503 505 log.warning('Permission denied for %s %s' % (cls, self.user))
504 506 anonymous = self.user.username == 'default'
505 507
506 508 if anonymous:
507 509 p = url.current()
508 510
509 511 import rhodecode.lib.helpers as h
510 512 h.flash(_('You need to be a signed in to '
511 513 'view this page'),
512 514 category='warning')
513 515 return redirect(url('login_home', came_from=p))
514 516
515 517 else:
516 518 # redirect with forbidden ret code
517 519 return abort(403)
518 520
519 521 def check_permissions(self):
520 522 """Dummy function for overriding"""
521 523 raise Exception('You have to write this function in child class')
522 524
523 525
524 526 class HasPermissionAllDecorator(PermsDecorator):
525 527 """
526 528 Checks for access permission for all given predicates. All of them
527 529 have to be meet in order to fulfill the request
528 530 """
529 531
530 532 def check_permissions(self):
531 533 if self.required_perms.issubset(self.user_perms.get('global')):
532 534 return True
533 535 return False
534 536
535 537
536 538 class HasPermissionAnyDecorator(PermsDecorator):
537 539 """
538 540 Checks for access permission for any of given predicates. In order to
539 541 fulfill the request any of predicates must be meet
540 542 """
541 543
542 544 def check_permissions(self):
543 545 if self.required_perms.intersection(self.user_perms.get('global')):
544 546 return True
545 547 return False
546 548
547 549
548 550 class HasRepoPermissionAllDecorator(PermsDecorator):
549 551 """
550 552 Checks for access permission for all given predicates for specific
551 553 repository. All of them have to be meet in order to fulfill the request
552 554 """
553 555
554 556 def check_permissions(self):
555 557 repo_name = get_repo_slug(request)
556 558 try:
557 559 user_perms = set([self.user_perms['repositories'][repo_name]])
558 560 except KeyError:
559 561 return False
560 562 if self.required_perms.issubset(user_perms):
561 563 return True
562 564 return False
563 565
564 566
565 567 class HasRepoPermissionAnyDecorator(PermsDecorator):
566 568 """
567 569 Checks for access permission for any of given predicates for specific
568 570 repository. In order to fulfill the request any of predicates must be meet
569 571 """
570 572
571 573 def check_permissions(self):
572 574 repo_name = get_repo_slug(request)
573 575
574 576 try:
575 577 user_perms = set([self.user_perms['repositories'][repo_name]])
576 578 except KeyError:
577 579 return False
578 580 if self.required_perms.intersection(user_perms):
579 581 return True
580 582 return False
581 583
582 584
583 585 class HasReposGroupPermissionAllDecorator(PermsDecorator):
584 586 """
585 587 Checks for access permission for all given predicates for specific
586 588 repository. All of them have to be meet in order to fulfill the request
587 589 """
588 590
589 591 def check_permissions(self):
590 592 group_name = get_repos_group_slug(request)
591 593 try:
592 594 user_perms = set([self.user_perms['repositories_groups'][group_name]])
593 595 except KeyError:
594 596 return False
595 597 if self.required_perms.issubset(user_perms):
596 598 return True
597 599 return False
598 600
599 601
600 602 class HasReposGroupPermissionAnyDecorator(PermsDecorator):
601 603 """
602 604 Checks for access permission for any of given predicates for specific
603 605 repository. In order to fulfill the request any of predicates must be meet
604 606 """
605 607
606 608 def check_permissions(self):
607 609 group_name = get_repos_group_slug(request)
608 610
609 611 try:
610 612 user_perms = set([self.user_perms['repositories_groups'][group_name]])
611 613 except KeyError:
612 614 return False
613 615 if self.required_perms.intersection(user_perms):
614 616 return True
615 617 return False
616 618
617 619
618 620 #==============================================================================
619 621 # CHECK FUNCTIONS
620 622 #==============================================================================
621 623 class PermsFunction(object):
622 624 """Base function for other check functions"""
623 625
624 626 def __init__(self, *perms):
625 627 available_perms = config['available_permissions']
626 628
627 629 for perm in perms:
628 630 if perm not in available_perms:
629 631 raise Exception("'%s' permission in not defined" % perm)
630 632 self.required_perms = set(perms)
631 633 self.user_perms = None
632 634 self.granted_for = ''
633 635 self.repo_name = None
634 636
635 637 def __call__(self, check_Location=''):
636 638 user = request.user
637 639 if not user:
638 640 return False
639 641 self.user_perms = user.permissions
640 642 self.granted_for = user
641 643 log.debug('checking %s %s %s', self.__class__.__name__,
642 644 self.required_perms, user)
643 645
644 646 if self.check_permissions():
645 647 log.debug('Permission granted %s @ %s', self.granted_for,
646 648 check_Location or 'unspecified location')
647 649 return True
648 650
649 651 else:
650 652 log.warning('Permission denied for %s @ %s', self.granted_for,
651 653 check_Location or 'unspecified location')
652 654 return False
653 655
654 656 def check_permissions(self):
655 657 """Dummy function for overriding"""
656 658 raise Exception('You have to write this function in child class')
657 659
658 660
659 661 class HasPermissionAll(PermsFunction):
660 662 def check_permissions(self):
661 663 if self.required_perms.issubset(self.user_perms.get('global')):
662 664 return True
663 665 return False
664 666
665 667
666 668 class HasPermissionAny(PermsFunction):
667 669 def check_permissions(self):
668 670 if self.required_perms.intersection(self.user_perms.get('global')):
669 671 return True
670 672 return False
671 673
672 674
673 675 class HasRepoPermissionAll(PermsFunction):
674 676
675 677 def __call__(self, repo_name=None, check_Location=''):
676 678 self.repo_name = repo_name
677 679 return super(HasRepoPermissionAll, self).__call__(check_Location)
678 680
679 681 def check_permissions(self):
680 682 if not self.repo_name:
681 683 self.repo_name = get_repo_slug(request)
682 684
683 685 try:
684 686 self.user_perms = set(
685 687 [self.user_perms['repositories'][self.repo_name]]
686 688 )
687 689 except KeyError:
688 690 return False
689 691 self.granted_for = self.repo_name
690 692 if self.required_perms.issubset(self.user_perms):
691 693 return True
692 694 return False
693 695
694 696
695 697 class HasRepoPermissionAny(PermsFunction):
696 698
697 699 def __call__(self, repo_name=None, check_Location=''):
698 700 self.repo_name = repo_name
699 701 return super(HasRepoPermissionAny, self).__call__(check_Location)
700 702
701 703 def check_permissions(self):
702 704 if not self.repo_name:
703 705 self.repo_name = get_repo_slug(request)
704 706
705 707 try:
706 708 self.user_perms = set(
707 709 [self.user_perms['repositories'][self.repo_name]]
708 710 )
709 711 except KeyError:
710 712 return False
711 713 self.granted_for = self.repo_name
712 714 if self.required_perms.intersection(self.user_perms):
713 715 return True
714 716 return False
715 717
716 718
717 719 class HasReposGroupPermissionAny(PermsFunction):
718 720 def __call__(self, group_name=None, check_Location=''):
719 721 self.group_name = group_name
720 722 return super(HasReposGroupPermissionAny, self).__call__(check_Location)
721 723
722 724 def check_permissions(self):
723 725 try:
724 726 self.user_perms = set(
725 727 [self.user_perms['repositories_groups'][self.group_name]]
726 728 )
727 729 except KeyError:
728 730 return False
729 731 self.granted_for = self.repo_name
730 732 if self.required_perms.intersection(self.user_perms):
731 733 return True
732 734 return False
733 735
734 736
735 737 class HasReposGroupPermissionAll(PermsFunction):
736 738 def __call__(self, group_name=None, check_Location=''):
737 739 self.group_name = group_name
738 740 return super(HasReposGroupPermissionAny, self).__call__(check_Location)
739 741
740 742 def check_permissions(self):
741 743 try:
742 744 self.user_perms = set(
743 745 [self.user_perms['repositories_groups'][self.group_name]]
744 746 )
745 747 except KeyError:
746 748 return False
747 749 self.granted_for = self.repo_name
748 750 if self.required_perms.issubset(self.user_perms):
749 751 return True
750 752 return False
751 753
752 754
753 755 #==============================================================================
754 756 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
755 757 #==============================================================================
756 758 class HasPermissionAnyMiddleware(object):
757 759 def __init__(self, *perms):
758 760 self.required_perms = set(perms)
759 761
760 762 def __call__(self, user, repo_name):
761 763 usr = AuthUser(user.user_id)
762 764 try:
763 765 self.user_perms = set([usr.permissions['repositories'][repo_name]])
764 766 except:
765 767 self.user_perms = set()
766 768 self.granted_for = ''
767 769 self.username = user.username
768 770 self.repo_name = repo_name
769 771 return self.check_permissions()
770 772
771 773 def check_permissions(self):
772 774 log.debug('checking mercurial protocol '
773 775 'permissions %s for user:%s repository:%s', self.user_perms,
774 776 self.username, self.repo_name)
775 777 if self.required_perms.intersection(self.user_perms):
776 778 log.debug('permission granted')
777 779 return True
778 780 log.debug('permission denied')
779 781 return False
General Comments 0
You need to be logged in to leave comments. Login now