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