API key come hash SHA-256, una per sessione, TTL rinnovabile (#41)

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 11:31:29 +02:00
parent 1d93eded27
commit 35f46926a9
14 changed files with 343 additions and 110 deletions
+2
View File
@@ -1,5 +1,6 @@
"""SQLAlchemy models for TieMeasureFlow."""
from src.backend.models.orm.user import User
from src.backend.models.orm.api_key import ApiKey
from src.backend.models.orm.recipe import Recipe, RecipeVersion
from src.backend.models.orm.task import RecipeTask, RecipeSubtask
from src.backend.models.orm.measurement import Measurement
@@ -11,6 +12,7 @@ from src.backend.models.orm.vision import VisionReferenceImage, VisionResult
__all__ = [
"User",
"ApiKey",
"Recipe",
"RecipeVersion",
"RecipeTask",
+25
View File
@@ -0,0 +1,25 @@
"""API key sessions: one row per login, stored as a SHA-256 hash."""
from datetime import datetime
from typing import Optional
from sqlalchemy import DateTime, ForeignKey, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
from src.backend.database import Base
class ApiKey(Base):
"""One API key per login session.
Only the SHA-256 hex digest is stored, never the key. Dates are naive UTC.
"""
__tablename__ = "api_keys"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(
Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True
)
key_hash: Mapped[str] = mapped_column(String(64), nullable=False, unique=True, index=True)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
expires_at: Mapped[datetime] = mapped_column(DateTime, nullable=False)
last_used_at: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True)
-1
View File
@@ -32,7 +32,6 @@ class User(Base):
# Status
active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
api_key: Mapped[Optional[str]] = mapped_column(String(64), unique=True, nullable=True, index=True)
# Timestamps
created_at: Mapped[datetime] = mapped_column(