100 lines
3.7 KiB
Python
100 lines
3.7 KiB
Python
|
|
from datetime import timedelta
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from django.core.exceptions import PermissionDenied, ValidationError
|
||
|
|
from django.utils import timezone
|
||
|
|
|
||
|
|
from intent.orgs import services
|
||
|
|
from intent.orgs.models import InviteStatus, OrgMembership, Role, validate_org_slug
|
||
|
|
|
||
|
|
|
||
|
|
def test_create_org_makes_creator_owner(owner, org):
|
||
|
|
assert org.memberships.get(user=owner).role == Role.OWNER
|
||
|
|
|
||
|
|
|
||
|
|
def test_staff_cannot_own_org(make_user):
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
services.create_org(slug="x", name="X", owner=make_user(is_staff=True))
|
||
|
|
|
||
|
|
|
||
|
|
def test_reserved_slug_rejected():
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
validate_org_slug("Admin")
|
||
|
|
|
||
|
|
|
||
|
|
def test_invite_requires_owner(collaborator, make_user, org):
|
||
|
|
with pytest.raises(PermissionDenied):
|
||
|
|
services.invite(org, collaborator, user=make_user())
|
||
|
|
|
||
|
|
|
||
|
|
def test_reinvite_replaces_pending_invite(owner, make_user, org):
|
||
|
|
invitee = make_user()
|
||
|
|
first, _ = services.invite(org, owner, user=invitee)
|
||
|
|
second, _ = services.invite(org, owner, user=invitee, role=Role.OWNER)
|
||
|
|
first.refresh_from_db()
|
||
|
|
assert first.status == InviteStatus.REVOKED
|
||
|
|
assert second.status == InviteStatus.PENDING
|
||
|
|
|
||
|
|
|
||
|
|
def test_cannot_invite_existing_member_or_staff(owner, collaborator, make_user, org):
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
services.invite(org, owner, user=collaborator)
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
services.invite(org, owner, email="COLE@example.com")
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
services.invite(org, owner, user=make_user(is_staff=True))
|
||
|
|
|
||
|
|
|
||
|
|
def test_accept_creates_membership_with_invited_role(owner, make_user, org):
|
||
|
|
invitee = make_user()
|
||
|
|
invite, _ = services.invite(org, owner, user=invitee, role=Role.OWNER)
|
||
|
|
services.accept_invite(invite, invitee)
|
||
|
|
assert org.memberships.get(user=invitee).role == Role.OWNER
|
||
|
|
invite.refresh_from_db()
|
||
|
|
assert invite.status == InviteStatus.ACCEPTED
|
||
|
|
assert invite.accepted_by == invitee
|
||
|
|
|
||
|
|
|
||
|
|
def test_expired_invite_cannot_be_accepted(owner, make_user, org):
|
||
|
|
invitee = make_user()
|
||
|
|
invite, _ = services.invite(org, owner, user=invitee)
|
||
|
|
invite.expires_at = timezone.now() - timedelta(seconds=1)
|
||
|
|
invite.save()
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
services.accept_invite(invite, invitee)
|
||
|
|
|
||
|
|
|
||
|
|
def test_email_invite_is_found_by_verified_email(owner, make_user, org):
|
||
|
|
invitee = make_user("ivy")
|
||
|
|
invite, _ = services.invite(org, owner, email="Ivy@Example.com")
|
||
|
|
assert list(services.open_invites_for(invitee)) == [invite]
|
||
|
|
assert services.is_addressed_to(invite, invitee)
|
||
|
|
assert not services.is_addressed_to(invite, make_user())
|
||
|
|
|
||
|
|
|
||
|
|
def test_last_owner_cannot_leave_or_be_demoted(owner, org):
|
||
|
|
membership = org.memberships.get(user=owner)
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
services.remove_member(membership, owner)
|
||
|
|
with pytest.raises(ValidationError):
|
||
|
|
services.update_membership(
|
||
|
|
membership, owner, role=Role.COLLABORATOR, can_create_projects=False
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def test_owner_can_step_down_once_another_owner_exists(owner, collaborator, org):
|
||
|
|
services.update_membership(
|
||
|
|
org.memberships.get(user=collaborator), owner, role=Role.OWNER, can_create_projects=False
|
||
|
|
)
|
||
|
|
services.remove_member(org.memberships.get(user=owner), owner)
|
||
|
|
assert not org.memberships.filter(user=owner).exists()
|
||
|
|
|
||
|
|
|
||
|
|
def test_member_can_leave_but_not_remove_others(owner, collaborator, make_user, org):
|
||
|
|
other = make_user()
|
||
|
|
OrgMembership.objects.create(org=org, user=other)
|
||
|
|
with pytest.raises(PermissionDenied):
|
||
|
|
services.remove_member(org.memberships.get(user=other), collaborator)
|
||
|
|
services.remove_member(org.memberships.get(user=collaborator), collaborator)
|
||
|
|
assert not org.memberships.filter(user=collaborator).exists()
|