##// END OF EJS Templates
fix(permissions): use consent cache purge when creating repos, similar as groups and repo groups
super-admin -
r5242:f8424773 default
parent child Browse files
Show More
@@ -1,254 +1,253 b''
1 # Copyright (C) 2016-2023 RhodeCode GmbH
1 # Copyright (C) 2016-2023 RhodeCode GmbH
2 #
2 #
3 # This program is free software: you can redistribute it and/or modify
3 # This program is free software: you can redistribute it and/or modify
4 # it under the terms of the GNU Affero General Public License, version 3
4 # it under the terms of the GNU Affero General Public License, version 3
5 # (only), as published by the Free Software Foundation.
5 # (only), as published by the Free Software Foundation.
6 #
6 #
7 # This program is distributed in the hope that it will be useful,
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
10 # GNU General Public License for more details.
11 #
11 #
12 # You should have received a copy of the GNU Affero General Public License
12 # You should have received a copy of the GNU Affero General Public License
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 #
14 #
15 # This program is dual-licensed. If you wish to learn more about the
15 # This program is dual-licensed. If you wish to learn more about the
16 # RhodeCode Enterprise Edition, including its added features, Support services,
16 # RhodeCode Enterprise Edition, including its added features, Support services,
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
17 # and proprietary license terms, please see https://rhodecode.com/licenses/
18
18
19 import logging
19 import logging
20 import formencode
20 import formencode
21 import formencode.htmlfill
21 import formencode.htmlfill
22
22
23 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
23 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
24
24
25 from pyramid.renderers import render
25 from pyramid.renderers import render
26 from pyramid.response import Response
26 from pyramid.response import Response
27 from sqlalchemy.orm import aliased
27 from sqlalchemy.orm import aliased
28
28
29 from rhodecode import events
29 from rhodecode import events
30 from rhodecode.apps._base import BaseAppView, DataGridAppView
30 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.lib.celerylib.utils import get_task_id
31 from rhodecode.lib.celerylib.utils import get_task_id
32
32
33 from rhodecode.lib.auth import (
33 from rhodecode.lib.auth import (
34 LoginRequired, CSRFRequired, NotAnonymous,
34 LoginRequired, CSRFRequired, NotAnonymous,
35 HasPermissionAny, HasRepoGroupPermissionAny)
35 HasPermissionAny, HasRepoGroupPermissionAny)
36 from rhodecode.lib import helpers as h
36 from rhodecode.lib import helpers as h
37 from rhodecode.lib.utils import repo_name_slug
37 from rhodecode.lib.utils import repo_name_slug
38 from rhodecode.lib.utils2 import safe_int, safe_str
38 from rhodecode.lib.utils2 import safe_int, safe_str
39 from rhodecode.model.forms import RepoForm
39 from rhodecode.model.forms import RepoForm
40 from rhodecode.model.permission import PermissionModel
40 from rhodecode.model.permission import PermissionModel
41 from rhodecode.model.repo import RepoModel
41 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.scm import RepoList, RepoGroupList, ScmModel
42 from rhodecode.model.scm import RepoList, RepoGroupList, ScmModel
43 from rhodecode.model.settings import SettingsModel
43 from rhodecode.model.settings import SettingsModel
44 from rhodecode.model.db import (
44 from rhodecode.model.db import (
45 in_filter_generator, or_, func, Session, Repository, RepoGroup, User)
45 in_filter_generator, or_, func, Session, Repository, RepoGroup, User)
46
46
47 log = logging.getLogger(__name__)
47 log = logging.getLogger(__name__)
48
48
49
49
50 class AdminReposView(BaseAppView, DataGridAppView):
50 class AdminReposView(BaseAppView, DataGridAppView):
51
51
52 def load_default_context(self):
52 def load_default_context(self):
53 c = self._get_local_tmpl_context()
53 c = self._get_local_tmpl_context()
54 return c
54 return c
55
55
56 def _load_form_data(self, c):
56 def _load_form_data(self, c):
57 acl_groups = RepoGroupList(RepoGroup.query().all(),
57 acl_groups = RepoGroupList(RepoGroup.query().all(),
58 perm_set=['group.write', 'group.admin'])
58 perm_set=['group.write', 'group.admin'])
59 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
59 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
60 c.repo_groups_choices = list(map(lambda k: safe_str(k[0]), c.repo_groups))
60 c.repo_groups_choices = list(map(lambda k: safe_str(k[0]), c.repo_groups))
61 c.personal_repo_group = self._rhodecode_user.personal_repo_group
61 c.personal_repo_group = self._rhodecode_user.personal_repo_group
62
62
63 @LoginRequired()
63 @LoginRequired()
64 @NotAnonymous()
64 @NotAnonymous()
65 # perms check inside
65 # perms check inside
66 def repository_list(self):
66 def repository_list(self):
67 c = self.load_default_context()
67 c = self.load_default_context()
68 return self._get_template_context(c)
68 return self._get_template_context(c)
69
69
70 @LoginRequired()
70 @LoginRequired()
71 @NotAnonymous()
71 @NotAnonymous()
72 # perms check inside
72 # perms check inside
73 def repository_list_data(self):
73 def repository_list_data(self):
74 self.load_default_context()
74 self.load_default_context()
75 column_map = {
75 column_map = {
76 'name': 'repo_name',
76 'name': 'repo_name',
77 'desc': 'description',
77 'desc': 'description',
78 'last_change': 'updated_on',
78 'last_change': 'updated_on',
79 'owner': 'user_username',
79 'owner': 'user_username',
80 }
80 }
81 draw, start, limit = self._extract_chunk(self.request)
81 draw, start, limit = self._extract_chunk(self.request)
82 search_q, order_by, order_dir = self._extract_ordering(
82 search_q, order_by, order_dir = self._extract_ordering(
83 self.request, column_map=column_map)
83 self.request, column_map=column_map)
84
84
85 _perms = ['repository.admin']
85 _perms = ['repository.admin']
86 allowed_ids = [-1] + self._rhodecode_user.repo_acl_ids_from_stack(_perms)
86 allowed_ids = [-1] + self._rhodecode_user.repo_acl_ids_from_stack(_perms)
87
87
88 repos_data_total_count = Repository.query() \
88 repos_data_total_count = Repository.query() \
89 .filter(or_(
89 .filter(or_(
90 # generate multiple IN to fix limitation problems
90 # generate multiple IN to fix limitation problems
91 *in_filter_generator(Repository.repo_id, allowed_ids))
91 *in_filter_generator(Repository.repo_id, allowed_ids))
92 ) \
92 ) \
93 .count()
93 .count()
94
94
95 RepoFork = aliased(Repository)
95 RepoFork = aliased(Repository)
96 OwnerUser = aliased(User)
96 OwnerUser = aliased(User)
97 base_q = Session.query(
97 base_q = Session.query(
98 Repository.repo_id,
98 Repository.repo_id,
99 Repository.repo_name,
99 Repository.repo_name,
100 Repository.description,
100 Repository.description,
101 Repository.repo_type,
101 Repository.repo_type,
102 Repository.repo_state,
102 Repository.repo_state,
103 Repository.private,
103 Repository.private,
104 Repository.archived,
104 Repository.archived,
105 Repository.updated_on,
105 Repository.updated_on,
106 Repository._changeset_cache,
106 Repository._changeset_cache,
107 RepoFork.repo_name.label('fork_repo_name'),
107 RepoFork.repo_name.label('fork_repo_name'),
108 OwnerUser.username.label('owner_username'),
108 OwnerUser.username.label('owner_username'),
109 ) \
109 ) \
110 .filter(or_(
110 .filter(or_(
111 # generate multiple IN to fix limitation problems
111 # generate multiple IN to fix limitation problems
112 *in_filter_generator(Repository.repo_id, allowed_ids))
112 *in_filter_generator(Repository.repo_id, allowed_ids))
113 ) \
113 ) \
114 .outerjoin(RepoFork, Repository.fork_id == RepoFork.repo_id) \
114 .outerjoin(RepoFork, Repository.fork_id == RepoFork.repo_id) \
115 .join(OwnerUser, Repository.user_id == OwnerUser.user_id)
115 .join(OwnerUser, Repository.user_id == OwnerUser.user_id)
116
116
117 if search_q:
117 if search_q:
118 like_expression = f'%{safe_str(search_q)}%'
118 like_expression = f'%{safe_str(search_q)}%'
119 base_q = base_q.filter(or_(
119 base_q = base_q.filter(or_(
120 Repository.repo_name.ilike(like_expression),
120 Repository.repo_name.ilike(like_expression),
121 ))
121 ))
122
122
123 #TODO: check if we need group_by here ?
123 #TODO: check if we need group_by here ?
124 #base_q = base_q.group_by(Repository, User)
124 #base_q = base_q.group_by(Repository, User)
125
125
126 repos_data_total_filtered_count = base_q.count()
126 repos_data_total_filtered_count = base_q.count()
127
127
128 sort_defined = False
128 sort_defined = False
129 if order_by == 'repo_name':
129 if order_by == 'repo_name':
130 sort_col = func.lower(Repository.repo_name)
130 sort_col = func.lower(Repository.repo_name)
131 sort_defined = True
131 sort_defined = True
132 elif order_by == 'user_username':
132 elif order_by == 'user_username':
133 sort_col = OwnerUser.username
133 sort_col = OwnerUser.username
134 else:
134 else:
135 sort_col = getattr(Repository, order_by, None)
135 sort_col = getattr(Repository, order_by, None)
136
136
137 if sort_defined or sort_col:
137 if sort_defined or sort_col:
138 if order_dir == 'asc':
138 if order_dir == 'asc':
139 sort_col = sort_col.asc()
139 sort_col = sort_col.asc()
140 else:
140 else:
141 sort_col = sort_col.desc()
141 sort_col = sort_col.desc()
142
142
143 base_q = base_q.order_by(sort_col)
143 base_q = base_q.order_by(sort_col)
144 base_q = base_q.offset(start).limit(limit)
144 base_q = base_q.offset(start).limit(limit)
145
145
146 repos_list = base_q.all()
146 repos_list = base_q.all()
147
147
148 repos_data = RepoModel().get_repos_as_dict(
148 repos_data = RepoModel().get_repos_as_dict(
149 repo_list=repos_list, admin=True, super_user_actions=True)
149 repo_list=repos_list, admin=True, super_user_actions=True)
150
150
151 data = ({
151 data = ({
152 'draw': draw,
152 'draw': draw,
153 'data': repos_data,
153 'data': repos_data,
154 'recordsTotal': repos_data_total_count,
154 'recordsTotal': repos_data_total_count,
155 'recordsFiltered': repos_data_total_filtered_count,
155 'recordsFiltered': repos_data_total_filtered_count,
156 })
156 })
157 return data
157 return data
158
158
159 @LoginRequired()
159 @LoginRequired()
160 @NotAnonymous()
160 @NotAnonymous()
161 # perms check inside
161 # perms check inside
162 def repository_new(self):
162 def repository_new(self):
163 c = self.load_default_context()
163 c = self.load_default_context()
164
164
165 new_repo = self.request.GET.get('repo', '')
165 new_repo = self.request.GET.get('repo', '')
166 parent_group_id = safe_int(self.request.GET.get('parent_group'))
166 parent_group_id = safe_int(self.request.GET.get('parent_group'))
167 _gr = RepoGroup.get(parent_group_id)
167 _gr = RepoGroup.get(parent_group_id)
168
168
169 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
169 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
170 # you're not super admin nor have global create permissions,
170 # you're not super admin nor have global create permissions,
171 # but maybe you have at least write permission to a parent group ?
171 # but maybe you have at least write permission to a parent group ?
172
172
173 gr_name = _gr.group_name if _gr else None
173 gr_name = _gr.group_name if _gr else None
174 # create repositories with write permission on group is set to true
174 # create repositories with write permission on group is set to true
175 create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
175 create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
176 group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
176 group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
177 group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
177 group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
178 if not (group_admin or (group_write and create_on_write)):
178 if not (group_admin or (group_write and create_on_write)):
179 raise HTTPForbidden()
179 raise HTTPForbidden()
180
180
181 self._load_form_data(c)
181 self._load_form_data(c)
182 c.new_repo = repo_name_slug(new_repo)
182 c.new_repo = repo_name_slug(new_repo)
183
183
184 # apply the defaults from defaults page
184 # apply the defaults from defaults page
185 defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
185 defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
186 # set checkbox to autochecked
186 # set checkbox to autochecked
187 defaults['repo_copy_permissions'] = True
187 defaults['repo_copy_permissions'] = True
188
188
189 parent_group_choice = '-1'
189 parent_group_choice = '-1'
190 if not self._rhodecode_user.is_admin and self._rhodecode_user.personal_repo_group:
190 if not self._rhodecode_user.is_admin and self._rhodecode_user.personal_repo_group:
191 parent_group_choice = self._rhodecode_user.personal_repo_group
191 parent_group_choice = self._rhodecode_user.personal_repo_group
192
192
193 if parent_group_id and _gr:
193 if parent_group_id and _gr:
194 if parent_group_id in [x[0] for x in c.repo_groups]:
194 if parent_group_id in [x[0] for x in c.repo_groups]:
195 parent_group_choice = safe_str(parent_group_id)
195 parent_group_choice = safe_str(parent_group_id)
196
196
197 defaults.update({'repo_group': parent_group_choice})
197 defaults.update({'repo_group': parent_group_choice})
198
198
199 data = render('rhodecode:templates/admin/repos/repo_add.mako',
199 data = render('rhodecode:templates/admin/repos/repo_add.mako',
200 self._get_template_context(c), self.request)
200 self._get_template_context(c), self.request)
201 html = formencode.htmlfill.render(
201 html = formencode.htmlfill.render(
202 data,
202 data,
203 defaults=defaults,
203 defaults=defaults,
204 encoding="UTF-8",
204 encoding="UTF-8",
205 force_defaults=False
205 force_defaults=False
206 )
206 )
207 return Response(html)
207 return Response(html)
208
208
209 @LoginRequired()
209 @LoginRequired()
210 @NotAnonymous()
210 @NotAnonymous()
211 @CSRFRequired()
211 @CSRFRequired()
212 # perms check inside
212 # perms check inside
213 def repository_create(self):
213 def repository_create(self):
214 c = self.load_default_context()
214 c = self.load_default_context()
215
215
216 form_result = {}
216 form_result = {}
217 self._load_form_data(c)
217 self._load_form_data(c)
218
218
219 try:
219 try:
220 # CanWriteToGroup validators checks permissions of this POST
220 # CanWriteToGroup validators checks permissions of this POST
221 form = RepoForm(
221 form = RepoForm(
222 self.request.translate, repo_groups=c.repo_groups_choices)()
222 self.request.translate, repo_groups=c.repo_groups_choices)()
223 form_result = form.to_python(dict(self.request.POST))
223 form_result = form.to_python(dict(self.request.POST))
224 copy_permissions = form_result.get('repo_copy_permissions')
224 copy_permissions = form_result.get('repo_copy_permissions')
225 # create is done sometimes async on celery, db transaction
225 # create is done sometimes async on celery, db transaction
226 # management is handled there.
226 # management is handled there.
227 task = RepoModel().create(form_result, self._rhodecode_user.user_id)
227 task = RepoModel().create(form_result, self._rhodecode_user.user_id)
228 task_id = get_task_id(task)
228 task_id = get_task_id(task)
229 except formencode.Invalid as errors:
229 except formencode.Invalid as errors:
230 data = render('rhodecode:templates/admin/repos/repo_add.mako',
230 data = render('rhodecode:templates/admin/repos/repo_add.mako',
231 self._get_template_context(c), self.request)
231 self._get_template_context(c), self.request)
232 html = formencode.htmlfill.render(
232 html = formencode.htmlfill.render(
233 data,
233 data,
234 defaults=errors.value,
234 defaults=errors.value,
235 errors=errors.unpack_errors() or {},
235 errors=errors.unpack_errors() or {},
236 prefix_error=False,
236 prefix_error=False,
237 encoding="UTF-8",
237 encoding="UTF-8",
238 force_defaults=False
238 force_defaults=False
239 )
239 )
240 return Response(html)
240 return Response(html)
241
241
242 except Exception as e:
242 except Exception as e:
243 msg = self._log_creation_exception(e, form_result.get('repo_name'))
243 msg = self._log_creation_exception(e, form_result.get('repo_name'))
244 h.flash(msg, category='error')
244 h.flash(msg, category='error')
245 raise HTTPFound(h.route_path('home'))
245 raise HTTPFound(h.route_path('home'))
246
246
247 repo_name = form_result.get('repo_name_full')
247 repo_name = form_result.get('repo_name_full')
248
248
249 affected_user_ids = [self._rhodecode_user.user_id]
249 PermissionModel().trigger_permission_flush()
250 PermissionModel().trigger_permission_flush(affected_user_ids)
251
250
252 raise HTTPFound(
251 raise HTTPFound(
253 h.route_path('repo_creating', repo_name=repo_name,
252 h.route_path('repo_creating', repo_name=repo_name,
254 _query=dict(task_id=task_id)))
253 _query=dict(task_id=task_id)))
General Comments 0
You need to be logged in to leave comments. Login now