""" User model definition """ from sqlalchemy import Column, String, Boolean, DateTime from sqlalchemy.sql import func import uuid from app.database import Base class User(Base): __tablename__ = 'users' id = Column(String, primary_key=True, default=lambda: str(uuid.uuid4())) username = Column(String(50), unique=True, nullable=False, index=True) email = Column(String, unique=True, nullable=True) # Nullable: OIDC-only users have no local password. Local accounts # still always have one. hashed_password = Column(String, nullable=True) role = Column(String, nullable=False, default='user') # 'admin' | 'user' is_active = Column(Boolean, default=True) created_at = Column(DateTime, server_default=func.now()) # Absolute path to this user's photo directory (e.g., "/photos/daniel") media_path = Column(String, nullable=False) # OIDC identity — populated when a user signs in via Authentik (or any # other OIDC provider later). `oidc_sub` is stable per provider, so # lookups key on (oidc_issuer, oidc_sub). NULL for password-only users. oidc_issuer = Column(String, nullable=True) oidc_sub = Column(String, nullable=True) # Profile bits that can come from OIDC claims or be filled in later. # avatar_url wins over Gravatar when set; the /auth/me response # computes the final avatar URL for the frontend. avatar_url = Column(String, nullable=True) display_name = Column(String, nullable=True) # Nextcloud integration. `nextcloud_username` defaults to the # `preferred_username` OIDC claim on first login but can be overridden # in Settings (the local mule-image username doesn't always match the # Nextcloud user — e.g. authentik `dtoro` ↔ Nextcloud `admin`). # `nextcloud_app_password_enc` is the user's Nextcloud app password # (created from Nextcloud → Settings → Security), Fernet-encrypted at # rest with a key derived from settings.secret_key. Used as HTTP Basic # auth on outgoing WebDAV calls when the user mutates a file under # their Nextcloud-rooted SourceRoot. nextcloud_username = Column(String, nullable=True, index=True) nextcloud_app_password_enc = Column(String, nullable=True)