##// END OF EJS Templates
fix(pyroutes): fixed generated JS routes for EE
super-admin -
r5257:557dc90c default
parent child Browse files
Show More
@@ -1,637 +1,637 b''
1 1 # Copyright (C) 2010-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 os
20 20 import sys
21 21 import collections
22 22 import tempfile
23 23 import time
24 24 import logging.config
25 25
26 26 from paste.gzipper import make_gzip_middleware
27 27 import pyramid.events
28 28 from pyramid.wsgi import wsgiapp
29 29 from pyramid.authorization import ACLAuthorizationPolicy
30 30 from pyramid.config import Configurator
31 31 from pyramid.settings import asbool, aslist
32 32 from pyramid.httpexceptions import (
33 33 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
34 34 from pyramid.renderers import render_to_response
35 35
36 36 from rhodecode.model import meta
37 37 from rhodecode.config import patches
38 38 from rhodecode.config import utils as config_utils
39 39 from rhodecode.config.settings_maker import SettingsMaker
40 40 from rhodecode.config.environment import load_pyramid_environment
41 41
42 42 import rhodecode.events
43 43 from rhodecode.lib.middleware.vcs import VCSMiddleware
44 44 from rhodecode.lib.request import Request
45 45 from rhodecode.lib.vcs import VCSCommunicationError
46 46 from rhodecode.lib.exceptions import VCSServerUnavailable
47 47 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
48 48 from rhodecode.lib.middleware.https_fixup import HttpsFixup
49 49 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
50 50 from rhodecode.lib.utils2 import AttributeDict
51 51 from rhodecode.lib.exc_tracking import store_exception, format_exc
52 52 from rhodecode.subscribers import (
53 53 scan_repositories_if_enabled, write_js_routes_if_enabled,
54 54 write_metadata_if_needed, write_usage_data)
55 55 from rhodecode.lib.statsd_client import StatsdClient
56 56
57 57 log = logging.getLogger(__name__)
58 58
59 59
60 60 def is_http_error(response):
61 61 # error which should have traceback
62 62 return response.status_code > 499
63 63
64 64
65 65 def should_load_all():
66 66 """
67 67 Returns if all application components should be loaded. In some cases it's
68 68 desired to skip apps loading for faster shell script execution
69 69 """
70 70 ssh_cmd = os.environ.get('RC_CMD_SSH_WRAPPER')
71 71 if ssh_cmd:
72 72 return False
73 73
74 74 return True
75 75
76 76
77 77 def make_pyramid_app(global_config, **settings):
78 78 """
79 79 Constructs the WSGI application based on Pyramid.
80 80
81 81 Specials:
82 82
83 83 * The application can also be integrated like a plugin via the call to
84 84 `includeme`. This is accompanied with the other utility functions which
85 85 are called. Changing this should be done with great care to not break
86 86 cases when these fragments are assembled from another place.
87 87
88 88 """
89 89 start_time = time.time()
90 90 log.info('Pyramid app config starting')
91 91
92 92 sanitize_settings_and_apply_defaults(global_config, settings)
93 93
94 94 # init and bootstrap StatsdClient
95 95 StatsdClient.setup(settings)
96 96
97 97 config = Configurator(settings=settings)
98 98 # Init our statsd at very start
99 99 config.registry.statsd = StatsdClient.statsd
100 100
101 101 # Apply compatibility patches
102 102 patches.inspect_getargspec()
103 103
104 104 load_pyramid_environment(global_config, settings)
105 105
106 106 # Static file view comes first
107 107 includeme_first(config)
108 108
109 109 includeme(config)
110 110
111 111 pyramid_app = config.make_wsgi_app()
112 112 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
113 113 pyramid_app.config = config
114 114
115 115 celery_settings = get_celery_config(settings)
116 116 config.configure_celery(celery_settings)
117 117
118 118 # creating the app uses a connection - return it after we are done
119 119 meta.Session.remove()
120 120
121 121 total_time = time.time() - start_time
122 122 log.info('Pyramid app created and configured in %.2fs', total_time)
123 123 return pyramid_app
124 124
125 125
126 126 def get_celery_config(settings):
127 127 """
128 128 Converts basic ini configuration into celery 4.X options
129 129 """
130 130
131 131 def key_converter(key_name):
132 132 pref = 'celery.'
133 133 if key_name.startswith(pref):
134 134 return key_name[len(pref):].replace('.', '_').lower()
135 135
136 136 def type_converter(parsed_key, value):
137 137 # cast to int
138 138 if value.isdigit():
139 139 return int(value)
140 140
141 141 # cast to bool
142 142 if value.lower() in ['true', 'false', 'True', 'False']:
143 143 return value.lower() == 'true'
144 144 return value
145 145
146 146 celery_config = {}
147 147 for k, v in settings.items():
148 148 pref = 'celery.'
149 149 if k.startswith(pref):
150 150 celery_config[key_converter(k)] = type_converter(key_converter(k), v)
151 151
152 152 # TODO:rethink if we want to support celerybeat based file config, probably NOT
153 153 # beat_config = {}
154 154 # for section in parser.sections():
155 155 # if section.startswith('celerybeat:'):
156 156 # name = section.split(':', 1)[1]
157 157 # beat_config[name] = get_beat_config(parser, section)
158 158
159 159 # final compose of settings
160 160 celery_settings = {}
161 161
162 162 if celery_config:
163 163 celery_settings.update(celery_config)
164 164 # if beat_config:
165 165 # celery_settings.update({'beat_schedule': beat_config})
166 166
167 167 return celery_settings
168 168
169 169
170 170 def not_found_view(request):
171 171 """
172 172 This creates the view which should be registered as not-found-view to
173 173 pyramid.
174 174 """
175 175
176 176 if not getattr(request, 'vcs_call', None):
177 177 # handle like regular case with our error_handler
178 178 return error_handler(HTTPNotFound(), request)
179 179
180 180 # handle not found view as a vcs call
181 181 settings = request.registry.settings
182 182 ae_client = getattr(request, 'ae_client', None)
183 183 vcs_app = VCSMiddleware(
184 184 HTTPNotFound(), request.registry, settings,
185 185 appenlight_client=ae_client)
186 186
187 187 return wsgiapp(vcs_app)(None, request)
188 188
189 189
190 190 def error_handler(exception, request):
191 191 import rhodecode
192 192 from rhodecode.lib import helpers
193 193
194 194 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
195 195
196 196 base_response = HTTPInternalServerError()
197 197 # prefer original exception for the response since it may have headers set
198 198 if isinstance(exception, HTTPException):
199 199 base_response = exception
200 200 elif isinstance(exception, VCSCommunicationError):
201 201 base_response = VCSServerUnavailable()
202 202
203 203 if is_http_error(base_response):
204 204 traceback_info = format_exc(request.exc_info)
205 205 log.error(
206 206 'error occurred handling this request for path: %s, \n%s',
207 207 request.path, traceback_info)
208 208
209 209 error_explanation = base_response.explanation or str(base_response)
210 210 if base_response.status_code == 404:
211 211 error_explanation += " Optionally you don't have permission to access this page."
212 212 c = AttributeDict()
213 213 c.error_message = base_response.status
214 214 c.error_explanation = error_explanation
215 215 c.visual = AttributeDict()
216 216
217 217 c.visual.rhodecode_support_url = (
218 218 request.registry.settings.get('rhodecode_support_url') or
219 219 request.route_url('rhodecode_support')
220 220 )
221 221 c.redirect_time = 0
222 222 c.rhodecode_name = rhodecode_title
223 223 if not c.rhodecode_name:
224 224 c.rhodecode_name = 'Rhodecode'
225 225
226 226 c.causes = []
227 227 if is_http_error(base_response):
228 228 c.causes.append('Server is overloaded.')
229 229 c.causes.append('Server database connection is lost.')
230 230 c.causes.append('Server expected unhandled error.')
231 231
232 232 if hasattr(base_response, 'causes'):
233 233 c.causes = base_response.causes
234 234
235 235 c.messages = helpers.flash.pop_messages(request=request)
236 236 exc_info = sys.exc_info()
237 237 c.exception_id = id(exc_info)
238 238 c.show_exception_id = isinstance(base_response, VCSServerUnavailable) \
239 239 or base_response.status_code > 499
240 240 c.exception_id_url = request.route_url(
241 241 'admin_settings_exception_tracker_show', exception_id=c.exception_id)
242 242
243 243 debug_mode = rhodecode.ConfigGet().get_bool('debug')
244 244 if c.show_exception_id:
245 245 store_exception(c.exception_id, exc_info)
246 246 c.exception_debug = debug_mode
247 247 c.exception_config_ini = rhodecode.CONFIG.get('__file__')
248 248
249 249 if debug_mode:
250 250 try:
251 251 from rich.traceback import install
252 252 install(show_locals=True)
253 253 log.debug('Installing rich tracebacks...')
254 254 except ImportError:
255 255 pass
256 256
257 257 response = render_to_response(
258 258 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
259 259 response=base_response)
260 260
261 261 response.headers["X-RC-Exception-Id"] = str(c.exception_id)
262 262
263 263 statsd = request.registry.statsd
264 264 if statsd and base_response.status_code > 499:
265 265 exc_type = f"{exception.__class__.__module__}.{exception.__class__.__name__}"
266 266 statsd.incr('rhodecode_exception_total',
267 267 tags=["exc_source:web",
268 268 f"http_code:{base_response.status_code}",
269 269 f"type:{exc_type}"])
270 270
271 271 return response
272 272
273 273
274 274 def includeme_first(config):
275 275 # redirect automatic browser favicon.ico requests to correct place
276 276 def favicon_redirect(context, request):
277 277 return HTTPFound(
278 278 request.static_path('rhodecode:public/images/favicon.ico'))
279 279
280 280 config.add_view(favicon_redirect, route_name='favicon')
281 281 config.add_route('favicon', '/favicon.ico')
282 282
283 283 def robots_redirect(context, request):
284 284 return HTTPFound(
285 285 request.static_path('rhodecode:public/robots.txt'))
286 286
287 287 config.add_view(robots_redirect, route_name='robots')
288 288 config.add_route('robots', '/robots.txt')
289 289
290 290 config.add_static_view(
291 291 '_static/deform', 'deform:static')
292 292 config.add_static_view(
293 293 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
294 294
295 295
296 296 ce_auth_resources = [
297 297 'rhodecode.authentication.plugins.auth_crowd',
298 298 'rhodecode.authentication.plugins.auth_headers',
299 299 'rhodecode.authentication.plugins.auth_jasig_cas',
300 300 'rhodecode.authentication.plugins.auth_ldap',
301 301 'rhodecode.authentication.plugins.auth_pam',
302 302 'rhodecode.authentication.plugins.auth_rhodecode',
303 303 'rhodecode.authentication.plugins.auth_token',
304 304 ]
305 305
306 306
307 307 def includeme(config, auth_resources=None):
308 308 from rhodecode.lib.celerylib.loader import configure_celery
309 309 log.debug('Initializing main includeme from %s', os.path.basename(__file__))
310 310 settings = config.registry.settings
311 311 config.set_request_factory(Request)
312 312
313 313 # plugin information
314 314 config.registry.rhodecode_plugins = collections.OrderedDict()
315 315
316 316 config.add_directive(
317 317 'register_rhodecode_plugin', register_rhodecode_plugin)
318 318
319 319 config.add_directive('configure_celery', configure_celery)
320 320
321 321 if settings.get('appenlight', False):
322 322 config.include('appenlight_client.ext.pyramid_tween')
323 323
324 324 load_all = should_load_all()
325 325
326 326 # Includes which are required. The application would fail without them.
327 327 config.include('pyramid_mako')
328 328 config.include('rhodecode.lib.rc_beaker')
329 329 config.include('rhodecode.lib.rc_cache')
330 330 config.include('rhodecode.lib.rc_cache.archive_cache')
331 331
332 332 config.include('rhodecode.apps._base.navigation')
333 333 config.include('rhodecode.apps._base.subscribers')
334 334 config.include('rhodecode.tweens')
335 335 config.include('rhodecode.authentication')
336 336
337 337 if load_all:
338 338
339 339 # load CE authentication plugins
340 340
341 341 if auth_resources:
342 342 ce_auth_resources.extend(auth_resources)
343 343
344 344 for resource in ce_auth_resources:
345 345 config.include(resource)
346 346
347 347 # Auto discover authentication plugins and include their configuration.
348 348 if asbool(settings.get('auth_plugin.import_legacy_plugins', 'true')):
349 349 from rhodecode.authentication import discover_legacy_plugins
350 350 discover_legacy_plugins(config)
351 351
352 352 # apps
353 353 if load_all:
354 354 log.debug('Starting config.include() calls')
355 355 config.include('rhodecode.api.includeme')
356 356 config.include('rhodecode.apps._base.includeme')
357 357 config.include('rhodecode.apps._base.navigation.includeme')
358 358 config.include('rhodecode.apps._base.subscribers.includeme')
359 359 config.include('rhodecode.apps.hovercards.includeme')
360 360 config.include('rhodecode.apps.ops.includeme')
361 361 config.include('rhodecode.apps.channelstream.includeme')
362 362 config.include('rhodecode.apps.file_store.includeme')
363 363 config.include('rhodecode.apps.admin.includeme')
364 364 config.include('rhodecode.apps.login.includeme')
365 365 config.include('rhodecode.apps.home.includeme')
366 366 config.include('rhodecode.apps.journal.includeme')
367 367
368 368 config.include('rhodecode.apps.repository.includeme')
369 369 config.include('rhodecode.apps.repo_group.includeme')
370 370 config.include('rhodecode.apps.user_group.includeme')
371 371 config.include('rhodecode.apps.search.includeme')
372 372 config.include('rhodecode.apps.user_profile.includeme')
373 373 config.include('rhodecode.apps.user_group_profile.includeme')
374 374 config.include('rhodecode.apps.my_account.includeme')
375 375 config.include('rhodecode.apps.gist.includeme')
376 376
377 377 config.include('rhodecode.apps.svn_support.includeme')
378 378 config.include('rhodecode.apps.ssh_support.includeme')
379 379 config.include('rhodecode.apps.debug_style')
380 380
381 381 if load_all:
382 382 config.include('rhodecode.integrations.includeme')
383 383 config.include('rhodecode.integrations.routes.includeme')
384 384
385 385 config.add_route('rhodecode_support', 'https://rhodecode.com/help/', static=True)
386 386 settings['default_locale_name'] = settings.get('lang', 'en')
387 387 config.add_translation_dirs('rhodecode:i18n/')
388 388
389 389 # Add subscribers.
390 390 if load_all:
391 log.debug('Adding subscribers....')
391 log.debug('Adding subscribers...')
392 392 config.add_subscriber(scan_repositories_if_enabled,
393 393 pyramid.events.ApplicationCreated)
394 394 config.add_subscriber(write_metadata_if_needed,
395 395 pyramid.events.ApplicationCreated)
396 396 config.add_subscriber(write_usage_data,
397 397 pyramid.events.ApplicationCreated)
398 398 config.add_subscriber(write_js_routes_if_enabled,
399 399 pyramid.events.ApplicationCreated)
400 400
401 401
402 402 # Set the default renderer for HTML templates to mako.
403 403 config.add_mako_renderer('.html')
404 404
405 405 config.add_renderer(
406 406 name='json_ext',
407 407 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
408 408
409 409 config.add_renderer(
410 410 name='string_html',
411 411 factory='rhodecode.lib.string_renderer.html')
412 412
413 413 # include RhodeCode plugins
414 414 includes = aslist(settings.get('rhodecode.includes', []))
415 415 log.debug('processing rhodecode.includes data...')
416 416 for inc in includes:
417 417 config.include(inc)
418 418
419 419 # custom not found view, if our pyramid app doesn't know how to handle
420 420 # the request pass it to potential VCS handling ap
421 421 config.add_notfound_view(not_found_view)
422 422 if not settings.get('debugtoolbar.enabled', False):
423 423 # disabled debugtoolbar handle all exceptions via the error_handlers
424 424 config.add_view(error_handler, context=Exception)
425 425
426 426 # all errors including 403/404/50X
427 427 config.add_view(error_handler, context=HTTPError)
428 428
429 429
430 430 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
431 431 """
432 432 Apply outer WSGI middlewares around the application.
433 433 """
434 434 registry = config.registry
435 435 settings = registry.settings
436 436
437 437 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
438 438 pyramid_app = HttpsFixup(pyramid_app, settings)
439 439
440 440 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
441 441 pyramid_app, settings)
442 442 registry.ae_client = _ae_client
443 443
444 444 if settings['gzip_responses']:
445 445 pyramid_app = make_gzip_middleware(
446 446 pyramid_app, settings, compress_level=1)
447 447
448 448 # this should be the outer most middleware in the wsgi stack since
449 449 # middleware like Routes make database calls
450 450 def pyramid_app_with_cleanup(environ, start_response):
451 451 start = time.time()
452 452 try:
453 453 return pyramid_app(environ, start_response)
454 454 finally:
455 455 # Dispose current database session and rollback uncommitted
456 456 # transactions.
457 457 meta.Session.remove()
458 458
459 459 # In a single threaded mode server, on non sqlite db we should have
460 460 # '0 Current Checked out connections' at the end of a request,
461 461 # if not, then something, somewhere is leaving a connection open
462 462 pool = meta.get_engine().pool
463 463 log.debug('sa pool status: %s', pool.status())
464 464 total = time.time() - start
465 465 log.debug('Request processing finalized: %.4fs', total)
466 466
467 467 return pyramid_app_with_cleanup
468 468
469 469
470 470 def sanitize_settings_and_apply_defaults(global_config, settings):
471 471 """
472 472 Applies settings defaults and does all type conversion.
473 473
474 474 We would move all settings parsing and preparation into this place, so that
475 475 we have only one place left which deals with this part. The remaining parts
476 476 of the application would start to rely fully on well prepared settings.
477 477
478 478 This piece would later be split up per topic to avoid a big fat monster
479 479 function.
480 480 """
481 481 jn = os.path.join
482 482
483 483 global_settings_maker = SettingsMaker(global_config)
484 484 global_settings_maker.make_setting('debug', default=False, parser='bool')
485 485 debug_enabled = asbool(global_config.get('debug'))
486 486
487 487 settings_maker = SettingsMaker(settings)
488 488
489 489 settings_maker.make_setting(
490 490 'logging.autoconfigure',
491 491 default=False,
492 492 parser='bool')
493 493
494 494 logging_conf = jn(os.path.dirname(global_config.get('__file__')), 'logging.ini')
495 495 settings_maker.enable_logging(logging_conf, level='INFO' if debug_enabled else 'DEBUG')
496 496
497 497 # Default includes, possible to change as a user
498 498 pyramid_includes = settings_maker.make_setting('pyramid.includes', [], parser='list:newline')
499 499 log.debug(
500 500 "Using the following pyramid.includes: %s",
501 501 pyramid_includes)
502 502
503 503 settings_maker.make_setting('rhodecode.edition', 'Community Edition')
504 504 settings_maker.make_setting('rhodecode.edition_id', 'CE')
505 505
506 506 if 'mako.default_filters' not in settings:
507 507 # set custom default filters if we don't have it defined
508 508 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
509 509 settings['mako.default_filters'] = 'h_filter'
510 510
511 511 if 'mako.directories' not in settings:
512 512 mako_directories = settings.setdefault('mako.directories', [
513 513 # Base templates of the original application
514 514 'rhodecode:templates',
515 515 ])
516 516 log.debug(
517 517 "Using the following Mako template directories: %s",
518 518 mako_directories)
519 519
520 520 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
521 521 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
522 522 raw_url = settings['beaker.session.url']
523 523 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
524 524 settings['beaker.session.url'] = 'redis://' + raw_url
525 525
526 526 settings_maker.make_setting('__file__', global_config.get('__file__'))
527 527
528 528 # TODO: johbo: Re-think this, usually the call to config.include
529 529 # should allow to pass in a prefix.
530 530 settings_maker.make_setting('rhodecode.api.url', '/_admin/api')
531 531
532 532 # Sanitize generic settings.
533 533 settings_maker.make_setting('default_encoding', 'UTF-8', parser='list')
534 534 settings_maker.make_setting('is_test', False, parser='bool')
535 535 settings_maker.make_setting('gzip_responses', False, parser='bool')
536 536
537 537 # statsd
538 538 settings_maker.make_setting('statsd.enabled', False, parser='bool')
539 539 settings_maker.make_setting('statsd.statsd_host', 'statsd-exporter', parser='string')
540 540 settings_maker.make_setting('statsd.statsd_port', 9125, parser='int')
541 541 settings_maker.make_setting('statsd.statsd_prefix', '')
542 542 settings_maker.make_setting('statsd.statsd_ipv6', False, parser='bool')
543 543
544 544 settings_maker.make_setting('vcs.svn.compatible_version', '')
545 545 settings_maker.make_setting('vcs.hooks.protocol', 'http')
546 546 settings_maker.make_setting('vcs.hooks.host', '*')
547 547 settings_maker.make_setting('vcs.scm_app_implementation', 'http')
548 548 settings_maker.make_setting('vcs.server', '')
549 549 settings_maker.make_setting('vcs.server.protocol', 'http')
550 550 settings_maker.make_setting('vcs.server.enable', 'true', parser='bool')
551 551 settings_maker.make_setting('startup.import_repos', 'false', parser='bool')
552 552 settings_maker.make_setting('vcs.hooks.direct_calls', 'false', parser='bool')
553 553 settings_maker.make_setting('vcs.start_server', 'false', parser='bool')
554 554 settings_maker.make_setting('vcs.backends', 'hg, git, svn', parser='list')
555 555 settings_maker.make_setting('vcs.connection_timeout', 3600, parser='int')
556 556
557 557 settings_maker.make_setting('vcs.methods.cache', True, parser='bool')
558 558
559 559 # Support legacy values of vcs.scm_app_implementation. Legacy
560 560 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
561 561 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
562 562 scm_app_impl = settings['vcs.scm_app_implementation']
563 563 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
564 564 settings['vcs.scm_app_implementation'] = 'http'
565 565
566 566 settings_maker.make_setting('appenlight', False, parser='bool')
567 567
568 568 temp_store = tempfile.gettempdir()
569 569 tmp_cache_dir = jn(temp_store, 'rc_cache')
570 570
571 571 # save default, cache dir, and use it for all backends later.
572 572 default_cache_dir = settings_maker.make_setting(
573 573 'cache_dir',
574 574 default=tmp_cache_dir, default_when_empty=True,
575 575 parser='dir:ensured')
576 576
577 577 # exception store cache
578 578 settings_maker.make_setting(
579 579 'exception_tracker.store_path',
580 580 default=jn(default_cache_dir, 'exc_store'), default_when_empty=True,
581 581 parser='dir:ensured'
582 582 )
583 583
584 584 settings_maker.make_setting(
585 585 'celerybeat-schedule.path',
586 586 default=jn(default_cache_dir, 'celerybeat_schedule', 'celerybeat-schedule.db'), default_when_empty=True,
587 587 parser='file:ensured'
588 588 )
589 589
590 590 settings_maker.make_setting('exception_tracker.send_email', False, parser='bool')
591 591 settings_maker.make_setting('exception_tracker.email_prefix', '[RHODECODE ERROR]', default_when_empty=True)
592 592
593 593 # sessions, ensure file since no-value is memory
594 594 settings_maker.make_setting('beaker.session.type', 'file')
595 595 settings_maker.make_setting('beaker.session.data_dir', jn(default_cache_dir, 'session_data'))
596 596
597 597 # cache_general
598 598 settings_maker.make_setting('rc_cache.cache_general.backend', 'dogpile.cache.rc.file_namespace')
599 599 settings_maker.make_setting('rc_cache.cache_general.expiration_time', 60 * 60 * 12, parser='int')
600 600 settings_maker.make_setting('rc_cache.cache_general.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_general.db'))
601 601
602 602 # cache_perms
603 603 settings_maker.make_setting('rc_cache.cache_perms.backend', 'dogpile.cache.rc.file_namespace')
604 604 settings_maker.make_setting('rc_cache.cache_perms.expiration_time', 60 * 60, parser='int')
605 605 settings_maker.make_setting('rc_cache.cache_perms.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_perms_db'))
606 606
607 607 # cache_repo
608 608 settings_maker.make_setting('rc_cache.cache_repo.backend', 'dogpile.cache.rc.file_namespace')
609 609 settings_maker.make_setting('rc_cache.cache_repo.expiration_time', 60 * 60 * 24 * 30, parser='int')
610 610 settings_maker.make_setting('rc_cache.cache_repo.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_repo_db'))
611 611
612 612 # cache_license
613 613 settings_maker.make_setting('rc_cache.cache_license.backend', 'dogpile.cache.rc.file_namespace')
614 614 settings_maker.make_setting('rc_cache.cache_license.expiration_time', 60 * 5, parser='int')
615 615 settings_maker.make_setting('rc_cache.cache_license.arguments.filename', jn(default_cache_dir, 'rhodecode_cache_license_db'))
616 616
617 617 # cache_repo_longterm memory, 96H
618 618 settings_maker.make_setting('rc_cache.cache_repo_longterm.backend', 'dogpile.cache.rc.memory_lru')
619 619 settings_maker.make_setting('rc_cache.cache_repo_longterm.expiration_time', 345600, parser='int')
620 620 settings_maker.make_setting('rc_cache.cache_repo_longterm.max_size', 10000, parser='int')
621 621
622 622 # sql_cache_short
623 623 settings_maker.make_setting('rc_cache.sql_cache_short.backend', 'dogpile.cache.rc.memory_lru')
624 624 settings_maker.make_setting('rc_cache.sql_cache_short.expiration_time', 30, parser='int')
625 625 settings_maker.make_setting('rc_cache.sql_cache_short.max_size', 10000, parser='int')
626 626
627 627 # archive_cache
628 628 settings_maker.make_setting('archive_cache.store_dir', jn(default_cache_dir, 'archive_cache'), default_when_empty=True,)
629 629 settings_maker.make_setting('archive_cache.cache_size_gb', 10, parser='float')
630 630 settings_maker.make_setting('archive_cache.cache_shards', 10, parser='int')
631 631
632 632 settings_maker.env_expand()
633 633
634 634 # configure instance id
635 635 config_utils.set_instance_id(settings)
636 636
637 637 return settings
@@ -1,382 +1,412 b''
1 1
2 2 /******************************************************************************
3 3 * *
4 4 * DO NOT CHANGE THIS FILE MANUALLY *
5 5 * *
6 6 * *
7 7 * This file is automatically generated when the app starts up with *
8 8 * generate_js_files = true *
9 9 * *
10 10 * To add a route here pass jsroute=True to the route definition in the app *
11 11 * *
12 12 ******************************************************************************/
13 13 function registerRCRoutes() {
14 14 // routes registration
15 pyroutes.register('admin_artifacts', '/_admin/_admin/artifacts', []);
16 pyroutes.register('admin_artifacts_delete', '/_admin/_admin/artifacts/%(uid)s/delete', ['uid']);
17 pyroutes.register('admin_artifacts_show_all', '/_admin/_admin/artifacts', []);
18 pyroutes.register('admin_artifacts_show_info', '/_admin/_admin/artifacts/%(uid)s', ['uid']);
19 pyroutes.register('admin_artifacts_update', '/_admin/_admin/artifacts/%(uid)s/update', ['uid']);
15 pyroutes.register('admin_artifacts', '/_admin/artifacts', []);
16 pyroutes.register('admin_artifacts_data', '/_admin/artifacts-data', []);
17 pyroutes.register('admin_artifacts_delete', '/_admin/artifacts/%(uid)s/delete', ['uid']);
18 pyroutes.register('admin_artifacts_show_all', '/_admin/artifacts', []);
19 pyroutes.register('admin_artifacts_show_info', '/_admin/artifacts/%(uid)s', ['uid']);
20 pyroutes.register('admin_artifacts_update', '/_admin/artifacts/%(uid)s/update', ['uid']);
20 21 pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']);
21 22 pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []);
22 pyroutes.register('admin_automation', '/_admin/_admin/automation', []);
23 pyroutes.register('admin_automation', '/_admin/automation', []);
24 pyroutes.register('admin_automation_update', '/_admin/automation/%(entry_id)s/update', ['entry_id']);
23 25 pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []);
24 26 pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []);
25 27 pyroutes.register('admin_home', '/_admin', []);
26 28 pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []);
27 29 pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []);
28 30 pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []);
29 31 pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []);
32 pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []);
30 33 pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []);
31 34 pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []);
32 35 pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []);
33 36 pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []);
34 37 pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []);
35 38 pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []);
36 39 pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []);
37 40 pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []);
38 41 pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []);
39 pyroutes.register('admin_scheduler', '/_admin/_admin/scheduler', []);
42 pyroutes.register('admin_scheduler', '/_admin/scheduler', []);
43 pyroutes.register('admin_scheduler_show_tasks', '/_admin/scheduler/_tasks', []);
40 44 pyroutes.register('admin_settings', '/_admin/settings', []);
41 45 pyroutes.register('admin_settings_email', '/_admin/settings/email', []);
42 46 pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []);
43 47 pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []);
44 48 pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']);
45 49 pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions_delete_all', []);
46 50 pyroutes.register('admin_settings_exception_tracker_show', '/_admin/settings/exceptions/%(exception_id)s', ['exception_id']);
47 51 pyroutes.register('admin_settings_global', '/_admin/settings/global', []);
48 52 pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []);
49 53 pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []);
50 54 pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []);
51 55 pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []);
52 56 pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []);
53 57 pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []);
54 58 pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []);
55 59 pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []);
56 60 pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []);
57 61 pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []);
62 pyroutes.register('admin_settings_license', '/_admin/settings/license', []);
63 pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []);
58 64 pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []);
59 65 pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []);
60 66 pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []);
61 67 pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []);
62 68 pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []);
63 69 pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []);
64 70 pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []);
71 pyroutes.register('admin_settings_scheduler_create', '/_admin/scheduler/create', []);
72 pyroutes.register('admin_settings_scheduler_delete', '/_admin/scheduler/%(schedule_id)s/delete', ['schedule_id']);
73 pyroutes.register('admin_settings_scheduler_edit', '/_admin/scheduler/%(schedule_id)s', ['schedule_id']);
74 pyroutes.register('admin_settings_scheduler_execute', '/_admin/scheduler/%(schedule_id)s/execute', ['schedule_id']);
75 pyroutes.register('admin_settings_scheduler_new', '/_admin/scheduler/new', []);
76 pyroutes.register('admin_settings_scheduler_update', '/_admin/scheduler/%(schedule_id)s/update', ['schedule_id']);
65 77 pyroutes.register('admin_settings_search', '/_admin/settings/search', []);
66 78 pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []);
67 79 pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []);
68 80 pyroutes.register('admin_settings_system', '/_admin/settings/system', []);
69 81 pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []);
70 82 pyroutes.register('admin_settings_update', '/_admin/settings/update', []);
71 83 pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []);
72 84 pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []);
73 85 pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []);
74 86 pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []);
75 87 pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []);
76 88 pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []);
77 89 pyroutes.register('apiv2', '/_admin/api', []);
78 90 pyroutes.register('atom_feed_home', '/%(repo_name)s/feed-atom', ['repo_name']);
79 91 pyroutes.register('atom_feed_home_old', '/%(repo_name)s/feed/atom', ['repo_name']);
80 92 pyroutes.register('auth_home', '/_admin/auth*traverse', []);
81 93 pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']);
82 94 pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']);
83 95 pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []);
84 96 pyroutes.register('channelstream_proxy', '/_channelstream', []);
85 97 pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []);
98 pyroutes.register('commit_draft_comments_submit', '/%(repo_name)s/changeset/%(commit_id)s/draft_comments_submit', ['repo_name', 'commit_id']);
86 99 pyroutes.register('debug_style_email', '/_admin/debug_style/email/%(email_id)s', ['email_id']);
87 100 pyroutes.register('debug_style_email_plain_rendered', '/_admin/debug_style/email-rendered/%(email_id)s', ['email_id']);
88 101 pyroutes.register('debug_style_home', '/_admin/debug_style', []);
89 102 pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']);
90 103 pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']);
91 104 pyroutes.register('download_file_by_token', '/_file_store/token-download/%(_auth_token)s/%(fid)s', ['_auth_token', 'fid']);
92 105 pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']);
93 106 pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']);
94 107 pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']);
95 108 pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']);
96 109 pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']);
97 110 pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']);
98 111 pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']);
99 112 pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']);
100 113 pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']);
101 114 pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']);
102 115 pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']);
103 116 pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']);
104 117 pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']);
105 118 pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']);
106 119 pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']);
107 120 pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']);
108 121 pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']);
109 122 pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']);
110 123 pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']);
111 124 pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']);
112 125 pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']);
113 126 pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']);
114 127 pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']);
115 128 pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']);
116 129 pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']);
117 130 pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']);
118 131 pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']);
119 132 pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']);
120 133 pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']);
121 134 pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']);
122 135 pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']);
123 136 pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']);
124 137 pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']);
125 138 pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']);
126 139 pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']);
127 140 pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']);
128 141 pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']);
129 142 pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']);
130 143 pyroutes.register('edit_user_audit_logs_download', '/_admin/users/%(user_id)s/edit/audit/download', ['user_id']);
131 144 pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']);
132 145 pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']);
133 146 pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']);
134 147 pyroutes.register('edit_user_auth_tokens_view', '/_admin/users/%(user_id)s/edit/auth_tokens/view', ['user_id']);
135 148 pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']);
136 149 pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']);
137 150 pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']);
138 151 pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']);
139 152 pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']);
140 153 pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']);
141 154 pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']);
142 155 pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']);
143 156 pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']);
144 157 pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']);
145 158 pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']);
146 159 pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']);
147 160 pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']);
148 161 pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']);
149 162 pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']);
150 163 pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']);
151 164 pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']);
152 165 pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']);
153 166 pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']);
154 167 pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']);
155 168 pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']);
156 169 pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']);
157 170 pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']);
158 171 pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']);
159 172 pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']);
160 173 pyroutes.register('favicon', '/favicon.ico', []);
161 174 pyroutes.register('file_preview', '/_file_preview', []);
162 175 pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']);
163 176 pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']);
164 177 pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']);
165 178 pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']);
166 179 pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']);
167 180 pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']);
168 181 pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/rev/%(revision)s', ['gist_id', 'revision']);
169 182 pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']);
170 183 pyroutes.register('gists_create', '/_admin/gists/create', []);
171 184 pyroutes.register('gists_new', '/_admin/gists/new', []);
172 185 pyroutes.register('gists_show', '/_admin/gists', []);
173 186 pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']);
174 187 pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']);
175 188 pyroutes.register('global_integrations_home', '/_admin/integrations', []);
176 189 pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']);
177 190 pyroutes.register('global_integrations_new', '/_admin/integrations/new', []);
178 191 pyroutes.register('goto_switcher_data', '/_goto_data', []);
179 192 pyroutes.register('home', '/', []);
180 193 pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']);
181 194 pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']);
182 195 pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']);
183 196 pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']);
184 197 pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']);
185 198 pyroutes.register('journal', '/_admin/journal', []);
186 199 pyroutes.register('journal_atom', '/_admin/journal/atom', []);
187 200 pyroutes.register('journal_public', '/_admin/public_journal', []);
188 201 pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []);
189 202 pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []);
190 203 pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []);
191 204 pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []);
192 205 pyroutes.register('journal_rss', '/_admin/journal/rss', []);
193 206 pyroutes.register('login', '/_admin/login', []);
194 207 pyroutes.register('logout', '/_admin/logout', []);
195 208 pyroutes.register('main_page_repo_groups_data', '/_home_repo_groups', []);
196 209 pyroutes.register('main_page_repos_data', '/_home_repos', []);
197 210 pyroutes.register('markup_preview', '/_markup_preview', []);
198 211 pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []);
199 212 pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []);
200 213 pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []);
201 214 pyroutes.register('my_account_auth_tokens_view', '/_admin/my_account/auth_tokens/view', []);
202 215 pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []);
203 216 pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []);
204 217 pyroutes.register('my_account_edit', '/_admin/my_account/edit', []);
205 218 pyroutes.register('my_account_emails', '/_admin/my_account/emails', []);
206 219 pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []);
207 220 pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []);
221 pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []);
222 pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []);
208 223 pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']);
209 224 pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []);
210 225 pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []);
211 226 pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []);
212 227 pyroutes.register('my_account_password', '/_admin/my_account/password', []);
213 228 pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []);
214 229 pyroutes.register('my_account_perms', '/_admin/my_account/perms', []);
215 230 pyroutes.register('my_account_profile', '/_admin/my_account/profile', []);
216 231 pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []);
217 232 pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []);
218 233 pyroutes.register('my_account_repos', '/_admin/my_account/repos', []);
219 234 pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []);
220 235 pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []);
221 236 pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []);
222 237 pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []);
223 238 pyroutes.register('my_account_update', '/_admin/my_account/update', []);
224 239 pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []);
225 240 pyroutes.register('my_account_watched', '/_admin/my_account/watched', []);
226 241 pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']);
227 242 pyroutes.register('notifications_mark_all_read', '/_admin/notifications_mark_all_read', []);
228 243 pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']);
229 244 pyroutes.register('notifications_show_all', '/_admin/notifications', []);
230 245 pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']);
231 246 pyroutes.register('ops_error_test', '/_admin/ops/error', []);
232 247 pyroutes.register('ops_healthcheck', '/_admin/ops/status', []);
233 248 pyroutes.register('ops_ping', '/_admin/ops/ping', []);
234 249 pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []);
250 pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']);
235 251 pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']);
236 252 pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']);
237 253 pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']);
238 254 pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']);
239 255 pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']);
240 256 pyroutes.register('pullrequest_comment_edit', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/edit', ['repo_name', 'pull_request_id', 'comment_id']);
241 257 pyroutes.register('pullrequest_comments', '/%(repo_name)s/pull-request/%(pull_request_id)s/comments', ['repo_name', 'pull_request_id']);
242 258 pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']);
243 259 pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']);
260 pyroutes.register('pullrequest_draft_comments_submit', '/%(repo_name)s/pull-request/%(pull_request_id)s/draft_comments_submit', ['repo_name', 'pull_request_id']);
244 261 pyroutes.register('pullrequest_drafts', '/%(repo_name)s/pull-request/%(pull_request_id)s/drafts', ['repo_name', 'pull_request_id']);
245 262 pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']);
246 263 pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']);
247 264 pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']);
248 265 pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']);
249 266 pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']);
250 267 pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']);
251 268 pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']);
252 269 pyroutes.register('pullrequest_todos', '/%(repo_name)s/pull-request/%(pull_request_id)s/todos', ['repo_name', 'pull_request_id']);
253 270 pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']);
254 271 pyroutes.register('register', '/_admin/register', []);
255 272 pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']);
273 pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']);
274 pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']);
275 pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']);
276 pyroutes.register('repo_artifacts_info', '/%(repo_name)s/artifacts/info/%(uid)s', ['repo_name', 'uid']);
256 277 pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']);
278 pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']);
279 pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']);
280 pyroutes.register('repo_artifacts_stream_script', '/_file_store/stream-upload-script', []);
281 pyroutes.register('repo_artifacts_stream_store', '/_file_store/stream-upload', []);
282 pyroutes.register('repo_artifacts_update', '/%(repo_name)s/artifacts/update/%(uid)s', ['repo_name', 'uid']);
257 283 pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']);
284 pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']);
258 285 pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']);
259 286 pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
260 287 pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']);
261 288 pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']);
262 289 pyroutes.register('repo_commit_comment_attachment_upload', '/%(repo_name)s/changeset/%(commit_id)s/comment/attachment_upload', ['repo_name', 'commit_id']);
263 290 pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']);
264 291 pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']);
265 292 pyroutes.register('repo_commit_comment_edit', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/edit', ['repo_name', 'commit_id', 'comment_id']);
266 293 pyroutes.register('repo_commit_comment_history_view', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/history_view/%(comment_history_id)s', ['repo_name', 'commit_id', 'comment_id', 'comment_history_id']);
267 294 pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']);
268 295 pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']);
269 296 pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']);
270 297 pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']);
271 298 pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']);
272 299 pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']);
273 300 pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']);
274 301 pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']);
275 302 pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']);
276 303 pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
277 304 pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
278 305 pyroutes.register('repo_compare', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']);
279 306 pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']);
280 307 pyroutes.register('repo_create', '/_admin/repos/create', []);
281 308 pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']);
282 309 pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']);
283 310 pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']);
284 311 pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
285 312 pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
286 313 pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
287 314 pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
288 315 pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
289 316 pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
290 317 pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
291 318 pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
292 319 pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']);
293 320 pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']);
294 321 pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
295 322 pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
296 323 pyroutes.register('repo_files_check_head', '/%(repo_name)s/check_head/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
297 324 pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
298 325 pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
299 326 pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']);
300 327 pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']);
301 328 pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
302 329 pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
303 330 pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
304 331 pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
305 332 pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
306 333 pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']);
307 334 pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']);
308 335 pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']);
309 336 pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']);
310 337 pyroutes.register('repo_group_create', '/_admin/repo_group/create', []);
311 338 pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']);
312 339 pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']);
313 340 pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']);
314 341 pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']);
315 342 pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']);
316 343 pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']);
317 344 pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']);
318 345 pyroutes.register('repo_group_list_data', '/_repo_groups', []);
319 346 pyroutes.register('repo_group_new', '/_admin/repo_group/new', []);
320 347 pyroutes.register('repo_groups', '/_admin/repo_groups', []);
321 348 pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []);
322 349 pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']);
323 350 pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']);
324 351 pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']);
325 352 pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']);
326 353 pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']);
327 354 pyroutes.register('repo_list_data', '/_repos', []);
328 355 pyroutes.register('repo_new', '/_admin/repos/new', []);
329 356 pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']);
330 357 pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']);
331 358 pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']);
332 359 pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']);
333 360 pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']);
361 pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']);
362 pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']);
363 pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']);
334 364 pyroutes.register('repo_settings_quick_actions', '/%(repo_name)s/settings/quick-action', ['repo_name']);
335 365 pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']);
336 366 pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']);
337 367 pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']);
338 368 pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']);
339 369 pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']);
340 370 pyroutes.register('repos', '/_admin/repos', []);
341 371 pyroutes.register('repos_data', '/_admin/repos_data', []);
342 372 pyroutes.register('reset_password', '/_admin/password_reset', []);
343 373 pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []);
344 374 pyroutes.register('robots', '/robots.txt', []);
345 375 pyroutes.register('rss_feed_home', '/%(repo_name)s/feed-rss', ['repo_name']);
346 376 pyroutes.register('rss_feed_home_old', '/%(repo_name)s/feed/rss', ['repo_name']);
347 377 pyroutes.register('search', '/_admin/search', []);
348 378 pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']);
349 379 pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']);
350 380 pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']);
351 381 pyroutes.register('store_user_session_value', '/_store_session_attr', []);
352 382 pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']);
353 383 pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']);
354 384 pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']);
355 385 pyroutes.register('toggle_following', '/_admin/toggle_following', []);
356 386 pyroutes.register('upload_file', '/_file_store/upload', []);
357 387 pyroutes.register('user_autocomplete_data', '/_users', []);
358 388 pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']);
359 389 pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']);
360 390 pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']);
361 391 pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']);
362 392 pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']);
363 393 pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']);
364 394 pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']);
365 395 pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']);
366 396 pyroutes.register('user_group_autocomplete_data', '/_user_groups', []);
367 397 pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']);
368 398 pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']);
369 399 pyroutes.register('user_groups', '/_admin/user_groups', []);
370 400 pyroutes.register('user_groups_create', '/_admin/user_groups/create', []);
371 401 pyroutes.register('user_groups_data', '/_admin/user_groups_data', []);
372 402 pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']);
373 403 pyroutes.register('user_groups_new', '/_admin/user_groups/new', []);
374 404 pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']);
375 405 pyroutes.register('user_notice_dismiss', '/_admin/users/%(user_id)s/notice_dismiss', ['user_id']);
376 406 pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']);
377 407 pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']);
378 408 pyroutes.register('users', '/_admin/users', []);
379 409 pyroutes.register('users_create', '/_admin/users/create', []);
380 410 pyroutes.register('users_data', '/_admin/users_data', []);
381 411 pyroutes.register('users_new', '/_admin/users/new', []);
382 412 }
@@ -1,397 +1,398 b''
1 1 # Copyright (C) 2010-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 import io
19 19 import shlex
20 20
21 21 import math
22 22 import re
23 23 import os
24 24 import datetime
25 25 import logging
26 26 import queue
27 27 import subprocess
28 28
29 29
30 30 from dateutil.parser import parse
31 31 from pyramid.interfaces import IRoutesMapper
32 32 from pyramid.settings import asbool
33 33 from pyramid.path import AssetResolver
34 34 from threading import Thread
35 35
36 36 from rhodecode.config.jsroutes import generate_jsroutes_content
37 37 from rhodecode.lib.base import get_auth_user
38 38 from rhodecode.lib.celerylib.loader import set_celery_conf
39 39
40 40 import rhodecode
41 41
42 42
43 43 log = logging.getLogger(__name__)
44 44
45 45
46 46 def add_renderer_globals(event):
47 47 from rhodecode.lib import helpers
48 48
49 49 # TODO: When executed in pyramid view context the request is not available
50 50 # in the event. Find a better solution to get the request.
51 51 from pyramid.threadlocal import get_current_request
52 52 request = event['request'] or get_current_request()
53 53
54 54 # Add Pyramid translation as '_' to context
55 55 event['_'] = request.translate
56 56 event['_ungettext'] = request.plularize
57 57 event['h'] = helpers
58 58
59 59
60 60 def set_user_lang(event):
61 61 request = event.request
62 62 cur_user = getattr(request, 'user', None)
63 63
64 64 if cur_user:
65 65 user_lang = cur_user.get_instance().user_data.get('language')
66 66 if user_lang:
67 67 log.debug('lang: setting current user:%s language to: %s', cur_user, user_lang)
68 68 event.request._LOCALE_ = user_lang
69 69
70 70
71 71 def update_celery_conf(event):
72 72 log.debug('Setting celery config from new request')
73 73 set_celery_conf(request=event.request, registry=event.request.registry)
74 74
75 75
76 76 def add_request_user_context(event):
77 77 """
78 78 Adds auth user into request context
79 79 """
80 80
81 81 request = event.request
82 82 # access req_id as soon as possible
83 83 req_id = request.req_id
84 84
85 85 if hasattr(request, 'vcs_call'):
86 86 # skip vcs calls
87 87 return
88 88
89 89 if hasattr(request, 'rpc_method'):
90 90 # skip api calls
91 91 return
92 92
93 93 auth_user, auth_token = get_auth_user(request)
94 94 request.user = auth_user
95 95 request.user_auth_token = auth_token
96 96 request.environ['rc_auth_user'] = auth_user
97 97 request.environ['rc_auth_user_id'] = str(auth_user.user_id)
98 98 request.environ['rc_req_id'] = req_id
99 99
100 100
101 101 def reset_log_bucket(event):
102 102 """
103 103 reset the log bucket on new request
104 104 """
105 105 request = event.request
106 106 request.req_id_records_init()
107 107
108 108
109 109 def scan_repositories_if_enabled(event):
110 110 """
111 111 This is subscribed to the `pyramid.events.ApplicationCreated` event. It
112 112 does a repository scan if enabled in the settings.
113 113 """
114 114 settings = event.app.registry.settings
115 115 vcs_server_enabled = settings['vcs.server.enable']
116 116 import_on_startup = settings['startup.import_repos']
117 117 if vcs_server_enabled and import_on_startup:
118 118 from rhodecode.model.scm import ScmModel
119 119 from rhodecode.lib.utils import repo2db_mapper, get_rhodecode_base_path
120 120 repositories = ScmModel().repo_scan(get_rhodecode_base_path())
121 121 repo2db_mapper(repositories, remove_obsolete=False)
122 122
123 123
124 124 def write_metadata_if_needed(event):
125 125 """
126 126 Writes upgrade metadata
127 127 """
128 128 import rhodecode
129 129 from rhodecode.lib import system_info
130 130 from rhodecode.lib import ext_json
131 131
132 132 fname = '.rcmetadata.json'
133 133 ini_loc = os.path.dirname(rhodecode.CONFIG.get('__file__'))
134 134 metadata_destination = os.path.join(ini_loc, fname)
135 135
136 136 def get_update_age():
137 137 now = datetime.datetime.utcnow()
138 138
139 139 with open(metadata_destination, 'rb') as f:
140 140 data = ext_json.json.loads(f.read())
141 141 if 'created_on' in data:
142 142 update_date = parse(data['created_on'])
143 143 diff = now - update_date
144 144 return diff.total_seconds() / 60.0
145 145
146 146 return 0
147 147
148 148 def write():
149 149 configuration = system_info.SysInfo(
150 150 system_info.rhodecode_config)()['value']
151 151 license_token = configuration['config']['license_token']
152 152
153 153 setup = dict(
154 154 workers=configuration['config']['server:main'].get(
155 155 'workers', '?'),
156 156 worker_type=configuration['config']['server:main'].get(
157 157 'worker_class', 'sync'),
158 158 )
159 159 dbinfo = system_info.SysInfo(system_info.database_info)()['value']
160 160 del dbinfo['url']
161 161
162 162 metadata = dict(
163 163 desc='upgrade metadata info',
164 164 license_token=license_token,
165 165 created_on=datetime.datetime.utcnow().isoformat(),
166 166 usage=system_info.SysInfo(system_info.usage_info)()['value'],
167 167 platform=system_info.SysInfo(system_info.platform_type)()['value'],
168 168 database=dbinfo,
169 169 cpu=system_info.SysInfo(system_info.cpu)()['value'],
170 170 memory=system_info.SysInfo(system_info.memory)()['value'],
171 171 setup=setup
172 172 )
173 173
174 174 with open(metadata_destination, 'wb') as f:
175 175 f.write(ext_json.json.dumps(metadata))
176 176
177 177 settings = event.app.registry.settings
178 178 if settings.get('metadata.skip'):
179 179 return
180 180
181 181 # only write this every 24h, workers restart caused unwanted delays
182 182 try:
183 183 age_in_min = get_update_age()
184 184 except Exception:
185 185 age_in_min = 0
186 186
187 187 if age_in_min > 60 * 60 * 24:
188 188 return
189 189
190 190 try:
191 191 write()
192 192 except Exception:
193 193 pass
194 194
195 195
196 196 def write_usage_data(event):
197 197 import rhodecode
198 198 from rhodecode.lib import system_info
199 199 from rhodecode.lib import ext_json
200 200
201 201 settings = event.app.registry.settings
202 202 instance_tag = settings.get('metadata.write_usage_tag')
203 203 if not settings.get('metadata.write_usage'):
204 204 return
205 205
206 206 def get_update_age(dest_file):
207 207 now = datetime.datetime.utcnow()
208 208
209 209 with open(dest_file, 'rb') as f:
210 210 data = ext_json.json.loads(f.read())
211 211 if 'created_on' in data:
212 212 update_date = parse(data['created_on'])
213 213 diff = now - update_date
214 214 return math.ceil(diff.total_seconds() / 60.0)
215 215
216 216 return 0
217 217
218 218 utc_date = datetime.datetime.utcnow()
219 219 hour_quarter = int(math.ceil((utc_date.hour + utc_date.minute/60.0) / 6.))
220 220 fname = '.rc_usage_{date.year}{date.month:02d}{date.day:02d}_{hour}.json'.format(
221 221 date=utc_date, hour=hour_quarter)
222 222 ini_loc = os.path.dirname(rhodecode.CONFIG.get('__file__'))
223 223
224 224 usage_dir = os.path.join(ini_loc, '.rcusage')
225 225 if not os.path.isdir(usage_dir):
226 226 os.makedirs(usage_dir)
227 227 usage_metadata_destination = os.path.join(usage_dir, fname)
228 228
229 229 try:
230 230 age_in_min = get_update_age(usage_metadata_destination)
231 231 except Exception:
232 232 age_in_min = 0
233 233
234 234 # write every 6th hour
235 235 if age_in_min and age_in_min < 60 * 6:
236 236 log.debug('Usage file created %s minutes ago, skipping (threshold: %s minutes)...',
237 237 age_in_min, 60 * 6)
238 238 return
239 239
240 240 def write(dest_file):
241 241 configuration = system_info.SysInfo(system_info.rhodecode_config)()['value']
242 242 license_token = configuration['config']['license_token']
243 243
244 244 metadata = dict(
245 245 desc='Usage data',
246 246 instance_tag=instance_tag,
247 247 license_token=license_token,
248 248 created_on=datetime.datetime.utcnow().isoformat(),
249 249 usage=system_info.SysInfo(system_info.usage_info)()['value'],
250 250 )
251 251
252 252 with open(dest_file, 'wb') as f:
253 253 f.write(ext_json.formatted_json(metadata))
254 254
255 255 try:
256 256 log.debug('Writing usage file at: %s', usage_metadata_destination)
257 257 write(usage_metadata_destination)
258 258 except Exception:
259 259 pass
260 260
261 261
262 262 def write_js_routes_if_enabled(event):
263 263 registry = event.app.registry
264 264
265 265 mapper = registry.queryUtility(IRoutesMapper)
266 266 _argument_prog = re.compile(r'\{(.*?)\}|:\((.*)\)')
267 267
268 268 def _extract_route_information(route):
269 269 """
270 270 Convert a route into tuple(name, path, args), eg:
271 271 ('show_user', '/profile/%(username)s', ['username'])
272 272 """
273 273
274 routepath = route.pattern
274 route_path = route.pattern
275 275 pattern = route.pattern
276 276
277 277 def replace(matchobj):
278 278 if matchobj.group(1):
279 279 return "%%(%s)s" % matchobj.group(1).split(':')[0]
280 280 else:
281 281 return "%%(%s)s" % matchobj.group(2)
282 282
283 routepath = _argument_prog.sub(replace, routepath)
283 route_path = _argument_prog.sub(replace, route_path)
284 284
285 if not routepath.startswith('/'):
286 routepath = '/'+routepath
285 if not route_path.startswith('/'):
286 route_path = f'/{route_path}'
287 287
288 288 return (
289 289 route.name,
290 routepath,
290 route_path,
291 291 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
292 292 for arg in _argument_prog.findall(pattern)]
293 293 )
294 294
295 295 def get_routes():
296 296 # pyramid routes
297 297 for route in mapper.get_routes():
298 298 if not route.name.startswith('__'):
299 299 yield _extract_route_information(route)
300 300
301 301 if asbool(registry.settings.get('generate_js_files', 'false')):
302 302 static_path = AssetResolver().resolve('rhodecode:public').abspath()
303 303 jsroutes = get_routes()
304 304 jsroutes_file_content = generate_jsroutes_content(jsroutes)
305 305 jsroutes_file_path = os.path.join(
306 306 static_path, 'js', 'rhodecode', 'routes.js')
307 307
308 308 try:
309 309 with open(jsroutes_file_path, 'w', encoding='utf-8') as f:
310 310 f.write(jsroutes_file_content)
311 log.debug('generated JS files in %s', jsroutes_file_path)
311 312 except Exception:
312 313 log.exception('Failed to write routes.js into %s', jsroutes_file_path)
313 314
314 315
315 316 class Subscriber(object):
316 317 """
317 318 Base class for subscribers to the pyramid event system.
318 319 """
319 320 def __call__(self, event):
320 321 self.run(event)
321 322
322 323 def run(self, event):
323 324 raise NotImplementedError('Subclass has to implement this.')
324 325
325 326
326 327 class AsyncSubscriber(Subscriber):
327 328 """
328 329 Subscriber that handles the execution of events in a separate task to not
329 330 block the execution of the code which triggers the event. It puts the
330 331 received events into a queue from which the worker process takes them in
331 332 order.
332 333 """
333 334 def __init__(self):
334 335 self._stop = False
335 336 self._eventq = queue.Queue()
336 337 self._worker = self.create_worker()
337 338 self._worker.start()
338 339
339 340 def __call__(self, event):
340 341 self._eventq.put(event)
341 342
342 343 def create_worker(self):
343 344 worker = Thread(target=self.do_work)
344 345 worker.daemon = True
345 346 return worker
346 347
347 348 def stop_worker(self):
348 349 self._stop = False
349 350 self._eventq.put(None)
350 351 self._worker.join()
351 352
352 353 def do_work(self):
353 354 while not self._stop:
354 355 event = self._eventq.get()
355 356 if event is not None:
356 357 self.run(event)
357 358
358 359
359 360 class AsyncSubprocessSubscriber(AsyncSubscriber):
360 361 """
361 362 Subscriber that uses the subprocess module to execute a command if an
362 363 event is received. Events are handled asynchronously::
363 364
364 365 subscriber = AsyncSubprocessSubscriber('ls -la', timeout=10)
365 366 subscriber(dummyEvent) # running __call__(event)
366 367
367 368 """
368 369
369 370 def __init__(self, cmd, timeout=None):
370 371 if not isinstance(cmd, (list, tuple)):
371 372 cmd = shlex.split(cmd)
372 373 super().__init__()
373 374 self._cmd = cmd
374 375 self._timeout = timeout
375 376
376 377 def run(self, event):
377 378 cmd = self._cmd
378 379 timeout = self._timeout
379 380 log.debug('Executing command %s.', cmd)
380 381
381 382 try:
382 383 output = subprocess.check_output(
383 384 cmd, timeout=timeout, stderr=subprocess.STDOUT)
384 385 log.debug('Command finished %s', cmd)
385 386 if output:
386 387 log.debug('Command output: %s', output)
387 388 except subprocess.TimeoutExpired as e:
388 389 log.exception('Timeout while executing command.')
389 390 if e.output:
390 391 log.error('Command output: %s', e.output)
391 392 except subprocess.CalledProcessError as e:
392 393 log.exception('Error while executing command.')
393 394 if e.output:
394 395 log.error('Command output: %s', e.output)
395 396 except Exception:
396 397 log.exception(
397 398 'Exception while executing command %s.', cmd)
General Comments 0
You need to be logged in to leave comments. Login now