learn-platform-deploy/Backend/cmd/api/platform_admin.go

121 lines
3.2 KiB
Go

package main
import (
"errors"
"net/http"
"strings"
"github.com/go-chi/chi/v5"
)
func (a *app) platformAdminMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
claims, _ := r.Context().Value(userClaimsKey).(*accessClaims)
if claims == nil {
writeError(w, http.StatusUnauthorized, "no authenticated user")
return
}
if !hasAnyRole(claims, "admin", "platform_owner", "platform_admin") {
writeError(w, http.StatusForbidden, "platform admin role required")
return
}
next.ServeHTTP(w, r)
})
}
func (a *app) listTenants(w http.ResponseWriter, r *http.Request) {
docs, err := a.list("tenants", Doc{}, Sort{{Key: "name", Value: 1}})
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to list tenants")
return
}
writeJSON(w, http.StatusOK, docs)
}
func (a *app) createTenant(w http.ResponseWriter, r *http.Request) {
var payload map[string]any
if err := decodeJSON(r, &payload); err != nil {
writeError(w, http.StatusBadRequest, "invalid payload")
return
}
name := strings.TrimSpace(anyToString(payload["name"]))
if name == "" {
writeError(w, http.StatusBadRequest, "name is required")
return
}
payload["name"] = name
if slug := strings.TrimSpace(anyToString(payload["slug"])); slug != "" {
payload["slug"] = slugify(slug)
} else {
payload["slug"] = slugify(name)
}
doc, err := a.create("tenants", Doc(payload))
if err != nil {
writeError(w, http.StatusInternalServerError, "failed to create tenant")
return
}
writeJSON(w, http.StatusCreated, doc)
}
func (a *app) getTenant(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
doc, err := a.getByID("tenants", id)
if err != nil {
if errors.Is(err, ErrNotFound) {
writeError(w, http.StatusNotFound, "tenant not found")
return
}
writeError(w, http.StatusInternalServerError, "failed to load tenant")
return
}
writeJSON(w, http.StatusOK, doc)
}
func (a *app) patchTenant(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
var patch map[string]any
if err := decodeJSON(r, &patch); err != nil {
writeError(w, http.StatusBadRequest, "invalid patch payload")
return
}
if rawName, ok := patch["name"]; ok {
name := strings.TrimSpace(anyToString(rawName))
if name == "" {
writeError(w, http.StatusBadRequest, "name cannot be empty")
return
}
patch["name"] = name
}
if rawSlug, ok := patch["slug"]; ok {
slug := strings.TrimSpace(anyToString(rawSlug))
if slug == "" {
delete(patch, "slug")
} else {
patch["slug"] = slugify(slug)
}
}
doc, err := a.patch("tenants", id, Doc(patch))
if err != nil {
if errors.Is(err, ErrNotFound) {
writeError(w, http.StatusNotFound, "tenant not found")
return
}
writeError(w, http.StatusInternalServerError, "failed to update tenant")
return
}
writeJSON(w, http.StatusOK, doc)
}
func (a *app) deleteTenant(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
if err := a.deleteByID("tenants", id); err != nil {
if errors.Is(err, ErrNotFound) {
writeError(w, http.StatusNotFound, "tenant not found")
return
}
writeError(w, http.StatusInternalServerError, "failed to delete tenant")
return
}
w.WriteHeader(http.StatusNoContent)
}