##// END OF EJS Templates
assets: skip RoutesMiddleware matching on certain urls to avoid...
dan -
r463:7ccc440b default
parent child Browse files
Show More
@@ -1,375 +1,392 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Pylons middleware initialization
22 Pylons middleware initialization
23 """
23 """
24 import logging
24 import logging
25
25
26 from paste.registry import RegistryManager
26 from paste.registry import RegistryManager
27 from paste.gzipper import make_gzip_middleware
27 from paste.gzipper import make_gzip_middleware
28 from pylons.wsgiapp import PylonsApp
28 from pylons.wsgiapp import PylonsApp
29 from pyramid.authorization import ACLAuthorizationPolicy
29 from pyramid.authorization import ACLAuthorizationPolicy
30 from pyramid.config import Configurator
30 from pyramid.config import Configurator
31 from pyramid.static import static_view
31 from pyramid.static import static_view
32 from pyramid.settings import asbool, aslist
32 from pyramid.settings import asbool, aslist
33 from pyramid.wsgi import wsgiapp
33 from pyramid.wsgi import wsgiapp
34 from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
34 from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
35 from pylons.controllers.util import abort, redirect
35 from pylons.controllers.util import abort, redirect
36 import pyramid.httpexceptions as httpexceptions
36 import pyramid.httpexceptions as httpexceptions
37 from pyramid.renderers import render_to_response, render
37 from pyramid.renderers import render_to_response, render
38 from routes.middleware import RoutesMiddleware
38 from routes.middleware import RoutesMiddleware
39 import routes.util
39 import routes.util
40
40
41 import rhodecode
41 import rhodecode
42 import rhodecode.integrations # do not remove this as it registers celery tasks
42 import rhodecode.integrations # do not remove this as it registers celery tasks
43 from rhodecode.config import patches
43 from rhodecode.config import patches
44 from rhodecode.config.routing import STATIC_FILE_PREFIX
44 from rhodecode.config.environment import (
45 from rhodecode.config.environment import (
45 load_environment, load_pyramid_environment)
46 load_environment, load_pyramid_environment)
46 from rhodecode.lib.middleware import csrf
47 from rhodecode.lib.middleware import csrf
47 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
48 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
49 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
49 from rhodecode.lib.middleware.https_fixup import HttpsFixup
50 from rhodecode.lib.middleware.https_fixup import HttpsFixup
50 from rhodecode.lib.middleware.vcs import VCSMiddleware
51 from rhodecode.lib.middleware.vcs import VCSMiddleware
51 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
52 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
52
53
53
54
54 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
55
56
56
57
58 # this is used to avoid avoid the route lookup overhead in routesmiddleware
59 # for certain routes which won't go to pylons to - eg. static files, debugger
60 # it is only needed for the pylons migration and can be removed once complete
61 class SkippableRoutesMiddleware(RoutesMiddleware):
62 """ Routes middleware that allows you to skip prefixes """
63
64 def __init__(self, *args, **kw):
65 self.skip_prefixes = kw.pop('skip_prefixes', [])
66 super(SkippableRoutesMiddleware, self).__init__(*args, **kw)
67
68 def __call__(self, environ, start_response):
69 for prefix in self.skip_prefixes:
70 if environ['PATH_INFO'].startswith(prefix):
71 return self.app(environ, start_response)
72
73 return super(SkippableRoutesMiddleware, self).__call__(
74 environ, start_response)
75
76
57 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
77 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
58 """Create a Pylons WSGI application and return it
78 """Create a Pylons WSGI application and return it
59
79
60 ``global_conf``
80 ``global_conf``
61 The inherited configuration for this application. Normally from
81 The inherited configuration for this application. Normally from
62 the [DEFAULT] section of the Paste ini file.
82 the [DEFAULT] section of the Paste ini file.
63
83
64 ``full_stack``
84 ``full_stack``
65 Whether or not this application provides a full WSGI stack (by
85 Whether or not this application provides a full WSGI stack (by
66 default, meaning it handles its own exceptions and errors).
86 default, meaning it handles its own exceptions and errors).
67 Disable full_stack when this application is "managed" by
87 Disable full_stack when this application is "managed" by
68 another WSGI middleware.
88 another WSGI middleware.
69
89
70 ``app_conf``
90 ``app_conf``
71 The application's local configuration. Normally specified in
91 The application's local configuration. Normally specified in
72 the [app:<name>] section of the Paste ini file (where <name>
92 the [app:<name>] section of the Paste ini file (where <name>
73 defaults to main).
93 defaults to main).
74
94
75 """
95 """
76 # Apply compatibility patches
96 # Apply compatibility patches
77 patches.kombu_1_5_1_python_2_7_11()
97 patches.kombu_1_5_1_python_2_7_11()
78 patches.inspect_getargspec()
98 patches.inspect_getargspec()
79
99
80 # Configure the Pylons environment
100 # Configure the Pylons environment
81 config = load_environment(global_conf, app_conf)
101 config = load_environment(global_conf, app_conf)
82
102
83 # The Pylons WSGI app
103 # The Pylons WSGI app
84 app = PylonsApp(config=config)
104 app = PylonsApp(config=config)
85 if rhodecode.is_test:
105 if rhodecode.is_test:
86 app = csrf.CSRFDetector(app)
106 app = csrf.CSRFDetector(app)
87
107
88 expected_origin = config.get('expected_origin')
108 expected_origin = config.get('expected_origin')
89 if expected_origin:
109 if expected_origin:
90 # The API can be accessed from other Origins.
110 # The API can be accessed from other Origins.
91 app = csrf.OriginChecker(app, expected_origin,
111 app = csrf.OriginChecker(app, expected_origin,
92 skip_urls=[routes.util.url_for('api')])
112 skip_urls=[routes.util.url_for('api')])
93
113
94
114
95 if asbool(full_stack):
115 if asbool(full_stack):
96
116
97 # Appenlight monitoring and error handler
117 # Appenlight monitoring and error handler
98 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
118 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
99
119
100 # we want our low level middleware to get to the request ASAP. We don't
120 # we want our low level middleware to get to the request ASAP. We don't
101 # need any pylons stack middleware in them
121 # need any pylons stack middleware in them
102 app = VCSMiddleware(app, config, appenlight_client)
122 app = VCSMiddleware(app, config, appenlight_client)
103
123
104 # Establish the Registry for this application
124 # Establish the Registry for this application
105 app = RegistryManager(app)
125 app = RegistryManager(app)
106
126
107 app.config = config
127 app.config = config
108
128
109 return app
129 return app
110
130
111
131
112 def make_pyramid_app(global_config, **settings):
132 def make_pyramid_app(global_config, **settings):
113 """
133 """
114 Constructs the WSGI application based on Pyramid and wraps the Pylons based
134 Constructs the WSGI application based on Pyramid and wraps the Pylons based
115 application.
135 application.
116
136
117 Specials:
137 Specials:
118
138
119 * We migrate from Pylons to Pyramid. While doing this, we keep both
139 * We migrate from Pylons to Pyramid. While doing this, we keep both
120 frameworks functional. This involves moving some WSGI middlewares around
140 frameworks functional. This involves moving some WSGI middlewares around
121 and providing access to some data internals, so that the old code is
141 and providing access to some data internals, so that the old code is
122 still functional.
142 still functional.
123
143
124 * The application can also be integrated like a plugin via the call to
144 * The application can also be integrated like a plugin via the call to
125 `includeme`. This is accompanied with the other utility functions which
145 `includeme`. This is accompanied with the other utility functions which
126 are called. Changing this should be done with great care to not break
146 are called. Changing this should be done with great care to not break
127 cases when these fragments are assembled from another place.
147 cases when these fragments are assembled from another place.
128
148
129 """
149 """
130 # The edition string should be available in pylons too, so we add it here
150 # The edition string should be available in pylons too, so we add it here
131 # before copying the settings.
151 # before copying the settings.
132 settings.setdefault('rhodecode.edition', 'Community Edition')
152 settings.setdefault('rhodecode.edition', 'Community Edition')
133
153
134 # As long as our Pylons application does expect "unprepared" settings, make
154 # As long as our Pylons application does expect "unprepared" settings, make
135 # sure that we keep an unmodified copy. This avoids unintentional change of
155 # sure that we keep an unmodified copy. This avoids unintentional change of
136 # behavior in the old application.
156 # behavior in the old application.
137 settings_pylons = settings.copy()
157 settings_pylons = settings.copy()
138
158
139 sanitize_settings_and_apply_defaults(settings)
159 sanitize_settings_and_apply_defaults(settings)
140 config = Configurator(settings=settings)
160 config = Configurator(settings=settings)
141 add_pylons_compat_data(config.registry, global_config, settings_pylons)
161 add_pylons_compat_data(config.registry, global_config, settings_pylons)
142
162
143 load_pyramid_environment(global_config, settings)
163 load_pyramid_environment(global_config, settings)
144
164
165 includeme_first(config)
145 includeme(config)
166 includeme(config)
146 includeme_last(config)
147 pyramid_app = config.make_wsgi_app()
167 pyramid_app = config.make_wsgi_app()
148 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
168 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
149 return pyramid_app
169 return pyramid_app
150
170
151
171
152 def add_pylons_compat_data(registry, global_config, settings):
172 def add_pylons_compat_data(registry, global_config, settings):
153 """
173 """
154 Attach data to the registry to support the Pylons integration.
174 Attach data to the registry to support the Pylons integration.
155 """
175 """
156 registry._pylons_compat_global_config = global_config
176 registry._pylons_compat_global_config = global_config
157 registry._pylons_compat_settings = settings
177 registry._pylons_compat_settings = settings
158
178
159
179
160 def webob_to_pyramid_http_response(webob_response):
180 def webob_to_pyramid_http_response(webob_response):
161 ResponseClass = httpexceptions.status_map[webob_response.status_int]
181 ResponseClass = httpexceptions.status_map[webob_response.status_int]
162 pyramid_response = ResponseClass(webob_response.status)
182 pyramid_response = ResponseClass(webob_response.status)
163 pyramid_response.status = webob_response.status
183 pyramid_response.status = webob_response.status
164 pyramid_response.headers.update(webob_response.headers)
184 pyramid_response.headers.update(webob_response.headers)
165 if pyramid_response.headers['content-type'] == 'text/html':
185 if pyramid_response.headers['content-type'] == 'text/html':
166 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
186 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
167 return pyramid_response
187 return pyramid_response
168
188
169
189
170 def error_handler(exception, request):
190 def error_handler(exception, request):
171 # TODO: dan: replace the old pylons error controller with this
191 # TODO: dan: replace the old pylons error controller with this
172 from rhodecode.model.settings import SettingsModel
192 from rhodecode.model.settings import SettingsModel
173 from rhodecode.lib.utils2 import AttributeDict
193 from rhodecode.lib.utils2 import AttributeDict
174
194
175 try:
195 try:
176 rc_config = SettingsModel().get_all_settings()
196 rc_config = SettingsModel().get_all_settings()
177 except Exception:
197 except Exception:
178 log.exception('failed to fetch settings')
198 log.exception('failed to fetch settings')
179 rc_config = {}
199 rc_config = {}
180
200
181 base_response = HTTPInternalServerError()
201 base_response = HTTPInternalServerError()
182 # prefer original exception for the response since it may have headers set
202 # prefer original exception for the response since it may have headers set
183 if isinstance(exception, HTTPError):
203 if isinstance(exception, HTTPError):
184 base_response = exception
204 base_response = exception
185
205
186 c = AttributeDict()
206 c = AttributeDict()
187 c.error_message = base_response.status
207 c.error_message = base_response.status
188 c.error_explanation = base_response.explanation or str(base_response)
208 c.error_explanation = base_response.explanation or str(base_response)
189 c.visual = AttributeDict()
209 c.visual = AttributeDict()
190
210
191 c.visual.rhodecode_support_url = (
211 c.visual.rhodecode_support_url = (
192 request.registry.settings.get('rhodecode_support_url') or
212 request.registry.settings.get('rhodecode_support_url') or
193 request.route_url('rhodecode_support')
213 request.route_url('rhodecode_support')
194 )
214 )
195 c.redirect_time = 0
215 c.redirect_time = 0
196 c.rhodecode_name = rc_config.get('rhodecode_title', '')
216 c.rhodecode_name = rc_config.get('rhodecode_title', '')
197 if not c.rhodecode_name:
217 if not c.rhodecode_name:
198 c.rhodecode_name = 'Rhodecode'
218 c.rhodecode_name = 'Rhodecode'
199
219
200 response = render_to_response(
220 response = render_to_response(
201 '/errors/error_document.html', {'c': c}, request=request,
221 '/errors/error_document.html', {'c': c}, request=request,
202 response=base_response)
222 response=base_response)
203
223
204 return response
224 return response
205
225
206
226
207 def includeme(config):
227 def includeme(config):
208 settings = config.registry.settings
228 settings = config.registry.settings
209
229
210 if asbool(settings.get('appenlight', 'false')):
230 if asbool(settings.get('appenlight', 'false')):
211 config.include('appenlight_client.ext.pyramid_tween')
231 config.include('appenlight_client.ext.pyramid_tween')
212
232
213 # Includes which are required. The application would fail without them.
233 # Includes which are required. The application would fail without them.
214 config.include('pyramid_mako')
234 config.include('pyramid_mako')
215 config.include('pyramid_beaker')
235 config.include('pyramid_beaker')
216 config.include('rhodecode.admin')
236 config.include('rhodecode.admin')
217 config.include('rhodecode.authentication')
237 config.include('rhodecode.authentication')
218 config.include('rhodecode.integrations')
238 config.include('rhodecode.integrations')
219 config.include('rhodecode.login')
239 config.include('rhodecode.login')
220 config.include('rhodecode.tweens')
240 config.include('rhodecode.tweens')
221 config.include('rhodecode.api')
241 config.include('rhodecode.api')
222 config.add_route(
242 config.add_route(
223 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
243 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
224
244
225 # Set the authorization policy.
245 # Set the authorization policy.
226 authz_policy = ACLAuthorizationPolicy()
246 authz_policy = ACLAuthorizationPolicy()
227 config.set_authorization_policy(authz_policy)
247 config.set_authorization_policy(authz_policy)
228
248
229 # Set the default renderer for HTML templates to mako.
249 # Set the default renderer for HTML templates to mako.
230 config.add_mako_renderer('.html')
250 config.add_mako_renderer('.html')
231
251
232 # plugin information
252 # plugin information
233 config.registry.rhodecode_plugins = {}
253 config.registry.rhodecode_plugins = {}
234
254
235 config.add_directive(
255 config.add_directive(
236 'register_rhodecode_plugin', register_rhodecode_plugin)
256 'register_rhodecode_plugin', register_rhodecode_plugin)
237 # include RhodeCode plugins
257 # include RhodeCode plugins
238 includes = aslist(settings.get('rhodecode.includes', []))
258 includes = aslist(settings.get('rhodecode.includes', []))
239 for inc in includes:
259 for inc in includes:
240 config.include(inc)
260 config.include(inc)
241
261
242 pylons_app = make_app(
262 pylons_app = make_app(
243 config.registry._pylons_compat_global_config,
263 config.registry._pylons_compat_global_config,
244 **config.registry._pylons_compat_settings)
264 **config.registry._pylons_compat_settings)
245 config.registry._pylons_compat_config = pylons_app.config
265 config.registry._pylons_compat_config = pylons_app.config
246
266
247 pylons_app_as_view = wsgiapp(pylons_app)
267 pylons_app_as_view = wsgiapp(pylons_app)
248
268
249 # Protect from VCS Server error related pages when server is not available
269 # Protect from VCS Server error related pages when server is not available
250 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
270 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
251 if not vcs_server_enabled:
271 if not vcs_server_enabled:
252 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
272 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
253
273
254
274
255 def pylons_app_with_error_handler(context, request):
275 def pylons_app_with_error_handler(context, request):
256 """
276 """
257 Handle exceptions from rc pylons app:
277 Handle exceptions from rc pylons app:
258
278
259 - old webob type exceptions get converted to pyramid exceptions
279 - old webob type exceptions get converted to pyramid exceptions
260 - pyramid exceptions are passed to the error handler view
280 - pyramid exceptions are passed to the error handler view
261 """
281 """
262 try:
282 try:
263 response = pylons_app_as_view(context, request)
283 response = pylons_app_as_view(context, request)
264 if 400 <= response.status_int <= 599: # webob type error responses
284 if 400 <= response.status_int <= 599: # webob type error responses
265 return error_handler(
285 return error_handler(
266 webob_to_pyramid_http_response(response), request)
286 webob_to_pyramid_http_response(response), request)
267 except HTTPError as e: # pyramid type exceptions
287 except HTTPError as e: # pyramid type exceptions
268 return error_handler(e, request)
288 return error_handler(e, request)
269 except Exception:
289 except Exception:
270 if settings.get('debugtoolbar.enabled', False):
290 if settings.get('debugtoolbar.enabled', False):
271 raise
291 raise
272 return error_handler(HTTPInternalServerError(), request)
292 return error_handler(HTTPInternalServerError(), request)
273 return response
293 return response
274
294
275 # This is the glue which allows us to migrate in chunks. By registering the
295 # This is the glue which allows us to migrate in chunks. By registering the
276 # pylons based application as the "Not Found" view in Pyramid, we will
296 # pylons based application as the "Not Found" view in Pyramid, we will
277 # fallback to the old application each time the new one does not yet know
297 # fallback to the old application each time the new one does not yet know
278 # how to handle a request.
298 # how to handle a request.
279 config.add_notfound_view(pylons_app_with_error_handler)
299 config.add_notfound_view(pylons_app_with_error_handler)
280
300
281 if not settings.get('debugtoolbar.enabled', False):
301 if not settings.get('debugtoolbar.enabled', False):
282 # if no toolbar, then any exception gets caught and rendered
302 # if no toolbar, then any exception gets caught and rendered
283 config.add_view(error_handler, context=Exception)
303 config.add_view(error_handler, context=Exception)
284
304
285 config.add_view(error_handler, context=HTTPError)
305 config.add_view(error_handler, context=HTTPError)
286
306
287
307
288 def includeme_last(config):
308 def includeme_first(config):
289 """
290 The static file catchall needs to be last in the view configuration.
291 """
292 settings = config.registry.settings
293 config.add_static_view('_static', path='rhodecode:public')
294
295 # redirect automatic browser favicon.ico requests to correct place
309 # redirect automatic browser favicon.ico requests to correct place
296 def favicon_redirect(context, request):
310 def favicon_redirect(context, request):
297 return redirect(
311 return redirect(
298 request.static_url('rhodecode:public/images/favicon.ico'))
312 request.static_url('rhodecode:public/images/favicon.ico'))
313
299 config.add_view(favicon_redirect, route_name='favicon')
314 config.add_view(favicon_redirect, route_name='favicon')
300 config.add_route('favicon', '/favicon.ico')
315 config.add_route('favicon', '/favicon.ico')
301
316
317 config.add_static_view('_static', path='rhodecode:public')
318
302
319
303 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
320 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
304 """
321 """
305 Apply outer WSGI middlewares around the application.
322 Apply outer WSGI middlewares around the application.
306
323
307 Part of this has been moved up from the Pylons layer, so that the
324 Part of this has been moved up from the Pylons layer, so that the
308 data is also available if old Pylons code is hit through an already ported
325 data is also available if old Pylons code is hit through an already ported
309 view.
326 view.
310 """
327 """
311 settings = config.registry.settings
328 settings = config.registry.settings
312
329
313 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
330 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
314 pyramid_app = HttpsFixup(pyramid_app, settings)
331 pyramid_app = HttpsFixup(pyramid_app, settings)
315
332
316 # Add RoutesMiddleware to support the pylons compatibility tween during
333 # Add RoutesMiddleware to support the pylons compatibility tween during
317
318 # migration to pyramid.
334 # migration to pyramid.
319 pyramid_app = RoutesMiddleware(
335 pyramid_app = SkippableRoutesMiddleware(
320 pyramid_app, config.registry._pylons_compat_config['routes.map'])
336 pyramid_app, config.registry._pylons_compat_config['routes.map'],
337 skip_prefixes=(STATIC_FILE_PREFIX, '/_debug_toolbar'))
321
338
322 if asbool(settings.get('appenlight', 'false')):
339 if asbool(settings.get('appenlight', 'false')):
323 pyramid_app, _ = wrap_in_appenlight_if_enabled(
340 pyramid_app, _ = wrap_in_appenlight_if_enabled(
324 pyramid_app, config.registry._pylons_compat_config)
341 pyramid_app, config.registry._pylons_compat_config)
325
342
326 if asbool(settings.get('gzip_responses', 'true')):
343 if asbool(settings.get('gzip_responses', 'true')):
327 pyramid_app = make_gzip_middleware(
344 pyramid_app = make_gzip_middleware(
328 pyramid_app, settings, compress_level=1)
345 pyramid_app, settings, compress_level=1)
329
346
330 return pyramid_app
347 return pyramid_app
331
348
332
349
333 def sanitize_settings_and_apply_defaults(settings):
350 def sanitize_settings_and_apply_defaults(settings):
334 """
351 """
335 Applies settings defaults and does all type conversion.
352 Applies settings defaults and does all type conversion.
336
353
337 We would move all settings parsing and preparation into this place, so that
354 We would move all settings parsing and preparation into this place, so that
338 we have only one place left which deals with this part. The remaining parts
355 we have only one place left which deals with this part. The remaining parts
339 of the application would start to rely fully on well prepared settings.
356 of the application would start to rely fully on well prepared settings.
340
357
341 This piece would later be split up per topic to avoid a big fat monster
358 This piece would later be split up per topic to avoid a big fat monster
342 function.
359 function.
343 """
360 """
344
361
345 # Pyramid's mako renderer has to search in the templates folder so that the
362 # Pyramid's mako renderer has to search in the templates folder so that the
346 # old templates still work. Ported and new templates are expected to use
363 # old templates still work. Ported and new templates are expected to use
347 # real asset specifications for the includes.
364 # real asset specifications for the includes.
348 mako_directories = settings.setdefault('mako.directories', [
365 mako_directories = settings.setdefault('mako.directories', [
349 # Base templates of the original Pylons application
366 # Base templates of the original Pylons application
350 'rhodecode:templates',
367 'rhodecode:templates',
351 ])
368 ])
352 log.debug(
369 log.debug(
353 "Using the following Mako template directories: %s",
370 "Using the following Mako template directories: %s",
354 mako_directories)
371 mako_directories)
355
372
356 # Default includes, possible to change as a user
373 # Default includes, possible to change as a user
357 pyramid_includes = settings.setdefault('pyramid.includes', [
374 pyramid_includes = settings.setdefault('pyramid.includes', [
358 'rhodecode.lib.middleware.request_wrapper',
375 'rhodecode.lib.middleware.request_wrapper',
359 ])
376 ])
360 log.debug(
377 log.debug(
361 "Using the following pyramid.includes: %s",
378 "Using the following pyramid.includes: %s",
362 pyramid_includes)
379 pyramid_includes)
363
380
364 # TODO: johbo: Re-think this, usually the call to config.include
381 # TODO: johbo: Re-think this, usually the call to config.include
365 # should allow to pass in a prefix.
382 # should allow to pass in a prefix.
366 settings.setdefault('rhodecode.api.url', '/_admin/api')
383 settings.setdefault('rhodecode.api.url', '/_admin/api')
367
384
368 _bool_setting(settings, 'vcs.server.enable', 'true')
385 _bool_setting(settings, 'vcs.server.enable', 'true')
369 _bool_setting(settings, 'is_test', 'false')
386 _bool_setting(settings, 'is_test', 'false')
370
387
371 return settings
388 return settings
372
389
373
390
374 def _bool_setting(settings, name, default):
391 def _bool_setting(settings, name, default):
375 settings[name] = asbool(settings.get(name, default))
392 settings[name] = asbool(settings.get(name, default))
@@ -1,1154 +1,1155 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2016 RhodeCode GmbH
3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 Routes configuration
22 Routes configuration
23
23
24 The more specific and detailed routes should be defined first so they
24 The more specific and detailed routes should be defined first so they
25 may take precedent over the more generic routes. For more information
25 may take precedent over the more generic routes. For more information
26 refer to the routes manual at http://routes.groovie.org/docs/
26 refer to the routes manual at http://routes.groovie.org/docs/
27
27
28 IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
28 IMPORTANT: if you change any routing here, make sure to take a look at lib/base.py
29 and _route_name variable which uses some of stored naming here to do redirects.
29 and _route_name variable which uses some of stored naming here to do redirects.
30 """
30 """
31 import os
31 import os
32 import re
32 import re
33 from routes import Mapper
33 from routes import Mapper
34
34
35 from rhodecode.config import routing_links
35 from rhodecode.config import routing_links
36
36
37 # prefix for non repository related links needs to be prefixed with `/`
37 # prefix for non repository related links needs to be prefixed with `/`
38 ADMIN_PREFIX = '/_admin'
38 ADMIN_PREFIX = '/_admin'
39 STATIC_FILE_PREFIX = '/_static'
39
40
40 # Default requirements for URL parts
41 # Default requirements for URL parts
41 URL_NAME_REQUIREMENTS = {
42 URL_NAME_REQUIREMENTS = {
42 # group name can have a slash in them, but they must not end with a slash
43 # group name can have a slash in them, but they must not end with a slash
43 'group_name': r'.*?[^/]',
44 'group_name': r'.*?[^/]',
44 # repo names can have a slash in them, but they must not end with a slash
45 # repo names can have a slash in them, but they must not end with a slash
45 'repo_name': r'.*?[^/]',
46 'repo_name': r'.*?[^/]',
46 # file path eats up everything at the end
47 # file path eats up everything at the end
47 'f_path': r'.*',
48 'f_path': r'.*',
48 # reference types
49 # reference types
49 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
50 'source_ref_type': '(branch|book|tag|rev|\%\(source_ref_type\)s)',
50 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
51 'target_ref_type': '(branch|book|tag|rev|\%\(target_ref_type\)s)',
51 }
52 }
52
53
53
54
54 def add_route_requirements(route_path, requirements):
55 def add_route_requirements(route_path, requirements):
55 """
56 """
56 Adds regex requirements to pyramid routes using a mapping dict
57 Adds regex requirements to pyramid routes using a mapping dict
57
58
58 >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
59 >>> add_route_requirements('/{action}/{id}', {'id': r'\d+'})
59 '/{action}/{id:\d+}'
60 '/{action}/{id:\d+}'
60
61
61 """
62 """
62 for key, regex in requirements.items():
63 for key, regex in requirements.items():
63 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
64 route_path = route_path.replace('{%s}' % key, '{%s:%s}' % (key, regex))
64 return route_path
65 return route_path
65
66
66
67
67 class JSRoutesMapper(Mapper):
68 class JSRoutesMapper(Mapper):
68 """
69 """
69 Wrapper for routes.Mapper to make pyroutes compatible url definitions
70 Wrapper for routes.Mapper to make pyroutes compatible url definitions
70 """
71 """
71 _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
72 _named_route_regex = re.compile(r'^[a-z-_0-9A-Z]+$')
72 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
73 _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)')
73 def __init__(self, *args, **kw):
74 def __init__(self, *args, **kw):
74 super(JSRoutesMapper, self).__init__(*args, **kw)
75 super(JSRoutesMapper, self).__init__(*args, **kw)
75 self._jsroutes = []
76 self._jsroutes = []
76
77
77 def connect(self, *args, **kw):
78 def connect(self, *args, **kw):
78 """
79 """
79 Wrapper for connect to take an extra argument jsroute=True
80 Wrapper for connect to take an extra argument jsroute=True
80
81
81 :param jsroute: boolean, if True will add the route to the pyroutes list
82 :param jsroute: boolean, if True will add the route to the pyroutes list
82 """
83 """
83 if kw.pop('jsroute', False):
84 if kw.pop('jsroute', False):
84 if not self._named_route_regex.match(args[0]):
85 if not self._named_route_regex.match(args[0]):
85 raise Exception('only named routes can be added to pyroutes')
86 raise Exception('only named routes can be added to pyroutes')
86 self._jsroutes.append(args[0])
87 self._jsroutes.append(args[0])
87
88
88 super(JSRoutesMapper, self).connect(*args, **kw)
89 super(JSRoutesMapper, self).connect(*args, **kw)
89
90
90 def _extract_route_information(self, route):
91 def _extract_route_information(self, route):
91 """
92 """
92 Convert a route into tuple(name, path, args), eg:
93 Convert a route into tuple(name, path, args), eg:
93 ('user_profile', '/profile/%(username)s', ['username'])
94 ('user_profile', '/profile/%(username)s', ['username'])
94 """
95 """
95 routepath = route.routepath
96 routepath = route.routepath
96 def replace(matchobj):
97 def replace(matchobj):
97 if matchobj.group(1):
98 if matchobj.group(1):
98 return "%%(%s)s" % matchobj.group(1).split(':')[0]
99 return "%%(%s)s" % matchobj.group(1).split(':')[0]
99 else:
100 else:
100 return "%%(%s)s" % matchobj.group(2)
101 return "%%(%s)s" % matchobj.group(2)
101
102
102 routepath = self._argument_prog.sub(replace, routepath)
103 routepath = self._argument_prog.sub(replace, routepath)
103 return (
104 return (
104 route.name,
105 route.name,
105 routepath,
106 routepath,
106 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
107 [(arg[0].split(':')[0] if arg[0] != '' else arg[1])
107 for arg in self._argument_prog.findall(route.routepath)]
108 for arg in self._argument_prog.findall(route.routepath)]
108 )
109 )
109
110
110 def jsroutes(self):
111 def jsroutes(self):
111 """
112 """
112 Return a list of pyroutes.js compatible routes
113 Return a list of pyroutes.js compatible routes
113 """
114 """
114 for route_name in self._jsroutes:
115 for route_name in self._jsroutes:
115 yield self._extract_route_information(self._routenames[route_name])
116 yield self._extract_route_information(self._routenames[route_name])
116
117
117
118
118 def make_map(config):
119 def make_map(config):
119 """Create, configure and return the routes Mapper"""
120 """Create, configure and return the routes Mapper"""
120 rmap = JSRoutesMapper(directory=config['pylons.paths']['controllers'],
121 rmap = JSRoutesMapper(directory=config['pylons.paths']['controllers'],
121 always_scan=config['debug'])
122 always_scan=config['debug'])
122 rmap.minimization = False
123 rmap.minimization = False
123 rmap.explicit = False
124 rmap.explicit = False
124
125
125 from rhodecode.lib.utils2 import str2bool
126 from rhodecode.lib.utils2 import str2bool
126 from rhodecode.model import repo, repo_group
127 from rhodecode.model import repo, repo_group
127
128
128 def check_repo(environ, match_dict):
129 def check_repo(environ, match_dict):
129 """
130 """
130 check for valid repository for proper 404 handling
131 check for valid repository for proper 404 handling
131
132
132 :param environ:
133 :param environ:
133 :param match_dict:
134 :param match_dict:
134 """
135 """
135 repo_name = match_dict.get('repo_name')
136 repo_name = match_dict.get('repo_name')
136
137
137 if match_dict.get('f_path'):
138 if match_dict.get('f_path'):
138 # fix for multiple initial slashes that causes errors
139 # fix for multiple initial slashes that causes errors
139 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
140 match_dict['f_path'] = match_dict['f_path'].lstrip('/')
140 repo_model = repo.RepoModel()
141 repo_model = repo.RepoModel()
141 by_name_match = repo_model.get_by_repo_name(repo_name)
142 by_name_match = repo_model.get_by_repo_name(repo_name)
142 # if we match quickly from database, short circuit the operation,
143 # if we match quickly from database, short circuit the operation,
143 # and validate repo based on the type.
144 # and validate repo based on the type.
144 if by_name_match:
145 if by_name_match:
145 return True
146 return True
146
147
147 by_id_match = repo_model.get_repo_by_id(repo_name)
148 by_id_match = repo_model.get_repo_by_id(repo_name)
148 if by_id_match:
149 if by_id_match:
149 repo_name = by_id_match.repo_name
150 repo_name = by_id_match.repo_name
150 match_dict['repo_name'] = repo_name
151 match_dict['repo_name'] = repo_name
151 return True
152 return True
152
153
153 return False
154 return False
154
155
155 def check_group(environ, match_dict):
156 def check_group(environ, match_dict):
156 """
157 """
157 check for valid repository group path for proper 404 handling
158 check for valid repository group path for proper 404 handling
158
159
159 :param environ:
160 :param environ:
160 :param match_dict:
161 :param match_dict:
161 """
162 """
162 repo_group_name = match_dict.get('group_name')
163 repo_group_name = match_dict.get('group_name')
163 repo_group_model = repo_group.RepoGroupModel()
164 repo_group_model = repo_group.RepoGroupModel()
164 by_name_match = repo_group_model.get_by_group_name(repo_group_name)
165 by_name_match = repo_group_model.get_by_group_name(repo_group_name)
165 if by_name_match:
166 if by_name_match:
166 return True
167 return True
167
168
168 return False
169 return False
169
170
170 def check_user_group(environ, match_dict):
171 def check_user_group(environ, match_dict):
171 """
172 """
172 check for valid user group for proper 404 handling
173 check for valid user group for proper 404 handling
173
174
174 :param environ:
175 :param environ:
175 :param match_dict:
176 :param match_dict:
176 """
177 """
177 return True
178 return True
178
179
179 def check_int(environ, match_dict):
180 def check_int(environ, match_dict):
180 return match_dict.get('id').isdigit()
181 return match_dict.get('id').isdigit()
181
182
182
183
183 #==========================================================================
184 #==========================================================================
184 # CUSTOM ROUTES HERE
185 # CUSTOM ROUTES HERE
185 #==========================================================================
186 #==========================================================================
186
187
187 # MAIN PAGE
188 # MAIN PAGE
188 rmap.connect('home', '/', controller='home', action='index', jsroute=True)
189 rmap.connect('home', '/', controller='home', action='index', jsroute=True)
189 rmap.connect('goto_switcher_data', '/_goto_data', controller='home',
190 rmap.connect('goto_switcher_data', '/_goto_data', controller='home',
190 action='goto_switcher_data')
191 action='goto_switcher_data')
191 rmap.connect('repo_list_data', '/_repos', controller='home',
192 rmap.connect('repo_list_data', '/_repos', controller='home',
192 action='repo_list_data')
193 action='repo_list_data')
193
194
194 rmap.connect('user_autocomplete_data', '/_users', controller='home',
195 rmap.connect('user_autocomplete_data', '/_users', controller='home',
195 action='user_autocomplete_data', jsroute=True)
196 action='user_autocomplete_data', jsroute=True)
196 rmap.connect('user_group_autocomplete_data', '/_user_groups', controller='home',
197 rmap.connect('user_group_autocomplete_data', '/_user_groups', controller='home',
197 action='user_group_autocomplete_data')
198 action='user_group_autocomplete_data')
198
199
199 rmap.connect(
200 rmap.connect(
200 'user_profile', '/_profiles/{username}', controller='users',
201 'user_profile', '/_profiles/{username}', controller='users',
201 action='user_profile')
202 action='user_profile')
202
203
203 # TODO: johbo: Static links, to be replaced by our redirection mechanism
204 # TODO: johbo: Static links, to be replaced by our redirection mechanism
204 rmap.connect('rst_help',
205 rmap.connect('rst_help',
205 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
206 'http://docutils.sourceforge.net/docs/user/rst/quickref.html',
206 _static=True)
207 _static=True)
207 rmap.connect('markdown_help',
208 rmap.connect('markdown_help',
208 'http://daringfireball.net/projects/markdown/syntax',
209 'http://daringfireball.net/projects/markdown/syntax',
209 _static=True)
210 _static=True)
210 rmap.connect('rhodecode_official', 'https://rhodecode.com', _static=True)
211 rmap.connect('rhodecode_official', 'https://rhodecode.com', _static=True)
211 rmap.connect('rhodecode_support', 'https://rhodecode.com/help/', _static=True)
212 rmap.connect('rhodecode_support', 'https://rhodecode.com/help/', _static=True)
212 rmap.connect('rhodecode_translations', 'https://rhodecode.com/translate/enterprise', _static=True)
213 rmap.connect('rhodecode_translations', 'https://rhodecode.com/translate/enterprise', _static=True)
213 # TODO: anderson - making this a static link since redirect won't play
214 # TODO: anderson - making this a static link since redirect won't play
214 # nice with POST requests
215 # nice with POST requests
215 rmap.connect('enterprise_license_convert_from_old',
216 rmap.connect('enterprise_license_convert_from_old',
216 'https://rhodecode.com/u/license-upgrade',
217 'https://rhodecode.com/u/license-upgrade',
217 _static=True)
218 _static=True)
218
219
219 routing_links.connect_redirection_links(rmap)
220 routing_links.connect_redirection_links(rmap)
220
221
221 rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping')
222 rmap.connect('ping', '%s/ping' % (ADMIN_PREFIX,), controller='home', action='ping')
222 rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test')
223 rmap.connect('error_test', '%s/error_test' % (ADMIN_PREFIX,), controller='home', action='error_test')
223
224
224 # ADMIN REPOSITORY ROUTES
225 # ADMIN REPOSITORY ROUTES
225 with rmap.submapper(path_prefix=ADMIN_PREFIX,
226 with rmap.submapper(path_prefix=ADMIN_PREFIX,
226 controller='admin/repos') as m:
227 controller='admin/repos') as m:
227 m.connect('repos', '/repos',
228 m.connect('repos', '/repos',
228 action='create', conditions={'method': ['POST']})
229 action='create', conditions={'method': ['POST']})
229 m.connect('repos', '/repos',
230 m.connect('repos', '/repos',
230 action='index', conditions={'method': ['GET']})
231 action='index', conditions={'method': ['GET']})
231 m.connect('new_repo', '/create_repository', jsroute=True,
232 m.connect('new_repo', '/create_repository', jsroute=True,
232 action='create_repository', conditions={'method': ['GET']})
233 action='create_repository', conditions={'method': ['GET']})
233 m.connect('/repos/{repo_name}',
234 m.connect('/repos/{repo_name}',
234 action='update', conditions={'method': ['PUT'],
235 action='update', conditions={'method': ['PUT'],
235 'function': check_repo},
236 'function': check_repo},
236 requirements=URL_NAME_REQUIREMENTS)
237 requirements=URL_NAME_REQUIREMENTS)
237 m.connect('delete_repo', '/repos/{repo_name}',
238 m.connect('delete_repo', '/repos/{repo_name}',
238 action='delete', conditions={'method': ['DELETE']},
239 action='delete', conditions={'method': ['DELETE']},
239 requirements=URL_NAME_REQUIREMENTS)
240 requirements=URL_NAME_REQUIREMENTS)
240 m.connect('repo', '/repos/{repo_name}',
241 m.connect('repo', '/repos/{repo_name}',
241 action='show', conditions={'method': ['GET'],
242 action='show', conditions={'method': ['GET'],
242 'function': check_repo},
243 'function': check_repo},
243 requirements=URL_NAME_REQUIREMENTS)
244 requirements=URL_NAME_REQUIREMENTS)
244
245
245 # ADMIN REPOSITORY GROUPS ROUTES
246 # ADMIN REPOSITORY GROUPS ROUTES
246 with rmap.submapper(path_prefix=ADMIN_PREFIX,
247 with rmap.submapper(path_prefix=ADMIN_PREFIX,
247 controller='admin/repo_groups') as m:
248 controller='admin/repo_groups') as m:
248 m.connect('repo_groups', '/repo_groups',
249 m.connect('repo_groups', '/repo_groups',
249 action='create', conditions={'method': ['POST']})
250 action='create', conditions={'method': ['POST']})
250 m.connect('repo_groups', '/repo_groups',
251 m.connect('repo_groups', '/repo_groups',
251 action='index', conditions={'method': ['GET']})
252 action='index', conditions={'method': ['GET']})
252 m.connect('new_repo_group', '/repo_groups/new',
253 m.connect('new_repo_group', '/repo_groups/new',
253 action='new', conditions={'method': ['GET']})
254 action='new', conditions={'method': ['GET']})
254 m.connect('update_repo_group', '/repo_groups/{group_name}',
255 m.connect('update_repo_group', '/repo_groups/{group_name}',
255 action='update', conditions={'method': ['PUT'],
256 action='update', conditions={'method': ['PUT'],
256 'function': check_group},
257 'function': check_group},
257 requirements=URL_NAME_REQUIREMENTS)
258 requirements=URL_NAME_REQUIREMENTS)
258
259
259 # EXTRAS REPO GROUP ROUTES
260 # EXTRAS REPO GROUP ROUTES
260 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
261 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
261 action='edit',
262 action='edit',
262 conditions={'method': ['GET'], 'function': check_group},
263 conditions={'method': ['GET'], 'function': check_group},
263 requirements=URL_NAME_REQUIREMENTS)
264 requirements=URL_NAME_REQUIREMENTS)
264 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
265 m.connect('edit_repo_group', '/repo_groups/{group_name}/edit',
265 action='edit',
266 action='edit',
266 conditions={'method': ['PUT'], 'function': check_group},
267 conditions={'method': ['PUT'], 'function': check_group},
267 requirements=URL_NAME_REQUIREMENTS)
268 requirements=URL_NAME_REQUIREMENTS)
268
269
269 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
270 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
270 action='edit_repo_group_advanced',
271 action='edit_repo_group_advanced',
271 conditions={'method': ['GET'], 'function': check_group},
272 conditions={'method': ['GET'], 'function': check_group},
272 requirements=URL_NAME_REQUIREMENTS)
273 requirements=URL_NAME_REQUIREMENTS)
273 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
274 m.connect('edit_repo_group_advanced', '/repo_groups/{group_name}/edit/advanced',
274 action='edit_repo_group_advanced',
275 action='edit_repo_group_advanced',
275 conditions={'method': ['PUT'], 'function': check_group},
276 conditions={'method': ['PUT'], 'function': check_group},
276 requirements=URL_NAME_REQUIREMENTS)
277 requirements=URL_NAME_REQUIREMENTS)
277
278
278 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
279 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
279 action='edit_repo_group_perms',
280 action='edit_repo_group_perms',
280 conditions={'method': ['GET'], 'function': check_group},
281 conditions={'method': ['GET'], 'function': check_group},
281 requirements=URL_NAME_REQUIREMENTS)
282 requirements=URL_NAME_REQUIREMENTS)
282 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
283 m.connect('edit_repo_group_perms', '/repo_groups/{group_name}/edit/permissions',
283 action='update_perms',
284 action='update_perms',
284 conditions={'method': ['PUT'], 'function': check_group},
285 conditions={'method': ['PUT'], 'function': check_group},
285 requirements=URL_NAME_REQUIREMENTS)
286 requirements=URL_NAME_REQUIREMENTS)
286
287
287 m.connect('delete_repo_group', '/repo_groups/{group_name}',
288 m.connect('delete_repo_group', '/repo_groups/{group_name}',
288 action='delete', conditions={'method': ['DELETE'],
289 action='delete', conditions={'method': ['DELETE'],
289 'function': check_group},
290 'function': check_group},
290 requirements=URL_NAME_REQUIREMENTS)
291 requirements=URL_NAME_REQUIREMENTS)
291
292
292 # ADMIN USER ROUTES
293 # ADMIN USER ROUTES
293 with rmap.submapper(path_prefix=ADMIN_PREFIX,
294 with rmap.submapper(path_prefix=ADMIN_PREFIX,
294 controller='admin/users') as m:
295 controller='admin/users') as m:
295 m.connect('users', '/users',
296 m.connect('users', '/users',
296 action='create', conditions={'method': ['POST']})
297 action='create', conditions={'method': ['POST']})
297 m.connect('users', '/users',
298 m.connect('users', '/users',
298 action='index', conditions={'method': ['GET']})
299 action='index', conditions={'method': ['GET']})
299 m.connect('new_user', '/users/new',
300 m.connect('new_user', '/users/new',
300 action='new', conditions={'method': ['GET']})
301 action='new', conditions={'method': ['GET']})
301 m.connect('update_user', '/users/{user_id}',
302 m.connect('update_user', '/users/{user_id}',
302 action='update', conditions={'method': ['PUT']})
303 action='update', conditions={'method': ['PUT']})
303 m.connect('delete_user', '/users/{user_id}',
304 m.connect('delete_user', '/users/{user_id}',
304 action='delete', conditions={'method': ['DELETE']})
305 action='delete', conditions={'method': ['DELETE']})
305 m.connect('edit_user', '/users/{user_id}/edit',
306 m.connect('edit_user', '/users/{user_id}/edit',
306 action='edit', conditions={'method': ['GET']})
307 action='edit', conditions={'method': ['GET']})
307 m.connect('user', '/users/{user_id}',
308 m.connect('user', '/users/{user_id}',
308 action='show', conditions={'method': ['GET']})
309 action='show', conditions={'method': ['GET']})
309 m.connect('force_password_reset_user', '/users/{user_id}/password_reset',
310 m.connect('force_password_reset_user', '/users/{user_id}/password_reset',
310 action='reset_password', conditions={'method': ['POST']})
311 action='reset_password', conditions={'method': ['POST']})
311 m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group',
312 m.connect('create_personal_repo_group', '/users/{user_id}/create_repo_group',
312 action='create_personal_repo_group', conditions={'method': ['POST']})
313 action='create_personal_repo_group', conditions={'method': ['POST']})
313
314
314 # EXTRAS USER ROUTES
315 # EXTRAS USER ROUTES
315 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
316 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
316 action='edit_advanced', conditions={'method': ['GET']})
317 action='edit_advanced', conditions={'method': ['GET']})
317 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
318 m.connect('edit_user_advanced', '/users/{user_id}/edit/advanced',
318 action='update_advanced', conditions={'method': ['PUT']})
319 action='update_advanced', conditions={'method': ['PUT']})
319
320
320 m.connect('edit_user_auth_tokens', '/users/{user_id}/edit/auth_tokens',
321 m.connect('edit_user_auth_tokens', '/users/{user_id}/edit/auth_tokens',
321 action='edit_auth_tokens', conditions={'method': ['GET']})
322 action='edit_auth_tokens', conditions={'method': ['GET']})
322 m.connect('edit_user_auth_tokens', '/users/{user_id}/edit/auth_tokens',
323 m.connect('edit_user_auth_tokens', '/users/{user_id}/edit/auth_tokens',
323 action='add_auth_token', conditions={'method': ['PUT']})
324 action='add_auth_token', conditions={'method': ['PUT']})
324 m.connect('edit_user_auth_tokens', '/users/{user_id}/edit/auth_tokens',
325 m.connect('edit_user_auth_tokens', '/users/{user_id}/edit/auth_tokens',
325 action='delete_auth_token', conditions={'method': ['DELETE']})
326 action='delete_auth_token', conditions={'method': ['DELETE']})
326
327
327 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
328 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
328 action='edit_global_perms', conditions={'method': ['GET']})
329 action='edit_global_perms', conditions={'method': ['GET']})
329 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
330 m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions',
330 action='update_global_perms', conditions={'method': ['PUT']})
331 action='update_global_perms', conditions={'method': ['PUT']})
331
332
332 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
333 m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary',
333 action='edit_perms_summary', conditions={'method': ['GET']})
334 action='edit_perms_summary', conditions={'method': ['GET']})
334
335
335 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
336 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
336 action='edit_emails', conditions={'method': ['GET']})
337 action='edit_emails', conditions={'method': ['GET']})
337 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
338 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
338 action='add_email', conditions={'method': ['PUT']})
339 action='add_email', conditions={'method': ['PUT']})
339 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
340 m.connect('edit_user_emails', '/users/{user_id}/edit/emails',
340 action='delete_email', conditions={'method': ['DELETE']})
341 action='delete_email', conditions={'method': ['DELETE']})
341
342
342 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
343 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
343 action='edit_ips', conditions={'method': ['GET']})
344 action='edit_ips', conditions={'method': ['GET']})
344 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
345 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
345 action='add_ip', conditions={'method': ['PUT']})
346 action='add_ip', conditions={'method': ['PUT']})
346 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
347 m.connect('edit_user_ips', '/users/{user_id}/edit/ips',
347 action='delete_ip', conditions={'method': ['DELETE']})
348 action='delete_ip', conditions={'method': ['DELETE']})
348
349
349 # ADMIN USER GROUPS REST ROUTES
350 # ADMIN USER GROUPS REST ROUTES
350 with rmap.submapper(path_prefix=ADMIN_PREFIX,
351 with rmap.submapper(path_prefix=ADMIN_PREFIX,
351 controller='admin/user_groups') as m:
352 controller='admin/user_groups') as m:
352 m.connect('users_groups', '/user_groups',
353 m.connect('users_groups', '/user_groups',
353 action='create', conditions={'method': ['POST']})
354 action='create', conditions={'method': ['POST']})
354 m.connect('users_groups', '/user_groups',
355 m.connect('users_groups', '/user_groups',
355 action='index', conditions={'method': ['GET']})
356 action='index', conditions={'method': ['GET']})
356 m.connect('new_users_group', '/user_groups/new',
357 m.connect('new_users_group', '/user_groups/new',
357 action='new', conditions={'method': ['GET']})
358 action='new', conditions={'method': ['GET']})
358 m.connect('update_users_group', '/user_groups/{user_group_id}',
359 m.connect('update_users_group', '/user_groups/{user_group_id}',
359 action='update', conditions={'method': ['PUT']})
360 action='update', conditions={'method': ['PUT']})
360 m.connect('delete_users_group', '/user_groups/{user_group_id}',
361 m.connect('delete_users_group', '/user_groups/{user_group_id}',
361 action='delete', conditions={'method': ['DELETE']})
362 action='delete', conditions={'method': ['DELETE']})
362 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
363 m.connect('edit_users_group', '/user_groups/{user_group_id}/edit',
363 action='edit', conditions={'method': ['GET']},
364 action='edit', conditions={'method': ['GET']},
364 function=check_user_group)
365 function=check_user_group)
365
366
366 # EXTRAS USER GROUP ROUTES
367 # EXTRAS USER GROUP ROUTES
367 m.connect('edit_user_group_global_perms',
368 m.connect('edit_user_group_global_perms',
368 '/user_groups/{user_group_id}/edit/global_permissions',
369 '/user_groups/{user_group_id}/edit/global_permissions',
369 action='edit_global_perms', conditions={'method': ['GET']})
370 action='edit_global_perms', conditions={'method': ['GET']})
370 m.connect('edit_user_group_global_perms',
371 m.connect('edit_user_group_global_perms',
371 '/user_groups/{user_group_id}/edit/global_permissions',
372 '/user_groups/{user_group_id}/edit/global_permissions',
372 action='update_global_perms', conditions={'method': ['PUT']})
373 action='update_global_perms', conditions={'method': ['PUT']})
373 m.connect('edit_user_group_perms_summary',
374 m.connect('edit_user_group_perms_summary',
374 '/user_groups/{user_group_id}/edit/permissions_summary',
375 '/user_groups/{user_group_id}/edit/permissions_summary',
375 action='edit_perms_summary', conditions={'method': ['GET']})
376 action='edit_perms_summary', conditions={'method': ['GET']})
376
377
377 m.connect('edit_user_group_perms',
378 m.connect('edit_user_group_perms',
378 '/user_groups/{user_group_id}/edit/permissions',
379 '/user_groups/{user_group_id}/edit/permissions',
379 action='edit_perms', conditions={'method': ['GET']})
380 action='edit_perms', conditions={'method': ['GET']})
380 m.connect('edit_user_group_perms',
381 m.connect('edit_user_group_perms',
381 '/user_groups/{user_group_id}/edit/permissions',
382 '/user_groups/{user_group_id}/edit/permissions',
382 action='update_perms', conditions={'method': ['PUT']})
383 action='update_perms', conditions={'method': ['PUT']})
383
384
384 m.connect('edit_user_group_advanced',
385 m.connect('edit_user_group_advanced',
385 '/user_groups/{user_group_id}/edit/advanced',
386 '/user_groups/{user_group_id}/edit/advanced',
386 action='edit_advanced', conditions={'method': ['GET']})
387 action='edit_advanced', conditions={'method': ['GET']})
387
388
388 m.connect('edit_user_group_members',
389 m.connect('edit_user_group_members',
389 '/user_groups/{user_group_id}/edit/members', jsroute=True,
390 '/user_groups/{user_group_id}/edit/members', jsroute=True,
390 action='edit_members', conditions={'method': ['GET']})
391 action='edit_members', conditions={'method': ['GET']})
391
392
392 # ADMIN PERMISSIONS ROUTES
393 # ADMIN PERMISSIONS ROUTES
393 with rmap.submapper(path_prefix=ADMIN_PREFIX,
394 with rmap.submapper(path_prefix=ADMIN_PREFIX,
394 controller='admin/permissions') as m:
395 controller='admin/permissions') as m:
395 m.connect('admin_permissions_application', '/permissions/application',
396 m.connect('admin_permissions_application', '/permissions/application',
396 action='permission_application_update', conditions={'method': ['POST']})
397 action='permission_application_update', conditions={'method': ['POST']})
397 m.connect('admin_permissions_application', '/permissions/application',
398 m.connect('admin_permissions_application', '/permissions/application',
398 action='permission_application', conditions={'method': ['GET']})
399 action='permission_application', conditions={'method': ['GET']})
399
400
400 m.connect('admin_permissions_global', '/permissions/global',
401 m.connect('admin_permissions_global', '/permissions/global',
401 action='permission_global_update', conditions={'method': ['POST']})
402 action='permission_global_update', conditions={'method': ['POST']})
402 m.connect('admin_permissions_global', '/permissions/global',
403 m.connect('admin_permissions_global', '/permissions/global',
403 action='permission_global', conditions={'method': ['GET']})
404 action='permission_global', conditions={'method': ['GET']})
404
405
405 m.connect('admin_permissions_object', '/permissions/object',
406 m.connect('admin_permissions_object', '/permissions/object',
406 action='permission_objects_update', conditions={'method': ['POST']})
407 action='permission_objects_update', conditions={'method': ['POST']})
407 m.connect('admin_permissions_object', '/permissions/object',
408 m.connect('admin_permissions_object', '/permissions/object',
408 action='permission_objects', conditions={'method': ['GET']})
409 action='permission_objects', conditions={'method': ['GET']})
409
410
410 m.connect('admin_permissions_ips', '/permissions/ips',
411 m.connect('admin_permissions_ips', '/permissions/ips',
411 action='permission_ips', conditions={'method': ['POST']})
412 action='permission_ips', conditions={'method': ['POST']})
412 m.connect('admin_permissions_ips', '/permissions/ips',
413 m.connect('admin_permissions_ips', '/permissions/ips',
413 action='permission_ips', conditions={'method': ['GET']})
414 action='permission_ips', conditions={'method': ['GET']})
414
415
415 m.connect('admin_permissions_overview', '/permissions/overview',
416 m.connect('admin_permissions_overview', '/permissions/overview',
416 action='permission_perms', conditions={'method': ['GET']})
417 action='permission_perms', conditions={'method': ['GET']})
417
418
418 # ADMIN DEFAULTS REST ROUTES
419 # ADMIN DEFAULTS REST ROUTES
419 with rmap.submapper(path_prefix=ADMIN_PREFIX,
420 with rmap.submapper(path_prefix=ADMIN_PREFIX,
420 controller='admin/defaults') as m:
421 controller='admin/defaults') as m:
421 m.connect('admin_defaults_repositories', '/defaults/repositories',
422 m.connect('admin_defaults_repositories', '/defaults/repositories',
422 action='update_repository_defaults', conditions={'method': ['POST']})
423 action='update_repository_defaults', conditions={'method': ['POST']})
423 m.connect('admin_defaults_repositories', '/defaults/repositories',
424 m.connect('admin_defaults_repositories', '/defaults/repositories',
424 action='index', conditions={'method': ['GET']})
425 action='index', conditions={'method': ['GET']})
425
426
426 # ADMIN DEBUG STYLE ROUTES
427 # ADMIN DEBUG STYLE ROUTES
427 if str2bool(config.get('debug_style')):
428 if str2bool(config.get('debug_style')):
428 with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style',
429 with rmap.submapper(path_prefix=ADMIN_PREFIX + '/debug_style',
429 controller='debug_style') as m:
430 controller='debug_style') as m:
430 m.connect('debug_style_home', '',
431 m.connect('debug_style_home', '',
431 action='index', conditions={'method': ['GET']})
432 action='index', conditions={'method': ['GET']})
432 m.connect('debug_style_template', '/t/{t_path}',
433 m.connect('debug_style_template', '/t/{t_path}',
433 action='template', conditions={'method': ['GET']})
434 action='template', conditions={'method': ['GET']})
434
435
435 # ADMIN SETTINGS ROUTES
436 # ADMIN SETTINGS ROUTES
436 with rmap.submapper(path_prefix=ADMIN_PREFIX,
437 with rmap.submapper(path_prefix=ADMIN_PREFIX,
437 controller='admin/settings') as m:
438 controller='admin/settings') as m:
438
439
439 # default
440 # default
440 m.connect('admin_settings', '/settings',
441 m.connect('admin_settings', '/settings',
441 action='settings_global_update',
442 action='settings_global_update',
442 conditions={'method': ['POST']})
443 conditions={'method': ['POST']})
443 m.connect('admin_settings', '/settings',
444 m.connect('admin_settings', '/settings',
444 action='settings_global', conditions={'method': ['GET']})
445 action='settings_global', conditions={'method': ['GET']})
445
446
446 m.connect('admin_settings_vcs', '/settings/vcs',
447 m.connect('admin_settings_vcs', '/settings/vcs',
447 action='settings_vcs_update',
448 action='settings_vcs_update',
448 conditions={'method': ['POST']})
449 conditions={'method': ['POST']})
449 m.connect('admin_settings_vcs', '/settings/vcs',
450 m.connect('admin_settings_vcs', '/settings/vcs',
450 action='settings_vcs',
451 action='settings_vcs',
451 conditions={'method': ['GET']})
452 conditions={'method': ['GET']})
452 m.connect('admin_settings_vcs', '/settings/vcs',
453 m.connect('admin_settings_vcs', '/settings/vcs',
453 action='delete_svn_pattern',
454 action='delete_svn_pattern',
454 conditions={'method': ['DELETE']})
455 conditions={'method': ['DELETE']})
455
456
456 m.connect('admin_settings_mapping', '/settings/mapping',
457 m.connect('admin_settings_mapping', '/settings/mapping',
457 action='settings_mapping_update',
458 action='settings_mapping_update',
458 conditions={'method': ['POST']})
459 conditions={'method': ['POST']})
459 m.connect('admin_settings_mapping', '/settings/mapping',
460 m.connect('admin_settings_mapping', '/settings/mapping',
460 action='settings_mapping', conditions={'method': ['GET']})
461 action='settings_mapping', conditions={'method': ['GET']})
461
462
462 m.connect('admin_settings_global', '/settings/global',
463 m.connect('admin_settings_global', '/settings/global',
463 action='settings_global_update',
464 action='settings_global_update',
464 conditions={'method': ['POST']})
465 conditions={'method': ['POST']})
465 m.connect('admin_settings_global', '/settings/global',
466 m.connect('admin_settings_global', '/settings/global',
466 action='settings_global', conditions={'method': ['GET']})
467 action='settings_global', conditions={'method': ['GET']})
467
468
468 m.connect('admin_settings_visual', '/settings/visual',
469 m.connect('admin_settings_visual', '/settings/visual',
469 action='settings_visual_update',
470 action='settings_visual_update',
470 conditions={'method': ['POST']})
471 conditions={'method': ['POST']})
471 m.connect('admin_settings_visual', '/settings/visual',
472 m.connect('admin_settings_visual', '/settings/visual',
472 action='settings_visual', conditions={'method': ['GET']})
473 action='settings_visual', conditions={'method': ['GET']})
473
474
474 m.connect('admin_settings_issuetracker',
475 m.connect('admin_settings_issuetracker',
475 '/settings/issue-tracker', action='settings_issuetracker',
476 '/settings/issue-tracker', action='settings_issuetracker',
476 conditions={'method': ['GET']})
477 conditions={'method': ['GET']})
477 m.connect('admin_settings_issuetracker_save',
478 m.connect('admin_settings_issuetracker_save',
478 '/settings/issue-tracker/save',
479 '/settings/issue-tracker/save',
479 action='settings_issuetracker_save',
480 action='settings_issuetracker_save',
480 conditions={'method': ['POST']})
481 conditions={'method': ['POST']})
481 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
482 m.connect('admin_issuetracker_test', '/settings/issue-tracker/test',
482 action='settings_issuetracker_test',
483 action='settings_issuetracker_test',
483 conditions={'method': ['POST']})
484 conditions={'method': ['POST']})
484 m.connect('admin_issuetracker_delete',
485 m.connect('admin_issuetracker_delete',
485 '/settings/issue-tracker/delete',
486 '/settings/issue-tracker/delete',
486 action='settings_issuetracker_delete',
487 action='settings_issuetracker_delete',
487 conditions={'method': ['DELETE']})
488 conditions={'method': ['DELETE']})
488
489
489 m.connect('admin_settings_email', '/settings/email',
490 m.connect('admin_settings_email', '/settings/email',
490 action='settings_email_update',
491 action='settings_email_update',
491 conditions={'method': ['POST']})
492 conditions={'method': ['POST']})
492 m.connect('admin_settings_email', '/settings/email',
493 m.connect('admin_settings_email', '/settings/email',
493 action='settings_email', conditions={'method': ['GET']})
494 action='settings_email', conditions={'method': ['GET']})
494
495
495 m.connect('admin_settings_hooks', '/settings/hooks',
496 m.connect('admin_settings_hooks', '/settings/hooks',
496 action='settings_hooks_update',
497 action='settings_hooks_update',
497 conditions={'method': ['POST', 'DELETE']})
498 conditions={'method': ['POST', 'DELETE']})
498 m.connect('admin_settings_hooks', '/settings/hooks',
499 m.connect('admin_settings_hooks', '/settings/hooks',
499 action='settings_hooks', conditions={'method': ['GET']})
500 action='settings_hooks', conditions={'method': ['GET']})
500
501
501 m.connect('admin_settings_search', '/settings/search',
502 m.connect('admin_settings_search', '/settings/search',
502 action='settings_search', conditions={'method': ['GET']})
503 action='settings_search', conditions={'method': ['GET']})
503
504
504 m.connect('admin_settings_system', '/settings/system',
505 m.connect('admin_settings_system', '/settings/system',
505 action='settings_system', conditions={'method': ['GET']})
506 action='settings_system', conditions={'method': ['GET']})
506
507
507 m.connect('admin_settings_system_update', '/settings/system/updates',
508 m.connect('admin_settings_system_update', '/settings/system/updates',
508 action='settings_system_update', conditions={'method': ['GET']})
509 action='settings_system_update', conditions={'method': ['GET']})
509
510
510 m.connect('admin_settings_supervisor', '/settings/supervisor',
511 m.connect('admin_settings_supervisor', '/settings/supervisor',
511 action='settings_supervisor', conditions={'method': ['GET']})
512 action='settings_supervisor', conditions={'method': ['GET']})
512 m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log',
513 m.connect('admin_settings_supervisor_log', '/settings/supervisor/{procid}/log',
513 action='settings_supervisor_log', conditions={'method': ['GET']})
514 action='settings_supervisor_log', conditions={'method': ['GET']})
514
515
515 m.connect('admin_settings_labs', '/settings/labs',
516 m.connect('admin_settings_labs', '/settings/labs',
516 action='settings_labs_update',
517 action='settings_labs_update',
517 conditions={'method': ['POST']})
518 conditions={'method': ['POST']})
518 m.connect('admin_settings_labs', '/settings/labs',
519 m.connect('admin_settings_labs', '/settings/labs',
519 action='settings_labs', conditions={'method': ['GET']})
520 action='settings_labs', conditions={'method': ['GET']})
520
521
521 # ADMIN MY ACCOUNT
522 # ADMIN MY ACCOUNT
522 with rmap.submapper(path_prefix=ADMIN_PREFIX,
523 with rmap.submapper(path_prefix=ADMIN_PREFIX,
523 controller='admin/my_account') as m:
524 controller='admin/my_account') as m:
524
525
525 m.connect('my_account', '/my_account',
526 m.connect('my_account', '/my_account',
526 action='my_account', conditions={'method': ['GET']})
527 action='my_account', conditions={'method': ['GET']})
527 m.connect('my_account_edit', '/my_account/edit',
528 m.connect('my_account_edit', '/my_account/edit',
528 action='my_account_edit', conditions={'method': ['GET']})
529 action='my_account_edit', conditions={'method': ['GET']})
529 m.connect('my_account', '/my_account',
530 m.connect('my_account', '/my_account',
530 action='my_account_update', conditions={'method': ['POST']})
531 action='my_account_update', conditions={'method': ['POST']})
531
532
532 m.connect('my_account_password', '/my_account/password',
533 m.connect('my_account_password', '/my_account/password',
533 action='my_account_password', conditions={'method': ['GET']})
534 action='my_account_password', conditions={'method': ['GET']})
534 m.connect('my_account_password', '/my_account/password',
535 m.connect('my_account_password', '/my_account/password',
535 action='my_account_password_update', conditions={'method': ['POST']})
536 action='my_account_password_update', conditions={'method': ['POST']})
536
537
537 m.connect('my_account_repos', '/my_account/repos',
538 m.connect('my_account_repos', '/my_account/repos',
538 action='my_account_repos', conditions={'method': ['GET']})
539 action='my_account_repos', conditions={'method': ['GET']})
539
540
540 m.connect('my_account_watched', '/my_account/watched',
541 m.connect('my_account_watched', '/my_account/watched',
541 action='my_account_watched', conditions={'method': ['GET']})
542 action='my_account_watched', conditions={'method': ['GET']})
542
543
543 m.connect('my_account_pullrequests', '/my_account/pull_requests',
544 m.connect('my_account_pullrequests', '/my_account/pull_requests',
544 action='my_account_pullrequests', conditions={'method': ['GET']})
545 action='my_account_pullrequests', conditions={'method': ['GET']})
545
546
546 m.connect('my_account_perms', '/my_account/perms',
547 m.connect('my_account_perms', '/my_account/perms',
547 action='my_account_perms', conditions={'method': ['GET']})
548 action='my_account_perms', conditions={'method': ['GET']})
548
549
549 m.connect('my_account_emails', '/my_account/emails',
550 m.connect('my_account_emails', '/my_account/emails',
550 action='my_account_emails', conditions={'method': ['GET']})
551 action='my_account_emails', conditions={'method': ['GET']})
551 m.connect('my_account_emails', '/my_account/emails',
552 m.connect('my_account_emails', '/my_account/emails',
552 action='my_account_emails_add', conditions={'method': ['POST']})
553 action='my_account_emails_add', conditions={'method': ['POST']})
553 m.connect('my_account_emails', '/my_account/emails',
554 m.connect('my_account_emails', '/my_account/emails',
554 action='my_account_emails_delete', conditions={'method': ['DELETE']})
555 action='my_account_emails_delete', conditions={'method': ['DELETE']})
555
556
556 m.connect('my_account_auth_tokens', '/my_account/auth_tokens',
557 m.connect('my_account_auth_tokens', '/my_account/auth_tokens',
557 action='my_account_auth_tokens', conditions={'method': ['GET']})
558 action='my_account_auth_tokens', conditions={'method': ['GET']})
558 m.connect('my_account_auth_tokens', '/my_account/auth_tokens',
559 m.connect('my_account_auth_tokens', '/my_account/auth_tokens',
559 action='my_account_auth_tokens_add', conditions={'method': ['POST']})
560 action='my_account_auth_tokens_add', conditions={'method': ['POST']})
560 m.connect('my_account_auth_tokens', '/my_account/auth_tokens',
561 m.connect('my_account_auth_tokens', '/my_account/auth_tokens',
561 action='my_account_auth_tokens_delete', conditions={'method': ['DELETE']})
562 action='my_account_auth_tokens_delete', conditions={'method': ['DELETE']})
562
563
563 # NOTIFICATION REST ROUTES
564 # NOTIFICATION REST ROUTES
564 with rmap.submapper(path_prefix=ADMIN_PREFIX,
565 with rmap.submapper(path_prefix=ADMIN_PREFIX,
565 controller='admin/notifications') as m:
566 controller='admin/notifications') as m:
566 m.connect('notifications', '/notifications',
567 m.connect('notifications', '/notifications',
567 action='index', conditions={'method': ['GET']})
568 action='index', conditions={'method': ['GET']})
568 m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
569 m.connect('notifications_mark_all_read', '/notifications/mark_all_read',
569 action='mark_all_read', conditions={'method': ['POST']})
570 action='mark_all_read', conditions={'method': ['POST']})
570
571
571 m.connect('/notifications/{notification_id}',
572 m.connect('/notifications/{notification_id}',
572 action='update', conditions={'method': ['PUT']})
573 action='update', conditions={'method': ['PUT']})
573 m.connect('/notifications/{notification_id}',
574 m.connect('/notifications/{notification_id}',
574 action='delete', conditions={'method': ['DELETE']})
575 action='delete', conditions={'method': ['DELETE']})
575 m.connect('notification', '/notifications/{notification_id}',
576 m.connect('notification', '/notifications/{notification_id}',
576 action='show', conditions={'method': ['GET']})
577 action='show', conditions={'method': ['GET']})
577
578
578 # ADMIN GIST
579 # ADMIN GIST
579 with rmap.submapper(path_prefix=ADMIN_PREFIX,
580 with rmap.submapper(path_prefix=ADMIN_PREFIX,
580 controller='admin/gists') as m:
581 controller='admin/gists') as m:
581 m.connect('gists', '/gists',
582 m.connect('gists', '/gists',
582 action='create', conditions={'method': ['POST']})
583 action='create', conditions={'method': ['POST']})
583 m.connect('gists', '/gists', jsroute=True,
584 m.connect('gists', '/gists', jsroute=True,
584 action='index', conditions={'method': ['GET']})
585 action='index', conditions={'method': ['GET']})
585 m.connect('new_gist', '/gists/new', jsroute=True,
586 m.connect('new_gist', '/gists/new', jsroute=True,
586 action='new', conditions={'method': ['GET']})
587 action='new', conditions={'method': ['GET']})
587
588
588 m.connect('/gists/{gist_id}',
589 m.connect('/gists/{gist_id}',
589 action='delete', conditions={'method': ['DELETE']})
590 action='delete', conditions={'method': ['DELETE']})
590 m.connect('edit_gist', '/gists/{gist_id}/edit',
591 m.connect('edit_gist', '/gists/{gist_id}/edit',
591 action='edit_form', conditions={'method': ['GET']})
592 action='edit_form', conditions={'method': ['GET']})
592 m.connect('edit_gist', '/gists/{gist_id}/edit',
593 m.connect('edit_gist', '/gists/{gist_id}/edit',
593 action='edit', conditions={'method': ['POST']})
594 action='edit', conditions={'method': ['POST']})
594 m.connect(
595 m.connect(
595 'edit_gist_check_revision', '/gists/{gist_id}/edit/check_revision',
596 'edit_gist_check_revision', '/gists/{gist_id}/edit/check_revision',
596 action='check_revision', conditions={'method': ['GET']})
597 action='check_revision', conditions={'method': ['GET']})
597
598
598 m.connect('gist', '/gists/{gist_id}',
599 m.connect('gist', '/gists/{gist_id}',
599 action='show', conditions={'method': ['GET']})
600 action='show', conditions={'method': ['GET']})
600 m.connect('gist_rev', '/gists/{gist_id}/{revision}',
601 m.connect('gist_rev', '/gists/{gist_id}/{revision}',
601 revision='tip',
602 revision='tip',
602 action='show', conditions={'method': ['GET']})
603 action='show', conditions={'method': ['GET']})
603 m.connect('formatted_gist', '/gists/{gist_id}/{revision}/{format}',
604 m.connect('formatted_gist', '/gists/{gist_id}/{revision}/{format}',
604 revision='tip',
605 revision='tip',
605 action='show', conditions={'method': ['GET']})
606 action='show', conditions={'method': ['GET']})
606 m.connect('formatted_gist_file', '/gists/{gist_id}/{revision}/{format}/{f_path}',
607 m.connect('formatted_gist_file', '/gists/{gist_id}/{revision}/{format}/{f_path}',
607 revision='tip',
608 revision='tip',
608 action='show', conditions={'method': ['GET']},
609 action='show', conditions={'method': ['GET']},
609 requirements=URL_NAME_REQUIREMENTS)
610 requirements=URL_NAME_REQUIREMENTS)
610
611
611 # ADMIN MAIN PAGES
612 # ADMIN MAIN PAGES
612 with rmap.submapper(path_prefix=ADMIN_PREFIX,
613 with rmap.submapper(path_prefix=ADMIN_PREFIX,
613 controller='admin/admin') as m:
614 controller='admin/admin') as m:
614 m.connect('admin_home', '', action='index')
615 m.connect('admin_home', '', action='index')
615 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
616 m.connect('admin_add_repo', '/add_repo/{new_repo:[a-z0-9\. _-]*}',
616 action='add_repo')
617 action='add_repo')
617 m.connect(
618 m.connect(
618 'pull_requests_global_0', '/pull_requests/{pull_request_id:[0-9]+}',
619 'pull_requests_global_0', '/pull_requests/{pull_request_id:[0-9]+}',
619 action='pull_requests')
620 action='pull_requests')
620 m.connect(
621 m.connect(
621 'pull_requests_global', '/pull-requests/{pull_request_id:[0-9]+}',
622 'pull_requests_global', '/pull-requests/{pull_request_id:[0-9]+}',
622 action='pull_requests')
623 action='pull_requests')
623
624
624
625
625 # USER JOURNAL
626 # USER JOURNAL
626 rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,),
627 rmap.connect('journal', '%s/journal' % (ADMIN_PREFIX,),
627 controller='journal', action='index')
628 controller='journal', action='index')
628 rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,),
629 rmap.connect('journal_rss', '%s/journal/rss' % (ADMIN_PREFIX,),
629 controller='journal', action='journal_rss')
630 controller='journal', action='journal_rss')
630 rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,),
631 rmap.connect('journal_atom', '%s/journal/atom' % (ADMIN_PREFIX,),
631 controller='journal', action='journal_atom')
632 controller='journal', action='journal_atom')
632
633
633 rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,),
634 rmap.connect('public_journal', '%s/public_journal' % (ADMIN_PREFIX,),
634 controller='journal', action='public_journal')
635 controller='journal', action='public_journal')
635
636
636 rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,),
637 rmap.connect('public_journal_rss', '%s/public_journal/rss' % (ADMIN_PREFIX,),
637 controller='journal', action='public_journal_rss')
638 controller='journal', action='public_journal_rss')
638
639
639 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,),
640 rmap.connect('public_journal_rss_old', '%s/public_journal_rss' % (ADMIN_PREFIX,),
640 controller='journal', action='public_journal_rss')
641 controller='journal', action='public_journal_rss')
641
642
642 rmap.connect('public_journal_atom',
643 rmap.connect('public_journal_atom',
643 '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal',
644 '%s/public_journal/atom' % (ADMIN_PREFIX,), controller='journal',
644 action='public_journal_atom')
645 action='public_journal_atom')
645
646
646 rmap.connect('public_journal_atom_old',
647 rmap.connect('public_journal_atom_old',
647 '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal',
648 '%s/public_journal_atom' % (ADMIN_PREFIX,), controller='journal',
648 action='public_journal_atom')
649 action='public_journal_atom')
649
650
650 rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
651 rmap.connect('toggle_following', '%s/toggle_following' % (ADMIN_PREFIX,),
651 controller='journal', action='toggle_following', jsroute=True,
652 controller='journal', action='toggle_following', jsroute=True,
652 conditions={'method': ['POST']})
653 conditions={'method': ['POST']})
653
654
654 # FULL TEXT SEARCH
655 # FULL TEXT SEARCH
655 rmap.connect('search', '%s/search' % (ADMIN_PREFIX,),
656 rmap.connect('search', '%s/search' % (ADMIN_PREFIX,),
656 controller='search')
657 controller='search')
657 rmap.connect('search_repo_home', '/{repo_name}/search',
658 rmap.connect('search_repo_home', '/{repo_name}/search',
658 controller='search',
659 controller='search',
659 action='index',
660 action='index',
660 conditions={'function': check_repo},
661 conditions={'function': check_repo},
661 requirements=URL_NAME_REQUIREMENTS)
662 requirements=URL_NAME_REQUIREMENTS)
662
663
663 # FEEDS
664 # FEEDS
664 rmap.connect('rss_feed_home', '/{repo_name}/feed/rss',
665 rmap.connect('rss_feed_home', '/{repo_name}/feed/rss',
665 controller='feed', action='rss',
666 controller='feed', action='rss',
666 conditions={'function': check_repo},
667 conditions={'function': check_repo},
667 requirements=URL_NAME_REQUIREMENTS)
668 requirements=URL_NAME_REQUIREMENTS)
668
669
669 rmap.connect('atom_feed_home', '/{repo_name}/feed/atom',
670 rmap.connect('atom_feed_home', '/{repo_name}/feed/atom',
670 controller='feed', action='atom',
671 controller='feed', action='atom',
671 conditions={'function': check_repo},
672 conditions={'function': check_repo},
672 requirements=URL_NAME_REQUIREMENTS)
673 requirements=URL_NAME_REQUIREMENTS)
673
674
674 #==========================================================================
675 #==========================================================================
675 # REPOSITORY ROUTES
676 # REPOSITORY ROUTES
676 #==========================================================================
677 #==========================================================================
677
678
678 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
679 rmap.connect('repo_creating_home', '/{repo_name}/repo_creating',
679 controller='admin/repos', action='repo_creating',
680 controller='admin/repos', action='repo_creating',
680 requirements=URL_NAME_REQUIREMENTS)
681 requirements=URL_NAME_REQUIREMENTS)
681 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
682 rmap.connect('repo_check_home', '/{repo_name}/crepo_check',
682 controller='admin/repos', action='repo_check',
683 controller='admin/repos', action='repo_check',
683 requirements=URL_NAME_REQUIREMENTS)
684 requirements=URL_NAME_REQUIREMENTS)
684
685
685 rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}',
686 rmap.connect('repo_stats', '/{repo_name}/repo_stats/{commit_id}',
686 controller='summary', action='repo_stats',
687 controller='summary', action='repo_stats',
687 conditions={'function': check_repo},
688 conditions={'function': check_repo},
688 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
689 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
689
690
690 rmap.connect('repo_refs_data', '/{repo_name}/refs-data',
691 rmap.connect('repo_refs_data', '/{repo_name}/refs-data',
691 controller='summary', action='repo_refs_data', jsroute=True,
692 controller='summary', action='repo_refs_data', jsroute=True,
692 requirements=URL_NAME_REQUIREMENTS)
693 requirements=URL_NAME_REQUIREMENTS)
693 rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog',
694 rmap.connect('repo_refs_changelog_data', '/{repo_name}/refs-data-changelog',
694 controller='summary', action='repo_refs_changelog_data',
695 controller='summary', action='repo_refs_changelog_data',
695 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
696 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
696
697
697 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
698 rmap.connect('changeset_home', '/{repo_name}/changeset/{revision}',
698 controller='changeset', revision='tip', jsroute=True,
699 controller='changeset', revision='tip', jsroute=True,
699 conditions={'function': check_repo},
700 conditions={'function': check_repo},
700 requirements=URL_NAME_REQUIREMENTS)
701 requirements=URL_NAME_REQUIREMENTS)
701 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
702 rmap.connect('changeset_children', '/{repo_name}/changeset_children/{revision}',
702 controller='changeset', revision='tip', action='changeset_children',
703 controller='changeset', revision='tip', action='changeset_children',
703 conditions={'function': check_repo},
704 conditions={'function': check_repo},
704 requirements=URL_NAME_REQUIREMENTS)
705 requirements=URL_NAME_REQUIREMENTS)
705 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
706 rmap.connect('changeset_parents', '/{repo_name}/changeset_parents/{revision}',
706 controller='changeset', revision='tip', action='changeset_parents',
707 controller='changeset', revision='tip', action='changeset_parents',
707 conditions={'function': check_repo},
708 conditions={'function': check_repo},
708 requirements=URL_NAME_REQUIREMENTS)
709 requirements=URL_NAME_REQUIREMENTS)
709
710
710 # repo edit options
711 # repo edit options
711 rmap.connect('edit_repo', '/{repo_name}/settings', jsroute=True,
712 rmap.connect('edit_repo', '/{repo_name}/settings', jsroute=True,
712 controller='admin/repos', action='edit',
713 controller='admin/repos', action='edit',
713 conditions={'method': ['GET'], 'function': check_repo},
714 conditions={'method': ['GET'], 'function': check_repo},
714 requirements=URL_NAME_REQUIREMENTS)
715 requirements=URL_NAME_REQUIREMENTS)
715
716
716 rmap.connect('edit_repo_perms', '/{repo_name}/settings/permissions',
717 rmap.connect('edit_repo_perms', '/{repo_name}/settings/permissions',
717 jsroute=True,
718 jsroute=True,
718 controller='admin/repos', action='edit_permissions',
719 controller='admin/repos', action='edit_permissions',
719 conditions={'method': ['GET'], 'function': check_repo},
720 conditions={'method': ['GET'], 'function': check_repo},
720 requirements=URL_NAME_REQUIREMENTS)
721 requirements=URL_NAME_REQUIREMENTS)
721 rmap.connect('edit_repo_perms_update', '/{repo_name}/settings/permissions',
722 rmap.connect('edit_repo_perms_update', '/{repo_name}/settings/permissions',
722 controller='admin/repos', action='edit_permissions_update',
723 controller='admin/repos', action='edit_permissions_update',
723 conditions={'method': ['PUT'], 'function': check_repo},
724 conditions={'method': ['PUT'], 'function': check_repo},
724 requirements=URL_NAME_REQUIREMENTS)
725 requirements=URL_NAME_REQUIREMENTS)
725
726
726 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
727 rmap.connect('edit_repo_fields', '/{repo_name}/settings/fields',
727 controller='admin/repos', action='edit_fields',
728 controller='admin/repos', action='edit_fields',
728 conditions={'method': ['GET'], 'function': check_repo},
729 conditions={'method': ['GET'], 'function': check_repo},
729 requirements=URL_NAME_REQUIREMENTS)
730 requirements=URL_NAME_REQUIREMENTS)
730 rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new',
731 rmap.connect('create_repo_fields', '/{repo_name}/settings/fields/new',
731 controller='admin/repos', action='create_repo_field',
732 controller='admin/repos', action='create_repo_field',
732 conditions={'method': ['PUT'], 'function': check_repo},
733 conditions={'method': ['PUT'], 'function': check_repo},
733 requirements=URL_NAME_REQUIREMENTS)
734 requirements=URL_NAME_REQUIREMENTS)
734 rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}',
735 rmap.connect('delete_repo_fields', '/{repo_name}/settings/fields/{field_id}',
735 controller='admin/repos', action='delete_repo_field',
736 controller='admin/repos', action='delete_repo_field',
736 conditions={'method': ['DELETE'], 'function': check_repo},
737 conditions={'method': ['DELETE'], 'function': check_repo},
737 requirements=URL_NAME_REQUIREMENTS)
738 requirements=URL_NAME_REQUIREMENTS)
738
739
739 rmap.connect('edit_repo_advanced', '/{repo_name}/settings/advanced',
740 rmap.connect('edit_repo_advanced', '/{repo_name}/settings/advanced',
740 controller='admin/repos', action='edit_advanced',
741 controller='admin/repos', action='edit_advanced',
741 conditions={'method': ['GET'], 'function': check_repo},
742 conditions={'method': ['GET'], 'function': check_repo},
742 requirements=URL_NAME_REQUIREMENTS)
743 requirements=URL_NAME_REQUIREMENTS)
743
744
744 rmap.connect('edit_repo_advanced_locking', '/{repo_name}/settings/advanced/locking',
745 rmap.connect('edit_repo_advanced_locking', '/{repo_name}/settings/advanced/locking',
745 controller='admin/repos', action='edit_advanced_locking',
746 controller='admin/repos', action='edit_advanced_locking',
746 conditions={'method': ['PUT'], 'function': check_repo},
747 conditions={'method': ['PUT'], 'function': check_repo},
747 requirements=URL_NAME_REQUIREMENTS)
748 requirements=URL_NAME_REQUIREMENTS)
748 rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle',
749 rmap.connect('toggle_locking', '/{repo_name}/settings/advanced/locking_toggle',
749 controller='admin/repos', action='toggle_locking',
750 controller='admin/repos', action='toggle_locking',
750 conditions={'method': ['GET'], 'function': check_repo},
751 conditions={'method': ['GET'], 'function': check_repo},
751 requirements=URL_NAME_REQUIREMENTS)
752 requirements=URL_NAME_REQUIREMENTS)
752
753
753 rmap.connect('edit_repo_advanced_journal', '/{repo_name}/settings/advanced/journal',
754 rmap.connect('edit_repo_advanced_journal', '/{repo_name}/settings/advanced/journal',
754 controller='admin/repos', action='edit_advanced_journal',
755 controller='admin/repos', action='edit_advanced_journal',
755 conditions={'method': ['PUT'], 'function': check_repo},
756 conditions={'method': ['PUT'], 'function': check_repo},
756 requirements=URL_NAME_REQUIREMENTS)
757 requirements=URL_NAME_REQUIREMENTS)
757
758
758 rmap.connect('edit_repo_advanced_fork', '/{repo_name}/settings/advanced/fork',
759 rmap.connect('edit_repo_advanced_fork', '/{repo_name}/settings/advanced/fork',
759 controller='admin/repos', action='edit_advanced_fork',
760 controller='admin/repos', action='edit_advanced_fork',
760 conditions={'method': ['PUT'], 'function': check_repo},
761 conditions={'method': ['PUT'], 'function': check_repo},
761 requirements=URL_NAME_REQUIREMENTS)
762 requirements=URL_NAME_REQUIREMENTS)
762
763
763 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
764 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
764 controller='admin/repos', action='edit_caches_form',
765 controller='admin/repos', action='edit_caches_form',
765 conditions={'method': ['GET'], 'function': check_repo},
766 conditions={'method': ['GET'], 'function': check_repo},
766 requirements=URL_NAME_REQUIREMENTS)
767 requirements=URL_NAME_REQUIREMENTS)
767 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
768 rmap.connect('edit_repo_caches', '/{repo_name}/settings/caches',
768 controller='admin/repos', action='edit_caches',
769 controller='admin/repos', action='edit_caches',
769 conditions={'method': ['PUT'], 'function': check_repo},
770 conditions={'method': ['PUT'], 'function': check_repo},
770 requirements=URL_NAME_REQUIREMENTS)
771 requirements=URL_NAME_REQUIREMENTS)
771
772
772 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
773 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
773 controller='admin/repos', action='edit_remote_form',
774 controller='admin/repos', action='edit_remote_form',
774 conditions={'method': ['GET'], 'function': check_repo},
775 conditions={'method': ['GET'], 'function': check_repo},
775 requirements=URL_NAME_REQUIREMENTS)
776 requirements=URL_NAME_REQUIREMENTS)
776 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
777 rmap.connect('edit_repo_remote', '/{repo_name}/settings/remote',
777 controller='admin/repos', action='edit_remote',
778 controller='admin/repos', action='edit_remote',
778 conditions={'method': ['PUT'], 'function': check_repo},
779 conditions={'method': ['PUT'], 'function': check_repo},
779 requirements=URL_NAME_REQUIREMENTS)
780 requirements=URL_NAME_REQUIREMENTS)
780
781
781 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
782 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
782 controller='admin/repos', action='edit_statistics_form',
783 controller='admin/repos', action='edit_statistics_form',
783 conditions={'method': ['GET'], 'function': check_repo},
784 conditions={'method': ['GET'], 'function': check_repo},
784 requirements=URL_NAME_REQUIREMENTS)
785 requirements=URL_NAME_REQUIREMENTS)
785 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
786 rmap.connect('edit_repo_statistics', '/{repo_name}/settings/statistics',
786 controller='admin/repos', action='edit_statistics',
787 controller='admin/repos', action='edit_statistics',
787 conditions={'method': ['PUT'], 'function': check_repo},
788 conditions={'method': ['PUT'], 'function': check_repo},
788 requirements=URL_NAME_REQUIREMENTS)
789 requirements=URL_NAME_REQUIREMENTS)
789 rmap.connect('repo_settings_issuetracker',
790 rmap.connect('repo_settings_issuetracker',
790 '/{repo_name}/settings/issue-tracker',
791 '/{repo_name}/settings/issue-tracker',
791 controller='admin/repos', action='repo_issuetracker',
792 controller='admin/repos', action='repo_issuetracker',
792 conditions={'method': ['GET'], 'function': check_repo},
793 conditions={'method': ['GET'], 'function': check_repo},
793 requirements=URL_NAME_REQUIREMENTS)
794 requirements=URL_NAME_REQUIREMENTS)
794 rmap.connect('repo_issuetracker_test',
795 rmap.connect('repo_issuetracker_test',
795 '/{repo_name}/settings/issue-tracker/test',
796 '/{repo_name}/settings/issue-tracker/test',
796 controller='admin/repos', action='repo_issuetracker_test',
797 controller='admin/repos', action='repo_issuetracker_test',
797 conditions={'method': ['POST'], 'function': check_repo},
798 conditions={'method': ['POST'], 'function': check_repo},
798 requirements=URL_NAME_REQUIREMENTS)
799 requirements=URL_NAME_REQUIREMENTS)
799 rmap.connect('repo_issuetracker_delete',
800 rmap.connect('repo_issuetracker_delete',
800 '/{repo_name}/settings/issue-tracker/delete',
801 '/{repo_name}/settings/issue-tracker/delete',
801 controller='admin/repos', action='repo_issuetracker_delete',
802 controller='admin/repos', action='repo_issuetracker_delete',
802 conditions={'method': ['DELETE'], 'function': check_repo},
803 conditions={'method': ['DELETE'], 'function': check_repo},
803 requirements=URL_NAME_REQUIREMENTS)
804 requirements=URL_NAME_REQUIREMENTS)
804 rmap.connect('repo_issuetracker_save',
805 rmap.connect('repo_issuetracker_save',
805 '/{repo_name}/settings/issue-tracker/save',
806 '/{repo_name}/settings/issue-tracker/save',
806 controller='admin/repos', action='repo_issuetracker_save',
807 controller='admin/repos', action='repo_issuetracker_save',
807 conditions={'method': ['POST'], 'function': check_repo},
808 conditions={'method': ['POST'], 'function': check_repo},
808 requirements=URL_NAME_REQUIREMENTS)
809 requirements=URL_NAME_REQUIREMENTS)
809 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
810 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
810 controller='admin/repos', action='repo_settings_vcs_update',
811 controller='admin/repos', action='repo_settings_vcs_update',
811 conditions={'method': ['POST'], 'function': check_repo},
812 conditions={'method': ['POST'], 'function': check_repo},
812 requirements=URL_NAME_REQUIREMENTS)
813 requirements=URL_NAME_REQUIREMENTS)
813 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
814 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
814 controller='admin/repos', action='repo_settings_vcs',
815 controller='admin/repos', action='repo_settings_vcs',
815 conditions={'method': ['GET'], 'function': check_repo},
816 conditions={'method': ['GET'], 'function': check_repo},
816 requirements=URL_NAME_REQUIREMENTS)
817 requirements=URL_NAME_REQUIREMENTS)
817 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
818 rmap.connect('repo_vcs_settings', '/{repo_name}/settings/vcs',
818 controller='admin/repos', action='repo_delete_svn_pattern',
819 controller='admin/repos', action='repo_delete_svn_pattern',
819 conditions={'method': ['DELETE'], 'function': check_repo},
820 conditions={'method': ['DELETE'], 'function': check_repo},
820 requirements=URL_NAME_REQUIREMENTS)
821 requirements=URL_NAME_REQUIREMENTS)
821
822
822 # still working url for backward compat.
823 # still working url for backward compat.
823 rmap.connect('raw_changeset_home_depraced',
824 rmap.connect('raw_changeset_home_depraced',
824 '/{repo_name}/raw-changeset/{revision}',
825 '/{repo_name}/raw-changeset/{revision}',
825 controller='changeset', action='changeset_raw',
826 controller='changeset', action='changeset_raw',
826 revision='tip', conditions={'function': check_repo},
827 revision='tip', conditions={'function': check_repo},
827 requirements=URL_NAME_REQUIREMENTS)
828 requirements=URL_NAME_REQUIREMENTS)
828
829
829 # new URLs
830 # new URLs
830 rmap.connect('changeset_raw_home',
831 rmap.connect('changeset_raw_home',
831 '/{repo_name}/changeset-diff/{revision}',
832 '/{repo_name}/changeset-diff/{revision}',
832 controller='changeset', action='changeset_raw',
833 controller='changeset', action='changeset_raw',
833 revision='tip', conditions={'function': check_repo},
834 revision='tip', conditions={'function': check_repo},
834 requirements=URL_NAME_REQUIREMENTS)
835 requirements=URL_NAME_REQUIREMENTS)
835
836
836 rmap.connect('changeset_patch_home',
837 rmap.connect('changeset_patch_home',
837 '/{repo_name}/changeset-patch/{revision}',
838 '/{repo_name}/changeset-patch/{revision}',
838 controller='changeset', action='changeset_patch',
839 controller='changeset', action='changeset_patch',
839 revision='tip', conditions={'function': check_repo},
840 revision='tip', conditions={'function': check_repo},
840 requirements=URL_NAME_REQUIREMENTS)
841 requirements=URL_NAME_REQUIREMENTS)
841
842
842 rmap.connect('changeset_download_home',
843 rmap.connect('changeset_download_home',
843 '/{repo_name}/changeset-download/{revision}',
844 '/{repo_name}/changeset-download/{revision}',
844 controller='changeset', action='changeset_download',
845 controller='changeset', action='changeset_download',
845 revision='tip', conditions={'function': check_repo},
846 revision='tip', conditions={'function': check_repo},
846 requirements=URL_NAME_REQUIREMENTS)
847 requirements=URL_NAME_REQUIREMENTS)
847
848
848 rmap.connect('changeset_comment',
849 rmap.connect('changeset_comment',
849 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
850 '/{repo_name}/changeset/{revision}/comment', jsroute=True,
850 controller='changeset', revision='tip', action='comment',
851 controller='changeset', revision='tip', action='comment',
851 conditions={'function': check_repo},
852 conditions={'function': check_repo},
852 requirements=URL_NAME_REQUIREMENTS)
853 requirements=URL_NAME_REQUIREMENTS)
853
854
854 rmap.connect('changeset_comment_preview',
855 rmap.connect('changeset_comment_preview',
855 '/{repo_name}/changeset/comment/preview', jsroute=True,
856 '/{repo_name}/changeset/comment/preview', jsroute=True,
856 controller='changeset', action='preview_comment',
857 controller='changeset', action='preview_comment',
857 conditions={'function': check_repo, 'method': ['POST']},
858 conditions={'function': check_repo, 'method': ['POST']},
858 requirements=URL_NAME_REQUIREMENTS)
859 requirements=URL_NAME_REQUIREMENTS)
859
860
860 rmap.connect('changeset_comment_delete',
861 rmap.connect('changeset_comment_delete',
861 '/{repo_name}/changeset/comment/{comment_id}/delete',
862 '/{repo_name}/changeset/comment/{comment_id}/delete',
862 controller='changeset', action='delete_comment',
863 controller='changeset', action='delete_comment',
863 conditions={'function': check_repo, 'method': ['DELETE']},
864 conditions={'function': check_repo, 'method': ['DELETE']},
864 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
865 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
865
866
866 rmap.connect('changeset_info', '/changeset_info/{repo_name}/{revision}',
867 rmap.connect('changeset_info', '/changeset_info/{repo_name}/{revision}',
867 controller='changeset', action='changeset_info',
868 controller='changeset', action='changeset_info',
868 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
869 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
869
870
870 rmap.connect('compare_home',
871 rmap.connect('compare_home',
871 '/{repo_name}/compare',
872 '/{repo_name}/compare',
872 controller='compare', action='index',
873 controller='compare', action='index',
873 conditions={'function': check_repo},
874 conditions={'function': check_repo},
874 requirements=URL_NAME_REQUIREMENTS)
875 requirements=URL_NAME_REQUIREMENTS)
875
876
876 rmap.connect('compare_url',
877 rmap.connect('compare_url',
877 '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
878 '/{repo_name}/compare/{source_ref_type}@{source_ref:.*?}...{target_ref_type}@{target_ref:.*?}',
878 controller='compare', action='compare',
879 controller='compare', action='compare',
879 conditions={'function': check_repo},
880 conditions={'function': check_repo},
880 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
881 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
881
882
882 rmap.connect('pullrequest_home',
883 rmap.connect('pullrequest_home',
883 '/{repo_name}/pull-request/new', controller='pullrequests',
884 '/{repo_name}/pull-request/new', controller='pullrequests',
884 action='index', conditions={'function': check_repo,
885 action='index', conditions={'function': check_repo,
885 'method': ['GET']},
886 'method': ['GET']},
886 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
887 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
887
888
888 rmap.connect('pullrequest',
889 rmap.connect('pullrequest',
889 '/{repo_name}/pull-request/new', controller='pullrequests',
890 '/{repo_name}/pull-request/new', controller='pullrequests',
890 action='create', conditions={'function': check_repo,
891 action='create', conditions={'function': check_repo,
891 'method': ['POST']},
892 'method': ['POST']},
892 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
893 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
893
894
894 rmap.connect('pullrequest_repo_refs',
895 rmap.connect('pullrequest_repo_refs',
895 '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
896 '/{repo_name}/pull-request/refs/{target_repo_name:.*?[^/]}',
896 controller='pullrequests',
897 controller='pullrequests',
897 action='get_repo_refs',
898 action='get_repo_refs',
898 conditions={'function': check_repo, 'method': ['GET']},
899 conditions={'function': check_repo, 'method': ['GET']},
899 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
900 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
900
901
901 rmap.connect('pullrequest_repo_destinations',
902 rmap.connect('pullrequest_repo_destinations',
902 '/{repo_name}/pull-request/repo-destinations',
903 '/{repo_name}/pull-request/repo-destinations',
903 controller='pullrequests',
904 controller='pullrequests',
904 action='get_repo_destinations',
905 action='get_repo_destinations',
905 conditions={'function': check_repo, 'method': ['GET']},
906 conditions={'function': check_repo, 'method': ['GET']},
906 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
907 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
907
908
908 rmap.connect('pullrequest_show',
909 rmap.connect('pullrequest_show',
909 '/{repo_name}/pull-request/{pull_request_id}',
910 '/{repo_name}/pull-request/{pull_request_id}',
910 controller='pullrequests',
911 controller='pullrequests',
911 action='show', conditions={'function': check_repo,
912 action='show', conditions={'function': check_repo,
912 'method': ['GET']},
913 'method': ['GET']},
913 requirements=URL_NAME_REQUIREMENTS)
914 requirements=URL_NAME_REQUIREMENTS)
914
915
915 rmap.connect('pullrequest_update',
916 rmap.connect('pullrequest_update',
916 '/{repo_name}/pull-request/{pull_request_id}',
917 '/{repo_name}/pull-request/{pull_request_id}',
917 controller='pullrequests',
918 controller='pullrequests',
918 action='update', conditions={'function': check_repo,
919 action='update', conditions={'function': check_repo,
919 'method': ['PUT']},
920 'method': ['PUT']},
920 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
921 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
921
922
922 rmap.connect('pullrequest_merge',
923 rmap.connect('pullrequest_merge',
923 '/{repo_name}/pull-request/{pull_request_id}',
924 '/{repo_name}/pull-request/{pull_request_id}',
924 controller='pullrequests',
925 controller='pullrequests',
925 action='merge', conditions={'function': check_repo,
926 action='merge', conditions={'function': check_repo,
926 'method': ['POST']},
927 'method': ['POST']},
927 requirements=URL_NAME_REQUIREMENTS)
928 requirements=URL_NAME_REQUIREMENTS)
928
929
929 rmap.connect('pullrequest_delete',
930 rmap.connect('pullrequest_delete',
930 '/{repo_name}/pull-request/{pull_request_id}',
931 '/{repo_name}/pull-request/{pull_request_id}',
931 controller='pullrequests',
932 controller='pullrequests',
932 action='delete', conditions={'function': check_repo,
933 action='delete', conditions={'function': check_repo,
933 'method': ['DELETE']},
934 'method': ['DELETE']},
934 requirements=URL_NAME_REQUIREMENTS)
935 requirements=URL_NAME_REQUIREMENTS)
935
936
936 rmap.connect('pullrequest_show_all',
937 rmap.connect('pullrequest_show_all',
937 '/{repo_name}/pull-request',
938 '/{repo_name}/pull-request',
938 controller='pullrequests',
939 controller='pullrequests',
939 action='show_all', conditions={'function': check_repo,
940 action='show_all', conditions={'function': check_repo,
940 'method': ['GET']},
941 'method': ['GET']},
941 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
942 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
942
943
943 rmap.connect('pullrequest_comment',
944 rmap.connect('pullrequest_comment',
944 '/{repo_name}/pull-request-comment/{pull_request_id}',
945 '/{repo_name}/pull-request-comment/{pull_request_id}',
945 controller='pullrequests',
946 controller='pullrequests',
946 action='comment', conditions={'function': check_repo,
947 action='comment', conditions={'function': check_repo,
947 'method': ['POST']},
948 'method': ['POST']},
948 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
949 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
949
950
950 rmap.connect('pullrequest_comment_delete',
951 rmap.connect('pullrequest_comment_delete',
951 '/{repo_name}/pull-request-comment/{comment_id}/delete',
952 '/{repo_name}/pull-request-comment/{comment_id}/delete',
952 controller='pullrequests', action='delete_comment',
953 controller='pullrequests', action='delete_comment',
953 conditions={'function': check_repo, 'method': ['DELETE']},
954 conditions={'function': check_repo, 'method': ['DELETE']},
954 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
955 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
955
956
956 rmap.connect('summary_home_explicit', '/{repo_name}/summary',
957 rmap.connect('summary_home_explicit', '/{repo_name}/summary',
957 controller='summary', conditions={'function': check_repo},
958 controller='summary', conditions={'function': check_repo},
958 requirements=URL_NAME_REQUIREMENTS)
959 requirements=URL_NAME_REQUIREMENTS)
959
960
960 rmap.connect('branches_home', '/{repo_name}/branches',
961 rmap.connect('branches_home', '/{repo_name}/branches',
961 controller='branches', conditions={'function': check_repo},
962 controller='branches', conditions={'function': check_repo},
962 requirements=URL_NAME_REQUIREMENTS)
963 requirements=URL_NAME_REQUIREMENTS)
963
964
964 rmap.connect('tags_home', '/{repo_name}/tags',
965 rmap.connect('tags_home', '/{repo_name}/tags',
965 controller='tags', conditions={'function': check_repo},
966 controller='tags', conditions={'function': check_repo},
966 requirements=URL_NAME_REQUIREMENTS)
967 requirements=URL_NAME_REQUIREMENTS)
967
968
968 rmap.connect('bookmarks_home', '/{repo_name}/bookmarks',
969 rmap.connect('bookmarks_home', '/{repo_name}/bookmarks',
969 controller='bookmarks', conditions={'function': check_repo},
970 controller='bookmarks', conditions={'function': check_repo},
970 requirements=URL_NAME_REQUIREMENTS)
971 requirements=URL_NAME_REQUIREMENTS)
971
972
972 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
973 rmap.connect('changelog_home', '/{repo_name}/changelog', jsroute=True,
973 controller='changelog', conditions={'function': check_repo},
974 controller='changelog', conditions={'function': check_repo},
974 requirements=URL_NAME_REQUIREMENTS)
975 requirements=URL_NAME_REQUIREMENTS)
975
976
976 rmap.connect('changelog_summary_home', '/{repo_name}/changelog_summary',
977 rmap.connect('changelog_summary_home', '/{repo_name}/changelog_summary',
977 controller='changelog', action='changelog_summary',
978 controller='changelog', action='changelog_summary',
978 conditions={'function': check_repo},
979 conditions={'function': check_repo},
979 requirements=URL_NAME_REQUIREMENTS)
980 requirements=URL_NAME_REQUIREMENTS)
980
981
981 rmap.connect('changelog_file_home',
982 rmap.connect('changelog_file_home',
982 '/{repo_name}/changelog/{revision}/{f_path}',
983 '/{repo_name}/changelog/{revision}/{f_path}',
983 controller='changelog', f_path=None,
984 controller='changelog', f_path=None,
984 conditions={'function': check_repo},
985 conditions={'function': check_repo},
985 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
986 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
986
987
987 rmap.connect('changelog_details', '/{repo_name}/changelog_details/{cs}',
988 rmap.connect('changelog_details', '/{repo_name}/changelog_details/{cs}',
988 controller='changelog', action='changelog_details',
989 controller='changelog', action='changelog_details',
989 conditions={'function': check_repo},
990 conditions={'function': check_repo},
990 requirements=URL_NAME_REQUIREMENTS)
991 requirements=URL_NAME_REQUIREMENTS)
991
992
992 rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
993 rmap.connect('files_home', '/{repo_name}/files/{revision}/{f_path}',
993 controller='files', revision='tip', f_path='',
994 controller='files', revision='tip', f_path='',
994 conditions={'function': check_repo},
995 conditions={'function': check_repo},
995 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
996 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
996
997
997 rmap.connect('files_home_simple_catchrev',
998 rmap.connect('files_home_simple_catchrev',
998 '/{repo_name}/files/{revision}',
999 '/{repo_name}/files/{revision}',
999 controller='files', revision='tip', f_path='',
1000 controller='files', revision='tip', f_path='',
1000 conditions={'function': check_repo},
1001 conditions={'function': check_repo},
1001 requirements=URL_NAME_REQUIREMENTS)
1002 requirements=URL_NAME_REQUIREMENTS)
1002
1003
1003 rmap.connect('files_home_simple_catchall',
1004 rmap.connect('files_home_simple_catchall',
1004 '/{repo_name}/files',
1005 '/{repo_name}/files',
1005 controller='files', revision='tip', f_path='',
1006 controller='files', revision='tip', f_path='',
1006 conditions={'function': check_repo},
1007 conditions={'function': check_repo},
1007 requirements=URL_NAME_REQUIREMENTS)
1008 requirements=URL_NAME_REQUIREMENTS)
1008
1009
1009 rmap.connect('files_history_home',
1010 rmap.connect('files_history_home',
1010 '/{repo_name}/history/{revision}/{f_path}',
1011 '/{repo_name}/history/{revision}/{f_path}',
1011 controller='files', action='history', revision='tip', f_path='',
1012 controller='files', action='history', revision='tip', f_path='',
1012 conditions={'function': check_repo},
1013 conditions={'function': check_repo},
1013 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1014 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1014
1015
1015 rmap.connect('files_authors_home',
1016 rmap.connect('files_authors_home',
1016 '/{repo_name}/authors/{revision}/{f_path}',
1017 '/{repo_name}/authors/{revision}/{f_path}',
1017 controller='files', action='authors', revision='tip', f_path='',
1018 controller='files', action='authors', revision='tip', f_path='',
1018 conditions={'function': check_repo},
1019 conditions={'function': check_repo},
1019 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1020 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1020
1021
1021 rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
1022 rmap.connect('files_diff_home', '/{repo_name}/diff/{f_path}',
1022 controller='files', action='diff', f_path='',
1023 controller='files', action='diff', f_path='',
1023 conditions={'function': check_repo},
1024 conditions={'function': check_repo},
1024 requirements=URL_NAME_REQUIREMENTS)
1025 requirements=URL_NAME_REQUIREMENTS)
1025
1026
1026 rmap.connect('files_diff_2way_home',
1027 rmap.connect('files_diff_2way_home',
1027 '/{repo_name}/diff-2way/{f_path}',
1028 '/{repo_name}/diff-2way/{f_path}',
1028 controller='files', action='diff_2way', f_path='',
1029 controller='files', action='diff_2way', f_path='',
1029 conditions={'function': check_repo},
1030 conditions={'function': check_repo},
1030 requirements=URL_NAME_REQUIREMENTS)
1031 requirements=URL_NAME_REQUIREMENTS)
1031
1032
1032 rmap.connect('files_rawfile_home',
1033 rmap.connect('files_rawfile_home',
1033 '/{repo_name}/rawfile/{revision}/{f_path}',
1034 '/{repo_name}/rawfile/{revision}/{f_path}',
1034 controller='files', action='rawfile', revision='tip',
1035 controller='files', action='rawfile', revision='tip',
1035 f_path='', conditions={'function': check_repo},
1036 f_path='', conditions={'function': check_repo},
1036 requirements=URL_NAME_REQUIREMENTS)
1037 requirements=URL_NAME_REQUIREMENTS)
1037
1038
1038 rmap.connect('files_raw_home',
1039 rmap.connect('files_raw_home',
1039 '/{repo_name}/raw/{revision}/{f_path}',
1040 '/{repo_name}/raw/{revision}/{f_path}',
1040 controller='files', action='raw', revision='tip', f_path='',
1041 controller='files', action='raw', revision='tip', f_path='',
1041 conditions={'function': check_repo},
1042 conditions={'function': check_repo},
1042 requirements=URL_NAME_REQUIREMENTS)
1043 requirements=URL_NAME_REQUIREMENTS)
1043
1044
1044 rmap.connect('files_render_home',
1045 rmap.connect('files_render_home',
1045 '/{repo_name}/render/{revision}/{f_path}',
1046 '/{repo_name}/render/{revision}/{f_path}',
1046 controller='files', action='index', revision='tip', f_path='',
1047 controller='files', action='index', revision='tip', f_path='',
1047 rendered=True, conditions={'function': check_repo},
1048 rendered=True, conditions={'function': check_repo},
1048 requirements=URL_NAME_REQUIREMENTS)
1049 requirements=URL_NAME_REQUIREMENTS)
1049
1050
1050 rmap.connect('files_annotate_home',
1051 rmap.connect('files_annotate_home',
1051 '/{repo_name}/annotate/{revision}/{f_path}',
1052 '/{repo_name}/annotate/{revision}/{f_path}',
1052 controller='files', action='index', revision='tip',
1053 controller='files', action='index', revision='tip',
1053 f_path='', annotate=True, conditions={'function': check_repo},
1054 f_path='', annotate=True, conditions={'function': check_repo},
1054 requirements=URL_NAME_REQUIREMENTS)
1055 requirements=URL_NAME_REQUIREMENTS)
1055
1056
1056 rmap.connect('files_edit',
1057 rmap.connect('files_edit',
1057 '/{repo_name}/edit/{revision}/{f_path}',
1058 '/{repo_name}/edit/{revision}/{f_path}',
1058 controller='files', action='edit', revision='tip',
1059 controller='files', action='edit', revision='tip',
1059 f_path='',
1060 f_path='',
1060 conditions={'function': check_repo, 'method': ['POST']},
1061 conditions={'function': check_repo, 'method': ['POST']},
1061 requirements=URL_NAME_REQUIREMENTS)
1062 requirements=URL_NAME_REQUIREMENTS)
1062
1063
1063 rmap.connect('files_edit_home',
1064 rmap.connect('files_edit_home',
1064 '/{repo_name}/edit/{revision}/{f_path}',
1065 '/{repo_name}/edit/{revision}/{f_path}',
1065 controller='files', action='edit_home', revision='tip',
1066 controller='files', action='edit_home', revision='tip',
1066 f_path='', conditions={'function': check_repo},
1067 f_path='', conditions={'function': check_repo},
1067 requirements=URL_NAME_REQUIREMENTS)
1068 requirements=URL_NAME_REQUIREMENTS)
1068
1069
1069 rmap.connect('files_add',
1070 rmap.connect('files_add',
1070 '/{repo_name}/add/{revision}/{f_path}',
1071 '/{repo_name}/add/{revision}/{f_path}',
1071 controller='files', action='add', revision='tip',
1072 controller='files', action='add', revision='tip',
1072 f_path='',
1073 f_path='',
1073 conditions={'function': check_repo, 'method': ['POST']},
1074 conditions={'function': check_repo, 'method': ['POST']},
1074 requirements=URL_NAME_REQUIREMENTS)
1075 requirements=URL_NAME_REQUIREMENTS)
1075
1076
1076 rmap.connect('files_add_home',
1077 rmap.connect('files_add_home',
1077 '/{repo_name}/add/{revision}/{f_path}',
1078 '/{repo_name}/add/{revision}/{f_path}',
1078 controller='files', action='add_home', revision='tip',
1079 controller='files', action='add_home', revision='tip',
1079 f_path='', conditions={'function': check_repo},
1080 f_path='', conditions={'function': check_repo},
1080 requirements=URL_NAME_REQUIREMENTS)
1081 requirements=URL_NAME_REQUIREMENTS)
1081
1082
1082 rmap.connect('files_delete',
1083 rmap.connect('files_delete',
1083 '/{repo_name}/delete/{revision}/{f_path}',
1084 '/{repo_name}/delete/{revision}/{f_path}',
1084 controller='files', action='delete', revision='tip',
1085 controller='files', action='delete', revision='tip',
1085 f_path='',
1086 f_path='',
1086 conditions={'function': check_repo, 'method': ['POST']},
1087 conditions={'function': check_repo, 'method': ['POST']},
1087 requirements=URL_NAME_REQUIREMENTS)
1088 requirements=URL_NAME_REQUIREMENTS)
1088
1089
1089 rmap.connect('files_delete_home',
1090 rmap.connect('files_delete_home',
1090 '/{repo_name}/delete/{revision}/{f_path}',
1091 '/{repo_name}/delete/{revision}/{f_path}',
1091 controller='files', action='delete_home', revision='tip',
1092 controller='files', action='delete_home', revision='tip',
1092 f_path='', conditions={'function': check_repo},
1093 f_path='', conditions={'function': check_repo},
1093 requirements=URL_NAME_REQUIREMENTS)
1094 requirements=URL_NAME_REQUIREMENTS)
1094
1095
1095 rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
1096 rmap.connect('files_archive_home', '/{repo_name}/archive/{fname}',
1096 controller='files', action='archivefile',
1097 controller='files', action='archivefile',
1097 conditions={'function': check_repo},
1098 conditions={'function': check_repo},
1098 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1099 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1099
1100
1100 rmap.connect('files_nodelist_home',
1101 rmap.connect('files_nodelist_home',
1101 '/{repo_name}/nodelist/{revision}/{f_path}',
1102 '/{repo_name}/nodelist/{revision}/{f_path}',
1102 controller='files', action='nodelist',
1103 controller='files', action='nodelist',
1103 conditions={'function': check_repo},
1104 conditions={'function': check_repo},
1104 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1105 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1105
1106
1106 rmap.connect('files_nodetree_full',
1107 rmap.connect('files_nodetree_full',
1107 '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
1108 '/{repo_name}/nodetree_full/{commit_id}/{f_path}',
1108 controller='files', action='nodetree_full',
1109 controller='files', action='nodetree_full',
1109 conditions={'function': check_repo},
1110 conditions={'function': check_repo},
1110 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1111 requirements=URL_NAME_REQUIREMENTS, jsroute=True)
1111
1112
1112 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
1113 rmap.connect('repo_fork_create_home', '/{repo_name}/fork',
1113 controller='forks', action='fork_create',
1114 controller='forks', action='fork_create',
1114 conditions={'function': check_repo, 'method': ['POST']},
1115 conditions={'function': check_repo, 'method': ['POST']},
1115 requirements=URL_NAME_REQUIREMENTS)
1116 requirements=URL_NAME_REQUIREMENTS)
1116
1117
1117 rmap.connect('repo_fork_home', '/{repo_name}/fork',
1118 rmap.connect('repo_fork_home', '/{repo_name}/fork',
1118 controller='forks', action='fork',
1119 controller='forks', action='fork',
1119 conditions={'function': check_repo},
1120 conditions={'function': check_repo},
1120 requirements=URL_NAME_REQUIREMENTS)
1121 requirements=URL_NAME_REQUIREMENTS)
1121
1122
1122 rmap.connect('repo_forks_home', '/{repo_name}/forks',
1123 rmap.connect('repo_forks_home', '/{repo_name}/forks',
1123 controller='forks', action='forks',
1124 controller='forks', action='forks',
1124 conditions={'function': check_repo},
1125 conditions={'function': check_repo},
1125 requirements=URL_NAME_REQUIREMENTS)
1126 requirements=URL_NAME_REQUIREMENTS)
1126
1127
1127 rmap.connect('repo_followers_home', '/{repo_name}/followers',
1128 rmap.connect('repo_followers_home', '/{repo_name}/followers',
1128 controller='followers', action='followers',
1129 controller='followers', action='followers',
1129 conditions={'function': check_repo},
1130 conditions={'function': check_repo},
1130 requirements=URL_NAME_REQUIREMENTS)
1131 requirements=URL_NAME_REQUIREMENTS)
1131
1132
1132 # must be here for proper group/repo catching pattern
1133 # must be here for proper group/repo catching pattern
1133 _connect_with_slash(
1134 _connect_with_slash(
1134 rmap, 'repo_group_home', '/{group_name}',
1135 rmap, 'repo_group_home', '/{group_name}',
1135 controller='home', action='index_repo_group',
1136 controller='home', action='index_repo_group',
1136 conditions={'function': check_group},
1137 conditions={'function': check_group},
1137 requirements=URL_NAME_REQUIREMENTS)
1138 requirements=URL_NAME_REQUIREMENTS)
1138
1139
1139 # catch all, at the end
1140 # catch all, at the end
1140 _connect_with_slash(
1141 _connect_with_slash(
1141 rmap, 'summary_home', '/{repo_name}', jsroute=True,
1142 rmap, 'summary_home', '/{repo_name}', jsroute=True,
1142 controller='summary', action='index',
1143 controller='summary', action='index',
1143 conditions={'function': check_repo},
1144 conditions={'function': check_repo},
1144 requirements=URL_NAME_REQUIREMENTS)
1145 requirements=URL_NAME_REQUIREMENTS)
1145
1146
1146 return rmap
1147 return rmap
1147
1148
1148
1149
1149 def _connect_with_slash(mapper, name, path, *args, **kwargs):
1150 def _connect_with_slash(mapper, name, path, *args, **kwargs):
1150 """
1151 """
1151 Connect a route with an optional trailing slash in `path`.
1152 Connect a route with an optional trailing slash in `path`.
1152 """
1153 """
1153 mapper.connect(name + '_slash', path + '/', *args, **kwargs)
1154 mapper.connect(name + '_slash', path + '/', *args, **kwargs)
1154 mapper.connect(name, path, *args, **kwargs)
1155 mapper.connect(name, path, *args, **kwargs)
General Comments 0
You need to be logged in to leave comments. Login now