Files
sshecret/packages/sshecret-backend/src/sshecret_backend/view_models.py

170 lines
4.3 KiB
Python

"""Models for API views."""
import uuid
from datetime import datetime
from typing import Annotated, Self, override
from sqlmodel import Field, SQLModel
from pydantic import AfterValidator, IPvAnyAddress, IPvAnyNetwork
from sshecret.crypto import public_key_validator
from . import models
class ClientView(SQLModel):
"""View for a single client."""
id: uuid.UUID
name: str
description: str | None = None
public_key: str
policies: list[str] = ["0.0.0.0/0", "::/0"]
secrets: list[str] = Field(default_factory=list)
created_at: datetime | None
updated_at: datetime | None = None
@classmethod
def from_client_list(cls, clients: list[models.Client]) -> list[Self]:
"""Generate a list of responses from a list of clients."""
responses: list[Self] = [cls.from_client(client) for client in clients]
return responses
@classmethod
def from_client(cls, client: models.Client) -> Self:
"""Instantiate from a client."""
view = cls(
id=client.id,
name=client.name,
description=client.description,
public_key=client.public_key,
created_at=client.created_at,
updated_at=client.updated_at or None,
)
if client.secrets:
view.secrets = [secret.name for secret in client.secrets]
if client.policies:
view.policies = [policy.source for policy in client.policies]
return view
class ClientQueryResult(SQLModel):
"""Result class for queries towards the client list."""
clients: list[ClientView] = Field(default_factory=list)
total_results: int
remaining_results: int
class ClientCreate(SQLModel):
"""Model to create a client."""
name: str
description: str | None = None
public_key: Annotated[str, AfterValidator(public_key_validator)]
def to_client(self) -> models.Client:
"""Instantiate a client."""
return models.Client(
name=self.name,
public_key=self.public_key,
description=self.description,
)
class ClientUpdate(SQLModel):
"""Model to update the client public key."""
public_key: Annotated[str, AfterValidator(public_key_validator)]
class BodyValue(SQLModel):
"""A generic model with just a value parameter."""
value: str
class ClientSecretPublic(SQLModel):
"""Public model to manage client secrets."""
name: str
secret: str
description: str | None = None
@classmethod
def from_client_secret(cls, client_secret: models.ClientSecret) -> Self:
"""Instantiate from ClientSecret."""
return cls(
name=client_secret.name,
secret=client_secret.secret,
description=client_secret.description,
)
class ClientSecretResponse(ClientSecretPublic):
"""A secret view."""
created_at: datetime | None
updated_at: datetime | None = None
@override
@classmethod
def from_client_secret(cls, client_secret: models.ClientSecret) -> Self:
"""Instantiate from ClientSecret."""
return cls(
name=client_secret.name,
secret=client_secret.secret,
created_at=client_secret.created_at,
updated_at=client_secret.updated_at,
)
class ClientPolicyView(SQLModel):
"""Update object for client policy."""
sources: list[str] = ["0.0.0.0/0", "::/0"]
@classmethod
def from_client(cls, client: models.Client) -> Self:
"""Create from client."""
if not client.policies:
return cls()
return cls(sources=[policy.source for policy in client.policies])
class ClientPolicyUpdate(SQLModel):
"""Model for updating policies."""
sources: list[IPvAnyAddress | IPvAnyNetwork]
class ClientSecretList(SQLModel):
"""Model for aggregating identically named secrets."""
name: str
clients: list[str]
class ClientReference(SQLModel):
"""Reference to a client."""
id: str
name: str
class ClientSecretDetailList(SQLModel):
"""A more detailed version of the ClientSecretList."""
name: str
ids: list[str] = Field(default_factory=list)
clients: list[ClientReference] = Field(default_factory=list)
class AuditInfo(SQLModel):
"""Information about audit information."""
entries: int