##// END OF EJS Templates
authn: Fix priority of default values if some values are missing during POST...
johbo -
r237:840f51fa default
parent child Browse files
Show More
@@ -1,188 +1,191 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2012-2016 RhodeCode GmbH
3 # Copyright (C) 2012-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 import colander
21 import colander
22 import formencode.htmlfill
22 import formencode.htmlfill
23 import logging
23 import logging
24
24
25 from pyramid.httpexceptions import HTTPFound
25 from pyramid.httpexceptions import HTTPFound
26 from pyramid.renderers import render
26 from pyramid.renderers import render
27 from pyramid.response import Response
27 from pyramid.response import Response
28
28
29 from rhodecode.authentication.base import get_auth_cache_manager
29 from rhodecode.authentication.base import get_auth_cache_manager
30 from rhodecode.authentication.interface import IAuthnPluginRegistry
30 from rhodecode.authentication.interface import IAuthnPluginRegistry
31 from rhodecode.lib import auth
31 from rhodecode.lib import auth
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
32 from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator
33 from rhodecode.model.forms import AuthSettingsForm
33 from rhodecode.model.forms import AuthSettingsForm
34 from rhodecode.model.meta import Session
34 from rhodecode.model.meta import Session
35 from rhodecode.model.settings import SettingsModel
35 from rhodecode.model.settings import SettingsModel
36 from rhodecode.translation import _
36 from rhodecode.translation import _
37
37
38 log = logging.getLogger(__name__)
38 log = logging.getLogger(__name__)
39
39
40
40
41 class AuthnPluginViewBase(object):
41 class AuthnPluginViewBase(object):
42
42
43 def __init__(self, context, request):
43 def __init__(self, context, request):
44 self.request = request
44 self.request = request
45 self.context = context
45 self.context = context
46 self.plugin = context.plugin
46 self.plugin = context.plugin
47 self._rhodecode_user = request.user
47 self._rhodecode_user = request.user
48
48
49 @LoginRequired()
49 @LoginRequired()
50 @HasPermissionAllDecorator('hg.admin')
50 @HasPermissionAllDecorator('hg.admin')
51 def settings_get(self, defaults=None, errors=None):
51 def settings_get(self, defaults=None, errors=None):
52 """
52 """
53 View that displays the plugin settings as a form.
53 View that displays the plugin settings as a form.
54 """
54 """
55 defaults = defaults or {}
55 defaults = defaults or {}
56 errors = errors or {}
56 errors = errors or {}
57 schema = self.plugin.get_settings_schema()
57 schema = self.plugin.get_settings_schema()
58
58
59 # Get default values for the form.
59 # Compute default values for the form. Priority is:
60 # 1. Passed to this method 2. DB value 3. Schema default
60 for node in schema:
61 for node in schema:
61 db_value = self.plugin.get_setting_by_name(node.name)
62 db_value = self.plugin.get_setting_by_name(
63 node.name, colander.null)
62 defaults.setdefault(node.name, db_value)
64 defaults.setdefault(node.name, db_value)
65 defaults = schema.serialize(defaults)
63
66
64 template_context = {
67 template_context = {
65 'defaults': defaults,
68 'defaults': defaults,
66 'errors': errors,
69 'errors': errors,
67 'plugin': self.context.plugin,
70 'plugin': self.context.plugin,
68 'resource': self.context,
71 'resource': self.context,
69 }
72 }
70
73
71 return template_context
74 return template_context
72
75
73 @LoginRequired()
76 @LoginRequired()
74 @HasPermissionAllDecorator('hg.admin')
77 @HasPermissionAllDecorator('hg.admin')
75 @auth.CSRFRequired()
78 @auth.CSRFRequired()
76 def settings_post(self):
79 def settings_post(self):
77 """
80 """
78 View that validates and stores the plugin settings.
81 View that validates and stores the plugin settings.
79 """
82 """
80 schema = self.plugin.get_settings_schema()
83 schema = self.plugin.get_settings_schema()
81 try:
84 try:
82 valid_data = schema.deserialize(self.request.params)
85 valid_data = schema.deserialize(self.request.params)
83 except colander.Invalid, e:
86 except colander.Invalid, e:
84 # Display error message and display form again.
87 # Display error message and display form again.
85 self.request.session.flash(
88 self.request.session.flash(
86 _('Errors exist when saving plugin settings. '
89 _('Errors exist when saving plugin settings. '
87 'Please check the form inputs.'),
90 'Please check the form inputs.'),
88 queue='error')
91 queue='error')
89 defaults = schema.flatten(self.request.params)
92 defaults = schema.flatten(self.request.params)
90 return self.settings_get(errors=e.asdict(), defaults=defaults)
93 return self.settings_get(errors=e.asdict(), defaults=defaults)
91
94
92 # Store validated data.
95 # Store validated data.
93 for name, value in valid_data.items():
96 for name, value in valid_data.items():
94 self.plugin.create_or_update_setting(name, value)
97 self.plugin.create_or_update_setting(name, value)
95 Session.commit()
98 Session.commit()
96
99
97 # Display success message and redirect.
100 # Display success message and redirect.
98 self.request.session.flash(
101 self.request.session.flash(
99 _('Auth settings updated successfully.'),
102 _('Auth settings updated successfully.'),
100 queue='success')
103 queue='success')
101 redirect_to = self.request.resource_path(
104 redirect_to = self.request.resource_path(
102 self.context, route_name='auth_home')
105 self.context, route_name='auth_home')
103 return HTTPFound(redirect_to)
106 return HTTPFound(redirect_to)
104
107
105
108
106 # TODO: Ongoing migration in these views.
109 # TODO: Ongoing migration in these views.
107 # - Maybe we should also use a colander schema for these views.
110 # - Maybe we should also use a colander schema for these views.
108 class AuthSettingsView(object):
111 class AuthSettingsView(object):
109 def __init__(self, context, request):
112 def __init__(self, context, request):
110 self.context = context
113 self.context = context
111 self.request = request
114 self.request = request
112
115
113 # TODO: Move this into a utility function. It is needed in all view
116 # TODO: Move this into a utility function. It is needed in all view
114 # classes during migration. Maybe a mixin?
117 # classes during migration. Maybe a mixin?
115
118
116 # Some of the decorators rely on this attribute to be present on the
119 # Some of the decorators rely on this attribute to be present on the
117 # class of the decorated method.
120 # class of the decorated method.
118 self._rhodecode_user = request.user
121 self._rhodecode_user = request.user
119
122
120 @LoginRequired()
123 @LoginRequired()
121 @HasPermissionAllDecorator('hg.admin')
124 @HasPermissionAllDecorator('hg.admin')
122 def index(self, defaults=None, errors=None, prefix_error=False):
125 def index(self, defaults=None, errors=None, prefix_error=False):
123 defaults = defaults or {}
126 defaults = defaults or {}
124 authn_registry = self.request.registry.getUtility(IAuthnPluginRegistry)
127 authn_registry = self.request.registry.getUtility(IAuthnPluginRegistry)
125 enabled_plugins = SettingsModel().get_auth_plugins()
128 enabled_plugins = SettingsModel().get_auth_plugins()
126
129
127 # Create template context and render it.
130 # Create template context and render it.
128 template_context = {
131 template_context = {
129 'resource': self.context,
132 'resource': self.context,
130 'available_plugins': authn_registry.get_plugins(),
133 'available_plugins': authn_registry.get_plugins(),
131 'enabled_plugins': enabled_plugins,
134 'enabled_plugins': enabled_plugins,
132 }
135 }
133 html = render('rhodecode:templates/admin/auth/auth_settings.html',
136 html = render('rhodecode:templates/admin/auth/auth_settings.html',
134 template_context,
137 template_context,
135 request=self.request)
138 request=self.request)
136
139
137 # Create form default values and fill the form.
140 # Create form default values and fill the form.
138 form_defaults = {
141 form_defaults = {
139 'auth_plugins': ','.join(enabled_plugins)
142 'auth_plugins': ','.join(enabled_plugins)
140 }
143 }
141 form_defaults.update(defaults)
144 form_defaults.update(defaults)
142 html = formencode.htmlfill.render(
145 html = formencode.htmlfill.render(
143 html,
146 html,
144 defaults=form_defaults,
147 defaults=form_defaults,
145 errors=errors,
148 errors=errors,
146 prefix_error=prefix_error,
149 prefix_error=prefix_error,
147 encoding="UTF-8",
150 encoding="UTF-8",
148 force_defaults=False)
151 force_defaults=False)
149
152
150 return Response(html)
153 return Response(html)
151
154
152 @LoginRequired()
155 @LoginRequired()
153 @HasPermissionAllDecorator('hg.admin')
156 @HasPermissionAllDecorator('hg.admin')
154 @auth.CSRFRequired()
157 @auth.CSRFRequired()
155 def auth_settings(self):
158 def auth_settings(self):
156 try:
159 try:
157 form = AuthSettingsForm()()
160 form = AuthSettingsForm()()
158 form_result = form.to_python(self.request.params)
161 form_result = form.to_python(self.request.params)
159 plugins = ','.join(form_result['auth_plugins'])
162 plugins = ','.join(form_result['auth_plugins'])
160 setting = SettingsModel().create_or_update_setting(
163 setting = SettingsModel().create_or_update_setting(
161 'auth_plugins', plugins)
164 'auth_plugins', plugins)
162 Session().add(setting)
165 Session().add(setting)
163 Session().commit()
166 Session().commit()
164
167
165 cache_manager = get_auth_cache_manager()
168 cache_manager = get_auth_cache_manager()
166 cache_manager.clear()
169 cache_manager.clear()
167 self.request.session.flash(
170 self.request.session.flash(
168 _('Auth settings updated successfully.'),
171 _('Auth settings updated successfully.'),
169 queue='success')
172 queue='success')
170 except formencode.Invalid as errors:
173 except formencode.Invalid as errors:
171 e = errors.error_dict or {}
174 e = errors.error_dict or {}
172 self.request.session.flash(
175 self.request.session.flash(
173 _('Errors exist when saving plugin setting. '
176 _('Errors exist when saving plugin setting. '
174 'Please check the form inputs.'),
177 'Please check the form inputs.'),
175 queue='error')
178 queue='error')
176 return self.index(
179 return self.index(
177 defaults=errors.value,
180 defaults=errors.value,
178 errors=e,
181 errors=e,
179 prefix_error=False)
182 prefix_error=False)
180 except Exception:
183 except Exception:
181 log.exception('Exception in auth_settings')
184 log.exception('Exception in auth_settings')
182 self.request.session.flash(
185 self.request.session.flash(
183 _('Error occurred during update of auth settings.'),
186 _('Error occurred during update of auth settings.'),
184 queue='error')
187 queue='error')
185
188
186 redirect_to = self.request.resource_path(
189 redirect_to = self.request.resource_path(
187 self.context, route_name='auth_home')
190 self.context, route_name='auth_home')
188 return HTTPFound(redirect_to)
191 return HTTPFound(redirect_to)
General Comments 0
You need to be logged in to leave comments. Login now