def test_password_change_email_unverified(self, pyramid_request, pyramid_config, monkeypatch): stub_user = pretend.stub( username="******", name="", email="*****@*****.**", primary_email=pretend.stub(email="*****@*****.**", verified=False), ) subject_renderer = pyramid_config.testing_add_renderer( "email/password-change/subject.txt") subject_renderer.string_response = "Email Subject" body_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.txt") body_renderer.string_response = "Email Body" html_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.html") html_renderer.string_response = "Email HTML Body" send_email = pretend.stub( delay=pretend.call_recorder(lambda *args, **kwargs: None)) pyramid_request.task = pretend.call_recorder( lambda *args, **kwargs: send_email) monkeypatch.setattr(email, "send_email", send_email) result = email.send_password_change_email(pyramid_request, stub_user) assert result == {"username": stub_user.username} subject_renderer.assert_() body_renderer.assert_(username=stub_user.username) html_renderer.assert_(username=stub_user.username) assert pyramid_request.task.calls == [] assert send_email.delay.calls == []
def change_password(self): form = ChangePasswordForm( **self.request.POST, username=self.request.user.username, full_name=self.request.user.name, email=self.request.user.email, user_service=self.user_service, ) if form.validate(): self.user_service.update_user(self.request.user.id, password=form.new_password.data) send_password_change_email(self.request, self.request.user) self.request.session.flash("Password updated", queue="success") return {**self.default_response, "change_password_form": form}
def test_password_change_email(self, pyramid_request, pyramid_config, monkeypatch): stub_user = pretend.stub(email="*****@*****.**", username="******", name="") subject_renderer = pyramid_config.testing_add_renderer( "email/password-change.subject.txt") subject_renderer.string_response = "Email Subject" body_renderer = pyramid_config.testing_add_renderer( "email/password-change.body.txt") body_renderer.string_response = "Email Body" send_email = pretend.stub( delay=pretend.call_recorder(lambda *args, **kwargs: None)) pyramid_request.task = pretend.call_recorder( lambda *args, **kwargs: send_email) monkeypatch.setattr(email, "send_email", send_email) result = email.send_password_change_email(pyramid_request, user=stub_user) assert result == {"username": stub_user.username} subject_renderer.assert_() body_renderer.assert_(username=stub_user.username) assert pyramid_request.task.calls == [pretend.call(send_email)] assert send_email.delay.calls == [ pretend.call( "Email Subject", "Email Body", recipient=f"{stub_user.username} <{stub_user.email}>", ) ]
def change_password(self): form = ChangePasswordForm( **self.request.POST, username=self.request.user.username, full_name=self.request.user.name, email=self.request.user.email, user_service=self.user_service, breach_service=self.breach_service, check_password_metrics_tags=["method:new_password"], ) if form.validate(): self.user_service.update_user( self.request.user.id, password=form.new_password.data ) send_password_change_email(self.request, self.request.user) self.request.session.flash("Password updated", queue="success") return {**self.default_response, "change_password_form": form}
def change_password(self): form = ChangePasswordForm( **self.request.POST, username=self.request.user.username, full_name=self.request.user.name, email=self.request.user.email, user_service=self.user_service, breach_service=self.breach_service, check_password_metrics_tags=["method:new_password"], ) if form.validate(): self.user_service.update_user(self.request.user.id, password=form.new_password.data) self.user_service.record_event( self.request.user.id, tag="account:password:change", ip_address=self.request.remote_addr, ) send_password_change_email(self.request, self.request.user) self.request.session.flash("Password updated", queue="success") return {**self.default_response, "change_password_form": form}
def change_password(self): form = ChangePasswordForm( **self.request.POST, username=self.request.user.username, full_name=self.request.user.name, email=self.request.user.email, user_service=self.user_service, ) if form.validate(): self.user_service.update_user( self.request.user.id, password=form.new_password.data, ) send_password_change_email(self.request, self.request.user) self.request.session.flash( 'Password updated.', queue='success' ) return { **self.default_response, 'change_password_form': form, }
def test_password_change_email(self, pyramid_request, pyramid_config, monkeypatch): stub_user = pretend.stub( username="******", name="", email="*****@*****.**", primary_email=pretend.stub(email="*****@*****.**", verified=True), ) subject_renderer = pyramid_config.testing_add_renderer( "email/password-change/subject.txt" ) subject_renderer.string_response = "Email Subject" body_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.txt" ) body_renderer.string_response = "Email Body" html_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.html" ) html_renderer.string_response = "Email HTML Body" send_email = pretend.stub( delay=pretend.call_recorder(lambda *args, **kwargs: None) ) pyramid_request.task = pretend.call_recorder(lambda *args, **kwargs: send_email) monkeypatch.setattr(email, "send_email", send_email) result = email.send_password_change_email(pyramid_request, stub_user) assert result == {"username": stub_user.username} subject_renderer.assert_() body_renderer.assert_(username=stub_user.username) html_renderer.assert_(username=stub_user.username) assert pyramid_request.task.calls == [pretend.call(send_email)] assert send_email.delay.calls == [ pretend.call( f"{stub_user.username} <{stub_user.email}>", attr.asdict( EmailMessage( subject="Email Subject", body_text="Email Body", body_html=( "<html>\n<head></head>\n" "<body><p>Email HTML Body</p></body>\n</html>\n" ), ) ), ) ]
def test_password_change_email(self, pyramid_request, pyramid_config, monkeypatch): stub_user = pretend.stub( username="******", name="", email="*****@*****.**", primary_email=pretend.stub(email="*****@*****.**", verified=True), ) subject_renderer = pyramid_config.testing_add_renderer( "email/password-change/subject.txt") subject_renderer.string_response = "Email Subject" body_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.txt") body_renderer.string_response = "Email Body" html_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.html") html_renderer.string_response = "Email HTML Body" send_email = pretend.stub( delay=pretend.call_recorder(lambda *args, **kwargs: None)) pyramid_request.task = pretend.call_recorder( lambda *args, **kwargs: send_email) monkeypatch.setattr(email, "send_email", send_email) result = email.send_password_change_email(pyramid_request, stub_user) assert result == {"username": stub_user.username} subject_renderer.assert_() body_renderer.assert_(username=stub_user.username) html_renderer.assert_(username=stub_user.username) assert pyramid_request.task.calls == [pretend.call(send_email)] assert send_email.delay.calls == [ pretend.call( f"{stub_user.username} <{stub_user.email}>", attr.asdict( EmailMessage( subject="Email Subject", body_text="Email Body", body_html=( "<html>\n<head></head>\n" "<body><p>Email HTML Body</p></body>\n</html>\n"), )), ) ]
def test_password_change_email( self, pyramid_request, pyramid_config, monkeypatch): stub_user = pretend.stub( email='*****@*****.**', username='******', name="", ) subject_renderer = pyramid_config.testing_add_renderer( 'email/password-change.subject.txt' ) subject_renderer.string_response = 'Email Subject' body_renderer = pyramid_config.testing_add_renderer( 'email/password-change.body.txt' ) body_renderer.string_response = 'Email Body' send_email = pretend.stub( delay=pretend.call_recorder(lambda *args, **kwargs: None) ) pyramid_request.task = pretend.call_recorder( lambda *args, **kwargs: send_email ) monkeypatch.setattr(email, 'send_email', send_email) result = email.send_password_change_email( pyramid_request, user=stub_user, ) assert result == { 'username': stub_user.username, } subject_renderer.assert_() body_renderer.assert_(username=stub_user.username) assert pyramid_request.task.calls == [ pretend.call(send_email), ] assert send_email.delay.calls == [ pretend.call( 'Email Subject', 'Email Body', recipient=f"{stub_user.username} <{stub_user.email}>", ), ]
def test_password_change_email( self, pyramid_request, pyramid_config, monkeypatch): stub_user = pretend.stub( email='email', username='******', ) subject_renderer = pyramid_config.testing_add_renderer( 'email/password-change.subject.txt' ) subject_renderer.string_response = 'Email Subject' body_renderer = pyramid_config.testing_add_renderer( 'email/password-change.body.txt' ) body_renderer.string_response = 'Email Body' send_email = pretend.stub( delay=pretend.call_recorder(lambda *args, **kwargs: None) ) pyramid_request.task = pretend.call_recorder( lambda *args, **kwargs: send_email ) monkeypatch.setattr(email, 'send_email', send_email) result = email.send_password_change_email( pyramid_request, user=stub_user, ) assert result == { 'username': stub_user.username, } subject_renderer.assert_() body_renderer.assert_(username=stub_user.username) assert pyramid_request.task.calls == [ pretend.call(send_email), ] assert send_email.delay.calls == [ pretend.call( 'Email Body', 'Email Subject', recipients=[stub_user.email], ), ]
def test_password_change_email_unverified( self, pyramid_request, pyramid_config, monkeypatch ): stub_user = pretend.stub( username="******", name="", email="*****@*****.**", primary_email=pretend.stub(email="*****@*****.**", verified=False), ) subject_renderer = pyramid_config.testing_add_renderer( "email/password-change/subject.txt" ) subject_renderer.string_response = "Email Subject" body_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.txt" ) body_renderer.string_response = "Email Body" html_renderer = pyramid_config.testing_add_renderer( "email/password-change/body.html" ) html_renderer.string_response = "Email HTML Body" send_email = pretend.stub( delay=pretend.call_recorder(lambda *args, **kwargs: None) ) pyramid_request.task = pretend.call_recorder(lambda *args, **kwargs: send_email) monkeypatch.setattr(email, "send_email", send_email) result = email.send_password_change_email(pyramid_request, stub_user) assert result == {"username": stub_user.username} subject_renderer.assert_() body_renderer.assert_(username=stub_user.username) html_renderer.assert_(username=stub_user.username) assert pyramid_request.task.calls == [] assert send_email.delay.calls == []
def reset_password(request, _form_class=ResetPasswordForm): if request.authenticated_userid is not None: return HTTPSeeOther(request.route_path("index")) user_service = request.find_service(IUserService, context=None) breach_service = request.find_service(IPasswordBreachedService, context=None) token_service = request.find_service(ITokenService, name="password") def _error(message): request.session.flash(message, queue="error") return HTTPSeeOther(request.route_path("accounts.request-password-reset")) try: token = request.params.get("token") data = token_service.loads(token) except TokenExpired: return _error(request._("Expired token: request a new password reset link")) except TokenInvalid: return _error(request._("Invalid token: request a new password reset link")) except TokenMissing: return _error(request._("Invalid token: no token supplied")) # Check whether this token is being used correctly if data.get("action") != "password-reset": return _error(request._("Invalid token: not a password reset token")) # Check whether a user with the given user ID exists user = user_service.get_user(uuid.UUID(data.get("user.id"))) if user is None: return _error(request._("Invalid token: user not found")) # Check whether the user has logged in since the token was created last_login = data.get("user.last_login") if str(user.last_login) > last_login: # TODO: track and audit this, seems alertable return _error( request._( "Invalid token: user has logged in since this token was requested" ) ) # Check whether the password has been changed since the token was created password_date = data.get("user.password_date") if str(user.password_date) > password_date: return _error( request._( "Invalid token: password has already been changed since this " "token was requested" ) ) form = _form_class( **request.params, username=user.username, full_name=user.name, email=user.email, user_service=user_service, breach_service=breach_service, ) if request.method == "POST" and form.validate(): password_reset_limiter = request.find_service( IRateLimiter, name="password.reset" ) # Update password. user_service.update_user(user.id, password=form.new_password.data) user_service.record_event( user.id, tag="account:password:reset", ip_address=request.remote_addr ) password_reset_limiter.clear(user.id) # Send password change email send_password_change_email(request, user) # Flash a success message request.session.flash( request._("You have reset your password"), queue="success" ) # Redirect to account login. return HTTPSeeOther(request.route_path("accounts.login")) return {"form": form}