"""Tests for auth_service.""" from __future__ import annotations from pathlib import Path import aiosqlite import pytest from app.db import init_db from app.services import auth_service, setup_service @pytest.fixture async def db(tmp_path: Path) -> aiosqlite.Connection: # type: ignore[misc] """Provide an initialised DB with setup already complete.""" conn: aiosqlite.Connection = await aiosqlite.connect(str(tmp_path / "auth.db")) conn.row_factory = aiosqlite.Row await init_db(conn) # Pre-run setup so auth operations have a password hash to check. await setup_service.run_setup( conn, master_password="correctpassword1", database_path="bangui.db", fail2ban_socket="/var/run/fail2ban/fail2ban.sock", timezone="UTC", session_duration_minutes=60, ) yield conn await conn.close() class TestLogin: async def test_login_returns_session_on_correct_password( self, db: aiosqlite.Connection ) -> None: """login() returns a Session on the correct password.""" session = await auth_service.login(db, password="correctpassword1", session_duration_minutes=60) assert session.token assert len(session.token) == 64 # 32 bytes → 64 hex chars assert session.expires_at > session.created_at async def test_login_raises_on_wrong_password( self, db: aiosqlite.Connection ) -> None: """login() raises ValueError for an incorrect password.""" with pytest.raises(ValueError, match="Incorrect password"): await auth_service.login(db, password="wrongpassword", session_duration_minutes=60) async def test_login_persists_session(self, db: aiosqlite.Connection) -> None: """login() stores the session in the database.""" from app.repositories import session_repo session = await auth_service.login(db, password="correctpassword1", session_duration_minutes=60) stored = await session_repo.get_session(db, session.token) assert stored is not None assert stored.token == session.token class TestValidateSession: async def test_validate_returns_session_for_valid_token( self, db: aiosqlite.Connection ) -> None: """validate_session() returns the session for a valid token.""" session = await auth_service.login(db, password="correctpassword1", session_duration_minutes=60) validated = await auth_service.validate_session(db, session.token) assert validated.token == session.token async def test_validate_raises_for_unknown_token( self, db: aiosqlite.Connection ) -> None: """validate_session() raises ValueError for a non-existent token.""" with pytest.raises(ValueError, match="not found"): await auth_service.validate_session(db, "deadbeef" * 8) class TestLogout: async def test_logout_removes_session(self, db: aiosqlite.Connection) -> None: """logout() deletes the session so it can no longer be validated.""" from app.repositories import session_repo session = await auth_service.login(db, password="correctpassword1", session_duration_minutes=60) await auth_service.logout(db, session.token) stored = await session_repo.get_session(db, session.token) assert stored is None