comparison rhodecode/lib/auth.py @ 1016:3790279d2538 beta

#56 added propagation of permission from group
author Marcin Kuzminski <marcin@python-works.com>
date Wed, 09 Feb 2011 18:54:20 +0100
parents b232a36cc51f
children 405b80e4ccd5
comparison
equal deleted inserted replaced
1015:65129c332d37 1016:3790279d2538
39 from rhodecode.lib.auth_ldap import AuthLdap 39 from rhodecode.lib.auth_ldap import AuthLdap
40 40
41 from rhodecode.model import meta 41 from rhodecode.model import meta
42 from rhodecode.model.user import UserModel 42 from rhodecode.model.user import UserModel
43 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \ 43 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \
44 UserToPerm 44 UserToPerm, UsersGroupToPerm, UsersGroupMember
45 45
46 46
47 log = logging.getLogger(__name__) 47 log = logging.getLogger(__name__)
48
49
50 PERM_WEIGHTS = {'repository.none':0,
51 'repository.read':1,
52 'repository.write':3,
53 'repository.admin':3}
54
48 55
49 class PasswordGenerator(object): 56 class PasswordGenerator(object):
50 """This is a simple class for generating password from 57 """This is a simple class for generating password from
51 different sets of characters 58 different sets of characters
52 usage: 59 usage:
71 self.passwd = ''.join([random.choice(type) for _ in xrange(len)]) 78 self.passwd = ''.join([random.choice(type) for _ in xrange(len)])
72 return self.passwd 79 return self.passwd
73 80
74 81
75 def get_crypt_password(password): 82 def get_crypt_password(password):
76 """Cryptographic function used for password hashing based on sha1 83 """Cryptographic function used for password hashing based on pybcrypt
84
77 :param password: password to hash 85 :param password: password to hash
78 """ 86 """
79 return bcrypt.hashpw(password, bcrypt.gensalt(10)) 87 return bcrypt.hashpw(password, bcrypt.gensalt(10))
80 88
81 def check_password(password, hashed): 89 def check_password(password, hashed):
82 return bcrypt.hashpw(password, hashed) == hashed 90 return bcrypt.hashpw(password, hashed) == hashed
83 91
84 def authfunc(environ, username, password): 92 def authfunc(environ, username, password):
85 """ 93 """Dummy authentication function used in Mercurial/Git/ and access control,
86 Dummy authentication function used in Mercurial/Git/ and access control,
87 94
88 :param environ: needed only for using in Basic auth 95 :param environ: needed only for using in Basic auth
89 """ 96 """
90 return authenticate(username, password) 97 return authenticate(username, password)
91 98
92 99
93 def authenticate(username, password): 100 def authenticate(username, password):
94 """ 101 """Authentication function used for access control,
95 Authentication function used for access control,
96 firstly checks for db authentication then if ldap is enabled for ldap 102 firstly checks for db authentication then if ldap is enabled for ldap
97 authentication, also creates ldap user if not in database 103 authentication, also creates ldap user if not in database
98 104
99 :param username: username 105 :param username: username
100 :param password: password 106 :param password: password
128 134
129 from rhodecode.model.settings import SettingsModel 135 from rhodecode.model.settings import SettingsModel
130 ldap_settings = SettingsModel().get_ldap_settings() 136 ldap_settings = SettingsModel().get_ldap_settings()
131 137
132 #====================================================================== 138 #======================================================================
133 # FALLBACK TO LDAP AUTH IN ENABLE 139 # FALLBACK TO LDAP AUTH IF ENABLE
134 #====================================================================== 140 #======================================================================
135 if ldap_settings.get('ldap_active', False): 141 if ldap_settings.get('ldap_active', False):
136 log.debug("Authenticating user using ldap") 142 log.debug("Authenticating user using ldap")
137 kwargs = { 143 kwargs = {
138 'server':ldap_settings.get('ldap_host', ''), 144 'server':ldap_settings.get('ldap_host', ''),
158 'lastname' : ldap_attrs[ldap_settings.get('ldap_attr_lastname')][0], 164 'lastname' : ldap_attrs[ldap_settings.get('ldap_attr_lastname')][0],
159 'email' : ldap_attrs[ldap_settings.get('ldap_attr_email')][0], 165 'email' : ldap_attrs[ldap_settings.get('ldap_attr_email')][0],
160 } 166 }
161 167
162 if user_model.create_ldap(username, password, user_dn, user_attrs): 168 if user_model.create_ldap(username, password, user_dn, user_attrs):
163 log.info('created new ldap user') 169 log.info('created new ldap user %s', username)
164 170
165 return True 171 return True
166 except (LdapUsernameError, LdapPasswordError,): 172 except (LdapUsernameError, LdapPasswordError,):
167 pass 173 pass
168 except (Exception,): 174 except (Exception,):
169 log.error(traceback.format_exc()) 175 log.error(traceback.format_exc())
170 pass 176 pass
171 return False 177 return False
172 178
173 class AuthUser(object): 179 class AuthUser(object):
174 """ 180 """A simple object that handles a mercurial username for authentication
175 A simple object that handles a mercurial username for authentication 181 """
176 """ 182
177 def __init__(self): 183 def __init__(self):
178 self.username = 'None' 184 self.username = 'None'
179 self.name = '' 185 self.name = ''
180 self.lastname = '' 186 self.lastname = ''
181 self.email = '' 187 self.email = ''
187 def __repr__(self): 193 def __repr__(self):
188 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username) 194 return "<AuthUser('id:%s:%s')>" % (self.user_id, self.username)
189 195
190 def set_available_permissions(config): 196 def set_available_permissions(config):
191 """This function will propagate pylons globals with all available defined 197 """This function will propagate pylons globals with all available defined
192 permission given in db. We don't wannt to check each time from db for new 198 permission given in db. We don't want to check each time from db for new
193 permissions since adding a new permission also requires application restart 199 permissions since adding a new permission also requires application restart
194 ie. to decorate new views with the newly created permission 200 ie. to decorate new views with the newly created permission
195 201
196 :param config: current pylons config instance 202 :param config: current pylons config instance
197 203
211 config['base_path'] = config['pylons.app_globals'].base_path 217 config['base_path'] = config['pylons.app_globals'].base_path
212 218
213 219
214 def fill_perms(user): 220 def fill_perms(user):
215 """Fills user permission attribute with permissions taken from database 221 """Fills user permission attribute with permissions taken from database
216 222 works for permissions given for repositories, and for permissions that
217 :param user: 223 as part of beeing group member
218 224
225 :param user: user instance to fill his perms
219 """ 226 """
220 227
221 sa = meta.Session() 228 sa = meta.Session()
222 user.permissions['repositories'] = {} 229 user.permissions['repositories'] = {}
223 user.permissions['global'] = set() 230 user.permissions['global'] = set()
253 .filter(User.username == 'default').one()) 260 .filter(User.username == 'default').one())
254 261
255 for perm in default_global_perms: 262 for perm in default_global_perms:
256 user.permissions['global'].add(perm.permission.permission_name) 263 user.permissions['global'].add(perm.permission.permission_name)
257 264
258 #default repositories 265 #default for repositories
259 for perm in default_perms: 266 for perm in default_perms:
260 if perm.Repository.private and not perm.Repository.user_id == user.user_id: 267 if perm.Repository.private and not perm.Repository.user_id == user.user_id:
261 #disable defaults for private repos, 268 #disable defaults for private repos,
262 p = 'repository.none' 269 p = 'repository.none'
263 elif perm.Repository.user_id == user.user_id: 270 elif perm.Repository.user_id == user.user_id:
267 p = perm.Permission.permission_name 274 p = perm.Permission.permission_name
268 275
269 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p 276 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
270 277
271 #======================================================================= 278 #=======================================================================
272 # #overwrite default with user permissions if any 279 # overwrite default with user permissions if any
273 #======================================================================= 280 #=======================================================================
274 user_perms = sa.query(RepoToPerm, Permission, Repository)\ 281 user_perms = sa.query(RepoToPerm, Permission, Repository)\
275 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\ 282 .join((Repository, RepoToPerm.repository_id == Repository.repo_id))\
276 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\ 283 .join((Permission, RepoToPerm.permission_id == Permission.permission_id))\
277 .filter(RepoToPerm.user_id == user.user_id).all() 284 .filter(RepoToPerm.user_id == user.user_id).all()
280 if perm.Repository.user_id == user.user_id:#set admin if owner 287 if perm.Repository.user_id == user.user_id:#set admin if owner
281 p = 'repository.admin' 288 p = 'repository.admin'
282 else: 289 else:
283 p = perm.Permission.permission_name 290 p = perm.Permission.permission_name
284 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p 291 user.permissions['repositories'][perm.RepoToPerm.repository.repo_name] = p
292
293
294 #=======================================================================
295 # check if user is part of groups for this repository and fill in
296 # (or replace with higher) permissions
297 #=======================================================================
298 user_perms_from_users_groups = sa.query(UsersGroupToPerm, Permission, Repository,)\
299 .join((Repository, UsersGroupToPerm.repository_id == Repository.repo_id))\
300 .join((Permission, UsersGroupToPerm.permission_id == Permission.permission_id))\
301 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
302 .filter(UsersGroupMember.user_id == user.user_id).all()
303
304 for perm in user_perms_from_users_groups:
305 p = perm.Permission.permission_name
306 cur_perm = user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name]
307 #overwrite permission only if it's greater than permission given from other sources
308 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
309 user.permissions['repositories'][perm.UsersGroupToPerm.repository.repo_name] = p
310
285 meta.Session.remove() 311 meta.Session.remove()
286 return user 312 return user
287 313
288 def get_user(session): 314 def get_user(session):
289 """ 315 """Gets user from session, and wraps permissions into user
290 Gets user from session, and wraps permissions into user 316
291 :param session: 317 :param session:
292 """ 318 """
293 user = session.get('rhodecode_user', AuthUser()) 319 user = session.get('rhodecode_user', AuthUser())
294 #if the user is not logged in we check for anonymous access 320 #if the user is not logged in we check for anonymous access
295 #if user is logged and it's a default user check if we still have anonymous 321 #if user is logged and it's a default user check if we still have anonymous