Show More
@@ -109,7 +109,17 b' class TestLoginController(object):' | |||
|
109 | 109 | |
|
110 | 110 | def test_login_regular_forbidden_when_super_admin_restriction(self): |
|
111 | 111 | from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin |
|
112 |
with fixture. |
|
|
112 | with fixture.auth_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN): | |
|
113 | response = self.app.post(route_path('login'), | |
|
114 | {'username': 'test_regular', | |
|
115 | 'password': 'test12'}) | |
|
116 | ||
|
117 | response.mustcontain('invalid user name') | |
|
118 | response.mustcontain('invalid password') | |
|
119 | ||
|
120 | def test_login_regular_forbidden_when_scope_restriction(self): | |
|
121 | from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin | |
|
122 | with fixture.scope_restriction(RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS): | |
|
113 | 123 | response = self.app.post(route_path('login'), |
|
114 | 124 | {'username': 'test_regular', |
|
115 | 125 | 'password': 'test12'}) |
@@ -26,13 +26,13 b' import logging' | |||
|
26 | 26 | |
|
27 | 27 | import colander |
|
28 | 28 | |
|
29 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase | |
|
30 | 29 | from rhodecode.translation import _ |
|
31 | ||
|
32 | from rhodecode.authentication.base import RhodeCodeAuthPluginBase, hybrid_property | |
|
33 | from rhodecode.authentication.routes import AuthnPluginResourceBase | |
|
34 | 30 | from rhodecode.lib.utils2 import safe_str |
|
35 | 31 | from rhodecode.model.db import User |
|
32 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase | |
|
33 | from rhodecode.authentication.base import ( | |
|
34 | RhodeCodeAuthPluginBase, hybrid_property, HTTP_TYPE, VCS_TYPE) | |
|
35 | from rhodecode.authentication.routes import AuthnPluginResourceBase | |
|
36 | 36 | |
|
37 | 37 | log = logging.getLogger(__name__) |
|
38 | 38 | |
@@ -48,8 +48,11 b' class RhodecodeAuthnResource(AuthnPlugin' | |||
|
48 | 48 | |
|
49 | 49 | class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase): |
|
50 | 50 | uid = 'rhodecode' |
|
51 |
|
|
|
52 |
|
|
|
51 | AUTH_RESTRICTION_NONE = 'user_all' | |
|
52 | AUTH_RESTRICTION_SUPER_ADMIN = 'user_super_admin' | |
|
53 | AUTH_RESTRICTION_SCOPE_ALL = 'scope_all' | |
|
54 | AUTH_RESTRICTION_SCOPE_HTTP = 'scope_http' | |
|
55 | AUTH_RESTRICTION_SCOPE_VCS = 'scope_vcs' | |
|
53 | 56 | |
|
54 | 57 | def includeme(self, config): |
|
55 | 58 | config.add_authn_plugin(self) |
@@ -104,16 +107,32 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||
|
104 | 107 | return None |
|
105 | 108 | |
|
106 | 109 | if userobj.extern_type != self.name: |
|
107 | log.warning( | |
|
108 | "userobj:%s extern_type mismatch got:`%s` expected:`%s`", | |
|
110 | log.warning("userobj:%s extern_type mismatch got:`%s` expected:`%s`", | |
|
109 | 111 | userobj, userobj.extern_type, self.name) |
|
110 | 112 | return None |
|
111 | 113 | |
|
112 | login_restriction = settings.get('login_restriction', '') | |
|
113 | if login_restriction == self.LOGIN_RESTRICTION_SUPER_ADMIN and userobj.admin is False: | |
|
114 | log.info( | |
|
115 | "userobj:%s is not super-admin and login restriction is set to %s", | |
|
116 | userobj, login_restriction) | |
|
114 | # check scope of auth | |
|
115 | scope_restriction = settings.get('scope_restriction', '') | |
|
116 | ||
|
117 | if scope_restriction == self.AUTH_RESTRICTION_SCOPE_HTTP \ | |
|
118 | and self.auth_type != HTTP_TYPE: | |
|
119 | log.warning("userobj:%s tried scope type %s and scope restriction is set to %s", | |
|
120 | userobj, self.auth_type, scope_restriction) | |
|
121 | return None | |
|
122 | ||
|
123 | if scope_restriction == self.AUTH_RESTRICTION_SCOPE_VCS \ | |
|
124 | and self.auth_type != VCS_TYPE: | |
|
125 | log.warning("userobj:%s tried scope type %s and scope restriction is set to %s", | |
|
126 | userobj, self.auth_type, scope_restriction) | |
|
127 | return None | |
|
128 | ||
|
129 | # check super-admin restriction | |
|
130 | auth_restriction = settings.get('auth_restriction', '') | |
|
131 | ||
|
132 | if auth_restriction == self.AUTH_RESTRICTION_SUPER_ADMIN \ | |
|
133 | and userobj.admin is False: | |
|
134 | log.warning("userobj:%s is not super-admin and auth restriction is set to %s", | |
|
135 | userobj, auth_restriction) | |
|
117 | 136 | return None |
|
118 | 137 | |
|
119 | 138 | user_attrs = { |
@@ -154,30 +173,45 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||
|
154 | 173 | elif userobj.username == username and password_match: |
|
155 | 174 | log.info('user `%s` authenticated correctly', userobj.username) |
|
156 | 175 | return user_attrs |
|
157 | log.warn("user `%s` used a wrong password when " | |
|
176 | log.warning("user `%s` used a wrong password when " | |
|
158 | 177 | "authenticating on this plugin", userobj.username) |
|
159 | 178 | return None |
|
160 | 179 | else: |
|
161 | log.warning( | |
|
162 | 'user `%s` failed to authenticate via %s, reason: account not ' | |
|
180 | log.warning('user `%s` failed to authenticate via %s, reason: account not ' | |
|
163 | 181 | 'active.', username, self.name) |
|
164 | 182 | return None |
|
165 | 183 | |
|
166 | 184 | |
|
167 | 185 | class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase): |
|
168 | login_restriction_choices = [ | |
|
169 | (RhodeCodeAuthPlugin.LOGIN_RESTRICTION_NONE, 'All users'), | |
|
170 |
(RhodeCodeAuthPlugin. |
|
|
186 | ||
|
187 | auth_restriction_choices = [ | |
|
188 | (RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE, 'All users'), | |
|
189 | (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SUPER_ADMIN, 'Super admins only'), | |
|
190 | ] | |
|
191 | ||
|
192 | auth_scope_choices = [ | |
|
193 | (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL, 'HTTP and VCS'), | |
|
194 | (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_HTTP, 'HTTP only'), | |
|
171 | 195 | ] |
|
172 | 196 | |
|
173 |
|
|
|
197 | auth_restriction = colander.SchemaNode( | |
|
174 | 198 | colander.String(), |
|
175 |
default= |
|
|
176 |
description=_(' |
|
|
177 |
title=_(' |
|
|
178 |
validator=colander.OneOf([x[0] for x in |
|
|
199 | default=auth_restriction_choices[0], | |
|
200 | description=_('Allowed user types for authentication using this plugin.'), | |
|
201 | title=_('User restriction'), | |
|
202 | validator=colander.OneOf([x[0] for x in auth_restriction_choices]), | |
|
179 | 203 | widget='select_with_labels', |
|
180 |
choices= |
|
|
204 | choices=auth_restriction_choices | |
|
205 | ) | |
|
206 | scope_restriction = colander.SchemaNode( | |
|
207 | colander.String(), | |
|
208 | default=auth_scope_choices[0], | |
|
209 | description=_('Allowed protocols for authentication using this plugin. ' | |
|
210 | 'VCS means GIT/HG/SVN. HTTP is web based login.'), | |
|
211 | title=_('Scope restriction'), | |
|
212 | validator=colander.OneOf([x[0] for x in auth_scope_choices]), | |
|
213 | widget='select_with_labels', | |
|
214 | choices=auth_scope_choices | |
|
181 | 215 | ) |
|
182 | 216 | |
|
183 | 217 |
@@ -23,7 +23,9 b' RhodeCode authentication token plugin fo' | |||
|
23 | 23 | """ |
|
24 | 24 | |
|
25 | 25 | import logging |
|
26 | import colander | |
|
26 | 27 | |
|
28 | from rhodecode.authentication.schema import AuthnPluginSettingsSchemaBase | |
|
27 | 29 | from rhodecode.translation import _ |
|
28 | 30 | from rhodecode.authentication.base import ( |
|
29 | 31 | RhodeCodeAuthPluginBase, VCS_TYPE, hybrid_property) |
@@ -48,6 +50,7 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||
|
48 | 50 | Enables usage of authentication tokens for vcs operations. |
|
49 | 51 | """ |
|
50 | 52 | uid = 'token' |
|
53 | AUTH_RESTRICTION_SCOPE_VCS = 'scope_vcs' | |
|
51 | 54 | |
|
52 | 55 | def includeme(self, config): |
|
53 | 56 | config.add_authn_plugin(self) |
@@ -67,6 +70,9 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||
|
67 | 70 | route_name='auth_home', |
|
68 | 71 | context=RhodecodeAuthnResource) |
|
69 | 72 | |
|
73 | def get_settings_schema(self): | |
|
74 | return RhodeCodeSettingsSchema() | |
|
75 | ||
|
70 | 76 | def get_display_name(self): |
|
71 | 77 | return _('Rhodecode Token') |
|
72 | 78 | |
@@ -142,12 +148,10 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||
|
142 | 148 | 'user `%s` successfully authenticated via %s', |
|
143 | 149 | user_attrs['username'], self.name) |
|
144 | 150 | return user_attrs |
|
145 | log.warn( | |
|
146 | 'user `%s` failed to authenticate via %s, reason: bad or ' | |
|
151 | log.warning('user `%s` failed to authenticate via %s, reason: bad or ' | |
|
147 | 152 | 'inactive token.', username, self.name) |
|
148 | 153 | else: |
|
149 | log.warning( | |
|
150 | 'user `%s` failed to authenticate via %s, reason: account not ' | |
|
154 | log.warning('user `%s` failed to authenticate via %s, reason: account not ' | |
|
151 | 155 | 'active.', username, self.name) |
|
152 | 156 | return None |
|
153 | 157 | |
@@ -155,3 +159,19 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||
|
155 | 159 | def includeme(config): |
|
156 | 160 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid) |
|
157 | 161 | plugin_factory(plugin_id).includeme(config) |
|
162 | ||
|
163 | ||
|
164 | class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase): | |
|
165 | auth_scope_choices = [ | |
|
166 | (RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_VCS, 'VCS only'), | |
|
167 | ] | |
|
168 | ||
|
169 | scope_restriction = colander.SchemaNode( | |
|
170 | colander.String(), | |
|
171 | default=auth_scope_choices[0], | |
|
172 | description=_('Choose operation scope restriction when authenticating.'), | |
|
173 | title=_('Scope restriction'), | |
|
174 | validator=colander.OneOf([x[0] for x in auth_scope_choices]), | |
|
175 | widget='select_with_labels', | |
|
176 | choices=auth_scope_choices | |
|
177 | ) |
@@ -122,15 +122,15 b' class Fixture(object):' | |||
|
122 | 122 | |
|
123 | 123 | return context() |
|
124 | 124 | |
|
125 |
def |
|
|
125 | def auth_restriction(self, auth_restriction): | |
|
126 | 126 | """ |
|
127 |
Context process for changing the builtin rhodecode plugin |
|
|
127 | Context process for changing the builtin rhodecode plugin auth restrictions. | |
|
128 | 128 | Use like: |
|
129 | 129 | fixture = Fixture() |
|
130 |
with fixture. |
|
|
130 | with fixture.auth_restriction('super_admin'): | |
|
131 | 131 | #tests |
|
132 | 132 | |
|
133 |
after this block |
|
|
133 | after this block auth restriction will be taken off | |
|
134 | 134 | """ |
|
135 | 135 | |
|
136 | 136 | class context(object): |
@@ -143,13 +143,45 b' class Fixture(object):' | |||
|
143 | 143 | def __enter__(self): |
|
144 | 144 | plugin = self._get_pluing() |
|
145 | 145 | plugin.create_or_update_setting( |
|
146 |
' |
|
|
146 | 'auth_restriction', auth_restriction) | |
|
147 | 147 | Session().commit() |
|
148 | 148 | |
|
149 | 149 | def __exit__(self, exc_type, exc_val, exc_tb): |
|
150 | 150 | plugin = self._get_pluing() |
|
151 | 151 | plugin.create_or_update_setting( |
|
152 |
' |
|
|
152 | 'auth_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_NONE) | |
|
153 | Session().commit() | |
|
154 | ||
|
155 | return context() | |
|
156 | ||
|
157 | def scope_restriction(self, scope_restriction): | |
|
158 | """ | |
|
159 | Context process for changing the builtin rhodecode plugin scope restrictions. | |
|
160 | Use like: | |
|
161 | fixture = Fixture() | |
|
162 | with fixture.scope_restriction('scope_http'): | |
|
163 | #tests | |
|
164 | ||
|
165 | after this block scope restriction will be taken off | |
|
166 | """ | |
|
167 | ||
|
168 | class context(object): | |
|
169 | def _get_pluing(self): | |
|
170 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format( | |
|
171 | RhodeCodeAuthPlugin.uid) | |
|
172 | plugin = RhodeCodeAuthPlugin(plugin_id) | |
|
173 | return plugin | |
|
174 | ||
|
175 | def __enter__(self): | |
|
176 | plugin = self._get_pluing() | |
|
177 | plugin.create_or_update_setting( | |
|
178 | 'scope_restriction', scope_restriction) | |
|
179 | Session().commit() | |
|
180 | ||
|
181 | def __exit__(self, exc_type, exc_val, exc_tb): | |
|
182 | plugin = self._get_pluing() | |
|
183 | plugin.create_or_update_setting( | |
|
184 | 'scope_restriction', RhodeCodeAuthPlugin.AUTH_RESTRICTION_SCOPE_ALL) | |
|
153 | 185 | Session().commit() |
|
154 | 186 | |
|
155 | 187 | return context() |
General Comments 0
You need to be logged in to leave comments.
Login now