Mercurial > kallithea
comparison rhodecode/model/user.py @ 1512:bf263968da47
merge beta in stable branch
author | Marcin Kuzminski <marcin@python-works.com> |
---|---|
date | Fri, 07 Oct 2011 01:08:50 +0200 |
parents | a3b2b4b4e440 5875955def39 |
children | 5585609772d0 |
comparison
equal
deleted
inserted
replaced
1329:e058df3ff2b4 | 1512:bf263968da47 |
---|---|
2 """ | 2 """ |
3 rhodecode.model.user | 3 rhodecode.model.user |
4 ~~~~~~~~~~~~~~~~~~~~ | 4 ~~~~~~~~~~~~~~~~~~~~ |
5 | 5 |
6 users model for RhodeCode | 6 users model for RhodeCode |
7 | 7 |
8 :created_on: Apr 9, 2010 | 8 :created_on: Apr 9, 2010 |
9 :author: marcink | 9 :author: marcink |
10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com> | 10 :copyright: (C) 2009-2011 Marcin Kuzminski <marcin@python-works.com> |
11 :license: GPLv3, see COPYING for more details. | 11 :license: GPLv3, see COPYING for more details. |
12 """ | 12 """ |
13 # This program is free software: you can redistribute it and/or modify | 13 # This program is free software: you can redistribute it and/or modify |
14 # it under the terms of the GNU General Public License as published by | 14 # it under the terms of the GNU General Public License as published by |
15 # the Free Software Foundation, either version 3 of the License, or | 15 # the Free Software Foundation, either version 3 of the License, or |
28 | 28 |
29 from pylons.i18n.translation import _ | 29 from pylons.i18n.translation import _ |
30 | 30 |
31 from rhodecode.model import BaseModel | 31 from rhodecode.model import BaseModel |
32 from rhodecode.model.caching_query import FromCache | 32 from rhodecode.model.caching_query import FromCache |
33 from rhodecode.model.db import User | 33 from rhodecode.model.db import User, RepoToPerm, Repository, Permission, \ |
34 | 34 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember |
35 from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException | 35 from rhodecode.lib.exceptions import DefaultUserException, \ |
36 UserOwnsReposException | |
36 | 37 |
37 from sqlalchemy.exc import DatabaseError | 38 from sqlalchemy.exc import DatabaseError |
39 from rhodecode.lib import generate_api_key | |
40 from sqlalchemy.orm import joinedload | |
38 | 41 |
39 log = logging.getLogger(__name__) | 42 log = logging.getLogger(__name__) |
43 | |
44 PERM_WEIGHTS = {'repository.none': 0, | |
45 'repository.read': 1, | |
46 'repository.write': 3, | |
47 'repository.admin': 3} | |
48 | |
40 | 49 |
41 class UserModel(BaseModel): | 50 class UserModel(BaseModel): |
42 | 51 |
43 def get(self, user_id, cache=False): | 52 def get(self, user_id, cache=False): |
44 user = self.sa.query(User) | 53 user = self.sa.query(User) |
45 if cache: | 54 if cache: |
46 user = user.options(FromCache("sql_cache_short", | 55 user = user.options(FromCache("sql_cache_short", |
47 "get_user_%s" % user_id)) | 56 "get_user_%s" % user_id)) |
48 return user.get(user_id) | 57 return user.get(user_id) |
49 | |
50 | 58 |
51 def get_by_username(self, username, cache=False, case_insensitive=False): | 59 def get_by_username(self, username, cache=False, case_insensitive=False): |
52 | 60 |
53 if case_insensitive: | 61 if case_insensitive: |
54 user = self.sa.query(User).filter(User.username.ilike(username)) | 62 user = self.sa.query(User).filter(User.username.ilike(username)) |
58 if cache: | 66 if cache: |
59 user = user.options(FromCache("sql_cache_short", | 67 user = user.options(FromCache("sql_cache_short", |
60 "get_user_%s" % username)) | 68 "get_user_%s" % username)) |
61 return user.scalar() | 69 return user.scalar() |
62 | 70 |
71 def get_by_api_key(self, api_key, cache=False): | |
72 | |
73 user = self.sa.query(User)\ | |
74 .filter(User.api_key == api_key) | |
75 if cache: | |
76 user = user.options(FromCache("sql_cache_short", | |
77 "get_user_%s" % api_key)) | |
78 return user.scalar() | |
79 | |
63 def create(self, form_data): | 80 def create(self, form_data): |
64 try: | 81 try: |
65 new_user = User() | 82 new_user = User() |
66 for k, v in form_data.items(): | 83 for k, v in form_data.items(): |
67 setattr(new_user, k, v) | 84 setattr(new_user, k, v) |
68 | 85 |
86 new_user.api_key = generate_api_key(form_data['username']) | |
69 self.sa.add(new_user) | 87 self.sa.add(new_user) |
70 self.sa.commit() | 88 self.sa.commit() |
71 except: | 89 except: |
72 log.error(traceback.format_exc()) | 90 log.error(traceback.format_exc()) |
73 self.sa.rollback() | 91 self.sa.rollback() |
74 raise | 92 raise |
75 | 93 |
76 def create_ldap(self, username, password): | 94 def create_ldap(self, username, password, user_dn, attrs): |
77 """ | 95 """ |
78 Checks if user is in database, if not creates this user marked | 96 Checks if user is in database, if not creates this user marked |
79 as ldap user | 97 as ldap user |
80 :param username: | 98 :param username: |
81 :param password: | 99 :param password: |
100 :param user_dn: | |
101 :param attrs: | |
82 """ | 102 """ |
83 from rhodecode.lib.auth import get_crypt_password | 103 from rhodecode.lib.auth import get_crypt_password |
84 log.debug('Checking for such ldap account in RhodeCode database') | 104 log.debug('Checking for such ldap account in RhodeCode database') |
85 if self.get_by_username(username, case_insensitive=True) is None: | 105 if self.get_by_username(username, case_insensitive=True) is None: |
86 try: | 106 try: |
87 new_user = User() | 107 new_user = User() |
88 new_user.username = username.lower()#add ldap account always lowercase | 108 # add ldap account always lowercase |
109 new_user.username = username.lower() | |
89 new_user.password = get_crypt_password(password) | 110 new_user.password = get_crypt_password(password) |
90 new_user.email = '%s@ldap.server' % username | 111 new_user.api_key = generate_api_key(username) |
112 new_user.email = attrs['email'] | |
91 new_user.active = True | 113 new_user.active = True |
92 new_user.is_ldap = True | 114 new_user.ldap_dn = user_dn |
93 new_user.name = '%s@ldap' % username | 115 new_user.name = attrs['name'] |
94 new_user.lastname = '' | 116 new_user.lastname = attrs['lastname'] |
95 | |
96 | 117 |
97 self.sa.add(new_user) | 118 self.sa.add(new_user) |
98 self.sa.commit() | 119 self.sa.commit() |
99 return True | 120 return True |
100 except (DatabaseError,): | 121 except (DatabaseError,): |
128 self.sa.rollback() | 149 self.sa.rollback() |
129 raise | 150 raise |
130 | 151 |
131 def update(self, user_id, form_data): | 152 def update(self, user_id, form_data): |
132 try: | 153 try: |
133 new_user = self.get(user_id, cache=False) | 154 user = self.get(user_id, cache=False) |
134 if new_user.username == 'default': | 155 if user.username == 'default': |
135 raise DefaultUserException( | 156 raise DefaultUserException( |
136 _("You can't Edit this user since it's" | 157 _("You can't Edit this user since it's" |
137 " crucial for entire application")) | 158 " crucial for entire application")) |
138 | 159 |
139 for k, v in form_data.items(): | 160 for k, v in form_data.items(): |
140 if k == 'new_password' and v != '': | 161 if k == 'new_password' and v != '': |
141 new_user.password = v | 162 user.password = v |
163 user.api_key = generate_api_key(user.username) | |
142 else: | 164 else: |
143 setattr(new_user, k, v) | 165 setattr(user, k, v) |
144 | 166 |
145 self.sa.add(new_user) | 167 self.sa.add(user) |
146 self.sa.commit() | 168 self.sa.commit() |
147 except: | 169 except: |
148 log.error(traceback.format_exc()) | 170 log.error(traceback.format_exc()) |
149 self.sa.rollback() | 171 self.sa.rollback() |
150 raise | 172 raise |
151 | 173 |
152 def update_my_account(self, user_id, form_data): | 174 def update_my_account(self, user_id, form_data): |
153 try: | 175 try: |
154 new_user = self.get(user_id, cache=False) | 176 user = self.get(user_id, cache=False) |
155 if new_user.username == 'default': | 177 if user.username == 'default': |
156 raise DefaultUserException( | 178 raise DefaultUserException( |
157 _("You can't Edit this user since it's" | 179 _("You can't Edit this user since it's" |
158 " crucial for entire application")) | 180 " crucial for entire application")) |
159 for k, v in form_data.items(): | 181 for k, v in form_data.items(): |
160 if k == 'new_password' and v != '': | 182 if k == 'new_password' and v != '': |
161 new_user.password = v | 183 user.password = v |
184 user.api_key = generate_api_key(user.username) | |
162 else: | 185 else: |
163 if k not in ['admin', 'active']: | 186 if k not in ['admin', 'active']: |
164 setattr(new_user, k, v) | 187 setattr(user, k, v) |
165 | 188 |
166 self.sa.add(new_user) | 189 self.sa.add(user) |
167 self.sa.commit() | 190 self.sa.commit() |
168 except: | 191 except: |
169 log.error(traceback.format_exc()) | 192 log.error(traceback.format_exc()) |
170 self.sa.rollback() | 193 self.sa.rollback() |
171 raise | 194 raise |
188 except: | 211 except: |
189 log.error(traceback.format_exc()) | 212 log.error(traceback.format_exc()) |
190 self.sa.rollback() | 213 self.sa.rollback() |
191 raise | 214 raise |
192 | 215 |
216 def reset_password_link(self, data): | |
217 from rhodecode.lib.celerylib import tasks, run_task | |
218 run_task(tasks.send_password_link, data['email']) | |
219 | |
193 def reset_password(self, data): | 220 def reset_password(self, data): |
194 from rhodecode.lib.celerylib import tasks, run_task | 221 from rhodecode.lib.celerylib import tasks, run_task |
195 run_task(tasks.reset_user_password, data['email']) | 222 run_task(tasks.reset_user_password, data['email']) |
196 | 223 |
197 | 224 def fill_data(self, auth_user, user_id=None, api_key=None): |
198 def fill_data(self, user): | 225 """ |
199 """ | 226 Fetches auth_user by user_id,or api_key if present. |
200 Fills user data with those from database and log out user if not | 227 Fills auth_user attributes with those taken from database. |
228 Additionally set's is_authenitated if lookup fails | |
201 present in database | 229 present in database |
202 :param user: | 230 |
203 """ | 231 :param auth_user: instance of user to set attributes |
204 | 232 :param user_id: user id to fetch by |
205 if not hasattr(user, 'user_id') or user.user_id is None: | 233 :param api_key: api key to fetch by |
206 raise Exception('passed in user has to have the user_id attribute') | 234 """ |
207 | 235 if user_id is None and api_key is None: |
208 | 236 raise Exception('You need to pass user_id or api_key') |
209 log.debug('filling auth user data') | 237 |
210 try: | 238 try: |
211 dbuser = self.get(user.user_id) | 239 if api_key: |
212 user.username = dbuser.username | 240 dbuser = self.get_by_api_key(api_key) |
213 user.is_admin = dbuser.admin | 241 else: |
214 user.name = dbuser.name | 242 dbuser = self.get(user_id) |
215 user.lastname = dbuser.lastname | 243 |
216 user.email = dbuser.email | 244 if dbuser is not None: |
217 except: | 245 log.debug('filling %s data', dbuser) |
218 log.error(traceback.format_exc()) | 246 for k, v in dbuser.get_dict().items(): |
219 user.is_authenticated = False | 247 setattr(auth_user, k, v) |
248 | |
249 except: | |
250 log.error(traceback.format_exc()) | |
251 auth_user.is_authenticated = False | |
252 | |
253 return auth_user | |
254 | |
255 def fill_perms(self, user): | |
256 """ | |
257 Fills user permission attribute with permissions taken from database | |
258 works for permissions given for repositories, and for permissions that | |
259 are granted to groups | |
260 | |
261 :param user: user instance to fill his perms | |
262 """ | |
263 | |
264 user.permissions['repositories'] = {} | |
265 user.permissions['global'] = set() | |
266 | |
267 #====================================================================== | |
268 # fetch default permissions | |
269 #====================================================================== | |
270 default_user = self.get_by_username('default', cache=True) | |
271 | |
272 default_perms = self.sa.query(RepoToPerm, Repository, Permission)\ | |
273 .join((Repository, RepoToPerm.repository_id == | |
274 Repository.repo_id))\ | |
275 .join((Permission, RepoToPerm.permission_id == | |
276 Permission.permission_id))\ | |
277 .filter(RepoToPerm.user == default_user).all() | |
278 | |
279 if user.is_admin: | |
280 #================================================================== | |
281 # #admin have all default rights set to admin | |
282 #================================================================== | |
283 user.permissions['global'].add('hg.admin') | |
284 | |
285 for perm in default_perms: | |
286 p = 'repository.admin' | |
287 user.permissions['repositories'][perm.RepoToPerm. | |
288 repository.repo_name] = p | |
289 | |
290 else: | |
291 #================================================================== | |
292 # set default permissions | |
293 #================================================================== | |
294 uid = user.user_id | |
295 | |
296 #default global | |
297 default_global_perms = self.sa.query(UserToPerm)\ | |
298 .filter(UserToPerm.user == default_user) | |
299 | |
300 for perm in default_global_perms: | |
301 user.permissions['global'].add(perm.permission.permission_name) | |
302 | |
303 #default for repositories | |
304 for perm in default_perms: | |
305 if perm.Repository.private and not (perm.Repository.user_id == | |
306 uid): | |
307 #diself.sable defaults for private repos, | |
308 p = 'repository.none' | |
309 elif perm.Repository.user_id == uid: | |
310 #set admin if owner | |
311 p = 'repository.admin' | |
312 else: | |
313 p = perm.Permission.permission_name | |
314 | |
315 user.permissions['repositories'][perm.RepoToPerm. | |
316 repository.repo_name] = p | |
317 | |
318 #================================================================== | |
319 # overwrite default with user permissions if any | |
320 #================================================================== | |
321 | |
322 #user global | |
323 user_perms = self.sa.query(UserToPerm)\ | |
324 .options(joinedload(UserToPerm.permission))\ | |
325 .filter(UserToPerm.user_id == uid).all() | |
326 | |
327 for perm in user_perms: | |
328 user.permissions['global'].add(perm.permission. | |
329 permission_name) | |
330 | |
331 #user repositories | |
332 user_repo_perms = self.sa.query(RepoToPerm, Permission, | |
333 Repository)\ | |
334 .join((Repository, RepoToPerm.repository_id == | |
335 Repository.repo_id))\ | |
336 .join((Permission, RepoToPerm.permission_id == | |
337 Permission.permission_id))\ | |
338 .filter(RepoToPerm.user_id == uid).all() | |
339 | |
340 for perm in user_repo_perms: | |
341 # set admin if owner | |
342 if perm.Repository.user_id == uid: | |
343 p = 'repository.admin' | |
344 else: | |
345 p = perm.Permission.permission_name | |
346 user.permissions['repositories'][perm.RepoToPerm. | |
347 repository.repo_name] = p | |
348 | |
349 #================================================================== | |
350 # check if user is part of groups for this repository and fill in | |
351 # (or replace with higher) permissions | |
352 #================================================================== | |
353 | |
354 #users group global | |
355 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\ | |
356 .options(joinedload(UsersGroupToPerm.permission))\ | |
357 .join((UsersGroupMember, UsersGroupToPerm.users_group_id == | |
358 UsersGroupMember.users_group_id))\ | |
359 .filter(UsersGroupMember.user_id == uid).all() | |
360 | |
361 for perm in user_perms_from_users_groups: | |
362 user.permissions['global'].add(perm.permission.permission_name) | |
363 | |
364 #users group repositories | |
365 user_repo_perms_from_users_groups = self.sa.query( | |
366 UsersGroupRepoToPerm, | |
367 Permission, Repository,)\ | |
368 .join((Repository, UsersGroupRepoToPerm.repository_id == | |
369 Repository.repo_id))\ | |
370 .join((Permission, UsersGroupRepoToPerm.permission_id == | |
371 Permission.permission_id))\ | |
372 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == | |
373 UsersGroupMember.users_group_id))\ | |
374 .filter(UsersGroupMember.user_id == uid).all() | |
375 | |
376 for perm in user_repo_perms_from_users_groups: | |
377 p = perm.Permission.permission_name | |
378 cur_perm = user.permissions['repositories'][perm. | |
379 UsersGroupRepoToPerm. | |
380 repository.repo_name] | |
381 #overwrite permission only if it's greater than permission | |
382 # given from other sources | |
383 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]: | |
384 user.permissions['repositories'][perm.UsersGroupRepoToPerm. | |
385 repository.repo_name] = p | |
220 | 386 |
221 return user | 387 return user |