示例#1
0
def test_user_login_get():
    app = pretend.stub(
        config=pretend.stub(),
        db=pretend.stub(
            accounts=pretend.stub(
                user_authenticate=pretend.stub(),
            ),
        ),
        templates=pretend.stub(
            get_template=pretend.call_recorder(
                lambda t: pretend.stub(render=lambda **ctx: ""),
            ),
        ),
        translations=None,
    )
    request = pretend.stub(
        method="GET",
        form=MultiDict(),
        values={},
        _session=Session({}, "1234", False),
    )

    resp = login(app, request)

    assert resp.status_code == 200
    assert app.templates.get_template.calls == [
        pretend.call("accounts/login.html"),
    ]
示例#2
0
    def test_post_validate_no_redirects(self, pyramid_request,
                                        pyramid_services, expected_next_url,
                                        observed_next_url):
        user_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: 1),
            update_user=lambda *a, **k: None,
        )
        breach_service = pretend.stub(
            check_password=lambda password, tags=None: False)

        pyramid_services.register_service(IUserService, None, user_service)
        pyramid_services.register_service(IPasswordBreachedService, None,
                                          breach_service)

        pyramid_request.method = "POST"
        pyramid_request.POST["next"] = expected_next_url

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
            password=pretend.stub(data="password"),
        )
        form_class = pretend.call_recorder(lambda d, **kw: form_obj)
        pyramid_request.route_path = pretend.call_recorder(
            lambda a: "/the-redirect")
        result = views.login(pyramid_request, _form_class=form_class)

        assert isinstance(result, HTTPSeeOther)
        assert result.headers["Location"] == observed_next_url
示例#3
0
    def test_post_invalid_returns_form(self, pyramid_request, next_url):
        user_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: user_service
        )
        pyramid_request.method = "POST"
        if next_url is not None:
            pyramid_request.POST["next"] = next_url
        form_obj = pretend.stub(validate=pretend.call_recorder(lambda: False))
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)
        assert pyramid_request.registry.datadog.increment.calls == [
            pretend.call('warehouse.authentication.start',
                         tags=['auth_method:login_form']),
            pretend.call('warehouse.authentication.failure',
                         tags=['auth_method:login_form']),
        ]

        assert result == {
            "form": form_obj,
            "redirect": {"field": "next", "data": next_url},
        }
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]
示例#4
0
 def test_redirect_authenticated_user(self):
     pyramid_request = pretend.stub(authenticated_userid=1)
     pyramid_request.route_path = pretend.call_recorder(
         lambda a: "/the-redirect")
     result = views.login(pyramid_request)
     assert isinstance(result, HTTPSeeOther)
     assert result.headers["Location"] == "/the-redirect"
示例#5
0
    def test_post_invalid_returns_form(self, pyramid_request, next_url):
        user_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: user_service)
        pyramid_request.method = "POST"
        if next_url is not None:
            pyramid_request.POST["next"] = next_url
        form_obj = pretend.stub(validate=pretend.call_recorder(lambda: False))
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert result == {
            "form": form_obj,
            "redirect": {
                "field": "next",
                "data": next_url
            },
        }
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]
示例#6
0
    def test_post_invalid_returns_form(self, pyramid_request, next_url):
        user_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: user_service
        )
        pyramid_request.method = "POST"
        if next_url is not None:
            pyramid_request.POST["next"] = next_url
        form_obj = pretend.stub(validate=pretend.call_recorder(lambda: False))
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)
        assert pyramid_request.registry.datadog.increment.calls == [
            pretend.call('warehouse.authentication.start',
                         tags=['auth_method:login_form']),
            pretend.call('warehouse.authentication.failure',
                         tags=['auth_method:login_form']),
        ]

        assert result == {
            "form": form_obj,
            "redirect": {"field": "next", "data": next_url},
        }
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]
示例#7
0
    def test_get_returns_form(self, pyramid_request, next_url):
        user_service = pretend.stub()
        breach_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context=None: {
                IUserService: user_service,
                IPasswordBreachedService: breach_service,
            }[iface])
        form_obj = pretend.stub()
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        if next_url is not None:
            pyramid_request.GET["next"] = next_url

        result = views.login(pyramid_request, _form_class=form_class)

        assert result == {
            "form": form_obj,
            "redirect": {
                "field": "next",
                "data": next_url
            },
        }
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
            pretend.call(IPasswordBreachedService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service)
        ]
