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
4 changes: 4 additions & 0 deletions api/app/settings/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,10 @@
)

DISABLE_INVITE_LINKS = env.bool("DISABLE_INVITE_LINKS", False)
# Number of days after which a newly created invite link expires when no explicit
# expiry is provided. Defaults to None, which keeps the previous behaviour of
# links never expiring unless an expiry date is set explicitly.
INVITE_LINK_EXPIRY_DAYS = env.int("INVITE_LINK_EXPIRY_DAYS", default=None)
PREVENT_SIGNUP = env.bool("PREVENT_SIGNUP", default=False)
PREVENT_EMAIL_PASSWORD = env.bool("PREVENT_EMAIL_PASSWORD", default=False)
COOKIE_AUTH_ENABLED = env.bool("COOKIE_AUTH_ENABLED", default=False)
Expand Down
9 changes: 9 additions & 0 deletions api/organisations/invites/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import timedelta

from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.db import models
Expand Down Expand Up @@ -53,6 +55,13 @@ def validate_invite_links_are_enabled(self): # type: ignore[no-untyped-def]
if settings.DISABLE_INVITE_LINKS:
raise InviteLinksDisabledError()

@hook(BEFORE_CREATE)
def set_default_expiry(self) -> None:
if self.expires_at is None and settings.INVITE_LINK_EXPIRY_DAYS is not None:
self.expires_at = timezone.now() + timedelta(
days=settings.INVITE_LINK_EXPIRY_DAYS
)


class Invite(LifecycleModelMixin, AbstractBaseInviteModel): # type: ignore[misc]
email = models.EmailField()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,54 @@ def test_invite_link_is_expired__no_expiry_date__returns_false(
assert not is_expired


def test_create_invite_link__default_expiry_setting__sets_expires_at(
organisation: Organisation,
settings: "SettingsWrapper",
) -> None:
# Given
settings.INVITE_LINK_EXPIRY_DAYS = 7
before = timezone.now()

# When
invite_link = InviteLink.objects.create(organisation=organisation)

# Then
assert invite_link.expires_at is not None
expected = before + timedelta(days=7)
assert abs((invite_link.expires_at - expected).total_seconds()) < 60


def test_create_invite_link__no_default_expiry_setting__stays_indefinite(
organisation: Organisation,
settings: "SettingsWrapper",
) -> None:
# Given
settings.INVITE_LINK_EXPIRY_DAYS = None

# When
invite_link = InviteLink.objects.create(organisation=organisation)

# Then
assert invite_link.expires_at is None


def test_create_invite_link__explicit_expiry__not_overridden_by_default(
organisation: Organisation,
settings: "SettingsWrapper",
) -> None:
# Given
settings.INVITE_LINK_EXPIRY_DAYS = 7
explicit_expiry = timezone.now() + timedelta(days=1)

# When
invite_link = InviteLink.objects.create(
organisation=organisation, expires_at=explicit_expiry
)

# Then
assert invite_link.expires_at == explicit_expiry


@pytest.mark.django_db
def test_create_invite_link__invite_links_disabled__raises_error(
settings: "SettingsWrapper",
Expand Down
Loading