##// END OF EJS Templates
repo-permissions: moved permissions into pyramid....
marcink -
r1734:ddacc559 default
parent child Browse files
Show More
@@ -0,0 +1,98 b''
1 # -*- coding: utf-8 -*-
2
3 # Copyright (C) 2011-2017 RhodeCode GmbH
4 #
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
21 import logging
22
23 import deform
24 from pyramid.httpexceptions import HTTPFound
25 from pyramid.view import view_config
26
27 from rhodecode.apps._base import RepoAppView
28 from rhodecode.forms import RcForm
29 from rhodecode.lib import helpers as h
30 from rhodecode.lib import audit_logger
31 from rhodecode.lib.auth import (
32 LoginRequired, HasRepoPermissionAnyDecorator,
33 HasRepoPermissionAllDecorator, CSRFRequired)
34 from rhodecode.model.db import RepositoryField, RepoGroup
35 from rhodecode.model.forms import RepoPermsForm
36 from rhodecode.model.meta import Session
37 from rhodecode.model.repo import RepoModel
38 from rhodecode.model.scm import RepoGroupList, ScmModel
39 from rhodecode.model.validation_schema.schemas import repo_schema
40
41 log = logging.getLogger(__name__)
42
43
44 class RepoSettingsPermissionsView(RepoAppView):
45
46 def load_default_context(self):
47 c = self._get_local_tmpl_context()
48
49 # TODO(marcink): remove repo_info and use c.rhodecode_db_repo instead
50 c.repo_info = self.db_repo
51
52 self._register_global_c(c)
53 return c
54
55 @LoginRequired()
56 @HasRepoPermissionAnyDecorator('repository.admin')
57 @view_config(
58 route_name='edit_repo_perms', request_method='GET',
59 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
60 def edit_permissions(self):
61 c = self.load_default_context()
62 c.active = 'permissions'
63 return self._get_template_context(c)
64
65 @LoginRequired()
66 @HasRepoPermissionAllDecorator('repository.admin')
67 @CSRFRequired()
68 @view_config(
69 route_name='edit_repo_perms', request_method='POST',
70 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
71 def edit_permissions_update(self):
72 _ = self.request.translate
73 c = self.load_default_context()
74 c.active = 'permissions'
75 data = self.request.POST
76 # store private flag outside of HTML to verify if we can modify
77 # default user permissions, prevents submition of FAKE post data
78 # into the form for private repos
79 data['repo_private'] = self.db_repo.private
80 form = RepoPermsForm()().to_python(data)
81 changes = RepoModel().update_permissions(
82 self.db_repo_name, form['perm_additions'], form['perm_updates'],
83 form['perm_deletions'])
84
85 action_data = {
86 'added': changes['added'],
87 'updated': changes['updated'],
88 'deleted': changes['deleted'],
89 }
90 audit_logger.store(
91 'repo.edit.permissions', action_data=action_data,
92 user=self._rhodecode_user, repo=self.db_repo)
93
94 Session().commit()
95 h.flash(_('Repository permissions updated'), category='success')
96
97 raise HTTPFound(
98 self.request.route_path('edit_repo_perms', repo_name=self.db_repo_name))
@@ -31,6 +31,11 b' def includeme(config):'
31 name='edit_repo_caches',
31 name='edit_repo_caches',
32 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
32 pattern='/{repo_name:.*?[^/]}/settings/caches', repo_route=True)
33
33
34 # Permissions
35 config.add_route(
36 name='edit_repo_perms',
37 pattern='/{repo_name:.*?[^/]}/settings/permissions', repo_route=True)
38
34 # Repo Review Rules
39 # Repo Review Rules
35 config.add_route(
40 config.add_route(
36 name='repo_reviewers',
41 name='repo_reviewers',
@@ -39,6 +39,7 b' def route_path(name, params=None, **kwar'
39 base_url = {
39 base_url = {
40 'edit_repo': '/{repo_name}/settings',
40 'edit_repo': '/{repo_name}/settings',
41 'edit_repo_caches': '/{repo_name}/settings/caches',
41 'edit_repo_caches': '/{repo_name}/settings/caches',
42 'edit_repo_perms': '/{repo_name}/settings/permissions',
42 }[name].format(**kwargs)
43 }[name].format(**kwargs)
43
44
44 if params:
45 if params:
@@ -59,7 +60,8 b' def _get_permission_for_user(user, repo)'
59 class TestAdminRepoSettings(object):
60 class TestAdminRepoSettings(object):
60 @pytest.mark.parametrize('urlname', [
61 @pytest.mark.parametrize('urlname', [
61 'edit_repo',
62 'edit_repo',
62 'edit_repo_caches'
63 'edit_repo_caches',
64 'edit_repo_perms',
63 ])
65 ])
64 def test_show_page(self, urlname, app, backend):
66 def test_show_page(self, urlname, app, backend):
65 app.get(route_path(urlname, repo_name=backend.repo_name), status=200)
67 app.get(route_path(urlname, repo_name=backend.repo_name), status=200)
@@ -72,7 +74,6 b' class TestAdminRepoSettings(object):'
72 self.app.get(route_path('edit_repo', repo_name=backend_hg.repo_name))
74 self.app.get(route_path('edit_repo', repo_name=backend_hg.repo_name))
73
75
74 @pytest.mark.parametrize('urlname', [
76 @pytest.mark.parametrize('urlname', [
75 'edit_repo_perms',
76 'edit_repo_advanced',
77 'edit_repo_advanced',
77 'repo_vcs_settings',
78 'repo_vcs_settings',
78 'edit_repo_fields',
79 'edit_repo_fields',
@@ -661,16 +661,6 b' def make_map(config):'
661 requirements=URL_NAME_REQUIREMENTS)
661 requirements=URL_NAME_REQUIREMENTS)
662
662
663 # repo edit options
663 # repo edit options
664 rmap.connect('edit_repo_perms', '/{repo_name}/settings/permissions',
665 jsroute=True,
666 controller='admin/repos', action='edit_permissions',
667 conditions={'method': ['GET'], 'function': check_repo},
668 requirements=URL_NAME_REQUIREMENTS)
669 rmap.connect('edit_repo_perms_update', '/{repo_name}/settings/permissions',
670 controller='admin/repos', action='edit_permissions_update',
671 conditions={'method': ['PUT'], 'function': check_repo},
672 requirements=URL_NAME_REQUIREMENTS)
673
674 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
664 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
675 controller='admin/repos', action='edit_fields',
665 controller='admin/repos', action='edit_fields',
676 conditions={'method': ['GET'], 'function': check_repo},
666 conditions={'method': ['GET'], 'function': check_repo},
@@ -339,33 +339,6 b' class ReposController(BaseRepoController'
339 # url('repo', repo_name=ID)
339 # url('repo', repo_name=ID)
340
340
341 @HasRepoPermissionAllDecorator('repository.admin')
341 @HasRepoPermissionAllDecorator('repository.admin')
342 def edit_permissions(self, repo_name):
343 """GET /repo_name/settings: Form to edit an existing item"""
344 c.repo_info = self._load_repo(repo_name)
345 c.active = 'permissions'
346 defaults = RepoModel()._get_defaults(repo_name)
347
348 return htmlfill.render(
349 render('admin/repos/repo_edit.mako'),
350 defaults=defaults,
351 encoding="UTF-8",
352 force_defaults=False)
353
354 @HasRepoPermissionAllDecorator('repository.admin')
355 @auth.CSRFRequired()
356 def edit_permissions_update(self, repo_name):
357 form = RepoPermsForm()().to_python(request.POST)
358 RepoModel().update_permissions(repo_name,
359 form['perm_additions'], form['perm_updates'], form['perm_deletions'])
360
361 #TODO: implement this
362 #action_logger(c.rhodecode_user, 'admin_changed_repo_permissions',
363 # repo_name, self.ip_addr, self.sa)
364 Session().commit()
365 h.flash(_('Repository permissions updated'), category='success')
366 return redirect(url('edit_repo_perms', repo_name=repo_name))
367
368 @HasRepoPermissionAllDecorator('repository.admin')
369 def edit_fields(self, repo_name):
342 def edit_fields(self, repo_name):
370 """GET /repo_name/settings: Form to edit an existing item"""
343 """GET /repo_name/settings: Form to edit an existing item"""
371 c.repo_info = self._load_repo(repo_name)
344 c.repo_info = self._load_repo(repo_name)
@@ -36,6 +36,7 b' ACTIONS = {'
36
36
37 'repo.add': {},
37 'repo.add': {},
38 'repo.edit': {},
38 'repo.edit': {},
39 'repo.edit.permissions': {},
39 'repo.commit.strip': {}
40 'repo.commit.strip': {}
40 }
41 }
41
42
@@ -295,16 +295,6 b' class RepoModel(BaseModel):'
295 replacement_user = User.get_first_super_admin().username
295 replacement_user = User.get_first_super_admin().username
296 defaults.update({'user': replacement_user})
296 defaults.update({'user': replacement_user})
297
297
298 # fill repository users
299 for p in repo_info.repo_to_perm:
300 defaults.update({'u_perm_%s' % p.user.user_id:
301 p.permission.permission_name})
302
303 # fill repository groups
304 for p in repo_info.users_group_to_perm:
305 defaults.update({'g_perm_%s' % p.users_group.users_group_id:
306 p.permission.permission_name})
307
308 return defaults
298 return defaults
309
299
310 def update(self, repo, **kwargs):
300 def update(self, repo, **kwargs):
@@ -507,10 +497,16 b' class RepoModel(BaseModel):'
507
497
508 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
498 req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin')
509
499
500 changes = {
501 'added': [],
502 'updated': [],
503 'deleted': []
504 }
510 # update permissions
505 # update permissions
511 for member_id, perm, member_type in perm_updates:
506 for member_id, perm, member_type in perm_updates:
512 member_id = int(member_id)
507 member_id = int(member_id)
513 if member_type == 'user':
508 if member_type == 'user':
509 member_name = User.get(member_id).username
514 # this updates also current one if found
510 # this updates also current one if found
515 self.grant_user_permission(
511 self.grant_user_permission(
516 repo=repo, user=member_id, perm=perm)
512 repo=repo, user=member_id, perm=perm)
@@ -522,10 +518,14 b' class RepoModel(BaseModel):'
522 self.grant_user_group_permission(
518 self.grant_user_group_permission(
523 repo=repo, group_name=member_id, perm=perm)
519 repo=repo, group_name=member_id, perm=perm)
524
520
521 changes['updated'].append({'type': member_type, 'id': member_id,
522 'name': member_name, 'new_perm': perm})
523
525 # set new permissions
524 # set new permissions
526 for member_id, perm, member_type in perm_additions:
525 for member_id, perm, member_type in perm_additions:
527 member_id = int(member_id)
526 member_id = int(member_id)
528 if member_type == 'user':
527 if member_type == 'user':
528 member_name = User.get(member_id).username
529 self.grant_user_permission(
529 self.grant_user_permission(
530 repo=repo, user=member_id, perm=perm)
530 repo=repo, user=member_id, perm=perm)
531 else: # set for user group
531 else: # set for user group
@@ -535,11 +535,13 b' class RepoModel(BaseModel):'
535 *req_perms)(member_name, user=cur_user):
535 *req_perms)(member_name, user=cur_user):
536 self.grant_user_group_permission(
536 self.grant_user_group_permission(
537 repo=repo, group_name=member_id, perm=perm)
537 repo=repo, group_name=member_id, perm=perm)
538
538 changes['added'].append({'type': member_type, 'id': member_id,
539 'name': member_name, 'new_perm': perm})
539 # delete permissions
540 # delete permissions
540 for member_id, perm, member_type in perm_deletions:
541 for member_id, perm, member_type in perm_deletions:
541 member_id = int(member_id)
542 member_id = int(member_id)
542 if member_type == 'user':
543 if member_type == 'user':
544 member_name = User.get(member_id).username
543 self.revoke_user_permission(repo=repo, user=member_id)
545 self.revoke_user_permission(repo=repo, user=member_id)
544 else: # set for user group
546 else: # set for user group
545 # check if we have permissions to alter this usergroup
547 # check if we have permissions to alter this usergroup
@@ -549,6 +551,10 b' class RepoModel(BaseModel):'
549 self.revoke_user_group_permission(
551 self.revoke_user_group_permission(
550 repo=repo, group_name=member_id)
552 repo=repo, group_name=member_id)
551
553
554 changes['deleted'].append({'type': member_type, 'id': member_id,
555 'name': member_name, 'new_perm': perm})
556 return changes
557
552 def create_fork(self, form_data, cur_user):
558 def create_fork(self, form_data, cur_user):
553 """
559 """
554 Simple wrapper into executing celery task for fork creation
560 Simple wrapper into executing celery task for fork creation
@@ -784,7 +784,8 b" def ValidPerms(type_='repo'):"
784 del_member = perm_dict.get('id')
784 del_member = perm_dict.get('id')
785 del_type = perm_dict.get('type')
785 del_type = perm_dict.get('type')
786 if del_member and del_type:
786 if del_member and del_type:
787 perm_deletions.add((del_member, None, del_type))
787 perm_deletions.add(
788 (del_member, None, del_type))
788
789
789 # store additions in order of how they were added in web form
790 # store additions in order of how they were added in web form
790 for k in sorted(new_perms_group.keys()):
791 for k in sorted(new_perms_group.keys()):
@@ -793,36 +794,48 b" def ValidPerms(type_='repo'):"
793 new_type = perm_dict.get('type')
794 new_type = perm_dict.get('type')
794 new_perm = perm_dict.get('perm')
795 new_perm = perm_dict.get('perm')
795 if new_member and new_perm and new_type:
796 if new_member and new_perm and new_type:
796 perm_additions.add((new_member, new_perm, new_type))
797 perm_additions.add(
798 (new_member, new_perm, new_type))
797
799
798 # get updates of permissions
800 # get updates of permissions
799 # (read the existing radio button states)
801 # (read the existing radio button states)
802 default_user_id = User.get_default_user().user_id
800 for k, update_value in value.iteritems():
803 for k, update_value in value.iteritems():
801 if k.startswith('u_perm_') or k.startswith('g_perm_'):
804 if k.startswith('u_perm_') or k.startswith('g_perm_'):
802 member = k[7:]
805 member = k[7:]
803 update_type = {'u': 'user',
806 update_type = {'u': 'user',
804 'g': 'users_group'}[k[0]]
807 'g': 'users_group'}[k[0]]
805 if member == User.DEFAULT_USER:
808
809 if safe_int(member) == default_user_id:
806 if str2bool(value.get('repo_private')):
810 if str2bool(value.get('repo_private')):
807 # set none for default when updating to
811 # prevent from updating default user permissions
808 # private repo protects agains form manipulation
812 # when this repository is marked as private
809 update_value = EMPTY_PERM
813 update_value = EMPTY_PERM
810 perm_updates.add((member, update_value, update_type))
811 # check the deletes
812
814
813 value['perm_additions'] = list(perm_additions)
815 perm_updates.add(
816 (member, update_value, update_type))
817
818 value['perm_additions'] = [] # propagated later
814 value['perm_updates'] = list(perm_updates)
819 value['perm_updates'] = list(perm_updates)
815 value['perm_deletions'] = list(perm_deletions)
820 value['perm_deletions'] = list(perm_deletions)
816
821
817 # validate users they exist and they are active !
822 updates_map = dict(
818 for member_id, _perm, member_type in perm_additions:
823 (x[0], (x[1], x[2])) for x in value['perm_updates'])
824 # make sure Additions don't override updates.
825 for member_id, perm, member_type in list(perm_additions):
826 if member_id in updates_map:
827 perm = updates_map[member_id][0]
828 value['perm_additions'].append((member_id, perm, member_type))
829
830 # on new entries validate users they exist and they are active !
831 # this leaves feedback to the form
819 try:
832 try:
820 if member_type == 'user':
833 if member_type == 'user':
821 self.user_db = User.query()\
834 User.query()\
822 .filter(User.active == true())\
835 .filter(User.active == true())\
823 .filter(User.user_id == member_id).one()
836 .filter(User.user_id == member_id).one()
824 if member_type == 'users_group':
837 if member_type == 'users_group':
825 self.user_db = UserGroup.query()\
838 UserGroup.query()\
826 .filter(UserGroup.users_group_active == true())\
839 .filter(UserGroup.users_group_active == true())\
827 .filter(UserGroup.users_group_id == member_id)\
840 .filter(UserGroup.users_group_id == member_id)\
828 .one()
841 .one()
@@ -24,7 +24,6 b' function registerRCRoutes() {'
24 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
24 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
25 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/default-reviewers', ['repo_name']);
25 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/default-reviewers', ['repo_name']);
26 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
26 pyroutes.register('changeset_home', '/%(repo_name)s/changeset/%(revision)s', ['repo_name', 'revision']);
27 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
28 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
27 pyroutes.register('changeset_comment', '/%(repo_name)s/changeset/%(revision)s/comment', ['repo_name', 'revision']);
29 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
28 pyroutes.register('changeset_comment_preview', '/%(repo_name)s/changeset/comment/preview', ['repo_name']);
30 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
29 pyroutes.register('changeset_comment_delete', '/%(repo_name)s/changeset/comment/%(comment_id)s/delete', ['repo_name', 'comment_id']);
@@ -99,6 +98,7 b' function registerRCRoutes() {'
99 pyroutes.register('goto_switcher_data', '/_goto_data', []);
98 pyroutes.register('goto_switcher_data', '/_goto_data', []);
100 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
99 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
101 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
100 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
101 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
102 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
102 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
103 pyroutes.register('repo_maintenance', '/%(repo_name)s/maintenance', ['repo_name']);
103 pyroutes.register('repo_maintenance', '/%(repo_name)s/maintenance', ['repo_name']);
104 pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/maintenance/execute', ['repo_name']);
104 pyroutes.register('repo_maintenance_execute', '/%(repo_name)s/maintenance/execute', ['repo_name']);
@@ -42,7 +42,7 b''
42 <a href="${h.route_path('edit_repo', repo_name=c.repo_name)}">${_('Settings')}</a>
42 <a href="${h.route_path('edit_repo', repo_name=c.repo_name)}">${_('Settings')}</a>
43 </li>
43 </li>
44 <li class="${'active' if c.active=='permissions' else ''}">
44 <li class="${'active' if c.active=='permissions' else ''}">
45 <a href="${h.url('edit_repo_perms', repo_name=c.repo_name)}">${_('Permissions')}</a>
45 <a href="${h.route_path('edit_repo_perms', repo_name=c.repo_name)}">${_('Permissions')}</a>
46 </li>
46 </li>
47 <li class="${'active' if c.active=='advanced' else ''}">
47 <li class="${'active' if c.active=='advanced' else ''}">
48 <a href="${h.url('edit_repo_advanced', repo_name=c.repo_name)}">${_('Advanced')}</a>
48 <a href="${h.url('edit_repo_advanced', repo_name=c.repo_name)}">${_('Advanced')}</a>
@@ -5,8 +5,7 b''
5 <h3 class="panel-title">${_('Repository Permissions')}</h3>
5 <h3 class="panel-title">${_('Repository Permissions')}</h3>
6 </div>
6 </div>
7 <div class="panel-body">
7 <div class="panel-body">
8 ${h.secure_form(url('edit_repo_perms_update', repo_name=c.repo_name), method='put')}
8 ${h.secure_form(h.route_path('edit_repo_perms', repo_name=c.repo_name), method='POST')}
9 ${h.hidden('repo_private')}
10 <table id="permissions_manage" class="rctable permissions">
9 <table id="permissions_manage" class="rctable permissions">
11 <tr>
10 <tr>
12 <th class="td-radio">${_('None')}</th>
11 <th class="td-radio">${_('None')}</th>
@@ -40,7 +39,7 b''
40 <tr>
39 <tr>
41 <td colspan="4">
40 <td colspan="4">
42 <span class="private_repo_msg">
41 <span class="private_repo_msg">
43 <strong>${_('private repository')}</strong>
42 <strong title="${_user.permission}">${_('private repository')}</strong>
44 </span>
43 </span>
45 </td>
44 </td>
46 <td class="private_repo_msg">
45 <td class="private_repo_msg">
@@ -50,10 +49,10 b''
50 </tr>
49 </tr>
51 %else:
50 %else:
52 <tr>
51 <tr>
53 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.none')}</td>
52 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.none', checked=_user.permission=='repository.none')}</td>
54 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.read')}</td>
53 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.read', checked=_user.permission=='repository.read')}</td>
55 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.write')}</td>
54 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.write', checked=_user.permission=='repository.write')}</td>
56 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.admin')}</td>
55 <td class="td-radio">${h.radio('u_perm_%s' % _user.user_id,'repository.admin', checked=_user.permission=='repository.admin')}</td>
57 <td class="td-user">
56 <td class="td-user">
58 ${base.gravatar(_user.email, 16)}
57 ${base.gravatar(_user.email, 16)}
59 <span class="user">
58 <span class="user">
@@ -79,10 +78,10 b''
79 ## USER GROUPS
78 ## USER GROUPS
80 %for _user_group in c.repo_info.permission_user_groups():
79 %for _user_group in c.repo_info.permission_user_groups():
81 <tr>
80 <tr>
82 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.none')}</td>
81 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.none', checked=_user_group.permission=='repository.none')}</td>
83 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.read')}</td>
82 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.read', checked=_user_group.permission=='repository.read')}</td>
84 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.write')}</td>
83 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.write', checked=_user_group.permission=='repository.write')}</td>
85 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.admin')}</td>
84 <td class="td-radio">${h.radio('g_perm_%s' % _user_group.users_group_id,'repository.admin', checked=_user_group.permission=='repository.admin')}</td>
86 <td class="td-componentname">
85 <td class="td-componentname">
87 <i class="icon-group" ></i>
86 <i class="icon-group" ></i>
88 %if h.HasPermissionAny('hg.admin')():
87 %if h.HasPermissionAny('hg.admin')():
@@ -146,7 +146,7 b''
146 %if actions:
146 %if actions:
147 <td class="td-action">
147 <td class="td-action">
148 %if section == 'repositories':
148 %if section == 'repositories':
149 <a href="${h.url('edit_repo_perms',repo_name=k,anchor='permissions_manage')}">${_('edit')}</a>
149 <a href="${h.route_path('edit_repo_perms',repo_name=k,anchor='permissions_manage')}">${_('edit')}</a>
150 %elif section == 'repositories_groups':
150 %elif section == 'repositories_groups':
151 <a href="${h.url('edit_repo_group_perms',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
151 <a href="${h.url('edit_repo_group_perms',group_name=k,anchor='permissions_manage')}">${_('edit')}</a>
152 %elif section == 'user_groups':
152 %elif section == 'user_groups':
General Comments 0
You need to be logged in to leave comments. Login now