示例#8
0
    def test_get_returns_form(self, pyramid_request, pyramid_services,
                              next_url):
        user_service = pretend.stub()
        breach_service = pretend.stub()

        pyramid_services.register_service(IUserService, None, user_service)
        pyramid_services.register_service(IPasswordBreachedService, None,
                                          breach_service)

        form_obj = pretend.stub()
        form_class = pretend.call_recorder(lambda d, **kw: form_obj)

        if next_url is not None:
            pyramid_request.GET["next"] = next_url

        result = views.login(pyramid_request, _form_class=form_class)

        assert result == {
            "form": form_obj,
            "redirect": {
                "field": "next",
                "data": next_url
            },
        }
        assert form_class.calls == [
            pretend.call(
                pyramid_request.POST,
                request=pyramid_request,
                user_service=user_service,
                breach_service=breach_service,
                check_password_metrics_tags=[
                    "method:auth", "auth_method:login_form"
                ],
            )
        ]
示例#9
0
def test_user_login_post_valid(app, form, values, session, location):
    app.db = pretend.stub(
        accounts=pretend.stub(
            get_user_id=lambda username: 9001,
            user_authenticate=lambda user, password: True,
        ),
    )

    request = pretend.stub(
        method="POST",
        form=MultiDict(form),
        host="example.com",
        values=values,
        url_adapter=pretend.stub(
            build=lambda *a, **kw: "/",
        ),
        _session=Session(session, "1234", False),
    )

    resp = login(app, request)

    assert request.session["user.id"] == 9001
    assert resp.status_code == 303
    assert resp.headers["Location"] == location
    assert resp.headers.getlist("Set-Cookie") == ["username=test; Path=/"]
示例#10
0
    def test_post_invalid_returns_form(self, pyramid_request, pyramid_services,
                                       metrics, next_url):
        user_service = pretend.stub()
        breach_service = pretend.stub()

        pyramid_services.register_service(IUserService, None, user_service)
        pyramid_services.register_service(IPasswordBreachedService, None,
                                          breach_service)

        pyramid_request.method = "POST"
        if next_url is not None:
            pyramid_request.POST["next"] = next_url
        form_obj = pretend.stub(validate=pretend.call_recorder(lambda: False))
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)
        assert metrics.increment.calls == [
            pretend.call("warehouse.authentication.start",
                         tags=["auth_method:login_form"]),
            pretend.call("warehouse.authentication.failure",
                         tags=["auth_method:login_form"]),
        ]

        assert result == {
            "form": form_obj,
            "redirect": {
                "field": "next",
                "data": next_url
            },
        }
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service)
        ]
        assert form_obj.validate.calls == [pretend.call()]
