feat(v2): enforce repository safety invariants
This commit is contained in:
@@ -3,6 +3,7 @@ import base64
|
||||
import hashlib
|
||||
from collections.abc import AsyncIterator
|
||||
from datetime import UTC, datetime
|
||||
from pathlib import Path
|
||||
from typing import Annotated, Any, cast
|
||||
|
||||
from fastapi import Depends, FastAPI, Header, Request, Response
|
||||
@@ -17,7 +18,7 @@ from backup_tool.cli import build_alembic_config
|
||||
from backup_tool.config import Settings
|
||||
from backup_tool.db.engine import SchemaNotCurrentError, assert_schema_current, create_engine
|
||||
from backup_tool.db.models import ApiToken, AuditEvent, IdempotencyRecord, Repository, Secret, User
|
||||
from backup_tool.repository import RepositoryError, initialize
|
||||
from backup_tool.repository import RepositoryError, initialize, inspect_repository
|
||||
from backup_tool.security.auth import (
|
||||
hash_password,
|
||||
hash_token,
|
||||
@@ -490,6 +491,26 @@ def create_app(settings: Settings) -> FastAPI:
|
||||
"encryption": repository.encryption,
|
||||
}
|
||||
|
||||
@app.get("/api/v2/repositories")
|
||||
async def list_repositories(
|
||||
db: Annotated[AsyncSession, Depends(session)],
|
||||
_: Annotated[tuple[User, set[str], bool], Depends(actor)],
|
||||
) -> dict[str, Any]:
|
||||
items = list((await db.scalars(select(Repository).order_by(Repository.name))).all())
|
||||
return {
|
||||
"items": [
|
||||
{
|
||||
"id": item.id,
|
||||
"name": item.name,
|
||||
"format_version": item.format_version,
|
||||
"compression": item.compression,
|
||||
"encryption": item.encryption,
|
||||
"state": item.state,
|
||||
}
|
||||
for item in items
|
||||
]
|
||||
}
|
||||
|
||||
@app.get("/api/v2/repositories/{repository_id}")
|
||||
async def get_repository(
|
||||
repository_id: str,
|
||||
@@ -508,6 +529,26 @@ def create_app(settings: Settings) -> FastAPI:
|
||||
"state": repository.state,
|
||||
}
|
||||
|
||||
@app.get("/api/v2/repositories/{repository_id}/inspection")
|
||||
async def inspect_repository_endpoint(
|
||||
repository_id: str,
|
||||
db: Annotated[AsyncSession, Depends(session)],
|
||||
_: Annotated[tuple[User, set[str], bool], Depends(actor)],
|
||||
) -> dict[str, Any]:
|
||||
repository = await db.get(Repository, repository_id)
|
||||
if repository is None:
|
||||
raise Problem(404, "resource_not_found", "Repository was not found.")
|
||||
try:
|
||||
inspected = inspect_repository(Path(repository.root))
|
||||
except RepositoryError as error:
|
||||
raise Problem(409, "repository_invalid", str(error)) from error
|
||||
return {
|
||||
"id": repository.id,
|
||||
"format_version": inspected.format_version,
|
||||
"compression": inspected.compression,
|
||||
"encryption": inspected.encryption,
|
||||
}
|
||||
|
||||
@app.patch("/api/v2/repositories/{repository_id}")
|
||||
async def patch_repository(
|
||||
repository_id: str,
|
||||
|
||||
Reference in New Issue
Block a user