##// END OF EJS Templates
auth-plugins: use a nicer visual display of auth plugins that would highlight that order is...
marcink -
r2659:8b68aff1 default
parent child Browse files
Show More
@@ -1,191 +1,191 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2012-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import colander
22 22 import formencode.htmlfill
23 23 import logging
24 24
25 25 from pyramid.httpexceptions import HTTPFound
26 26 from pyramid.renderers import render
27 27 from pyramid.response import Response
28 28
29 29 from rhodecode.apps._base import BaseAppView
30 30 from rhodecode.authentication.base import (
31 31 get_auth_cache_manager, get_perms_cache_manager, get_authn_registry)
32 32 from rhodecode.lib import helpers as h
33 33 from rhodecode.lib.auth import (
34 34 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
35 35 from rhodecode.lib.caches import clear_cache_manager
36 36 from rhodecode.model.forms import AuthSettingsForm
37 37 from rhodecode.model.meta import Session
38 38 from rhodecode.model.settings import SettingsModel
39 39
40 40 log = logging.getLogger(__name__)
41 41
42 42
43 43 class AuthnPluginViewBase(BaseAppView):
44 44
45 45 def load_default_context(self):
46 46 c = self._get_local_tmpl_context()
47 47 self.plugin = self.context.plugin
48 48 return c
49 49
50 50 @LoginRequired()
51 51 @HasPermissionAllDecorator('hg.admin')
52 52 def settings_get(self, defaults=None, errors=None):
53 53 """
54 54 View that displays the plugin settings as a form.
55 55 """
56 56 c = self.load_default_context()
57 57 defaults = defaults or {}
58 58 errors = errors or {}
59 59 schema = self.plugin.get_settings_schema()
60 60
61 61 # Compute default values for the form. Priority is:
62 62 # 1. Passed to this method 2. DB value 3. Schema default
63 63 for node in schema:
64 64 if node.name not in defaults:
65 65 defaults[node.name] = self.plugin.get_setting_by_name(
66 66 node.name, node.default, cache=False)
67 67
68 68 template_context = {
69 69 'defaults': defaults,
70 70 'errors': errors,
71 71 'plugin': self.context.plugin,
72 72 'resource': self.context,
73 73 }
74 74
75 75 return self._get_template_context(c, **template_context)
76 76
77 77 @LoginRequired()
78 78 @HasPermissionAllDecorator('hg.admin')
79 79 @CSRFRequired()
80 80 def settings_post(self):
81 81 """
82 82 View that validates and stores the plugin settings.
83 83 """
84 84 _ = self.request.translate
85 85 self.load_default_context()
86 86 schema = self.plugin.get_settings_schema()
87 87 data = self.request.params
88 88
89 89 try:
90 90 valid_data = schema.deserialize(data)
91 91 except colander.Invalid as e:
92 92 # Display error message and display form again.
93 93 h.flash(
94 94 _('Errors exist when saving plugin settings. '
95 95 'Please check the form inputs.'),
96 96 category='error')
97 97 defaults = {key: data[key] for key in data if key in schema}
98 98 return self.settings_get(errors=e.asdict(), defaults=defaults)
99 99
100 100 # Store validated data.
101 101 for name, value in valid_data.items():
102 102 self.plugin.create_or_update_setting(name, value)
103 103 Session().commit()
104 104
105 105 # cleanup cache managers in case of change for plugin
106 106 # TODO(marcink): because we can register multiple namespaces
107 107 # we should at some point figure out how to retrieve ALL namespace
108 108 # cache managers and clear them...
109 109 cache_manager = get_auth_cache_manager()
110 110 clear_cache_manager(cache_manager)
111 111
112 112 cache_manager = get_perms_cache_manager()
113 113 clear_cache_manager(cache_manager)
114 114
115 115 # Display success message and redirect.
116 116 h.flash(_('Auth settings updated successfully.'), category='success')
117 117 redirect_to = self.request.resource_path(
118 118 self.context, route_name='auth_home')
119 119 return HTTPFound(redirect_to)
120 120
121 121
122 122 class AuthSettingsView(BaseAppView):
123 123 def load_default_context(self):
124 124 c = self._get_local_tmpl_context()
125 125 return c
126 126
127 127 @LoginRequired()
128 128 @HasPermissionAllDecorator('hg.admin')
129 129 def index(self, defaults=None, errors=None, prefix_error=False):
130 130 c = self.load_default_context()
131 131
132 132 defaults = defaults or {}
133 133 authn_registry = get_authn_registry(self.request.registry)
134 134 enabled_plugins = SettingsModel().get_auth_plugins()
135 135
136 136 # Create template context and render it.
137 137 template_context = {
138 138 'resource': self.context,
139 139 'available_plugins': authn_registry.get_plugins(),
140 140 'enabled_plugins': enabled_plugins,
141 141 }
142 142 html = render('rhodecode:templates/admin/auth/auth_settings.mako',
143 143 self._get_template_context(c, **template_context),
144 144 self.request)
145 145
146 146 # Create form default values and fill the form.
147 147 form_defaults = {
148 'auth_plugins': ','.join(enabled_plugins)
148 'auth_plugins': ',\n'.join(enabled_plugins)
149 149 }
150 150 form_defaults.update(defaults)
151 151 html = formencode.htmlfill.render(
152 152 html,
153 153 defaults=form_defaults,
154 154 errors=errors,
155 155 prefix_error=prefix_error,
156 156 encoding="UTF-8",
157 157 force_defaults=False)
158 158
159 159 return Response(html)
160 160
161 161 @LoginRequired()
162 162 @HasPermissionAllDecorator('hg.admin')
163 163 @CSRFRequired()
164 164 def auth_settings(self):
165 165 _ = self.request.translate
166 166 try:
167 167 form = AuthSettingsForm(self.request.translate)()
168 168 form_result = form.to_python(self.request.POST)
169 169 plugins = ','.join(form_result['auth_plugins'])
170 170 setting = SettingsModel().create_or_update_setting(
171 171 'auth_plugins', plugins)
172 172 Session().add(setting)
173 173 Session().commit()
174 174
175 175 h.flash(_('Auth settings updated successfully.'), category='success')
176 176 except formencode.Invalid as errors:
177 177 e = errors.error_dict or {}
178 178 h.flash(_('Errors exist when saving plugin setting. '
179 179 'Please check the form inputs.'), category='error')
180 180 return self.index(
181 181 defaults=errors.value,
182 182 errors=e,
183 183 prefix_error=False)
184 184 except Exception:
185 185 log.exception('Exception in auth_settings')
186 186 h.flash(_('Error occurred during update of auth settings.'),
187 187 category='error')
188 188
189 189 redirect_to = self.request.resource_path(
190 190 self.context, route_name='auth_home')
191 191 return HTTPFound(redirect_to)
@@ -1,116 +1,118 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/base/base.mako"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Authentication Settings')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}}
8 8 %endif
9 9 </%def>
10 10
11 11 <%def name="breadcrumbs_links()">
12 12 ${h.link_to(_('Admin'),h.route_path('admin_home'))}
13 13 &raquo;
14 14 ${_('Authentication Plugins')}
15 15 </%def>
16 16
17 17 <%def name="menu_bar_nav()">
18 18 ${self.menu_items(active='admin')}
19 19 </%def>
20 20
21 21 <%def name="main()">
22 22
23 23 <div class="box">
24 24 <div class="title">
25 25 ${self.breadcrumbs()}
26 26 </div>
27 27
28 28 <div class='sidebar-col-wrapper'>
29 29
30 30 <div class="sidebar">
31 31 <ul class="nav nav-pills nav-stacked">
32 32 % for item in resource.get_root().get_nav_list():
33 33 <li ${'class=active' if item == resource else ''}>
34 34 <a href="${request.resource_path(item, route_name='auth_home')}">${item.display_name}</a>
35 35 </li>
36 36 % endfor
37 37 </ul>
38 38 </div>
39 39
40 40 <div class="main-content-full-width">
41 41 ${h.secure_form(request.resource_path(resource, route_name='auth_home'), request=request)}
42 42 <div class="form">
43 43
44 44 <div class="panel panel-default">
45 45
46 46 <div class="panel-heading">
47 47 <h3 class="panel-title">${_("Enabled and Available Plugins")}</h3>
48 48 </div>
49 49
50 50 <div class="fields panel-body">
51 51
52 52 <div class="field">
53 53 <div class="label">${_("Enabled Plugins")}</div>
54 54 <div class="textarea text-area editor">
55 55 ${h.textarea('auth_plugins',cols=23,rows=5,class_="medium")}
56 56 </div>
57 <p class="help-block">
58 ${_('Add a list of plugins, separated by commas. '
59 'The order of the plugins is also the order in which '
60 'RhodeCode Enterprise will try to authenticate a user.')}
61 </p>
57 <p class="help-block pre-formatting">${_('List of plugins, separated by commas.'
58 '\nThe order of the plugins is also the order in which '
59 'RhodeCode Enterprise will try to authenticate a user.')}</p>
62 60 </div>
63 61
64 62 <div class="field">
65 63 <div class="label">${_('Available Built-in Plugins')}</div>
66 64 <ul class="auth_plugins">
67 65 %for plugin in available_plugins:
68 66 <li>
69 67 <div class="auth_buttons">
70 68 <span plugin_id="${plugin.get_id()}" class="toggle-plugin btn ${'btn-success' if plugin.get_id() in enabled_plugins else ''}">
71 69 ${_('enabled') if plugin.get_id() in enabled_plugins else _('disabled')}
72 70 </span>
73 71 ${plugin.get_display_name()} (${plugin.get_id()})
74 72 </div>
75 73 </li>
76 74 %endfor
77 75 </ul>
78 76 </div>
79 77
80 78 <div class="buttons">
81 79 ${h.submit('save',_('Save'),class_="btn")}
82 80 </div>
83 81 </div>
84 82 </div>
85 83 </div>
86 84 ${h.end_form()}
87 85 </div>
88 86 </div>
89 87 </div>
90 88
91 89 <script>
92 90 $('.toggle-plugin').click(function(e){
93 91 var auth_plugins_input = $('#auth_plugins');
94 var notEmpty = function(element, index, array) {
95 return (element != "");
96 };
97 var elems = auth_plugins_input.val().split(',').filter(notEmpty);
92 var elems = [];
93
94 $.each(auth_plugins_input.val().split(',') , function (index, element) {
95 if (element !== "") {
96 elems.push(element.strip())
97 }
98 });
99
98 100 var cur_button = e.currentTarget;
99 101 var plugin_id = $(cur_button).attr('plugin_id');
100 102 if($(cur_button).hasClass('btn-success')){
101 103 elems.splice(elems.indexOf(plugin_id), 1);
102 auth_plugins_input.val(elems.join(','));
104 auth_plugins_input.val(elems.join(',\n'));
103 105 $(cur_button).removeClass('btn-success');
104 106 cur_button.innerHTML = _gettext('disabled');
105 107 }
106 108 else{
107 109 if(elems.indexOf(plugin_id) == -1){
108 110 elems.push(plugin_id);
109 111 }
110 auth_plugins_input.val(elems.join(','));
112 auth_plugins_input.val(elems.join(',\n'));
111 113 $(cur_button).addClass('btn-success');
112 114 cur_button.innerHTML = _gettext('enabled');
113 115 }
114 116 });
115 117 </script>
116 118 </%def>
General Comments 0
You need to be logged in to leave comments. Login now