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('websauna.require_activation', True)) allow_inactive_login = asbool(settings.get('websauna.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, 'websauna.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 do_post_login_actions(self, user: IUser, headers: dict, location: str = None) -> Response: """What happens after a successful login. Override this to customize e.g. where the user lands. :param user: User object. :param headers: Dictionary with headers to be added to the HTTPFound response. :param location: URL to redirect the user to. :return: Redirection to location. """ request = self.request if not location: location = get_config_route(request, 'websauna.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 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 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: location = get_config_route(request, 'websauna.request_password_reset_redirect') assert location return HTTPFound(location=location)
def authenticate_user(self, user: IUser, login_source: str, location: str = None) -> Response: """Make the current session logged in session for this particular user. How to authenticate user using the login service (assuming you have done password match or related yourself): .. code-block:: python from websauna.system.user.utils import get_login_service def my_view(request): # load user model instance from database # user = ... login_service = get_login_service(request) response = login_service.authenticate_user(user, "my-login-source") :raise AuthenticationFailure: If login cannot proceed due to disabled user account, etc. :return: HTTPResponse what should happen as post-login action """ request = self.request settings = request.registry.settings require_activation = asbool( settings.get('websauna.require_activation', True)) allow_inactive_login = asbool( settings.get('websauna.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, 'websauna.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 login(request: Request) -> [HTTPFound, dict]: """Default login view implementation. :param request: Pyramid request. :return: Context to be used by the renderer or a HTTPFound redirect if user is already logged in. """ login_redirect_view = get_config_route(request, "websauna.login_redirect") # Create login form schema schema = request.registry.getUtility(ILoginSchema) schema = schema().bind(request=request) # Create login form form = request.registry.getUtility(ILoginForm) form = form(schema) settings = request.registry.settings social_logins = aslist(settings.get("websauna.social_logins", "")) # Process form if request.method == "POST": try: controls = request.POST.items() captured = form.validate(controls) except deform.ValidationFailure as e: return {'form': e.render(), 'errors': e.error.children} username = captured['username'] password = captured['password'] login_service = get_login_service(request) try: return login_service.authenticate_credentials( username, password, login_source="login_form") except AuthenticationFailure as e: # Tell user they cannot login at the moment messages.add(request, msg=str(e), msg_id="msg-authentication-failure", kind="error") return { 'form': form.render(appstruct=captured), 'errors': [e], "social_logins": social_logins } else: # HTTP get, display login form if request.user: # Already logged in return HTTPFound(location=login_redirect_view) # Display login form return {'form': form.render(), "social_logins": social_logins}
def login(request): """Default login view implementation.""" login_redirect_view = get_config_route(request, "websauna.login_redirect") # Create login form schema schema = request.registry.getUtility(ILoginSchema) schema = schema().bind(request=request) # Create login form form = request.registry.getUtility(ILoginForm) form = form(schema) settings = request.registry.settings social_logins = aslist(settings.get("websauna.social_logins", "")) # Process form if request.method == "POST": try: controls = request.POST.items() captured = form.validate(controls) except deform.ValidationFailure as e: return { 'form': e.render(), 'errors': e.error.children } username = captured['username'] password = captured['password'] login_service = get_login_service(request) try: return login_service.authenticate_credentials(username, password, login_source="login_form") except AuthenticationFailure as e: # Tell user they cannot login at the moment messages.add(request, msg=str(e), msg_id="msg-authentication-failure", kind="error") return { 'form': form.render(appstruct=captured), 'errors': [e], "social_logins": social_logins } else: # HTTP get, display login form if request.user: # Already logged in return HTTPFound(location=login_redirect_view) # Display login form return {'form': form.render(), "social_logins": social_logins}
def authenticate_user(self, user: IUser, login_source: str, location: str=None) -> Response: """Make the current session logged in session for this particular user. How to authenticate user using the login service (assuming you have done password match or related yourself): .. code-block:: python from websauna.system.user.utils import get_login_service def my_view(request): # load user model instance from database # user = ... login_service = get_login_service(request) response = login_service.authenticate_user(user, "my-login-source") :raise AuthenticationFailure: If login cannot proceed due to disabled user account, etc. :return: HTTPResponse what should happen as post-login action """ request = self.request settings = request.registry.settings require_activation = asbool(settings.get('websauna.require_activation', True)) allow_inactive_login = asbool(settings.get('websauna.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, 'websauna.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 create_forgot_password_request(self, email: str, location: str = 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 :param email: User email. :param location: URL to redirect the user after the password request. :return: Redirect to location. :raise: CannotResetPasswordException if there is any reason the password cannot be reset. Usually wrong email. """ request = self.request 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: {email}".format(email=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: location = get_config_route( request, 'websauna.request_password_reset_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, 'websauna.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 do_post_login_actions(self, user: IUser, headers: dict, location: str=None): """What happens after a succesful login. Override this to customize e.g. where the user lands. """ request = self.request if not location: location = get_config_route(request, 'websauna.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 logout(self, location: str = None) -> Response: """Log out user from the site. * Terminate session * Show logged out message * Redirect the user to post login page :param location: Override the redirect page. If none use ``websauna.login_redirect``. TODO - to be changed. :return: HTTPFound to location. """ # TODO: Horus might go request = self.request logout_redirect_view = get_config_route(request, 'websauna.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 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, 'websauna.reset_password_redirect') return HTTPFound(location=location)
def do_post_login_actions(self, user: IUser, headers: dict, location: str = None): """What happens after a succesful login. Override this to customize e.g. where the user lands. """ request = self.request if not location: location = get_config_route(request, 'websauna.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 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('websauna.require_activation', True)) allow_inactive_login = asbool( settings.get('websauna.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, 'websauna.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: str = None) -> Response: """Perform actual password reset operations. User has following password reset link (GET) or enters the code on a form. :param activation_code: Activation code provided by the user. :param password: New user password. :param location: URL to redirect the user after the password request. :return: Redirect to location. :raise: HTTPNotFound if activation_code is not found. """ 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"), request) location = location or get_config_route( request, 'websauna.reset_password_redirect') return HTTPFound(location=location)
def do_post_login_actions(self, user: IUser, headers: dict, location: str = None): """Override what happens after login.""" request = self.request self.update_login_data(user) e = Login(request, user) request.registry.notify(e) # Where this user was going before he or she hit login button login_state = get_login_state(request) if login_state: location = login_state["url"] else: # Only greet user if he/she was not continuing action self.greet_user(user) location = get_config_route(request, 'websauna.login_redirect') return HTTPFound(location)