diff --git a/rhodecode/apps/admin/views/users.py b/rhodecode/apps/admin/views/users.py --- a/rhodecode/apps/admin/views/users.py +++ b/rhodecode/apps/admin/views/users.py @@ -185,7 +185,7 @@ class AdminUsersView(BaseAppView, DataGr def users_new(self): _ = self.request.translate c = self.load_default_context() - c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name + c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.uid self._set_personal_repo_group_template_vars(c) return self._get_template_context(c) @@ -198,7 +198,7 @@ class AdminUsersView(BaseAppView, DataGr def users_create(self): _ = self.request.translate c = self.load_default_context() - c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name + c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.uid user_model = UserModel() user_form = UserForm(self.request.translate)() try: diff --git a/rhodecode/apps/login/views.py b/rhodecode/apps/login/views.py --- a/rhodecode/apps/login/views.py +++ b/rhodecode/apps/login/views.py @@ -32,6 +32,7 @@ from pyramid.view import view_config from rhodecode.apps._base import BaseAppView from rhodecode.authentication.base import authenticate, HTTP_TYPE +from rhodecode.authentication.plugins import auth_rhodecode from rhodecode.events import UserRegistered, trigger from rhodecode.lib import helpers as h from rhodecode.lib import audit_logger @@ -367,15 +368,24 @@ class LoginView(BaseAppView): # matching emails msg = _('If such email exists, a password reset link was sent to it.') + def default_response(): + log.debug('faking response on invalid password reset') + # make this take 2s, to prevent brute forcing. + time.sleep(2) + h.flash(msg, category='success') + return HTTPFound(self.request.route_path('reset_password')) + if self.request.POST: if h.HasPermissionAny('hg.password_reset.disabled')(): _email = self.request.POST.get('email', '') log.error('Failed attempt to reset password for `%s`.', _email) - h.flash(_('Password reset has been disabled.'), - category='error') + h.flash(_('Password reset has been disabled.'), category='error') return HTTPFound(self.request.route_path('reset_password')) password_reset_form = PasswordResetForm(self.request.translate)() + description = u'Generated token for password reset from {}'.format( + datetime.datetime.now().isoformat()) + try: form_result = password_reset_form.to_python( self.request.POST) @@ -395,10 +405,14 @@ class LoginView(BaseAppView): # Generate reset URL and send mail. user = User.get_by_email(user_email) + # only allow rhodecode based users to reset their password + # external auth shouldn't allow password reset + if user and user.extern_type != auth_rhodecode.RhodeCodeAuthPlugin.uid: + log.warning('User %s with external type `%s` tried a password reset. ' + 'This try was rejected', user, user.extern_type) + return default_response() + # generate password reset token that expires in 10 minutes - description = u'Generated token for password reset from {}'.format( - datetime.datetime.now().isoformat()) - reset_token = UserModel().add_auth_token( user=user, lifetime_minutes=10, role=UserModel.auth_token_role.ROLE_PASSWORD_RESET, @@ -411,15 +425,14 @@ class LoginView(BaseAppView): _query={'key': reset_token.api_key}) UserModel().reset_password_link( form_result, password_reset_url) - # Display success message and redirect. - h.flash(msg, category='success') action_data = {'email': user_email, 'user_agent': self.request.user_agent} audit_logger.store_web( 'user.password.reset_request', action_data=action_data, user=self._rhodecode_user, commit=True) - return HTTPFound(self.request.route_path('reset_password')) + + return default_response() except formencode.Invalid as errors: template_context.update({ @@ -434,11 +447,7 @@ class LoginView(BaseAppView): # case of failed captcha return self._get_template_context(c, **template_context) - log.debug('faking response on invalid password reset') - # make this take 2s, to prevent brute forcing. - time.sleep(2) - h.flash(msg, category='success') - return HTTPFound(self.request.route_path('reset_password')) + return default_response() return self._get_template_context(c, **template_context) diff --git a/rhodecode/templates/admin/users/user_edit_profile.mako b/rhodecode/templates/admin/users/user_edit_profile.mako --- a/rhodecode/templates/admin/users/user_edit_profile.mako +++ b/rhodecode/templates/admin/users/user_edit_profile.mako @@ -103,11 +103,12 @@
- ${_('Source of Record')}: + ${_('Authentication type')}:

${c.extern_type}

${h.hidden('extern_type', readonly="readonly")} +

${_('User was created using an external source. He is bound to authentication using this method.')}

@@ -127,7 +128,7 @@ ## allowed_languages is defined in the users.py ## c.language comes from base.py as a default language ${h.select('language', c.language, c.allowed_languages)} -

${h.literal(_('Help translate %(rc_link)s into your language.') % {'rc_link': h.link_to('RhodeCode Enterprise', h.route_url('rhodecode_translations'))})}

+

${h.literal(_('User interface language. Help translate %(rc_link)s into your language.') % {'rc_link': h.link_to('RhodeCode Enterprise', h.route_url('rhodecode_translations'))})}