F-6 from t-paliad-074 architecture audit. The Gitea repo was renamed m/patholo → mAi/paliad → m/paliad, but go.mod still declared `mgit.msbls.de/m/patholo` and every internal import echoed the pre-rebrand name. Sweep: - go.mod: module path → mgit.msbls.de/m/paliad - All *.go files: imports rewritten via sed - README.md, docs/design-kanzlai-integration.md: mAi/paliad → m/paliad - Frontend issue-reference comments (mAi/paliad#N → m/paliad#N) in i18n.ts, theme.ts, sidebar.ts, app.ts, Sidebar.tsx, PWAHead.tsx, global.css Verified: go build/vet/test ./... clean, bun run build clean, no remaining mgit.msbls.de/m/patholo or mAi/paliad references outside docs that intentionally describe the rename history.
213 lines
5.3 KiB
Go
213 lines
5.3 KiB
Go
package handlers
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
|
|
"github.com/google/uuid"
|
|
|
|
"mgit.msbls.de/m/paliad/internal/services"
|
|
)
|
|
|
|
// GET /api/partner-units — list every PartnerUnit (readable by all
|
|
// authenticated users).
|
|
//
|
|
// `?include=members` returns each unit enriched with its lead's display
|
|
// name + email and the full members list. Used by the /team directory page
|
|
// so the frontend can render the "group by partner unit" view with one fetch.
|
|
func handleListPartnerUnits(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
if _, ok := requireUser(w, r); !ok {
|
|
return
|
|
}
|
|
if r.URL.Query().Get("include") == "members" {
|
|
rows, err := dbSvc.partnerUnit.ListWithMembers(r.Context())
|
|
if err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, rows)
|
|
return
|
|
}
|
|
rows, err := dbSvc.partnerUnit.List(r.Context())
|
|
if err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, rows)
|
|
}
|
|
|
|
// POST /api/partner-units — admin-only create.
|
|
func handleCreatePartnerUnit(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
uid, ok := requireUser(w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
var input services.CreatePartnerUnitInput
|
|
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON"})
|
|
return
|
|
}
|
|
d, err := dbSvc.partnerUnit.Create(r.Context(), uid, input)
|
|
if err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusCreated, d)
|
|
}
|
|
|
|
// GET /api/partner-units/{id}
|
|
func handleGetPartnerUnit(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
if _, ok := requireUser(w, r); !ok {
|
|
return
|
|
}
|
|
id, err := uuid.Parse(r.PathValue("id"))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
|
|
return
|
|
}
|
|
d, err := dbSvc.partnerUnit.GetByID(r.Context(), id)
|
|
if err != nil {
|
|
if errors.Is(err, sql.ErrNoRows) {
|
|
writeJSON(w, http.StatusNotFound, map[string]string{"error": "not found"})
|
|
return
|
|
}
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, d)
|
|
}
|
|
|
|
// PATCH /api/partner-units/{id} — admin-only.
|
|
func handleUpdatePartnerUnit(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
uid, ok := requireUser(w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
id, err := uuid.Parse(r.PathValue("id"))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
|
|
return
|
|
}
|
|
var input services.UpdatePartnerUnitInput
|
|
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON"})
|
|
return
|
|
}
|
|
d, err := dbSvc.partnerUnit.Update(r.Context(), uid, id, input)
|
|
if err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, d)
|
|
}
|
|
|
|
// DELETE /api/partner-units/{id} — admin-only.
|
|
func handleDeletePartnerUnit(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
uid, ok := requireUser(w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
id, err := uuid.Parse(r.PathValue("id"))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
|
|
return
|
|
}
|
|
if err := dbSvc.partnerUnit.Delete(r.Context(), uid, id); err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// GET /api/partner-units/{id}/members
|
|
func handleListPartnerUnitMembers(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
if _, ok := requireUser(w, r); !ok {
|
|
return
|
|
}
|
|
id, err := uuid.Parse(r.PathValue("id"))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
|
|
return
|
|
}
|
|
rows, err := dbSvc.partnerUnit.ListMembers(r.Context(), id)
|
|
if err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, rows)
|
|
}
|
|
|
|
// POST /api/partner-units/{id}/members — admin-only. Body: {"user_id": "<uuid>"}
|
|
func handleAddPartnerUnitMember(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
uid, ok := requireUser(w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
partnerUnitID, err := uuid.Parse(r.PathValue("id"))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid id"})
|
|
return
|
|
}
|
|
var body struct {
|
|
UserID uuid.UUID `json:"user_id"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid JSON"})
|
|
return
|
|
}
|
|
if err := dbSvc.partnerUnit.AddMember(r.Context(), uid, partnerUnitID, body.UserID); err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// DELETE /api/partner-units/{id}/members/{user_id} — admin-only.
|
|
func handleRemovePartnerUnitMember(w http.ResponseWriter, r *http.Request) {
|
|
if !requireDB(w) {
|
|
return
|
|
}
|
|
uid, ok := requireUser(w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
partnerUnitID, err := uuid.Parse(r.PathValue("id"))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid partner_unit id"})
|
|
return
|
|
}
|
|
userID, err := uuid.Parse(r.PathValue("user_id"))
|
|
if err != nil {
|
|
writeJSON(w, http.StatusBadRequest, map[string]string{"error": "invalid user id"})
|
|
return
|
|
}
|
|
if err := dbSvc.partnerUnit.RemoveMember(r.Context(), uid, partnerUnitID, userID); err != nil {
|
|
writeServiceError(w, err)
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|