##// END OF EJS Templates
Added redirection to page that request came from, after login in
marcink -
r437:930f8182 default
parent child Browse files
Show More
@@ -1,97 +1,102
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 c.came_from = request.GET.get('came_from',None)
46
45 if c.hg_app_user.is_authenticated:
47 if c.hg_app_user.is_authenticated:
46 return redirect(url('hg_home'))
48 return redirect(url('hg_home'))
47
49
48 if request.POST:
50 if request.POST:
49 #import Login Form validator class
51 #import Login Form validator class
50 login_form = LoginForm()
52 login_form = LoginForm()
51 try:
53 try:
52 c.form_result = login_form.to_python(dict(request.POST))
54 c.form_result = login_form.to_python(dict(request.POST))
55 if c.came_from:
56 return redirect(c.came_from)
57 else:
53 return redirect(url('hg_home'))
58 return redirect(url('hg_home'))
54
59
55 except formencode.Invalid as errors:
60 except formencode.Invalid as errors:
56 return htmlfill.render(
61 return htmlfill.render(
57 render('/login.html'),
62 render('/login.html'),
58 defaults=errors.value,
63 defaults=errors.value,
59 errors=errors.error_dict or {},
64 errors=errors.error_dict or {},
60 prefix_error=False,
65 prefix_error=False,
61 encoding="UTF-8")
66 encoding="UTF-8")
62
67
63 return render('/login.html')
68 return render('/login.html')
64
69
65 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')
70 @HasPermissionAnyDecorator('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')
66 def register(self):
71 def register(self):
67 user_model = UserModel()
72 user_model = UserModel()
68 c.auto_active = False
73 c.auto_active = False
69 for perm in user_model.get_default().user_perms:
74 for perm in user_model.get_default().user_perms:
70 if perm.permission.permission_name == 'hg.register.auto_activate':
75 if perm.permission.permission_name == 'hg.register.auto_activate':
71 c.auto_active = True
76 c.auto_active = True
72 break
77 break
73
78
74 if request.POST:
79 if request.POST:
75
80
76 register_form = RegisterForm()()
81 register_form = RegisterForm()()
77 try:
82 try:
78 form_result = register_form.to_python(dict(request.POST))
83 form_result = register_form.to_python(dict(request.POST))
79 form_result['active'] = c.auto_active
84 form_result['active'] = c.auto_active
80 user_model.create_registration(form_result)
85 user_model.create_registration(form_result)
81 return redirect(url('login_home'))
86 return redirect(url('login_home'))
82
87
83 except formencode.Invalid as errors:
88 except formencode.Invalid as errors:
84 return htmlfill.render(
89 return htmlfill.render(
85 render('/register.html'),
90 render('/register.html'),
86 defaults=errors.value,
91 defaults=errors.value,
87 errors=errors.error_dict or {},
92 errors=errors.error_dict or {},
88 prefix_error=False,
93 prefix_error=False,
89 encoding="UTF-8")
94 encoding="UTF-8")
90
95
91 return render('/register.html')
96 return render('/register.html')
92
97
93 def logout(self):
98 def logout(self):
94 session['hg_app_user'] = AuthUser()
99 session['hg_app_user'] = AuthUser()
95 session.save()
100 session.save()
96 log.info('Logging out and setting user as Empty')
101 log.info('Logging out and setting user as Empty')
97 redirect(url('hg_home'))
102 redirect(url('hg_home'))
@@ -1,450 +1,454
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 return user
127 return user
128
128
129 def fill_perms(user):
129 def fill_perms(user):
130 """
130 """
131 Fills user permission attribute with permissions taken from database
131 Fills user permission attribute with permissions taken from database
132 @param user:
132 @param user:
133 """
133 """
134
134
135 sa = meta.Session
135 sa = meta.Session
136 user.permissions['repositories'] = {}
136 user.permissions['repositories'] = {}
137 user.permissions['global'] = set()
137 user.permissions['global'] = set()
138
138
139 #===========================================================================
139 #===========================================================================
140 # fetch default permissions
140 # fetch default permissions
141 #===========================================================================
141 #===========================================================================
142 default_perms = sa.query(RepoToPerm, Repository, Permission)\
142 default_perms = sa.query(RepoToPerm, Repository, Permission)\
143 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
143 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
144 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
144 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
145 .filter(RepoToPerm.user == sa.query(User).filter(User.username ==
145 .filter(RepoToPerm.user == sa.query(User).filter(User.username ==
146 'default').scalar()).all()
146 'default').scalar()).all()
147
147
148 if user.is_admin:
148 if user.is_admin:
149 #=======================================================================
149 #=======================================================================
150 # #admin have all default rights set to admin
150 # #admin have all default rights set to admin
151 #=======================================================================
151 #=======================================================================
152 user.permissions['global'].add('hg.admin')
152 user.permissions['global'].add('hg.admin')
153
153
154 for perm in default_perms:
154 for perm in default_perms:
155 p = 'repository.admin'
155 p = 'repository.admin'
156 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
156 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
157
157
158 else:
158 else:
159 #=======================================================================
159 #=======================================================================
160 # set default permissions
160 # set default permissions
161 #=======================================================================
161 #=======================================================================
162
162
163 #default global
163 #default global
164 default_global_perms = sa.query(UserToPerm)\
164 default_global_perms = sa.query(UserToPerm)\
165 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
165 .filter(UserToPerm.user == sa.query(User).filter(User.username ==
166 'default').one())
166 'default').one())
167
167
168 for perm in default_global_perms:
168 for perm in default_global_perms:
169 user.permissions['global'].add(perm.permission.permission_name)
169 user.permissions['global'].add(perm.permission.permission_name)
170
170
171 #default repositories
171 #default repositories
172 for perm in default_perms:
172 for perm in default_perms:
173 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:
174 #disable defaults for private repos,
174 #disable defaults for private repos,
175 p = 'repository.none'
175 p = 'repository.none'
176 elif perm.Repository.user_id == user.user_id:
176 elif perm.Repository.user_id == user.user_id:
177 #set admin if owner
177 #set admin if owner
178 p = 'repository.admin'
178 p = 'repository.admin'
179 else:
179 else:
180 p = perm.Permission.permission_name
180 p = perm.Permission.permission_name
181
181
182 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
182 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
183
183
184 #=======================================================================
184 #=======================================================================
185 # #overwrite default with user permissions if any
185 # #overwrite default with user permissions if any
186 #=======================================================================
186 #=======================================================================
187 user_perms = sa.query(RepoToPerm, Permission, Repository)\
187 user_perms = sa.query(RepoToPerm, Permission, Repository)\
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
232 return redirect(url('login_home'))
232 p = request.environ.get('PATH_INFO')
233 if request.environ.get('QUERY_STRING'):
234 p+='?'+request.environ.get('QUERY_STRING')
235 log.debug('redirecting to login page with %',p)
236 return redirect(url('login_home',came_from=p))
233
237
234 class PermsDecorator(object):
238 class PermsDecorator(object):
235 """Base class for decorators"""
239 """Base class for decorators"""
236
240
237 def __init__(self, *required_perms):
241 def __init__(self, *required_perms):
238 available_perms = config['available_permissions']
242 available_perms = config['available_permissions']
239 for perm in required_perms:
243 for perm in required_perms:
240 if perm not in available_perms:
244 if perm not in available_perms:
241 raise Exception("'%s' permission is not defined" % perm)
245 raise Exception("'%s' permission is not defined" % perm)
242 self.required_perms = set(required_perms)
246 self.required_perms = set(required_perms)
243 self.user_perms = None
247 self.user_perms = None
244
248
245 def __call__(self, func):
249 def __call__(self, func):
246 return decorator(self.__wrapper, func)
250 return decorator(self.__wrapper, func)
247
251
248
252
249 def __wrapper(self, func, *fargs, **fkwargs):
253 def __wrapper(self, func, *fargs, **fkwargs):
250 # _wrapper.__name__ = func.__name__
254 # _wrapper.__name__ = func.__name__
251 # _wrapper.__dict__.update(func.__dict__)
255 # _wrapper.__dict__.update(func.__dict__)
252 # _wrapper.__doc__ = func.__doc__
256 # _wrapper.__doc__ = func.__doc__
253
257
254 self.user_perms = session.get('hg_app_user', AuthUser()).permissions
258 self.user_perms = session.get('hg_app_user', AuthUser()).permissions
255 log.debug('checking %s permissions %s for %s',
259 log.debug('checking %s permissions %s for %s',
256 self.__class__.__name__, self.required_perms, func.__name__)
260 self.__class__.__name__, self.required_perms, func.__name__)
257
261
258 if self.check_permissions():
262 if self.check_permissions():
259 log.debug('Permission granted for %s', func.__name__)
263 log.debug('Permission granted for %s', func.__name__)
260
264
261 return func(*fargs, **fkwargs)
265 return func(*fargs, **fkwargs)
262
266
263 else:
267 else:
264 log.warning('Permission denied for %s', func.__name__)
268 log.warning('Permission denied for %s', func.__name__)
265 #redirect with forbidden ret code
269 #redirect with forbidden ret code
266 return abort(403)
270 return abort(403)
267
271
268
272
269
273
270 def check_permissions(self):
274 def check_permissions(self):
271 """Dummy function for overriding"""
275 """Dummy function for overriding"""
272 raise Exception('You have to write this function in child class')
276 raise Exception('You have to write this function in child class')
273
277
274 class HasPermissionAllDecorator(PermsDecorator):
278 class HasPermissionAllDecorator(PermsDecorator):
275 """Checks for access permission for all given predicates. All of them
279 """Checks for access permission for all given predicates. All of them
276 have to be meet in order to fulfill the request
280 have to be meet in order to fulfill the request
277 """
281 """
278
282
279 def check_permissions(self):
283 def check_permissions(self):
280 if self.required_perms.issubset(self.user_perms.get('global')):
284 if self.required_perms.issubset(self.user_perms.get('global')):
281 return True
285 return True
282 return False
286 return False
283
287
284
288
285 class HasPermissionAnyDecorator(PermsDecorator):
289 class HasPermissionAnyDecorator(PermsDecorator):
286 """Checks for access permission for any of given predicates. In order to
290 """Checks for access permission for any of given predicates. In order to
287 fulfill the request any of predicates must be meet
291 fulfill the request any of predicates must be meet
288 """
292 """
289
293
290 def check_permissions(self):
294 def check_permissions(self):
291 if self.required_perms.intersection(self.user_perms.get('global')):
295 if self.required_perms.intersection(self.user_perms.get('global')):
292 return True
296 return True
293 return False
297 return False
294
298
295 class HasRepoPermissionAllDecorator(PermsDecorator):
299 class HasRepoPermissionAllDecorator(PermsDecorator):
296 """Checks for access permission for all given predicates for specific
300 """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
301 repository. All of them have to be meet in order to fulfill the request
298 """
302 """
299
303
300 def check_permissions(self):
304 def check_permissions(self):
301 repo_name = get_repo_slug(request)
305 repo_name = get_repo_slug(request)
302 try:
306 try:
303 user_perms = set([self.user_perms['repositories'][repo_name]])
307 user_perms = set([self.user_perms['repositories'][repo_name]])
304 except KeyError:
308 except KeyError:
305 return False
309 return False
306 if self.required_perms.issubset(user_perms):
310 if self.required_perms.issubset(user_perms):
307 return True
311 return True
308 return False
312 return False
309
313
310
314
311 class HasRepoPermissionAnyDecorator(PermsDecorator):
315 class HasRepoPermissionAnyDecorator(PermsDecorator):
312 """Checks for access permission for any of given predicates for specific
316 """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
317 repository. In order to fulfill the request any of predicates must be meet
314 """
318 """
315
319
316 def check_permissions(self):
320 def check_permissions(self):
317 repo_name = get_repo_slug(request)
321 repo_name = get_repo_slug(request)
318
322
319 try:
323 try:
320 user_perms = set([self.user_perms['repositories'][repo_name]])
324 user_perms = set([self.user_perms['repositories'][repo_name]])
321 except KeyError:
325 except KeyError:
322 return False
326 return False
323 if self.required_perms.intersection(user_perms):
327 if self.required_perms.intersection(user_perms):
324 return True
328 return True
325 return False
329 return False
326 #===============================================================================
330 #===============================================================================
327 # CHECK FUNCTIONS
331 # CHECK FUNCTIONS
328 #===============================================================================
332 #===============================================================================
329
333
330 class PermsFunction(object):
334 class PermsFunction(object):
331 """Base function for other check functions"""
335 """Base function for other check functions"""
332
336
333 def __init__(self, *perms):
337 def __init__(self, *perms):
334 available_perms = config['available_permissions']
338 available_perms = config['available_permissions']
335
339
336 for perm in perms:
340 for perm in perms:
337 if perm not in available_perms:
341 if perm not in available_perms:
338 raise Exception("'%s' permission in not defined" % perm)
342 raise Exception("'%s' permission in not defined" % perm)
339 self.required_perms = set(perms)
343 self.required_perms = set(perms)
340 self.user_perms = None
344 self.user_perms = None
341 self.granted_for = ''
345 self.granted_for = ''
342 self.repo_name = None
346 self.repo_name = None
343
347
344 def __call__(self, check_Location=''):
348 def __call__(self, check_Location=''):
345 user = session.get('hg_app_user', False)
349 user = session.get('hg_app_user', False)
346 if not user:
350 if not user:
347 return False
351 return False
348 self.user_perms = user.permissions
352 self.user_perms = user.permissions
349 self.granted_for = user.username
353 self.granted_for = user.username
350 log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
354 log.debug('checking %s %s', self.__class__.__name__, self.required_perms)
351
355
352 if self.check_permissions():
356 if self.check_permissions():
353 log.debug('Permission granted for %s @%s', self.granted_for,
357 log.debug('Permission granted for %s @%s', self.granted_for,
354 check_Location)
358 check_Location)
355 return True
359 return True
356
360
357 else:
361 else:
358 log.warning('Permission denied for %s @%s', self.granted_for,
362 log.warning('Permission denied for %s @%s', self.granted_for,
359 check_Location)
363 check_Location)
360 return False
364 return False
361
365
362 def check_permissions(self):
366 def check_permissions(self):
363 """Dummy function for overriding"""
367 """Dummy function for overriding"""
364 raise Exception('You have to write this function in child class')
368 raise Exception('You have to write this function in child class')
365
369
366 class HasPermissionAll(PermsFunction):
370 class HasPermissionAll(PermsFunction):
367 def check_permissions(self):
371 def check_permissions(self):
368 if self.required_perms.issubset(self.user_perms.get('global')):
372 if self.required_perms.issubset(self.user_perms.get('global')):
369 return True
373 return True
370 return False
374 return False
371
375
372 class HasPermissionAny(PermsFunction):
376 class HasPermissionAny(PermsFunction):
373 def check_permissions(self):
377 def check_permissions(self):
374 if self.required_perms.intersection(self.user_perms.get('global')):
378 if self.required_perms.intersection(self.user_perms.get('global')):
375 return True
379 return True
376 return False
380 return False
377
381
378 class HasRepoPermissionAll(PermsFunction):
382 class HasRepoPermissionAll(PermsFunction):
379
383
380 def __call__(self, repo_name=None, check_Location=''):
384 def __call__(self, repo_name=None, check_Location=''):
381 self.repo_name = repo_name
385 self.repo_name = repo_name
382 return super(HasRepoPermissionAll, self).__call__(check_Location)
386 return super(HasRepoPermissionAll, self).__call__(check_Location)
383
387
384 def check_permissions(self):
388 def check_permissions(self):
385 if not self.repo_name:
389 if not self.repo_name:
386 self.repo_name = get_repo_slug(request)
390 self.repo_name = get_repo_slug(request)
387
391
388 try:
392 try:
389 self.user_perms = set([self.user_perms['repositories']\
393 self.user_perms = set([self.user_perms['repositories']\
390 [self.repo_name]])
394 [self.repo_name]])
391 except KeyError:
395 except KeyError:
392 return False
396 return False
393 self.granted_for = self.repo_name
397 self.granted_for = self.repo_name
394 if self.required_perms.issubset(self.user_perms):
398 if self.required_perms.issubset(self.user_perms):
395 return True
399 return True
396 return False
400 return False
397
401
398 class HasRepoPermissionAny(PermsFunction):
402 class HasRepoPermissionAny(PermsFunction):
399
403
400 def __call__(self, repo_name=None, check_Location=''):
404 def __call__(self, repo_name=None, check_Location=''):
401 self.repo_name = repo_name
405 self.repo_name = repo_name
402 return super(HasRepoPermissionAny, self).__call__(check_Location)
406 return super(HasRepoPermissionAny, self).__call__(check_Location)
403
407
404 def check_permissions(self):
408 def check_permissions(self):
405 if not self.repo_name:
409 if not self.repo_name:
406 self.repo_name = get_repo_slug(request)
410 self.repo_name = get_repo_slug(request)
407
411
408 try:
412 try:
409 self.user_perms = set([self.user_perms['repositories']\
413 self.user_perms = set([self.user_perms['repositories']\
410 [self.repo_name]])
414 [self.repo_name]])
411 except KeyError:
415 except KeyError:
412 return False
416 return False
413 self.granted_for = self.repo_name
417 self.granted_for = self.repo_name
414 if self.required_perms.intersection(self.user_perms):
418 if self.required_perms.intersection(self.user_perms):
415 return True
419 return True
416 return False
420 return False
417
421
418 #===============================================================================
422 #===============================================================================
419 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
423 # SPECIAL VERSION TO HANDLE MIDDLEWARE AUTH
420 #===============================================================================
424 #===============================================================================
421
425
422 class HasPermissionAnyMiddleware(object):
426 class HasPermissionAnyMiddleware(object):
423 def __init__(self, *perms):
427 def __init__(self, *perms):
424 self.required_perms = set(perms)
428 self.required_perms = set(perms)
425
429
426 def __call__(self, user, repo_name):
430 def __call__(self, user, repo_name):
427 usr = AuthUser()
431 usr = AuthUser()
428 usr.user_id = user.user_id
432 usr.user_id = user.user_id
429 usr.username = user.username
433 usr.username = user.username
430 usr.is_admin = user.admin
434 usr.is_admin = user.admin
431
435
432 try:
436 try:
433 self.user_perms = set([fill_perms(usr)\
437 self.user_perms = set([fill_perms(usr)\
434 .permissions['repositories'][repo_name]])
438 .permissions['repositories'][repo_name]])
435 except:
439 except:
436 self.user_perms = set()
440 self.user_perms = set()
437 self.granted_for = ''
441 self.granted_for = ''
438 self.username = user.username
442 self.username = user.username
439 self.repo_name = repo_name
443 self.repo_name = repo_name
440 return self.check_permissions()
444 return self.check_permissions()
441
445
442 def check_permissions(self):
446 def check_permissions(self):
443 log.debug('checking mercurial protocol '
447 log.debug('checking mercurial protocol '
444 'permissions for user:%s repository:%s',
448 'permissions for user:%s repository:%s',
445 self.username, self.repo_name)
449 self.username, self.repo_name)
446 if self.required_perms.intersection(self.user_perms):
450 if self.required_perms.intersection(self.user_perms):
447 log.debug('permission granted')
451 log.debug('permission granted')
448 return True
452 return True
449 log.debug('permission denied')
453 log.debug('permission denied')
450 return False
454 return False
@@ -1,78 +1,78
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml" id="mainhtml">
4 <head>
4 <head>
5 <title>${_('Sign In to hg-app')}</title>
5 <title>${_('Sign In to hg-app')}</title>
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <link rel="icon" href="/images/hgicon.png" type="image/png" />
7 <link rel="icon" href="/images/hgicon.png" type="image/png" />
8 <meta name="robots" content="index, nofollow"/>
8 <meta name="robots" content="index, nofollow"/>
9
9
10 <!-- stylesheets -->
10 <!-- stylesheets -->
11 <link rel="stylesheet" type="text/css" href="/css/reset.css" />
11 <link rel="stylesheet" type="text/css" href="/css/reset.css" />
12 <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />
12 <link rel="stylesheet" type="text/css" href="/css/style.css" media="screen" />
13 <link id="color" rel="stylesheet" type="text/css" href="/css/colors/blue.css" />
13 <link id="color" rel="stylesheet" type="text/css" href="/css/colors/blue.css" />
14
14
15 <!-- scripts -->
15 <!-- scripts -->
16
16
17 </head>
17 </head>
18 <body>
18 <body>
19 <div id="login">
19 <div id="login">
20 <!-- login -->
20 <!-- login -->
21 <div class="title">
21 <div class="title">
22 <h5>${_('Sign In to hg-app')}</h5>
22 <h5>${_('Sign In to hg-app')}</h5>
23 <div class="corner tl"></div>
23 <div class="corner tl"></div>
24 <div class="corner tr"></div>
24 <div class="corner tr"></div>
25 </div>
25 </div>
26 <div class="inner">
26 <div class="inner">
27 ${h.form(h.url.current())}
27 ${h.form(h.url.current(came_from=c.came_from))}
28 <div class="form">
28 <div class="form">
29 <!-- fields -->
29 <!-- fields -->
30
30
31 <div class="fields">
31 <div class="fields">
32 <div class="field">
32 <div class="field">
33 <div class="label">
33 <div class="label">
34 <label for="username">${_('Username')}:</label>
34 <label for="username">${_('Username')}:</label>
35 </div>
35 </div>
36 <div class="input">
36 <div class="input">
37 ${h.text('username',class_='focus',size=40)}
37 ${h.text('username',class_='focus',size=40)}
38 </div>
38 </div>
39
39
40 </div>
40 </div>
41 <div class="field">
41 <div class="field">
42 <div class="label">
42 <div class="label">
43 <label for="password">${_('Password')}:</label>
43 <label for="password">${_('Password')}:</label>
44 </div>
44 </div>
45 <div class="input">
45 <div class="input">
46 ${h.password('password',class_='focus',size=40)}
46 ${h.password('password',class_='focus',size=40)}
47 </div>
47 </div>
48
48
49 </div>
49 </div>
50 ##<div class="field">
50 ##<div class="field">
51 ## <div class="checkbox">
51 ## <div class="checkbox">
52 ## <input type="checkbox" id="remember" name="remember" />
52 ## <input type="checkbox" id="remember" name="remember" />
53 ## <label for="remember">Remember me</label>
53 ## <label for="remember">Remember me</label>
54 ## </div>
54 ## </div>
55 ##</div>
55 ##</div>
56 <div class="buttons">
56 <div class="buttons">
57 ${h.submit('sign_in','Sign In',class_="ui-button ui-widget ui-state-default ui-corner-all")}
57 ${h.submit('sign_in','Sign In',class_="ui-button ui-widget ui-state-default ui-corner-all")}
58 </div>
58 </div>
59 </div>
59 </div>
60 <!-- end fields -->
60 <!-- end fields -->
61 <!-- links -->
61 <!-- links -->
62 <div class="links">
62 <div class="links">
63 ${h.link_to(_('Forgot your password ?'),h.url('#'))}
63 ${h.link_to(_('Forgot your password ?'),h.url('#'))}
64 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
64 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
65 /
65 /
66 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
66 ${h.link_to(_("Don't have an account ?"),h.url('register'))}
67 %endif
67 %endif
68 </div>
68 </div>
69
69
70 <!-- end links -->
70 <!-- end links -->
71 </div>
71 </div>
72 ${h.end_form()}
72 ${h.end_form()}
73 </div>
73 </div>
74 <!-- end login -->
74 <!-- end login -->
75 </div>
75 </div>
76 </body>
76 </body>
77 </html>
77 </html>
78
78
General Comments 0
You need to be logged in to leave comments. Login now