Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions dev/environment
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ TOKEN_PASSWORD_SECRET="an insecure password reset secret key"
TOKEN_EMAIL_SECRET="an insecure email verification secret key"
TOKEN_TWO_FACTOR_SECRET="an insecure two-factor auth secret key"
TOKEN_REMEMBER_DEVICE_SECRET="an insecure remember device auth secret key"
TOKEN_CONFIRM_LOGIN_SECRET="an insecure confirm login auth secret key"

WAREHOUSE_LEGACY_DOMAIN=pypi.python.org

Expand Down
10 changes: 10 additions & 0 deletions tests/common/db/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
TermsOfServiceEngagement,
User,
UserTermsOfServiceEngagement,
UserUniqueLogin,
)

from ...common.constants import REMOTE_ADDR
from .base import WarehouseFactory

fake = faker.Faker()
Expand Down Expand Up @@ -130,3 +132,11 @@ class Meta:
# TODO: Replace when factory_boy supports `unique`.
# See https://github.com/FactoryBoy/factory_boy/pull/997
name = factory.Sequence(lambda _: fake.unique.user_name())


class UserUniqueLoginFactory(WarehouseFactory):
class Meta:
model = UserUniqueLogin

user = factory.SubFactory(UserFactory)
ip_address = REMOTE_ADDR
6 changes: 5 additions & 1 deletion tests/functional/manage/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
from webob.multidict import MultiDict

from warehouse.accounts.interfaces import IPasswordBreachedService, IUserService
from warehouse.accounts.models import UniqueLoginStatus
from warehouse.manage import views
from warehouse.manage.views import organizations as org_views
from warehouse.organizations.interfaces import IOrganizationService
from warehouse.organizations.models import OrganizationType
from warehouse.utils.otp import _get_totp

from ...common.db.accounts import EmailFactory, UserFactory
from ...common.db.accounts import EmailFactory, UserFactory, UserUniqueLoginFactory


class TestManageAccount:
Expand Down Expand Up @@ -52,6 +53,9 @@ def test_changing_password_succeeds(self, webtest, socket_enabled):
with_terms_of_service_agreement=True,
clear_pwd="password",
)
UserUniqueLoginFactory.create(
user=user, ip_address="1.2.3.4", status=UniqueLoginStatus.CONFIRMED
)

# visit login page
login_page = webtest.get("/account/login/", status=HTTPStatus.OK)
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/accounts/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ def test_includeme(monkeypatch):
pretend.call(
TokenServiceFactory(name="two_factor"), ITokenService, name="two_factor"
),
pretend.call(
TokenServiceFactory(name="confirm_login"),
ITokenService,
name="confirm_login",
),
pretend.call(
TokenServiceFactory(name="remember_device"),
ITokenService,
Expand Down
20 changes: 19 additions & 1 deletion tests/unit/accounts/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@

from pyramid.authorization import Authenticated

from warehouse.accounts.models import Email, RecoveryCode, User, UserFactory, WebAuthn
from warehouse.accounts.models import (
Email,
RecoveryCode,
User,
UserFactory,
WebAuthn,
)
from warehouse.authnz import Permissions
from warehouse.utils.security_policy import principals_for

from ...common.db.accounts import (
EmailFactory as DBEmailFactory,
UserEventFactory as DBUserEventFactory,
UserFactory as DBUserFactory,
UserUniqueLoginFactory,
)
from ...common.db.packaging import (
ProjectFactory as DBProjectFactory,
Expand Down Expand Up @@ -309,3 +316,14 @@ def test_user_projects_is_ordered_by_name(self, db_session):
DBRoleFactory.create(project=project3, user=user)

assert user.projects == [project2, project3, project1]


class TestUserUniqueLogin:
def test_repr(self, db_session):
unique_login = UserUniqueLoginFactory.create()
assert (
repr(unique_login)
== f"<UserUniqueLogin(user={unique_login.user.username!r}, "
f"ip_address={unique_login.ip_address!r}, "
f"status={unique_login.status!r})>"
)
Loading