43 lines
1.2 KiB
Python
43 lines
1.2 KiB
Python
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
|