Пример #1
0
    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 == []
Пример #2
0
    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}
Пример #3
0
    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}>",
            )
        ]
Пример #4
0
    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}
Пример #5
0
    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}
Пример #6
0
    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,
        }
Пример #7
0
    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"
                        ),
                    )
                ),
            )
        ]
Пример #8
0
    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"),
                    )),
            )
        ]
Пример #9
0
    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}>",
            ),
        ]
Пример #10
0
    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],
            ),
        ]
Пример #11
0
    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 == []
Пример #12
0
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}