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