package area import ( "net/http" "yovision.local/sense/app/sense/identity" "yovision.local/sense/internal/platform" ) type Module struct{ service *Service } func NewModule(service *Service) *Module { return &Module{service: service} } func (m *Module) Register(app *platform.App) { activeService.Store(m.service) app.Handle("GET /api/v1/areas", identity.Require(identity.PermissionAreaRead, http.HandlerFunc(m.list))) app.Handle("POST /api/v1/areas", identity.Require(identity.PermissionAreaWrite, http.HandlerFunc(m.create))) app.Handle("PATCH /api/v1/areas/{id}", identity.Require(identity.PermissionAreaWrite, http.HandlerFunc(m.update))) app.Handle("POST /api/v1/areas/{id}/recalibrate", identity.Require(identity.PermissionAreaWrite, http.HandlerFunc(m.recalibrate))) app.Handle("POST /api/v1/areas/{id}/disable", identity.Require(identity.PermissionAreaWrite, http.HandlerFunc(m.disable))) } type writeRequest struct { DeviceID string `json:"device_id"` ProfileToken string `json:"profile_token"` Name string `json:"name"` Kind string `json:"kind"` Direction string `json:"direction"` Points []Point `json:"points"` Version int64 `json:"version"` } func (m *Module) list(w http.ResponseWriter, r *http.Request) { items, err := m.service.List(r.Context(), r.URL.Query().Get("device_id")) if err != nil { platform.WriteError(w, err) return } platform.WriteJSON(w, http.StatusOK, map[string]any{"items": items, "total": len(items)}) } func (m *Module) create(w http.ResponseWriter, r *http.Request) { var req writeRequest if err := platform.DecodeJSON(r, &req); err != nil { platform.WriteError(w, err) return } actor, _ := identity.PrincipalFromContext(r.Context()) item, err := m.service.Create(r.Context(), actor, req.DeviceID, req.ProfileToken, req.Name, req.Kind, req.Direction, req.Points) writeResult(w, item, err, http.StatusCreated) } func (m *Module) update(w http.ResponseWriter, r *http.Request) { m.writeExisting(w, r, false) } func (m *Module) recalibrate(w http.ResponseWriter, r *http.Request) { m.writeExisting(w, r, true) } func (m *Module) writeExisting(w http.ResponseWriter, r *http.Request, recalibrate bool) { var req writeRequest if err := platform.DecodeJSON(r, &req); err != nil { platform.WriteError(w, err) return } actor, _ := identity.PrincipalFromContext(r.Context()) item, err := m.service.Update(r.Context(), actor, r.PathValue("id"), req.Name, req.Direction, req.Points, req.Version, recalibrate) writeResult(w, item, err, http.StatusOK) } func (m *Module) disable(w http.ResponseWriter, r *http.Request) { var req struct { Version int64 `json:"version"` } if err := platform.DecodeJSON(r, &req); err != nil { platform.WriteError(w, err) return } actor, _ := identity.PrincipalFromContext(r.Context()) item, err := m.service.Disable(r.Context(), actor, r.PathValue("id"), req.Version) writeResult(w, item, err, http.StatusOK) } func writeResult(w http.ResponseWriter, item Area, err error, status int) { if err != nil { code := "area_invalid" httpStatus := http.StatusBadRequest if err == ErrConflict { code = "version_conflict" httpStatus = http.StatusConflict } if err == ErrNotFound { code = "area_not_found" httpStatus = http.StatusNotFound } platform.WriteError(w, &platform.APIError{Status: httpStatus, Code: code, Message: err.Error()}) return } platform.WriteJSON(w, status, item) }