示例#11
0
    def test_post_validate_redirects(self, monkeypatch, pyramid_request,
                                     with_user):
        remember = pretend.call_recorder(
            lambda request, user_id: [("foo", "bar")]
        )
        monkeypatch.setattr(views, "remember", remember)

        new_session = {}

        login_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: 1),
        )
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: login_service
        )
        pyramid_request.method = "POST"
        pyramid_request.session = pretend.stub(
            items=lambda: [("a", "b"), ("foo", "bar")],
            update=new_session.update,
            invalidate=pretend.call_recorder(lambda: None),
            new_csrf_token=pretend.call_recorder(lambda: None),
        )

        pyramid_request.set_property(
            lambda r: 1234 if with_user else None,
            name="unauthenticated_userid",
        )

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
        )
        form_class = pretend.call_recorder(lambda d, login_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert isinstance(result, HTTPSeeOther)

        assert result.headers["Location"] == "/"
        assert result.headers["foo"] == "bar"

        assert form_class.calls == [
            pretend.call(pyramid_request.POST, login_service=login_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]

        assert login_service.find_userid.calls == [pretend.call("theuser")]

        if with_user:
            assert new_session == {}
        else:
            assert new_session == {"a": "b", "foo": "bar"}

        assert remember.calls == [pretend.call(pyramid_request, 1)]
        assert pyramid_request.session.invalidate.calls == [pretend.call()]
        assert pyramid_request.find_service.calls == [
            pretend.call(ILoginService, context=None),
        ]
        assert pyramid_request.session.new_csrf_token.calls == [pretend.call()]
示例#12
0
 def test_redirect_authenticated_user(self):
     pyramid_request = pretend.stub(authenticated_userid=1)
     pyramid_request.route_path = pretend.call_recorder(
         lambda a: '/the-redirect'
     )
     result = views.login(pyramid_request)
     assert isinstance(result, HTTPSeeOther)
     assert result.headers["Location"] == "/the-redirect"
示例#13
0
    def test_post_validate_redirects(self, monkeypatch, pyramid_request,
                                     with_user):
        remember = pretend.call_recorder(
            lambda request, user_id: [("foo", "bar")])
        monkeypatch.setattr(views, "remember", remember)

        new_session = {}

        login_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: 1), )
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: login_service)
        pyramid_request.method = "POST"
        pyramid_request.session = pretend.stub(
            items=lambda: [("a", "b"), ("foo", "bar")],
            update=new_session.update,
            invalidate=pretend.call_recorder(lambda: None),
            new_csrf_token=pretend.call_recorder(lambda: None),
        )

        pyramid_request.set_property(
            lambda r: 1234 if with_user else None,
            name="unauthenticated_userid",
        )

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
        )
        form_class = pretend.call_recorder(lambda d, login_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert isinstance(result, HTTPSeeOther)

        assert result.headers["Location"] == "/"
        assert result.headers["foo"] == "bar"

        assert form_class.calls == [
            pretend.call(pyramid_request.POST, login_service=login_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]

        assert login_service.find_userid.calls == [pretend.call("theuser")]

        if with_user:
            assert new_session == {}
        else:
            assert new_session == {"a": "b", "foo": "bar"}

        assert remember.calls == [pretend.call(pyramid_request, 1)]
        assert pyramid_request.session.invalidate.calls == [pretend.call()]
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
        ]
        assert pyramid_request.session.new_csrf_token.calls == [pretend.call()]
示例#14
0
    def test_get_returns_form(self, pyramid_request):
        login_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: login_service)
        form_obj = pretend.stub()
        form_class = pretend.call_recorder(lambda d, login_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert result == {"form": form_obj}
        assert pyramid_request.find_service.calls == [
            pretend.call(ILoginService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, login_service=login_service),
        ]
示例#15
0
    def test_get_returns_form(self, pyramid_request):
        login_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: login_service
        )
        form_obj = pretend.stub()
        form_class = pretend.call_recorder(lambda d, login_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert result == {"form": form_obj}
        assert pyramid_request.find_service.calls == [
            pretend.call(ILoginService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, login_service=login_service),
        ]
示例#16
0
def test_user_login_get(app):
    app.db = pretend.stub(accounts=pretend.stub(
        user_authenticate=pretend.stub(), ), )

    request = pretend.stub(
        method="GET",
        form=MultiDict(),
        values={},
        _session=Session({}, "1234", False),
    )

    resp = login(app, request)

    assert resp.status_code == 200
    assert resp.response.context == {
        "form": mock.ANY,
        "next": None,
    }
示例#17
0
    def test_post_validate_no_redirects(self, pyramid_request,
                                        expected_next_url, observed_next_url):
        login_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: 1), )
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: login_service)
        pyramid_request.method = "POST"
        pyramid_request.POST["next"] = expected_next_url

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
        )
        form_class = pretend.call_recorder(lambda d, login_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert isinstance(result, HTTPSeeOther)

        assert result.headers["Location"] == observed_next_url
示例#18
0
def test_user_login_get(app):
    app.db = pretend.stub(
        accounts=pretend.stub(
            user_authenticate=pretend.stub(),
        ),
    )

    request = pretend.stub(
        method="GET",
        form=MultiDict(),
        values={},
        _session=Session({}, "1234", False),
    )

    resp = login(app, request)

    assert resp.status_code == 200
    assert resp.response.context == {
        "form": mock.ANY,
        "next": None,
    }
示例#19
0
def test_user_login_post_valid(app, form, values, session, location):
    app.db = pretend.stub(accounts=pretend.stub(
        get_user_id=lambda username: 9001,
        user_authenticate=lambda user, password: True,
    ), )

    request = pretend.stub(
        method="POST",
        form=MultiDict(form),
        host="example.com",
        values=values,
        url_adapter=pretend.stub(build=lambda *a, **kw: "/",
                                 ),
        _session=Session(session, "1234", False),
    )

    resp = login(app, request)

    assert request.session["user.id"] == 9001
    assert resp.status_code == 303
    assert resp.headers["Location"] == location
    assert resp.headers.getlist("Set-Cookie") == ["username=test; Path=/"]
示例#20
0
    def test_post_validate_no_redirects(self, pyramid_request,
                                        expected_next_url, observed_next_url):
        login_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: 1),
        )
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: login_service
        )
        pyramid_request.method = "POST"
        pyramid_request.POST["next"] = expected_next_url

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
        )
        form_class = pretend.call_recorder(lambda d, login_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert isinstance(result, HTTPSeeOther)

        assert result.headers["Location"] == observed_next_url
示例#21
0
    def test_get_returns_form(self, pyramid_request, next_url):
        login_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: login_service
        )
        form_obj = pretend.stub()
        form_class = pretend.call_recorder(lambda d, login_service: form_obj)

        if next_url is not None:
            pyramid_request.GET["next"] = next_url

        result = views.login(pyramid_request, _form_class=form_class)

        assert result == {
            "form": form_obj,
            "redirect": {"field": "next", "data": next_url},
        }
        assert pyramid_request.find_service.calls == [
            pretend.call(ILoginService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, login_service=login_service),
        ]
