##// END OF EJS Templates
core: allow loading all auth plugins in once place for CE/EE code.
milka -
r4602:592efda0 stable
parent child Browse files
Show More
@@ -1,766 +1,775 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2010-2020 RhodeCode GmbH
3 # Copyright (C) 2010-2020 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 import os
21 import os
22 import sys
22 import sys
23 import logging
23 import logging
24 import collections
24 import collections
25 import tempfile
25 import tempfile
26 import time
26 import time
27
27
28 from paste.gzipper import make_gzip_middleware
28 from paste.gzipper import make_gzip_middleware
29 import pyramid.events
29 import pyramid.events
30 from pyramid.wsgi import wsgiapp
30 from pyramid.wsgi import wsgiapp
31 from pyramid.authorization import ACLAuthorizationPolicy
31 from pyramid.authorization import ACLAuthorizationPolicy
32 from pyramid.config import Configurator
32 from pyramid.config import Configurator
33 from pyramid.settings import asbool, aslist
33 from pyramid.settings import asbool, aslist
34 from pyramid.httpexceptions import (
34 from pyramid.httpexceptions import (
35 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
35 HTTPException, HTTPError, HTTPInternalServerError, HTTPFound, HTTPNotFound)
36 from pyramid.renderers import render_to_response
36 from pyramid.renderers import render_to_response
37
37
38 from rhodecode.model import meta
38 from rhodecode.model import meta
39 from rhodecode.config import patches
39 from rhodecode.config import patches
40 from rhodecode.config import utils as config_utils
40 from rhodecode.config import utils as config_utils
41 from rhodecode.config.environment import load_pyramid_environment
41 from rhodecode.config.environment import load_pyramid_environment
42
42
43 import rhodecode.events
43 import rhodecode.events
44 from rhodecode.lib.middleware.vcs import VCSMiddleware
44 from rhodecode.lib.middleware.vcs import VCSMiddleware
45 from rhodecode.lib.request import Request
45 from rhodecode.lib.request import Request
46 from rhodecode.lib.vcs import VCSCommunicationError
46 from rhodecode.lib.vcs import VCSCommunicationError
47 from rhodecode.lib.exceptions import VCSServerUnavailable
47 from rhodecode.lib.exceptions import VCSServerUnavailable
48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
48 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
49 from rhodecode.lib.middleware.https_fixup import HttpsFixup
49 from rhodecode.lib.middleware.https_fixup import HttpsFixup
50 from rhodecode.lib.celerylib.loader import configure_celery
50 from rhodecode.lib.celerylib.loader import configure_celery
51 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
51 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
52 from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
52 from rhodecode.lib.utils2 import aslist as rhodecode_aslist, AttributeDict
53 from rhodecode.lib.exc_tracking import store_exception
53 from rhodecode.lib.exc_tracking import store_exception
54 from rhodecode.subscribers import (
54 from rhodecode.subscribers import (
55 scan_repositories_if_enabled, write_js_routes_if_enabled,
55 scan_repositories_if_enabled, write_js_routes_if_enabled,
56 write_metadata_if_needed, write_usage_data)
56 write_metadata_if_needed, write_usage_data)
57
57
58
58
59 log = logging.getLogger(__name__)
59 log = logging.getLogger(__name__)
60
60
61
61
62 def is_http_error(response):
62 def is_http_error(response):
63 # error which should have traceback
63 # error which should have traceback
64 return response.status_code > 499
64 return response.status_code > 499
65
65
66
66
67 def should_load_all():
67 def should_load_all():
68 """
68 """
69 Returns if all application components should be loaded. In some cases it's
69 Returns if all application components should be loaded. In some cases it's
70 desired to skip apps loading for faster shell script execution
70 desired to skip apps loading for faster shell script execution
71 """
71 """
72 ssh_cmd = os.environ.get('RC_CMD_SSH_WRAPPER')
72 ssh_cmd = os.environ.get('RC_CMD_SSH_WRAPPER')
73 if ssh_cmd:
73 if ssh_cmd:
74 return False
74 return False
75
75
76 return True
76 return True
77
77
78
78
79 def make_pyramid_app(global_config, **settings):
79 def make_pyramid_app(global_config, **settings):
80 """
80 """
81 Constructs the WSGI application based on Pyramid.
81 Constructs the WSGI application based on Pyramid.
82
82
83 Specials:
83 Specials:
84
84
85 * The application can also be integrated like a plugin via the call to
85 * The application can also be integrated like a plugin via the call to
86 `includeme`. This is accompanied with the other utility functions which
86 `includeme`. This is accompanied with the other utility functions which
87 are called. Changing this should be done with great care to not break
87 are called. Changing this should be done with great care to not break
88 cases when these fragments are assembled from another place.
88 cases when these fragments are assembled from another place.
89
89
90 """
90 """
91
91
92 # Allows to use format style "{ENV_NAME}" placeholders in the configuration. It
92 # Allows to use format style "{ENV_NAME}" placeholders in the configuration. It
93 # will be replaced by the value of the environment variable "NAME" in this case.
93 # will be replaced by the value of the environment variable "NAME" in this case.
94 start_time = time.time()
94 start_time = time.time()
95
95
96 debug = asbool(global_config.get('debug'))
96 debug = asbool(global_config.get('debug'))
97 if debug:
97 if debug:
98 enable_debug()
98 enable_debug()
99
99
100 environ = {'ENV_{}'.format(key): value for key, value in os.environ.items()}
100 environ = {'ENV_{}'.format(key): value for key, value in os.environ.items()}
101
101
102 global_config = _substitute_values(global_config, environ)
102 global_config = _substitute_values(global_config, environ)
103 settings = _substitute_values(settings, environ)
103 settings = _substitute_values(settings, environ)
104
104
105 sanitize_settings_and_apply_defaults(global_config, settings)
105 sanitize_settings_and_apply_defaults(global_config, settings)
106
106
107 config = Configurator(settings=settings)
107 config = Configurator(settings=settings)
108
108
109 # Apply compatibility patches
109 # Apply compatibility patches
110 patches.inspect_getargspec()
110 patches.inspect_getargspec()
111
111
112 load_pyramid_environment(global_config, settings)
112 load_pyramid_environment(global_config, settings)
113
113
114 # Static file view comes first
114 # Static file view comes first
115 includeme_first(config)
115 includeme_first(config)
116
116
117 includeme(config)
117 includeme(config)
118
118
119 pyramid_app = config.make_wsgi_app()
119 pyramid_app = config.make_wsgi_app()
120 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
120 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
121 pyramid_app.config = config
121 pyramid_app.config = config
122
122
123 config.configure_celery(global_config['__file__'])
123 config.configure_celery(global_config['__file__'])
124 # creating the app uses a connection - return it after we are done
124 # creating the app uses a connection - return it after we are done
125 meta.Session.remove()
125 meta.Session.remove()
126 total_time = time.time() - start_time
126 total_time = time.time() - start_time
127 log.info('Pyramid app `%s` created and configured in %.2fs',
127 log.info('Pyramid app `%s` created and configured in %.2fs',
128 pyramid_app.func_name, total_time)
128 pyramid_app.func_name, total_time)
129
129
130 return pyramid_app
130 return pyramid_app
131
131
132
132
133 def not_found_view(request):
133 def not_found_view(request):
134 """
134 """
135 This creates the view which should be registered as not-found-view to
135 This creates the view which should be registered as not-found-view to
136 pyramid.
136 pyramid.
137 """
137 """
138
138
139 if not getattr(request, 'vcs_call', None):
139 if not getattr(request, 'vcs_call', None):
140 # handle like regular case with our error_handler
140 # handle like regular case with our error_handler
141 return error_handler(HTTPNotFound(), request)
141 return error_handler(HTTPNotFound(), request)
142
142
143 # handle not found view as a vcs call
143 # handle not found view as a vcs call
144 settings = request.registry.settings
144 settings = request.registry.settings
145 ae_client = getattr(request, 'ae_client', None)
145 ae_client = getattr(request, 'ae_client', None)
146 vcs_app = VCSMiddleware(
146 vcs_app = VCSMiddleware(
147 HTTPNotFound(), request.registry, settings,
147 HTTPNotFound(), request.registry, settings,
148 appenlight_client=ae_client)
148 appenlight_client=ae_client)
149
149
150 return wsgiapp(vcs_app)(None, request)
150 return wsgiapp(vcs_app)(None, request)
151
151
152
152
153 def error_handler(exception, request):
153 def error_handler(exception, request):
154 import rhodecode
154 import rhodecode
155 from rhodecode.lib import helpers
155 from rhodecode.lib import helpers
156
156
157 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
157 rhodecode_title = rhodecode.CONFIG.get('rhodecode_title') or 'RhodeCode'
158
158
159 base_response = HTTPInternalServerError()
159 base_response = HTTPInternalServerError()
160 # prefer original exception for the response since it may have headers set
160 # prefer original exception for the response since it may have headers set
161 if isinstance(exception, HTTPException):
161 if isinstance(exception, HTTPException):
162 base_response = exception
162 base_response = exception
163 elif isinstance(exception, VCSCommunicationError):
163 elif isinstance(exception, VCSCommunicationError):
164 base_response = VCSServerUnavailable()
164 base_response = VCSServerUnavailable()
165
165
166 if is_http_error(base_response):
166 if is_http_error(base_response):
167 log.exception(
167 log.exception(
168 'error occurred handling this request for path: %s', request.path)
168 'error occurred handling this request for path: %s', request.path)
169
169
170 error_explanation = base_response.explanation or str(base_response)
170 error_explanation = base_response.explanation or str(base_response)
171 if base_response.status_code == 404:
171 if base_response.status_code == 404:
172 error_explanation += " Optionally you don't have permission to access this page."
172 error_explanation += " Optionally you don't have permission to access this page."
173 c = AttributeDict()
173 c = AttributeDict()
174 c.error_message = base_response.status
174 c.error_message = base_response.status
175 c.error_explanation = error_explanation
175 c.error_explanation = error_explanation
176 c.visual = AttributeDict()
176 c.visual = AttributeDict()
177
177
178 c.visual.rhodecode_support_url = (
178 c.visual.rhodecode_support_url = (
179 request.registry.settings.get('rhodecode_support_url') or
179 request.registry.settings.get('rhodecode_support_url') or
180 request.route_url('rhodecode_support')
180 request.route_url('rhodecode_support')
181 )
181 )
182 c.redirect_time = 0
182 c.redirect_time = 0
183 c.rhodecode_name = rhodecode_title
183 c.rhodecode_name = rhodecode_title
184 if not c.rhodecode_name:
184 if not c.rhodecode_name:
185 c.rhodecode_name = 'Rhodecode'
185 c.rhodecode_name = 'Rhodecode'
186
186
187 c.causes = []
187 c.causes = []
188 if is_http_error(base_response):
188 if is_http_error(base_response):
189 c.causes.append('Server is overloaded.')
189 c.causes.append('Server is overloaded.')
190 c.causes.append('Server database connection is lost.')
190 c.causes.append('Server database connection is lost.')
191 c.causes.append('Server expected unhandled error.')
191 c.causes.append('Server expected unhandled error.')
192
192
193 if hasattr(base_response, 'causes'):
193 if hasattr(base_response, 'causes'):
194 c.causes = base_response.causes
194 c.causes = base_response.causes
195
195
196 c.messages = helpers.flash.pop_messages(request=request)
196 c.messages = helpers.flash.pop_messages(request=request)
197
197
198 exc_info = sys.exc_info()
198 exc_info = sys.exc_info()
199 c.exception_id = id(exc_info)
199 c.exception_id = id(exc_info)
200 c.show_exception_id = isinstance(base_response, VCSServerUnavailable) \
200 c.show_exception_id = isinstance(base_response, VCSServerUnavailable) \
201 or base_response.status_code > 499
201 or base_response.status_code > 499
202 c.exception_id_url = request.route_url(
202 c.exception_id_url = request.route_url(
203 'admin_settings_exception_tracker_show', exception_id=c.exception_id)
203 'admin_settings_exception_tracker_show', exception_id=c.exception_id)
204
204
205 if c.show_exception_id:
205 if c.show_exception_id:
206 store_exception(c.exception_id, exc_info)
206 store_exception(c.exception_id, exc_info)
207
207
208 response = render_to_response(
208 response = render_to_response(
209 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
209 '/errors/error_document.mako', {'c': c, 'h': helpers}, request=request,
210 response=base_response)
210 response=base_response)
211
211
212 return response
212 return response
213
213
214
214
215 def includeme_first(config):
215 def includeme_first(config):
216 # redirect automatic browser favicon.ico requests to correct place
216 # redirect automatic browser favicon.ico requests to correct place
217 def favicon_redirect(context, request):
217 def favicon_redirect(context, request):
218 return HTTPFound(
218 return HTTPFound(
219 request.static_path('rhodecode:public/images/favicon.ico'))
219 request.static_path('rhodecode:public/images/favicon.ico'))
220
220
221 config.add_view(favicon_redirect, route_name='favicon')
221 config.add_view(favicon_redirect, route_name='favicon')
222 config.add_route('favicon', '/favicon.ico')
222 config.add_route('favicon', '/favicon.ico')
223
223
224 def robots_redirect(context, request):
224 def robots_redirect(context, request):
225 return HTTPFound(
225 return HTTPFound(
226 request.static_path('rhodecode:public/robots.txt'))
226 request.static_path('rhodecode:public/robots.txt'))
227
227
228 config.add_view(robots_redirect, route_name='robots')
228 config.add_view(robots_redirect, route_name='robots')
229 config.add_route('robots', '/robots.txt')
229 config.add_route('robots', '/robots.txt')
230
230
231 config.add_static_view(
231 config.add_static_view(
232 '_static/deform', 'deform:static')
232 '_static/deform', 'deform:static')
233 config.add_static_view(
233 config.add_static_view(
234 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
234 '_static/rhodecode', path='rhodecode:public', cache_max_age=3600 * 24)
235
235
236
236
237 def includeme(config):
237 def includeme(config, auth_resources=None):
238 log.debug('Initializing main includeme from %s', os.path.basename(__file__))
238 log.debug('Initializing main includeme from %s', os.path.basename(__file__))
239 settings = config.registry.settings
239 settings = config.registry.settings
240 config.set_request_factory(Request)
240 config.set_request_factory(Request)
241
241
242 # plugin information
242 # plugin information
243 config.registry.rhodecode_plugins = collections.OrderedDict()
243 config.registry.rhodecode_plugins = collections.OrderedDict()
244
244
245 config.add_directive(
245 config.add_directive(
246 'register_rhodecode_plugin', register_rhodecode_plugin)
246 'register_rhodecode_plugin', register_rhodecode_plugin)
247
247
248 config.add_directive('configure_celery', configure_celery)
248 config.add_directive('configure_celery', configure_celery)
249
249
250 if asbool(settings.get('appenlight', 'false')):
250 if asbool(settings.get('appenlight', 'false')):
251 config.include('appenlight_client.ext.pyramid_tween')
251 config.include('appenlight_client.ext.pyramid_tween')
252
252
253 load_all = should_load_all()
253 load_all = should_load_all()
254
254
255 # Includes which are required. The application would fail without them.
255 # Includes which are required. The application would fail without them.
256 config.include('pyramid_mako')
256 config.include('pyramid_mako')
257 config.include('rhodecode.lib.rc_beaker')
257 config.include('rhodecode.lib.rc_beaker')
258 config.include('rhodecode.lib.rc_cache')
258 config.include('rhodecode.lib.rc_cache')
259
259
260 config.include('rhodecode.apps._base.navigation')
260 config.include('rhodecode.apps._base.navigation')
261 config.include('rhodecode.apps._base.subscribers')
261 config.include('rhodecode.apps._base.subscribers')
262 config.include('rhodecode.tweens')
262 config.include('rhodecode.tweens')
263 config.include('rhodecode.authentication')
263 config.include('rhodecode.authentication')
264
264
265 if load_all:
265 if load_all:
266 config.include('rhodecode.integrations')
266 config.include('rhodecode.integrations')
267
267
268 if load_all:
268 if load_all:
269 ce_auth_resources = [
270 'rhodecode.authentication.plugins.auth_crowd',
271 'rhodecode.authentication.plugins.auth_headers',
272 'rhodecode.authentication.plugins.auth_jasig_cas',
273 'rhodecode.authentication.plugins.auth_ldap',
274 'rhodecode.authentication.plugins.auth_pam',
275 'rhodecode.authentication.plugins.auth_rhodecode',
276 'rhodecode.authentication.plugins.auth_token',
277 ]
278
269 # load CE authentication plugins
279 # load CE authentication plugins
270 config.include('rhodecode.authentication.plugins.auth_crowd')
280
271 config.include('rhodecode.authentication.plugins.auth_headers')
281 if auth_resources:
272 config.include('rhodecode.authentication.plugins.auth_jasig_cas')
282 ce_auth_resources.extend(auth_resources)
273 config.include('rhodecode.authentication.plugins.auth_ldap')
283
274 config.include('rhodecode.authentication.plugins.auth_pam')
284 for resource in ce_auth_resources:
275 config.include('rhodecode.authentication.plugins.auth_rhodecode')
285 config.include(resource)
276 config.include('rhodecode.authentication.plugins.auth_token')
277
286
278 # Auto discover authentication plugins and include their configuration.
287 # Auto discover authentication plugins and include their configuration.
279 if asbool(settings.get('auth_plugin.import_legacy_plugins', 'true')):
288 if asbool(settings.get('auth_plugin.import_legacy_plugins', 'true')):
280 from rhodecode.authentication import discover_legacy_plugins
289 from rhodecode.authentication import discover_legacy_plugins
281 discover_legacy_plugins(config)
290 discover_legacy_plugins(config)
282
291
283 # apps
292 # apps
284 if load_all:
293 if load_all:
285 config.include('rhodecode.apps._base')
294 config.include('rhodecode.apps._base')
286 config.include('rhodecode.apps.hovercards')
295 config.include('rhodecode.apps.hovercards')
287 config.include('rhodecode.apps.ops')
296 config.include('rhodecode.apps.ops')
288 config.include('rhodecode.apps.admin')
297 config.include('rhodecode.apps.admin')
289 config.include('rhodecode.apps.channelstream')
298 config.include('rhodecode.apps.channelstream')
290 config.include('rhodecode.apps.file_store')
299 config.include('rhodecode.apps.file_store')
291 config.include('rhodecode.apps.login')
300 config.include('rhodecode.apps.login')
292 config.include('rhodecode.apps.home')
301 config.include('rhodecode.apps.home')
293 config.include('rhodecode.apps.journal')
302 config.include('rhodecode.apps.journal')
294 config.include('rhodecode.apps.repository')
303 config.include('rhodecode.apps.repository')
295 config.include('rhodecode.apps.repo_group')
304 config.include('rhodecode.apps.repo_group')
296 config.include('rhodecode.apps.user_group')
305 config.include('rhodecode.apps.user_group')
297 config.include('rhodecode.apps.search')
306 config.include('rhodecode.apps.search')
298 config.include('rhodecode.apps.user_profile')
307 config.include('rhodecode.apps.user_profile')
299 config.include('rhodecode.apps.user_group_profile')
308 config.include('rhodecode.apps.user_group_profile')
300 config.include('rhodecode.apps.my_account')
309 config.include('rhodecode.apps.my_account')
301 config.include('rhodecode.apps.svn_support')
310 config.include('rhodecode.apps.svn_support')
302 config.include('rhodecode.apps.ssh_support')
311 config.include('rhodecode.apps.ssh_support')
303 config.include('rhodecode.apps.gist')
312 config.include('rhodecode.apps.gist')
304 config.include('rhodecode.apps.debug_style')
313 config.include('rhodecode.apps.debug_style')
305 config.include('rhodecode.api')
314 config.include('rhodecode.api')
306
315
307 config.add_route('rhodecode_support', 'https://rhodecode.com/help/', static=True)
316 config.add_route('rhodecode_support', 'https://rhodecode.com/help/', static=True)
308 config.add_translation_dirs('rhodecode:i18n/')
317 config.add_translation_dirs('rhodecode:i18n/')
309 settings['default_locale_name'] = settings.get('lang', 'en')
318 settings['default_locale_name'] = settings.get('lang', 'en')
310
319
311 # Add subscribers.
320 # Add subscribers.
312 if load_all:
321 if load_all:
313 config.add_subscriber(scan_repositories_if_enabled,
322 config.add_subscriber(scan_repositories_if_enabled,
314 pyramid.events.ApplicationCreated)
323 pyramid.events.ApplicationCreated)
315 config.add_subscriber(write_metadata_if_needed,
324 config.add_subscriber(write_metadata_if_needed,
316 pyramid.events.ApplicationCreated)
325 pyramid.events.ApplicationCreated)
317 config.add_subscriber(write_usage_data,
326 config.add_subscriber(write_usage_data,
318 pyramid.events.ApplicationCreated)
327 pyramid.events.ApplicationCreated)
319 config.add_subscriber(write_js_routes_if_enabled,
328 config.add_subscriber(write_js_routes_if_enabled,
320 pyramid.events.ApplicationCreated)
329 pyramid.events.ApplicationCreated)
321
330
322 # request custom methods
331 # request custom methods
323 config.add_request_method(
332 config.add_request_method(
324 'rhodecode.lib.partial_renderer.get_partial_renderer',
333 'rhodecode.lib.partial_renderer.get_partial_renderer',
325 'get_partial_renderer')
334 'get_partial_renderer')
326
335
327 config.add_request_method(
336 config.add_request_method(
328 'rhodecode.lib.request_counter.get_request_counter',
337 'rhodecode.lib.request_counter.get_request_counter',
329 'request_count')
338 'request_count')
330
339
331 # Set the authorization policy.
340 # Set the authorization policy.
332 authz_policy = ACLAuthorizationPolicy()
341 authz_policy = ACLAuthorizationPolicy()
333 config.set_authorization_policy(authz_policy)
342 config.set_authorization_policy(authz_policy)
334
343
335 # Set the default renderer for HTML templates to mako.
344 # Set the default renderer for HTML templates to mako.
336 config.add_mako_renderer('.html')
345 config.add_mako_renderer('.html')
337
346
338 config.add_renderer(
347 config.add_renderer(
339 name='json_ext',
348 name='json_ext',
340 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
349 factory='rhodecode.lib.ext_json_renderer.pyramid_ext_json')
341
350
342 config.add_renderer(
351 config.add_renderer(
343 name='string_html',
352 name='string_html',
344 factory='rhodecode.lib.string_renderer.html')
353 factory='rhodecode.lib.string_renderer.html')
345
354
346 # include RhodeCode plugins
355 # include RhodeCode plugins
347 includes = aslist(settings.get('rhodecode.includes', []))
356 includes = aslist(settings.get('rhodecode.includes', []))
348 for inc in includes:
357 for inc in includes:
349 config.include(inc)
358 config.include(inc)
350
359
351 # custom not found view, if our pyramid app doesn't know how to handle
360 # custom not found view, if our pyramid app doesn't know how to handle
352 # the request pass it to potential VCS handling ap
361 # the request pass it to potential VCS handling ap
353 config.add_notfound_view(not_found_view)
362 config.add_notfound_view(not_found_view)
354 if not settings.get('debugtoolbar.enabled', False):
363 if not settings.get('debugtoolbar.enabled', False):
355 # disabled debugtoolbar handle all exceptions via the error_handlers
364 # disabled debugtoolbar handle all exceptions via the error_handlers
356 config.add_view(error_handler, context=Exception)
365 config.add_view(error_handler, context=Exception)
357
366
358 # all errors including 403/404/50X
367 # all errors including 403/404/50X
359 config.add_view(error_handler, context=HTTPError)
368 config.add_view(error_handler, context=HTTPError)
360
369
361
370
362 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
371 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
363 """
372 """
364 Apply outer WSGI middlewares around the application.
373 Apply outer WSGI middlewares around the application.
365 """
374 """
366 registry = config.registry
375 registry = config.registry
367 settings = registry.settings
376 settings = registry.settings
368
377
369 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
378 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
370 pyramid_app = HttpsFixup(pyramid_app, settings)
379 pyramid_app = HttpsFixup(pyramid_app, settings)
371
380
372 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
381 pyramid_app, _ae_client = wrap_in_appenlight_if_enabled(
373 pyramid_app, settings)
382 pyramid_app, settings)
374 registry.ae_client = _ae_client
383 registry.ae_client = _ae_client
375
384
376 if settings['gzip_responses']:
385 if settings['gzip_responses']:
377 pyramid_app = make_gzip_middleware(
386 pyramid_app = make_gzip_middleware(
378 pyramid_app, settings, compress_level=1)
387 pyramid_app, settings, compress_level=1)
379
388
380 # this should be the outer most middleware in the wsgi stack since
389 # this should be the outer most middleware in the wsgi stack since
381 # middleware like Routes make database calls
390 # middleware like Routes make database calls
382 def pyramid_app_with_cleanup(environ, start_response):
391 def pyramid_app_with_cleanup(environ, start_response):
383 try:
392 try:
384 return pyramid_app(environ, start_response)
393 return pyramid_app(environ, start_response)
385 finally:
394 finally:
386 # Dispose current database session and rollback uncommitted
395 # Dispose current database session and rollback uncommitted
387 # transactions.
396 # transactions.
388 meta.Session.remove()
397 meta.Session.remove()
389
398
390 # In a single threaded mode server, on non sqlite db we should have
399 # In a single threaded mode server, on non sqlite db we should have
391 # '0 Current Checked out connections' at the end of a request,
400 # '0 Current Checked out connections' at the end of a request,
392 # if not, then something, somewhere is leaving a connection open
401 # if not, then something, somewhere is leaving a connection open
393 pool = meta.Base.metadata.bind.engine.pool
402 pool = meta.Base.metadata.bind.engine.pool
394 log.debug('sa pool status: %s', pool.status())
403 log.debug('sa pool status: %s', pool.status())
395 log.debug('Request processing finalized')
404 log.debug('Request processing finalized')
396
405
397 return pyramid_app_with_cleanup
406 return pyramid_app_with_cleanup
398
407
399
408
400 def sanitize_settings_and_apply_defaults(global_config, settings):
409 def sanitize_settings_and_apply_defaults(global_config, settings):
401 """
410 """
402 Applies settings defaults and does all type conversion.
411 Applies settings defaults and does all type conversion.
403
412
404 We would move all settings parsing and preparation into this place, so that
413 We would move all settings parsing and preparation into this place, so that
405 we have only one place left which deals with this part. The remaining parts
414 we have only one place left which deals with this part. The remaining parts
406 of the application would start to rely fully on well prepared settings.
415 of the application would start to rely fully on well prepared settings.
407
416
408 This piece would later be split up per topic to avoid a big fat monster
417 This piece would later be split up per topic to avoid a big fat monster
409 function.
418 function.
410 """
419 """
411
420
412 settings.setdefault('rhodecode.edition', 'Community Edition')
421 settings.setdefault('rhodecode.edition', 'Community Edition')
413 settings.setdefault('rhodecode.edition_id', 'CE')
422 settings.setdefault('rhodecode.edition_id', 'CE')
414
423
415 if 'mako.default_filters' not in settings:
424 if 'mako.default_filters' not in settings:
416 # set custom default filters if we don't have it defined
425 # set custom default filters if we don't have it defined
417 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
426 settings['mako.imports'] = 'from rhodecode.lib.base import h_filter'
418 settings['mako.default_filters'] = 'h_filter'
427 settings['mako.default_filters'] = 'h_filter'
419
428
420 if 'mako.directories' not in settings:
429 if 'mako.directories' not in settings:
421 mako_directories = settings.setdefault('mako.directories', [
430 mako_directories = settings.setdefault('mako.directories', [
422 # Base templates of the original application
431 # Base templates of the original application
423 'rhodecode:templates',
432 'rhodecode:templates',
424 ])
433 ])
425 log.debug(
434 log.debug(
426 "Using the following Mako template directories: %s",
435 "Using the following Mako template directories: %s",
427 mako_directories)
436 mako_directories)
428
437
429 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
438 # NOTE(marcink): fix redis requirement for schema of connection since 3.X
430 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
439 if 'beaker.session.type' in settings and settings['beaker.session.type'] == 'ext:redis':
431 raw_url = settings['beaker.session.url']
440 raw_url = settings['beaker.session.url']
432 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
441 if not raw_url.startswith(('redis://', 'rediss://', 'unix://')):
433 settings['beaker.session.url'] = 'redis://' + raw_url
442 settings['beaker.session.url'] = 'redis://' + raw_url
434
443
435 # Default includes, possible to change as a user
444 # Default includes, possible to change as a user
436 pyramid_includes = settings.setdefault('pyramid.includes', [])
445 pyramid_includes = settings.setdefault('pyramid.includes', [])
437 log.debug(
446 log.debug(
438 "Using the following pyramid.includes: %s",
447 "Using the following pyramid.includes: %s",
439 pyramid_includes)
448 pyramid_includes)
440
449
441 # TODO: johbo: Re-think this, usually the call to config.include
450 # TODO: johbo: Re-think this, usually the call to config.include
442 # should allow to pass in a prefix.
451 # should allow to pass in a prefix.
443 settings.setdefault('rhodecode.api.url', '/_admin/api')
452 settings.setdefault('rhodecode.api.url', '/_admin/api')
444 settings.setdefault('__file__', global_config.get('__file__'))
453 settings.setdefault('__file__', global_config.get('__file__'))
445
454
446 # Sanitize generic settings.
455 # Sanitize generic settings.
447 _list_setting(settings, 'default_encoding', 'UTF-8')
456 _list_setting(settings, 'default_encoding', 'UTF-8')
448 _bool_setting(settings, 'is_test', 'false')
457 _bool_setting(settings, 'is_test', 'false')
449 _bool_setting(settings, 'gzip_responses', 'false')
458 _bool_setting(settings, 'gzip_responses', 'false')
450
459
451 # Call split out functions that sanitize settings for each topic.
460 # Call split out functions that sanitize settings for each topic.
452 _sanitize_appenlight_settings(settings)
461 _sanitize_appenlight_settings(settings)
453 _sanitize_vcs_settings(settings)
462 _sanitize_vcs_settings(settings)
454 _sanitize_cache_settings(settings)
463 _sanitize_cache_settings(settings)
455
464
456 # configure instance id
465 # configure instance id
457 config_utils.set_instance_id(settings)
466 config_utils.set_instance_id(settings)
458
467
459 return settings
468 return settings
460
469
461
470
462 def enable_debug():
471 def enable_debug():
463 """
472 """
464 Helper to enable debug on running instance
473 Helper to enable debug on running instance
465 :return:
474 :return:
466 """
475 """
467 import tempfile
476 import tempfile
468 import textwrap
477 import textwrap
469 import logging.config
478 import logging.config
470
479
471 ini_template = textwrap.dedent("""
480 ini_template = textwrap.dedent("""
472 #####################################
481 #####################################
473 ### DEBUG LOGGING CONFIGURATION ####
482 ### DEBUG LOGGING CONFIGURATION ####
474 #####################################
483 #####################################
475 [loggers]
484 [loggers]
476 keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
485 keys = root, sqlalchemy, beaker, celery, rhodecode, ssh_wrapper
477
486
478 [handlers]
487 [handlers]
479 keys = console, console_sql
488 keys = console, console_sql
480
489
481 [formatters]
490 [formatters]
482 keys = generic, color_formatter, color_formatter_sql
491 keys = generic, color_formatter, color_formatter_sql
483
492
484 #############
493 #############
485 ## LOGGERS ##
494 ## LOGGERS ##
486 #############
495 #############
487 [logger_root]
496 [logger_root]
488 level = NOTSET
497 level = NOTSET
489 handlers = console
498 handlers = console
490
499
491 [logger_sqlalchemy]
500 [logger_sqlalchemy]
492 level = INFO
501 level = INFO
493 handlers = console_sql
502 handlers = console_sql
494 qualname = sqlalchemy.engine
503 qualname = sqlalchemy.engine
495 propagate = 0
504 propagate = 0
496
505
497 [logger_beaker]
506 [logger_beaker]
498 level = DEBUG
507 level = DEBUG
499 handlers =
508 handlers =
500 qualname = beaker.container
509 qualname = beaker.container
501 propagate = 1
510 propagate = 1
502
511
503 [logger_rhodecode]
512 [logger_rhodecode]
504 level = DEBUG
513 level = DEBUG
505 handlers =
514 handlers =
506 qualname = rhodecode
515 qualname = rhodecode
507 propagate = 1
516 propagate = 1
508
517
509 [logger_ssh_wrapper]
518 [logger_ssh_wrapper]
510 level = DEBUG
519 level = DEBUG
511 handlers =
520 handlers =
512 qualname = ssh_wrapper
521 qualname = ssh_wrapper
513 propagate = 1
522 propagate = 1
514
523
515 [logger_celery]
524 [logger_celery]
516 level = DEBUG
525 level = DEBUG
517 handlers =
526 handlers =
518 qualname = celery
527 qualname = celery
519
528
520
529
521 ##############
530 ##############
522 ## HANDLERS ##
531 ## HANDLERS ##
523 ##############
532 ##############
524
533
525 [handler_console]
534 [handler_console]
526 class = StreamHandler
535 class = StreamHandler
527 args = (sys.stderr, )
536 args = (sys.stderr, )
528 level = DEBUG
537 level = DEBUG
529 formatter = color_formatter
538 formatter = color_formatter
530
539
531 [handler_console_sql]
540 [handler_console_sql]
532 # "level = DEBUG" logs SQL queries and results.
541 # "level = DEBUG" logs SQL queries and results.
533 # "level = INFO" logs SQL queries.
542 # "level = INFO" logs SQL queries.
534 # "level = WARN" logs neither. (Recommended for production systems.)
543 # "level = WARN" logs neither. (Recommended for production systems.)
535 class = StreamHandler
544 class = StreamHandler
536 args = (sys.stderr, )
545 args = (sys.stderr, )
537 level = WARN
546 level = WARN
538 formatter = color_formatter_sql
547 formatter = color_formatter_sql
539
548
540 ################
549 ################
541 ## FORMATTERS ##
550 ## FORMATTERS ##
542 ################
551 ################
543
552
544 [formatter_generic]
553 [formatter_generic]
545 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
554 class = rhodecode.lib.logging_formatter.ExceptionAwareFormatter
546 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
555 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
547 datefmt = %Y-%m-%d %H:%M:%S
556 datefmt = %Y-%m-%d %H:%M:%S
548
557
549 [formatter_color_formatter]
558 [formatter_color_formatter]
550 class = rhodecode.lib.logging_formatter.ColorRequestTrackingFormatter
559 class = rhodecode.lib.logging_formatter.ColorRequestTrackingFormatter
551 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
560 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s | %(req_id)s
552 datefmt = %Y-%m-%d %H:%M:%S
561 datefmt = %Y-%m-%d %H:%M:%S
553
562
554 [formatter_color_formatter_sql]
563 [formatter_color_formatter_sql]
555 class = rhodecode.lib.logging_formatter.ColorFormatterSql
564 class = rhodecode.lib.logging_formatter.ColorFormatterSql
556 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
565 format = %(asctime)s.%(msecs)03d [%(process)d] %(levelname)-5.5s [%(name)s] %(message)s
557 datefmt = %Y-%m-%d %H:%M:%S
566 datefmt = %Y-%m-%d %H:%M:%S
558 """)
567 """)
559
568
560 with tempfile.NamedTemporaryFile(prefix='rc_debug_logging_', suffix='.ini',
569 with tempfile.NamedTemporaryFile(prefix='rc_debug_logging_', suffix='.ini',
561 delete=False) as f:
570 delete=False) as f:
562 log.info('Saved Temporary DEBUG config at %s', f.name)
571 log.info('Saved Temporary DEBUG config at %s', f.name)
563 f.write(ini_template)
572 f.write(ini_template)
564
573
565 logging.config.fileConfig(f.name)
574 logging.config.fileConfig(f.name)
566 log.debug('DEBUG MODE ON')
575 log.debug('DEBUG MODE ON')
567 os.remove(f.name)
576 os.remove(f.name)
568
577
569
578
570 def _sanitize_appenlight_settings(settings):
579 def _sanitize_appenlight_settings(settings):
571 _bool_setting(settings, 'appenlight', 'false')
580 _bool_setting(settings, 'appenlight', 'false')
572
581
573
582
574 def _sanitize_vcs_settings(settings):
583 def _sanitize_vcs_settings(settings):
575 """
584 """
576 Applies settings defaults and does type conversion for all VCS related
585 Applies settings defaults and does type conversion for all VCS related
577 settings.
586 settings.
578 """
587 """
579 _string_setting(settings, 'vcs.svn.compatible_version', '')
588 _string_setting(settings, 'vcs.svn.compatible_version', '')
580 _string_setting(settings, 'vcs.hooks.protocol', 'http')
589 _string_setting(settings, 'vcs.hooks.protocol', 'http')
581 _string_setting(settings, 'vcs.hooks.host', '127.0.0.1')
590 _string_setting(settings, 'vcs.hooks.host', '127.0.0.1')
582 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
591 _string_setting(settings, 'vcs.scm_app_implementation', 'http')
583 _string_setting(settings, 'vcs.server', '')
592 _string_setting(settings, 'vcs.server', '')
584 _string_setting(settings, 'vcs.server.protocol', 'http')
593 _string_setting(settings, 'vcs.server.protocol', 'http')
585 _bool_setting(settings, 'startup.import_repos', 'false')
594 _bool_setting(settings, 'startup.import_repos', 'false')
586 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
595 _bool_setting(settings, 'vcs.hooks.direct_calls', 'false')
587 _bool_setting(settings, 'vcs.server.enable', 'true')
596 _bool_setting(settings, 'vcs.server.enable', 'true')
588 _bool_setting(settings, 'vcs.start_server', 'false')
597 _bool_setting(settings, 'vcs.start_server', 'false')
589 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
598 _list_setting(settings, 'vcs.backends', 'hg, git, svn')
590 _int_setting(settings, 'vcs.connection_timeout', 3600)
599 _int_setting(settings, 'vcs.connection_timeout', 3600)
591
600
592 # Support legacy values of vcs.scm_app_implementation. Legacy
601 # Support legacy values of vcs.scm_app_implementation. Legacy
593 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
602 # configurations may use 'rhodecode.lib.middleware.utils.scm_app_http', or
594 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
603 # disabled since 4.13 'vcsserver.scm_app' which is now mapped to 'http'.
595 scm_app_impl = settings['vcs.scm_app_implementation']
604 scm_app_impl = settings['vcs.scm_app_implementation']
596 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
605 if scm_app_impl in ['rhodecode.lib.middleware.utils.scm_app_http', 'vcsserver.scm_app']:
597 settings['vcs.scm_app_implementation'] = 'http'
606 settings['vcs.scm_app_implementation'] = 'http'
598
607
599
608
600 def _sanitize_cache_settings(settings):
609 def _sanitize_cache_settings(settings):
601 temp_store = tempfile.gettempdir()
610 temp_store = tempfile.gettempdir()
602 default_cache_dir = os.path.join(temp_store, 'rc_cache')
611 default_cache_dir = os.path.join(temp_store, 'rc_cache')
603
612
604 # save default, cache dir, and use it for all backends later.
613 # save default, cache dir, and use it for all backends later.
605 default_cache_dir = _string_setting(
614 default_cache_dir = _string_setting(
606 settings,
615 settings,
607 'cache_dir',
616 'cache_dir',
608 default_cache_dir, lower=False, default_when_empty=True)
617 default_cache_dir, lower=False, default_when_empty=True)
609
618
610 # ensure we have our dir created
619 # ensure we have our dir created
611 if not os.path.isdir(default_cache_dir):
620 if not os.path.isdir(default_cache_dir):
612 os.makedirs(default_cache_dir, mode=0o755)
621 os.makedirs(default_cache_dir, mode=0o755)
613
622
614 # exception store cache
623 # exception store cache
615 _string_setting(
624 _string_setting(
616 settings,
625 settings,
617 'exception_tracker.store_path',
626 'exception_tracker.store_path',
618 temp_store, lower=False, default_when_empty=True)
627 temp_store, lower=False, default_when_empty=True)
619 _bool_setting(
628 _bool_setting(
620 settings,
629 settings,
621 'exception_tracker.send_email',
630 'exception_tracker.send_email',
622 'false')
631 'false')
623 _string_setting(
632 _string_setting(
624 settings,
633 settings,
625 'exception_tracker.email_prefix',
634 'exception_tracker.email_prefix',
626 '[RHODECODE ERROR]', lower=False, default_when_empty=True)
635 '[RHODECODE ERROR]', lower=False, default_when_empty=True)
627
636
628 # cache_perms
637 # cache_perms
629 _string_setting(
638 _string_setting(
630 settings,
639 settings,
631 'rc_cache.cache_perms.backend',
640 'rc_cache.cache_perms.backend',
632 'dogpile.cache.rc.file_namespace', lower=False)
641 'dogpile.cache.rc.file_namespace', lower=False)
633 _int_setting(
642 _int_setting(
634 settings,
643 settings,
635 'rc_cache.cache_perms.expiration_time',
644 'rc_cache.cache_perms.expiration_time',
636 60)
645 60)
637 _string_setting(
646 _string_setting(
638 settings,
647 settings,
639 'rc_cache.cache_perms.arguments.filename',
648 'rc_cache.cache_perms.arguments.filename',
640 os.path.join(default_cache_dir, 'rc_cache_1'), lower=False)
649 os.path.join(default_cache_dir, 'rc_cache_1'), lower=False)
641
650
642 # cache_repo
651 # cache_repo
643 _string_setting(
652 _string_setting(
644 settings,
653 settings,
645 'rc_cache.cache_repo.backend',
654 'rc_cache.cache_repo.backend',
646 'dogpile.cache.rc.file_namespace', lower=False)
655 'dogpile.cache.rc.file_namespace', lower=False)
647 _int_setting(
656 _int_setting(
648 settings,
657 settings,
649 'rc_cache.cache_repo.expiration_time',
658 'rc_cache.cache_repo.expiration_time',
650 60)
659 60)
651 _string_setting(
660 _string_setting(
652 settings,
661 settings,
653 'rc_cache.cache_repo.arguments.filename',
662 'rc_cache.cache_repo.arguments.filename',
654 os.path.join(default_cache_dir, 'rc_cache_2'), lower=False)
663 os.path.join(default_cache_dir, 'rc_cache_2'), lower=False)
655
664
656 # cache_license
665 # cache_license
657 _string_setting(
666 _string_setting(
658 settings,
667 settings,
659 'rc_cache.cache_license.backend',
668 'rc_cache.cache_license.backend',
660 'dogpile.cache.rc.file_namespace', lower=False)
669 'dogpile.cache.rc.file_namespace', lower=False)
661 _int_setting(
670 _int_setting(
662 settings,
671 settings,
663 'rc_cache.cache_license.expiration_time',
672 'rc_cache.cache_license.expiration_time',
664 5*60)
673 5*60)
665 _string_setting(
674 _string_setting(
666 settings,
675 settings,
667 'rc_cache.cache_license.arguments.filename',
676 'rc_cache.cache_license.arguments.filename',
668 os.path.join(default_cache_dir, 'rc_cache_3'), lower=False)
677 os.path.join(default_cache_dir, 'rc_cache_3'), lower=False)
669
678
670 # cache_repo_longterm memory, 96H
679 # cache_repo_longterm memory, 96H
671 _string_setting(
680 _string_setting(
672 settings,
681 settings,
673 'rc_cache.cache_repo_longterm.backend',
682 'rc_cache.cache_repo_longterm.backend',
674 'dogpile.cache.rc.memory_lru', lower=False)
683 'dogpile.cache.rc.memory_lru', lower=False)
675 _int_setting(
684 _int_setting(
676 settings,
685 settings,
677 'rc_cache.cache_repo_longterm.expiration_time',
686 'rc_cache.cache_repo_longterm.expiration_time',
678 345600)
687 345600)
679 _int_setting(
688 _int_setting(
680 settings,
689 settings,
681 'rc_cache.cache_repo_longterm.max_size',
690 'rc_cache.cache_repo_longterm.max_size',
682 10000)
691 10000)
683
692
684 # sql_cache_short
693 # sql_cache_short
685 _string_setting(
694 _string_setting(
686 settings,
695 settings,
687 'rc_cache.sql_cache_short.backend',
696 'rc_cache.sql_cache_short.backend',
688 'dogpile.cache.rc.memory_lru', lower=False)
697 'dogpile.cache.rc.memory_lru', lower=False)
689 _int_setting(
698 _int_setting(
690 settings,
699 settings,
691 'rc_cache.sql_cache_short.expiration_time',
700 'rc_cache.sql_cache_short.expiration_time',
692 30)
701 30)
693 _int_setting(
702 _int_setting(
694 settings,
703 settings,
695 'rc_cache.sql_cache_short.max_size',
704 'rc_cache.sql_cache_short.max_size',
696 10000)
705 10000)
697
706
698
707
699 def _int_setting(settings, name, default):
708 def _int_setting(settings, name, default):
700 settings[name] = int(settings.get(name, default))
709 settings[name] = int(settings.get(name, default))
701 return settings[name]
710 return settings[name]
702
711
703
712
704 def _bool_setting(settings, name, default):
713 def _bool_setting(settings, name, default):
705 input_val = settings.get(name, default)
714 input_val = settings.get(name, default)
706 if isinstance(input_val, unicode):
715 if isinstance(input_val, unicode):
707 input_val = input_val.encode('utf8')
716 input_val = input_val.encode('utf8')
708 settings[name] = asbool(input_val)
717 settings[name] = asbool(input_val)
709 return settings[name]
718 return settings[name]
710
719
711
720
712 def _list_setting(settings, name, default):
721 def _list_setting(settings, name, default):
713 raw_value = settings.get(name, default)
722 raw_value = settings.get(name, default)
714
723
715 old_separator = ','
724 old_separator = ','
716 if old_separator in raw_value:
725 if old_separator in raw_value:
717 # If we get a comma separated list, pass it to our own function.
726 # If we get a comma separated list, pass it to our own function.
718 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
727 settings[name] = rhodecode_aslist(raw_value, sep=old_separator)
719 else:
728 else:
720 # Otherwise we assume it uses pyramids space/newline separation.
729 # Otherwise we assume it uses pyramids space/newline separation.
721 settings[name] = aslist(raw_value)
730 settings[name] = aslist(raw_value)
722 return settings[name]
731 return settings[name]
723
732
724
733
725 def _string_setting(settings, name, default, lower=True, default_when_empty=False):
734 def _string_setting(settings, name, default, lower=True, default_when_empty=False):
726 value = settings.get(name, default)
735 value = settings.get(name, default)
727
736
728 if default_when_empty and not value:
737 if default_when_empty and not value:
729 # use default value when value is empty
738 # use default value when value is empty
730 value = default
739 value = default
731
740
732 if lower:
741 if lower:
733 value = value.lower()
742 value = value.lower()
734 settings[name] = value
743 settings[name] = value
735 return settings[name]
744 return settings[name]
736
745
737
746
738 def _substitute_values(mapping, substitutions):
747 def _substitute_values(mapping, substitutions):
739 result = {}
748 result = {}
740
749
741 try:
750 try:
742 for key, value in mapping.items():
751 for key, value in mapping.items():
743 # initialize without substitution first
752 # initialize without substitution first
744 result[key] = value
753 result[key] = value
745
754
746 # Note: Cannot use regular replacements, since they would clash
755 # Note: Cannot use regular replacements, since they would clash
747 # with the implementation of ConfigParser. Using "format" instead.
756 # with the implementation of ConfigParser. Using "format" instead.
748 try:
757 try:
749 result[key] = value.format(**substitutions)
758 result[key] = value.format(**substitutions)
750 except KeyError as e:
759 except KeyError as e:
751 env_var = '{}'.format(e.args[0])
760 env_var = '{}'.format(e.args[0])
752
761
753 msg = 'Failed to substitute: `{key}={{{var}}}` with environment entry. ' \
762 msg = 'Failed to substitute: `{key}={{{var}}}` with environment entry. ' \
754 'Make sure your environment has {var} set, or remove this ' \
763 'Make sure your environment has {var} set, or remove this ' \
755 'variable from config file'.format(key=key, var=env_var)
764 'variable from config file'.format(key=key, var=env_var)
756
765
757 if env_var.startswith('ENV_'):
766 if env_var.startswith('ENV_'):
758 raise ValueError(msg)
767 raise ValueError(msg)
759 else:
768 else:
760 log.warning(msg)
769 log.warning(msg)
761
770
762 except ValueError as e:
771 except ValueError as e:
763 log.warning('Failed to substitute ENV variable: %s', e)
772 log.warning('Failed to substitute ENV variable: %s', e)
764 result = mapping
773 result = mapping
765
774
766 return result
775 return result
General Comments 0
You need to be logged in to leave comments. Login now