package admin import ( "net/http" "strings" "github.com/go-chi/chi/v5" "github.com/ultisuite/ulti-backend/internal/api/apiresponse" "github.com/ultisuite/ulti-backend/internal/api/apivalidate" "github.com/ultisuite/ulti-backend/internal/api/drive" "github.com/ultisuite/ulti-backend/internal/api/middleware" ) func (h *Handler) registerDriveAdminRoutes(r chi.Router, read, write func(http.Handler) http.Handler) { r.With(read).Get("/drive/org-folders", h.ListDriveOrgFolders) r.With(write).Post("/drive/org-folders", h.CreateDriveOrgFolder) r.With(write).Put("/drive/org-folders/{folderID}", h.UpdateDriveOrgFolder) r.With(write).Delete("/drive/org-folders/{folderID}", h.DeleteDriveOrgFolder) r.With(write).Post("/drive/org-folders/sync", h.SyncDriveOrgFolders) h.registerDriveOrgMountRoutes(r, read, write) } func (h *Handler) driveService() *drive.Service { return drive.NewService(h.svc.nc, nil, h.svc.db) } func (h *Handler) ListDriveOrgFolders(w http.ResponseWriter, r *http.Request) { svc := h.driveService() folders, err := svc.ListOrgFoldersAdmin(r.Context()) if err != nil { h.logger.Error("list drive org folders", "error", err) apivalidate.WriteInternal(w, r) return } apiresponse.WriteJSON(w, http.StatusOK, map[string]any{"folders": folders}) } func (h *Handler) CreateDriveOrgFolder(w http.ResponseWriter, r *http.Request) { claims := middleware.ClaimsFromContext(r.Context()) svc := h.driveService() var req struct { OrgSlug string `json:"org_slug"` MountPoint string `json:"mount_point"` QuotaBytes *int64 `json:"quota_bytes"` } if err := apivalidate.DecodeJSON(w, r, 32<<10, &req); err != nil { return } createdBy := "" if claims != nil { createdBy = claims.Email } folder, err := svc.CreateOrgFolder(r.Context(), drive.CreateOrgFolderParams{ OrgSlug: req.OrgSlug, MountPoint: req.MountPoint, QuotaBytes: req.QuotaBytes, CreatedBy: createdBy, }) if err != nil { writeDriveAdminError(w, r, err) return } apiresponse.WriteJSON(w, http.StatusCreated, folder) } func (h *Handler) UpdateDriveOrgFolder(w http.ResponseWriter, r *http.Request) { svc := h.driveService() var req struct { MountPoint string `json:"mount_point"` QuotaBytes *int64 `json:"quota_bytes"` } if err := apivalidate.DecodeJSON(w, r, 32<<10, &req); err != nil { return } folder, err := svc.UpdateOrgFolder(r.Context(), chi.URLParam(r, "folderID"), req.MountPoint, req.QuotaBytes) if err != nil { writeDriveAdminError(w, r, err) return } apiresponse.WriteJSON(w, http.StatusOK, folder) } func (h *Handler) DeleteDriveOrgFolder(w http.ResponseWriter, r *http.Request) { svc := h.driveService() if err := svc.DeleteOrgFolder(r.Context(), chi.URLParam(r, "folderID")); err != nil { writeDriveAdminError(w, r, err) return } w.WriteHeader(http.StatusNoContent) } func (h *Handler) SyncDriveOrgFolders(w http.ResponseWriter, r *http.Request) { claims := middleware.ClaimsFromContext(r.Context()) svc := h.driveService() var req struct { OrgSlugs []string `json:"org_slugs"` } if err := apivalidate.DecodeJSON(w, r, 32<<10, &req); err != nil { return } createdBy := "" if claims != nil { createdBy = claims.Email } folders, err := svc.SyncOrgFolders(r.Context(), req.OrgSlugs, createdBy) if err != nil { writeDriveAdminError(w, r, err) return } apiresponse.WriteJSON(w, http.StatusOK, map[string]any{"folders": folders}) } func writeDriveAdminError(w http.ResponseWriter, r *http.Request, err error) { switch { case err == drive.ErrNotFound: apivalidate.WriteNotFound(w, r, "not found") case err == drive.ErrConflict: apiresponse.WriteError(w, r, http.StatusConflict, "drive.conflict", "resource conflict", nil) case err == drive.ErrInvalid: apiresponse.WriteError(w, r, http.StatusBadRequest, apiresponse.CodeInvalidRequest, "invalid request body", nil) default: if strings.Contains(err.Error(), "not found") { apivalidate.WriteNotFound(w, r, "not found") return } apivalidate.WriteInternal(w, r) } }