Files
Imago/app/models/client.py
T
bruno 9bb440707c
CI / Lint & Format (push) Failing after 11s
CI / Tests (push) Has been skipped
CI / Security Scan (push) Failing after 8s
CI / Docker Build (push) Has been skipped
AI Vision: multi-provider config, model testing, per-client AI preferences
Backend:
- Add ai_provider + ai_model columns to APIClient model
- New admin_ai router: GET /admin/api/ai/status + POST /admin/api/ai/test
- Update ai_vision.py: provider_override + model_override support
- Update pipeline: load client AI prefs for image processing
- ClientUpdate/ClientResponse schemas include ai_provider/ai_model

Frontend:
- New AIConfigSection component: provider list, model dropdowns,
  test button with live results (no page refresh needed)
- AI types (ai.types.ts) + API (api/ai.ts)
- APIClient types extended with ai_provider/ai_model
2026-06-25 10:30:50 -04:00

75 lines
2.8 KiB
Python

"""
Modèle SQLAlchemy — APIClient : clients authentifiés du hub
"""
import enum
import uuid as uuid_lib
from datetime import datetime, timezone
from sqlalchemy import (
Column, String, JSON, Boolean, DateTime, Enum as SAEnum,
BigInteger, Integer,
)
from sqlalchemy.orm import relationship
from app.database import Base
class ClientPlan(str, enum.Enum):
FREE = "free"
STANDARD = "standard"
PREMIUM = "premium"
class APIClient(Base):
__tablename__ = "api_clients"
# ── Identité ──────────────────────────────────────────────
id = Column(
String(36),
primary_key=True,
default=lambda: str(uuid_lib.uuid4()),
index=True,
)
name = Column(String(256), nullable=False)
# ── Authentification ──────────────────────────────────────
api_key_hash = Column(String(64), nullable=False, unique=True, index=True)
# ── Permissions ───────────────────────────────────────────
scopes = Column(JSON, nullable=False, default=list)
plan = Column(
SAEnum(ClientPlan),
default=ClientPlan.FREE,
nullable=False,
)
is_active = Column(Boolean, default=True, nullable=False)
# ── Quota tracking ─────────────────────────────────────────
storage_used_bytes = Column(BigInteger, default=0, nullable=False)
quota_storage_mb = Column(Integer, default=500, nullable=False)
quota_images = Column(Integer, default=1000, nullable=False)
# ── AI Preferences (per-client provider/model override) ────
ai_provider = Column(String(64), nullable=True)
ai_model = Column(String(256), nullable=True)
# ── Timestamps ────────────────────────────────────────────
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
updated_at = Column(
DateTime(timezone=True),
default=lambda: datetime.now(timezone.utc),
onupdate=lambda: datetime.now(timezone.utc),
)
# ── Relations (ajoutée par Livrable 1.2) ──────────────────
images = relationship(
"Image",
back_populates="client",
cascade="all, delete-orphan",
)
def __repr__(self) -> str:
return f"<APIClient id={self.id} name={self.name} plan={self.plan}>"
def has_scope(self, scope: str) -> bool:
"""Vérifie si le client possède le scope demandé."""
return scope in (self.scopes or [])