package api import ( "encoding/json" "net/http" "archivmail/internal/audit" ) // handleGetIMAPMode returns the current IMAP mode for the tenant. // GET /api/admin/settings/imap-mode func (s *Server) handleGetIMAPMode(w http.ResponseWriter, r *http.Request) { tenantID := tenantFromCtx(r.Context()) if tenantID == nil { writeError(w, http.StatusBadRequest, "no tenant context") return } mode, err := s.tenantStore.GetIMAPMode(r.Context(), *tenantID) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, map[string]string{"mode": mode}) } // handleSetIMAPMode sets the IMAP mode for the tenant. // PUT /api/admin/settings/imap-mode // Body: { "mode": "shared"|"personal", "confirmed": true } func (s *Server) handleSetIMAPMode(w http.ResponseWriter, r *http.Request) { tenantID := tenantFromCtx(r.Context()) if tenantID == nil { writeError(w, http.StatusBadRequest, "no tenant context") return } var req struct { Mode string `json:"mode"` Confirmed bool `json:"confirmed"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeError(w, http.StatusBadRequest, "invalid request body") return } // Double opt-in for shared mode if req.Mode == "shared" && !req.Confirmed { writeError(w, http.StatusBadRequest, "confirmed must be true to enable shared mode") return } if err := s.tenantStore.SetIMAPMode(r.Context(), *tenantID, req.Mode); err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } sess := sessionFromCtx(r.Context()) s.audlog.Log(audit.Entry{ EventType: "imap_mode_changed", Username: sess.Username, IPAddress: s.remoteIP(r), Detail: "imap_mode set to " + req.Mode, Success: true, }) writeJSON(w, http.StatusOK, map[string]string{"mode": req.Mode}) }