def __init__(self, request): super(AuthController, self).__init__(request) schema = request.registry.getUtility(ILoginSchema) self.schema = schema().bind(request=self.request) form = request.registry.getUtility(ILoginForm) self.login_redirect_view = get_config_route( request, 'horus.login_redirect' ) self.logout_redirect_view = get_config_route( request, 'horus.logout_redirect' ) self.require_activation = asbool( self.settings.get('horus.require_activation', True) ) self.allow_inactive_login = asbool( self.settings.get('horus.allow_inactive_login', False) ) # XXX: Bootstrap classes leak into Deform here login_button = deform.Button(name="login_email", title="Login with email", css_class="btn-lg btn-block") self.form = form(self.schema, buttons=(login_button,)) # If the form is embedded on other pages force it go to right HTTP POST endpoint self.form.action = request.route_url("login")
def authenticate_user(self, user: IUser, login_source:str, location: str=None): """Make the current session logged in session for this particular user.""" request = self.request settings = request.registry.settings require_activation = asbool(settings.get('horus.require_activation', True)) allow_inactive_login = asbool(settings.get('horus.allow_inactive_login', False)) if (not allow_inactive_login) and require_activation and (not user.is_activated()): raise AuthenticationFailure('Your account is not active, please check your e-mail. If your account activation email as expired please request a password reset.') if not user.can_login(): raise AuthenticationFailure('This user account cannot log in at the moment.') user_registry = get_user_registry(request) token = user_registry.get_session_token(user) headers = remember(request, token) # assert headers, "Authentication backend did not give us any session headers" if not location: location = get_config_route(request, 'horus.login_redirect') self.greet_user(user) self.update_login_data(user) e = events.Login(request, user) request.registry.notify(e) return HTTPFound(location=location, headers=headers)
def reset_password(self, activation_code: str, password: str, location=None) -> Response: """Perform actual password reset operations. User has following password reset link (GET) or enters the code on a form. """ request = self.request user_registry = get_user_registry(request) user = user_registry.get_user_by_password_reset_token(activation_code) if not user: return HTTPNotFound("Activation code not found") user_registry.reset_password(user, password) messages.add( request, msg= "The password reset complete. Please sign in with your new password.", kind='success', msg_id="msg-password-reset-complete") request.registry.notify( PasswordResetEvent(self.request, user, password)) request.registry.notify( UserAuthSensitiveOperation(self.request, user, "password_reset")) location = location or get_config_route( request, 'horus.reset_password_redirect') return HTTPFound(location=location)
def create_forgot_password_request(self, email, location=None) -> Response: """Create a new email activation token for a user and produce the following screen. * Sets user password reset token * Sends out reset password email * The existing of user with such email should be validated beforehand :raise: CannotResetPasswordException if there is any reason the password cannot be reset. Usually wrong email. """ request = self.request dbsession = self.request.dbsession user_registry = get_user_registry(request) reset_info = user_registry.create_password_reset_token(email) if not reset_info: raise CannotResetPasswordException( "Cannot reset password for email: {}".format(email)) user, token, expiration_seconds = reset_info link = request.route_url('reset_password', code=token) context = dict(link=link, user=user, expiration_hours=int(expiration_seconds / 3600)) send_templated_mail(request, [ email, ], "login/email/forgot_password", context=context) messages.add(request, msg="Please check your email to continue password reset.", kind='success', msg_id="msg-check-email") if not location: #: TODO configuration option here probable wrong location = get_config_route(request, 'horus.reset_password_redirect') assert location return HTTPFound(location=location)
def logout(self, location=None) -> Response: """Log out user from the site. * Terminate session * Show logged out message * Redirect the user to post login page """ # TODO: Horus might go request = self.request logout_redirect_view = get_config_route(request, 'horus.logout_redirect') location = location or logout_redirect_view messages.add(request, msg="You are now logged out.", kind="success", msg_id="msg-logged-out") headers = forget(request) return HTTPFound(location=location, headers=headers)
def authenticated(request:Request, user:UserMixin, location:str=None) -> HTTPFound: """Logs in the user. TODO: Make this is a registry component for overriding Sets the auth cookies and redirects to the page defined in horus.login_redirect, which defaults to a view named 'index'. Fills in user last login details. :param request: Current request :param user: User model to log in :param location: Override the redirect page. If none use ``horus.login_redirect`` """ # See that our user model matches one we expect from the configuration registry = request.registry User = get_user_class(registry) assert User assert isinstance(user, User) assert user.id, "Cannot login with invalid user object" if not user.can_login(): raise RuntimeError("Got authenticated() request for disabled user - should not happen") headers = remember(request, user.id) # assert headers, "Authentication backend did not give us any session headers" if not user.last_login_at: e = events.FirstLogin(request, user) request.registry.notify(e) # Update user security details user.last_login_at = now() user.last_login_ip = request.client_addr if not location: location = get_config_route(request, 'horus.login_redirect') messages.add(request, kind="success", msg="You are now logged in.", msg_id="msg-you-are-logged-in") return HTTPFound(location=location, headers=headers)
def authenticate_user(self, user: IUser, login_source: str, location: str = None): """Make the current session logged in session for this particular user.""" request = self.request settings = request.registry.settings require_activation = asbool( settings.get('horus.require_activation', True)) allow_inactive_login = asbool( settings.get('horus.allow_inactive_login', False)) if (not allow_inactive_login) and require_activation and ( not user.is_activated()): raise AuthenticationFailure( 'Your account is not active, please check your e-mail. If your account activation email as expired please request a password reset.' ) if not user.can_login(): raise AuthenticationFailure( 'This user account cannot log in at the moment.') user_registry = get_user_registry(request) token = user_registry.get_session_token(user) headers = remember(request, token) # assert headers, "Authentication backend did not give us any session headers" if not location: location = get_config_route(request, 'horus.login_redirect') self.greet_user(user) self.update_login_data(user) e = events.Login(request, user) request.registry.notify(e) return HTTPFound(location=location, headers=headers)