##// END OF EJS Templates
permissions: flush cache when creating a new fork.
marcink -
r2874:b71876f9 default
parent child Browse files
Show More
@@ -1,43 +1,43 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22
23 23 from rhodecode import events
24 24 from rhodecode.lib import rc_cache
25 25
26 26 log = logging.getLogger(__name__)
27 27
28 28
29 29 def trigger_user_permission_flush(event):
30 30 """
31 Subscriber to the `UserPermissionChange`. This triggers the
31 Subscriber to the `UserPermissionsChange`. This triggers the
32 32 automatic flush of permission caches, so the users affected receive new permissions
33 33 Right Away
34 34 """
35 35 affected_user_ids = event.user_ids
36 36 for user_id in affected_user_ids:
37 37 cache_namespace_uid = 'cache_user_auth.{}'.format(user_id)
38 38 del_keys = rc_cache.clear_cache_namespace('cache_perms', cache_namespace_uid)
39 39 log.debug('Deleted %s cache keys for user_id: %s', del_keys, user_id)
40 40
41 41
42 42 def includeme(config):
43 43 config.add_subscriber(trigger_user_permission_flush, events.UserPermissionsChange)
@@ -1,259 +1,263 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2011-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import datetime
23 23 import formencode
24 24 import formencode.htmlfill
25 25
26 26 from pyramid.httpexceptions import HTTPFound
27 27 from pyramid.view import view_config
28 28 from pyramid.renderers import render
29 29 from pyramid.response import Response
30 30
31 from rhodecode import events
31 32 from rhodecode.apps._base import RepoAppView, DataGridAppView
32 33 from rhodecode.lib.auth import (
33 34 LoginRequired, HasRepoPermissionAnyDecorator, NotAnonymous,
34 35 HasRepoPermissionAny, HasPermissionAnyDecorator, CSRFRequired)
35 36 import rhodecode.lib.helpers as h
36 37 from rhodecode.lib.celerylib.utils import get_task_id
37 38 from rhodecode.model.db import coalesce, or_, Repository, RepoGroup
38 39 from rhodecode.model.repo import RepoModel
39 40 from rhodecode.model.forms import RepoForkForm
40 41 from rhodecode.model.scm import ScmModel, RepoGroupList
41 42 from rhodecode.lib.utils2 import safe_int, safe_unicode
42 43
43 44 log = logging.getLogger(__name__)
44 45
45 46
46 47 class RepoForksView(RepoAppView, DataGridAppView):
47 48
48 49 def load_default_context(self):
49 50 c = self._get_local_tmpl_context(include_app_defaults=True)
50 51 c.rhodecode_repo = self.rhodecode_vcs_repo
51 52
52 53 acl_groups = RepoGroupList(
53 54 RepoGroup.query().all(),
54 55 perm_set=['group.write', 'group.admin'])
55 56 c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
56 57 c.repo_groups_choices = map(lambda k: safe_unicode(k[0]), c.repo_groups)
57 58 choices, c.landing_revs = ScmModel().get_repo_landing_revs(
58 59 self.request.translate)
59 60 c.landing_revs_choices = choices
60 61 c.personal_repo_group = c.rhodecode_user.personal_repo_group
61 62
62 63 return c
63 64
64 65 @LoginRequired()
65 66 @HasRepoPermissionAnyDecorator(
66 67 'repository.read', 'repository.write', 'repository.admin')
67 68 @view_config(
68 69 route_name='repo_forks_show_all', request_method='GET',
69 70 renderer='rhodecode:templates/forks/forks.mako')
70 71 def repo_forks_show_all(self):
71 72 c = self.load_default_context()
72 73 return self._get_template_context(c)
73 74
74 75 @LoginRequired()
75 76 @HasRepoPermissionAnyDecorator(
76 77 'repository.read', 'repository.write', 'repository.admin')
77 78 @view_config(
78 79 route_name='repo_forks_data', request_method='GET',
79 80 renderer='json_ext', xhr=True)
80 81 def repo_forks_data(self):
81 82 _ = self.request.translate
82 83 self.load_default_context()
83 84 column_map = {
84 85 'fork_name': 'repo_name',
85 86 'fork_date': 'created_on',
86 87 'last_activity': 'updated_on'
87 88 }
88 89 draw, start, limit = self._extract_chunk(self.request)
89 90 search_q, order_by, order_dir = self._extract_ordering(
90 91 self.request, column_map=column_map)
91 92
92 93 acl_check = HasRepoPermissionAny(
93 94 'repository.read', 'repository.write', 'repository.admin')
94 95 repo_id = self.db_repo.repo_id
95 96 allowed_ids = [-1]
96 97 for f in Repository.query().filter(Repository.fork_id == repo_id):
97 98 if acl_check(f.repo_name, 'get forks check'):
98 99 allowed_ids.append(f.repo_id)
99 100
100 101 forks_data_total_count = Repository.query()\
101 102 .filter(Repository.fork_id == repo_id)\
102 103 .filter(Repository.repo_id.in_(allowed_ids))\
103 104 .count()
104 105
105 106 # json generate
106 107 base_q = Repository.query()\
107 108 .filter(Repository.fork_id == repo_id)\
108 109 .filter(Repository.repo_id.in_(allowed_ids))\
109 110
110 111 if search_q:
111 112 like_expression = u'%{}%'.format(safe_unicode(search_q))
112 113 base_q = base_q.filter(or_(
113 114 Repository.repo_name.ilike(like_expression),
114 115 Repository.description.ilike(like_expression),
115 116 ))
116 117
117 118 forks_data_total_filtered_count = base_q.count()
118 119
119 120 sort_col = getattr(Repository, order_by, None)
120 121 if sort_col:
121 122 if order_dir == 'asc':
122 123 # handle null values properly to order by NULL last
123 124 if order_by in ['last_activity']:
124 125 sort_col = coalesce(sort_col, datetime.date.max)
125 126 sort_col = sort_col.asc()
126 127 else:
127 128 # handle null values properly to order by NULL last
128 129 if order_by in ['last_activity']:
129 130 sort_col = coalesce(sort_col, datetime.date.min)
130 131 sort_col = sort_col.desc()
131 132
132 133 base_q = base_q.order_by(sort_col)
133 134 base_q = base_q.offset(start).limit(limit)
134 135
135 136 fork_list = base_q.all()
136 137
137 138 def fork_actions(fork):
138 139 url_link = h.route_path(
139 140 'repo_compare',
140 141 repo_name=fork.repo_name,
141 142 source_ref_type=self.db_repo.landing_rev[0],
142 143 source_ref=self.db_repo.landing_rev[1],
143 144 target_ref_type=self.db_repo.landing_rev[0],
144 145 target_ref=self.db_repo.landing_rev[1],
145 146 _query=dict(merge=1, target_repo=f.repo_name))
146 147 return h.link_to(_('Compare fork'), url_link, class_='btn-link')
147 148
148 149 def fork_name(fork):
149 150 return h.link_to(fork.repo_name,
150 151 h.route_path('repo_summary', repo_name=fork.repo_name))
151 152
152 153 forks_data = []
153 154 for fork in fork_list:
154 155 forks_data.append({
155 156 "username": h.gravatar_with_user(self.request, fork.user.username),
156 157 "fork_name": fork_name(fork),
157 158 "description": fork.description,
158 159 "fork_date": h.age_component(fork.created_on, time_is_local=True),
159 160 "last_activity": h.format_date(fork.updated_on),
160 161 "action": fork_actions(fork),
161 162 })
162 163
163 164 data = ({
164 165 'draw': draw,
165 166 'data': forks_data,
166 167 'recordsTotal': forks_data_total_count,
167 168 'recordsFiltered': forks_data_total_filtered_count,
168 169 })
169 170
170 171 return data
171 172
172 173 @LoginRequired()
173 174 @NotAnonymous()
174 175 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
175 176 @HasRepoPermissionAnyDecorator(
176 177 'repository.read', 'repository.write', 'repository.admin')
177 178 @view_config(
178 179 route_name='repo_fork_new', request_method='GET',
179 180 renderer='rhodecode:templates/forks/forks.mako')
180 181 def repo_fork_new(self):
181 182 c = self.load_default_context()
182 183
183 184 defaults = RepoModel()._get_defaults(self.db_repo_name)
184 185 # alter the description to indicate a fork
185 186 defaults['description'] = (
186 187 'fork of repository: %s \n%s' % (
187 188 defaults['repo_name'], defaults['description']))
188 189 # add suffix to fork
189 190 defaults['repo_name'] = '%s-fork' % defaults['repo_name']
190 191
191 192 data = render('rhodecode:templates/forks/fork.mako',
192 193 self._get_template_context(c), self.request)
193 194 html = formencode.htmlfill.render(
194 195 data,
195 196 defaults=defaults,
196 197 encoding="UTF-8",
197 198 force_defaults=False
198 199 )
199 200 return Response(html)
200 201
201 202 @LoginRequired()
202 203 @NotAnonymous()
203 204 @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
204 205 @HasRepoPermissionAnyDecorator(
205 206 'repository.read', 'repository.write', 'repository.admin')
206 207 @CSRFRequired()
207 208 @view_config(
208 209 route_name='repo_fork_create', request_method='POST',
209 210 renderer='rhodecode:templates/forks/fork.mako')
210 211 def repo_fork_create(self):
211 212 _ = self.request.translate
212 213 c = self.load_default_context()
213 214
214 215 _form = RepoForkForm(self.request.translate, old_data={'repo_type': self.db_repo.repo_type},
215 216 repo_groups=c.repo_groups_choices,
216 217 landing_revs=c.landing_revs_choices)()
217 218 post_data = dict(self.request.POST)
218 219
219 220 # forbid injecting other repo by forging a request
220 221 post_data['fork_parent_id'] = self.db_repo.repo_id
221 222
222 223 form_result = {}
223 224 task_id = None
224 225 try:
225 226 form_result = _form.to_python(post_data)
226 227 # create fork is done sometimes async on celery, db transaction
227 228 # management is handled there.
228 229 task = RepoModel().create_fork(
229 230 form_result, c.rhodecode_user.user_id)
230 231
231 232 task_id = get_task_id(task)
232 233 except formencode.Invalid as errors:
233 234 c.rhodecode_db_repo = self.db_repo
234 235
235 236 data = render('rhodecode:templates/forks/fork.mako',
236 237 self._get_template_context(c), self.request)
237 238 html = formencode.htmlfill.render(
238 239 data,
239 240 defaults=errors.value,
240 241 errors=errors.error_dict or {},
241 242 prefix_error=False,
242 243 encoding="UTF-8",
243 244 force_defaults=False
244 245 )
245 246 return Response(html)
246 247 except Exception:
247 248 log.exception(
248 249 u'Exception while trying to fork the repository %s',
249 250 self.db_repo_name)
250 251 msg = (
251 252 _('An error occurred during repository forking %s') % (
252 253 self.db_repo_name, ))
253 254 h.flash(msg, category='error')
254 255
255 256 repo_name = form_result.get('repo_name_full', self.db_repo_name)
257
258 events.trigger(events.UserPermissionsChange([self._rhodecode_user.user_id]))
259
256 260 raise HTTPFound(
257 261 h.route_path('repo_creating',
258 262 repo_name=repo_name,
259 263 _query=dict(task_id=task_id)))
General Comments 0
You need to be logged in to leave comments. Login now