示例#22
0
    def test_post_invalid_returns_form(self, pyramid_request, next_url):
        user_service = pretend.stub()
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: user_service
        )
        pyramid_request.method = "POST"
        if next_url is not None:
            pyramid_request.POST["next"] = next_url
        form_obj = pretend.stub(validate=pretend.call_recorder(lambda: False))
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        result = views.login(pyramid_request, _form_class=form_class)

        assert result == {
            "form": form_obj,
            "redirect": {"field": "next", "data": next_url},
        }
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
        ]
        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]
示例#23
0
    def test_post_validate_redirects(self, monkeypatch, pyramid_request,
                                     with_user):
        remember = pretend.call_recorder(
            lambda request, user_id: [("foo", "bar")]
        )
        monkeypatch.setattr(views, "remember", remember)

        new_session = {}

        user_id = uuid.uuid4()
        user_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: user_id),
            update_user=pretend.call_recorder(lambda *a, **kw: None),
        )
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: user_service
        )
        pyramid_request.method = "POST"
        pyramid_request.session = pretend.stub(
            items=lambda: [("a", "b"), ("foo", "bar")],
            update=new_session.update,
            invalidate=pretend.call_recorder(lambda: None),
            new_csrf_token=pretend.call_recorder(lambda: None),
        )

        pyramid_request.set_property(
            lambda r: str(uuid.uuid4()) if with_user else None,
            name="unauthenticated_userid",
        )

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
        )
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        pyramid_request.route_path = pretend.call_recorder(
            lambda a: '/the-redirect'
        )

        now = datetime.datetime.utcnow()

        with freezegun.freeze_time(now):
            result = views.login(pyramid_request, _form_class=form_class)

        assert pyramid_request.registry.datadog.increment.calls == [
            pretend.call('warehouse.authentication.start',
                         tags=['auth_method:login_form']),
            pretend.call('warehouse.authentication.complete',
                         tags=['auth_method:login_form']),
        ]

        assert isinstance(result, HTTPSeeOther)
        assert pyramid_request.route_path.calls == [
            pretend.call('manage.projects')
        ]
        assert result.headers["Location"] == "/the-redirect"
        assert result.headers["foo"] == "bar"

        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]

        assert user_service.find_userid.calls == [pretend.call("theuser")]
        assert user_service.update_user.calls == [
            pretend.call(user_id, last_login=now),
        ]

        if with_user:
            assert new_session == {}
        else:
            assert new_session == {"a": "b", "foo": "bar"}

        assert remember.calls == [pretend.call(pyramid_request, str(user_id))]
        assert pyramid_request.session.invalidate.calls == [pretend.call()]
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
            pretend.call(IUserService, context=None),
        ]
        assert pyramid_request.session.new_csrf_token.calls == [pretend.call()]
