"""Auth endpoint tests.""" from __future__ import annotations from datetime import UTC, datetime, timedelta import jwt from flask import Flask from flask.testing import FlaskClient from backend.app.models import User def test_login_success(client: FlaskClient, admin_user: User) -> None: resp = client.post( "/api/auth/login", json={"username": "admin1", "password": "adminpass1"} ) assert resp.status_code == 200 body = resp.get_json() assert "access_token" in body and body["access_token"] assert body["user"] == {"id": admin_user.id, "username": "admin1", "role": "admin"} def test_login_wrong_password(client: FlaskClient, admin_user: User) -> None: resp = client.post( "/api/auth/login", json={"username": "admin1", "password": "wrong"} ) assert resp.status_code == 401 assert resp.get_json() == {"error": "Invalid credentials"} def test_login_unknown_user(client: FlaskClient) -> None: resp = client.post( "/api/auth/login", json={"username": "ghost", "password": "anything!!"} ) assert resp.status_code == 401 # Generic message — must not leak whether username exists. assert resp.get_json() == {"error": "Invalid credentials"} def test_login_missing_fields(client: FlaskClient) -> None: resp = client.post("/api/auth/login", json={}) assert resp.status_code == 401 def test_me_requires_token(client: FlaskClient) -> None: resp = client.get("/api/auth/me") assert resp.status_code == 401 def test_me_returns_current_user( client: FlaskClient, admin_user: User, admin_token: str ) -> None: resp = client.get("/api/auth/me", headers={"Authorization": f"Bearer {admin_token}"}) assert resp.status_code == 200 body = resp.get_json() assert body["username"] == "admin1" assert body["role"] == "admin" assert "password_hash" not in body def test_me_with_invalid_token(client: FlaskClient) -> None: resp = client.get("/api/auth/me", headers={"Authorization": "Bearer not.a.jwt"}) assert resp.status_code == 401 def test_me_with_expired_token( app: Flask, client: FlaskClient, admin_user: User ) -> None: now = datetime.now(UTC) - timedelta(minutes=120) payload = { "sub": str(admin_user.id), "role": "admin", "iat": int(now.timestamp()), "exp": int((now + timedelta(minutes=1)).timestamp()), } token = jwt.encode( payload, app.config["JWT_SECRET"], algorithm=app.config["JWT_ALGORITHM"] ) resp = client.get("/api/auth/me", headers={"Authorization": f"Bearer {token}"}) assert resp.status_code == 401 assert resp.get_json() == {"error": "Token expired"} def test_logout_ok_with_token(client: FlaskClient, admin_token: str) -> None: resp = client.post( "/api/auth/logout", headers={"Authorization": f"Bearer {admin_token}"} ) assert resp.status_code == 200 def test_logout_without_token_is_401(client: FlaskClient) -> None: resp = client.post("/api/auth/logout") assert resp.status_code == 401