2037359e8d
Fusion-Task-Id: FN-011 Fusion-Task-Lineage: 4a9aca6f-9d91-43aa-8d2a-d59657c1541a
57 lines
1.6 KiB
Python
57 lines
1.6 KiB
Python
"""Credential models and storage interface.
|
|
|
|
Security rules:
|
|
- No plaintext ``private_key`` or ``token`` fields exist on any model class.
|
|
- The ``encrypted_payload`` field is opaque bytes encoded as a string.
|
|
"""
|
|
|
|
import abc
|
|
import uuid
|
|
from datetime import datetime, timezone
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field
|
|
|
|
from app.git.types import CredentialKind
|
|
|
|
|
|
class GitCredential(BaseModel):
|
|
"""Base credential model.
|
|
|
|
Never stores plaintext secrets. The ``encrypted_payload`` field holds
|
|
opaque encrypted data.
|
|
"""
|
|
|
|
model_config = ConfigDict(extra="forbid")
|
|
|
|
id: uuid.UUID = Field(default_factory=uuid.uuid4)
|
|
kind: CredentialKind
|
|
encrypted_payload: str = Field(repr=False)
|
|
created_at: datetime = Field(
|
|
default_factory=lambda: datetime.now(timezone.utc)
|
|
)
|
|
updated_at: datetime = Field(
|
|
default_factory=lambda: datetime.now(timezone.utc)
|
|
)
|
|
|
|
|
|
class AccessTokenCredential(GitCredential):
|
|
"""Access-token credential discriminated by ``kind``."""
|
|
|
|
kind: CredentialKind = CredentialKind.access_token
|
|
|
|
|
|
class CredentialStorage(abc.ABC):
|
|
"""Abstract storage backend for :class:`GitCredential` records."""
|
|
|
|
@abc.abstractmethod
|
|
def create(self, credential: GitCredential) -> uuid.UUID:
|
|
"""Persist *credential* and return its ID."""
|
|
|
|
@abc.abstractmethod
|
|
def get(self, credential_id: uuid.UUID) -> GitCredential | None:
|
|
"""Retrieve a credential by ID, or ``None`` if not found."""
|
|
|
|
@abc.abstractmethod
|
|
def delete(self, credential_id: uuid.UUID) -> None:
|
|
"""Remove a credential by ID."""
|