示例#24
0
    def test_post_validate_redirects(self, monkeypatch, pyramid_request,
                                     with_user):
        remember = pretend.call_recorder(
            lambda request, user_id: [("foo", "bar")]
        )
        monkeypatch.setattr(views, "remember", remember)

        new_session = {}

        user_id = uuid.uuid4()
        user_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: user_id),
            update_user=pretend.call_recorder(lambda *a, **kw: None),
        )
        pyramid_request.find_service = pretend.call_recorder(
            lambda iface, context: user_service
        )
        pyramid_request.method = "POST"
        pyramid_request.session = pretend.stub(
            items=lambda: [("a", "b"), ("foo", "bar")],
            update=new_session.update,
            invalidate=pretend.call_recorder(lambda: None),
            new_csrf_token=pretend.call_recorder(lambda: None),
        )

        pyramid_request.set_property(
            lambda r: str(uuid.uuid4()) if with_user else None,
            name="unauthenticated_userid",
        )

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
        )
        form_class = pretend.call_recorder(lambda d, user_service: form_obj)

        pyramid_request.route_path = pretend.call_recorder(
            lambda a: '/the-redirect'
        )

        now = datetime.datetime.utcnow()

        with freezegun.freeze_time(now):
            result = views.login(pyramid_request, _form_class=form_class)

        assert isinstance(result, HTTPSeeOther)
        assert pyramid_request.route_path.calls == [
            pretend.call('manage.projects')
        ]
        assert result.headers["Location"] == "/the-redirect"
        assert result.headers["foo"] == "bar"

        assert form_class.calls == [
            pretend.call(pyramid_request.POST, user_service=user_service),
        ]
        assert form_obj.validate.calls == [pretend.call()]

        assert user_service.find_userid.calls == [pretend.call("theuser")]
        assert user_service.update_user.calls == [
            pretend.call(user_id, last_login=now),
        ]

        if with_user:
            assert new_session == {}
        else:
            assert new_session == {"a": "b", "foo": "bar"}

        assert remember.calls == [pretend.call(pyramid_request, str(user_id))]
        assert pyramid_request.session.invalidate.calls == [pretend.call()]
        assert pyramid_request.find_service.calls == [
            pretend.call(IUserService, context=None),
            pretend.call(IUserService, context=None),
        ]
        assert pyramid_request.session.new_csrf_token.calls == [pretend.call()]
示例#25
0
    def test_post_validate_redirects(self, monkeypatch, pyramid_request,
                                     pyramid_services, metrics, with_user):
        remember = pretend.call_recorder(
            lambda request, user_id: [("foo", "bar")])
        monkeypatch.setattr(views, "remember", remember)

        new_session = {}

        user_id = uuid.uuid4()
        user_service = pretend.stub(
            find_userid=pretend.call_recorder(lambda username: user_id),
            update_user=pretend.call_recorder(lambda *a, **kw: None),
        )
        breach_service = pretend.stub(
            check_password=lambda password, tags=None: False)

        pyramid_services.register_service(IUserService, None, user_service)
        pyramid_services.register_service(IPasswordBreachedService, None,
                                          breach_service)

        pyramid_request.method = "POST"
        pyramid_request.session = pretend.stub(
            items=lambda: [("a", "b"), ("foo", "bar")],
            update=new_session.update,
            invalidate=pretend.call_recorder(lambda: None),
            new_csrf_token=pretend.call_recorder(lambda: None),
        )

        pyramid_request.set_property(
            lambda r: str(uuid.uuid4()) if with_user else None,
            name="unauthenticated_userid",
        )

        form_obj = pretend.stub(
            validate=pretend.call_recorder(lambda: True),
            username=pretend.stub(data="theuser"),
            password=pretend.stub(data="password"),
        )
        form_class = pretend.call_recorder(lambda d, **kw: form_obj)

        pyramid_request.route_path = pretend.call_recorder(
            lambda a: "/the-redirect")

        now = datetime.datetime.utcnow()

        with freezegun.freeze_time(now):
            result = views.login(pyramid_request, _form_class=form_class)

        assert metrics.increment.calls == []

        assert isinstance(result, HTTPSeeOther)
        assert pyramid_request.route_path.calls == [
            pretend.call("manage.projects")
        ]
        assert result.headers["Location"] == "/the-redirect"
        assert result.headers["foo"] == "bar"

        assert form_class.calls == [
            pretend.call(
                pyramid_request.POST,
                request=pyramid_request,
                user_service=user_service,
                breach_service=breach_service,
                check_password_metrics_tags=[
                    "method:auth", "auth_method:login_form"
                ],
            )
        ]
        assert form_obj.validate.calls == [pretend.call()]

        assert user_service.find_userid.calls == [pretend.call("theuser")]
        assert user_service.update_user.calls == [
            pretend.call(user_id, last_login=now)
        ]

        if with_user:
            assert new_session == {}
        else:
            assert new_session == {"a": "b", "foo": "bar"}

        assert remember.calls == [pretend.call(pyramid_request, str(user_id))]
        assert pyramid_request.session.invalidate.calls == [pretend.call()]
        assert pyramid_request.session.new_csrf_token.calls == [pretend.call()]