##// END OF EJS Templates
auth: don't check for delegated admin if we are super admin.
marcink -
r3588:9ddb7b46 new-ui
parent child Browse files
Show More
@@ -1,723 +1,723 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 time
22 22 import logging
23 23 import operator
24 24
25 25 from pyramid import compat
26 26 from pyramid.httpexceptions import HTTPFound, HTTPForbidden, HTTPBadRequest
27 27
28 28 from rhodecode.lib import helpers as h, diffs
29 29 from rhodecode.lib.utils2 import (
30 30 StrictAttributeDict, str2bool, safe_int, datetime_to_time, safe_unicode)
31 31 from rhodecode.lib.vcs.exceptions import RepositoryRequirementError
32 32 from rhodecode.model import repo
33 33 from rhodecode.model import repo_group
34 34 from rhodecode.model import user_group
35 35 from rhodecode.model import user
36 36 from rhodecode.model.db import User
37 37 from rhodecode.model.scm import ScmModel
38 38 from rhodecode.model.settings import VcsSettingsModel
39 39
40 40 log = logging.getLogger(__name__)
41 41
42 42
43 43 ADMIN_PREFIX = '/_admin'
44 44 STATIC_FILE_PREFIX = '/_static'
45 45
46 46 URL_NAME_REQUIREMENTS = {
47 47 # group name can have a slash in them, but they must not end with a slash
48 48 'group_name': r'.*?[^/]',
49 49 'repo_group_name': r'.*?[^/]',
50 50 # repo names can have a slash in them, but they must not end with a slash
51 51 'repo_name': r'.*?[^/]',
52 52 # file path eats up everything at the end
53 53 'f_path': r'.*',
54 54 # reference types
55 55 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
56 56 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
57 57 }
58 58
59 59
60 60 def add_route_with_slash(config,name, pattern, **kw):
61 61 config.add_route(name, pattern, **kw)
62 62 if not pattern.endswith('/'):
63 63 config.add_route(name + '_slash', pattern + '/', **kw)
64 64
65 65
66 66 def add_route_requirements(route_path, requirements=None):
67 67 """
68 68 Adds regex requirements to pyramid routes using a mapping dict
69 69 e.g::
70 70 add_route_requirements('{repo_name}/settings')
71 71 """
72 72 requirements = requirements or URL_NAME_REQUIREMENTS
73 73 for key, regex in requirements.items():
74 74 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
75 75 return route_path
76 76
77 77
78 78 def get_format_ref_id(repo):
79 79 """Returns a `repo` specific reference formatter function"""
80 80 if h.is_svn(repo):
81 81 return _format_ref_id_svn
82 82 else:
83 83 return _format_ref_id
84 84
85 85
86 86 def _format_ref_id(name, raw_id):
87 87 """Default formatting of a given reference `name`"""
88 88 return name
89 89
90 90
91 91 def _format_ref_id_svn(name, raw_id):
92 92 """Special way of formatting a reference for Subversion including path"""
93 93 return '%s@%s' % (name, raw_id)
94 94
95 95
96 96 class TemplateArgs(StrictAttributeDict):
97 97 pass
98 98
99 99
100 100 class BaseAppView(object):
101 101
102 102 def __init__(self, context, request):
103 103 self.request = request
104 104 self.context = context
105 105 self.session = request.session
106 106 if not hasattr(request, 'user'):
107 107 # NOTE(marcink): edge case, we ended up in matched route
108 108 # but probably of web-app context, e.g API CALL/VCS CALL
109 109 if hasattr(request, 'vcs_call') or hasattr(request, 'rpc_method'):
110 110 log.warning('Unable to process request `%s` in this scope', request)
111 111 raise HTTPBadRequest()
112 112
113 113 self._rhodecode_user = request.user # auth user
114 114 self._rhodecode_db_user = self._rhodecode_user.get_instance()
115 115 self._maybe_needs_password_change(
116 116 request.matched_route.name, self._rhodecode_db_user)
117 117
118 118 def _maybe_needs_password_change(self, view_name, user_obj):
119 119 log.debug('Checking if user %s needs password change on view %s',
120 120 user_obj, view_name)
121 121 skip_user_views = [
122 122 'logout', 'login',
123 123 'my_account_password', 'my_account_password_update'
124 124 ]
125 125
126 126 if not user_obj:
127 127 return
128 128
129 129 if user_obj.username == User.DEFAULT_USER:
130 130 return
131 131
132 132 now = time.time()
133 133 should_change = user_obj.user_data.get('force_password_change')
134 134 change_after = safe_int(should_change) or 0
135 135 if should_change and now > change_after:
136 136 log.debug('User %s requires password change', user_obj)
137 137 h.flash('You are required to change your password', 'warning',
138 138 ignore_duplicate=True)
139 139
140 140 if view_name not in skip_user_views:
141 141 raise HTTPFound(
142 142 self.request.route_path('my_account_password'))
143 143
144 144 def _log_creation_exception(self, e, repo_name):
145 145 _ = self.request.translate
146 146 reason = None
147 147 if len(e.args) == 2:
148 148 reason = e.args[1]
149 149
150 150 if reason == 'INVALID_CERTIFICATE':
151 151 log.exception(
152 152 'Exception creating a repository: invalid certificate')
153 153 msg = (_('Error creating repository %s: invalid certificate')
154 154 % repo_name)
155 155 else:
156 156 log.exception("Exception creating a repository")
157 157 msg = (_('Error creating repository %s')
158 158 % repo_name)
159 159 return msg
160 160
161 161 def _get_local_tmpl_context(self, include_app_defaults=True):
162 162 c = TemplateArgs()
163 163 c.auth_user = self.request.user
164 164 # TODO(marcink): migrate the usage of c.rhodecode_user to c.auth_user
165 165 c.rhodecode_user = self.request.user
166 166
167 167 if include_app_defaults:
168 168 from rhodecode.lib.base import attach_context_attributes
169 169 attach_context_attributes(c, self.request, self.request.user.user_id)
170 170
171 171 c.is_super_admin = c.auth_user.is_admin
172 172
173 173 c.can_create_repo = c.is_super_admin
174 174 c.can_create_repo_group = c.is_super_admin
175 175 c.can_create_user_group = c.is_super_admin
176 176
177 177 c.is_delegated_admin = False
178 178
179 if not c.auth_user.is_default:
179 if not c.auth_user.is_default and not c.is_super_admin:
180 180 c.can_create_repo = h.HasPermissionAny('hg.create.repository')(
181 181 user=self.request.user)
182 182 repositories = c.auth_user.repositories_admin or c.can_create_repo
183 183
184 184 c.can_create_repo_group = h.HasPermissionAny('hg.repogroup.create.true')(
185 185 user=self.request.user)
186 186 repository_groups = c.auth_user.repository_groups_admin or c.can_create_repo_group
187 187
188 188 c.can_create_user_group = h.HasPermissionAny('hg.usergroup.create.true')(
189 189 user=self.request.user)
190 190 user_groups = c.auth_user.user_groups_admin or c.can_create_user_group
191 191 # delegated admin can create, or manage some objects
192 192 c.is_delegated_admin = repositories or repository_groups or user_groups
193 193 return c
194 194
195 195 def _get_template_context(self, tmpl_args, **kwargs):
196 196
197 197 local_tmpl_args = {
198 198 'defaults': {},
199 199 'errors': {},
200 200 'c': tmpl_args
201 201 }
202 202 local_tmpl_args.update(kwargs)
203 203 return local_tmpl_args
204 204
205 205 def load_default_context(self):
206 206 """
207 207 example:
208 208
209 209 def load_default_context(self):
210 210 c = self._get_local_tmpl_context()
211 211 c.custom_var = 'foobar'
212 212
213 213 return c
214 214 """
215 215 raise NotImplementedError('Needs implementation in view class')
216 216
217 217
218 218 class RepoAppView(BaseAppView):
219 219
220 220 def __init__(self, context, request):
221 221 super(RepoAppView, self).__init__(context, request)
222 222 self.db_repo = request.db_repo
223 223 self.db_repo_name = self.db_repo.repo_name
224 224 self.db_repo_pull_requests = ScmModel().get_pull_requests(self.db_repo)
225 225
226 226 def _handle_missing_requirements(self, error):
227 227 log.error(
228 228 'Requirements are missing for repository %s: %s',
229 229 self.db_repo_name, safe_unicode(error))
230 230
231 231 def _get_local_tmpl_context(self, include_app_defaults=True):
232 232 _ = self.request.translate
233 233 c = super(RepoAppView, self)._get_local_tmpl_context(
234 234 include_app_defaults=include_app_defaults)
235 235
236 236 # register common vars for this type of view
237 237 c.rhodecode_db_repo = self.db_repo
238 238 c.repo_name = self.db_repo_name
239 239 c.repository_pull_requests = self.db_repo_pull_requests
240 240 self.path_filter = PathFilter(None)
241 241
242 242 c.repository_requirements_missing = {}
243 243 try:
244 244 self.rhodecode_vcs_repo = self.db_repo.scm_instance()
245 245 if self.rhodecode_vcs_repo:
246 246 path_perms = self.rhodecode_vcs_repo.get_path_permissions(
247 247 c.auth_user.username)
248 248 self.path_filter = PathFilter(path_perms)
249 249 except RepositoryRequirementError as e:
250 250 c.repository_requirements_missing = {'error': str(e)}
251 251 self._handle_missing_requirements(e)
252 252 self.rhodecode_vcs_repo = None
253 253
254 254 c.path_filter = self.path_filter # used by atom_feed_entry.mako
255 255
256 256 if self.rhodecode_vcs_repo is None:
257 257 # unable to fetch this repo as vcs instance, report back to user
258 258 h.flash(_(
259 259 "The repository `%(repo_name)s` cannot be loaded in filesystem. "
260 260 "Please check if it exist, or is not damaged.") %
261 261 {'repo_name': c.repo_name},
262 262 category='error', ignore_duplicate=True)
263 263 if c.repository_requirements_missing:
264 264 route = self.request.matched_route.name
265 265 if route.startswith(('edit_repo', 'repo_summary')):
266 266 # allow summary and edit repo on missing requirements
267 267 return c
268 268
269 269 raise HTTPFound(
270 270 h.route_path('repo_summary', repo_name=self.db_repo_name))
271 271
272 272 else: # redirect if we don't show missing requirements
273 273 raise HTTPFound(h.route_path('home'))
274 274
275 275 c.has_origin_repo_read_perm = False
276 276 if self.db_repo.fork:
277 277 c.has_origin_repo_read_perm = h.HasRepoPermissionAny(
278 278 'repository.write', 'repository.read', 'repository.admin')(
279 279 self.db_repo.fork.repo_name, 'summary fork link')
280 280
281 281 return c
282 282
283 283 def _get_f_path_unchecked(self, matchdict, default=None):
284 284 """
285 285 Should only be used by redirects, everything else should call _get_f_path
286 286 """
287 287 f_path = matchdict.get('f_path')
288 288 if f_path:
289 289 # fix for multiple initial slashes that causes errors for GIT
290 290 return f_path.lstrip('/')
291 291
292 292 return default
293 293
294 294 def _get_f_path(self, matchdict, default=None):
295 295 f_path_match = self._get_f_path_unchecked(matchdict, default)
296 296 return self.path_filter.assert_path_permissions(f_path_match)
297 297
298 298 def _get_general_setting(self, target_repo, settings_key, default=False):
299 299 settings_model = VcsSettingsModel(repo=target_repo)
300 300 settings = settings_model.get_general_settings()
301 301 return settings.get(settings_key, default)
302 302
303 303 def get_recache_flag(self):
304 304 for flag_name in ['force_recache', 'force-recache', 'no-cache']:
305 305 flag_val = self.request.GET.get(flag_name)
306 306 if str2bool(flag_val):
307 307 return True
308 308 return False
309 309
310 310
311 311 class PathFilter(object):
312 312
313 313 # Expects and instance of BasePathPermissionChecker or None
314 314 def __init__(self, permission_checker):
315 315 self.permission_checker = permission_checker
316 316
317 317 def assert_path_permissions(self, path):
318 318 if path and self.permission_checker and not self.permission_checker.has_access(path):
319 319 raise HTTPForbidden()
320 320 return path
321 321
322 322 def filter_patchset(self, patchset):
323 323 if not self.permission_checker or not patchset:
324 324 return patchset, False
325 325 had_filtered = False
326 326 filtered_patchset = []
327 327 for patch in patchset:
328 328 filename = patch.get('filename', None)
329 329 if not filename or self.permission_checker.has_access(filename):
330 330 filtered_patchset.append(patch)
331 331 else:
332 332 had_filtered = True
333 333 if had_filtered:
334 334 if isinstance(patchset, diffs.LimitedDiffContainer):
335 335 filtered_patchset = diffs.LimitedDiffContainer(patchset.diff_limit, patchset.cur_diff_size, filtered_patchset)
336 336 return filtered_patchset, True
337 337 else:
338 338 return patchset, False
339 339
340 340 def render_patchset_filtered(self, diffset, patchset, source_ref=None, target_ref=None):
341 341 filtered_patchset, has_hidden_changes = self.filter_patchset(patchset)
342 342 result = diffset.render_patchset(
343 343 filtered_patchset, source_ref=source_ref, target_ref=target_ref)
344 344 result.has_hidden_changes = has_hidden_changes
345 345 return result
346 346
347 347 def get_raw_patch(self, diff_processor):
348 348 if self.permission_checker is None:
349 349 return diff_processor.as_raw()
350 350 elif self.permission_checker.has_full_access:
351 351 return diff_processor.as_raw()
352 352 else:
353 353 return '# Repository has user-specific filters, raw patch generation is disabled.'
354 354
355 355 @property
356 356 def is_enabled(self):
357 357 return self.permission_checker is not None
358 358
359 359
360 360 class RepoGroupAppView(BaseAppView):
361 361 def __init__(self, context, request):
362 362 super(RepoGroupAppView, self).__init__(context, request)
363 363 self.db_repo_group = request.db_repo_group
364 364 self.db_repo_group_name = self.db_repo_group.group_name
365 365
366 366 def _get_local_tmpl_context(self, include_app_defaults=True):
367 367 _ = self.request.translate
368 368 c = super(RepoGroupAppView, self)._get_local_tmpl_context(
369 369 include_app_defaults=include_app_defaults)
370 370 c.repo_group = self.db_repo_group
371 371 return c
372 372
373 373 def _revoke_perms_on_yourself(self, form_result):
374 374 _updates = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
375 375 form_result['perm_updates'])
376 376 _additions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
377 377 form_result['perm_additions'])
378 378 _deletions = filter(lambda u: self._rhodecode_user.user_id == int(u[0]),
379 379 form_result['perm_deletions'])
380 380 admin_perm = 'group.admin'
381 381 if _updates and _updates[0][1] != admin_perm or \
382 382 _additions and _additions[0][1] != admin_perm or \
383 383 _deletions and _deletions[0][1] != admin_perm:
384 384 return True
385 385 return False
386 386
387 387
388 388 class UserGroupAppView(BaseAppView):
389 389 def __init__(self, context, request):
390 390 super(UserGroupAppView, self).__init__(context, request)
391 391 self.db_user_group = request.db_user_group
392 392 self.db_user_group_name = self.db_user_group.users_group_name
393 393
394 394
395 395 class UserAppView(BaseAppView):
396 396 def __init__(self, context, request):
397 397 super(UserAppView, self).__init__(context, request)
398 398 self.db_user = request.db_user
399 399 self.db_user_id = self.db_user.user_id
400 400
401 401 _ = self.request.translate
402 402 if not request.db_user_supports_default:
403 403 if self.db_user.username == User.DEFAULT_USER:
404 404 h.flash(_("Editing user `{}` is disabled.".format(
405 405 User.DEFAULT_USER)), category='warning')
406 406 raise HTTPFound(h.route_path('users'))
407 407
408 408
409 409 class DataGridAppView(object):
410 410 """
411 411 Common class to have re-usable grid rendering components
412 412 """
413 413
414 414 def _extract_ordering(self, request, column_map=None):
415 415 column_map = column_map or {}
416 416 column_index = safe_int(request.GET.get('order[0][column]'))
417 417 order_dir = request.GET.get(
418 418 'order[0][dir]', 'desc')
419 419 order_by = request.GET.get(
420 420 'columns[%s][data][sort]' % column_index, 'name_raw')
421 421
422 422 # translate datatable to DB columns
423 423 order_by = column_map.get(order_by) or order_by
424 424
425 425 search_q = request.GET.get('search[value]')
426 426 return search_q, order_by, order_dir
427 427
428 428 def _extract_chunk(self, request):
429 429 start = safe_int(request.GET.get('start'), 0)
430 430 length = safe_int(request.GET.get('length'), 25)
431 431 draw = safe_int(request.GET.get('draw'))
432 432 return draw, start, length
433 433
434 434 def _get_order_col(self, order_by, model):
435 435 if isinstance(order_by, compat.string_types):
436 436 try:
437 437 return operator.attrgetter(order_by)(model)
438 438 except AttributeError:
439 439 return None
440 440 else:
441 441 return order_by
442 442
443 443
444 444 class BaseReferencesView(RepoAppView):
445 445 """
446 446 Base for reference view for branches, tags and bookmarks.
447 447 """
448 448 def load_default_context(self):
449 449 c = self._get_local_tmpl_context()
450 450
451 451
452 452 return c
453 453
454 454 def load_refs_context(self, ref_items, partials_template):
455 455 _render = self.request.get_partial_renderer(partials_template)
456 456 pre_load = ["author", "date", "message"]
457 457
458 458 is_svn = h.is_svn(self.rhodecode_vcs_repo)
459 459 is_hg = h.is_hg(self.rhodecode_vcs_repo)
460 460
461 461 format_ref_id = get_format_ref_id(self.rhodecode_vcs_repo)
462 462
463 463 closed_refs = {}
464 464 if is_hg:
465 465 closed_refs = self.rhodecode_vcs_repo.branches_closed
466 466
467 467 data = []
468 468 for ref_name, commit_id in ref_items:
469 469 commit = self.rhodecode_vcs_repo.get_commit(
470 470 commit_id=commit_id, pre_load=pre_load)
471 471 closed = ref_name in closed_refs
472 472
473 473 # TODO: johbo: Unify generation of reference links
474 474 use_commit_id = '/' in ref_name or is_svn
475 475
476 476 if use_commit_id:
477 477 files_url = h.route_path(
478 478 'repo_files',
479 479 repo_name=self.db_repo_name,
480 480 f_path=ref_name if is_svn else '',
481 481 commit_id=commit_id)
482 482
483 483 else:
484 484 files_url = h.route_path(
485 485 'repo_files',
486 486 repo_name=self.db_repo_name,
487 487 f_path=ref_name if is_svn else '',
488 488 commit_id=ref_name,
489 489 _query=dict(at=ref_name))
490 490
491 491 data.append({
492 492 "name": _render('name', ref_name, files_url, closed),
493 493 "name_raw": ref_name,
494 494 "date": _render('date', commit.date),
495 495 "date_raw": datetime_to_time(commit.date),
496 496 "author": _render('author', commit.author),
497 497 "commit": _render(
498 498 'commit', commit.message, commit.raw_id, commit.idx),
499 499 "commit_raw": commit.idx,
500 500 "compare": _render(
501 501 'compare', format_ref_id(ref_name, commit.raw_id)),
502 502 })
503 503
504 504 return data
505 505
506 506
507 507 class RepoRoutePredicate(object):
508 508 def __init__(self, val, config):
509 509 self.val = val
510 510
511 511 def text(self):
512 512 return 'repo_route = %s' % self.val
513 513
514 514 phash = text
515 515
516 516 def __call__(self, info, request):
517 517 if hasattr(request, 'vcs_call'):
518 518 # skip vcs calls
519 519 return
520 520
521 521 repo_name = info['match']['repo_name']
522 522 repo_model = repo.RepoModel()
523 523
524 524 by_name_match = repo_model.get_by_repo_name(repo_name, cache=False)
525 525
526 526 def redirect_if_creating(route_info, db_repo):
527 527 skip_views = ['edit_repo_advanced_delete']
528 528 route = route_info['route']
529 529 # we should skip delete view so we can actually "remove" repositories
530 530 # if they get stuck in creating state.
531 531 if route.name in skip_views:
532 532 return
533 533
534 534 if db_repo.repo_state in [repo.Repository.STATE_PENDING]:
535 535 repo_creating_url = request.route_path(
536 536 'repo_creating', repo_name=db_repo.repo_name)
537 537 raise HTTPFound(repo_creating_url)
538 538
539 539 if by_name_match:
540 540 # register this as request object we can re-use later
541 541 request.db_repo = by_name_match
542 542 redirect_if_creating(info, by_name_match)
543 543 return True
544 544
545 545 by_id_match = repo_model.get_repo_by_id(repo_name)
546 546 if by_id_match:
547 547 request.db_repo = by_id_match
548 548 redirect_if_creating(info, by_id_match)
549 549 return True
550 550
551 551 return False
552 552
553 553
554 554 class RepoForbidArchivedRoutePredicate(object):
555 555 def __init__(self, val, config):
556 556 self.val = val
557 557
558 558 def text(self):
559 559 return 'repo_forbid_archived = %s' % self.val
560 560
561 561 phash = text
562 562
563 563 def __call__(self, info, request):
564 564 _ = request.translate
565 565 rhodecode_db_repo = request.db_repo
566 566
567 567 log.debug(
568 568 '%s checking if archived flag for repo for %s',
569 569 self.__class__.__name__, rhodecode_db_repo.repo_name)
570 570
571 571 if rhodecode_db_repo.archived:
572 572 log.warning('Current view is not supported for archived repo:%s',
573 573 rhodecode_db_repo.repo_name)
574 574
575 575 h.flash(
576 576 h.literal(_('Action not supported for archived repository.')),
577 577 category='warning')
578 578 summary_url = request.route_path(
579 579 'repo_summary', repo_name=rhodecode_db_repo.repo_name)
580 580 raise HTTPFound(summary_url)
581 581 return True
582 582
583 583
584 584 class RepoTypeRoutePredicate(object):
585 585 def __init__(self, val, config):
586 586 self.val = val or ['hg', 'git', 'svn']
587 587
588 588 def text(self):
589 589 return 'repo_accepted_type = %s' % self.val
590 590
591 591 phash = text
592 592
593 593 def __call__(self, info, request):
594 594 if hasattr(request, 'vcs_call'):
595 595 # skip vcs calls
596 596 return
597 597
598 598 rhodecode_db_repo = request.db_repo
599 599
600 600 log.debug(
601 601 '%s checking repo type for %s in %s',
602 602 self.__class__.__name__, rhodecode_db_repo.repo_type, self.val)
603 603
604 604 if rhodecode_db_repo.repo_type in self.val:
605 605 return True
606 606 else:
607 607 log.warning('Current view is not supported for repo type:%s',
608 608 rhodecode_db_repo.repo_type)
609 609 return False
610 610
611 611
612 612 class RepoGroupRoutePredicate(object):
613 613 def __init__(self, val, config):
614 614 self.val = val
615 615
616 616 def text(self):
617 617 return 'repo_group_route = %s' % self.val
618 618
619 619 phash = text
620 620
621 621 def __call__(self, info, request):
622 622 if hasattr(request, 'vcs_call'):
623 623 # skip vcs calls
624 624 return
625 625
626 626 repo_group_name = info['match']['repo_group_name']
627 627 repo_group_model = repo_group.RepoGroupModel()
628 628 by_name_match = repo_group_model.get_by_group_name(repo_group_name, cache=False)
629 629
630 630 if by_name_match:
631 631 # register this as request object we can re-use later
632 632 request.db_repo_group = by_name_match
633 633 return True
634 634
635 635 return False
636 636
637 637
638 638 class UserGroupRoutePredicate(object):
639 639 def __init__(self, val, config):
640 640 self.val = val
641 641
642 642 def text(self):
643 643 return 'user_group_route = %s' % self.val
644 644
645 645 phash = text
646 646
647 647 def __call__(self, info, request):
648 648 if hasattr(request, 'vcs_call'):
649 649 # skip vcs calls
650 650 return
651 651
652 652 user_group_id = info['match']['user_group_id']
653 653 user_group_model = user_group.UserGroup()
654 654 by_id_match = user_group_model.get(user_group_id, cache=False)
655 655
656 656 if by_id_match:
657 657 # register this as request object we can re-use later
658 658 request.db_user_group = by_id_match
659 659 return True
660 660
661 661 return False
662 662
663 663
664 664 class UserRoutePredicateBase(object):
665 665 supports_default = None
666 666
667 667 def __init__(self, val, config):
668 668 self.val = val
669 669
670 670 def text(self):
671 671 raise NotImplementedError()
672 672
673 673 def __call__(self, info, request):
674 674 if hasattr(request, 'vcs_call'):
675 675 # skip vcs calls
676 676 return
677 677
678 678 user_id = info['match']['user_id']
679 679 user_model = user.User()
680 680 by_id_match = user_model.get(user_id, cache=False)
681 681
682 682 if by_id_match:
683 683 # register this as request object we can re-use later
684 684 request.db_user = by_id_match
685 685 request.db_user_supports_default = self.supports_default
686 686 return True
687 687
688 688 return False
689 689
690 690
691 691 class UserRoutePredicate(UserRoutePredicateBase):
692 692 supports_default = False
693 693
694 694 def text(self):
695 695 return 'user_route = %s' % self.val
696 696
697 697 phash = text
698 698
699 699
700 700 class UserRouteWithDefaultPredicate(UserRoutePredicateBase):
701 701 supports_default = True
702 702
703 703 def text(self):
704 704 return 'user_with_default_route = %s' % self.val
705 705
706 706 phash = text
707 707
708 708
709 709 def includeme(config):
710 710 config.add_route_predicate(
711 711 'repo_route', RepoRoutePredicate)
712 712 config.add_route_predicate(
713 713 'repo_accepted_types', RepoTypeRoutePredicate)
714 714 config.add_route_predicate(
715 715 'repo_forbid_when_archived', RepoForbidArchivedRoutePredicate)
716 716 config.add_route_predicate(
717 717 'repo_group_route', RepoGroupRoutePredicate)
718 718 config.add_route_predicate(
719 719 'user_group_route', UserGroupRoutePredicate)
720 720 config.add_route_predicate(
721 721 'user_route_with_default', UserRouteWithDefaultPredicate)
722 722 config.add_route_predicate(
723 723 'user_route', UserRoutePredicate)
General Comments 0
You need to be logged in to leave comments. Login now