##// END OF EJS Templates
repos: only flush permissions for owner on creation. The repo creation task flushes ALL and can be done async
super-admin -
r4869:dbc52491 default
parent child Browse files
Show More
@@ -1,249 +1,250 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2020 RhodeCode GmbH
3 # Copyright (C) 2016-2020 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 formencode
22 import formencode
23 import formencode.htmlfill
23 import formencode.htmlfill
24
24
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
25 from pyramid.httpexceptions import HTTPFound, HTTPForbidden
26
26
27 from pyramid.renderers import render
27 from pyramid.renderers import render
28 from pyramid.response import Response
28 from pyramid.response import Response
29
29
30 from rhodecode import events
30 from rhodecode import events
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 from rhodecode.lib.celerylib.utils import get_task_id
32 from rhodecode.lib.celerylib.utils import get_task_id
33
33
34 from rhodecode.lib.auth import (
34 from rhodecode.lib.auth import (
35 LoginRequired, CSRFRequired, NotAnonymous,
35 LoginRequired, CSRFRequired, NotAnonymous,
36 HasPermissionAny, HasRepoGroupPermissionAny)
36 HasPermissionAny, HasRepoGroupPermissionAny)
37 from rhodecode.lib import helpers as h
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib.utils import repo_name_slug
38 from rhodecode.lib.utils import repo_name_slug
39 from rhodecode.lib.utils2 import safe_int, safe_unicode
39 from rhodecode.lib.utils2 import safe_int, safe_unicode
40 from rhodecode.model.forms import RepoForm
40 from rhodecode.model.forms import RepoForm
41 from rhodecode.model.permission import PermissionModel
41 from rhodecode.model.permission import PermissionModel
42 from rhodecode.model.repo import RepoModel
42 from rhodecode.model.repo import RepoModel
43 from rhodecode.model.scm import RepoList, RepoGroupList, ScmModel
43 from rhodecode.model.scm import RepoList, RepoGroupList, ScmModel
44 from rhodecode.model.settings import SettingsModel
44 from rhodecode.model.settings import SettingsModel
45 from rhodecode.model.db import (
45 from rhodecode.model.db import (
46 in_filter_generator, or_, func, Session, Repository, RepoGroup, User)
46 in_filter_generator, or_, func, Session, Repository, RepoGroup, User)
47
47
48 log = logging.getLogger(__name__)
48 log = logging.getLogger(__name__)
49
49
50
50
51 class AdminReposView(BaseAppView, DataGridAppView):
51 class AdminReposView(BaseAppView, DataGridAppView):
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 return c
55 return c
56
56
57 def _load_form_data(self, c):
57 def _load_form_data(self, c):
58 acl_groups = RepoGroupList(RepoGroup.query().all(),
58 acl_groups = RepoGroupList(RepoGroup.query().all(),
59 perm_set=['group.write', 'group.admin'])
59 perm_set=['group.write', 'group.admin'])
60 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
60 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
61 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
61 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
62 c.personal_repo_group = self._rhodecode_user.personal_repo_group
62 c.personal_repo_group = self._rhodecode_user.personal_repo_group
63
63
64 @LoginRequired()
64 @LoginRequired()
65 @NotAnonymous()
65 @NotAnonymous()
66 # perms check inside
66 # perms check inside
67 def repository_list(self):
67 def repository_list(self):
68 c = self.load_default_context()
68 c = self.load_default_context()
69 return self._get_template_context(c)
69 return self._get_template_context(c)
70
70
71 @LoginRequired()
71 @LoginRequired()
72 @NotAnonymous()
72 @NotAnonymous()
73 # perms check inside
73 # perms check inside
74 def repository_list_data(self):
74 def repository_list_data(self):
75 self.load_default_context()
75 self.load_default_context()
76 column_map = {
76 column_map = {
77 'name': 'repo_name',
77 'name': 'repo_name',
78 'desc': 'description',
78 'desc': 'description',
79 'last_change': 'updated_on',
79 'last_change': 'updated_on',
80 'owner': 'user_username',
80 'owner': 'user_username',
81 }
81 }
82 draw, start, limit = self._extract_chunk(self.request)
82 draw, start, limit = self._extract_chunk(self.request)
83 search_q, order_by, order_dir = self._extract_ordering(
83 search_q, order_by, order_dir = self._extract_ordering(
84 self.request, column_map=column_map)
84 self.request, column_map=column_map)
85
85
86 _perms = ['repository.admin']
86 _perms = ['repository.admin']
87 allowed_ids = [-1] + self._rhodecode_user.repo_acl_ids_from_stack(_perms)
87 allowed_ids = [-1] + self._rhodecode_user.repo_acl_ids_from_stack(_perms)
88
88
89 repos_data_total_count = Repository.query() \
89 repos_data_total_count = Repository.query() \
90 .filter(or_(
90 .filter(or_(
91 # generate multiple IN to fix limitation problems
91 # generate multiple IN to fix limitation problems
92 *in_filter_generator(Repository.repo_id, allowed_ids))
92 *in_filter_generator(Repository.repo_id, allowed_ids))
93 ) \
93 ) \
94 .count()
94 .count()
95
95
96 base_q = Session.query(
96 base_q = Session.query(
97 Repository.repo_id,
97 Repository.repo_id,
98 Repository.repo_name,
98 Repository.repo_name,
99 Repository.description,
99 Repository.description,
100 Repository.repo_type,
100 Repository.repo_type,
101 Repository.repo_state,
101 Repository.repo_state,
102 Repository.private,
102 Repository.private,
103 Repository.archived,
103 Repository.archived,
104 Repository.fork,
104 Repository.fork,
105 Repository.updated_on,
105 Repository.updated_on,
106 Repository._changeset_cache,
106 Repository._changeset_cache,
107 User,
107 User,
108 ) \
108 ) \
109 .filter(or_(
109 .filter(or_(
110 # generate multiple IN to fix limitation problems
110 # generate multiple IN to fix limitation problems
111 *in_filter_generator(Repository.repo_id, allowed_ids))
111 *in_filter_generator(Repository.repo_id, allowed_ids))
112 ) \
112 ) \
113 .join(User, User.user_id == Repository.user_id) \
113 .join(User, User.user_id == Repository.user_id) \
114 .group_by(Repository, User)
114 .group_by(Repository, User)
115
115
116 if search_q:
116 if search_q:
117 like_expression = u'%{}%'.format(safe_unicode(search_q))
117 like_expression = u'%{}%'.format(safe_unicode(search_q))
118 base_q = base_q.filter(or_(
118 base_q = base_q.filter(or_(
119 Repository.repo_name.ilike(like_expression),
119 Repository.repo_name.ilike(like_expression),
120 ))
120 ))
121
121
122 repos_data_total_filtered_count = base_q.count()
122 repos_data_total_filtered_count = base_q.count()
123
123
124 sort_defined = False
124 sort_defined = False
125 if order_by == 'repo_name':
125 if order_by == 'repo_name':
126 sort_col = func.lower(Repository.repo_name)
126 sort_col = func.lower(Repository.repo_name)
127 sort_defined = True
127 sort_defined = True
128 elif order_by == 'user_username':
128 elif order_by == 'user_username':
129 sort_col = User.username
129 sort_col = User.username
130 else:
130 else:
131 sort_col = getattr(Repository, order_by, None)
131 sort_col = getattr(Repository, order_by, None)
132
132
133 if sort_defined or sort_col:
133 if sort_defined or sort_col:
134 if order_dir == 'asc':
134 if order_dir == 'asc':
135 sort_col = sort_col.asc()
135 sort_col = sort_col.asc()
136 else:
136 else:
137 sort_col = sort_col.desc()
137 sort_col = sort_col.desc()
138
138
139 base_q = base_q.order_by(sort_col)
139 base_q = base_q.order_by(sort_col)
140 base_q = base_q.offset(start).limit(limit)
140 base_q = base_q.offset(start).limit(limit)
141
141
142 repos_list = base_q.all()
142 repos_list = base_q.all()
143
143
144 repos_data = RepoModel().get_repos_as_dict(
144 repos_data = RepoModel().get_repos_as_dict(
145 repo_list=repos_list, admin=True, super_user_actions=True)
145 repo_list=repos_list, admin=True, super_user_actions=True)
146
146
147 data = ({
147 data = ({
148 'draw': draw,
148 'draw': draw,
149 'data': repos_data,
149 'data': repos_data,
150 'recordsTotal': repos_data_total_count,
150 'recordsTotal': repos_data_total_count,
151 'recordsFiltered': repos_data_total_filtered_count,
151 'recordsFiltered': repos_data_total_filtered_count,
152 })
152 })
153 return data
153 return data
154
154
155 @LoginRequired()
155 @LoginRequired()
156 @NotAnonymous()
156 @NotAnonymous()
157 # perms check inside
157 # perms check inside
158 def repository_new(self):
158 def repository_new(self):
159 c = self.load_default_context()
159 c = self.load_default_context()
160
160
161 new_repo = self.request.GET.get('repo', '')
161 new_repo = self.request.GET.get('repo', '')
162 parent_group_id = safe_int(self.request.GET.get('parent_group'))
162 parent_group_id = safe_int(self.request.GET.get('parent_group'))
163 _gr = RepoGroup.get(parent_group_id)
163 _gr = RepoGroup.get(parent_group_id)
164
164
165 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
165 if not HasPermissionAny('hg.admin', 'hg.create.repository')():
166 # you're not super admin nor have global create permissions,
166 # you're not super admin nor have global create permissions,
167 # but maybe you have at least write permission to a parent group ?
167 # but maybe you have at least write permission to a parent group ?
168
168
169 gr_name = _gr.group_name if _gr else None
169 gr_name = _gr.group_name if _gr else None
170 # create repositories with write permission on group is set to true
170 # create repositories with write permission on group is set to true
171 create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
171 create_on_write = HasPermissionAny('hg.create.write_on_repogroup.true')()
172 group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
172 group_admin = HasRepoGroupPermissionAny('group.admin')(group_name=gr_name)
173 group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
173 group_write = HasRepoGroupPermissionAny('group.write')(group_name=gr_name)
174 if not (group_admin or (group_write and create_on_write)):
174 if not (group_admin or (group_write and create_on_write)):
175 raise HTTPForbidden()
175 raise HTTPForbidden()
176
176
177 self._load_form_data(c)
177 self._load_form_data(c)
178 c.new_repo = repo_name_slug(new_repo)
178 c.new_repo = repo_name_slug(new_repo)
179
179
180 # apply the defaults from defaults page
180 # apply the defaults from defaults page
181 defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
181 defaults = SettingsModel().get_default_repo_settings(strip_prefix=True)
182 # set checkbox to autochecked
182 # set checkbox to autochecked
183 defaults['repo_copy_permissions'] = True
183 defaults['repo_copy_permissions'] = True
184
184
185 parent_group_choice = '-1'
185 parent_group_choice = '-1'
186 if not self._rhodecode_user.is_admin and self._rhodecode_user.personal_repo_group:
186 if not self._rhodecode_user.is_admin and self._rhodecode_user.personal_repo_group:
187 parent_group_choice = self._rhodecode_user.personal_repo_group
187 parent_group_choice = self._rhodecode_user.personal_repo_group
188
188
189 if parent_group_id and _gr:
189 if parent_group_id and _gr:
190 if parent_group_id in [x[0] for x in c.repo_groups]:
190 if parent_group_id in [x[0] for x in c.repo_groups]:
191 parent_group_choice = safe_unicode(parent_group_id)
191 parent_group_choice = safe_unicode(parent_group_id)
192
192
193 defaults.update({'repo_group': parent_group_choice})
193 defaults.update({'repo_group': parent_group_choice})
194
194
195 data = render('rhodecode:templates/admin/repos/repo_add.mako',
195 data = render('rhodecode:templates/admin/repos/repo_add.mako',
196 self._get_template_context(c), self.request)
196 self._get_template_context(c), self.request)
197 html = formencode.htmlfill.render(
197 html = formencode.htmlfill.render(
198 data,
198 data,
199 defaults=defaults,
199 defaults=defaults,
200 encoding="UTF-8",
200 encoding="UTF-8",
201 force_defaults=False
201 force_defaults=False
202 )
202 )
203 return Response(html)
203 return Response(html)
204
204
205 @LoginRequired()
205 @LoginRequired()
206 @NotAnonymous()
206 @NotAnonymous()
207 @CSRFRequired()
207 @CSRFRequired()
208 # perms check inside
208 # perms check inside
209 def repository_create(self):
209 def repository_create(self):
210 c = self.load_default_context()
210 c = self.load_default_context()
211
211
212 form_result = {}
212 form_result = {}
213 self._load_form_data(c)
213 self._load_form_data(c)
214
214
215 try:
215 try:
216 # CanWriteToGroup validators checks permissions of this POST
216 # CanWriteToGroup validators checks permissions of this POST
217 form = RepoForm(
217 form = RepoForm(
218 self.request.translate, repo_groups=c.repo_groups_choices)()
218 self.request.translate, repo_groups=c.repo_groups_choices)()
219 form_result = form.to_python(dict(self.request.POST))
219 form_result = form.to_python(dict(self.request.POST))
220 copy_permissions = form_result.get('repo_copy_permissions')
220 copy_permissions = form_result.get('repo_copy_permissions')
221 # create is done sometimes async on celery, db transaction
221 # create is done sometimes async on celery, db transaction
222 # management is handled there.
222 # management is handled there.
223 task = RepoModel().create(form_result, self._rhodecode_user.user_id)
223 task = RepoModel().create(form_result, self._rhodecode_user.user_id)
224 task_id = get_task_id(task)
224 task_id = get_task_id(task)
225 except formencode.Invalid as errors:
225 except formencode.Invalid as errors:
226 data = render('rhodecode:templates/admin/repos/repo_add.mako',
226 data = render('rhodecode:templates/admin/repos/repo_add.mako',
227 self._get_template_context(c), self.request)
227 self._get_template_context(c), self.request)
228 html = formencode.htmlfill.render(
228 html = formencode.htmlfill.render(
229 data,
229 data,
230 defaults=errors.value,
230 defaults=errors.value,
231 errors=errors.error_dict or {},
231 errors=errors.error_dict or {},
232 prefix_error=False,
232 prefix_error=False,
233 encoding="UTF-8",
233 encoding="UTF-8",
234 force_defaults=False
234 force_defaults=False
235 )
235 )
236 return Response(html)
236 return Response(html)
237
237
238 except Exception as e:
238 except Exception as e:
239 msg = self._log_creation_exception(e, form_result.get('repo_name'))
239 msg = self._log_creation_exception(e, form_result.get('repo_name'))
240 h.flash(msg, category='error')
240 h.flash(msg, category='error')
241 raise HTTPFound(h.route_path('home'))
241 raise HTTPFound(h.route_path('home'))
242
242
243 repo_name = form_result.get('repo_name_full')
243 repo_name = form_result.get('repo_name_full')
244
244
245 PermissionModel().trigger_permission_flush()
245 affected_user_ids = [self._rhodecode_user.user_id]
246 PermissionModel().trigger_permission_flush(affected_user_ids)
246
247
247 raise HTTPFound(
248 raise HTTPFound(
248 h.route_path('repo_creating', repo_name=repo_name,
249 h.route_path('repo_creating', repo_name=repo_name,
249 _query=dict(task_id=task_id)))
250 _query=dict(task_id=task_id)))
General Comments 0
You need to be logged in to leave comments. Login now