Show More
@@ -107,6 +107,16 b' class TestLoginController(object):' | |||||
107 |
|
107 | |||
108 | response.mustcontain('/%s' % HG_REPO) |
|
108 | response.mustcontain('/%s' % HG_REPO) | |
109 |
|
109 | |||
|
110 | def test_login_regular_forbidden_when_super_admin_restriction(self): | |||
|
111 | from rhodecode.authentication.plugins.auth_rhodecode import RhodeCodeAuthPlugin | |||
|
112 | with fixture.login_restriction(RhodeCodeAuthPlugin.LOGIN_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 | ||||
110 | def test_login_ok_came_from(self): |
|
120 | def test_login_ok_came_from(self): | |
111 | test_came_from = '/_admin/users?branch=stable' |
|
121 | test_came_from = '/_admin/users?branch=stable' | |
112 | _url = '{}?came_from={}'.format(route_path('login'), test_came_from) |
|
122 | _url = '{}?came_from={}'.format(route_path('login'), test_came_from) |
@@ -46,20 +46,10 b' class RhodecodeAuthnResource(AuthnPlugin' | |||||
46 | pass |
|
46 | pass | |
47 |
|
47 | |||
48 |
|
48 | |||
49 | class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase): |
|
|||
50 |
|
||||
51 | superadmin_restriction = colander.SchemaNode( |
|
|||
52 | colander.Bool(), |
|
|||
53 | default=False, |
|
|||
54 | description=_('Only allow super-admins to log-in using this plugin.'), |
|
|||
55 | missing=False, |
|
|||
56 | title=_('Enabled'), |
|
|||
57 | widget='bool', |
|
|||
58 | ) |
|
|||
59 |
|
||||
60 |
|
||||
61 | class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase): |
|
49 | class RhodeCodeAuthPlugin(RhodeCodeAuthPluginBase): | |
62 | uid = 'rhodecode' |
|
50 | uid = 'rhodecode' | |
|
51 | LOGIN_RESTRICTION_NONE = 'none' | |||
|
52 | LOGIN_RESTRICTION_SUPER_ADMIN = 'super_admin' | |||
63 |
|
53 | |||
64 | def includeme(self, config): |
|
54 | def includeme(self, config): | |
65 | config.add_authn_plugin(self) |
|
55 | config.add_authn_plugin(self) | |
@@ -112,12 +102,20 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||||
112 | if not userobj: |
|
102 | if not userobj: | |
113 | log.debug('userobj was:%s skipping', userobj) |
|
103 | log.debug('userobj was:%s skipping', userobj) | |
114 | return None |
|
104 | return None | |
|
105 | ||||
115 | if userobj.extern_type != self.name: |
|
106 | if userobj.extern_type != self.name: | |
116 | log.warning( |
|
107 | log.warning( | |
117 | "userobj:%s extern_type mismatch got:`%s` expected:`%s`", |
|
108 | "userobj:%s extern_type mismatch got:`%s` expected:`%s`", | |
118 | userobj, userobj.extern_type, self.name) |
|
109 | userobj, userobj.extern_type, self.name) | |
119 | return None |
|
110 | return None | |
120 |
|
111 | |||
|
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) | |||
|
117 | return None | |||
|
118 | ||||
121 | user_attrs = { |
|
119 | user_attrs = { | |
122 | "username": userobj.username, |
|
120 | "username": userobj.username, | |
123 | "firstname": userobj.firstname, |
|
121 | "firstname": userobj.firstname, | |
@@ -149,8 +147,8 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||||
149 | user_attrs['_hash_migrate'] = new_hash |
|
147 | user_attrs['_hash_migrate'] = new_hash | |
150 |
|
148 | |||
151 | if userobj.username == User.DEFAULT_USER and userobj.active: |
|
149 | if userobj.username == User.DEFAULT_USER and userobj.active: | |
152 | log.info( |
|
150 | log.info('user `%s` authenticated correctly as anonymous user', | |
153 |
|
|
151 | userobj.username) | |
154 | return user_attrs |
|
152 | return user_attrs | |
155 |
|
153 | |||
156 | elif userobj.username == username and password_match: |
|
154 | elif userobj.username == username and password_match: | |
@@ -166,6 +164,23 b' class RhodeCodeAuthPlugin(RhodeCodeAuthP' | |||||
166 | return None |
|
164 | return None | |
167 |
|
165 | |||
168 |
|
166 | |||
|
167 | class RhodeCodeSettingsSchema(AuthnPluginSettingsSchemaBase): | |||
|
168 | login_restriction_choices = [ | |||
|
169 | (RhodeCodeAuthPlugin.LOGIN_RESTRICTION_NONE, 'All users'), | |||
|
170 | (RhodeCodeAuthPlugin.LOGIN_RESTRICTION_SUPER_ADMIN, 'Super admins only') | |||
|
171 | ] | |||
|
172 | ||||
|
173 | login_restriction = colander.SchemaNode( | |||
|
174 | colander.String(), | |||
|
175 | default=login_restriction_choices[0], | |||
|
176 | description=_('Choose login restrition for users.'), | |||
|
177 | title=_('Login restriction'), | |||
|
178 | validator=colander.OneOf([x[0] for x in login_restriction_choices]), | |||
|
179 | widget='select_with_labels', | |||
|
180 | choices=login_restriction_choices | |||
|
181 | ) | |||
|
182 | ||||
|
183 | ||||
169 | def includeme(config): |
|
184 | def includeme(config): | |
170 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid) |
|
185 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format(RhodeCodeAuthPlugin.uid) | |
171 | plugin_factory(plugin_id).includeme(config) |
|
186 | plugin_factory(plugin_id).includeme(config) |
@@ -66,6 +66,8 b'' | |||||
66 | <div class="checkbox">${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div> |
|
66 | <div class="checkbox">${h.checkbox(node.name, True, checked=defaults.get(node.name))}</div> | |
67 | %elif node.widget == "select": |
|
67 | %elif node.widget == "select": | |
68 | ${h.select(node.name, defaults.get(node.name), node.validator.choices, class_="select2AuthSetting")} |
|
68 | ${h.select(node.name, defaults.get(node.name), node.validator.choices, class_="select2AuthSetting")} | |
|
69 | %elif node.widget == "select_with_labels": | |||
|
70 | ${h.select(node.name, defaults.get(node.name), node.choices, class_="select2AuthSetting")} | |||
69 | %elif node.widget == "textarea": |
|
71 | %elif node.widget == "textarea": | |
70 | <div class="textarea" style="margin-left: 0px">${h.textarea(node.name, defaults.get(node.name), rows=10)}</div> |
|
72 | <div class="textarea" style="margin-left: 0px">${h.textarea(node.name, defaults.get(node.name), rows=10)}</div> | |
71 | %elif node.widget == "readonly": |
|
73 | %elif node.widget == "readonly": |
@@ -38,6 +38,8 b' from rhodecode.model.repo_group import R' | |||||
38 | from rhodecode.model.user_group import UserGroupModel |
|
38 | from rhodecode.model.user_group import UserGroupModel | |
39 | from rhodecode.model.gist import GistModel |
|
39 | from rhodecode.model.gist import GistModel | |
40 | from rhodecode.model.auth_token import AuthTokenModel |
|
40 | from rhodecode.model.auth_token import AuthTokenModel | |
|
41 | from rhodecode.authentication.plugins.auth_rhodecode import \ | |||
|
42 | RhodeCodeAuthPlugin | |||
41 |
|
43 | |||
42 | dn = os.path.dirname |
|
44 | dn = os.path.dirname | |
43 | FIXTURES = os.path.join(dn(dn(os.path.abspath(__file__))), 'tests', 'fixtures') |
|
45 | FIXTURES = os.path.join(dn(dn(os.path.abspath(__file__))), 'tests', 'fixtures') | |
@@ -120,6 +122,38 b' class Fixture(object):' | |||||
120 |
|
122 | |||
121 | return context() |
|
123 | return context() | |
122 |
|
124 | |||
|
125 | def login_restriction(self, login_restriction): | |||
|
126 | """ | |||
|
127 | Context process for changing the builtin rhodecode plugin login restrictions. | |||
|
128 | Use like: | |||
|
129 | fixture = Fixture() | |||
|
130 | with fixture.login_restriction('super_admin'): | |||
|
131 | #tests | |||
|
132 | ||||
|
133 | after this block login restriction will be taken off | |||
|
134 | """ | |||
|
135 | ||||
|
136 | class context(object): | |||
|
137 | def _get_pluing(self): | |||
|
138 | plugin_id = 'egg:rhodecode-enterprise-ce#{}'.format( | |||
|
139 | RhodeCodeAuthPlugin.uid) | |||
|
140 | plugin = RhodeCodeAuthPlugin(plugin_id) | |||
|
141 | return plugin | |||
|
142 | ||||
|
143 | def __enter__(self): | |||
|
144 | plugin = self._get_pluing() | |||
|
145 | plugin.create_or_update_setting( | |||
|
146 | 'login_restriction', login_restriction) | |||
|
147 | Session().commit() | |||
|
148 | ||||
|
149 | def __exit__(self, exc_type, exc_val, exc_tb): | |||
|
150 | plugin = self._get_pluing() | |||
|
151 | plugin.create_or_update_setting( | |||
|
152 | 'login_restriction', RhodeCodeAuthPlugin.LOGIN_RESTRICTION_NONE) | |||
|
153 | Session().commit() | |||
|
154 | ||||
|
155 | return context() | |||
|
156 | ||||
123 | def _get_repo_create_params(self, **custom): |
|
157 | def _get_repo_create_params(self, **custom): | |
124 | defs = { |
|
158 | defs = { | |
125 | 'repo_name': None, |
|
159 | 'repo_name': None, |
General Comments 0
You need to be logged in to leave comments.
Login now