##// END OF EJS Templates
repo group: use lazy string formatting when logging...
Mads Kiilerich -
r8749:4b5ab042 stable
parent child Browse files
Show More
@@ -1,530 +1,528 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 """
15 15 kallithea.model.repo_group
16 16 ~~~~~~~~~~~~~~~~~~~~~~~~~~
17 17
18 18 repo group model for Kallithea
19 19
20 20 This file was forked by the Kallithea project in July 2014.
21 21 Original author and date, and relevant copyright and licensing information is below:
22 22 :created_on: Jan 25, 2011
23 23 :author: marcink
24 24 :copyright: (c) 2013 RhodeCode GmbH, and others.
25 25 :license: GPLv3, see LICENSE.md for more details.
26 26 """
27 27
28 28
29 29 import datetime
30 30 import logging
31 31 import os
32 32 import shutil
33 33 import traceback
34 34
35 35 import kallithea.lib.utils2
36 36 from kallithea.lib.utils2 import LazyProperty
37 37 from kallithea.model import db, meta, repo
38 38
39 39
40 40 log = logging.getLogger(__name__)
41 41
42 42
43 43 class RepoGroupModel(object):
44 44
45 45 @LazyProperty
46 46 def repos_path(self):
47 47 """
48 48 Gets the repositories root path from database
49 49 """
50 50
51 51 q = db.Ui.get_by_key('paths', '/')
52 52 return q.ui_value
53 53
54 54 def _create_default_perms(self, new_group):
55 55 # create default permission
56 56 default_perm = 'group.read'
57 57 def_user = db.User.get_default_user()
58 58 for p in def_user.user_perms:
59 59 if p.permission.permission_name.startswith('group.'):
60 60 default_perm = p.permission.permission_name
61 61 break
62 62
63 63 repo_group_to_perm = db.UserRepoGroupToPerm()
64 64 repo_group_to_perm.permission = db.Permission.get_by_key(default_perm)
65 65
66 66 repo_group_to_perm.group = new_group
67 67 repo_group_to_perm.user_id = def_user.user_id
68 68 meta.Session().add(repo_group_to_perm)
69 69 return repo_group_to_perm
70 70
71 71 def _create_group(self, group_name):
72 72 """
73 73 makes repository group on filesystem
74 74
75 75 :param repo_name:
76 76 :param parent_id:
77 77 """
78 78
79 79 create_path = os.path.join(self.repos_path, group_name)
80 80 log.debug('creating new group in %s', create_path)
81 81
82 82 if os.path.isdir(create_path):
83 83 raise Exception('That directory already exists !')
84 84
85 85 os.makedirs(create_path)
86 86 log.debug('Created group in %s', create_path)
87 87
88 88 def _rename_group(self, old, new):
89 89 """
90 90 Renames a group on filesystem
91 91
92 92 :param group_name:
93 93 """
94 94
95 95 if old == new:
96 96 log.debug('skipping group rename')
97 97 return
98 98
99 99 log.debug('renaming repository group from %s to %s', old, new)
100 100
101 101 old_path = os.path.join(self.repos_path, old)
102 102 new_path = os.path.join(self.repos_path, new)
103 103
104 104 log.debug('renaming repos paths from %s to %s', old_path, new_path)
105 105
106 106 if os.path.isdir(new_path):
107 107 raise Exception('Was trying to rename to already '
108 108 'existing dir %s' % new_path)
109 109 shutil.move(old_path, new_path)
110 110
111 111 def _delete_group(self, group, force_delete=False):
112 112 """
113 113 Deletes a group from a filesystem
114 114
115 115 :param group: instance of group from database
116 116 :param force_delete: use shutil rmtree to remove all objects
117 117 """
118 118 paths = group.full_path.split(kallithea.URL_SEP)
119 119 paths = os.sep.join(paths)
120 120
121 121 rm_path = os.path.join(self.repos_path, paths)
122 122 log.info("Removing group %s", rm_path)
123 123 # delete only if that path really exists
124 124 if os.path.isdir(rm_path):
125 125 if force_delete:
126 126 shutil.rmtree(rm_path)
127 127 else:
128 128 # archive that group
129 129 _now = datetime.datetime.now()
130 130 _ms = str(_now.microsecond).rjust(6, '0')
131 131 _d = 'rm__%s_GROUP_%s' % (_now.strftime('%Y%m%d_%H%M%S_' + _ms),
132 132 group.name)
133 133 shutil.move(rm_path, os.path.join(self.repos_path, _d))
134 134
135 135 def create(self, group_name, group_description, owner, parent=None,
136 136 just_db=False, copy_permissions=False):
137 137 try:
138 138 if kallithea.lib.utils2.repo_name_slug(group_name) != group_name:
139 139 raise Exception('invalid repo group name %s' % group_name)
140 140
141 141 owner = db.User.guess_instance(owner)
142 142 parent_group = db.RepoGroup.guess_instance(parent)
143 143 new_repo_group = db.RepoGroup()
144 144 new_repo_group.owner = owner
145 145 new_repo_group.group_description = group_description or group_name
146 146 new_repo_group.parent_group = parent_group
147 147 new_repo_group.group_name = new_repo_group.get_new_name(group_name)
148 148
149 149 meta.Session().add(new_repo_group)
150 150
151 151 # create an ADMIN permission for owner except if we're super admin,
152 152 # later owner should go into the owner field of groups
153 153 if not owner.is_admin:
154 154 self.grant_user_permission(repo_group=new_repo_group,
155 155 user=owner, perm='group.admin')
156 156
157 157 if parent_group and copy_permissions:
158 158 # copy permissions from parent
159 159 user_perms = db.UserRepoGroupToPerm.query() \
160 160 .filter(db.UserRepoGroupToPerm.group == parent_group).all()
161 161
162 162 group_perms = db.UserGroupRepoGroupToPerm.query() \
163 163 .filter(db.UserGroupRepoGroupToPerm.group == parent_group).all()
164 164
165 165 for perm in user_perms:
166 166 # don't copy over the permission for user who is creating
167 167 # this group, if he is not super admin he get's admin
168 168 # permission set above
169 169 if perm.user != owner or owner.is_admin:
170 170 db.UserRepoGroupToPerm.create(perm.user, new_repo_group, perm.permission)
171 171
172 172 for perm in group_perms:
173 173 db.UserGroupRepoGroupToPerm.create(perm.users_group, new_repo_group, perm.permission)
174 174 else:
175 175 self._create_default_perms(new_repo_group)
176 176
177 177 if not just_db:
178 178 # we need to flush here, in order to check if database won't
179 179 # throw any exceptions, create filesystem dirs at the very end
180 180 meta.Session().flush()
181 181 self._create_group(new_repo_group.group_name)
182 182
183 183 return new_repo_group
184 184 except Exception:
185 185 log.error(traceback.format_exc())
186 186 raise
187 187
188 188 def _update_permissions(self, repo_group, perms_new=None,
189 189 perms_updates=None, recursive=None,
190 190 check_perms=True):
191 191 from kallithea.lib.auth import HasUserGroupPermissionLevel
192 192
193 193 if not perms_new:
194 194 perms_new = []
195 195 if not perms_updates:
196 196 perms_updates = []
197 197
198 198 def _set_perm_user(obj, user, perm):
199 199 if isinstance(obj, db.RepoGroup):
200 200 self.grant_user_permission(repo_group=obj, user=user, perm=perm)
201 201 elif isinstance(obj, db.Repository):
202 202 user = db.User.guess_instance(user)
203 203
204 204 # private repos will not allow to change the default permissions
205 205 # using recursive mode
206 206 if obj.private and user.is_default_user:
207 207 return
208 208
209 209 # we set group permission but we have to switch to repo
210 210 # permission
211 211 perm = perm.replace('group.', 'repository.')
212 212 repo.RepoModel().grant_user_permission(
213 213 repo=obj, user=user, perm=perm
214 214 )
215 215
216 216 def _set_perm_group(obj, users_group, perm):
217 217 if isinstance(obj, db.RepoGroup):
218 218 self.grant_user_group_permission(repo_group=obj,
219 219 group_name=users_group,
220 220 perm=perm)
221 221 elif isinstance(obj, db.Repository):
222 222 # we set group permission but we have to switch to repo
223 223 # permission
224 224 perm = perm.replace('group.', 'repository.')
225 225 repo.RepoModel().grant_user_group_permission(
226 226 repo=obj, group_name=users_group, perm=perm
227 227 )
228 228
229 229 # start updates
230 230 updates = []
231 231 log.debug('Now updating permissions for %s in recursive mode:%s',
232 232 repo_group, recursive)
233 233
234 234 for obj in repo_group.recursive_groups_and_repos():
235 235 # iterated obj is an instance of a repos group or repository in
236 236 # that group, recursive option can be: none, repos, groups, all
237 237 if recursive == 'all':
238 238 pass
239 239 elif recursive == 'repos':
240 240 # skip groups, other than this one
241 241 if isinstance(obj, db.RepoGroup) and not obj == repo_group:
242 242 continue
243 243 elif recursive == 'groups':
244 244 # skip repos
245 245 if isinstance(obj, db.Repository):
246 246 continue
247 247 else: # recursive == 'none': # DEFAULT don't apply to iterated objects
248 248 obj = repo_group
249 249 # also we do a break at the end of this loop.
250 250
251 251 # update permissions
252 252 for member, perm, member_type in perms_updates:
253 253 ## set for user
254 254 if member_type == 'user':
255 255 # this updates also current one if found
256 256 _set_perm_user(obj, user=member, perm=perm)
257 257 ## set for user group
258 258 else:
259 259 # check if we have permissions to alter this usergroup's access
260 260 if not check_perms or HasUserGroupPermissionLevel('read')(member):
261 261 _set_perm_group(obj, users_group=member, perm=perm)
262 262 # set new permissions
263 263 for member, perm, member_type in perms_new:
264 264 if member_type == 'user':
265 265 _set_perm_user(obj, user=member, perm=perm)
266 266 else:
267 267 # check if we have permissions to alter this usergroup's access
268 268 if not check_perms or HasUserGroupPermissionLevel('read')(member):
269 269 _set_perm_group(obj, users_group=member, perm=perm)
270 270 updates.append(obj)
271 271 # if it's not recursive call for all,repos,groups
272 272 # break the loop and don't proceed with other changes
273 273 if recursive not in ['all', 'repos', 'groups']:
274 274 break
275 275
276 276 return updates
277 277
278 278 def update(self, repo_group, repo_group_args):
279 279 try:
280 280 repo_group = db.RepoGroup.guess_instance(repo_group)
281 281 old_path = repo_group.full_path # aka .group_name
282 282
283 283 if 'owner' in repo_group_args:
284 284 repo_group.owner = db.User.get_by_username(repo_group_args['owner'])
285 285 if 'group_description' in repo_group_args:
286 286 repo_group.group_description = repo_group_args['group_description']
287 287 if 'parent_group_id' in repo_group_args:
288 288 assert repo_group_args['parent_group_id'] != '-1', repo_group_args # RepoGroupForm should have converted to None
289 289 repo_group.parent_group = db.RepoGroup.get(repo_group_args['parent_group_id'])
290 290 repo_group.group_name = repo_group.get_new_name(repo_group.name)
291 291 if 'group_name' in repo_group_args:
292 292 group_name = repo_group_args['group_name']
293 293 if kallithea.lib.utils2.repo_name_slug(group_name) != group_name:
294 294 raise Exception('invalid repo group name %s' % group_name)
295 295 repo_group.group_name = repo_group.get_new_name(group_name)
296 296 new_path = repo_group.full_path
297 297 meta.Session().add(repo_group)
298 298
299 299 # Iterate over all members of this repo group and update the full
300 300 # path (repo_name and group_name) based on the (already updated)
301 301 # full path of the parent.
302 302 # This can potentially be a heavy operation.
303 303 for obj in repo_group.recursive_groups_and_repos():
304 304 if isinstance(obj, db.RepoGroup):
305 305 new_name = obj.get_new_name(obj.name)
306 log.debug('Fixing group %s to new name %s'
307 % (obj.group_name, new_name))
306 log.debug('Fixing repo group %s to new name %s', obj.group_name, new_name)
308 307 obj.group_name = new_name
309 308 elif isinstance(obj, db.Repository):
310 309 new_name = obj.get_new_name(obj.just_name)
311 log.debug('Fixing repo %s to new name %s'
312 % (obj.repo_name, new_name))
310 log.debug('Fixing repo %s to new name %s', obj.repo_name, new_name)
313 311 obj.repo_name = new_name
314 312
315 313 # Rename in file system
316 314 self._rename_group(old_path, new_path)
317 315
318 316 return repo_group
319 317 except Exception:
320 318 log.error(traceback.format_exc())
321 319 raise
322 320
323 321 def delete(self, repo_group, force_delete=False):
324 322 repo_group = db.RepoGroup.guess_instance(repo_group)
325 323 try:
326 324 meta.Session().delete(repo_group)
327 325 self._delete_group(repo_group, force_delete)
328 326 except Exception:
329 327 log.error('Error removing repo_group %s', repo_group)
330 328 raise
331 329
332 330 def add_permission(self, repo_group, obj, obj_type, perm, recursive):
333 331 repo_group = db.RepoGroup.guess_instance(repo_group)
334 332 perm = db.Permission.guess_instance(perm)
335 333
336 334 for el in repo_group.recursive_groups_and_repos():
337 335 # iterated obj is an instance of a repos group or repository in
338 336 # that group, recursive option can be: none, repos, groups, all
339 337 if recursive == 'all':
340 338 pass
341 339 elif recursive == 'repos':
342 340 # skip groups, other than this one
343 341 if isinstance(el, db.RepoGroup) and not el == repo_group:
344 342 continue
345 343 elif recursive == 'groups':
346 344 # skip repos
347 345 if isinstance(el, db.Repository):
348 346 continue
349 347 else: # recursive == 'none': # DEFAULT don't apply to iterated objects
350 348 el = repo_group
351 349 # also we do a break at the end of this loop.
352 350
353 351 if isinstance(el, db.RepoGroup):
354 352 if obj_type == 'user':
355 353 RepoGroupModel().grant_user_permission(el, user=obj, perm=perm)
356 354 elif obj_type == 'user_group':
357 355 RepoGroupModel().grant_user_group_permission(el, group_name=obj, perm=perm)
358 356 else:
359 357 raise Exception('undefined object type %s' % obj_type)
360 358 elif isinstance(el, db.Repository):
361 359 # for repos we need to hotfix the name of permission
362 360 _perm = perm.permission_name.replace('group.', 'repository.')
363 361 if obj_type == 'user':
364 362 repo.RepoModel().grant_user_permission(el, user=obj, perm=_perm)
365 363 elif obj_type == 'user_group':
366 364 repo.RepoModel().grant_user_group_permission(el, group_name=obj, perm=_perm)
367 365 else:
368 366 raise Exception('undefined object type %s' % obj_type)
369 367 else:
370 368 raise Exception('el should be instance of Repository or '
371 369 'RepositoryGroup got %s instead' % type(el))
372 370
373 371 # if it's not recursive call for all,repos,groups
374 372 # break the loop and don't proceed with other changes
375 373 if recursive not in ['all', 'repos', 'groups']:
376 374 break
377 375
378 376 def delete_permission(self, repo_group, obj, obj_type, recursive):
379 377 """
380 378 Revokes permission for repo_group for given obj(user or users_group),
381 379 obj_type can be user or user group
382 380
383 381 :param repo_group:
384 382 :param obj: user or user group id
385 383 :param obj_type: user or user group type
386 384 :param recursive: recurse to all children of group
387 385 """
388 386 repo_group = db.RepoGroup.guess_instance(repo_group)
389 387
390 388 for el in repo_group.recursive_groups_and_repos():
391 389 # iterated obj is an instance of a repos group or repository in
392 390 # that group, recursive option can be: none, repos, groups, all
393 391 if recursive == 'all':
394 392 pass
395 393 elif recursive == 'repos':
396 394 # skip groups, other than this one
397 395 if isinstance(el, db.RepoGroup) and not el == repo_group:
398 396 continue
399 397 elif recursive == 'groups':
400 398 # skip repos
401 399 if isinstance(el, db.Repository):
402 400 continue
403 401 else: # recursive == 'none': # DEFAULT don't apply to iterated objects
404 402 el = repo_group
405 403 # also we do a break at the end of this loop.
406 404
407 405 if isinstance(el, db.RepoGroup):
408 406 if obj_type == 'user':
409 407 RepoGroupModel().revoke_user_permission(el, user=obj)
410 408 elif obj_type == 'user_group':
411 409 RepoGroupModel().revoke_user_group_permission(el, group_name=obj)
412 410 else:
413 411 raise Exception('undefined object type %s' % obj_type)
414 412 elif isinstance(el, db.Repository):
415 413 if obj_type == 'user':
416 414 repo.RepoModel().revoke_user_permission(el, user=obj)
417 415 elif obj_type == 'user_group':
418 416 repo.RepoModel().revoke_user_group_permission(el, group_name=obj)
419 417 else:
420 418 raise Exception('undefined object type %s' % obj_type)
421 419 else:
422 420 raise Exception('el should be instance of Repository or '
423 421 'RepositoryGroup got %s instead' % type(el))
424 422
425 423 # if it's not recursive call for all,repos,groups
426 424 # break the loop and don't proceed with other changes
427 425 if recursive not in ['all', 'repos', 'groups']:
428 426 break
429 427
430 428 def grant_user_permission(self, repo_group, user, perm):
431 429 """
432 430 Grant permission for user on given repository group, or update
433 431 existing one if found
434 432
435 433 :param repo_group: Instance of RepoGroup, repositories_group_id,
436 434 or repositories_group name
437 435 :param user: Instance of User, user_id or username
438 436 :param perm: Instance of Permission, or permission_name
439 437 """
440 438
441 439 repo_group = db.RepoGroup.guess_instance(repo_group)
442 440 user = db.User.guess_instance(user)
443 441 permission = db.Permission.guess_instance(perm)
444 442
445 443 # check if we have that permission already
446 444 obj = db.UserRepoGroupToPerm.query() \
447 445 .filter(db.UserRepoGroupToPerm.user == user) \
448 446 .filter(db.UserRepoGroupToPerm.group == repo_group) \
449 447 .scalar()
450 448 if obj is None:
451 449 # create new !
452 450 obj = db.UserRepoGroupToPerm()
453 451 meta.Session().add(obj)
454 452 obj.group = repo_group
455 453 obj.user = user
456 454 obj.permission = permission
457 455 log.debug('Granted perm %s to %s on %s', perm, user, repo_group)
458 456 return obj
459 457
460 458 def revoke_user_permission(self, repo_group, user):
461 459 """
462 460 Revoke permission for user on given repository group
463 461
464 462 :param repo_group: Instance of RepoGroup, repositories_group_id,
465 463 or repositories_group name
466 464 :param user: Instance of User, user_id or username
467 465 """
468 466
469 467 repo_group = db.RepoGroup.guess_instance(repo_group)
470 468 user = db.User.guess_instance(user)
471 469
472 470 obj = db.UserRepoGroupToPerm.query() \
473 471 .filter(db.UserRepoGroupToPerm.user == user) \
474 472 .filter(db.UserRepoGroupToPerm.group == repo_group) \
475 473 .scalar()
476 474 if obj is not None:
477 475 meta.Session().delete(obj)
478 476 log.debug('Revoked perm on %s on %s', repo_group, user)
479 477
480 478 def grant_user_group_permission(self, repo_group, group_name, perm):
481 479 """
482 480 Grant permission for user group on given repository group, or update
483 481 existing one if found
484 482
485 483 :param repo_group: Instance of RepoGroup, repositories_group_id,
486 484 or repositories_group name
487 485 :param group_name: Instance of UserGroup, users_group_id,
488 486 or user group name
489 487 :param perm: Instance of Permission, or permission_name
490 488 """
491 489 repo_group = db.RepoGroup.guess_instance(repo_group)
492 490 group_name = db.UserGroup.guess_instance(group_name)
493 491 permission = db.Permission.guess_instance(perm)
494 492
495 493 # check if we have that permission already
496 494 obj = db.UserGroupRepoGroupToPerm.query() \
497 495 .filter(db.UserGroupRepoGroupToPerm.group == repo_group) \
498 496 .filter(db.UserGroupRepoGroupToPerm.users_group == group_name) \
499 497 .scalar()
500 498
501 499 if obj is None:
502 500 # create new
503 501 obj = db.UserGroupRepoGroupToPerm()
504 502 meta.Session().add(obj)
505 503
506 504 obj.group = repo_group
507 505 obj.users_group = group_name
508 506 obj.permission = permission
509 507 log.debug('Granted perm %s to %s on %s', perm, group_name, repo_group)
510 508 return obj
511 509
512 510 def revoke_user_group_permission(self, repo_group, group_name):
513 511 """
514 512 Revoke permission for user group on given repository group
515 513
516 514 :param repo_group: Instance of RepoGroup, repositories_group_id,
517 515 or repositories_group name
518 516 :param group_name: Instance of UserGroup, users_group_id,
519 517 or user group name
520 518 """
521 519 repo_group = db.RepoGroup.guess_instance(repo_group)
522 520 group_name = db.UserGroup.guess_instance(group_name)
523 521
524 522 obj = db.UserGroupRepoGroupToPerm.query() \
525 523 .filter(db.UserGroupRepoGroupToPerm.group == repo_group) \
526 524 .filter(db.UserGroupRepoGroupToPerm.users_group == group_name) \
527 525 .scalar()
528 526 if obj is not None:
529 527 meta.Session().delete(obj)
530 528 log.debug('Revoked perm to %s on %s', repo_group, group_name)
General Comments 0
You need to be logged in to leave comments. Login now