197 lines
5.5 KiB
Python
197 lines
5.5 KiB
Python
import datetime
|
|
|
|
import pytest
|
|
|
|
from app.model.models import (
|
|
AccessAuthorizationDB,
|
|
Card,
|
|
GroupDB,
|
|
OneShotAccess,
|
|
)
|
|
from app.services.door import checkAccess
|
|
|
|
|
|
def test_check_access_with_valid_oneshot(db_session):
|
|
# Setup: create card with valid access
|
|
group = GroupDB(name="Test Group")
|
|
db_session.add(group)
|
|
db_session.commit()
|
|
|
|
card = Card(
|
|
key="test-key-123",
|
|
group_id=group.id,
|
|
enabled=True,
|
|
name="test_card",
|
|
card_serial="00:00:00:00:00:00:00",
|
|
)
|
|
db_session.add(card)
|
|
|
|
oneshot = OneShotAccess(
|
|
uses=1, ends_at=datetime.datetime.now() + datetime.timedelta(days=1)
|
|
)
|
|
db_session.add(oneshot)
|
|
|
|
aa = AccessAuthorizationDB(name="Test AA", is_active=True, type="oneshot")
|
|
db_session.add(aa)
|
|
aa.oneshot = oneshot
|
|
group.accessauths = [aa]
|
|
|
|
db_session.commit()
|
|
|
|
# Test: access should be granted within time window
|
|
assert checkAccess("test-key-123", db_session)
|
|
assert aa.oneshot.uses == 0
|
|
|
|
|
|
def test_check_access_invalid_card(db_session):
|
|
# Should raise exception for non-existent card
|
|
with pytest.raises(Exception, match="No Access"):
|
|
checkAccess("non-existent-key", db_session)
|
|
|
|
|
|
def test_check_access_with_inactive_aa(db_session):
|
|
# Setup: create card with valid access
|
|
group = GroupDB(name="Test Group")
|
|
db_session.add(group)
|
|
db_session.commit()
|
|
|
|
card = Card(
|
|
key="test-key-123",
|
|
group_id=group.id,
|
|
enabled=True,
|
|
name="test_card",
|
|
card_serial="00:00:00:00:00:00:00",
|
|
)
|
|
db_session.add(card)
|
|
|
|
oneshot = OneShotAccess(
|
|
uses=1, ends_at=datetime.datetime.now() + datetime.timedelta(days=1)
|
|
)
|
|
db_session.add(oneshot)
|
|
aa = AccessAuthorizationDB(name="Test oneshot AA", is_active=False, type="oneshot")
|
|
db_session.add(aa)
|
|
aa.oneshot = oneshot
|
|
group.accessauths = [aa]
|
|
|
|
db_session.commit()
|
|
|
|
assert not checkAccess("test-key-123", db_session)
|
|
|
|
|
|
def test_check_access_with_inactive_card(db_session):
|
|
# Setup: create card with valid access
|
|
group = GroupDB(name="Test Group")
|
|
db_session.add(group)
|
|
db_session.commit()
|
|
|
|
card = Card(
|
|
key="test-key-123",
|
|
group_id=group.id,
|
|
enabled=False,
|
|
name="test_card",
|
|
card_serial="00:00:00:00:00:00:00",
|
|
)
|
|
db_session.add(card)
|
|
|
|
oneshot = OneShotAccess(
|
|
uses=1, ends_at=datetime.datetime.now() + datetime.timedelta(days=1)
|
|
)
|
|
db_session.add(oneshot)
|
|
aa = AccessAuthorizationDB(name="Test oneshot AA", is_active=True, type="oneshot")
|
|
db_session.add(aa)
|
|
aa.oneshot = oneshot
|
|
group.accessauths = [aa]
|
|
|
|
db_session.commit()
|
|
|
|
assert not checkAccess("test-key-123", db_session)
|
|
|
|
|
|
def test_regression_check_access_issue_28(db_session):
|
|
# Having a active aa after a inactive/invalid one denies access
|
|
group = GroupDB(name="Test Group")
|
|
db_session.add(group)
|
|
db_session.commit()
|
|
|
|
card = Card(
|
|
key="test-key-123",
|
|
group_id=group.id,
|
|
enabled=True,
|
|
name="test_card",
|
|
card_serial="00:00:00:00:00:00:00",
|
|
)
|
|
db_session.add(card)
|
|
|
|
# Creating oneshot with inactive AA
|
|
oneshot1 = OneShotAccess(
|
|
uses=1, ends_at=datetime.datetime.now() + datetime.timedelta(days=1)
|
|
)
|
|
db_session.add(oneshot1)
|
|
aa1 = AccessAuthorizationDB(name="First AA", is_active=False, type="oneshot")
|
|
db_session.add(aa1)
|
|
aa1.oneshot = oneshot1
|
|
|
|
# Creating oneshot with active AA
|
|
oneshot2 = OneShotAccess(
|
|
uses=1, ends_at=datetime.datetime.now() + datetime.timedelta(days=1)
|
|
)
|
|
db_session.add(oneshot2)
|
|
aa2 = AccessAuthorizationDB(name="Second AA", is_active=True, type="oneshot")
|
|
db_session.add(aa2)
|
|
aa2.oneshot = oneshot2
|
|
|
|
group.accessauths = [aa1, aa2]
|
|
|
|
db_session.commit()
|
|
|
|
assert checkAccess("test-key-123", db_session)
|
|
|
|
|
|
# Berlin's DST rules as a POSIX TZ string: +01:00 in winter, +02:00 in summer.
|
|
BERLIN_TZ = "CET-1CEST,M3.5.0,M10.5.0/3"
|
|
|
|
|
|
def _create_card_with_oneshot(db_session, ends_at):
|
|
"""Create a card whose only authorization is a oneshot ending at ends_at."""
|
|
group = GroupDB(name="Test Group")
|
|
db_session.add(group)
|
|
db_session.commit()
|
|
|
|
card = Card(
|
|
key="test-key-123",
|
|
group_id=group.id,
|
|
enabled=True,
|
|
name="test_card",
|
|
card_serial="00:00:00:00:00:00:00",
|
|
)
|
|
db_session.add(card)
|
|
|
|
oneshot = OneShotAccess(uses=1, ends_at=ends_at)
|
|
db_session.add(oneshot)
|
|
|
|
aa = AccessAuthorizationDB(name="Test AA", is_active=True, type="oneshot")
|
|
db_session.add(aa)
|
|
aa.oneshot = oneshot
|
|
group.accessauths = [aa]
|
|
|
|
db_session.commit()
|
|
|
|
|
|
@pytest.mark.parametrize("system_tz", [BERLIN_TZ], indirect=True)
|
|
def test_check_access_oneshot_end_time_is_compared_in_utc(db_session, system_tz):
|
|
"""A oneshot ending in 30 minutes is valid even though the local clock is
|
|
ahead of UTC: the stored end time is UTC and must not be read as local time."""
|
|
ends_at = datetime.datetime.now(datetime.UTC) + datetime.timedelta(minutes=30)
|
|
_create_card_with_oneshot(db_session, ends_at)
|
|
|
|
assert checkAccess("test-key-123", db_session)
|
|
|
|
|
|
@pytest.mark.parametrize("system_tz", [BERLIN_TZ], indirect=True)
|
|
def test_check_access_oneshot_expired(db_session, system_tz):
|
|
"""A oneshot that already ended must be rejected whatever the local clock is."""
|
|
ends_at = datetime.datetime.now(datetime.UTC) - datetime.timedelta(minutes=30)
|
|
_create_card_with_oneshot(db_session, ends_at)
|
|
|
|
assert not checkAccess("test-key-123", db_session)
|