##// END OF EJS Templates
permissions: flush default user permissions on global app permission changes.
marcink -
r3384:e6231c06 default
parent child Browse files
Show More
@@ -1,509 +1,518 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2019 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 re
22 22 import logging
23 23 import formencode
24 24 import formencode.htmlfill
25 25 import datetime
26 26 from pyramid.interfaces import IRoutesMapper
27 27
28 28 from pyramid.view import view_config
29 29 from pyramid.httpexceptions import HTTPFound
30 30 from pyramid.renderers import render
31 31 from pyramid.response import Response
32 32
33 33 from rhodecode.apps._base import BaseAppView, DataGridAppView
34 34 from rhodecode.apps.ssh_support import SshKeyFileChangeEvent
35 from rhodecode.events import trigger
35 from rhodecode import events
36 36
37 37 from rhodecode.lib import helpers as h
38 38 from rhodecode.lib.auth import (
39 39 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
40 40 from rhodecode.lib.utils2 import aslist, safe_unicode
41 41 from rhodecode.model.db import (
42 42 or_, coalesce, User, UserIpMap, UserSshKeys)
43 43 from rhodecode.model.forms import (
44 44 ApplicationPermissionsForm, ObjectPermissionsForm, UserPermissionsForm)
45 45 from rhodecode.model.meta import Session
46 46 from rhodecode.model.permission import PermissionModel
47 47 from rhodecode.model.settings import SettingsModel
48 48
49 49
50 50 log = logging.getLogger(__name__)
51 51
52 52
53 53 class AdminPermissionsView(BaseAppView, DataGridAppView):
54 54 def load_default_context(self):
55 55 c = self._get_local_tmpl_context()
56 56 PermissionModel().set_global_permission_choices(
57 57 c, gettext_translator=self.request.translate)
58 58 return c
59 59
60 60 @LoginRequired()
61 61 @HasPermissionAllDecorator('hg.admin')
62 62 @view_config(
63 63 route_name='admin_permissions_application', request_method='GET',
64 64 renderer='rhodecode:templates/admin/permissions/permissions.mako')
65 65 def permissions_application(self):
66 66 c = self.load_default_context()
67 67 c.active = 'application'
68 68
69 69 c.user = User.get_default_user(refresh=True)
70 70
71 71 app_settings = SettingsModel().get_all_settings()
72 72 defaults = {
73 73 'anonymous': c.user.active,
74 74 'default_register_message': app_settings.get(
75 75 'rhodecode_register_message')
76 76 }
77 77 defaults.update(c.user.get_default_perms())
78 78
79 79 data = render('rhodecode:templates/admin/permissions/permissions.mako',
80 80 self._get_template_context(c), self.request)
81 81 html = formencode.htmlfill.render(
82 82 data,
83 83 defaults=defaults,
84 84 encoding="UTF-8",
85 85 force_defaults=False
86 86 )
87 87 return Response(html)
88 88
89 89 @LoginRequired()
90 90 @HasPermissionAllDecorator('hg.admin')
91 91 @CSRFRequired()
92 92 @view_config(
93 93 route_name='admin_permissions_application_update', request_method='POST',
94 94 renderer='rhodecode:templates/admin/permissions/permissions.mako')
95 95 def permissions_application_update(self):
96 96 _ = self.request.translate
97 97 c = self.load_default_context()
98 98 c.active = 'application'
99 99
100 100 _form = ApplicationPermissionsForm(
101 101 self.request.translate,
102 102 [x[0] for x in c.register_choices],
103 103 [x[0] for x in c.password_reset_choices],
104 104 [x[0] for x in c.extern_activate_choices])()
105 105
106 106 try:
107 107 form_result = _form.to_python(dict(self.request.POST))
108 108 form_result.update({'perm_user_name': User.DEFAULT_USER})
109 109 PermissionModel().update_application_permissions(form_result)
110 110
111 111 settings = [
112 112 ('register_message', 'default_register_message'),
113 113 ]
114 114 for setting, form_key in settings:
115 115 sett = SettingsModel().create_or_update_setting(
116 116 setting, form_result[form_key])
117 117 Session().add(sett)
118 118
119 119 Session().commit()
120 120 h.flash(_('Application permissions updated successfully'),
121 121 category='success')
122 122
123 123 except formencode.Invalid as errors:
124 124 defaults = errors.value
125 125
126 126 data = render(
127 127 'rhodecode:templates/admin/permissions/permissions.mako',
128 128 self._get_template_context(c), self.request)
129 129 html = formencode.htmlfill.render(
130 130 data,
131 131 defaults=defaults,
132 132 errors=errors.error_dict or {},
133 133 prefix_error=False,
134 134 encoding="UTF-8",
135 135 force_defaults=False
136 136 )
137 137 return Response(html)
138 138
139 139 except Exception:
140 140 log.exception("Exception during update of permissions")
141 141 h.flash(_('Error occurred during update of permissions'),
142 142 category='error')
143 143
144 affected_user_ids = [User.get_default_user().user_id]
145 events.trigger(events.UserPermissionsChange(affected_user_ids))
146
144 147 raise HTTPFound(h.route_path('admin_permissions_application'))
145 148
146 149 @LoginRequired()
147 150 @HasPermissionAllDecorator('hg.admin')
148 151 @view_config(
149 152 route_name='admin_permissions_object', request_method='GET',
150 153 renderer='rhodecode:templates/admin/permissions/permissions.mako')
151 154 def permissions_objects(self):
152 155 c = self.load_default_context()
153 156 c.active = 'objects'
154 157
155 158 c.user = User.get_default_user(refresh=True)
156 159 defaults = {}
157 160 defaults.update(c.user.get_default_perms())
158 161
159 162 data = render(
160 163 'rhodecode:templates/admin/permissions/permissions.mako',
161 164 self._get_template_context(c), self.request)
162 165 html = formencode.htmlfill.render(
163 166 data,
164 167 defaults=defaults,
165 168 encoding="UTF-8",
166 169 force_defaults=False
167 170 )
168 171 return Response(html)
169 172
170 173 @LoginRequired()
171 174 @HasPermissionAllDecorator('hg.admin')
172 175 @CSRFRequired()
173 176 @view_config(
174 177 route_name='admin_permissions_object_update', request_method='POST',
175 178 renderer='rhodecode:templates/admin/permissions/permissions.mako')
176 179 def permissions_objects_update(self):
177 180 _ = self.request.translate
178 181 c = self.load_default_context()
179 182 c.active = 'objects'
180 183
181 184 _form = ObjectPermissionsForm(
182 185 self.request.translate,
183 186 [x[0] for x in c.repo_perms_choices],
184 187 [x[0] for x in c.group_perms_choices],
185 188 [x[0] for x in c.user_group_perms_choices],
186 189 )()
187 190
188 191 try:
189 192 form_result = _form.to_python(dict(self.request.POST))
190 193 form_result.update({'perm_user_name': User.DEFAULT_USER})
191 194 PermissionModel().update_object_permissions(form_result)
192 195
193 196 Session().commit()
194 197 h.flash(_('Object permissions updated successfully'),
195 198 category='success')
196 199
197 200 except formencode.Invalid as errors:
198 201 defaults = errors.value
199 202
200 203 data = render(
201 204 'rhodecode:templates/admin/permissions/permissions.mako',
202 205 self._get_template_context(c), self.request)
203 206 html = formencode.htmlfill.render(
204 207 data,
205 208 defaults=defaults,
206 209 errors=errors.error_dict or {},
207 210 prefix_error=False,
208 211 encoding="UTF-8",
209 212 force_defaults=False
210 213 )
211 214 return Response(html)
212 215 except Exception:
213 216 log.exception("Exception during update of permissions")
214 217 h.flash(_('Error occurred during update of permissions'),
215 218 category='error')
216 219
220 affected_user_ids = [User.get_default_user().user_id]
221 events.trigger(events.UserPermissionsChange(affected_user_ids))
222
217 223 raise HTTPFound(h.route_path('admin_permissions_object'))
218 224
219 225 @LoginRequired()
220 226 @HasPermissionAllDecorator('hg.admin')
221 227 @view_config(
222 228 route_name='admin_permissions_branch', request_method='GET',
223 229 renderer='rhodecode:templates/admin/permissions/permissions.mako')
224 230 def permissions_branch(self):
225 231 c = self.load_default_context()
226 232 c.active = 'branch'
227 233
228 234 c.user = User.get_default_user(refresh=True)
229 235 defaults = {}
230 236 defaults.update(c.user.get_default_perms())
231 237
232 238 data = render(
233 239 'rhodecode:templates/admin/permissions/permissions.mako',
234 240 self._get_template_context(c), self.request)
235 241 html = formencode.htmlfill.render(
236 242 data,
237 243 defaults=defaults,
238 244 encoding="UTF-8",
239 245 force_defaults=False
240 246 )
241 247 return Response(html)
242 248
243 249 @LoginRequired()
244 250 @HasPermissionAllDecorator('hg.admin')
245 251 @view_config(
246 252 route_name='admin_permissions_global', request_method='GET',
247 253 renderer='rhodecode:templates/admin/permissions/permissions.mako')
248 254 def permissions_global(self):
249 255 c = self.load_default_context()
250 256 c.active = 'global'
251 257
252 258 c.user = User.get_default_user(refresh=True)
253 259 defaults = {}
254 260 defaults.update(c.user.get_default_perms())
255 261
256 262 data = render(
257 263 'rhodecode:templates/admin/permissions/permissions.mako',
258 264 self._get_template_context(c), self.request)
259 265 html = formencode.htmlfill.render(
260 266 data,
261 267 defaults=defaults,
262 268 encoding="UTF-8",
263 269 force_defaults=False
264 270 )
265 271 return Response(html)
266 272
267 273 @LoginRequired()
268 274 @HasPermissionAllDecorator('hg.admin')
269 275 @CSRFRequired()
270 276 @view_config(
271 277 route_name='admin_permissions_global_update', request_method='POST',
272 278 renderer='rhodecode:templates/admin/permissions/permissions.mako')
273 279 def permissions_global_update(self):
274 280 _ = self.request.translate
275 281 c = self.load_default_context()
276 282 c.active = 'global'
277 283
278 284 _form = UserPermissionsForm(
279 285 self.request.translate,
280 286 [x[0] for x in c.repo_create_choices],
281 287 [x[0] for x in c.repo_create_on_write_choices],
282 288 [x[0] for x in c.repo_group_create_choices],
283 289 [x[0] for x in c.user_group_create_choices],
284 290 [x[0] for x in c.fork_choices],
285 291 [x[0] for x in c.inherit_default_permission_choices])()
286 292
287 293 try:
288 294 form_result = _form.to_python(dict(self.request.POST))
289 295 form_result.update({'perm_user_name': User.DEFAULT_USER})
290 296 PermissionModel().update_user_permissions(form_result)
291 297
292 298 Session().commit()
293 299 h.flash(_('Global permissions updated successfully'),
294 300 category='success')
295 301
296 302 except formencode.Invalid as errors:
297 303 defaults = errors.value
298 304
299 305 data = render(
300 306 'rhodecode:templates/admin/permissions/permissions.mako',
301 307 self._get_template_context(c), self.request)
302 308 html = formencode.htmlfill.render(
303 309 data,
304 310 defaults=defaults,
305 311 errors=errors.error_dict or {},
306 312 prefix_error=False,
307 313 encoding="UTF-8",
308 314 force_defaults=False
309 315 )
310 316 return Response(html)
311 317 except Exception:
312 318 log.exception("Exception during update of permissions")
313 319 h.flash(_('Error occurred during update of permissions'),
314 320 category='error')
315 321
322 affected_user_ids = [User.get_default_user().user_id]
323 events.trigger(events.UserPermissionsChange(affected_user_ids))
324
316 325 raise HTTPFound(h.route_path('admin_permissions_global'))
317 326
318 327 @LoginRequired()
319 328 @HasPermissionAllDecorator('hg.admin')
320 329 @view_config(
321 330 route_name='admin_permissions_ips', request_method='GET',
322 331 renderer='rhodecode:templates/admin/permissions/permissions.mako')
323 332 def permissions_ips(self):
324 333 c = self.load_default_context()
325 334 c.active = 'ips'
326 335
327 336 c.user = User.get_default_user(refresh=True)
328 337 c.user_ip_map = (
329 338 UserIpMap.query().filter(UserIpMap.user == c.user).all())
330 339
331 340 return self._get_template_context(c)
332 341
333 342 @LoginRequired()
334 343 @HasPermissionAllDecorator('hg.admin')
335 344 @view_config(
336 345 route_name='admin_permissions_overview', request_method='GET',
337 346 renderer='rhodecode:templates/admin/permissions/permissions.mako')
338 347 def permissions_overview(self):
339 348 c = self.load_default_context()
340 349 c.active = 'perms'
341 350
342 351 c.user = User.get_default_user(refresh=True)
343 352 c.perm_user = c.user.AuthUser()
344 353 return self._get_template_context(c)
345 354
346 355 @LoginRequired()
347 356 @HasPermissionAllDecorator('hg.admin')
348 357 @view_config(
349 358 route_name='admin_permissions_auth_token_access', request_method='GET',
350 359 renderer='rhodecode:templates/admin/permissions/permissions.mako')
351 360 def auth_token_access(self):
352 361 from rhodecode import CONFIG
353 362
354 363 c = self.load_default_context()
355 364 c.active = 'auth_token_access'
356 365
357 366 c.user = User.get_default_user(refresh=True)
358 367 c.perm_user = c.user.AuthUser()
359 368
360 369 mapper = self.request.registry.queryUtility(IRoutesMapper)
361 370 c.view_data = []
362 371
363 372 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
364 373 introspector = self.request.registry.introspector
365 374
366 375 view_intr = {}
367 376 for view_data in introspector.get_category('views'):
368 377 intr = view_data['introspectable']
369 378
370 379 if 'route_name' in intr and intr['attr']:
371 380 view_intr[intr['route_name']] = '{}:{}'.format(
372 381 str(intr['derived_callable'].func_name), intr['attr']
373 382 )
374 383
375 384 c.whitelist_key = 'api_access_controllers_whitelist'
376 385 c.whitelist_file = CONFIG.get('__file__')
377 386 whitelist_views = aslist(
378 387 CONFIG.get(c.whitelist_key), sep=',')
379 388
380 389 for route_info in mapper.get_routes():
381 390 if not route_info.name.startswith('__'):
382 391 routepath = route_info.pattern
383 392
384 393 def replace(matchobj):
385 394 if matchobj.group(1):
386 395 return "{%s}" % matchobj.group(1).split(':')[0]
387 396 else:
388 397 return "{%s}" % matchobj.group(2)
389 398
390 399 routepath = _argument_prog.sub(replace, routepath)
391 400
392 401 if not routepath.startswith('/'):
393 402 routepath = '/' + routepath
394 403
395 404 view_fqn = view_intr.get(route_info.name, 'NOT AVAILABLE')
396 405 active = view_fqn in whitelist_views
397 406 c.view_data.append((route_info.name, view_fqn, routepath, active))
398 407
399 408 c.whitelist_views = whitelist_views
400 409 return self._get_template_context(c)
401 410
402 411 def ssh_enabled(self):
403 412 return self.request.registry.settings.get(
404 413 'ssh.generate_authorized_keyfile')
405 414
406 415 @LoginRequired()
407 416 @HasPermissionAllDecorator('hg.admin')
408 417 @view_config(
409 418 route_name='admin_permissions_ssh_keys', request_method='GET',
410 419 renderer='rhodecode:templates/admin/permissions/permissions.mako')
411 420 def ssh_keys(self):
412 421 c = self.load_default_context()
413 422 c.active = 'ssh_keys'
414 423 c.ssh_enabled = self.ssh_enabled()
415 424 return self._get_template_context(c)
416 425
417 426 @LoginRequired()
418 427 @HasPermissionAllDecorator('hg.admin')
419 428 @view_config(
420 429 route_name='admin_permissions_ssh_keys_data', request_method='GET',
421 430 renderer='json_ext', xhr=True)
422 431 def ssh_keys_data(self):
423 432 _ = self.request.translate
424 433 self.load_default_context()
425 434 column_map = {
426 435 'fingerprint': 'ssh_key_fingerprint',
427 436 'username': User.username
428 437 }
429 438 draw, start, limit = self._extract_chunk(self.request)
430 439 search_q, order_by, order_dir = self._extract_ordering(
431 440 self.request, column_map=column_map)
432 441
433 442 ssh_keys_data_total_count = UserSshKeys.query()\
434 443 .count()
435 444
436 445 # json generate
437 446 base_q = UserSshKeys.query().join(UserSshKeys.user)
438 447
439 448 if search_q:
440 449 like_expression = u'%{}%'.format(safe_unicode(search_q))
441 450 base_q = base_q.filter(or_(
442 451 User.username.ilike(like_expression),
443 452 UserSshKeys.ssh_key_fingerprint.ilike(like_expression),
444 453 ))
445 454
446 455 users_data_total_filtered_count = base_q.count()
447 456
448 457 sort_col = self._get_order_col(order_by, UserSshKeys)
449 458 if sort_col:
450 459 if order_dir == 'asc':
451 460 # handle null values properly to order by NULL last
452 461 if order_by in ['created_on']:
453 462 sort_col = coalesce(sort_col, datetime.date.max)
454 463 sort_col = sort_col.asc()
455 464 else:
456 465 # handle null values properly to order by NULL last
457 466 if order_by in ['created_on']:
458 467 sort_col = coalesce(sort_col, datetime.date.min)
459 468 sort_col = sort_col.desc()
460 469
461 470 base_q = base_q.order_by(sort_col)
462 471 base_q = base_q.offset(start).limit(limit)
463 472
464 473 ssh_keys = base_q.all()
465 474
466 475 ssh_keys_data = []
467 476 for ssh_key in ssh_keys:
468 477 ssh_keys_data.append({
469 478 "username": h.gravatar_with_user(self.request, ssh_key.user.username),
470 479 "fingerprint": ssh_key.ssh_key_fingerprint,
471 480 "description": ssh_key.description,
472 481 "created_on": h.format_date(ssh_key.created_on),
473 482 "accessed_on": h.format_date(ssh_key.accessed_on),
474 483 "action": h.link_to(
475 484 _('Edit'), h.route_path('edit_user_ssh_keys',
476 485 user_id=ssh_key.user.user_id))
477 486 })
478 487
479 488 data = ({
480 489 'draw': draw,
481 490 'data': ssh_keys_data,
482 491 'recordsTotal': ssh_keys_data_total_count,
483 492 'recordsFiltered': users_data_total_filtered_count,
484 493 })
485 494
486 495 return data
487 496
488 497 @LoginRequired()
489 498 @HasPermissionAllDecorator('hg.admin')
490 499 @CSRFRequired()
491 500 @view_config(
492 501 route_name='admin_permissions_ssh_keys_update', request_method='POST',
493 502 renderer='rhodecode:templates/admin/permissions/permissions.mako')
494 503 def ssh_keys_update(self):
495 504 _ = self.request.translate
496 505 self.load_default_context()
497 506
498 507 ssh_enabled = self.ssh_enabled()
499 508 key_file = self.request.registry.settings.get(
500 509 'ssh.authorized_keys_file_path')
501 510 if ssh_enabled:
502 trigger(SshKeyFileChangeEvent(), self.request.registry)
511 events.trigger(SshKeyFileChangeEvent(), self.request.registry)
503 512 h.flash(_('Updated SSH keys file: {}').format(key_file),
504 513 category='success')
505 514 else:
506 515 h.flash(_('SSH key support is disabled in .ini file'),
507 516 category='warning')
508 517
509 518 raise HTTPFound(h.route_path('admin_permissions_ssh_keys'))
General Comments 0
You need to be logged in to leave comments. Login now