##// END OF EJS Templates
caches: flush permission caches when editing affected objects so we can reach them right after changes.
marcink -
r2876:3939ff15 default
parent child Browse files
Show More
@@ -1,183 +1,189 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import deform
22 import deform
23
23
24 from pyramid.view import view_config
24 from pyramid.view import view_config
25 from pyramid.httpexceptions import HTTPFound
25 from pyramid.httpexceptions import HTTPFound
26
26
27 from rhodecode import events
27 from rhodecode.apps._base import RepoGroupAppView
28 from rhodecode.apps._base import RepoGroupAppView
28 from rhodecode.forms import RcForm
29 from rhodecode.forms import RcForm
29 from rhodecode.lib import helpers as h
30 from rhodecode.lib import helpers as h
30 from rhodecode.lib import audit_logger
31 from rhodecode.lib import audit_logger
31 from rhodecode.lib.auth import (
32 from rhodecode.lib.auth import (
32 LoginRequired, HasPermissionAll,
33 LoginRequired, HasPermissionAll,
33 HasRepoGroupPermissionAny, HasRepoGroupPermissionAnyDecorator, CSRFRequired)
34 HasRepoGroupPermissionAny, HasRepoGroupPermissionAnyDecorator, CSRFRequired)
34 from rhodecode.model.db import Session, RepoGroup
35 from rhodecode.model.db import Session, RepoGroup, User
35 from rhodecode.model.scm import RepoGroupList
36 from rhodecode.model.scm import RepoGroupList
36 from rhodecode.model.repo_group import RepoGroupModel
37 from rhodecode.model.repo_group import RepoGroupModel
37 from rhodecode.model.validation_schema.schemas import repo_group_schema
38 from rhodecode.model.validation_schema.schemas import repo_group_schema
38
39
39 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
40
41
41
42
42 class RepoGroupSettingsView(RepoGroupAppView):
43 class RepoGroupSettingsView(RepoGroupAppView):
43 def load_default_context(self):
44 def load_default_context(self):
44 c = self._get_local_tmpl_context()
45 c = self._get_local_tmpl_context()
45 c.repo_group = self.db_repo_group
46 c.repo_group = self.db_repo_group
46 no_parrent = not c.repo_group.parent_group
47 no_parrent = not c.repo_group.parent_group
47 can_create_in_root = self._can_create_repo_group()
48 can_create_in_root = self._can_create_repo_group()
48
49
49 show_root_location = False
50 show_root_location = False
50 if no_parrent or can_create_in_root:
51 if no_parrent or can_create_in_root:
51 # we're global admin, we're ok and we can create TOP level groups
52 # we're global admin, we're ok and we can create TOP level groups
52 # or in case this group is already at top-level we also allow
53 # or in case this group is already at top-level we also allow
53 # creation in root
54 # creation in root
54 show_root_location = True
55 show_root_location = True
55
56
56 acl_groups = RepoGroupList(
57 acl_groups = RepoGroupList(
57 RepoGroup.query().all(),
58 RepoGroup.query().all(),
58 perm_set=['group.admin'])
59 perm_set=['group.admin'])
59 c.repo_groups = RepoGroup.groups_choices(
60 c.repo_groups = RepoGroup.groups_choices(
60 groups=acl_groups,
61 groups=acl_groups,
61 show_empty_group=show_root_location)
62 show_empty_group=show_root_location)
62 # filter out current repo group
63 # filter out current repo group
63 exclude_group_ids = [c.repo_group.group_id]
64 exclude_group_ids = [c.repo_group.group_id]
64 c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids,
65 c.repo_groups = filter(lambda x: x[0] not in exclude_group_ids,
65 c.repo_groups)
66 c.repo_groups)
66 c.repo_groups_choices = map(lambda k: k[0], c.repo_groups)
67 c.repo_groups_choices = map(lambda k: k[0], c.repo_groups)
67
68
68 parent_group = c.repo_group.parent_group
69 parent_group = c.repo_group.parent_group
69
70
70 add_parent_group = (parent_group and (
71 add_parent_group = (parent_group and (
71 parent_group.group_id not in c.repo_groups_choices))
72 parent_group.group_id not in c.repo_groups_choices))
72 if add_parent_group:
73 if add_parent_group:
73 c.repo_groups_choices.append(parent_group.group_id)
74 c.repo_groups_choices.append(parent_group.group_id)
74 c.repo_groups.append(RepoGroup._generate_choice(parent_group))
75 c.repo_groups.append(RepoGroup._generate_choice(parent_group))
75
76
77 return c
76 return c
78
77
79 def _can_create_repo_group(self, parent_group_id=None):
78 def _can_create_repo_group(self, parent_group_id=None):
80 is_admin = HasPermissionAll('hg.admin')('group create controller')
79 is_admin = HasPermissionAll('hg.admin')('group create controller')
81 create_repo_group = HasPermissionAll(
80 create_repo_group = HasPermissionAll(
82 'hg.repogroup.create.true')('group create controller')
81 'hg.repogroup.create.true')('group create controller')
83 if is_admin or (create_repo_group and not parent_group_id):
82 if is_admin or (create_repo_group and not parent_group_id):
84 # we're global admin, or we have global repo group create
83 # we're global admin, or we have global repo group create
85 # permission
84 # permission
86 # we're ok and we can create TOP level groups
85 # we're ok and we can create TOP level groups
87 return True
86 return True
88 elif parent_group_id:
87 elif parent_group_id:
89 # we check the permission if we can write to parent group
88 # we check the permission if we can write to parent group
90 group = RepoGroup.get(parent_group_id)
89 group = RepoGroup.get(parent_group_id)
91 group_name = group.group_name if group else None
90 group_name = group.group_name if group else None
92 if HasRepoGroupPermissionAny('group.admin')(
91 if HasRepoGroupPermissionAny('group.admin')(
93 group_name, 'check if user is an admin of group'):
92 group_name, 'check if user is an admin of group'):
94 # we're an admin of passed in group, we're ok.
93 # we're an admin of passed in group, we're ok.
95 return True
94 return True
96 else:
95 else:
97 return False
96 return False
98 return False
97 return False
99
98
100 def _get_schema(self, c, old_values=None):
99 def _get_schema(self, c, old_values=None):
101 return repo_group_schema.RepoGroupSettingsSchema().bind(
100 return repo_group_schema.RepoGroupSettingsSchema().bind(
102 repo_group_repo_group_options=c.repo_groups_choices,
101 repo_group_repo_group_options=c.repo_groups_choices,
103 repo_group_repo_group_items=c.repo_groups,
102 repo_group_repo_group_items=c.repo_groups,
104
103
105 # user caller
104 # user caller
106 user=self._rhodecode_user,
105 user=self._rhodecode_user,
107 old_values=old_values
106 old_values=old_values
108 )
107 )
109
108
110 @LoginRequired()
109 @LoginRequired()
111 @HasRepoGroupPermissionAnyDecorator('group.admin')
110 @HasRepoGroupPermissionAnyDecorator('group.admin')
112 @view_config(
111 @view_config(
113 route_name='edit_repo_group', request_method='GET',
112 route_name='edit_repo_group', request_method='GET',
114 renderer='rhodecode:templates/admin/repo_groups/repo_group_edit.mako')
113 renderer='rhodecode:templates/admin/repo_groups/repo_group_edit.mako')
115 def edit_settings(self):
114 def edit_settings(self):
116 c = self.load_default_context()
115 c = self.load_default_context()
117 c.active = 'settings'
116 c.active = 'settings'
118
117
119 defaults = RepoGroupModel()._get_defaults(self.db_repo_group_name)
118 defaults = RepoGroupModel()._get_defaults(self.db_repo_group_name)
120 defaults['repo_group_owner'] = defaults['user']
119 defaults['repo_group_owner'] = defaults['user']
121
120
122 schema = self._get_schema(c)
121 schema = self._get_schema(c)
123 c.form = RcForm(schema, appstruct=defaults)
122 c.form = RcForm(schema, appstruct=defaults)
124 return self._get_template_context(c)
123 return self._get_template_context(c)
125
124
126 @LoginRequired()
125 @LoginRequired()
127 @HasRepoGroupPermissionAnyDecorator('group.admin')
126 @HasRepoGroupPermissionAnyDecorator('group.admin')
128 @CSRFRequired()
127 @CSRFRequired()
129 @view_config(
128 @view_config(
130 route_name='edit_repo_group', request_method='POST',
129 route_name='edit_repo_group', request_method='POST',
131 renderer='rhodecode:templates/admin/repo_groups/repo_group_edit.mako')
130 renderer='rhodecode:templates/admin/repo_groups/repo_group_edit.mako')
132 def edit_settings_update(self):
131 def edit_settings_update(self):
133 _ = self.request.translate
132 _ = self.request.translate
134 c = self.load_default_context()
133 c = self.load_default_context()
135 c.active = 'settings'
134 c.active = 'settings'
136
135
137 old_repo_group_name = self.db_repo_group_name
136 old_repo_group_name = self.db_repo_group_name
138 new_repo_group_name = old_repo_group_name
137 new_repo_group_name = old_repo_group_name
139
138
140 old_values = RepoGroupModel()._get_defaults(self.db_repo_group_name)
139 old_values = RepoGroupModel()._get_defaults(self.db_repo_group_name)
141 schema = self._get_schema(c, old_values=old_values)
140 schema = self._get_schema(c, old_values=old_values)
142
141
143 c.form = RcForm(schema)
142 c.form = RcForm(schema)
144 pstruct = self.request.POST.items()
143 pstruct = self.request.POST.items()
145
144
146 try:
145 try:
147 schema_data = c.form.validate(pstruct)
146 schema_data = c.form.validate(pstruct)
148 except deform.ValidationFailure as err_form:
147 except deform.ValidationFailure as err_form:
149 return self._get_template_context(c)
148 return self._get_template_context(c)
150
149
151 # data is now VALID, proceed with updates
150 # data is now VALID, proceed with updates
152 # save validated data back into the updates dict
151 # save validated data back into the updates dict
153 validated_updates = dict(
152 validated_updates = dict(
154 group_name=schema_data['repo_group']['repo_group_name_without_group'],
153 group_name=schema_data['repo_group']['repo_group_name_without_group'],
155 group_parent_id=schema_data['repo_group']['repo_group_id'],
154 group_parent_id=schema_data['repo_group']['repo_group_id'],
156 user=schema_data['repo_group_owner'],
155 user=schema_data['repo_group_owner'],
157 group_description=schema_data['repo_group_description'],
156 group_description=schema_data['repo_group_description'],
158 enable_locking=schema_data['repo_group_enable_locking'],
157 enable_locking=schema_data['repo_group_enable_locking'],
159 )
158 )
160
159
161 try:
160 try:
162 RepoGroupModel().update(self.db_repo_group, validated_updates)
161 RepoGroupModel().update(self.db_repo_group, validated_updates)
163
162
164 audit_logger.store_web(
163 audit_logger.store_web(
165 'repo_group.edit', action_data={'old_data': old_values},
164 'repo_group.edit', action_data={'old_data': old_values},
166 user=c.rhodecode_user)
165 user=c.rhodecode_user)
167
166
168 Session().commit()
167 Session().commit()
169
168
170 # use the new full name for redirect once we know we updated
169 # use the new full name for redirect once we know we updated
171 # the name on filesystem and in DB
170 # the name on filesystem and in DB
172 new_repo_group_name = schema_data['repo_group']['repo_group_name_with_group']
171 new_repo_group_name = schema_data['repo_group']['repo_group_name_with_group']
173
172
174 h.flash(_('Repository Group `{}` updated successfully').format(
173 h.flash(_('Repository Group `{}` updated successfully').format(
175 old_repo_group_name), category='success')
174 old_repo_group_name), category='success')
176
175
177 except Exception:
176 except Exception:
178 log.exception("Exception during update or repository group")
177 log.exception("Exception during update or repository group")
179 h.flash(_('Error occurred during update of repository group %s')
178 h.flash(_('Error occurred during update of repository group %s')
180 % old_repo_group_name, category='error')
179 % old_repo_group_name, category='error')
181
180
181 name_changed = old_repo_group_name != new_repo_group_name
182 if name_changed:
183 owner = User.get_by_username(schema_data['repo_group_owner'])
184 owner_id = owner.user_id if owner else self._rhodecode_user.user_id
185 events.trigger(events.UserPermissionsChange([
186 self._rhodecode_user.user_id, owner_id]))
187
182 raise HTTPFound(
188 raise HTTPFound(
183 h.route_path('edit_repo_group', repo_group_name=new_repo_group_name))
189 h.route_path('edit_repo_group', repo_group_name=new_repo_group_name))
@@ -1,256 +1,262 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22
22
23 import deform
23 import deform
24 from pyramid.httpexceptions import HTTPFound
24 from pyramid.httpexceptions import HTTPFound
25 from pyramid.view import view_config
25 from pyramid.view import view_config
26
26
27 from rhodecode import events
27 from rhodecode.apps._base import RepoAppView
28 from rhodecode.apps._base import RepoAppView
28 from rhodecode.forms import RcForm
29 from rhodecode.forms import RcForm
29 from rhodecode.lib import helpers as h
30 from rhodecode.lib import helpers as h
30 from rhodecode.lib import audit_logger
31 from rhodecode.lib import audit_logger
31 from rhodecode.lib.auth import (
32 from rhodecode.lib.auth import (
32 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
33 LoginRequired, HasRepoPermissionAnyDecorator, CSRFRequired)
33 from rhodecode.model.db import RepositoryField, RepoGroup, Repository
34 from rhodecode.model.db import RepositoryField, RepoGroup, Repository, User
34 from rhodecode.model.meta import Session
35 from rhodecode.model.meta import Session
35 from rhodecode.model.repo import RepoModel
36 from rhodecode.model.repo import RepoModel
36 from rhodecode.model.scm import RepoGroupList, ScmModel
37 from rhodecode.model.scm import RepoGroupList, ScmModel
37 from rhodecode.model.validation_schema.schemas import repo_schema
38 from rhodecode.model.validation_schema.schemas import repo_schema
38
39
39 log = logging.getLogger(__name__)
40 log = logging.getLogger(__name__)
40
41
41
42
42 class RepoSettingsView(RepoAppView):
43 class RepoSettingsView(RepoAppView):
43
44
44 def load_default_context(self):
45 def load_default_context(self):
45 c = self._get_local_tmpl_context()
46 c = self._get_local_tmpl_context()
46
47
47 acl_groups = RepoGroupList(
48 acl_groups = RepoGroupList(
48 RepoGroup.query().all(),
49 RepoGroup.query().all(),
49 perm_set=['group.write', 'group.admin'])
50 perm_set=['group.write', 'group.admin'])
50 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
51 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
51 c.repo_groups_choices = map(lambda k: k[0], c.repo_groups)
52 c.repo_groups_choices = map(lambda k: k[0], c.repo_groups)
52
53
53 # in case someone no longer have a group.write access to a repository
54 # in case someone no longer have a group.write access to a repository
54 # pre fill the list with this entry, we don't care if this is the same
55 # pre fill the list with this entry, we don't care if this is the same
55 # but it will allow saving repo data properly.
56 # but it will allow saving repo data properly.
56 repo_group = self.db_repo.group
57 repo_group = self.db_repo.group
57 if repo_group and repo_group.group_id not in c.repo_groups_choices:
58 if repo_group and repo_group.group_id not in c.repo_groups_choices:
58 c.repo_groups_choices.append(repo_group.group_id)
59 c.repo_groups_choices.append(repo_group.group_id)
59 c.repo_groups.append(RepoGroup._generate_choice(repo_group))
60 c.repo_groups.append(RepoGroup._generate_choice(repo_group))
60
61
61 if c.repository_requirements_missing or self.rhodecode_vcs_repo is None:
62 if c.repository_requirements_missing or self.rhodecode_vcs_repo is None:
62 # we might be in missing requirement state, so we load things
63 # we might be in missing requirement state, so we load things
63 # without touching scm_instance()
64 # without touching scm_instance()
64 c.landing_revs_choices, c.landing_revs = \
65 c.landing_revs_choices, c.landing_revs = \
65 ScmModel().get_repo_landing_revs(self.request.translate)
66 ScmModel().get_repo_landing_revs(self.request.translate)
66 else:
67 else:
67 c.landing_revs_choices, c.landing_revs = \
68 c.landing_revs_choices, c.landing_revs = \
68 ScmModel().get_repo_landing_revs(
69 ScmModel().get_repo_landing_revs(
69 self.request.translate, self.db_repo)
70 self.request.translate, self.db_repo)
70
71
71 c.personal_repo_group = c.auth_user.personal_repo_group
72 c.personal_repo_group = c.auth_user.personal_repo_group
72 c.repo_fields = RepositoryField.query()\
73 c.repo_fields = RepositoryField.query()\
73 .filter(RepositoryField.repository == self.db_repo).all()
74 .filter(RepositoryField.repository == self.db_repo).all()
74
75
76 return c
75 return c
77
76
78 def _get_schema(self, c, old_values=None):
77 def _get_schema(self, c, old_values=None):
79 return repo_schema.RepoSettingsSchema().bind(
78 return repo_schema.RepoSettingsSchema().bind(
80 repo_type=self.db_repo.repo_type,
79 repo_type=self.db_repo.repo_type,
81 repo_type_options=[self.db_repo.repo_type],
80 repo_type_options=[self.db_repo.repo_type],
82 repo_ref_options=c.landing_revs_choices,
81 repo_ref_options=c.landing_revs_choices,
83 repo_ref_items=c.landing_revs,
82 repo_ref_items=c.landing_revs,
84 repo_repo_group_options=c.repo_groups_choices,
83 repo_repo_group_options=c.repo_groups_choices,
85 repo_repo_group_items=c.repo_groups,
84 repo_repo_group_items=c.repo_groups,
86 # user caller
85 # user caller
87 user=self._rhodecode_user,
86 user=self._rhodecode_user,
88 old_values=old_values
87 old_values=old_values
89 )
88 )
90
89
91 @LoginRequired()
90 @LoginRequired()
92 @HasRepoPermissionAnyDecorator('repository.admin')
91 @HasRepoPermissionAnyDecorator('repository.admin')
93 @view_config(
92 @view_config(
94 route_name='edit_repo', request_method='GET',
93 route_name='edit_repo', request_method='GET',
95 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
94 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
96 def edit_settings(self):
95 def edit_settings(self):
97 c = self.load_default_context()
96 c = self.load_default_context()
98 c.active = 'settings'
97 c.active = 'settings'
99
98
100 defaults = RepoModel()._get_defaults(self.db_repo_name)
99 defaults = RepoModel()._get_defaults(self.db_repo_name)
101 defaults['repo_owner'] = defaults['user']
100 defaults['repo_owner'] = defaults['user']
102 defaults['repo_landing_commit_ref'] = defaults['repo_landing_rev']
101 defaults['repo_landing_commit_ref'] = defaults['repo_landing_rev']
103
102
104 schema = self._get_schema(c)
103 schema = self._get_schema(c)
105 c.form = RcForm(schema, appstruct=defaults)
104 c.form = RcForm(schema, appstruct=defaults)
106 return self._get_template_context(c)
105 return self._get_template_context(c)
107
106
108 @LoginRequired()
107 @LoginRequired()
109 @HasRepoPermissionAnyDecorator('repository.admin')
108 @HasRepoPermissionAnyDecorator('repository.admin')
110 @CSRFRequired()
109 @CSRFRequired()
111 @view_config(
110 @view_config(
112 route_name='edit_repo', request_method='POST',
111 route_name='edit_repo', request_method='POST',
113 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
112 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
114 def edit_settings_update(self):
113 def edit_settings_update(self):
115 _ = self.request.translate
114 _ = self.request.translate
116 c = self.load_default_context()
115 c = self.load_default_context()
117 c.active = 'settings'
116 c.active = 'settings'
118 old_repo_name = self.db_repo_name
117 old_repo_name = self.db_repo_name
119
118
120 old_values = self.db_repo.get_api_data()
119 old_values = self.db_repo.get_api_data()
121 schema = self._get_schema(c, old_values=old_values)
120 schema = self._get_schema(c, old_values=old_values)
122
121
123 c.form = RcForm(schema)
122 c.form = RcForm(schema)
124 pstruct = self.request.POST.items()
123 pstruct = self.request.POST.items()
125 pstruct.append(('repo_type', self.db_repo.repo_type))
124 pstruct.append(('repo_type', self.db_repo.repo_type))
126 try:
125 try:
127 schema_data = c.form.validate(pstruct)
126 schema_data = c.form.validate(pstruct)
128 except deform.ValidationFailure as err_form:
127 except deform.ValidationFailure as err_form:
129 return self._get_template_context(c)
128 return self._get_template_context(c)
130
129
131 # data is now VALID, proceed with updates
130 # data is now VALID, proceed with updates
132 # save validated data back into the updates dict
131 # save validated data back into the updates dict
133 validated_updates = dict(
132 validated_updates = dict(
134 repo_name=schema_data['repo_group']['repo_name_without_group'],
133 repo_name=schema_data['repo_group']['repo_name_without_group'],
135 repo_group=schema_data['repo_group']['repo_group_id'],
134 repo_group=schema_data['repo_group']['repo_group_id'],
136
135
137 user=schema_data['repo_owner'],
136 user=schema_data['repo_owner'],
138 repo_description=schema_data['repo_description'],
137 repo_description=schema_data['repo_description'],
139 repo_private=schema_data['repo_private'],
138 repo_private=schema_data['repo_private'],
140 clone_uri=schema_data['repo_clone_uri'],
139 clone_uri=schema_data['repo_clone_uri'],
141 push_uri=schema_data['repo_push_uri'],
140 push_uri=schema_data['repo_push_uri'],
142 repo_landing_rev=schema_data['repo_landing_commit_ref'],
141 repo_landing_rev=schema_data['repo_landing_commit_ref'],
143 repo_enable_statistics=schema_data['repo_enable_statistics'],
142 repo_enable_statistics=schema_data['repo_enable_statistics'],
144 repo_enable_locking=schema_data['repo_enable_locking'],
143 repo_enable_locking=schema_data['repo_enable_locking'],
145 repo_enable_downloads=schema_data['repo_enable_downloads'],
144 repo_enable_downloads=schema_data['repo_enable_downloads'],
146 )
145 )
147 # detect if SYNC URI changed, if we get OLD means we keep old values
146 # detect if SYNC URI changed, if we get OLD means we keep old values
148 if schema_data['repo_clone_uri_change'] == 'OLD':
147 if schema_data['repo_clone_uri_change'] == 'OLD':
149 validated_updates['clone_uri'] = self.db_repo.clone_uri
148 validated_updates['clone_uri'] = self.db_repo.clone_uri
150
149
151 if schema_data['repo_push_uri_change'] == 'OLD':
150 if schema_data['repo_push_uri_change'] == 'OLD':
152 validated_updates['push_uri'] = self.db_repo.push_uri
151 validated_updates['push_uri'] = self.db_repo.push_uri
153
152
154 # use the new full name for redirect
153 # use the new full name for redirect
155 new_repo_name = schema_data['repo_group']['repo_name_with_group']
154 new_repo_name = schema_data['repo_group']['repo_name_with_group']
156
155
157 # save extra fields into our validated data
156 # save extra fields into our validated data
158 for key, value in pstruct:
157 for key, value in pstruct:
159 if key.startswith(RepositoryField.PREFIX):
158 if key.startswith(RepositoryField.PREFIX):
160 validated_updates[key] = value
159 validated_updates[key] = value
161
160
162 try:
161 try:
163 RepoModel().update(self.db_repo, **validated_updates)
162 RepoModel().update(self.db_repo, **validated_updates)
164 ScmModel().mark_for_invalidation(new_repo_name)
163 ScmModel().mark_for_invalidation(new_repo_name)
165
164
166 audit_logger.store_web(
165 audit_logger.store_web(
167 'repo.edit', action_data={'old_data': old_values},
166 'repo.edit', action_data={'old_data': old_values},
168 user=self._rhodecode_user, repo=self.db_repo)
167 user=self._rhodecode_user, repo=self.db_repo)
169
168
170 Session().commit()
169 Session().commit()
171
170
172 h.flash(_('Repository `{}` updated successfully').format(
171 h.flash(_('Repository `{}` updated successfully').format(
173 old_repo_name), category='success')
172 old_repo_name), category='success')
174 except Exception:
173 except Exception:
175 log.exception("Exception during update of repository")
174 log.exception("Exception during update of repository")
176 h.flash(_('Error occurred during update of repository {}').format(
175 h.flash(_('Error occurred during update of repository {}').format(
177 old_repo_name), category='error')
176 old_repo_name), category='error')
178
177
178 name_changed = old_repo_name != new_repo_name
179 if name_changed:
180 owner = User.get_by_username(schema_data['repo_owner'])
181 owner_id = owner.user_id if owner else self._rhodecode_user.user_id
182 events.trigger(events.UserPermissionsChange([
183 self._rhodecode_user.user_id, owner_id]))
184
179 raise HTTPFound(
185 raise HTTPFound(
180 h.route_path('edit_repo', repo_name=new_repo_name))
186 h.route_path('edit_repo', repo_name=new_repo_name))
181
187
182 @LoginRequired()
188 @LoginRequired()
183 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
189 @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin')
184 @view_config(
190 @view_config(
185 route_name='repo_edit_toggle_locking', request_method='GET',
191 route_name='repo_edit_toggle_locking', request_method='GET',
186 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
192 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
187 def toggle_locking(self):
193 def toggle_locking(self):
188 """
194 """
189 Toggle locking of repository by simple GET call to url
195 Toggle locking of repository by simple GET call to url
190 """
196 """
191 _ = self.request.translate
197 _ = self.request.translate
192 repo = self.db_repo
198 repo = self.db_repo
193
199
194 try:
200 try:
195 if repo.enable_locking:
201 if repo.enable_locking:
196 if repo.locked[0]:
202 if repo.locked[0]:
197 Repository.unlock(repo)
203 Repository.unlock(repo)
198 action = _('Unlocked')
204 action = _('Unlocked')
199 else:
205 else:
200 Repository.lock(
206 Repository.lock(
201 repo, self._rhodecode_user.user_id,
207 repo, self._rhodecode_user.user_id,
202 lock_reason=Repository.LOCK_WEB)
208 lock_reason=Repository.LOCK_WEB)
203 action = _('Locked')
209 action = _('Locked')
204
210
205 h.flash(_('Repository has been %s') % action,
211 h.flash(_('Repository has been %s') % action,
206 category='success')
212 category='success')
207 except Exception:
213 except Exception:
208 log.exception("Exception during unlocking")
214 log.exception("Exception during unlocking")
209 h.flash(_('An error occurred during unlocking'),
215 h.flash(_('An error occurred during unlocking'),
210 category='error')
216 category='error')
211 raise HTTPFound(
217 raise HTTPFound(
212 h.route_path('repo_summary', repo_name=self.db_repo_name))
218 h.route_path('repo_summary', repo_name=self.db_repo_name))
213
219
214 @LoginRequired()
220 @LoginRequired()
215 @HasRepoPermissionAnyDecorator('repository.admin')
221 @HasRepoPermissionAnyDecorator('repository.admin')
216 @view_config(
222 @view_config(
217 route_name='edit_repo_statistics', request_method='GET',
223 route_name='edit_repo_statistics', request_method='GET',
218 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
224 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
219 def edit_statistics_form(self):
225 def edit_statistics_form(self):
220 c = self.load_default_context()
226 c = self.load_default_context()
221
227
222 if self.db_repo.stats:
228 if self.db_repo.stats:
223 # this is on what revision we ended up so we add +1 for count
229 # this is on what revision we ended up so we add +1 for count
224 last_rev = self.db_repo.stats.stat_on_revision + 1
230 last_rev = self.db_repo.stats.stat_on_revision + 1
225 else:
231 else:
226 last_rev = 0
232 last_rev = 0
227
233
228 c.active = 'statistics'
234 c.active = 'statistics'
229 c.stats_revision = last_rev
235 c.stats_revision = last_rev
230 c.repo_last_rev = self.rhodecode_vcs_repo.count()
236 c.repo_last_rev = self.rhodecode_vcs_repo.count()
231
237
232 if last_rev == 0 or c.repo_last_rev == 0:
238 if last_rev == 0 or c.repo_last_rev == 0:
233 c.stats_percentage = 0
239 c.stats_percentage = 0
234 else:
240 else:
235 c.stats_percentage = '%.2f' % (
241 c.stats_percentage = '%.2f' % (
236 (float((last_rev)) / c.repo_last_rev) * 100)
242 (float((last_rev)) / c.repo_last_rev) * 100)
237 return self._get_template_context(c)
243 return self._get_template_context(c)
238
244
239 @LoginRequired()
245 @LoginRequired()
240 @HasRepoPermissionAnyDecorator('repository.admin')
246 @HasRepoPermissionAnyDecorator('repository.admin')
241 @CSRFRequired()
247 @CSRFRequired()
242 @view_config(
248 @view_config(
243 route_name='edit_repo_statistics_reset', request_method='POST',
249 route_name='edit_repo_statistics_reset', request_method='POST',
244 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
250 renderer='rhodecode:templates/admin/repos/repo_edit.mako')
245 def repo_statistics_reset(self):
251 def repo_statistics_reset(self):
246 _ = self.request.translate
252 _ = self.request.translate
247
253
248 try:
254 try:
249 RepoModel().delete_stats(self.db_repo_name)
255 RepoModel().delete_stats(self.db_repo_name)
250 Session().commit()
256 Session().commit()
251 except Exception:
257 except Exception:
252 log.exception('Edit statistics failure')
258 log.exception('Edit statistics failure')
253 h.flash(_('An error occurred during deletion of repository stats'),
259 h.flash(_('An error occurred during deletion of repository stats'),
254 category='error')
260 category='error')
255 raise HTTPFound(
261 raise HTTPFound(
256 h.route_path('edit_repo_statistics', repo_name=self.db_repo_name))
262 h.route_path('edit_repo_statistics', repo_name=self.db_repo_name))
@@ -1,534 +1,545 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2018 RhodeCode GmbH
3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
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
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
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/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22
22
23 import peppercorn
23 import peppercorn
24 import formencode
24 import formencode
25 import formencode.htmlfill
25 import formencode.htmlfill
26 from pyramid.httpexceptions import HTTPFound
26 from pyramid.httpexceptions import HTTPFound
27 from pyramid.view import view_config
27 from pyramid.view import view_config
28 from pyramid.response import Response
28 from pyramid.response import Response
29 from pyramid.renderers import render
29 from pyramid.renderers import render
30
30
31 from rhodecode import events
31 from rhodecode import events
32 from rhodecode.lib.exceptions import (
32 from rhodecode.lib.exceptions import (
33 RepoGroupAssignmentError, UserGroupAssignedException)
33 RepoGroupAssignmentError, UserGroupAssignedException)
34 from rhodecode.model.forms import (
34 from rhodecode.model.forms import (
35 UserGroupPermsForm, UserGroupForm, UserIndividualPermissionsForm,
35 UserGroupPermsForm, UserGroupForm, UserIndividualPermissionsForm,
36 UserPermissionsForm)
36 UserPermissionsForm)
37 from rhodecode.model.permission import PermissionModel
37 from rhodecode.model.permission import PermissionModel
38
38
39 from rhodecode.apps._base import UserGroupAppView
39 from rhodecode.apps._base import UserGroupAppView
40 from rhodecode.lib.auth import (
40 from rhodecode.lib.auth import (
41 LoginRequired, HasUserGroupPermissionAnyDecorator, CSRFRequired)
41 LoginRequired, HasUserGroupPermissionAnyDecorator, CSRFRequired)
42 from rhodecode.lib import helpers as h, audit_logger
42 from rhodecode.lib import helpers as h, audit_logger
43 from rhodecode.lib.utils2 import str2bool
43 from rhodecode.lib.utils2 import str2bool
44 from rhodecode.model.db import User
44 from rhodecode.model.db import User
45 from rhodecode.model.meta import Session
45 from rhodecode.model.meta import Session
46 from rhodecode.model.user_group import UserGroupModel
46 from rhodecode.model.user_group import UserGroupModel
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50
50
51 class UserGroupsView(UserGroupAppView):
51 class UserGroupsView(UserGroupAppView):
52
52
53 def load_default_context(self):
53 def load_default_context(self):
54 c = self._get_local_tmpl_context()
54 c = self._get_local_tmpl_context()
55
55
56 PermissionModel().set_global_permission_choices(
56 PermissionModel().set_global_permission_choices(
57 c, gettext_translator=self.request.translate)
57 c, gettext_translator=self.request.translate)
58
58
59 return c
59 return c
60
60
61 @LoginRequired()
61 @LoginRequired()
62 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
62 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
63 @view_config(
63 @view_config(
64 route_name='user_group_members_data', request_method='GET',
64 route_name='user_group_members_data', request_method='GET',
65 renderer='json_ext', xhr=True)
65 renderer='json_ext', xhr=True)
66 def user_group_members(self):
66 def user_group_members(self):
67 """
67 """
68 Return members of given user group
68 Return members of given user group
69 """
69 """
70 self.load_default_context()
70 self.load_default_context()
71 user_group = self.db_user_group
71 user_group = self.db_user_group
72 group_members_obj = sorted((x.user for x in user_group.members),
72 group_members_obj = sorted((x.user for x in user_group.members),
73 key=lambda u: u.username.lower())
73 key=lambda u: u.username.lower())
74
74
75 group_members = [
75 group_members = [
76 {
76 {
77 'id': user.user_id,
77 'id': user.user_id,
78 'first_name': user.first_name,
78 'first_name': user.first_name,
79 'last_name': user.last_name,
79 'last_name': user.last_name,
80 'username': user.username,
80 'username': user.username,
81 'icon_link': h.gravatar_url(user.email, 30),
81 'icon_link': h.gravatar_url(user.email, 30),
82 'value_display': h.person(user.email),
82 'value_display': h.person(user.email),
83 'value': user.username,
83 'value': user.username,
84 'value_type': 'user',
84 'value_type': 'user',
85 'active': user.active,
85 'active': user.active,
86 }
86 }
87 for user in group_members_obj
87 for user in group_members_obj
88 ]
88 ]
89
89
90 return {
90 return {
91 'members': group_members
91 'members': group_members
92 }
92 }
93
93
94 @LoginRequired()
94 @LoginRequired()
95 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
95 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
96 @view_config(
96 @view_config(
97 route_name='edit_user_group_perms_summary', request_method='GET',
97 route_name='edit_user_group_perms_summary', request_method='GET',
98 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
98 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
99 def user_group_perms_summary(self):
99 def user_group_perms_summary(self):
100 c = self.load_default_context()
100 c = self.load_default_context()
101 c.user_group = self.db_user_group
101 c.user_group = self.db_user_group
102 c.active = 'perms_summary'
102 c.active = 'perms_summary'
103 c.permissions = UserGroupModel().get_perms_summary(
103 c.permissions = UserGroupModel().get_perms_summary(
104 c.user_group.users_group_id)
104 c.user_group.users_group_id)
105 return self._get_template_context(c)
105 return self._get_template_context(c)
106
106
107 @LoginRequired()
107 @LoginRequired()
108 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
108 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
109 @view_config(
109 @view_config(
110 route_name='edit_user_group_perms_summary_json', request_method='GET',
110 route_name='edit_user_group_perms_summary_json', request_method='GET',
111 renderer='json_ext')
111 renderer='json_ext')
112 def user_group_perms_summary_json(self):
112 def user_group_perms_summary_json(self):
113 self.load_default_context()
113 self.load_default_context()
114 user_group = self.db_user_group
114 user_group = self.db_user_group
115 return UserGroupModel().get_perms_summary(user_group.users_group_id)
115 return UserGroupModel().get_perms_summary(user_group.users_group_id)
116
116
117 def _revoke_perms_on_yourself(self, form_result):
117 def _revoke_perms_on_yourself(self, form_result):
118 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
118 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
119 form_result['perm_updates'])
119 form_result['perm_updates'])
120 _additions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
120 _additions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
121 form_result['perm_additions'])
121 form_result['perm_additions'])
122 _deletions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
122 _deletions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
123 form_result['perm_deletions'])
123 form_result['perm_deletions'])
124 admin_perm = 'usergroup.admin'
124 admin_perm = 'usergroup.admin'
125 if _updates and _updates[0][1] != admin_perm or \
125 if _updates and _updates[0][1] != admin_perm or \
126 _additions and _additions[0][1] != admin_perm or \
126 _additions and _additions[0][1] != admin_perm or \
127 _deletions and _deletions[0][1] != admin_perm:
127 _deletions and _deletions[0][1] != admin_perm:
128 return True
128 return True
129 return False
129 return False
130
130
131 @LoginRequired()
131 @LoginRequired()
132 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
132 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
133 @CSRFRequired()
133 @CSRFRequired()
134 @view_config(
134 @view_config(
135 route_name='user_groups_update', request_method='POST',
135 route_name='user_groups_update', request_method='POST',
136 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
136 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
137 def user_group_update(self):
137 def user_group_update(self):
138 _ = self.request.translate
138 _ = self.request.translate
139
139
140 user_group = self.db_user_group
140 user_group = self.db_user_group
141 user_group_id = user_group.users_group_id
141 user_group_id = user_group.users_group_id
142
142
143 old_user_group_name = self.db_user_group_name
144 new_user_group_name = old_user_group_name
145
143 c = self.load_default_context()
146 c = self.load_default_context()
144 c.user_group = user_group
147 c.user_group = user_group
145 c.group_members_obj = [x.user for x in c.user_group.members]
148 c.group_members_obj = [x.user for x in c.user_group.members]
146 c.group_members_obj.sort(key=lambda u: u.username.lower())
149 c.group_members_obj.sort(key=lambda u: u.username.lower())
147 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
150 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
148 c.active = 'settings'
151 c.active = 'settings'
149
152
150 users_group_form = UserGroupForm(
153 users_group_form = UserGroupForm(
151 self.request.translate, edit=True,
154 self.request.translate, edit=True,
152 old_data=c.user_group.get_dict(), allow_disabled=True)()
155 old_data=c.user_group.get_dict(), allow_disabled=True)()
153
156
154 old_values = c.user_group.get_api_data()
157 old_values = c.user_group.get_api_data()
155 user_group_name = self.request.POST.get('users_group_name')
158
156 try:
159 try:
157 form_result = users_group_form.to_python(self.request.POST)
160 form_result = users_group_form.to_python(self.request.POST)
158 pstruct = peppercorn.parse(self.request.POST.items())
161 pstruct = peppercorn.parse(self.request.POST.items())
159 form_result['users_group_members'] = pstruct['user_group_members']
162 form_result['users_group_members'] = pstruct['user_group_members']
160
163
161 user_group, added_members, removed_members = \
164 user_group, added_members, removed_members = \
162 UserGroupModel().update(c.user_group, form_result)
165 UserGroupModel().update(c.user_group, form_result)
163 updated_user_group = form_result['users_group_name']
166 new_user_group_name = form_result['users_group_name']
164
167
165 for user_id in added_members:
168 for user_id in added_members:
166 user = User.get(user_id)
169 user = User.get(user_id)
167 user_data = user.get_api_data()
170 user_data = user.get_api_data()
168 audit_logger.store_web(
171 audit_logger.store_web(
169 'user_group.edit.member.add',
172 'user_group.edit.member.add',
170 action_data={'user': user_data, 'old_data': old_values},
173 action_data={'user': user_data, 'old_data': old_values},
171 user=self._rhodecode_user)
174 user=self._rhodecode_user)
172
175
173 for user_id in removed_members:
176 for user_id in removed_members:
174 user = User.get(user_id)
177 user = User.get(user_id)
175 user_data = user.get_api_data()
178 user_data = user.get_api_data()
176 audit_logger.store_web(
179 audit_logger.store_web(
177 'user_group.edit.member.delete',
180 'user_group.edit.member.delete',
178 action_data={'user': user_data, 'old_data': old_values},
181 action_data={'user': user_data, 'old_data': old_values},
179 user=self._rhodecode_user)
182 user=self._rhodecode_user)
180
183
181 audit_logger.store_web(
184 audit_logger.store_web(
182 'user_group.edit', action_data={'old_data': old_values},
185 'user_group.edit', action_data={'old_data': old_values},
183 user=self._rhodecode_user)
186 user=self._rhodecode_user)
184
187
185 h.flash(_('Updated user group %s') % updated_user_group,
188 h.flash(_('Updated user group %s') % new_user_group_name,
186 category='success')
189 category='success')
187
190
188 affected_user_ids = []
191 affected_user_ids = []
189 for user_id in added_members + removed_members:
192 for user_id in added_members + removed_members:
190 affected_user_ids.append(user_id)
193 affected_user_ids.append(user_id)
194
195 name_changed = old_user_group_name != new_user_group_name
196 if name_changed:
197 owner = User.get_by_username(form_result['user'])
198 owner_id = owner.user_id if owner else self._rhodecode_user.user_id
199 affected_user_ids.append(self._rhodecode_user.user_id)
200 affected_user_ids.append(owner_id)
201
191 events.trigger(events.UserPermissionsChange(affected_user_ids))
202 events.trigger(events.UserPermissionsChange(affected_user_ids))
192
203
193 Session().commit()
204 Session().commit()
194 except formencode.Invalid as errors:
205 except formencode.Invalid as errors:
195 defaults = errors.value
206 defaults = errors.value
196 e = errors.error_dict or {}
207 e = errors.error_dict or {}
197
208
198 data = render(
209 data = render(
199 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
210 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
200 self._get_template_context(c), self.request)
211 self._get_template_context(c), self.request)
201 html = formencode.htmlfill.render(
212 html = formencode.htmlfill.render(
202 data,
213 data,
203 defaults=defaults,
214 defaults=defaults,
204 errors=e,
215 errors=e,
205 prefix_error=False,
216 prefix_error=False,
206 encoding="UTF-8",
217 encoding="UTF-8",
207 force_defaults=False
218 force_defaults=False
208 )
219 )
209 return Response(html)
220 return Response(html)
210
221
211 except Exception:
222 except Exception:
212 log.exception("Exception during update of user group")
223 log.exception("Exception during update of user group")
213 h.flash(_('Error occurred during update of user group %s')
224 h.flash(_('Error occurred during update of user group %s')
214 % user_group_name, category='error')
225 % new_user_group_name, category='error')
215
226
216 raise HTTPFound(
227 raise HTTPFound(
217 h.route_path('edit_user_group', user_group_id=user_group_id))
228 h.route_path('edit_user_group', user_group_id=user_group_id))
218
229
219 @LoginRequired()
230 @LoginRequired()
220 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
231 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
221 @CSRFRequired()
232 @CSRFRequired()
222 @view_config(
233 @view_config(
223 route_name='user_groups_delete', request_method='POST',
234 route_name='user_groups_delete', request_method='POST',
224 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
235 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
225 def user_group_delete(self):
236 def user_group_delete(self):
226 _ = self.request.translate
237 _ = self.request.translate
227 user_group = self.db_user_group
238 user_group = self.db_user_group
228
239
229 self.load_default_context()
240 self.load_default_context()
230 force = str2bool(self.request.POST.get('force'))
241 force = str2bool(self.request.POST.get('force'))
231
242
232 old_values = user_group.get_api_data()
243 old_values = user_group.get_api_data()
233 try:
244 try:
234 UserGroupModel().delete(user_group, force=force)
245 UserGroupModel().delete(user_group, force=force)
235 audit_logger.store_web(
246 audit_logger.store_web(
236 'user.delete', action_data={'old_data': old_values},
247 'user.delete', action_data={'old_data': old_values},
237 user=self._rhodecode_user)
248 user=self._rhodecode_user)
238 Session().commit()
249 Session().commit()
239 h.flash(_('Successfully deleted user group'), category='success')
250 h.flash(_('Successfully deleted user group'), category='success')
240 except UserGroupAssignedException as e:
251 except UserGroupAssignedException as e:
241 h.flash(str(e), category='error')
252 h.flash(str(e), category='error')
242 except Exception:
253 except Exception:
243 log.exception("Exception during deletion of user group")
254 log.exception("Exception during deletion of user group")
244 h.flash(_('An error occurred during deletion of user group'),
255 h.flash(_('An error occurred during deletion of user group'),
245 category='error')
256 category='error')
246 raise HTTPFound(h.route_path('user_groups'))
257 raise HTTPFound(h.route_path('user_groups'))
247
258
248 @LoginRequired()
259 @LoginRequired()
249 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
260 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
250 @view_config(
261 @view_config(
251 route_name='edit_user_group', request_method='GET',
262 route_name='edit_user_group', request_method='GET',
252 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
263 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
253 def user_group_edit(self):
264 def user_group_edit(self):
254 user_group = self.db_user_group
265 user_group = self.db_user_group
255
266
256 c = self.load_default_context()
267 c = self.load_default_context()
257 c.user_group = user_group
268 c.user_group = user_group
258 c.group_members_obj = [x.user for x in c.user_group.members]
269 c.group_members_obj = [x.user for x in c.user_group.members]
259 c.group_members_obj.sort(key=lambda u: u.username.lower())
270 c.group_members_obj.sort(key=lambda u: u.username.lower())
260 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
271 c.group_members = [(x.user_id, x.username) for x in c.group_members_obj]
261
272
262 c.active = 'settings'
273 c.active = 'settings'
263
274
264 defaults = user_group.get_dict()
275 defaults = user_group.get_dict()
265 # fill owner
276 # fill owner
266 if user_group.user:
277 if user_group.user:
267 defaults.update({'user': user_group.user.username})
278 defaults.update({'user': user_group.user.username})
268 else:
279 else:
269 replacement_user = User.get_first_super_admin().username
280 replacement_user = User.get_first_super_admin().username
270 defaults.update({'user': replacement_user})
281 defaults.update({'user': replacement_user})
271
282
272 data = render(
283 data = render(
273 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
284 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
274 self._get_template_context(c), self.request)
285 self._get_template_context(c), self.request)
275 html = formencode.htmlfill.render(
286 html = formencode.htmlfill.render(
276 data,
287 data,
277 defaults=defaults,
288 defaults=defaults,
278 encoding="UTF-8",
289 encoding="UTF-8",
279 force_defaults=False
290 force_defaults=False
280 )
291 )
281 return Response(html)
292 return Response(html)
282
293
283 @LoginRequired()
294 @LoginRequired()
284 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
295 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
285 @view_config(
296 @view_config(
286 route_name='edit_user_group_perms', request_method='GET',
297 route_name='edit_user_group_perms', request_method='GET',
287 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
298 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
288 def user_group_edit_perms(self):
299 def user_group_edit_perms(self):
289 user_group = self.db_user_group
300 user_group = self.db_user_group
290 c = self.load_default_context()
301 c = self.load_default_context()
291 c.user_group = user_group
302 c.user_group = user_group
292 c.active = 'perms'
303 c.active = 'perms'
293
304
294 defaults = {}
305 defaults = {}
295 # fill user group users
306 # fill user group users
296 for p in c.user_group.user_user_group_to_perm:
307 for p in c.user_group.user_user_group_to_perm:
297 defaults.update({'u_perm_%s' % p.user.user_id:
308 defaults.update({'u_perm_%s' % p.user.user_id:
298 p.permission.permission_name})
309 p.permission.permission_name})
299
310
300 for p in c.user_group.user_group_user_group_to_perm:
311 for p in c.user_group.user_group_user_group_to_perm:
301 defaults.update({'g_perm_%s' % p.user_group.users_group_id:
312 defaults.update({'g_perm_%s' % p.user_group.users_group_id:
302 p.permission.permission_name})
313 p.permission.permission_name})
303
314
304 data = render(
315 data = render(
305 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
316 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
306 self._get_template_context(c), self.request)
317 self._get_template_context(c), self.request)
307 html = formencode.htmlfill.render(
318 html = formencode.htmlfill.render(
308 data,
319 data,
309 defaults=defaults,
320 defaults=defaults,
310 encoding="UTF-8",
321 encoding="UTF-8",
311 force_defaults=False
322 force_defaults=False
312 )
323 )
313 return Response(html)
324 return Response(html)
314
325
315 @LoginRequired()
326 @LoginRequired()
316 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
327 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
317 @CSRFRequired()
328 @CSRFRequired()
318 @view_config(
329 @view_config(
319 route_name='edit_user_group_perms_update', request_method='POST',
330 route_name='edit_user_group_perms_update', request_method='POST',
320 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
331 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
321 def user_group_update_perms(self):
332 def user_group_update_perms(self):
322 """
333 """
323 grant permission for given user group
334 grant permission for given user group
324 """
335 """
325 _ = self.request.translate
336 _ = self.request.translate
326
337
327 user_group = self.db_user_group
338 user_group = self.db_user_group
328 user_group_id = user_group.users_group_id
339 user_group_id = user_group.users_group_id
329 c = self.load_default_context()
340 c = self.load_default_context()
330 c.user_group = user_group
341 c.user_group = user_group
331 form = UserGroupPermsForm(self.request.translate)().to_python(self.request.POST)
342 form = UserGroupPermsForm(self.request.translate)().to_python(self.request.POST)
332
343
333 if not self._rhodecode_user.is_admin:
344 if not self._rhodecode_user.is_admin:
334 if self._revoke_perms_on_yourself(form):
345 if self._revoke_perms_on_yourself(form):
335 msg = _('Cannot change permission for yourself as admin')
346 msg = _('Cannot change permission for yourself as admin')
336 h.flash(msg, category='warning')
347 h.flash(msg, category='warning')
337 raise HTTPFound(
348 raise HTTPFound(
338 h.route_path('edit_user_group_perms',
349 h.route_path('edit_user_group_perms',
339 user_group_id=user_group_id))
350 user_group_id=user_group_id))
340
351
341 try:
352 try:
342 changes = UserGroupModel().update_permissions(
353 changes = UserGroupModel().update_permissions(
343 user_group,
354 user_group,
344 form['perm_additions'], form['perm_updates'],
355 form['perm_additions'], form['perm_updates'],
345 form['perm_deletions'])
356 form['perm_deletions'])
346
357
347 except RepoGroupAssignmentError:
358 except RepoGroupAssignmentError:
348 h.flash(_('Target group cannot be the same'), category='error')
359 h.flash(_('Target group cannot be the same'), category='error')
349 raise HTTPFound(
360 raise HTTPFound(
350 h.route_path('edit_user_group_perms',
361 h.route_path('edit_user_group_perms',
351 user_group_id=user_group_id))
362 user_group_id=user_group_id))
352
363
353 action_data = {
364 action_data = {
354 'added': changes['added'],
365 'added': changes['added'],
355 'updated': changes['updated'],
366 'updated': changes['updated'],
356 'deleted': changes['deleted'],
367 'deleted': changes['deleted'],
357 }
368 }
358 audit_logger.store_web(
369 audit_logger.store_web(
359 'user_group.edit.permissions', action_data=action_data,
370 'user_group.edit.permissions', action_data=action_data,
360 user=self._rhodecode_user)
371 user=self._rhodecode_user)
361
372
362 Session().commit()
373 Session().commit()
363 h.flash(_('User Group permissions updated'), category='success')
374 h.flash(_('User Group permissions updated'), category='success')
364
375
365 affected_user_ids = []
376 affected_user_ids = []
366 for change in changes['added'] + changes['updated'] + changes['deleted']:
377 for change in changes['added'] + changes['updated'] + changes['deleted']:
367 if change['type'] == 'user':
378 if change['type'] == 'user':
368 affected_user_ids.append(change['id'])
379 affected_user_ids.append(change['id'])
369
380
370 events.trigger(events.UserPermissionsChange(affected_user_ids))
381 events.trigger(events.UserPermissionsChange(affected_user_ids))
371
382
372 raise HTTPFound(
383 raise HTTPFound(
373 h.route_path('edit_user_group_perms', user_group_id=user_group_id))
384 h.route_path('edit_user_group_perms', user_group_id=user_group_id))
374
385
375 @LoginRequired()
386 @LoginRequired()
376 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
387 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
377 @view_config(
388 @view_config(
378 route_name='edit_user_group_global_perms', request_method='GET',
389 route_name='edit_user_group_global_perms', request_method='GET',
379 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
390 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
380 def user_group_global_perms_edit(self):
391 def user_group_global_perms_edit(self):
381 user_group = self.db_user_group
392 user_group = self.db_user_group
382 c = self.load_default_context()
393 c = self.load_default_context()
383 c.user_group = user_group
394 c.user_group = user_group
384 c.active = 'global_perms'
395 c.active = 'global_perms'
385
396
386 c.default_user = User.get_default_user()
397 c.default_user = User.get_default_user()
387 defaults = c.user_group.get_dict()
398 defaults = c.user_group.get_dict()
388 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
399 defaults.update(c.default_user.get_default_perms(suffix='_inherited'))
389 defaults.update(c.user_group.get_default_perms())
400 defaults.update(c.user_group.get_default_perms())
390
401
391 data = render(
402 data = render(
392 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
403 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
393 self._get_template_context(c), self.request)
404 self._get_template_context(c), self.request)
394 html = formencode.htmlfill.render(
405 html = formencode.htmlfill.render(
395 data,
406 data,
396 defaults=defaults,
407 defaults=defaults,
397 encoding="UTF-8",
408 encoding="UTF-8",
398 force_defaults=False
409 force_defaults=False
399 )
410 )
400 return Response(html)
411 return Response(html)
401
412
402 @LoginRequired()
413 @LoginRequired()
403 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
414 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
404 @CSRFRequired()
415 @CSRFRequired()
405 @view_config(
416 @view_config(
406 route_name='edit_user_group_global_perms_update', request_method='POST',
417 route_name='edit_user_group_global_perms_update', request_method='POST',
407 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
418 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
408 def user_group_global_perms_update(self):
419 def user_group_global_perms_update(self):
409 _ = self.request.translate
420 _ = self.request.translate
410 user_group = self.db_user_group
421 user_group = self.db_user_group
411 user_group_id = self.db_user_group.users_group_id
422 user_group_id = self.db_user_group.users_group_id
412
423
413 c = self.load_default_context()
424 c = self.load_default_context()
414 c.user_group = user_group
425 c.user_group = user_group
415 c.active = 'global_perms'
426 c.active = 'global_perms'
416
427
417 try:
428 try:
418 # first stage that verifies the checkbox
429 # first stage that verifies the checkbox
419 _form = UserIndividualPermissionsForm(self.request.translate)
430 _form = UserIndividualPermissionsForm(self.request.translate)
420 form_result = _form.to_python(dict(self.request.POST))
431 form_result = _form.to_python(dict(self.request.POST))
421 inherit_perms = form_result['inherit_default_permissions']
432 inherit_perms = form_result['inherit_default_permissions']
422 user_group.inherit_default_permissions = inherit_perms
433 user_group.inherit_default_permissions = inherit_perms
423 Session().add(user_group)
434 Session().add(user_group)
424
435
425 if not inherit_perms:
436 if not inherit_perms:
426 # only update the individual ones if we un check the flag
437 # only update the individual ones if we un check the flag
427 _form = UserPermissionsForm(
438 _form = UserPermissionsForm(
428 self.request.translate,
439 self.request.translate,
429 [x[0] for x in c.repo_create_choices],
440 [x[0] for x in c.repo_create_choices],
430 [x[0] for x in c.repo_create_on_write_choices],
441 [x[0] for x in c.repo_create_on_write_choices],
431 [x[0] for x in c.repo_group_create_choices],
442 [x[0] for x in c.repo_group_create_choices],
432 [x[0] for x in c.user_group_create_choices],
443 [x[0] for x in c.user_group_create_choices],
433 [x[0] for x in c.fork_choices],
444 [x[0] for x in c.fork_choices],
434 [x[0] for x in c.inherit_default_permission_choices])()
445 [x[0] for x in c.inherit_default_permission_choices])()
435
446
436 form_result = _form.to_python(dict(self.request.POST))
447 form_result = _form.to_python(dict(self.request.POST))
437 form_result.update(
448 form_result.update(
438 {'perm_user_group_id': user_group.users_group_id})
449 {'perm_user_group_id': user_group.users_group_id})
439
450
440 PermissionModel().update_user_group_permissions(form_result)
451 PermissionModel().update_user_group_permissions(form_result)
441
452
442 Session().commit()
453 Session().commit()
443 h.flash(_('User Group global permissions updated successfully'),
454 h.flash(_('User Group global permissions updated successfully'),
444 category='success')
455 category='success')
445
456
446 except formencode.Invalid as errors:
457 except formencode.Invalid as errors:
447 defaults = errors.value
458 defaults = errors.value
448
459
449 data = render(
460 data = render(
450 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
461 'rhodecode:templates/admin/user_groups/user_group_edit.mako',
451 self._get_template_context(c), self.request)
462 self._get_template_context(c), self.request)
452 html = formencode.htmlfill.render(
463 html = formencode.htmlfill.render(
453 data,
464 data,
454 defaults=defaults,
465 defaults=defaults,
455 errors=errors.error_dict or {},
466 errors=errors.error_dict or {},
456 prefix_error=False,
467 prefix_error=False,
457 encoding="UTF-8",
468 encoding="UTF-8",
458 force_defaults=False
469 force_defaults=False
459 )
470 )
460 return Response(html)
471 return Response(html)
461 except Exception:
472 except Exception:
462 log.exception("Exception during permissions saving")
473 log.exception("Exception during permissions saving")
463 h.flash(_('An error occurred during permissions saving'),
474 h.flash(_('An error occurred during permissions saving'),
464 category='error')
475 category='error')
465
476
466 raise HTTPFound(
477 raise HTTPFound(
467 h.route_path('edit_user_group_global_perms',
478 h.route_path('edit_user_group_global_perms',
468 user_group_id=user_group_id))
479 user_group_id=user_group_id))
469
480
470 @LoginRequired()
481 @LoginRequired()
471 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
482 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
472 @view_config(
483 @view_config(
473 route_name='edit_user_group_advanced', request_method='GET',
484 route_name='edit_user_group_advanced', request_method='GET',
474 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
485 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
475 def user_group_edit_advanced(self):
486 def user_group_edit_advanced(self):
476 user_group = self.db_user_group
487 user_group = self.db_user_group
477
488
478 c = self.load_default_context()
489 c = self.load_default_context()
479 c.user_group = user_group
490 c.user_group = user_group
480 c.active = 'advanced'
491 c.active = 'advanced'
481 c.group_members_obj = sorted(
492 c.group_members_obj = sorted(
482 (x.user for x in c.user_group.members),
493 (x.user for x in c.user_group.members),
483 key=lambda u: u.username.lower())
494 key=lambda u: u.username.lower())
484
495
485 c.group_to_repos = sorted(
496 c.group_to_repos = sorted(
486 (x.repository for x in c.user_group.users_group_repo_to_perm),
497 (x.repository for x in c.user_group.users_group_repo_to_perm),
487 key=lambda u: u.repo_name.lower())
498 key=lambda u: u.repo_name.lower())
488
499
489 c.group_to_repo_groups = sorted(
500 c.group_to_repo_groups = sorted(
490 (x.group for x in c.user_group.users_group_repo_group_to_perm),
501 (x.group for x in c.user_group.users_group_repo_group_to_perm),
491 key=lambda u: u.group_name.lower())
502 key=lambda u: u.group_name.lower())
492
503
493 c.group_to_review_rules = sorted(
504 c.group_to_review_rules = sorted(
494 (x.users_group for x in c.user_group.user_group_review_rules),
505 (x.users_group for x in c.user_group.user_group_review_rules),
495 key=lambda u: u.users_group_name.lower())
506 key=lambda u: u.users_group_name.lower())
496
507
497 return self._get_template_context(c)
508 return self._get_template_context(c)
498
509
499 @LoginRequired()
510 @LoginRequired()
500 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
511 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
501 @CSRFRequired()
512 @CSRFRequired()
502 @view_config(
513 @view_config(
503 route_name='edit_user_group_advanced_sync', request_method='POST',
514 route_name='edit_user_group_advanced_sync', request_method='POST',
504 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
515 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
505 def user_group_edit_advanced_set_synchronization(self):
516 def user_group_edit_advanced_set_synchronization(self):
506 _ = self.request.translate
517 _ = self.request.translate
507 user_group = self.db_user_group
518 user_group = self.db_user_group
508 user_group_id = user_group.users_group_id
519 user_group_id = user_group.users_group_id
509
520
510 existing = user_group.group_data.get('extern_type')
521 existing = user_group.group_data.get('extern_type')
511
522
512 if existing:
523 if existing:
513 new_state = user_group.group_data
524 new_state = user_group.group_data
514 new_state['extern_type'] = None
525 new_state['extern_type'] = None
515 else:
526 else:
516 new_state = user_group.group_data
527 new_state = user_group.group_data
517 new_state['extern_type'] = 'manual'
528 new_state['extern_type'] = 'manual'
518 new_state['extern_type_set_by'] = self._rhodecode_user.username
529 new_state['extern_type_set_by'] = self._rhodecode_user.username
519
530
520 try:
531 try:
521 user_group.group_data = new_state
532 user_group.group_data = new_state
522 Session().add(user_group)
533 Session().add(user_group)
523 Session().commit()
534 Session().commit()
524
535
525 h.flash(_('User Group synchronization updated successfully'),
536 h.flash(_('User Group synchronization updated successfully'),
526 category='success')
537 category='success')
527 except Exception:
538 except Exception:
528 log.exception("Exception during sync settings saving")
539 log.exception("Exception during sync settings saving")
529 h.flash(_('An error occurred during synchronization update'),
540 h.flash(_('An error occurred during synchronization update'),
530 category='error')
541 category='error')
531
542
532 raise HTTPFound(
543 raise HTTPFound(
533 h.route_path('edit_user_group_advanced',
544 h.route_path('edit_user_group_advanced',
534 user_group_id=user_group_id))
545 user_group_id=user_group_id))
General Comments 0
You need to be logged in to leave comments. Login now