##// END OF EJS Templates
branch-permissions: fixed override of default permissions for branches from admin page
marcink -
r2988:390bbe68 default
parent child Browse files
Show More
@@ -1,557 +1,558 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 permissions model for RhodeCode
23 23 """
24 24
25 25
26 26 import logging
27 27 import traceback
28 28
29 29 from sqlalchemy.exc import DatabaseError
30 30
31 31 from rhodecode.model import BaseModel
32 32 from rhodecode.model.db import (
33 33 User, Permission, UserToPerm, UserRepoToPerm, UserRepoGroupToPerm,
34 34 UserUserGroupToPerm, UserGroup, UserGroupToPerm, UserToRepoBranchPermission)
35 35 from rhodecode.lib.utils2 import str2bool, safe_int
36 36
37 37 log = logging.getLogger(__name__)
38 38
39 39
40 40 class PermissionModel(BaseModel):
41 41 """
42 42 Permissions model for RhodeCode
43 43 """
44 44
45 45 cls = Permission
46 46 global_perms = {
47 47 'default_repo_create': None,
48 48 # special case for create repos on write access to group
49 49 'default_repo_create_on_write': None,
50 50 'default_repo_group_create': None,
51 51 'default_user_group_create': None,
52 52 'default_fork_create': None,
53 53 'default_inherit_default_permissions': None,
54 54 'default_register': None,
55 55 'default_password_reset': None,
56 56 'default_extern_activate': None,
57 57
58 58 # object permissions below
59 59 'default_repo_perm': None,
60 60 'default_group_perm': None,
61 61 'default_user_group_perm': None,
62 62
63 63 # branch
64 64 'default_branch_perm': None,
65 65 }
66 66
67 67 def set_global_permission_choices(self, c_obj, gettext_translator):
68 68 _ = gettext_translator
69 69
70 70 c_obj.repo_perms_choices = [
71 71 ('repository.none', _('None'),),
72 72 ('repository.read', _('Read'),),
73 73 ('repository.write', _('Write'),),
74 74 ('repository.admin', _('Admin'),)]
75 75
76 76 c_obj.group_perms_choices = [
77 77 ('group.none', _('None'),),
78 78 ('group.read', _('Read'),),
79 79 ('group.write', _('Write'),),
80 80 ('group.admin', _('Admin'),)]
81 81
82 82 c_obj.user_group_perms_choices = [
83 83 ('usergroup.none', _('None'),),
84 84 ('usergroup.read', _('Read'),),
85 85 ('usergroup.write', _('Write'),),
86 86 ('usergroup.admin', _('Admin'),)]
87 87
88 88 c_obj.branch_perms_choices = [
89 89 ('branch.none', _('Protected/No Access'),),
90 90 ('branch.merge', _('Web merge'),),
91 91 ('branch.push', _('Push'),),
92 92 ('branch.push_force', _('Force Push'),)]
93 93
94 94 c_obj.register_choices = [
95 95 ('hg.register.none', _('Disabled')),
96 96 ('hg.register.manual_activate', _('Allowed with manual account activation')),
97 97 ('hg.register.auto_activate', _('Allowed with automatic account activation')),]
98 98
99 99 c_obj.password_reset_choices = [
100 100 ('hg.password_reset.enabled', _('Allow password recovery')),
101 101 ('hg.password_reset.hidden', _('Hide password recovery link')),
102 102 ('hg.password_reset.disabled', _('Disable password recovery')),]
103 103
104 104 c_obj.extern_activate_choices = [
105 105 ('hg.extern_activate.manual', _('Manual activation of external account')),
106 106 ('hg.extern_activate.auto', _('Automatic activation of external account')),]
107 107
108 108 c_obj.repo_create_choices = [
109 109 ('hg.create.none', _('Disabled')),
110 110 ('hg.create.repository', _('Enabled'))]
111 111
112 112 c_obj.repo_create_on_write_choices = [
113 113 ('hg.create.write_on_repogroup.false', _('Disabled')),
114 114 ('hg.create.write_on_repogroup.true', _('Enabled'))]
115 115
116 116 c_obj.user_group_create_choices = [
117 117 ('hg.usergroup.create.false', _('Disabled')),
118 118 ('hg.usergroup.create.true', _('Enabled'))]
119 119
120 120 c_obj.repo_group_create_choices = [
121 121 ('hg.repogroup.create.false', _('Disabled')),
122 122 ('hg.repogroup.create.true', _('Enabled'))]
123 123
124 124 c_obj.fork_choices = [
125 125 ('hg.fork.none', _('Disabled')),
126 126 ('hg.fork.repository', _('Enabled'))]
127 127
128 128 c_obj.inherit_default_permission_choices = [
129 129 ('hg.inherit_default_perms.false', _('Disabled')),
130 130 ('hg.inherit_default_perms.true', _('Enabled'))]
131 131
132 132 def get_default_perms(self, object_perms, suffix):
133 133 defaults = {}
134 134 for perm in object_perms:
135 135 # perms
136 136 if perm.permission.permission_name.startswith('repository.'):
137 137 defaults['default_repo_perm' + suffix] = perm.permission.permission_name
138 138
139 139 if perm.permission.permission_name.startswith('group.'):
140 140 defaults['default_group_perm' + suffix] = perm.permission.permission_name
141 141
142 142 if perm.permission.permission_name.startswith('usergroup.'):
143 143 defaults['default_user_group_perm' + suffix] = perm.permission.permission_name
144 144
145 145 # branch
146 146 if perm.permission.permission_name.startswith('branch.'):
147 147 defaults['default_branch_perm' + suffix] = perm.permission.permission_name
148 148
149 149 # creation of objects
150 150 if perm.permission.permission_name.startswith('hg.create.write_on_repogroup'):
151 151 defaults['default_repo_create_on_write' + suffix] = perm.permission.permission_name
152 152
153 153 elif perm.permission.permission_name.startswith('hg.create.'):
154 154 defaults['default_repo_create' + suffix] = perm.permission.permission_name
155 155
156 156 if perm.permission.permission_name.startswith('hg.fork.'):
157 157 defaults['default_fork_create' + suffix] = perm.permission.permission_name
158 158
159 159 if perm.permission.permission_name.startswith('hg.inherit_default_perms.'):
160 160 defaults['default_inherit_default_permissions' + suffix] = perm.permission.permission_name
161 161
162 162 if perm.permission.permission_name.startswith('hg.repogroup.'):
163 163 defaults['default_repo_group_create' + suffix] = perm.permission.permission_name
164 164
165 165 if perm.permission.permission_name.startswith('hg.usergroup.'):
166 166 defaults['default_user_group_create' + suffix] = perm.permission.permission_name
167 167
168 168 # registration and external account activation
169 169 if perm.permission.permission_name.startswith('hg.register.'):
170 170 defaults['default_register' + suffix] = perm.permission.permission_name
171 171
172 172 if perm.permission.permission_name.startswith('hg.password_reset.'):
173 173 defaults['default_password_reset' + suffix] = perm.permission.permission_name
174 174
175 175 if perm.permission.permission_name.startswith('hg.extern_activate.'):
176 176 defaults['default_extern_activate' + suffix] = perm.permission.permission_name
177 177
178 178 return defaults
179 179
180 180 def _make_new_user_perm(self, user, perm_name):
181 181 log.debug('Creating new user permission:%s', perm_name)
182 182 new = UserToPerm()
183 183 new.user = user
184 184 new.permission = Permission.get_by_key(perm_name)
185 185 return new
186 186
187 187 def _make_new_user_group_perm(self, user_group, perm_name):
188 188 log.debug('Creating new user group permission:%s', perm_name)
189 189 new = UserGroupToPerm()
190 190 new.users_group = user_group
191 191 new.permission = Permission.get_by_key(perm_name)
192 192 return new
193 193
194 194 def _keep_perm(self, perm_name, keep_fields):
195 195 def get_pat(field_name):
196 196 return {
197 197 # global perms
198 198 'default_repo_create': 'hg.create.',
199 199 # special case for create repos on write access to group
200 200 'default_repo_create_on_write': 'hg.create.write_on_repogroup.',
201 201 'default_repo_group_create': 'hg.repogroup.create.',
202 202 'default_user_group_create': 'hg.usergroup.create.',
203 203 'default_fork_create': 'hg.fork.',
204 204 'default_inherit_default_permissions': 'hg.inherit_default_perms.',
205 205
206 206 # application perms
207 207 'default_register': 'hg.register.',
208 208 'default_password_reset': 'hg.password_reset.',
209 209 'default_extern_activate': 'hg.extern_activate.',
210 210
211 211 # object permissions below
212 212 'default_repo_perm': 'repository.',
213 213 'default_group_perm': 'group.',
214 214 'default_user_group_perm': 'usergroup.',
215 215 # branch
216 216 'default_branch_perm': 'branch.',
217 217
218 218 }[field_name]
219 219 for field in keep_fields:
220 220 pat = get_pat(field)
221 221 if perm_name.startswith(pat):
222 222 return True
223 223 return False
224 224
225 225 def _clear_object_perm(self, object_perms, preserve=None):
226 226 preserve = preserve or []
227 227 _deleted = []
228 228 for perm in object_perms:
229 229 perm_name = perm.permission.permission_name
230 230 if not self._keep_perm(perm_name, keep_fields=preserve):
231 231 _deleted.append(perm_name)
232 232 self.sa.delete(perm)
233 233 return _deleted
234 234
235 235 def _clear_user_perms(self, user_id, preserve=None):
236 236 perms = self.sa.query(UserToPerm)\
237 237 .filter(UserToPerm.user_id == user_id)\
238 238 .all()
239 239 return self._clear_object_perm(perms, preserve=preserve)
240 240
241 241 def _clear_user_group_perms(self, user_group_id, preserve=None):
242 242 perms = self.sa.query(UserGroupToPerm)\
243 243 .filter(UserGroupToPerm.users_group_id == user_group_id)\
244 244 .all()
245 245 return self._clear_object_perm(perms, preserve=preserve)
246 246
247 247 def _set_new_object_perms(self, obj_type, object, form_result, preserve=None):
248 248 # clear current entries, to make this function idempotent
249 249 # it will fix even if we define more permissions or permissions
250 250 # are somehow missing
251 251 preserve = preserve or []
252 252 _global_perms = self.global_perms.copy()
253 253 if obj_type not in ['user', 'user_group']:
254 254 raise ValueError("obj_type must be on of 'user' or 'user_group'")
255 255 global_perms = len(_global_perms)
256 256 default_user_perms = len(Permission.DEFAULT_USER_PERMISSIONS)
257 257 if global_perms != default_user_perms:
258 258 raise Exception(
259 259 'Inconsistent permissions definition. Got {} vs {}'.format(
260 260 global_perms, default_user_perms))
261 261
262 262 if obj_type == 'user':
263 263 self._clear_user_perms(object.user_id, preserve)
264 264 if obj_type == 'user_group':
265 265 self._clear_user_group_perms(object.users_group_id, preserve)
266 266
267 267 # now kill the keys that we want to preserve from the form.
268 268 for key in preserve:
269 269 del _global_perms[key]
270 270
271 271 for k in _global_perms.copy():
272 272 _global_perms[k] = form_result[k]
273 273
274 274 # at that stage we validate all are passed inside form_result
275 275 for _perm_key, perm_value in _global_perms.items():
276 276 if perm_value is None:
277 277 raise ValueError('Missing permission for %s' % (_perm_key,))
278 278
279 279 if obj_type == 'user':
280 280 p = self._make_new_user_perm(object, perm_value)
281 281 self.sa.add(p)
282 282 if obj_type == 'user_group':
283 283 p = self._make_new_user_group_perm(object, perm_value)
284 284 self.sa.add(p)
285 285
286 286 def _set_new_user_perms(self, user, form_result, preserve=None):
287 287 return self._set_new_object_perms(
288 288 'user', user, form_result, preserve)
289 289
290 290 def _set_new_user_group_perms(self, user_group, form_result, preserve=None):
291 291 return self._set_new_object_perms(
292 292 'user_group', user_group, form_result, preserve)
293 293
294 294 def set_new_user_perms(self, user, form_result):
295 295 # calculate what to preserve from what is given in form_result
296 296 preserve = set(self.global_perms.keys()).difference(set(form_result.keys()))
297 297 return self._set_new_user_perms(user, form_result, preserve)
298 298
299 299 def set_new_user_group_perms(self, user_group, form_result):
300 300 # calculate what to preserve from what is given in form_result
301 301 preserve = set(self.global_perms.keys()).difference(set(form_result.keys()))
302 302 return self._set_new_user_group_perms(user_group, form_result, preserve)
303 303
304 304 def create_permissions(self):
305 305 """
306 306 Create permissions for whole system
307 307 """
308 308 for p in Permission.PERMS:
309 309 if not Permission.get_by_key(p[0]):
310 310 new_perm = Permission()
311 311 new_perm.permission_name = p[0]
312 312 new_perm.permission_longname = p[0] # translation err with p[1]
313 313 self.sa.add(new_perm)
314 314
315 315 def _create_default_object_permission(self, obj_type, obj, obj_perms,
316 316 force=False):
317 317 if obj_type not in ['user', 'user_group']:
318 318 raise ValueError("obj_type must be on of 'user' or 'user_group'")
319 319
320 320 def _get_group(perm_name):
321 321 return '.'.join(perm_name.split('.')[:1])
322 322
323 323 defined_perms_groups = map(
324 324 _get_group, (x.permission.permission_name for x in obj_perms))
325 325 log.debug('GOT ALREADY DEFINED:%s', obj_perms)
326 326
327 327 if force:
328 328 self._clear_object_perm(obj_perms)
329 329 self.sa.commit()
330 330 defined_perms_groups = []
331 331 # for every default permission that needs to be created, we check if
332 332 # it's group is already defined, if it's not we create default perm
333 333 for perm_name in Permission.DEFAULT_USER_PERMISSIONS:
334 334 gr = _get_group(perm_name)
335 335 if gr not in defined_perms_groups:
336 336 log.debug('GR:%s not found, creating permission %s',
337 337 gr, perm_name)
338 338 if obj_type == 'user':
339 339 new_perm = self._make_new_user_perm(obj, perm_name)
340 340 self.sa.add(new_perm)
341 341 if obj_type == 'user_group':
342 342 new_perm = self._make_new_user_group_perm(obj, perm_name)
343 343 self.sa.add(new_perm)
344 344
345 345 def create_default_user_permissions(self, user, force=False):
346 346 """
347 347 Creates only missing default permissions for user, if force is set it
348 348 resets the default permissions for that user
349 349
350 350 :param user:
351 351 :param force:
352 352 """
353 353 user = self._get_user(user)
354 354 obj_perms = UserToPerm.query().filter(UserToPerm.user == user).all()
355 355 return self._create_default_object_permission(
356 356 'user', user, obj_perms, force)
357 357
358 358 def create_default_user_group_permissions(self, user_group, force=False):
359 359 """
360 360 Creates only missing default permissions for user group, if force is
361 361 set it resets the default permissions for that user group
362 362
363 363 :param user_group:
364 364 :param force:
365 365 """
366 366 user_group = self._get_user_group(user_group)
367 367 obj_perms = UserToPerm.query().filter(UserGroupToPerm.users_group == user_group).all()
368 368 return self._create_default_object_permission(
369 369 'user_group', user_group, obj_perms, force)
370 370
371 371 def update_application_permissions(self, form_result):
372 372 if 'perm_user_id' in form_result:
373 373 perm_user = User.get(safe_int(form_result['perm_user_id']))
374 374 else:
375 375 # used mostly to do lookup for default user
376 376 perm_user = User.get_by_username(form_result['perm_user_name'])
377 377
378 378 try:
379 379 # stage 1 set anonymous access
380 380 if perm_user.username == User.DEFAULT_USER:
381 381 perm_user.active = str2bool(form_result['anonymous'])
382 382 self.sa.add(perm_user)
383 383
384 384 # stage 2 reset defaults and set them from form data
385 385 self._set_new_user_perms(perm_user, form_result, preserve=[
386 386 'default_repo_perm',
387 387 'default_group_perm',
388 388 'default_user_group_perm',
389 389 'default_branch_perm',
390 390
391 391 'default_repo_group_create',
392 392 'default_user_group_create',
393 393 'default_repo_create_on_write',
394 394 'default_repo_create',
395 395 'default_fork_create',
396 396 'default_inherit_default_permissions',])
397 397
398 398 self.sa.commit()
399 399 except (DatabaseError,):
400 400 log.error(traceback.format_exc())
401 401 self.sa.rollback()
402 402 raise
403 403
404 404 def update_user_permissions(self, form_result):
405 405 if 'perm_user_id' in form_result:
406 406 perm_user = User.get(safe_int(form_result['perm_user_id']))
407 407 else:
408 408 # used mostly to do lookup for default user
409 409 perm_user = User.get_by_username(form_result['perm_user_name'])
410 410 try:
411 411 # stage 2 reset defaults and set them from form data
412 412 self._set_new_user_perms(perm_user, form_result, preserve=[
413 413 'default_repo_perm',
414 414 'default_group_perm',
415 415 'default_user_group_perm',
416 416 'default_branch_perm',
417 417
418 418 'default_register',
419 419 'default_password_reset',
420 420 'default_extern_activate'])
421 421 self.sa.commit()
422 422 except (DatabaseError,):
423 423 log.error(traceback.format_exc())
424 424 self.sa.rollback()
425 425 raise
426 426
427 427 def update_user_group_permissions(self, form_result):
428 428 if 'perm_user_group_id' in form_result:
429 429 perm_user_group = UserGroup.get(safe_int(form_result['perm_user_group_id']))
430 430 else:
431 431 # used mostly to do lookup for default user
432 432 perm_user_group = UserGroup.get_by_group_name(form_result['perm_user_group_name'])
433 433 try:
434 434 # stage 2 reset defaults and set them from form data
435 435 self._set_new_user_group_perms(perm_user_group, form_result, preserve=[
436 436 'default_repo_perm',
437 437 'default_group_perm',
438 438 'default_user_group_perm',
439 439 'default_branch_perm',
440 440
441 441 'default_register',
442 442 'default_password_reset',
443 443 'default_extern_activate'])
444 444 self.sa.commit()
445 445 except (DatabaseError,):
446 446 log.error(traceback.format_exc())
447 447 self.sa.rollback()
448 448 raise
449 449
450 450 def update_object_permissions(self, form_result):
451 451 if 'perm_user_id' in form_result:
452 452 perm_user = User.get(safe_int(form_result['perm_user_id']))
453 453 else:
454 454 # used mostly to do lookup for default user
455 455 perm_user = User.get_by_username(form_result['perm_user_name'])
456 456 try:
457 457
458 458 # stage 2 reset defaults and set them from form data
459 459 self._set_new_user_perms(perm_user, form_result, preserve=[
460 460 'default_repo_group_create',
461 461 'default_user_group_create',
462 462 'default_repo_create_on_write',
463 463 'default_repo_create',
464 464 'default_fork_create',
465 465 'default_inherit_default_permissions',
466 466 'default_branch_perm',
467 467
468 468 'default_register',
469 469 'default_password_reset',
470 470 'default_extern_activate'])
471 471
472 472 # overwrite default repo permissions
473 473 if form_result['overwrite_default_repo']:
474 474 _def_name = form_result['default_repo_perm'].split('repository.')[-1]
475 475 _def = Permission.get_by_key('repository.' + _def_name)
476 476 for r2p in self.sa.query(UserRepoToPerm)\
477 477 .filter(UserRepoToPerm.user == perm_user)\
478 478 .all():
479 479 # don't reset PRIVATE repositories
480 480 if not r2p.repository.private:
481 481 r2p.permission = _def
482 482 self.sa.add(r2p)
483 483
484 484 # overwrite default repo group permissions
485 485 if form_result['overwrite_default_group']:
486 486 _def_name = form_result['default_group_perm'].split('group.')[-1]
487 487 _def = Permission.get_by_key('group.' + _def_name)
488 488 for g2p in self.sa.query(UserRepoGroupToPerm)\
489 489 .filter(UserRepoGroupToPerm.user == perm_user)\
490 490 .all():
491 491 g2p.permission = _def
492 492 self.sa.add(g2p)
493 493
494 494 # overwrite default user group permissions
495 495 if form_result['overwrite_default_user_group']:
496 496 _def_name = form_result['default_user_group_perm'].split('usergroup.')[-1]
497 497 # user groups
498 498 _def = Permission.get_by_key('usergroup.' + _def_name)
499 499 for g2p in self.sa.query(UserUserGroupToPerm)\
500 500 .filter(UserUserGroupToPerm.user == perm_user)\
501 501 .all():
502 502 g2p.permission = _def
503 503 self.sa.add(g2p)
504 504
505 505 # COMMIT
506 506 self.sa.commit()
507 507 except (DatabaseError,):
508 508 log.exception('Failed to set default object permissions')
509 509 self.sa.rollback()
510 510 raise
511 511
512 512 def update_branch_permissions(self, form_result):
513 513 if 'perm_user_id' in form_result:
514 514 perm_user = User.get(safe_int(form_result['perm_user_id']))
515 515 else:
516 516 # used mostly to do lookup for default user
517 517 perm_user = User.get_by_username(form_result['perm_user_name'])
518 518 try:
519 519
520 520 # stage 2 reset defaults and set them from form data
521 521 self._set_new_user_perms(perm_user, form_result, preserve=[
522 522 'default_repo_perm',
523 523 'default_group_perm',
524 524 'default_user_group_perm',
525 525
526 526 'default_repo_group_create',
527 527 'default_user_group_create',
528 528 'default_repo_create_on_write',
529 529 'default_repo_create',
530 530 'default_fork_create',
531 531 'default_inherit_default_permissions',
532 532
533 533 'default_register',
534 534 'default_password_reset',
535 535 'default_extern_activate'])
536 536
537 537 # overwrite default branch permissions
538 538 if form_result['overwrite_default_branch']:
539 539 _def_name = \
540 540 form_result['default_branch_perm'].split('branch.')[-1]
541 541
542 542 _def = Permission.get_by_key('branch.' + _def_name)
543 543
544 # TODO(marcink): those are bind to repo, perms, we need to unfold user somehow from this
545 for g2p in self.sa.query(UserToRepoBranchPermission) \
546 .filter(UserToRepoBranchPermission.user == perm_user) \
547 .all():
544 user_perms = UserToRepoBranchPermission.query()\
545 .join(UserToRepoBranchPermission.user_repo_to_perm)\
546 .filter(UserRepoToPerm.user == perm_user).all()
547
548 for g2p in user_perms:
548 549 g2p.permission = _def
549 550 self.sa.add(g2p)
550 551
551 552 # COMMIT
552 553 self.sa.commit()
553 554 except (DatabaseError,):
554 555 log.exception('Failed to set default branch permissions')
555 556 self.sa.rollback()
556 557 raise
557 558
General Comments 0
You need to be logged in to leave comments. Login now