##// END OF EJS Templates
managing users groups enforce permissions checks....
marcink -
r3789:32f66c83 beta
parent child Browse files
Show More
@@ -1,737 +1,746 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.repo
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Repository model for rhodecode
7 7
8 8 :created_on: Jun 5, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25 from __future__ import with_statement
26 26 import os
27 27 import shutil
28 28 import logging
29 29 import traceback
30 30 from datetime import datetime
31 31
32 32 from rhodecode.lib.vcs.backends import get_backend
33 33 from rhodecode.lib.compat import json
34 34 from rhodecode.lib.utils2 import LazyProperty, safe_str, safe_unicode,\
35 35 remove_prefix, obfuscate_url_pw
36 36 from rhodecode.lib.caching_query import FromCache
37 37 from rhodecode.lib.hooks import log_create_repository, log_delete_repository
38 38
39 39 from rhodecode.model import BaseModel
40 40 from rhodecode.model.db import Repository, UserRepoToPerm, User, Permission, \
41 41 Statistics, UserGroup, UserGroupRepoToPerm, RhodeCodeUi, RepoGroup,\
42 42 RhodeCodeSetting, RepositoryField
43 43 from rhodecode.lib import helpers as h
44 from rhodecode.lib.auth import HasRepoPermissionAny
44 from rhodecode.lib.auth import HasRepoPermissionAny, HasUserGroupPermissionAny
45 45 from rhodecode.lib.exceptions import AttachedForksError
46 from rhodecode.model.scm import UserGroupList
46 47
47 48 log = logging.getLogger(__name__)
48 49
49 50
50 51 class RepoModel(BaseModel):
51 52
52 53 cls = Repository
53 54 URL_SEPARATOR = Repository.url_sep()
54 55
55 56 def _get_user_group(self, users_group):
56 57 return self._get_instance(UserGroup, users_group,
57 58 callback=UserGroup.get_by_group_name)
58 59
59 60 def _get_repo_group(self, repos_group):
60 61 return self._get_instance(RepoGroup, repos_group,
61 62 callback=RepoGroup.get_by_group_name)
62 63
63 64 def _create_default_perms(self, repository, private):
64 65 # create default permission
65 66 default = 'repository.read'
66 67 def_user = User.get_default_user()
67 68 for p in def_user.user_perms:
68 69 if p.permission.permission_name.startswith('repository.'):
69 70 default = p.permission.permission_name
70 71 break
71 72
72 73 default_perm = 'repository.none' if private else default
73 74
74 75 repo_to_perm = UserRepoToPerm()
75 76 repo_to_perm.permission = Permission.get_by_key(default_perm)
76 77
77 78 repo_to_perm.repository = repository
78 79 repo_to_perm.user_id = def_user.user_id
79 80
80 81 return repo_to_perm
81 82
82 83 @LazyProperty
83 84 def repos_path(self):
84 85 """
85 86 Get's the repositories root path from database
86 87 """
87 88
88 89 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
89 90 return q.ui_value
90 91
91 92 def get(self, repo_id, cache=False):
92 93 repo = self.sa.query(Repository)\
93 94 .filter(Repository.repo_id == repo_id)
94 95
95 96 if cache:
96 97 repo = repo.options(FromCache("sql_cache_short",
97 98 "get_repo_%s" % repo_id))
98 99 return repo.scalar()
99 100
100 101 def get_repo(self, repository):
101 102 return self._get_repo(repository)
102 103
103 104 def get_by_repo_name(self, repo_name, cache=False):
104 105 repo = self.sa.query(Repository)\
105 106 .filter(Repository.repo_name == repo_name)
106 107
107 108 if cache:
108 109 repo = repo.options(FromCache("sql_cache_short",
109 110 "get_repo_%s" % repo_name))
110 111 return repo.scalar()
111 112
112 113 def get_all_user_repos(self, user):
113 114 """
114 115 Get's all repositories that user have at least read access
115 116
116 117 :param user:
117 118 :type user:
118 119 """
119 120 from rhodecode.lib.auth import AuthUser
120 121 user = self._get_user(user)
121 122 repos = AuthUser(user_id=user.user_id).permissions['repositories']
122 123 access_check = lambda r: r[1] in ['repository.read',
123 124 'repository.write',
124 125 'repository.admin']
125 126 repos = [x[0] for x in filter(access_check, repos.items())]
126 127 return Repository.query().filter(Repository.repo_name.in_(repos))
127 128
128 129 def get_users_js(self):
129 130 users = self.sa.query(User).filter(User.active == True).all()
130 131 return json.dumps([
131 132 {
132 133 'id': u.user_id,
133 134 'fname': u.name,
134 135 'lname': u.lastname,
135 136 'nname': u.username,
136 137 'gravatar_lnk': h.gravatar_url(u.email, 14)
137 138 } for u in users]
138 139 )
139 140
140 141 def get_users_groups_js(self):
141 142 users_groups = self.sa.query(UserGroup)\
142 143 .filter(UserGroup.users_group_active == True).all()
143
144 users_groups = UserGroupList(users_groups, perm_set=['usergroup.read',
145 'usergroup.write',
146 'usergroup.admin'])
144 147 return json.dumps([
145 148 {
146 149 'id': gr.users_group_id,
147 150 'grname': gr.users_group_name,
148 151 'grmembers': len(gr.members),
149 152 } for gr in users_groups]
150 153 )
151 154
152 155 @classmethod
153 156 def _render_datatable(cls, tmpl, *args, **kwargs):
154 157 import rhodecode
155 158 from pylons import tmpl_context as c
156 159 from pylons.i18n.translation import _
157 160
158 161 _tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
159 162 template = _tmpl_lookup.get_template('data_table/_dt_elements.html')
160 163
161 164 tmpl = template.get_def(tmpl)
162 165 kwargs.update(dict(_=_, h=h, c=c))
163 166 return tmpl.render(*args, **kwargs)
164 167
165 168 @classmethod
166 169 def update_repoinfo(cls, repositories=None):
167 170 if not repositories:
168 171 repositories = Repository.getAll()
169 172 for repo in repositories:
170 173 repo.update_changeset_cache()
171 174
172 175 def get_repos_as_dict(self, repos_list=None, admin=False, perm_check=True,
173 176 super_user_actions=False):
174 177 _render = self._render_datatable
175 178
176 179 def quick_menu(repo_name):
177 180 return _render('quick_menu', repo_name)
178 181
179 182 def repo_lnk(name, rtype, private, fork_of):
180 183 return _render('repo_name', name, rtype, private, fork_of,
181 184 short_name=not admin, admin=False)
182 185
183 186 def last_change(last_change):
184 187 return _render("last_change", last_change)
185 188
186 189 def rss_lnk(repo_name):
187 190 return _render("rss", repo_name)
188 191
189 192 def atom_lnk(repo_name):
190 193 return _render("atom", repo_name)
191 194
192 195 def last_rev(repo_name, cs_cache):
193 196 return _render('revision', repo_name, cs_cache.get('revision'),
194 197 cs_cache.get('raw_id'), cs_cache.get('author'),
195 198 cs_cache.get('message'))
196 199
197 200 def desc(desc):
198 201 from pylons import tmpl_context as c
199 202 if c.visual.stylify_metatags:
200 203 return h.urlify_text(h.desc_stylize(h.truncate(desc, 60)))
201 204 else:
202 205 return h.urlify_text(h.truncate(desc, 60))
203 206
204 207 def repo_actions(repo_name):
205 208 return _render('repo_actions', repo_name, super_user_actions)
206 209
207 210 def owner_actions(user_id, username):
208 211 return _render('user_name', user_id, username)
209 212
210 213 repos_data = []
211 214 for repo in repos_list:
212 215 if perm_check:
213 216 # check permission at this level
214 217 if not HasRepoPermissionAny(
215 218 'repository.read', 'repository.write', 'repository.admin'
216 219 )(repo.repo_name, 'get_repos_as_dict check'):
217 220 continue
218 221 cs_cache = repo.changeset_cache
219 222 row = {
220 223 "menu": quick_menu(repo.repo_name),
221 224 "raw_name": repo.repo_name.lower(),
222 225 "name": repo_lnk(repo.repo_name, repo.repo_type,
223 226 repo.private, repo.fork),
224 227 "last_change": last_change(repo.last_db_change),
225 228 "last_changeset": last_rev(repo.repo_name, cs_cache),
226 229 "raw_tip": cs_cache.get('revision'),
227 230 "desc": desc(repo.description),
228 231 "owner": h.person(repo.user.username),
229 232 "rss": rss_lnk(repo.repo_name),
230 233 "atom": atom_lnk(repo.repo_name),
231 234
232 235 }
233 236 if admin:
234 237 row.update({
235 238 "action": repo_actions(repo.repo_name),
236 239 "owner": owner_actions(repo.user.user_id,
237 240 h.person(repo.user.username))
238 241 })
239 242 repos_data.append(row)
240 243
241 244 return {
242 245 "totalRecords": len(repos_list),
243 246 "startIndex": 0,
244 247 "sort": "name",
245 248 "dir": "asc",
246 249 "records": repos_data
247 250 }
248 251
249 252 def _get_defaults(self, repo_name):
250 253 """
251 254 Get's information about repository, and returns a dict for
252 255 usage in forms
253 256
254 257 :param repo_name:
255 258 """
256 259
257 260 repo_info = Repository.get_by_repo_name(repo_name)
258 261
259 262 if repo_info is None:
260 263 return None
261 264
262 265 defaults = repo_info.get_dict()
263 266 group, repo_name, repo_name_full = repo_info.groups_and_repo
264 267 defaults['repo_name'] = repo_name
265 268 defaults['repo_group'] = getattr(group[-1] if group else None,
266 269 'group_id', None)
267 270
268 271 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
269 272 (1, 'repo_description'), (1, 'repo_enable_locking'),
270 273 (1, 'repo_landing_rev'), (0, 'clone_uri'),
271 274 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
272 275 attr = k
273 276 if strip:
274 277 attr = remove_prefix(k, 'repo_')
275 278
276 279 defaults[k] = defaults[attr]
277 280
278 281 # fill owner
279 282 if repo_info.user:
280 283 defaults.update({'user': repo_info.user.username})
281 284 else:
282 285 replacement_user = User.query().filter(User.admin ==
283 286 True).first().username
284 287 defaults.update({'user': replacement_user})
285 288
286 289 # fill repository users
287 290 for p in repo_info.repo_to_perm:
288 291 defaults.update({'u_perm_%s' % p.user.username:
289 292 p.permission.permission_name})
290 293
291 294 # fill repository groups
292 295 for p in repo_info.users_group_to_perm:
293 296 defaults.update({'g_perm_%s' % p.users_group.users_group_name:
294 297 p.permission.permission_name})
295 298
296 299 return defaults
297 300
298 301 def update(self, org_repo_name, **kwargs):
299 302 try:
300 303 cur_repo = self.get_by_repo_name(org_repo_name, cache=False)
301 304
302 305 if 'user' in kwargs:
303 306 cur_repo.user = User.get_by_username(kwargs['user'])
304 307
305 308 if 'repo_group' in kwargs:
306 309 cur_repo.group = RepoGroup.get(kwargs['repo_group'])
307 310
308 311 for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'),
309 312 (1, 'repo_description'), (1, 'repo_enable_locking'),
310 313 (1, 'repo_landing_rev'), (0, 'clone_uri'),
311 314 (1, 'repo_private'), (1, 'repo_enable_statistics')]:
312 315 if k in kwargs:
313 316 val = kwargs[k]
314 317 if strip:
315 318 k = remove_prefix(k, 'repo_')
316 319 setattr(cur_repo, k, val)
317 320
318 321 new_name = cur_repo.get_new_name(kwargs['repo_name'])
319 322 cur_repo.repo_name = new_name
320 323 #if private flag is set, reset default permission to NONE
321 324
322 325 if kwargs.get('repo_private'):
323 326 EMPTY_PERM = 'repository.none'
324 327 RepoModel().grant_user_permission(
325 328 repo=cur_repo, user='default', perm=EMPTY_PERM
326 329 )
327 330 #handle extra fields
328 331 for field in filter(lambda k: k.startswith(RepositoryField.PREFIX), kwargs):
329 332 k = RepositoryField.un_prefix_key(field)
330 333 ex_field = RepositoryField.get_by_key_name(key=k, repo=cur_repo)
331 334 if ex_field:
332 335 ex_field.field_value = kwargs[field]
333 336 self.sa.add(ex_field)
334 337 self.sa.add(cur_repo)
335 338
336 339 if org_repo_name != new_name:
337 340 # rename repository
338 341 self.__rename_repo(old=org_repo_name, new=new_name)
339 342
340 343 return cur_repo
341 344 except Exception:
342 345 log.error(traceback.format_exc())
343 346 raise
344 347
345 348 def create_repo(self, repo_name, repo_type, description, owner,
346 349 private=False, clone_uri=None, repos_group=None,
347 350 landing_rev='tip', just_db=False, fork_of=None,
348 351 copy_fork_permissions=False, enable_statistics=False,
349 352 enable_locking=False, enable_downloads=False):
350 353 """
351 354 Create repository
352 355
353 356 """
354 357 from rhodecode.model.scm import ScmModel
355 358
356 359 owner = self._get_user(owner)
357 360 fork_of = self._get_repo(fork_of)
358 361 repos_group = self._get_repo_group(repos_group)
359 362 try:
360 363
361 364 # repo name is just a name of repository
362 365 # while repo_name_full is a full qualified name that is combined
363 366 # with name and path of group
364 367 repo_name_full = repo_name
365 368 repo_name = repo_name.split(self.URL_SEPARATOR)[-1]
366 369
367 370 new_repo = Repository()
368 371 new_repo.enable_statistics = False
369 372 new_repo.repo_name = repo_name_full
370 373 new_repo.repo_type = repo_type
371 374 new_repo.user = owner
372 375 new_repo.group = repos_group
373 376 new_repo.description = description or repo_name
374 377 new_repo.private = private
375 378 new_repo.clone_uri = clone_uri
376 379 new_repo.landing_rev = landing_rev
377 380
378 381 new_repo.enable_statistics = enable_statistics
379 382 new_repo.enable_locking = enable_locking
380 383 new_repo.enable_downloads = enable_downloads
381 384
382 385 if repos_group:
383 386 new_repo.enable_locking = repos_group.enable_locking
384 387
385 388 if fork_of:
386 389 parent_repo = fork_of
387 390 new_repo.fork = parent_repo
388 391
389 392 self.sa.add(new_repo)
390 393
391 394 if fork_of:
392 395 if copy_fork_permissions:
393 396 repo = fork_of
394 397 user_perms = UserRepoToPerm.query()\
395 398 .filter(UserRepoToPerm.repository == repo).all()
396 399 group_perms = UserGroupRepoToPerm.query()\
397 400 .filter(UserGroupRepoToPerm.repository == repo).all()
398 401
399 402 for perm in user_perms:
400 403 UserRepoToPerm.create(perm.user, new_repo,
401 404 perm.permission)
402 405
403 406 for perm in group_perms:
404 407 UserGroupRepoToPerm.create(perm.users_group, new_repo,
405 408 perm.permission)
406 409 else:
407 410 perm_obj = self._create_default_perms(new_repo, private)
408 411 self.sa.add(perm_obj)
409 412 else:
410 413 perm_obj = self._create_default_perms(new_repo, private)
411 414 self.sa.add(perm_obj)
412 415
413 416 if not just_db:
414 417 self.__create_repo(repo_name, repo_type,
415 418 repos_group,
416 419 clone_uri)
417 420 log_create_repository(new_repo.get_dict(),
418 421 created_by=owner.username)
419 422
420 423 # now automatically start following this repository as owner
421 424 ScmModel(self.sa).toggle_following_repo(new_repo.repo_id,
422 425 owner.user_id)
423 426 return new_repo
424 427 except Exception:
425 428 log.error(traceback.format_exc())
426 429 raise
427 430
428 431 def create(self, form_data, cur_user, just_db=False, fork=None):
429 432 """
430 433 Backward compatibility function, just a wrapper on top of create_repo
431 434
432 435 :param form_data:
433 436 :param cur_user:
434 437 :param just_db:
435 438 :param fork:
436 439 """
437 440 owner = cur_user
438 441 repo_name = form_data['repo_name_full']
439 442 repo_type = form_data['repo_type']
440 443 description = form_data['repo_description']
441 444 private = form_data['repo_private']
442 445 clone_uri = form_data.get('clone_uri')
443 446 repos_group = form_data['repo_group']
444 447 landing_rev = form_data['repo_landing_rev']
445 448 copy_fork_permissions = form_data.get('copy_permissions')
446 449 fork_of = form_data.get('fork_parent_id')
447 450
448 451 ## repo creation defaults, private and repo_type are filled in form
449 452 defs = RhodeCodeSetting.get_default_repo_settings(strip_prefix=True)
450 453 enable_statistics = defs.get('repo_enable_statistics')
451 454 enable_locking = defs.get('repo_enable_locking')
452 455 enable_downloads = defs.get('repo_enable_downloads')
453 456
454 457 return self.create_repo(
455 458 repo_name, repo_type, description, owner, private, clone_uri,
456 459 repos_group, landing_rev, just_db, fork_of, copy_fork_permissions,
457 460 enable_statistics, enable_locking, enable_downloads
458 461 )
459 462
460 463 def _update_permissions(self, repo, perms_new=None,
461 464 perms_updates=None):
462 465 if not perms_new:
463 466 perms_new = []
464 467 if not perms_updates:
465 468 perms_updates = []
466 469
467 470 # update permissions
468 471 for member, perm, member_type in perms_updates:
469 472 if member_type == 'user':
470 473 # this updates existing one
471 474 self.grant_user_permission(
472 475 repo=repo, user=member, perm=perm
473 476 )
474 477 else:
475 self.grant_users_group_permission(
476 repo=repo, group_name=member, perm=perm
477 )
478 #check if we have permissions to alter this usergroup
479 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
480 'usergroup.admin')(member):
481 self.grant_users_group_permission(
482 repo=repo, group_name=member, perm=perm
483 )
478 484 # set new permissions
479 485 for member, perm, member_type in perms_new:
480 486 if member_type == 'user':
481 487 self.grant_user_permission(
482 488 repo=repo, user=member, perm=perm
483 489 )
484 490 else:
485 self.grant_users_group_permission(
486 repo=repo, group_name=member, perm=perm
487 )
491 #check if we have permissions to alter this usergroup
492 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
493 'usergroup.admin')(member):
494 self.grant_users_group_permission(
495 repo=repo, group_name=member, perm=perm
496 )
488 497
489 498 def create_fork(self, form_data, cur_user):
490 499 """
491 500 Simple wrapper into executing celery task for fork creation
492 501
493 502 :param form_data:
494 503 :param cur_user:
495 504 """
496 505 from rhodecode.lib.celerylib import tasks, run_task
497 506 run_task(tasks.create_repo_fork, form_data, cur_user)
498 507
499 508 def delete(self, repo, forks=None, fs_remove=True):
500 509 """
501 510 Delete given repository, forks parameter defines what do do with
502 511 attached forks. Throws AttachedForksError if deleted repo has attached
503 512 forks
504 513
505 514 :param repo:
506 515 :param forks: str 'delete' or 'detach'
507 516 :param fs_remove: remove(archive) repo from filesystem
508 517 """
509 518 repo = self._get_repo(repo)
510 519 if repo:
511 520 if forks == 'detach':
512 521 for r in repo.forks:
513 522 r.fork = None
514 523 self.sa.add(r)
515 524 elif forks == 'delete':
516 525 for r in repo.forks:
517 526 self.delete(r, forks='delete')
518 527 elif [f for f in repo.forks]:
519 528 raise AttachedForksError()
520 529
521 530 old_repo_dict = repo.get_dict()
522 531 owner = repo.user
523 532 try:
524 533 self.sa.delete(repo)
525 534 if fs_remove:
526 535 self.__delete_repo(repo)
527 536 else:
528 537 log.debug('skipping removal from filesystem')
529 538 log_delete_repository(old_repo_dict,
530 539 deleted_by=owner.username)
531 540 except Exception:
532 541 log.error(traceback.format_exc())
533 542 raise
534 543
535 544 def grant_user_permission(self, repo, user, perm):
536 545 """
537 546 Grant permission for user on given repository, or update existing one
538 547 if found
539 548
540 549 :param repo: Instance of Repository, repository_id, or repository name
541 550 :param user: Instance of User, user_id or username
542 551 :param perm: Instance of Permission, or permission_name
543 552 """
544 553 user = self._get_user(user)
545 554 repo = self._get_repo(repo)
546 555 permission = self._get_perm(perm)
547 556
548 557 # check if we have that permission already
549 558 obj = self.sa.query(UserRepoToPerm)\
550 559 .filter(UserRepoToPerm.user == user)\
551 560 .filter(UserRepoToPerm.repository == repo)\
552 561 .scalar()
553 562 if obj is None:
554 563 # create new !
555 564 obj = UserRepoToPerm()
556 565 obj.repository = repo
557 566 obj.user = user
558 567 obj.permission = permission
559 568 self.sa.add(obj)
560 569 log.debug('Granted perm %s to %s on %s' % (perm, user, repo))
561 570
562 571 def revoke_user_permission(self, repo, user):
563 572 """
564 573 Revoke permission for user on given repository
565 574
566 575 :param repo: Instance of Repository, repository_id, or repository name
567 576 :param user: Instance of User, user_id or username
568 577 """
569 578
570 579 user = self._get_user(user)
571 580 repo = self._get_repo(repo)
572 581
573 582 obj = self.sa.query(UserRepoToPerm)\
574 583 .filter(UserRepoToPerm.repository == repo)\
575 584 .filter(UserRepoToPerm.user == user)\
576 585 .scalar()
577 586 if obj:
578 587 self.sa.delete(obj)
579 588 log.debug('Revoked perm on %s on %s' % (repo, user))
580 589
581 590 def grant_users_group_permission(self, repo, group_name, perm):
582 591 """
583 592 Grant permission for user group on given repository, or update
584 593 existing one if found
585 594
586 595 :param repo: Instance of Repository, repository_id, or repository name
587 596 :param group_name: Instance of UserGroup, users_group_id,
588 597 or user group name
589 598 :param perm: Instance of Permission, or permission_name
590 599 """
591 600 repo = self._get_repo(repo)
592 601 group_name = self._get_user_group(group_name)
593 602 permission = self._get_perm(perm)
594 603
595 604 # check if we have that permission already
596 605 obj = self.sa.query(UserGroupRepoToPerm)\
597 606 .filter(UserGroupRepoToPerm.users_group == group_name)\
598 607 .filter(UserGroupRepoToPerm.repository == repo)\
599 608 .scalar()
600 609
601 610 if obj is None:
602 611 # create new
603 612 obj = UserGroupRepoToPerm()
604 613
605 614 obj.repository = repo
606 615 obj.users_group = group_name
607 616 obj.permission = permission
608 617 self.sa.add(obj)
609 618 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repo))
610 619
611 620 def revoke_users_group_permission(self, repo, group_name):
612 621 """
613 622 Revoke permission for user group on given repository
614 623
615 624 :param repo: Instance of Repository, repository_id, or repository name
616 625 :param group_name: Instance of UserGroup, users_group_id,
617 626 or user group name
618 627 """
619 628 repo = self._get_repo(repo)
620 629 group_name = self._get_user_group(group_name)
621 630
622 631 obj = self.sa.query(UserGroupRepoToPerm)\
623 632 .filter(UserGroupRepoToPerm.repository == repo)\
624 633 .filter(UserGroupRepoToPerm.users_group == group_name)\
625 634 .scalar()
626 635 if obj:
627 636 self.sa.delete(obj)
628 637 log.debug('Revoked perm to %s on %s' % (repo, group_name))
629 638
630 639 def delete_stats(self, repo_name):
631 640 """
632 641 removes stats for given repo
633 642
634 643 :param repo_name:
635 644 """
636 645 repo = self._get_repo(repo_name)
637 646 try:
638 647 obj = self.sa.query(Statistics)\
639 648 .filter(Statistics.repository == repo).scalar()
640 649 if obj:
641 650 self.sa.delete(obj)
642 651 except Exception:
643 652 log.error(traceback.format_exc())
644 653 raise
645 654
646 655 def __create_repo(self, repo_name, alias, parent, clone_uri=False):
647 656 """
648 657 makes repository on filesystem. It's group aware means it'll create
649 658 a repository within a group, and alter the paths accordingly of
650 659 group location
651 660
652 661 :param repo_name:
653 662 :param alias:
654 663 :param parent_id:
655 664 :param clone_uri:
656 665 """
657 666 from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group
658 667 from rhodecode.model.scm import ScmModel
659 668
660 669 if parent:
661 670 new_parent_path = os.sep.join(parent.full_path_splitted)
662 671 else:
663 672 new_parent_path = ''
664 673
665 674 # we need to make it str for mercurial
666 675 repo_path = os.path.join(*map(lambda x: safe_str(x),
667 676 [self.repos_path, new_parent_path, repo_name]))
668 677
669 678 # check if this path is not a repository
670 679 if is_valid_repo(repo_path, self.repos_path):
671 680 raise Exception('This path %s is a valid repository' % repo_path)
672 681
673 682 # check if this path is a group
674 683 if is_valid_repos_group(repo_path, self.repos_path):
675 684 raise Exception('This path %s is a valid group' % repo_path)
676 685
677 686 log.info('creating repo %s in %s @ %s' % (
678 687 repo_name, safe_unicode(repo_path),
679 688 obfuscate_url_pw(clone_uri)
680 689 )
681 690 )
682 691 backend = get_backend(alias)
683 692 if alias == 'hg':
684 693 backend(repo_path, create=True, src_url=clone_uri)
685 694 elif alias == 'git':
686 695 r = backend(repo_path, create=True, src_url=clone_uri, bare=True)
687 696 # add rhodecode hook into this repo
688 697 ScmModel().install_git_hook(repo=r)
689 698 else:
690 699 raise Exception('Undefined alias %s' % alias)
691 700
692 701 def __rename_repo(self, old, new):
693 702 """
694 703 renames repository on filesystem
695 704
696 705 :param old: old name
697 706 :param new: new name
698 707 """
699 708 log.info('renaming repo from %s to %s' % (old, new))
700 709
701 710 old_path = os.path.join(self.repos_path, old)
702 711 new_path = os.path.join(self.repos_path, new)
703 712 if os.path.isdir(new_path):
704 713 raise Exception(
705 714 'Was trying to rename to already existing dir %s' % new_path
706 715 )
707 716 shutil.move(old_path, new_path)
708 717
709 718 def __delete_repo(self, repo):
710 719 """
711 720 removes repo from filesystem, the removal is acctually made by
712 721 added rm__ prefix into dir, and rename internat .hg/.git dirs so this
713 722 repository is no longer valid for rhodecode, can be undeleted later on
714 723 by reverting the renames on this repository
715 724
716 725 :param repo: repo object
717 726 """
718 727 rm_path = os.path.join(self.repos_path, repo.repo_name)
719 728 log.info("Removing %s" % (rm_path))
720 729 # disable hg/git internal that it doesn't get detected as repo
721 730 alias = repo.repo_type
722 731
723 732 bare = getattr(repo.scm_instance, 'bare', False)
724 733
725 734 if not bare:
726 735 # skip this for bare git repos
727 736 shutil.move(os.path.join(rm_path, '.%s' % alias),
728 737 os.path.join(rm_path, 'rm__.%s' % alias))
729 738 # disable repo
730 739 _now = datetime.now()
731 740 _ms = str(_now.microsecond).rjust(6, '0')
732 741 _d = 'rm__%s__%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
733 742 repo.just_name)
734 743 if repo.group:
735 744 args = repo.group.full_path_splitted + [_d]
736 745 _d = os.path.join(*args)
737 746 shutil.move(rm_path, os.path.join(self.repos_path, _d))
@@ -1,429 +1,436 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.user_group
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 repo group model for RhodeCode
7 7
8 8 :created_on: Jan 25, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import os
27 27 import logging
28 28 import traceback
29 29 import shutil
30 30 import datetime
31 31
32 32 from rhodecode.lib.utils2 import LazyProperty
33 33
34 34 from rhodecode.model import BaseModel
35 35 from rhodecode.model.db import RepoGroup, RhodeCodeUi, UserRepoGroupToPerm, \
36 36 User, Permission, UserGroupRepoGroupToPerm, UserGroup, Repository
37 37
38 38 log = logging.getLogger(__name__)
39 39
40 40
41 41 class ReposGroupModel(BaseModel):
42 42
43 43 cls = RepoGroup
44 44
45 45 def _get_user_group(self, users_group):
46 46 return self._get_instance(UserGroup, users_group,
47 47 callback=UserGroup.get_by_group_name)
48 48
49 49 def _get_repo_group(self, repos_group):
50 50 return self._get_instance(RepoGroup, repos_group,
51 51 callback=RepoGroup.get_by_group_name)
52 52
53 53 @LazyProperty
54 54 def repos_path(self):
55 55 """
56 56 Get's the repositories root path from database
57 57 """
58 58
59 59 q = RhodeCodeUi.get_by_key('/')
60 60 return q.ui_value
61 61
62 62 def _create_default_perms(self, new_group):
63 63 # create default permission
64 64 default_perm = 'group.read'
65 65 def_user = User.get_default_user()
66 66 for p in def_user.user_perms:
67 67 if p.permission.permission_name.startswith('group.'):
68 68 default_perm = p.permission.permission_name
69 69 break
70 70
71 71 repo_group_to_perm = UserRepoGroupToPerm()
72 72 repo_group_to_perm.permission = Permission.get_by_key(default_perm)
73 73
74 74 repo_group_to_perm.group = new_group
75 75 repo_group_to_perm.user_id = def_user.user_id
76 76 return repo_group_to_perm
77 77
78 78 def __create_group(self, group_name):
79 79 """
80 80 makes repository group on filesystem
81 81
82 82 :param repo_name:
83 83 :param parent_id:
84 84 """
85 85
86 86 create_path = os.path.join(self.repos_path, group_name)
87 87 log.debug('creating new group in %s' % create_path)
88 88
89 89 if os.path.isdir(create_path):
90 90 raise Exception('That directory already exists !')
91 91
92 92 os.makedirs(create_path)
93 93
94 94 def __rename_group(self, old, new):
95 95 """
96 96 Renames a group on filesystem
97 97
98 98 :param group_name:
99 99 """
100 100
101 101 if old == new:
102 102 log.debug('skipping group rename')
103 103 return
104 104
105 105 log.debug('renaming repository group from %s to %s' % (old, new))
106 106
107 107 old_path = os.path.join(self.repos_path, old)
108 108 new_path = os.path.join(self.repos_path, new)
109 109
110 110 log.debug('renaming repos paths from %s to %s' % (old_path, new_path))
111 111
112 112 if os.path.isdir(new_path):
113 113 raise Exception('Was trying to rename to already '
114 114 'existing dir %s' % new_path)
115 115 shutil.move(old_path, new_path)
116 116
117 117 def __delete_group(self, group, force_delete=False):
118 118 """
119 119 Deletes a group from a filesystem
120 120
121 121 :param group: instance of group from database
122 122 :param force_delete: use shutil rmtree to remove all objects
123 123 """
124 124 paths = group.full_path.split(RepoGroup.url_sep())
125 125 paths = os.sep.join(paths)
126 126
127 127 rm_path = os.path.join(self.repos_path, paths)
128 128 log.info("Removing group %s" % (rm_path))
129 129 # delete only if that path really exists
130 130 if os.path.isdir(rm_path):
131 131 if force_delete:
132 132 shutil.rmtree(rm_path)
133 133 else:
134 134 #archive that group`
135 135 _now = datetime.datetime.now()
136 136 _ms = str(_now.microsecond).rjust(6, '0')
137 137 _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
138 138 group.name)
139 139 shutil.move(rm_path, os.path.join(self.repos_path, _d))
140 140
141 141 def create(self, group_name, group_description, owner, parent=None, just_db=False):
142 142 try:
143 143 new_repos_group = RepoGroup()
144 144 new_repos_group.user = self._get_user(owner)
145 145 new_repos_group.group_description = group_description or group_name
146 146 new_repos_group.parent_group = self._get_repo_group(parent)
147 147 new_repos_group.group_name = new_repos_group.get_new_name(group_name)
148 148
149 149 self.sa.add(new_repos_group)
150 150 perm_obj = self._create_default_perms(new_repos_group)
151 151 self.sa.add(perm_obj)
152 152
153 153 #create an ADMIN permission for owner, later owner should go into
154 154 #the owner field of groups
155 155 self.grant_user_permission(repos_group=new_repos_group,
156 156 user=owner, perm='group.admin')
157 157
158 158 if not just_db:
159 159 # we need to flush here, in order to check if database won't
160 160 # throw any exceptions, create filesystem dirs at the very end
161 161 self.sa.flush()
162 162 self.__create_group(new_repos_group.group_name)
163 163
164 164 return new_repos_group
165 165 except Exception:
166 166 log.error(traceback.format_exc())
167 167 raise
168 168
169 169 def _update_permissions(self, repos_group, perms_new=None,
170 170 perms_updates=None, recursive=False):
171 171 from rhodecode.model.repo import RepoModel
172 from rhodecode.lib.auth import HasUserGroupPermissionAny
172 173 if not perms_new:
173 174 perms_new = []
174 175 if not perms_updates:
175 176 perms_updates = []
176 177
177 178 def _set_perm_user(obj, user, perm):
178 179 if isinstance(obj, RepoGroup):
179 180 self.grant_user_permission(
180 181 repos_group=obj, user=user, perm=perm
181 182 )
182 183 elif isinstance(obj, Repository):
183 184 #we do this ONLY IF repository is non-private
184 185 if obj.private:
185 186 return
186 187
187 188 # we set group permission but we have to switch to repo
188 189 # permission
189 190 perm = perm.replace('group.', 'repository.')
190 191 RepoModel().grant_user_permission(
191 192 repo=obj, user=user, perm=perm
192 193 )
193 194
194 195 def _set_perm_group(obj, users_group, perm):
195 196 if isinstance(obj, RepoGroup):
196 197 self.grant_users_group_permission(
197 198 repos_group=obj, group_name=users_group, perm=perm
198 199 )
199 200 elif isinstance(obj, Repository):
200 201 # we set group permission but we have to switch to repo
201 202 # permission
202 203 perm = perm.replace('group.', 'repository.')
203 204 RepoModel().grant_users_group_permission(
204 205 repo=obj, group_name=users_group, perm=perm
205 206 )
206 207 updates = []
207 208 log.debug('Now updating permissions for %s in recursive mode:%s'
208 209 % (repos_group, recursive))
209 210
210 211 for obj in repos_group.recursive_groups_and_repos():
211 212 #obj is an instance of a group or repositories in that group
212 213 if not recursive:
213 214 obj = repos_group
214 215
215 216 # update permissions
216 217 for member, perm, member_type in perms_updates:
217 218 ## set for user
218 219 if member_type == 'user':
219 220 # this updates also current one if found
220 221 _set_perm_user(obj, user=member, perm=perm)
221 222 ## set for user group
222 223 else:
223 _set_perm_group(obj, users_group=member, perm=perm)
224 #check if we have permissions to alter this usergroup
225 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
226 'usergroup.admin')(member):
227 _set_perm_group(obj, users_group=member, perm=perm)
224 228 # set new permissions
225 229 for member, perm, member_type in perms_new:
226 230 if member_type == 'user':
227 231 _set_perm_user(obj, user=member, perm=perm)
228 232 else:
229 _set_perm_group(obj, users_group=member, perm=perm)
233 #check if we have permissions to alter this usergroup
234 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
235 'usergroup.admin')(member):
236 _set_perm_group(obj, users_group=member, perm=perm)
230 237 updates.append(obj)
231 238 #if it's not recursive call
232 239 # break the loop and don't proceed with other changes
233 240 if not recursive:
234 241 break
235 242 return updates
236 243
237 244 def update(self, repos_group, form_data):
238 245
239 246 try:
240 247 repos_group = self._get_repo_group(repos_group)
241 248 old_path = repos_group.full_path
242 249
243 250 # change properties
244 251 repos_group.group_description = form_data['group_description']
245 252 repos_group.group_parent_id = form_data['group_parent_id']
246 253 repos_group.enable_locking = form_data['enable_locking']
247 254
248 255 repos_group.parent_group = RepoGroup.get(form_data['group_parent_id'])
249 256 repos_group.group_name = repos_group.get_new_name(form_data['group_name'])
250 257 new_path = repos_group.full_path
251 258 self.sa.add(repos_group)
252 259
253 260 # iterate over all members of this groups and do fixes
254 261 # set locking if given
255 262 # if obj is a repoGroup also fix the name of the group according
256 263 # to the parent
257 264 # if obj is a Repo fix it's name
258 265 # this can be potentially heavy operation
259 266 for obj in repos_group.recursive_groups_and_repos():
260 267 #set the value from it's parent
261 268 obj.enable_locking = repos_group.enable_locking
262 269 if isinstance(obj, RepoGroup):
263 270 new_name = obj.get_new_name(obj.name)
264 271 log.debug('Fixing group %s to new name %s' \
265 272 % (obj.group_name, new_name))
266 273 obj.group_name = new_name
267 274 elif isinstance(obj, Repository):
268 275 # we need to get all repositories from this new group and
269 276 # rename them accordingly to new group path
270 277 new_name = obj.get_new_name(obj.just_name)
271 278 log.debug('Fixing repo %s to new name %s' \
272 279 % (obj.repo_name, new_name))
273 280 obj.repo_name = new_name
274 281 self.sa.add(obj)
275 282
276 283 self.__rename_group(old_path, new_path)
277 284
278 285 return repos_group
279 286 except Exception:
280 287 log.error(traceback.format_exc())
281 288 raise
282 289
283 290 def delete(self, repos_group, force_delete=False):
284 291 repos_group = self._get_repo_group(repos_group)
285 292 try:
286 293 self.sa.delete(repos_group)
287 294 self.__delete_group(repos_group, force_delete)
288 295 except Exception:
289 296 log.error('Error removing repos_group %s' % repos_group)
290 297 raise
291 298
292 299 def delete_permission(self, repos_group, obj, obj_type, recursive):
293 300 """
294 301 Revokes permission for repos_group for given obj(user or users_group),
295 302 obj_type can be user or user group
296 303
297 304 :param repos_group:
298 305 :param obj: user or user group id
299 306 :param obj_type: user or user group type
300 307 :param recursive: recurse to all children of group
301 308 """
302 309 from rhodecode.model.repo import RepoModel
303 310 repos_group = self._get_repo_group(repos_group)
304 311
305 312 for el in repos_group.recursive_groups_and_repos():
306 313 if not recursive:
307 314 # if we don't recurse set the permission on only the top level
308 315 # object
309 316 el = repos_group
310 317
311 318 if isinstance(el, RepoGroup):
312 319 if obj_type == 'user':
313 320 ReposGroupModel().revoke_user_permission(el, user=obj)
314 321 elif obj_type == 'users_group':
315 322 ReposGroupModel().revoke_users_group_permission(el, group_name=obj)
316 323 else:
317 324 raise Exception('undefined object type %s' % obj_type)
318 325 elif isinstance(el, Repository):
319 326 if obj_type == 'user':
320 327 RepoModel().revoke_user_permission(el, user=obj)
321 328 elif obj_type == 'users_group':
322 329 RepoModel().revoke_users_group_permission(el, group_name=obj)
323 330 else:
324 331 raise Exception('undefined object type %s' % obj_type)
325 332
326 333 #if it's not recursive call
327 334 # break the loop and don't proceed with other changes
328 335 if not recursive:
329 336 break
330 337
331 338 def grant_user_permission(self, repos_group, user, perm):
332 339 """
333 340 Grant permission for user on given repository group, or update
334 341 existing one if found
335 342
336 343 :param repos_group: Instance of ReposGroup, repositories_group_id,
337 344 or repositories_group name
338 345 :param user: Instance of User, user_id or username
339 346 :param perm: Instance of Permission, or permission_name
340 347 """
341 348
342 349 repos_group = self._get_repo_group(repos_group)
343 350 user = self._get_user(user)
344 351 permission = self._get_perm(perm)
345 352
346 353 # check if we have that permission already
347 354 obj = self.sa.query(UserRepoGroupToPerm)\
348 355 .filter(UserRepoGroupToPerm.user == user)\
349 356 .filter(UserRepoGroupToPerm.group == repos_group)\
350 357 .scalar()
351 358 if obj is None:
352 359 # create new !
353 360 obj = UserRepoGroupToPerm()
354 361 obj.group = repos_group
355 362 obj.user = user
356 363 obj.permission = permission
357 364 self.sa.add(obj)
358 365 log.debug('Granted perm %s to %s on %s' % (perm, user, repos_group))
359 366
360 367 def revoke_user_permission(self, repos_group, user):
361 368 """
362 369 Revoke permission for user on given repository group
363 370
364 371 :param repos_group: Instance of ReposGroup, repositories_group_id,
365 372 or repositories_group name
366 373 :param user: Instance of User, user_id or username
367 374 """
368 375
369 376 repos_group = self._get_repo_group(repos_group)
370 377 user = self._get_user(user)
371 378
372 379 obj = self.sa.query(UserRepoGroupToPerm)\
373 380 .filter(UserRepoGroupToPerm.user == user)\
374 381 .filter(UserRepoGroupToPerm.group == repos_group)\
375 382 .scalar()
376 383 if obj:
377 384 self.sa.delete(obj)
378 385 log.debug('Revoked perm on %s on %s' % (repos_group, user))
379 386
380 387 def grant_users_group_permission(self, repos_group, group_name, perm):
381 388 """
382 389 Grant permission for user group on given repository group, or update
383 390 existing one if found
384 391
385 392 :param repos_group: Instance of ReposGroup, repositories_group_id,
386 393 or repositories_group name
387 394 :param group_name: Instance of UserGroup, users_group_id,
388 395 or user group name
389 396 :param perm: Instance of Permission, or permission_name
390 397 """
391 398 repos_group = self._get_repo_group(repos_group)
392 399 group_name = self._get_user_group(group_name)
393 400 permission = self._get_perm(perm)
394 401
395 402 # check if we have that permission already
396 403 obj = self.sa.query(UserGroupRepoGroupToPerm)\
397 404 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
398 405 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
399 406 .scalar()
400 407
401 408 if obj is None:
402 409 # create new
403 410 obj = UserGroupRepoGroupToPerm()
404 411
405 412 obj.group = repos_group
406 413 obj.users_group = group_name
407 414 obj.permission = permission
408 415 self.sa.add(obj)
409 416 log.debug('Granted perm %s to %s on %s' % (perm, group_name, repos_group))
410 417
411 418 def revoke_users_group_permission(self, repos_group, group_name):
412 419 """
413 420 Revoke permission for user group on given repository group
414 421
415 422 :param repos_group: Instance of ReposGroup, repositories_group_id,
416 423 or repositories_group name
417 424 :param group_name: Instance of UserGroup, users_group_id,
418 425 or user group name
419 426 """
420 427 repos_group = self._get_repo_group(repos_group)
421 428 group_name = self._get_user_group(group_name)
422 429
423 430 obj = self.sa.query(UserGroupRepoGroupToPerm)\
424 431 .filter(UserGroupRepoGroupToPerm.group == repos_group)\
425 432 .filter(UserGroupRepoGroupToPerm.users_group == group_name)\
426 433 .scalar()
427 434 if obj:
428 435 self.sa.delete(obj)
429 436 log.debug('Revoked perm to %s on %s' % (repos_group, group_name))
@@ -1,343 +1,350 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.users_group
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 user group model for RhodeCode
7 7
8 8 :created_on: Oct 1, 2011
9 9 :author: nvinot
10 10 :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr>
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import logging
28 28 import traceback
29 29
30 30 from rhodecode.model import BaseModel
31 31 from rhodecode.model.db import UserGroupMember, UserGroup,\
32 32 UserGroupRepoToPerm, Permission, UserGroupToPerm, User, UserUserGroupToPerm,\
33 33 UserGroupUserGroupToPerm
34 34 from rhodecode.lib.exceptions import UserGroupsAssignedException,\
35 35 RepoGroupAssignmentError
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 39
40 40 class UserGroupModel(BaseModel):
41 41
42 42 cls = UserGroup
43 43
44 44 def _get_user_group(self, users_group):
45 45 return self._get_instance(UserGroup, users_group,
46 46 callback=UserGroup.get_by_group_name)
47 47
48 48 def _create_default_perms(self, user_group):
49 49 # create default permission
50 50 default_perm = 'usergroup.read'
51 51 def_user = User.get_default_user()
52 52 for p in def_user.user_perms:
53 53 if p.permission.permission_name.startswith('usergroup.'):
54 54 default_perm = p.permission.permission_name
55 55 break
56 56
57 57 user_group_to_perm = UserUserGroupToPerm()
58 58 user_group_to_perm.permission = Permission.get_by_key(default_perm)
59 59
60 60 user_group_to_perm.user_group = user_group
61 61 user_group_to_perm.user_id = def_user.user_id
62 62 return user_group_to_perm
63 63
64 64 def _update_permissions(self, user_group, perms_new=None,
65 65 perms_updates=None):
66 from rhodecode.lib.auth import HasUserGroupPermissionAny
66 67 if not perms_new:
67 68 perms_new = []
68 69 if not perms_updates:
69 70 perms_updates = []
70 71
71 72 # update permissions
72 73 for member, perm, member_type in perms_updates:
73 74 if member_type == 'user':
74 75 # this updates existing one
75 76 self.grant_user_permission(
76 77 user_group=user_group, user=member, perm=perm
77 78 )
78 79 else:
79 self.grant_users_group_permission(
80 target_user_group=user_group, user_group=member, perm=perm
81 )
80 #check if we have permissions to alter this usergroup
81 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
82 'usergroup.admin')(member):
83 self.grant_users_group_permission(
84 target_user_group=user_group, user_group=member, perm=perm
85 )
82 86 # set new permissions
83 87 for member, perm, member_type in perms_new:
84 88 if member_type == 'user':
85 89 self.grant_user_permission(
86 90 user_group=user_group, user=member, perm=perm
87 91 )
88 92 else:
89 self.grant_users_group_permission(
90 target_user_group=user_group, user_group=member, perm=perm
91 )
93 #check if we have permissions to alter this usergroup
94 if HasUserGroupPermissionAny('usergroup.read', 'usergroup.write',
95 'usergroup.admin')(member):
96 self.grant_users_group_permission(
97 target_user_group=user_group, user_group=member, perm=perm
98 )
92 99
93 100 def get(self, users_group_id, cache=False):
94 101 return UserGroup.get(users_group_id)
95 102
96 103 def get_group(self, users_group):
97 104 return self._get_user_group(users_group)
98 105
99 106 def get_by_name(self, name, cache=False, case_insensitive=False):
100 107 return UserGroup.get_by_group_name(name, cache, case_insensitive)
101 108
102 109 def create(self, name, owner, active=True):
103 110 try:
104 111 new_user_group = UserGroup()
105 112 new_user_group.user = self._get_user(owner)
106 113 new_user_group.users_group_name = name
107 114 new_user_group.users_group_active = active
108 115 self.sa.add(new_user_group)
109 116 perm_obj = self._create_default_perms(new_user_group)
110 117 self.sa.add(perm_obj)
111 118
112 119 self.grant_user_permission(user_group=new_user_group,
113 120 user=owner, perm='usergroup.admin')
114 121
115 122 return new_user_group
116 123 except Exception:
117 124 log.error(traceback.format_exc())
118 125 raise
119 126
120 127 def update(self, users_group, form_data):
121 128
122 129 try:
123 130 users_group = self._get_user_group(users_group)
124 131
125 132 for k, v in form_data.items():
126 133 if k == 'users_group_members':
127 134 users_group.members = []
128 135 self.sa.flush()
129 136 members_list = []
130 137 if v:
131 138 v = [v] if isinstance(v, basestring) else v
132 139 for u_id in set(v):
133 140 member = UserGroupMember(users_group.users_group_id, u_id)
134 141 members_list.append(member)
135 142 setattr(users_group, 'members', members_list)
136 143 setattr(users_group, k, v)
137 144
138 145 self.sa.add(users_group)
139 146 except Exception:
140 147 log.error(traceback.format_exc())
141 148 raise
142 149
143 150 def delete(self, users_group, force=False):
144 151 """
145 152 Deletes repository group, unless force flag is used
146 153 raises exception if there are members in that group, else deletes
147 154 group and users
148 155
149 156 :param users_group:
150 157 :param force:
151 158 """
152 159 try:
153 160 users_group = self._get_user_group(users_group)
154 161
155 162 # check if this group is not assigned to repo
156 163 assigned_groups = UserGroupRepoToPerm.query()\
157 164 .filter(UserGroupRepoToPerm.users_group == users_group).all()
158 165
159 166 if assigned_groups and not force:
160 167 raise UserGroupsAssignedException('RepoGroup assigned to %s' %
161 168 assigned_groups)
162 169
163 170 self.sa.delete(users_group)
164 171 except Exception:
165 172 log.error(traceback.format_exc())
166 173 raise
167 174
168 175 def add_user_to_group(self, users_group, user):
169 176 users_group = self._get_user_group(users_group)
170 177 user = self._get_user(user)
171 178
172 179 for m in users_group.members:
173 180 u = m.user
174 181 if u.user_id == user.user_id:
175 182 return True
176 183
177 184 try:
178 185 users_group_member = UserGroupMember()
179 186 users_group_member.user = user
180 187 users_group_member.users_group = users_group
181 188
182 189 users_group.members.append(users_group_member)
183 190 user.group_member.append(users_group_member)
184 191
185 192 self.sa.add(users_group_member)
186 193 return users_group_member
187 194 except Exception:
188 195 log.error(traceback.format_exc())
189 196 raise
190 197
191 198 def remove_user_from_group(self, users_group, user):
192 199 users_group = self._get_user_group(users_group)
193 200 user = self._get_user(user)
194 201
195 202 users_group_member = None
196 203 for m in users_group.members:
197 204 if m.user.user_id == user.user_id:
198 205 # Found this user's membership row
199 206 users_group_member = m
200 207 break
201 208
202 209 if users_group_member:
203 210 try:
204 211 self.sa.delete(users_group_member)
205 212 return True
206 213 except Exception:
207 214 log.error(traceback.format_exc())
208 215 raise
209 216 else:
210 217 # User isn't in that group
211 218 return False
212 219
213 220 def has_perm(self, users_group, perm):
214 221 users_group = self._get_user_group(users_group)
215 222 perm = self._get_perm(perm)
216 223
217 224 return UserGroupToPerm.query()\
218 225 .filter(UserGroupToPerm.users_group == users_group)\
219 226 .filter(UserGroupToPerm.permission == perm).scalar() is not None
220 227
221 228 def grant_perm(self, users_group, perm):
222 229 users_group = self._get_user_group(users_group)
223 230 perm = self._get_perm(perm)
224 231
225 232 # if this permission is already granted skip it
226 233 _perm = UserGroupToPerm.query()\
227 234 .filter(UserGroupToPerm.users_group == users_group)\
228 235 .filter(UserGroupToPerm.permission == perm)\
229 236 .scalar()
230 237 if _perm:
231 238 return
232 239
233 240 new = UserGroupToPerm()
234 241 new.users_group = users_group
235 242 new.permission = perm
236 243 self.sa.add(new)
237 244
238 245 def revoke_perm(self, users_group, perm):
239 246 users_group = self._get_user_group(users_group)
240 247 perm = self._get_perm(perm)
241 248
242 249 obj = UserGroupToPerm.query()\
243 250 .filter(UserGroupToPerm.users_group == users_group)\
244 251 .filter(UserGroupToPerm.permission == perm).scalar()
245 252 if obj:
246 253 self.sa.delete(obj)
247 254
248 255 def grant_user_permission(self, user_group, user, perm):
249 256 """
250 257 Grant permission for user on given user group, or update
251 258 existing one if found
252 259
253 260 :param user_group: Instance of UserGroup, users_group_id,
254 261 or users_group_name
255 262 :param user: Instance of User, user_id or username
256 263 :param perm: Instance of Permission, or permission_name
257 264 """
258 265
259 266 user_group = self._get_user_group(user_group)
260 267 user = self._get_user(user)
261 268 permission = self._get_perm(perm)
262 269
263 270 # check if we have that permission already
264 271 obj = self.sa.query(UserUserGroupToPerm)\
265 272 .filter(UserUserGroupToPerm.user == user)\
266 273 .filter(UserUserGroupToPerm.user_group == user_group)\
267 274 .scalar()
268 275 if obj is None:
269 276 # create new !
270 277 obj = UserUserGroupToPerm()
271 278 obj.user_group = user_group
272 279 obj.user = user
273 280 obj.permission = permission
274 281 self.sa.add(obj)
275 282 log.debug('Granted perm %s to %s on %s' % (perm, user, user_group))
276 283
277 284 def revoke_user_permission(self, user_group, user):
278 285 """
279 286 Revoke permission for user on given repository group
280 287
281 288 :param user_group: Instance of ReposGroup, repositories_group_id,
282 289 or repositories_group name
283 290 :param user: Instance of User, user_id or username
284 291 """
285 292
286 293 user_group = self._get_user_group(user_group)
287 294 user = self._get_user(user)
288 295
289 296 obj = self.sa.query(UserUserGroupToPerm)\
290 297 .filter(UserUserGroupToPerm.user == user)\
291 298 .filter(UserUserGroupToPerm.user_group == user_group)\
292 299 .scalar()
293 300 if obj:
294 301 self.sa.delete(obj)
295 302 log.debug('Revoked perm on %s on %s' % (user_group, user))
296 303
297 304 def grant_users_group_permission(self, target_user_group, user_group, perm):
298 305 """
299 306 Grant user group permission for given target_user_group
300 307
301 308 :param target_user_group:
302 309 :param user_group:
303 310 :param perm:
304 311 """
305 312 target_user_group = self._get_user_group(target_user_group)
306 313 user_group = self._get_user_group(user_group)
307 314 permission = self._get_perm(perm)
308 315 # forbid assigning same user group to itself
309 316 if target_user_group == user_group:
310 317 raise RepoGroupAssignmentError('target repo:%s cannot be '
311 318 'assigned to itself' % target_user_group)
312 319
313 320 # check if we have that permission already
314 321 obj = self.sa.query(UserGroupUserGroupToPerm)\
315 322 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
316 323 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
317 324 .scalar()
318 325 if obj is None:
319 326 # create new !
320 327 obj = UserGroupUserGroupToPerm()
321 328 obj.user_group = user_group
322 329 obj.target_user_group = target_user_group
323 330 obj.permission = permission
324 331 self.sa.add(obj)
325 332 log.debug('Granted perm %s to %s on %s' % (perm, target_user_group, user_group))
326 333
327 334 def revoke_users_group_permission(self, target_user_group, user_group):
328 335 """
329 336 Revoke user group permission for given target_user_group
330 337
331 338 :param target_user_group:
332 339 :param user_group:
333 340 """
334 341 target_user_group = self._get_user_group(target_user_group)
335 342 user_group = self._get_user_group(user_group)
336 343
337 344 obj = self.sa.query(UserGroupUserGroupToPerm)\
338 345 .filter(UserGroupUserGroupToPerm.target_user_group == target_user_group)\
339 346 .filter(UserGroupUserGroupToPerm.user_group == user_group)\
340 347 .scalar()
341 348 if obj:
342 349 self.sa.delete(obj)
343 350 log.debug('Revoked perm on %s on %s' % (target_user_group, user_group))
General Comments 0
You need to be logged in to leave comments. Login now