from __future__ import annotations import hashlib from typing import Optional from flask import current_app from itsdangerous import BadSignature, SignatureExpired, URLSafeTimedSerializer from .extensions import db from .models import User TOKEN_SALT = "fueltrack-api-access-token-v1" def _serializer() -> URLSafeTimedSerializer: return URLSafeTimedSerializer(current_app.config["SECRET_KEY"], salt=TOKEN_SALT) def _password_stamp(user: User) -> str: """Unieważnia token po zmianie hasła bez przechowywania tokenów w bazie.""" return hashlib.sha256(user.password_hash.encode("utf-8")).hexdigest()[:16] def create_access_token(user: User) -> str: return _serializer().dumps({"uid": user.id, "pwd": _password_stamp(user)}) def load_access_token(token: str) -> Optional[User]: try: payload = _serializer().loads( token, max_age=int(current_app.config["API_TOKEN_MAX_AGE_SECONDS"]), ) user = db.session.get(User, int(payload["uid"])) except (BadSignature, SignatureExpired, KeyError, TypeError, ValueError): return None if not user or not user.active: return None if payload.get("pwd") != _password_stamp(user): return None return user