17fc813823
M1, M2 and M3 complete * M1, M2 and M3 complete * review changes * docs * docs
75 lines
2.9 KiB
Go
75 lines
2.9 KiB
Go
// 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")
|
|
}
|
|
}
|