1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
from functools import wraps
from pylons import session, url, app_globals as g
from pylons.controllers.util import abort, redirect
from pylons_app.model import meta
from pylons_app.model.db import User
from sqlalchemy.exc import OperationalError
from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound
import crypt
import logging
log = logging.getLogger(__name__)
def get_crypt_password(password):
"""
Cryptographic function used for password hashing
@param password: password to hash
"""
return crypt.crypt(password, '6a')
def authfunc(environ, username, password):
sa = meta.Session
password_crypt = get_crypt_password(password)
try:
user = sa.query(User).filter(User.username == username).one()
except (NoResultFound, MultipleResultsFound, OperationalError) as e:
log.error(e)
user = None
if user:
if user.active:
if user.username == username and user.password == password_crypt:
log.info('user %s authenticated correctly', username)
return True
else:
log.error('user %s is disabled', username)
return False
class AuthUser(object):
"""
A simple object that handles a mercurial username for authentication
"""
username = 'None'
is_authenticated = False
is_admin = False
permissions = set()
group = set()
def __init__(self):
pass
def set_available_permissions(config):
"""
This function will propagate pylons globals with all available defined
permission given in db. We don't wannt to check each time from db for new
permissions since adding a new permission also requires application restart
ie. to decorate new views with the newly created permission
@param config:
"""
from pylons_app.model.meta import Session
from pylons_app.model.db import Permission
logging.info('getting information about all available permissions')
sa = Session()
all_perms = sa.query(Permission).all()
config['pylons.app_globals'].available_permissions = [x.permission_name for x in all_perms]
#===============================================================================
# DECORATORS
#===============================================================================
class LoginRequired(object):
"""
Must be logged in to execute this function else redirect to login page
"""
def __init__(self):
pass
def __call__(self, func):
@wraps(func)
def _wrapper(*fargs, **fkwargs):
user = session.get('hg_app_user', AuthUser())
log.info('Checking login required for user:%s', user.username)
if user.is_authenticated:
log.info('user %s is authenticated', user.username)
func(*fargs)
else:
logging.info('user %s not authenticated', user.username)
logging.info('redirecting to login page')
return redirect(url('login_home'))
return _wrapper
class PermsDecorator(object):
def __init__(self, *perms):
available_perms = g.available_permissions
for perm in perms:
if perm not in available_perms:
raise Exception("'%s' permission in not defined" % perm)
self.required_perms = set(perms)
self.user_perms = set([])#propagate this list from somewhere.
def __call__(self, func):
@wraps(func)
def _wrapper(*args, **kwargs):
logging.info('checking %s permissions %s for %s',
self.__class__.__name__[-3:], self.required_perms, func.__name__)
if self.check_permissions():
logging.info('Permission granted for %s', func.__name__)
return func(*args, **kwargs)
else:
logging.warning('Permission denied for %s', func.__name__)
#redirect with forbidden ret code
return redirect(url('access_denied'), 403)
return _wrapper
def check_permissions(self):
"""
Dummy function for overiding
"""
raise Exception('You have to write this function in child class')
class CheckPermissionAll(PermsDecorator):
"""
Checks for access permission for all given predicates. All of them have to
be meet in order to fulfill the request
"""
def check_permissions(self):
if self.required_perms.issubset(self.user_perms):
return True
return False
class CheckPermissionAny(PermsDecorator):
"""
Checks for access permission for any of given predicates. In order to
fulfill the request any of predicates must be meet
"""
def check_permissions(self):
if self.required_perms.intersection(self.user_perms):
return True
return False
|