##// END OF EJS Templates
merged with bugfixes
marcink -
r425:570b9e82 merge default
parent child Browse files
Show More
@@ -1,98 +1,97 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # login controller for pylons
3 # login controller for pylons
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20
20
21 """
21 """
22 Created on April 22, 2010
22 Created on April 22, 2010
23 login controller for pylons
23 login controller for pylons
24 @author: marcink
24 @author: marcink
25 """
25 """
26 from formencode import htmlfill
26 from formencode import htmlfill
27 from pylons import request, response, session, tmpl_context as c, url
27 from pylons import request, response, session, tmpl_context as c, url
28 from pylons.controllers.util import abort, redirect
28 from pylons.controllers.util import abort, redirect
29 from pylons_app.lib.auth import AuthUser, HasPermissionAnyDecorator
29 from pylons_app.lib.auth import AuthUser, HasPermissionAnyDecorator
30 from pylons_app.lib.base import BaseController, render
30 from pylons_app.lib.base import BaseController, render
31 from pylons_app.model.forms import LoginForm, RegisterForm
31 from pylons_app.model.forms import LoginForm, RegisterForm
32 from pylons_app.model.user_model import UserModel
32 from pylons_app.model.user_model import UserModel
33 import formencode
33 import formencode
34 import logging
34 import logging
35
35
36 log = logging.getLogger(__name__)
36 log = logging.getLogger(__name__)
37
37
38 class LoginController(BaseController):
38 class LoginController(BaseController):
39
39
40 def __before__(self):
40 def __before__(self):
41 super(LoginController, self).__before__()
41 super(LoginController, self).__before__()
42
42
43 def index(self):
43 def index(self):
44 #redirect if already logged in
44 #redirect if already logged in
45 if c.hg_app_user.is_authenticated:
45 if c.hg_app_user.is_authenticated:
46 return redirect(url('hg_home'))
46 return redirect(url('hg_home'))
47
47
48 if request.POST:
48 if request.POST:
49 #import Login Form validator class
49 #import Login Form validator class
50 login_form = LoginForm()
50 login_form = LoginForm()
51 try:
51 try:
52 c.form_result = login_form.to_python(dict(request.POST))
52 c.form_result = login_form.to_python(dict(request.POST))
53 return redirect(url('hg_home'))
53 return redirect(url('hg_home'))
54
54
55 except formencode.Invalid as errors:
55 except formencode.Invalid as errors:
56 return htmlfill.render(
56 return htmlfill.render(
57 render('/login.html'),
57 render('/login.html'),
58 defaults=errors.value,
58 defaults=errors.value,
59 errors=errors.error_dict or {},
59 errors=errors.error_dict or {},
60 prefix_error=False,
60 prefix_error=False,
61 encoding="UTF-8")
61 encoding="UTF-8")
62
62
63 return render('/login.html')
63 return render('/login.html')
64
64
65 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')
65 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')
66 def register(self):
66 def register(self):
67 user_model = UserModel()
67 user_model = UserModel()
68 c.auto_active = False
68 c.auto_active = False
69 for perm in user_model.get_default().user_perms:
69 for perm in user_model.get_default().user_perms:
70 print perm.permission.permission_name
71 if perm.permission.permission_name == 'hg.register.auto_activate':
70 if perm.permission.permission_name == 'hg.register.auto_activate':
72 c.auto_active = True
71 c.auto_active = True
73 break
72 break
74
73
75 if request.POST:
74 if request.POST:
76
75
77 register_form = RegisterForm()()
76 register_form = RegisterForm()()
78 try:
77 try:
79 form_result = register_form.to_python(dict(request.POST))
78 form_result = register_form.to_python(dict(request.POST))
80 form_result['active'] = c.auto_active
79 form_result['active'] = c.auto_active
81 user_model.create_registration(form_result)
80 user_model.create_registration(form_result)
82 return redirect(url('login_home'))
81 return redirect(url('login_home'))
83
82
84 except formencode.Invalid as errors:
83 except formencode.Invalid as errors:
85 return htmlfill.render(
84 return htmlfill.render(
86 render('/register.html'),
85 render('/register.html'),
87 defaults=errors.value,
86 defaults=errors.value,
88 errors=errors.error_dict or {},
87 errors=errors.error_dict or {},
89 prefix_error=False,
88 prefix_error=False,
90 encoding="UTF-8")
89 encoding="UTF-8")
91
90
92 return render('/register.html')
91 return render('/register.html')
93
92
94 def logout(self):
93 def logout(self):
95 session['hg_app_user'] = AuthUser()
94 session['hg_app_user'] = AuthUser()
96 session.save()
95 session.save()
97 log.info('Logging out and setting user as Empty')
96 log.info('Logging out and setting user as Empty')
98 redirect(url('hg_home'))
97 redirect(url('hg_home'))
@@ -1,450 +1,450 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 # encoding: utf-8
2 # encoding: utf-8
3 # authentication and permission libraries
3 # authentication and permission libraries
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
4 # Copyright (C) 2009-2010 Marcin Kuzminski <marcin@python-works.com>
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; version 2
8 # as published by the Free Software Foundation; version 2
9 # of the License or (at your opinion) any later version of the license.
9 # of the License or (at your opinion) any later version of the license.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19 # MA 02110-1301, USA.
19 # MA 02110-1301, USA.
20 """
20 """
21 Created on April 4, 2010
21 Created on April 4, 2010
22
22
23 @author: marcink
23 @author: marcink
24 """
24 """
25 from beaker.cache import cache_region
25 from beaker.cache import cache_region
26 from pylons import config, session, url, request
26 from pylons import config, session, url, request
27 from pylons.controllers.util import abort, redirect
27 from pylons.controllers.util import abort, redirect
28 from pylons_app.lib.utils import get_repo_slug
28 from pylons_app.lib.utils import get_repo_slug
29 from pylons_app.model import meta
29 from pylons_app.model import meta
30 from pylons_app.model.db import User, RepoToPerm, Repository, Permission, \
30 from pylons_app.model.db import User, RepoToPerm, Repository, Permission, \
31 UserToPerm
31 UserToPerm
32 from sqlalchemy.exc import OperationalError
32 from sqlalchemy.exc import OperationalError
33 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
33 from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
34 import bcrypt
34 import bcrypt
35 from decorator import decorator
35 from decorator import decorator
36 import logging
36 import logging
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40 def get_crypt_password(password):
40 def get_crypt_password(password):
41 """Cryptographic function used for password hashing based on sha1
41 """Cryptographic function used for password hashing based on sha1
42 @param password: password to hash
42 @param password: password to hash
43 """
43 """
44 return bcrypt.hashpw(password, bcrypt.gensalt(10))
44 return bcrypt.hashpw(password, bcrypt.gensalt(10))
45
45
46 def check_password(password, hashed):
46 def check_password(password, hashed):
47 return bcrypt.hashpw(password, hashed) == hashed
47 return bcrypt.hashpw(password, hashed) == hashed
48
48
49 @cache_region('super_short_term', 'cached_user')
49 @cache_region('super_short_term', 'cached_user')
50 def get_user_cached(username):
50 def get_user_cached(username):
51 sa = meta.Session
51 sa = meta.Session
52 try:
52 try:
53 user = sa.query(User).filter(User.username == username).one()
53 user = sa.query(User).filter(User.username == username).one()
54 finally:
54 finally:
55 meta.Session.remove()
55 meta.Session.remove()
56 return user
56 return user
57
57
58 def authfunc(environ, username, password):
58 def authfunc(environ, username, password):
59 try:
59 try:
60 user = get_user_cached(username)
60 user = get_user_cached(username)
61 except (NoResultFound, MultipleResultsFound, OperationalError) as e:
61 except (NoResultFound, MultipleResultsFound, OperationalError) as e:
62 log.error(e)
62 log.error(e)
63 user = None
63 user = None
64
64
65 if user:
65 if user:
66 if user.active:
66 if user.active:
67 if user.username == username and check_password(password, user.password):
67 if user.username == username and check_password(password, user.password):
68 log.info('user %s authenticated correctly', username)
68 log.info('user %s authenticated correctly', username)
69 return True
69 return True
70 else:
70 else:
71 log.error('user %s is disabled', username)
71 log.error('user %s is disabled', username)
72
72
73 return False
73 return False
74
74
75 class AuthUser(object):
75 class AuthUser(object):
76 """
76 """
77 A simple object that handles a mercurial username for authentication
77 A simple object that handles a mercurial username for authentication
78 """
78 """
79 def __init__(self):
79 def __init__(self):
80 self.username = 'None'
80 self.username = 'None'
81 self.name = ''
81 self.name = ''
82 self.lastname = ''
82 self.lastname = ''
83 self.email = ''
83 self.email = ''
84 self.user_id = None
84 self.user_id = None
85 self.is_authenticated = False
85 self.is_authenticated = False
86 self.is_admin = False
86 self.is_admin = False
87 self.permissions = {}
87 self.permissions = {}
88
88
89
89
90 def set_available_permissions(config):
90 def set_available_permissions(config):
91 """
91 """
92 This function will propagate pylons globals with all available defined
92 This function will propagate pylons globals with all available defined
93 permission given in db. We don't wannt to check each time from db for new
93 permission given in db. We don't wannt to check each time from db for new
94 permissions since adding a new permission also requires application restart
94 permissions since adding a new permission also requires application restart
95 ie. to decorate new views with the newly created permission
95 ie. to decorate new views with the newly created permission
96 @param config:
96 @param config:
97 """
97 """
98 log.info('getting information about all available permissions')
98 log.info('getting information about all available permissions')
99 try:
99 try:
100 sa = meta.Session
100 sa = meta.Session
101 all_perms = sa.query(Permission).all()
101 all_perms = sa.query(Permission).all()
102 finally:
102 finally:
103 meta.Session.remove()
103 meta.Session.remove()
104
104
105 config['available_permissions'] = [x.permission_name for x in all_perms]
105 config['available_permissions'] = [x.permission_name for x in all_perms]
106
106
107 def set_base_path(config):
107 def set_base_path(config):
108 config['base_path'] = config['pylons.app_globals'].base_path
108 config['base_path'] = config['pylons.app_globals'].base_path
109
109
110 def fill_data(user):
110 def fill_data(user):
111 """
111 """
112 Fills user data with those from database and log out user if not present
112 Fills user data with those from database and log out user if not present
113 in database
113 in database
114 @param user:
114 @param user:
115 """
115 """
116 sa = meta.Session
116 sa = meta.Session
117 dbuser = sa.query(User).get(user.user_id)
117 dbuser = sa.query(User).get(user.user_id)
118 if dbuser:
118 if dbuser:
119 user.username = dbuser.username
119 user.username = dbuser.username
120 user.is_admin = dbuser.admin
120 user.is_admin = dbuser.admin
121 user.name = dbuser.name
121 user.name = dbuser.name
122 user.lastname = dbuser.lastname
122 user.lastname = dbuser.lastname
123 user.email = dbuser.email
123 user.email = dbuser.email
124 else:
124 else:
125 user.is_authenticated = False
125 user.is_authenticated = False
126 meta.Session.remove()
126 meta.Session.remove()
127 from pprint import pprint
128 pprint(user.permissions)
129 return user
127 return user
130
128
131 def fill_perms(user):
129 def fill_perms(user):
132 """
130 """
133 Fills user permission attribute with permissions taken from database
131 Fills user permission attribute with permissions taken from database
134 @param user:
132 @param user:
135 """
133 """
136
134
137 sa = meta.Session
135 sa = meta.Session
138 user.permissions['repositories'] = {}
136 user.permissions['repositories'] = {}
139 user.permissions['global'] = set()
137 user.permissions['global'] = set()
140
138
141 #===========================================================================
139 #===========================================================================
142 # fetch default permissions
140 # fetch default permissions
143 #===========================================================================
141 #===========================================================================
144 default_perms = sa.query(RepoToPerm, UserToPerm, Repository, Permission)\
142 default_perms = sa.query(RepoToPerm, Repository, Permission)\
145 .outerjoin((UserToPerm, RepoToPerm.user_id == UserToPerm.user_id))\
146 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
143 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
147 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
144 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
148 .filter(RepoToPerm.user_id == sa.query(User).filter(User.username ==
145 .filter(RepoToPerm.user == sa.query(User).filter(User.username ==
149 'default').one().user_id).all()
146 'default').scalar()).all()
150
147
151 if user.is_admin:
148 if user.is_admin:
152 #=======================================================================
149 #=======================================================================
153 # #admin have all rights set to admin
150 # #admin have all default rights set to admin
154 #=======================================================================
151 #=======================================================================
155 user.permissions['global'].add('hg.admin')
152 user.permissions['global'].add('hg.admin')
156
153
157 for perm in default_perms:
154 for perm in default_perms:
158 p = 'repository.admin'
155 p = 'repository.admin'
159 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
156 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
160
157
161 else:
158 else:
162 #=======================================================================
159 #=======================================================================
163 # set default permissions
160 # set default permissions
164 #=======================================================================
161 #=======================================================================
165
162
166 #default global
163 #default global
167 for perm in default_perms:
164 default_global_perms = sa.query(UserToPerm)\
168 user.permissions['global'].add(perm.UserToPerm.permission.permission_name)
165 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
166 'default').one())
167
168 for perm in default_global_perms:
169 user.permissions['global'].add(perm.permission.permission_name)
169
170
170 #default repositories
171 #default repositories
171 for perm in default_perms:
172 for perm in default_perms:
172 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
173 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
173 #disable defaults for private repos,
174 #disable defaults for private repos,
174 p = 'repository.none'
175 p = 'repository.none'
175 elif perm.Repository.user_id == user.user_id:
176 elif perm.Repository.user_id == user.user_id:
176 #set admin if owner
177 #set admin if owner
177 p = 'repository.admin'
178 p = 'repository.admin'
178 else:
179 else:
179 p = perm.Permission.permission_name
180 p = perm.Permission.permission_name
180
181
181 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
182 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
182
183
183 #=======================================================================
184 #=======================================================================
184 # #overwrite default with user permissions if any
185 # #overwrite default with user permissions if any
185 #=======================================================================
186 #=======================================================================
186 user_perms = sa.query(RepoToPerm, UserToPerm, Permission, Repository)\
187 user_perms = sa.query(RepoToPerm, Permission, Repository)\
187 .outerjoin((UserToPerm, RepoToPerm.user_id == UserToPerm.user_id))\
188 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
188 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
189 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
189 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
190 .filter(RepoToPerm.user_id == user.user_id).all()
190 .filter(RepoToPerm.user_id == user.user_id).all()
191
191
192 for perm in user_perms:
192 for perm in user_perms:
193 if perm.Repository.user_id == user.user_id:#set admin if owner
193 if perm.Repository.user_id == user.user_id:#set admin if owner
194 p = 'repository.admin'
194 p = 'repository.admin'
195 else:
195 else:
196 p = perm.Permission.permission_name
196 p = perm.Permission.permission_name
197 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
197 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
198 meta.Session.remove()
198 meta.Session.remove()
199 return user
199 return user
200
200
201 def get_user(session):
201 def get_user(session):
202 """
202 """
203 Gets user from session, and wraps permissions into user
203 Gets user from session, and wraps permissions into user
204 @param session:
204 @param session:
205 """
205 """
206 user = session.get('hg_app_user', AuthUser())
206 user = session.get('hg_app_user', AuthUser())
207 if user.is_authenticated:
207 if user.is_authenticated:
208 user = fill_data(user)
208 user = fill_data(user)
209 user = fill_perms(user)
209 user = fill_perms(user)
210 session['hg_app_user'] = user
210 session['hg_app_user'] = user
211 session.save()
211 session.save()
212 return user
212 return user
213
213
214 #===============================================================================
214 #===============================================================================
215 # CHECK DECORATORS
215 # CHECK DECORATORS
216 #===============================================================================
216 #===============================================================================
217 class LoginRequired(object):
217 class LoginRequired(object):
218 """Must be logged in to execute this function else redirect to login page"""
218 """Must be logged in to execute this function else redirect to login page"""
219
219
220 def __call__(self, func):
220 def __call__(self, func):
221 return decorator(self.__wrapper, func)
221 return decorator(self.__wrapper, func)
222
222
223 def __wrapper(self, func, *fargs, **fkwargs):
223 def __wrapper(self, func, *fargs, **fkwargs):
224 user = session.get('hg_app_user', AuthUser())
224 user = session.get('hg_app_user', AuthUser())
225 log.debug('Checking login required for user:%s', user.username)
225 log.debug('Checking login required for user:%s', user.username)
226 if user.is_authenticated:
226 if user.is_authenticated:
227 log.debug('user %s is authenticated', user.username)
227 log.debug('user %s is authenticated', user.username)
228 return func(*fargs, **fkwargs)
228 return func(*fargs, **fkwargs)
229 else:
229 else:
230 log.warn('user %s not authenticated', user.username)
230 log.warn('user %s not authenticated', user.username)
231 log.debug('redirecting to login page')
231 log.debug('redirecting to login page')
232 return redirect(url('login_home'))
232 return redirect(url('login_home'))
233
233
234 class PermsDecorator(object):
234 class PermsDecorator(object):
235 """Base class for decorators"""
235 """Base class for decorators"""
236
236
237 def __init__(self, *required_perms):
237 def __init__(self, *required_perms):
238 available_perms = config['available_permissions']
238 available_perms = config['available_permissions']
239 for perm in required_perms:
239 for perm in required_perms:
240 if perm not in available_perms:
240 if perm not in available_perms:
241 raise Exception("'%s' permission is not defined" % perm)
241 raise Exception("'%s' permission is not defined" % perm)
242 self.required_perms = set(required_perms)
242 self.required_perms = set(required_perms)
243 self.user_perms = None
243 self.user_perms = None
244
244
245 def __call__(self, func):
245 def __call__(self, func):
246 return decorator(self.__wrapper, func)
246 return decorator(self.__wrapper, func)
247
247
248
248
249 def __wrapper(self, func, *fargs, **fkwargs):
249 def __wrapper(self, func, *fargs, **fkwargs):
250 # _wrapper.__name__ = func.__name__
250 # _wrapper.__name__ = func.__name__
251 # _wrapper.__dict__.update(func.__dict__)
251 # _wrapper.__dict__.update(func.__dict__)
252 # _wrapper.__doc__ = func.__doc__
252 # _wrapper.__doc__ = func.__doc__
253
253
254 self.user_perms = session.get('hg_app_user', AuthUser()).permissions
254 self.user_perms = session.get('hg_app_user', AuthUser()).permissions
255 log.debug('checking %s permissions %s for %s',
255 log.debug('checking %s permissions %s for %s',
256 self.__class__.__name__, self.required_perms, func.__name__)
256 self.__class__.__name__, self.required_perms, func.__name__)
257
257
258 if self.check_permissions():
258 if self.check_permissions():
259 log.debug('Permission granted for %s', func.__name__)
259 log.debug('Permission granted for %s', func.__name__)
260
260
261 return func(*fargs, **fkwargs)
261 return func(*fargs, **fkwargs)
262
262
263 else:
263 else:
264 log.warning('Permission denied for %s', func.__name__)
264 log.warning('Permission denied for %s', func.__name__)
265 #redirect with forbidden ret code
265 #redirect with forbidden ret code
266 return abort(403)
266 return abort(403)
267
267
268
268
269
269
270 def check_permissions(self):
270 def check_permissions(self):
271 """Dummy function for overriding"""
271 """Dummy function for overriding"""
272 raise Exception('You have to write this function in child class')
272 raise Exception('You have to write this function in child class')
273
273
274 class HasPermissionAllDecorator(PermsDecorator):
274 class HasPermissionAllDecorator(PermsDecorator):
275 """Checks for access permission for all given predicates. All of them
275 """Checks for access permission for all given predicates. All of them
276 have to be meet in order to fulfill the request
276 have to be meet in order to fulfill the request
277 """
277 """
278
278
279 def check_permissions(self):
279 def check_permissions(self):
280 if self.required_perms.issubset(self.user_perms.get('global')):
280 if self.required_perms.issubset(self.user_perms.get('global')):
281 return True
281 return True
282 return False
282 return False
283
283
284
284
285 class HasPermissionAnyDecorator(PermsDecorator):
285 class HasPermissionAnyDecorator(PermsDecorator):
286 """Checks for access permission for any of given predicates. In order to
286 """Checks for access permission for any of given predicates. In order to
287 fulfill the request any of predicates must be meet
287 fulfill the request any of predicates must be meet
288 """
288 """
289
289
290 def check_permissions(self):
290 def check_permissions(self):
291 if self.required_perms.intersection(self.user_perms.get('global')):
291 if self.required_perms.intersection(self.user_perms.get('global')):
292 return True
292 return True
293 return False
293 return False
294
294
295 class HasRepoPermissionAllDecorator(PermsDecorator):
295 class HasRepoPermissionAllDecorator(PermsDecorator):
296 """Checks for access permission for all given predicates for specific
296 """Checks for access permission for all given predicates for specific
297 repository. All of them have to be meet in order to fulfill the request
297 repository. All of them have to be meet in order to fulfill the request
298 """
298 """
299
299
300 def check_permissions(self):
300 def check_permissions(self):
301 repo_name = get_repo_slug(request)
301 repo_name = get_repo_slug(request)
302 try:
302 try:
303 user_perms = set([self.user_perms['repositories'][repo_name]])
303 user_perms = set([self.user_perms['repositories'][repo_name]])
304 except KeyError:
304 except KeyError:
305 return False
305 return False
306 if self.required_perms.issubset(user_perms):
306 if self.required_perms.issubset(user_perms):
307 return True
307 return True
308 return False
308 return False
309
309
310
310
311 class HasRepoPermissionAnyDecorator(PermsDecorator):
311 class HasRepoPermissionAnyDecorator(PermsDecorator):
312 """Checks for access permission for any of given predicates for specific
312 """Checks for access permission for any of given predicates for specific
313 repository. In order to fulfill the request any of predicates must be meet
313 repository. In order to fulfill the request any of predicates must be meet
314 """
314 """
315
315
316 def check_permissions(self):
316 def check_permissions(self):
317 repo_name = get_repo_slug(request)
317 repo_name = get_repo_slug(request)
318
318
319 try:
319 try:
320 user_perms = set([self.user_perms['repositories'][repo_name]])
320 user_perms = set([self.user_perms['repositories'][repo_name]])
321 except KeyError:
321 except KeyError:
322 return False
322 return False
323 if self.required_perms.intersection(user_perms):
323 if self.required_perms.intersection(user_perms):
324 return True
324 return True
325 return False
325 return False
326 #===============================================================================
326 #===============================================================================
327 # CHECK FUNCTIONS
327 # CHECK FUNCTIONS
328 #===============================================================================
328 #===============================================================================
329
329
330 class PermsFunction(object):
330 class PermsFunction(object):
331 """Base function for other check functions"""
331 """Base function for other check functions"""
332
332
333 def __init__(self, *perms):
333 def __init__(self, *perms):
334 available_perms = config['available_permissions']
334 available_perms = config['available_permissions']
335
335
336 for perm in perms:
336 for perm in perms:
337 if perm not in available_perms:
337 if perm not in available_perms:
338 raise Exception("'%s' permission in not defined" % perm)
338 raise Exception("'%s' permission in not defined" % perm)
339 self.required_perms = set(perms)
339 self.required_perms = set(perms)
340 self.user_perms = None
340 self.user_perms = None
341 self.granted_for = ''
341 self.granted_for = ''
342 self.repo_name = None
342 self.repo_name = None
343
343
344 def __call__(self, check_Location=''):
344 def __call__(self, check_Location=''):
345 user = session.get('hg_app_user', False)
345 user = session.get('hg_app_user', False)
346 if not user:
346 if not user:
347 return False
347 return False
348 self.user_perms = user.permissions
348 self.user_perms = user.permissions
349 self.granted_for = user.username
349 self.granted_for = user.username
350 log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
350 log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
351
351
352 if self.check_permissions():
352 if self.check_permissions():
353 log.debug('Permission granted for %s @%s', self.granted_for,
353 log.debug('Permission granted for %s @%s', self.granted_for,
354 check_Location)
354 check_Location)
355 return True
355 return True
356
356
357 else:
357 else:
358 log.warning('Permission denied for %s @%s', self.granted_for,
358 log.warning('Permission denied for %s @%s', self.granted_for,
359 check_Location)
359 check_Location)
360 return False
360 return False
361
361
362 def check_permissions(self):
362 def check_permissions(self):
363 """Dummy function for overriding"""
363 """Dummy function for overriding"""
364 raise Exception('You have to write this function in child class')
364 raise Exception('You have to write this function in child class')
365
365
366 class HasPermissionAll(PermsFunction):
366 class HasPermissionAll(PermsFunction):
367 def check_permissions(self):
367 def check_permissions(self):
368 if self.required_perms.issubset(self.user_perms.get('global')):
368 if self.required_perms.issubset(self.user_perms.get('global')):
369 return True
369 return True
370 return False
370 return False
371
371
372 class HasPermissionAny(PermsFunction):
372 class HasPermissionAny(PermsFunction):
373 def check_permissions(self):
373 def check_permissions(self):
374 if self.required_perms.intersection(self.user_perms.get('global')):
374 if self.required_perms.intersection(self.user_perms.get('global')):
375 return True
375 return True
376 return False
376 return False
377
377
378 class HasRepoPermissionAll(PermsFunction):
378 class HasRepoPermissionAll(PermsFunction):
379
379
380 def __call__(self, repo_name=None, check_Location=''):
380 def __call__(self, repo_name=None, check_Location=''):
381 self.repo_name = repo_name
381 self.repo_name = repo_name
382 return super(HasRepoPermissionAll, self).__call__(check_Location)
382 return super(HasRepoPermissionAll, self).__call__(check_Location)
383
383
384 def check_permissions(self):
384 def check_permissions(self):
385 if not self.repo_name:
385 if not self.repo_name:
386 self.repo_name = get_repo_slug(request)
386 self.repo_name = get_repo_slug(request)
387
387
388 try:
388 try:
389 self.user_perms = set([self.user_perms['repositories']\
389 self.user_perms = set([self.user_perms['repositories']\
390 [self.repo_name]])
390 [self.repo_name]])
391 except KeyError:
391 except KeyError:
392 return False
392 return False
393 self.granted_for = self.repo_name
393 self.granted_for = self.repo_name
394 if self.required_perms.issubset(self.user_perms):
394 if self.required_perms.issubset(self.user_perms):
395 return True
395 return True
396 return False
396 return False
397
397
398 class HasRepoPermissionAny(PermsFunction):
398 class HasRepoPermissionAny(PermsFunction):
399
399
400 def __call__(self, repo_name=None, check_Location=''):
400 def __call__(self, repo_name=None, check_Location=''):
401 self.repo_name = repo_name
401 self.repo_name = repo_name
402 return super(HasRepoPermissionAny, self).__call__(check_Location)
402 return super(HasRepoPermissionAny, self).__call__(check_Location)
403
403
404 def check_permissions(self):
404 def check_permissions(self):
405 if not self.repo_name:
405 if not self.repo_name:
406 self.repo_name = get_repo_slug(request)
406 self.repo_name = get_repo_slug(request)
407
407
408 try:
408 try:
409 self.user_perms = set([self.user_perms['repositories']\
409 self.user_perms = set([self.user_perms['repositories']\
410 [self.repo_name]])
410 [self.repo_name]])
411 except KeyError:
411 except KeyError:
412 return False
412 return False
413 self.granted_for = self.repo_name
413 self.granted_for = self.repo_name
414 if self.required_perms.intersection(self.user_perms):
414 if self.required_perms.intersection(self.user_perms):
415 return True
415 return True
416 return False
416 return False
417
417
418 #===============================================================================
418 #===============================================================================
419 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
419 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
420 #===============================================================================
420 #===============================================================================
421
421
422 class HasPermissionAnyMiddleware(object):
422 class HasPermissionAnyMiddleware(object):
423 def __init__(self, *perms):
423 def __init__(self, *perms):
424 self.required_perms = set(perms)
424 self.required_perms = set(perms)
425
425
426 def __call__(self, user, repo_name):
426 def __call__(self, user, repo_name):
427 usr = AuthUser()
427 usr = AuthUser()
428 usr.user_id = user.user_id
428 usr.user_id = user.user_id
429 usr.username = user.username
429 usr.username = user.username
430 usr.is_admin = user.admin
430 usr.is_admin = user.admin
431
431
432 try:
432 try:
433 self.user_perms = set([fill_perms(usr)\
433 self.user_perms = set([fill_perms(usr)\
434 .permissions['repositories'][repo_name]])
434 .permissions['repositories'][repo_name]])
435 except:
435 except:
436 self.user_perms = set()
436 self.user_perms = set()
437 self.granted_for = ''
437 self.granted_for = ''
438 self.username = user.username
438 self.username = user.username
439 self.repo_name = repo_name
439 self.repo_name = repo_name
440 return self.check_permissions()
440 return self.check_permissions()
441
441
442 def check_permissions(self):
442 def check_permissions(self):
443 log.debug('checking mercurial protocol '
443 log.debug('checking mercurial protocol '
444 'permissions for user:%s repository:%s',
444 'permissions for user:%s repository:%s',
445 self.username, self.repo_name)
445 self.username, self.repo_name)
446 if self.required_perms.intersection(self.user_perms):
446 if self.required_perms.intersection(self.user_perms):
447 log.debug('permission granted')
447 log.debug('permission granted')
448 return True
448 return True
449 log.debug('permission denied')
449 log.debug('permission denied')
450 return False
450 return False
General Comments 0
You need to be logged in to leave comments. Login now