a6e1cb4f87
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
64 lines
2.2 KiB
Python
64 lines
2.2 KiB
Python
# tests/test_operator_session.py
|
|
import time
|
|
import uuid
|
|
from datetime import datetime, timedelta
|
|
from types import SimpleNamespace
|
|
|
|
from backend.models import OperatorUser
|
|
from backend.operator_auth import (
|
|
make_operator_cookie, current_operator, COOKIE_NAME,
|
|
)
|
|
|
|
|
|
def _make_user(db, **kw):
|
|
u = OperatorUser(id=str(uuid.uuid4()), email=kw.pop("email", "u@x.com"),
|
|
display_name="U", password_hash="h", role=kw.pop("role", "admin"), **kw)
|
|
db.add(u)
|
|
db.commit()
|
|
return u
|
|
|
|
|
|
def _req(cookie_value):
|
|
# current_operator only reads request.cookies — a stub is enough.
|
|
return SimpleNamespace(cookies={COOKIE_NAME: cookie_value} if cookie_value else {})
|
|
|
|
|
|
def test_valid_cookie_resolves_user(db_session):
|
|
u = _make_user(db_session)
|
|
cookie = make_operator_cookie(u.id)
|
|
assert current_operator(_req(cookie), db_session).id == u.id
|
|
|
|
|
|
def test_no_or_garbage_cookie_is_none(db_session):
|
|
assert current_operator(_req(None), db_session) is None
|
|
assert current_operator(_req("garbage"), db_session) is None
|
|
|
|
|
|
def test_inactive_user_is_none(db_session):
|
|
u = _make_user(db_session, active=False)
|
|
assert current_operator(_req(make_operator_cookie(u.id)), db_session) is None
|
|
|
|
|
|
def test_locked_user_is_none(db_session):
|
|
u = _make_user(db_session, locked_until=datetime.utcnow() + timedelta(minutes=5))
|
|
assert current_operator(_req(make_operator_cookie(u.id)), db_session) is None
|
|
|
|
|
|
def test_cookie_older_than_sessions_valid_from_is_none(db_session):
|
|
u = _make_user(db_session)
|
|
old_iat = int(time.time()) - 1000
|
|
cookie = make_operator_cookie(u.id, iat=old_iat)
|
|
u.sessions_valid_from = datetime.utcnow()
|
|
db_session.commit()
|
|
assert current_operator(_req(cookie), db_session) is None
|
|
|
|
|
|
def test_cookie_minted_with_matching_iat_after_bump_still_valid(db_session):
|
|
# Guards the change-password race: bump sessions_valid_from to the new cookie's
|
|
# exact iat → that fresh cookie must remain valid.
|
|
u = _make_user(db_session)
|
|
new_iat = int(time.time())
|
|
u.sessions_valid_from = datetime.utcfromtimestamp(new_iat)
|
|
db_session.commit()
|
|
assert current_operator(_req(make_operator_cookie(u.id, iat=new_iat)), db_session).id == u.id
|