## Copyright © 2026 Olaf Kolkman ## SPDX-License-Identifier: GPL-3.0-or-later from uuid import uuid4 from fastapi import APIRouter, HTTPException from pydantic import BaseModel from backend.app.database import get_connection, init_db from backend.app.services.auth_service import authenticate_user from backend.app.services.token_service import issue_token, revoke_token, validate_token router = APIRouter() init_db() class LoginRequest(BaseModel): username: str password: str @router.post('/login') def login(payload: LoginRequest): user = authenticate_user(payload.username, payload.password) if user is None: raise HTTPException(status_code=401, detail='Invalid username or password') token_data = issue_token(user['id'], user['username']) return { 'access_token': token_data['access_token'], 'token_type': 'bearer', 'expires_at': token_data['expires_at'], 'refresh_token': token_data['refresh_token'], 'user': {'id': user['id'], 'username': user['username'], 'email': user['email']} } @router.post('/logout') def logout(payload: dict): token = payload.get('token') if not token: raise HTTPException(status_code=400, detail='Token is required') revoked = revoke_token(token) if not revoked: raise HTTPException(status_code=404, detail='Token not found or already revoked') return {'status': 'logged_out'} @router.get('/me') def current_user(token: str): info = validate_token(token) if info is None: raise HTTPException(status_code=401, detail='Token expired or invalid') with get_connection() as conn: user = conn.execute('SELECT * FROM users WHERE id = ?', (info['user_id'],)).fetchone() if user is None: raise HTTPException(status_code=404, detail='User not found') return { 'id': user['id'], 'username': user['username'], 'email': user['email'], 'is_admin': bool(user['is_admin']), }