Merged in feature/mutable-metadata1 (pull request #221)
M1, M2 and M3 complete * M1, M2 and M3 complete * review changes * docs * docs
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
// Package queryapi: Milestone 3 handler for
|
||||
// POST /super-admin/documents/{id}/reset-metadata.
|
||||
//
|
||||
// This file is the M3-owned partition (see tracking §2.9). It must not
|
||||
// introduce new types into models.go or customschemas.go.
|
||||
package queryapi
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"queryorchestration/internal/cognitoauth"
|
||||
"queryorchestration/internal/customschema"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/oapi-codegen/nullable"
|
||||
openapi_types "github.com/oapi-codegen/runtime/types"
|
||||
)
|
||||
|
||||
// ResetDocumentMetadata is POST /super-admin/documents/{id}/reset-metadata.
|
||||
// It wipes the document's custom metadata history and clears the schema
|
||||
// binding in a single atomic transaction. The operation is idempotent;
|
||||
// already-clean documents return 200 with metadataVersionsDeleted: 0.
|
||||
// Restricted to super_admin (enforced by Permit.io middleware upstream).
|
||||
func (s *Controllers) ResetDocumentMetadata(ctx echo.Context, id openapi_types.UUID) error {
|
||||
actor, ok := cognitoauth.GetUserSubject(ctx)
|
||||
if !ok {
|
||||
return echo.NewHTTPError(http.StatusUnauthorized, "missing user subject")
|
||||
}
|
||||
|
||||
result, err := s.svc.CustomSchema.ResetDocumentMetadata(ctx.Request().Context(), uuid.UUID(id), actor)
|
||||
if err != nil {
|
||||
return mapResetError(err)
|
||||
}
|
||||
|
||||
resp := DocumentMetadataResetResponse{
|
||||
DocumentId: openapi_types.UUID(result.DocumentID),
|
||||
MetadataVersionsDeleted: int32(result.MetadataVersionsDeleted), //nolint:gosec // bounded by row count
|
||||
ResetAt: result.ResetAt,
|
||||
ResetBy: result.ResetBy,
|
||||
}
|
||||
if result.PreviousSchemaID != nil {
|
||||
resp.PreviousSchemaId = nullable.NewNullableWithValue(openapi_types.UUID(*result.PreviousSchemaID))
|
||||
} else {
|
||||
resp.PreviousSchemaId = nullable.NewNullNullable[openapi_types.UUID]()
|
||||
}
|
||||
if result.PreviousSchemaName != nil {
|
||||
resp.PreviousSchemaName = nullable.NewNullableWithValue(*result.PreviousSchemaName)
|
||||
} else {
|
||||
resp.PreviousSchemaName = nullable.NewNullNullable[string]()
|
||||
}
|
||||
if result.PreviousSchemaVersion != nil {
|
||||
resp.PreviousSchemaVersion = nullable.NewNullableWithValue(int32(*result.PreviousSchemaVersion)) //nolint:gosec // schema version is a small counter
|
||||
} else {
|
||||
resp.PreviousSchemaVersion = nullable.NewNullNullable[int32]()
|
||||
}
|
||||
return ctx.JSON(http.StatusOK, resp)
|
||||
}
|
||||
|
||||
// mapResetError converts reset-specific service sentinels to HTTP errors.
|
||||
// Errors not recognized here are treated as unexpected server failures.
|
||||
func mapResetError(err error) error {
|
||||
switch {
|
||||
case errors.Is(err, customschema.ErrDocumentNotFound):
|
||||
return echo.NewHTTPError(http.StatusNotFound, "document not found")
|
||||
case errors.Is(err, customschema.ErrMutualExclusivityViolation):
|
||||
return echo.NewHTTPError(http.StatusConflict, err.Error())
|
||||
default:
|
||||
slog.Error("reset document metadata: unexpected error", "error", err)
|
||||
return echo.NewHTTPError(http.StatusInternalServerError, "internal server error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user