Complete backend

This commit is contained in:
2025-04-18 16:39:05 +02:00
parent 83551ffb4a
commit ec90fb7680
11 changed files with 561 additions and 121 deletions

View File

@ -1,8 +1,15 @@
#!/usr/bin/env python3
"""Database models.
TODO:
We might want to pass on audit information from the SSH server.
This might require some changes to these schemas.
"""
import uuid
from datetime import datetime
from sqlalchemy import Engine, Column, DateTime, func
import sqlalchemy as sa
from sqlmodel import Field, Relationship, SQLModel
@ -11,22 +18,48 @@ class Client(SQLModel, table=True):
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
name: str = Field(unique=True)
fingerprint: str
created_at: datetime = Field(
public_key: str
created_at: datetime | None = Field(
default=None,
sa_column=Column(
DateTime(timezone=True), server_default=func.now(), nullable=True
),
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"server_default": sa.func.now()},
nullable=False,
)
updated_at: datetime | None = Field(
default=None,
sa_column=Column(DateTime(timezone=True), onupdate=func.now(), nullable=True),
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"onupdate": sa.func.now(), "server_default": sa.func.now()},
)
secrets: list["ClientSecret"] = Relationship(
back_populates="client", passive_deletes="all"
)
policies: list["ClientAccessPolicy"] = Relationship(back_populates="client")
class ClientAccessPolicy(SQLModel, table=True):
"""Client access policies."""
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
source: str
client_id: uuid.UUID | None = Field(foreign_key="client.id", ondelete="CASCADE")
client: Client | None = Relationship(back_populates="policies")
created_at: datetime | None = Field(
default=None,
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"server_default": sa.func.now()},
nullable=False,
)
updated_at: datetime | None = Field(
default=None,
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"onupdate": sa.func.now(), "server_default": sa.func.now()},
)
class ClientSecret(SQLModel, table=True):
"""A client secret."""
@ -37,15 +70,17 @@ class ClientSecret(SQLModel, table=True):
client: Client | None = Relationship(back_populates="secrets")
secret: str
invalidated: bool = Field(default=False)
created_at: datetime = Field(
created_at: datetime | None = Field(
default=None,
sa_column=Column(
DateTime(timezone=True), server_default=func.now(), nullable=True
),
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"server_default": sa.func.now()},
nullable=False,
)
updated_at: datetime | None = Field(
default=None,
sa_column=Column(DateTime(timezone=True), onupdate=func.now(), nullable=True),
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"onupdate": sa.func.now(), "server_default": sa.func.now()},
)
@ -64,28 +99,27 @@ class AuditLog(SQLModel, table=True):
client_name: str | None = None
message: str
origin: str | None = None
timestamp: datetime | None = Field(
default=None,
sa_column=Column(
DateTime(timezone=True), server_default=func.now(), nullable=True
),
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"server_default": sa.func.now()},
nullable=False,
)
class APIClient(SQLModel, table=True):
"""Stores API Keys."""
id: uuid.UUID = Field(default_factory=uuid.uuid4, primary_key=True)
token: str
read_write: bool
created_at: datetime = Field(
created_at: datetime | None = Field(
default=None,
sa_column=Column(
DateTime(timezone=True), server_default=func.now(), nullable=True
),
sa_type=sa.DateTime(timezone=True),
sa_column_kwargs={"server_default": sa.func.now()},
nullable=False,
)
def init_db(engine: Engine) -> None:
def init_db(engine: sa.Engine) -> None:
"""Create database."""
SQLModel.metadata.create_all(engine)