Mercurial > kallithea
comparison rhodecode/model/user.py @ 4116:ffd45b185016 rhodecode-2.2.5-gpl
Imported some of the GPLv3'd changes from RhodeCode v2.2.5.
This imports changes between changesets 21af6c4eab3d and 6177597791c2 in
RhodeCode's original repository, including only changes to Python files and HTML.
RhodeCode clearly licensed its changes to these files under GPLv3
in their /LICENSE file, which states the following:
The Python code and integrated HTML are licensed under the GPLv3 license.
(See:
https://code.rhodecode.com/rhodecode/files/v2.2.5/LICENSE
or
http://web.archive.org/web/20140512193334/https://code.rhodecode.com/rhodecode/files/f3b123159901f15426d18e3dc395e8369f70ebe0/LICENSE
for an online copy of that LICENSE file)
Conservancy reviewed these changes and confirmed that they can be licensed as
a whole to the Kallithea project under GPLv3-only.
While some of the contents committed herein are clearly licensed
GPLv3-or-later, on the whole we must assume the are GPLv3-only, since the
statement above from RhodeCode indicates that they intend GPLv3-only as their
license, per GPLv3ยง14 and other relevant sections of GPLv3.
author | Bradley M. Kuhn <bkuhn@sfconservancy.org> |
---|---|
date | Wed, 02 Jul 2014 19:03:13 -0400 |
parents | 92da990f9eaf |
children | 7e5f8c12a3fc |
comparison
equal
deleted
inserted
replaced
4115:8b7294a804a0 | 4116:ffd45b185016 |
---|---|
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """ | |
3 rhodecode.model.user | |
4 ~~~~~~~~~~~~~~~~~~~~ | |
5 | |
6 users model for RhodeCode | |
7 | |
8 :created_on: Apr 9, 2010 | |
9 :author: marcink | |
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> | |
11 :license: GPLv3, see COPYING for more details. | |
12 """ | |
13 # This program is free software: you can redistribute it and/or modify | 2 # 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 | 3 # 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 | 4 # the Free Software Foundation, either version 3 of the License, or |
16 # (at your option) any later version. | 5 # (at your option) any later version. |
17 # | 6 # |
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 # GNU General Public License for more details. | 10 # GNU General Public License for more details. |
22 # | 11 # |
23 # You should have received a copy of the GNU General Public License | 12 # You should have received a copy of the GNU General Public License |
24 # along with this program. If not, see <http://www.gnu.org/licenses/>. | 13 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
14 """ | |
15 rhodecode.model.user | |
16 ~~~~~~~~~~~~~~~~~~~~ | |
17 | |
18 users model for RhodeCode | |
19 | |
20 :created_on: Apr 9, 2010 | |
21 :author: marcink | |
22 :copyright: (c) 2013 RhodeCode GmbH. | |
23 :license: GPLv3, see LICENSE for more details. | |
24 """ | |
25 | |
25 | 26 |
26 import logging | 27 import logging |
27 import traceback | 28 import traceback |
28 import itertools | |
29 import collections | |
30 from pylons import url | 29 from pylons import url |
31 from pylons.i18n.translation import _ | 30 from pylons.i18n.translation import _ |
32 | 31 |
33 from sqlalchemy.exc import DatabaseError | 32 from sqlalchemy.exc import DatabaseError |
34 from sqlalchemy.orm import joinedload | 33 |
35 | 34 |
36 from rhodecode.lib.utils2 import safe_unicode, generate_api_key, get_current_rhodecode_user | 35 from rhodecode.lib.utils2 import safe_unicode, generate_api_key, get_current_rhodecode_user |
37 from rhodecode.lib.caching_query import FromCache | 36 from rhodecode.lib.caching_query import FromCache |
38 from rhodecode.model import BaseModel | 37 from rhodecode.model import BaseModel |
39 from rhodecode.model.db import User, Repository, Permission, \ | 38 from rhodecode.model.db import User, UserToPerm, Notification, \ |
40 UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \ | 39 UserEmailMap, UserIpMap |
41 Notification, RepoGroup, UserGroupRepoGroupToPerm, \ | |
42 UserEmailMap, UserIpMap, UserGroupUserGroupToPerm, UserGroup | |
43 from rhodecode.lib.exceptions import DefaultUserException, \ | 40 from rhodecode.lib.exceptions import DefaultUserException, \ |
44 UserOwnsReposException | 41 UserOwnsReposException |
45 from rhodecode.model.meta import Session | 42 from rhodecode.model.meta import Session |
46 | 43 |
47 | 44 |
48 log = logging.getLogger(__name__) | 45 log = logging.getLogger(__name__) |
49 | |
50 PERM_WEIGHTS = Permission.PERM_WEIGHTS | |
51 | 46 |
52 | 47 |
53 class UserModel(BaseModel): | 48 class UserModel(BaseModel): |
54 cls = User | 49 cls = User |
55 | 50 |
66 def get_by_username(self, username, cache=False, case_insensitive=False): | 61 def get_by_username(self, username, cache=False, case_insensitive=False): |
67 | 62 |
68 if case_insensitive: | 63 if case_insensitive: |
69 user = self.sa.query(User).filter(User.username.ilike(username)) | 64 user = self.sa.query(User).filter(User.username.ilike(username)) |
70 else: | 65 else: |
71 user = self.sa.query(User).filter(User.username == username) | 66 user = self.sa.query(User)\ |
67 .filter(User.username == username) | |
72 if cache: | 68 if cache: |
73 user = user.options(FromCache("sql_cache_short", | 69 user = user.options(FromCache("sql_cache_short", |
74 "get_user_%s" % username)) | 70 "get_user_%s" % username)) |
75 return user.scalar() | 71 return user.scalar() |
76 | 72 |
91 'email': _fd['email'], 'firstname': _fd['firstname'], 'lastname': _fd['lastname'], | 87 'email': _fd['email'], 'firstname': _fd['firstname'], 'lastname': _fd['lastname'], |
92 'active': _fd['active'], 'admin': False | 88 'active': _fd['active'], 'admin': False |
93 } | 89 } |
94 # raises UserCreationError if it's not allowed | 90 # raises UserCreationError if it's not allowed |
95 check_allowed_create_user(user_data, cur_user) | 91 check_allowed_create_user(user_data, cur_user) |
96 | |
97 from rhodecode.lib.auth import get_crypt_password | 92 from rhodecode.lib.auth import get_crypt_password |
98 try: | 93 try: |
99 new_user = User() | 94 new_user = User() |
100 for k, v in form_data.items(): | 95 for k, v in form_data.items(): |
101 if k == 'password': | 96 if k == 'password': |
112 except Exception: | 107 except Exception: |
113 log.error(traceback.format_exc()) | 108 log.error(traceback.format_exc()) |
114 raise | 109 raise |
115 | 110 |
116 def create_or_update(self, username, password, email, firstname='', | 111 def create_or_update(self, username, password, email, firstname='', |
117 lastname='', active=True, admin=False, ldap_dn=None, | 112 lastname='', active=True, admin=False, |
118 cur_user=None): | 113 extern_type=None, extern_name=None, cur_user=None): |
119 """ | 114 """ |
120 Creates a new instance if not found, or updates current one | 115 Creates a new instance if not found, or updates current one |
121 | 116 |
122 :param username: | 117 :param username: |
123 :param password: | 118 :param password: |
125 :param active: | 120 :param active: |
126 :param firstname: | 121 :param firstname: |
127 :param lastname: | 122 :param lastname: |
128 :param active: | 123 :param active: |
129 :param admin: | 124 :param admin: |
130 :param ldap_dn: | 125 :param extern_name: |
126 :param extern_type: | |
131 :param cur_user: | 127 :param cur_user: |
132 """ | 128 """ |
133 if not cur_user: | 129 if not cur_user: |
134 cur_user = getattr(get_current_rhodecode_user(), 'username', None) | 130 cur_user = getattr(get_current_rhodecode_user(), 'username', None) |
135 | 131 |
136 from rhodecode.lib.auth import get_crypt_password | 132 from rhodecode.lib.auth import get_crypt_password, check_password |
137 from rhodecode.lib.hooks import log_create_user, check_allowed_create_user | 133 from rhodecode.lib.hooks import log_create_user, check_allowed_create_user |
138 user_data = { | 134 user_data = { |
139 'username': username, 'password': password, | 135 'username': username, 'password': password, |
140 'email': email, 'firstname': firstname, 'lastname': lastname, | 136 'email': email, 'firstname': firstname, 'lastname': lastname, |
141 'active': active, 'admin': admin | 137 'active': active, 'admin': admin |
155 edit = True | 151 edit = True |
156 | 152 |
157 try: | 153 try: |
158 new_user.username = username | 154 new_user.username = username |
159 new_user.admin = admin | 155 new_user.admin = admin |
160 # set password only if creating an user or password is changed | |
161 if not edit or user.password != password: | |
162 new_user.password = get_crypt_password(password) if password else None | |
163 new_user.api_key = generate_api_key(username) | |
164 new_user.email = email | 156 new_user.email = email |
165 new_user.active = active | 157 new_user.active = active |
166 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None | 158 new_user.extern_name = safe_unicode(extern_name) if extern_name else None |
159 new_user.extern_type = safe_unicode(extern_type) if extern_type else None | |
167 new_user.name = firstname | 160 new_user.name = firstname |
168 new_user.lastname = lastname | 161 new_user.lastname = lastname |
162 | |
163 if not edit: | |
164 new_user.api_key = generate_api_key(username) | |
165 | |
166 # set password only if creating an user or password is changed | |
167 password_change = new_user.password and not check_password(password, | |
168 new_user.password) | |
169 if not edit or password_change: | |
170 reason = 'new password' if edit else 'new user' | |
171 log.debug('Updating password reason=>%s' % (reason,)) | |
172 new_user.password = get_crypt_password(password) if password else None | |
173 | |
169 self.sa.add(new_user) | 174 self.sa.add(new_user) |
170 | 175 |
171 if not edit: | 176 if not edit: |
172 log_create_user(new_user.get_dict(), cur_user) | 177 log_create_user(new_user.get_dict(), cur_user) |
173 return new_user | 178 return new_user |
174 except (DatabaseError,): | 179 except (DatabaseError,): |
175 log.error(traceback.format_exc()) | 180 log.error(traceback.format_exc()) |
176 raise | 181 raise |
177 | 182 |
178 def create_for_container_auth(self, username, attrs, cur_user=None): | |
179 """ | |
180 Creates the given user if it's not already in the database | |
181 | |
182 :param username: | |
183 :param attrs: | |
184 :param cur_user: | |
185 """ | |
186 if not cur_user: | |
187 cur_user = getattr(get_current_rhodecode_user(), 'username', None) | |
188 if self.get_by_username(username, case_insensitive=True) is None: | |
189 # autogenerate email for container account without one | |
190 generate_email = lambda usr: '%s@container_auth.account' % usr | |
191 firstname = attrs['name'] | |
192 lastname = attrs['lastname'] | |
193 active = attrs.get('active', True) | |
194 email = attrs['email'] or generate_email(username) | |
195 | |
196 from rhodecode.lib.hooks import log_create_user, check_allowed_create_user | |
197 user_data = { | |
198 'username': username, 'password': None, | |
199 'email': email, 'firstname': firstname, 'lastname': lastname, | |
200 'active': attrs.get('active', True), 'admin': False | |
201 } | |
202 # raises UserCreationError if it's not allowed | |
203 check_allowed_create_user(user_data, cur_user) | |
204 | |
205 try: | |
206 new_user = User() | |
207 new_user.username = username | |
208 new_user.password = None | |
209 new_user.api_key = generate_api_key(username) | |
210 new_user.email = email | |
211 new_user.active = active | |
212 new_user.name = firstname | |
213 new_user.lastname = lastname | |
214 | |
215 self.sa.add(new_user) | |
216 log_create_user(new_user.get_dict(), cur_user) | |
217 return new_user | |
218 except (DatabaseError,): | |
219 log.error(traceback.format_exc()) | |
220 self.sa.rollback() | |
221 raise | |
222 log.debug('User %s already exists. Skipping creation of account' | |
223 ' for container auth.', username) | |
224 return None | |
225 | |
226 def create_ldap(self, username, password, user_dn, attrs, cur_user=None): | |
227 """ | |
228 Checks if user is in database, if not creates this user marked | |
229 as ldap user | |
230 | |
231 :param username: | |
232 :param password: | |
233 :param user_dn: | |
234 :param attrs: | |
235 :param cur_user: | |
236 """ | |
237 if not cur_user: | |
238 cur_user = getattr(get_current_rhodecode_user(), 'username', None) | |
239 from rhodecode.lib.auth import get_crypt_password | |
240 log.debug('Checking for such ldap account in RhodeCode database') | |
241 if self.get_by_username(username, case_insensitive=True) is None: | |
242 # autogenerate email for container account without one | |
243 generate_email = lambda usr: '%s@ldap.account' % usr | |
244 password = get_crypt_password(password) | |
245 firstname = attrs['name'] | |
246 lastname = attrs['lastname'] | |
247 active = attrs.get('active', True) | |
248 email = attrs['email'] or generate_email(username) | |
249 | |
250 from rhodecode.lib.hooks import log_create_user, check_allowed_create_user | |
251 user_data = { | |
252 'username': username, 'password': password, | |
253 'email': email, 'firstname': firstname, 'lastname': lastname, | |
254 'active': attrs.get('active', True), 'admin': False | |
255 } | |
256 # raises UserCreationError if it's not allowed | |
257 check_allowed_create_user(user_data, cur_user) | |
258 | |
259 try: | |
260 new_user = User() | |
261 username = username.lower() | |
262 # add ldap account always lowercase | |
263 new_user.username = username | |
264 new_user.password = password | |
265 new_user.api_key = generate_api_key(username) | |
266 new_user.email = email | |
267 new_user.active = active | |
268 new_user.ldap_dn = safe_unicode(user_dn) | |
269 new_user.name = firstname | |
270 new_user.lastname = lastname | |
271 self.sa.add(new_user) | |
272 | |
273 log_create_user(new_user.get_dict(), cur_user) | |
274 return new_user | |
275 except (DatabaseError,): | |
276 log.error(traceback.format_exc()) | |
277 self.sa.rollback() | |
278 raise | |
279 log.debug('this %s user exists skipping creation of ldap account', | |
280 username) | |
281 return None | |
282 | |
283 def create_registration(self, form_data): | 183 def create_registration(self, form_data): |
284 from rhodecode.model.notification import NotificationModel | 184 from rhodecode.model.notification import NotificationModel |
285 | 185 |
286 try: | 186 try: |
287 form_data['admin'] = False | 187 form_data['admin'] = False |
188 form_data['extern_name'] = 'rhodecode' | |
189 form_data['extern_type'] = 'rhodecode' | |
288 new_user = self.create(form_data) | 190 new_user = self.create(form_data) |
289 | 191 |
290 self.sa.add(new_user) | 192 self.sa.add(new_user) |
291 self.sa.flush() | 193 self.sa.flush() |
292 | 194 |
311 | 213 |
312 def update(self, user_id, form_data, skip_attrs=[]): | 214 def update(self, user_id, form_data, skip_attrs=[]): |
313 from rhodecode.lib.auth import get_crypt_password | 215 from rhodecode.lib.auth import get_crypt_password |
314 try: | 216 try: |
315 user = self.get(user_id, cache=False) | 217 user = self.get(user_id, cache=False) |
316 if user.username == 'default': | 218 if user.username == User.DEFAULT_USER: |
317 raise DefaultUserException( | 219 raise DefaultUserException( |
318 _("You can't Edit this user since it's" | 220 _("You can't Edit this user since it's " |
319 " crucial for entire application")) | 221 "crucial for entire application")) |
320 | 222 |
321 for k, v in form_data.items(): | 223 for k, v in form_data.items(): |
322 if k in skip_attrs: | 224 if k in skip_attrs: |
323 continue | 225 continue |
324 if k == 'new_password' and v: | 226 if k == 'new_password' and v: |
325 user.password = get_crypt_password(v) | 227 user.password = get_crypt_password(v) |
326 user.api_key = generate_api_key(user.username) | |
327 else: | 228 else: |
229 # old legacy thing orm models store firstname as name, | |
230 # need proper refactor to username | |
328 if k == 'firstname': | 231 if k == 'firstname': |
329 k = 'name' | 232 k = 'name' |
330 setattr(user, k, v) | 233 setattr(user, k, v) |
331 self.sa.add(user) | 234 self.sa.add(user) |
332 except Exception: | 235 except Exception: |
335 | 238 |
336 def update_user(self, user, **kwargs): | 239 def update_user(self, user, **kwargs): |
337 from rhodecode.lib.auth import get_crypt_password | 240 from rhodecode.lib.auth import get_crypt_password |
338 try: | 241 try: |
339 user = self._get_user(user) | 242 user = self._get_user(user) |
340 if user.username == 'default': | 243 if user.username == User.DEFAULT_USER: |
341 raise DefaultUserException( | 244 raise DefaultUserException( |
342 _("You can't Edit this user since it's" | 245 _("You can't Edit this user since it's" |
343 " crucial for entire application") | 246 " crucial for entire application") |
344 ) | 247 ) |
345 | 248 |
346 for k, v in kwargs.items(): | 249 for k, v in kwargs.items(): |
347 if k == 'password' and v: | 250 if k == 'password' and v: |
348 v = get_crypt_password(v) | 251 v = get_crypt_password(v) |
349 user.api_key = generate_api_key(user.username) | |
350 | 252 |
351 setattr(user, k, v) | 253 setattr(user, k, v) |
352 self.sa.add(user) | 254 self.sa.add(user) |
353 return user | 255 return user |
354 except Exception: | 256 except Exception: |
359 if not cur_user: | 261 if not cur_user: |
360 cur_user = getattr(get_current_rhodecode_user(), 'username', None) | 262 cur_user = getattr(get_current_rhodecode_user(), 'username', None) |
361 user = self._get_user(user) | 263 user = self._get_user(user) |
362 | 264 |
363 try: | 265 try: |
364 if user.username == 'default': | 266 if user.username == User.DEFAULT_USER: |
365 raise DefaultUserException( | 267 raise DefaultUserException( |
366 _(u"You can't remove this user since it's" | 268 _(u"You can't remove this user since it's" |
367 " crucial for entire application") | 269 " crucial for entire application") |
368 ) | 270 ) |
369 if user.repositories: | 271 if user.repositories: |
416 user = User.get_by_email(user_email) | 318 user = User.get_by_email(user_email) |
417 new_passwd = auth.PasswordGenerator().gen_password(8, | 319 new_passwd = auth.PasswordGenerator().gen_password(8, |
418 auth.PasswordGenerator.ALPHABETS_BIG_SMALL) | 320 auth.PasswordGenerator.ALPHABETS_BIG_SMALL) |
419 if user: | 321 if user: |
420 user.password = auth.get_crypt_password(new_passwd) | 322 user.password = auth.get_crypt_password(new_passwd) |
421 user.api_key = auth.generate_api_key(user.username) | |
422 Session().add(user) | 323 Session().add(user) |
423 Session().commit() | 324 Session().commit() |
424 log.info('change password for %s' % user_email) | 325 log.info('change password for %s' % user_email) |
425 if new_passwd is None: | 326 if new_passwd is None: |
426 raise Exception('unable to generate new password') | 327 raise Exception('unable to generate new password') |
439 # run_task, we're pass rollback state this wouldn't work then | 340 # run_task, we're pass rollback state this wouldn't work then |
440 Session().rollback() | 341 Session().rollback() |
441 | 342 |
442 return True | 343 return True |
443 | 344 |
444 def fill_data(self, auth_user, user_id=None, api_key=None): | 345 def fill_data(self, auth_user, user_id=None, api_key=None, username=None): |
445 """ | 346 """ |
446 Fetches auth_user by user_id,or api_key if present. | 347 Fetches auth_user by user_id,or api_key if present. |
447 Fills auth_user attributes with those taken from database. | 348 Fills auth_user attributes with those taken from database. |
448 Additionally set's is_authenitated if lookup fails | 349 Additionally set's is_authenitated if lookup fails |
449 present in database | 350 present in database |
450 | 351 |
451 :param auth_user: instance of user to set attributes | 352 :param auth_user: instance of user to set attributes |
452 :param user_id: user id to fetch by | 353 :param user_id: user id to fetch by |
453 :param api_key: api key to fetch by | 354 :param api_key: api key to fetch by |
454 """ | 355 :param username: username to fetch by |
455 if user_id is None and api_key is None: | 356 """ |
456 raise Exception('You need to pass user_id or api_key') | 357 if user_id is None and api_key is None and username is None: |
457 | 358 raise Exception('You need to pass user_id, api_key or username') |
458 try: | 359 |
459 if api_key: | 360 try: |
361 dbuser = None | |
362 if user_id: | |
363 dbuser = self.get(user_id) | |
364 elif api_key: | |
460 dbuser = self.get_by_api_key(api_key) | 365 dbuser = self.get_by_api_key(api_key) |
461 else: | 366 elif username: |
462 dbuser = self.get(user_id) | 367 dbuser = self.get_by_username(username) |
463 | 368 |
464 if dbuser is not None and dbuser.active: | 369 if dbuser is not None and dbuser.active: |
465 log.debug('filling %s data' % dbuser) | 370 log.debug('filling %s data' % dbuser) |
466 for k, v in dbuser.get_dict().items(): | 371 for k, v in dbuser.get_dict().iteritems(): |
467 setattr(auth_user, k, v) | 372 if k not in ['api_keys', 'permissions']: |
373 setattr(auth_user, k, v) | |
468 else: | 374 else: |
469 return False | 375 return False |
470 | 376 |
471 except Exception: | 377 except Exception: |
472 log.error(traceback.format_exc()) | 378 log.error(traceback.format_exc()) |
473 auth_user.is_authenticated = False | 379 auth_user.is_authenticated = False |
474 return False | 380 return False |
475 | 381 |
476 return True | 382 return True |
477 | |
478 def fill_perms(self, user, explicit=True, algo='higherwin'): | |
479 """ | |
480 Fills user permission attribute with permissions taken from database | |
481 works for permissions given for repositories, and for permissions that | |
482 are granted to groups | |
483 | |
484 :param user: user instance to fill his perms | |
485 :param explicit: In case there are permissions both for user and a group | |
486 that user is part of, explicit flag will defiine if user will | |
487 explicitly override permissions from group, if it's False it will | |
488 make decision based on the algo | |
489 :param algo: algorithm to decide what permission should be choose if | |
490 it's multiple defined, eg user in two different groups. It also | |
491 decides if explicit flag is turned off how to specify the permission | |
492 for case when user is in a group + have defined separate permission | |
493 """ | |
494 RK = 'repositories' | |
495 GK = 'repositories_groups' | |
496 UK = 'user_groups' | |
497 GLOBAL = 'global' | |
498 user.permissions[RK] = {} | |
499 user.permissions[GK] = {} | |
500 user.permissions[UK] = {} | |
501 user.permissions[GLOBAL] = set() | |
502 | |
503 def _choose_perm(new_perm, cur_perm): | |
504 new_perm_val = PERM_WEIGHTS[new_perm] | |
505 cur_perm_val = PERM_WEIGHTS[cur_perm] | |
506 if algo == 'higherwin': | |
507 if new_perm_val > cur_perm_val: | |
508 return new_perm | |
509 return cur_perm | |
510 elif algo == 'lowerwin': | |
511 if new_perm_val < cur_perm_val: | |
512 return new_perm | |
513 return cur_perm | |
514 | |
515 #====================================================================== | |
516 # fetch default permissions | |
517 #====================================================================== | |
518 default_user = User.get_by_username('default', cache=True) | |
519 default_user_id = default_user.user_id | |
520 | |
521 default_repo_perms = Permission.get_default_perms(default_user_id) | |
522 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id) | |
523 default_user_group_perms = Permission.get_default_user_group_perms(default_user_id) | |
524 | |
525 if user.is_admin: | |
526 #================================================================== | |
527 # admin user have all default rights for repositories | |
528 # and groups set to admin | |
529 #================================================================== | |
530 user.permissions[GLOBAL].add('hg.admin') | |
531 | |
532 # repositories | |
533 for perm in default_repo_perms: | |
534 r_k = perm.UserRepoToPerm.repository.repo_name | |
535 p = 'repository.admin' | |
536 user.permissions[RK][r_k] = p | |
537 | |
538 # repository groups | |
539 for perm in default_repo_groups_perms: | |
540 rg_k = perm.UserRepoGroupToPerm.group.group_name | |
541 p = 'group.admin' | |
542 user.permissions[GK][rg_k] = p | |
543 | |
544 # user groups | |
545 for perm in default_user_group_perms: | |
546 u_k = perm.UserUserGroupToPerm.user_group.users_group_name | |
547 p = 'usergroup.admin' | |
548 user.permissions[UK][u_k] = p | |
549 return user | |
550 | |
551 #================================================================== | |
552 # SET DEFAULTS GLOBAL, REPOS, REPOSITORY GROUPS | |
553 #================================================================== | |
554 uid = user.user_id | |
555 | |
556 # default global permissions taken fron the default user | |
557 default_global_perms = self.sa.query(UserToPerm)\ | |
558 .filter(UserToPerm.user_id == default_user_id) | |
559 | |
560 for perm in default_global_perms: | |
561 user.permissions[GLOBAL].add(perm.permission.permission_name) | |
562 | |
563 # defaults for repositories, taken from default user | |
564 for perm in default_repo_perms: | |
565 r_k = perm.UserRepoToPerm.repository.repo_name | |
566 if perm.Repository.private and not (perm.Repository.user_id == uid): | |
567 # disable defaults for private repos, | |
568 p = 'repository.none' | |
569 elif perm.Repository.user_id == uid: | |
570 # set admin if owner | |
571 p = 'repository.admin' | |
572 else: | |
573 p = perm.Permission.permission_name | |
574 | |
575 user.permissions[RK][r_k] = p | |
576 | |
577 # defaults for repository groups taken from default user permission | |
578 # on given group | |
579 for perm in default_repo_groups_perms: | |
580 rg_k = perm.UserRepoGroupToPerm.group.group_name | |
581 p = perm.Permission.permission_name | |
582 user.permissions[GK][rg_k] = p | |
583 | |
584 # defaults for user groups taken from default user permission | |
585 # on given user group | |
586 for perm in default_user_group_perms: | |
587 u_k = perm.UserUserGroupToPerm.user_group.users_group_name | |
588 p = perm.Permission.permission_name | |
589 user.permissions[UK][u_k] = p | |
590 | |
591 #====================================================================== | |
592 # !! OVERRIDE GLOBALS !! with user permissions if any found | |
593 #====================================================================== | |
594 # those can be configured from groups or users explicitly | |
595 _configurable = set([ | |
596 'hg.fork.none', 'hg.fork.repository', | |
597 'hg.create.none', 'hg.create.repository', | |
598 'hg.usergroup.create.false', 'hg.usergroup.create.true' | |
599 ]) | |
600 | |
601 # USER GROUPS comes first | |
602 # user group global permissions | |
603 user_perms_from_users_groups = self.sa.query(UserGroupToPerm)\ | |
604 .options(joinedload(UserGroupToPerm.permission))\ | |
605 .join((UserGroupMember, UserGroupToPerm.users_group_id == | |
606 UserGroupMember.users_group_id))\ | |
607 .filter(UserGroupMember.user_id == uid)\ | |
608 .order_by(UserGroupToPerm.users_group_id)\ | |
609 .all() | |
610 #need to group here by groups since user can be in more than one group | |
611 _grouped = [[x, list(y)] for x, y in | |
612 itertools.groupby(user_perms_from_users_groups, | |
613 lambda x:x.users_group)] | |
614 for gr, perms in _grouped: | |
615 # since user can be in multiple groups iterate over them and | |
616 # select the lowest permissions first (more explicit) | |
617 ##TODO: do this^^ | |
618 if not gr.inherit_default_permissions: | |
619 # NEED TO IGNORE all configurable permissions and | |
620 # replace them with explicitly set | |
621 user.permissions[GLOBAL] = user.permissions[GLOBAL]\ | |
622 .difference(_configurable) | |
623 for perm in perms: | |
624 user.permissions[GLOBAL].add(perm.permission.permission_name) | |
625 | |
626 # user specific global permissions | |
627 user_perms = self.sa.query(UserToPerm)\ | |
628 .options(joinedload(UserToPerm.permission))\ | |
629 .filter(UserToPerm.user_id == uid).all() | |
630 | |
631 if not user.inherit_default_permissions: | |
632 # NEED TO IGNORE all configurable permissions and | |
633 # replace them with explicitly set | |
634 user.permissions[GLOBAL] = user.permissions[GLOBAL]\ | |
635 .difference(_configurable) | |
636 | |
637 for perm in user_perms: | |
638 user.permissions[GLOBAL].add(perm.permission.permission_name) | |
639 ## END GLOBAL PERMISSIONS | |
640 | |
641 #====================================================================== | |
642 # !! PERMISSIONS FOR REPOSITORIES !! | |
643 #====================================================================== | |
644 #====================================================================== | |
645 # check if user is part of user groups for this repository and | |
646 # fill in his permission from it. _choose_perm decides of which | |
647 # permission should be selected based on selected method | |
648 #====================================================================== | |
649 | |
650 # user group for repositories permissions | |
651 user_repo_perms_from_users_groups = \ | |
652 self.sa.query(UserGroupRepoToPerm, Permission, Repository,)\ | |
653 .join((Repository, UserGroupRepoToPerm.repository_id == | |
654 Repository.repo_id))\ | |
655 .join((Permission, UserGroupRepoToPerm.permission_id == | |
656 Permission.permission_id))\ | |
657 .join((UserGroupMember, UserGroupRepoToPerm.users_group_id == | |
658 UserGroupMember.users_group_id))\ | |
659 .filter(UserGroupMember.user_id == uid)\ | |
660 .all() | |
661 | |
662 multiple_counter = collections.defaultdict(int) | |
663 for perm in user_repo_perms_from_users_groups: | |
664 r_k = perm.UserGroupRepoToPerm.repository.repo_name | |
665 multiple_counter[r_k] += 1 | |
666 p = perm.Permission.permission_name | |
667 cur_perm = user.permissions[RK][r_k] | |
668 | |
669 if perm.Repository.user_id == uid: | |
670 # set admin if owner | |
671 p = 'repository.admin' | |
672 else: | |
673 if multiple_counter[r_k] > 1: | |
674 p = _choose_perm(p, cur_perm) | |
675 user.permissions[RK][r_k] = p | |
676 | |
677 # user explicit permissions for repositories, overrides any specified | |
678 # by the group permission | |
679 user_repo_perms = Permission.get_default_perms(uid) | |
680 for perm in user_repo_perms: | |
681 r_k = perm.UserRepoToPerm.repository.repo_name | |
682 cur_perm = user.permissions[RK][r_k] | |
683 # set admin if owner | |
684 if perm.Repository.user_id == uid: | |
685 p = 'repository.admin' | |
686 else: | |
687 p = perm.Permission.permission_name | |
688 if not explicit: | |
689 p = _choose_perm(p, cur_perm) | |
690 user.permissions[RK][r_k] = p | |
691 | |
692 #====================================================================== | |
693 # !! PERMISSIONS FOR REPOSITORY GROUPS !! | |
694 #====================================================================== | |
695 #====================================================================== | |
696 # check if user is part of user groups for this repository groups and | |
697 # fill in his permission from it. _choose_perm decides of which | |
698 # permission should be selected based on selected method | |
699 #====================================================================== | |
700 # user group for repo groups permissions | |
701 user_repo_group_perms_from_users_groups = \ | |
702 self.sa.query(UserGroupRepoGroupToPerm, Permission, RepoGroup)\ | |
703 .join((RepoGroup, UserGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\ | |
704 .join((Permission, UserGroupRepoGroupToPerm.permission_id | |
705 == Permission.permission_id))\ | |
706 .join((UserGroupMember, UserGroupRepoGroupToPerm.users_group_id | |
707 == UserGroupMember.users_group_id))\ | |
708 .filter(UserGroupMember.user_id == uid)\ | |
709 .all() | |
710 | |
711 multiple_counter = collections.defaultdict(int) | |
712 for perm in user_repo_group_perms_from_users_groups: | |
713 g_k = perm.UserGroupRepoGroupToPerm.group.group_name | |
714 multiple_counter[g_k] += 1 | |
715 p = perm.Permission.permission_name | |
716 cur_perm = user.permissions[GK][g_k] | |
717 if multiple_counter[g_k] > 1: | |
718 p = _choose_perm(p, cur_perm) | |
719 user.permissions[GK][g_k] = p | |
720 | |
721 # user explicit permissions for repository groups | |
722 user_repo_groups_perms = Permission.get_default_group_perms(uid) | |
723 for perm in user_repo_groups_perms: | |
724 rg_k = perm.UserRepoGroupToPerm.group.group_name | |
725 p = perm.Permission.permission_name | |
726 cur_perm = user.permissions[GK][rg_k] | |
727 if not explicit: | |
728 p = _choose_perm(p, cur_perm) | |
729 user.permissions[GK][rg_k] = p | |
730 | |
731 #====================================================================== | |
732 # !! PERMISSIONS FOR USER GROUPS !! | |
733 #====================================================================== | |
734 # user group for user group permissions | |
735 user_group_user_groups_perms = \ | |
736 self.sa.query(UserGroupUserGroupToPerm, Permission, UserGroup)\ | |
737 .join((UserGroup, UserGroupUserGroupToPerm.target_user_group_id | |
738 == UserGroup.users_group_id))\ | |
739 .join((Permission, UserGroupUserGroupToPerm.permission_id | |
740 == Permission.permission_id))\ | |
741 .join((UserGroupMember, UserGroupUserGroupToPerm.user_group_id | |
742 == UserGroupMember.users_group_id))\ | |
743 .filter(UserGroupMember.user_id == uid)\ | |
744 .all() | |
745 | |
746 multiple_counter = collections.defaultdict(int) | |
747 for perm in user_group_user_groups_perms: | |
748 g_k = perm.UserGroupUserGroupToPerm.target_user_group.users_group_name | |
749 multiple_counter[g_k] += 1 | |
750 p = perm.Permission.permission_name | |
751 cur_perm = user.permissions[UK][g_k] | |
752 if multiple_counter[g_k] > 1: | |
753 p = _choose_perm(p, cur_perm) | |
754 user.permissions[UK][g_k] = p | |
755 | |
756 #user explicit permission for user groups | |
757 user_user_groups_perms = Permission.get_default_user_group_perms(uid) | |
758 for perm in user_user_groups_perms: | |
759 u_k = perm.UserUserGroupToPerm.user_group.users_group_name | |
760 p = perm.Permission.permission_name | |
761 cur_perm = user.permissions[UK][u_k] | |
762 if not explicit: | |
763 p = _choose_perm(p, cur_perm) | |
764 user.permissions[UK][u_k] = p | |
765 | |
766 return user | |
767 | 383 |
768 def has_perm(self, user, perm): | 384 def has_perm(self, user, perm): |
769 perm = self._get_perm(perm) | 385 perm = self._get_perm(perm) |
770 user = self._get_user(user) | 386 user = self._get_user(user) |
771 | 387 |
790 return | 406 return |
791 new = UserToPerm() | 407 new = UserToPerm() |
792 new.user = user | 408 new.user = user |
793 new.permission = perm | 409 new.permission = perm |
794 self.sa.add(new) | 410 self.sa.add(new) |
411 return new | |
795 | 412 |
796 def revoke_perm(self, user, perm): | 413 def revoke_perm(self, user, perm): |
797 """ | 414 """ |
798 Revoke users global permissions | 415 Revoke users global permissions |
799 | 416 |