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 |
@@ -259,7 +259,7 b' class RepoModel(BaseModel):' | |||||
259 | defaults = repo_info.get_dict() |
|
259 | defaults = repo_info.get_dict() | |
260 | defaults['repo_name'] = repo_info.just_name |
|
260 | defaults['repo_name'] = repo_info.just_name | |
261 |
|
261 | |||
262 |
groups |
|
262 | groups = repo_info.groups_with_parents | |
263 | parent_group = groups[-1] if groups else None |
|
263 | parent_group = groups[-1] if groups else None | |
264 |
|
264 | |||
265 | # we use -1 as this is how in HTML, we mark an empty group |
|
265 | # we use -1 as this is how in HTML, we mark an empty group | |
@@ -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( |
|
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( |
|
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 |
# |
|
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 |
|
|
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 |
|
|
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. |
|
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( |
|
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. |
|
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