Files
yovision/Sense/server/app/sense/area/http.go
T

90 lines
3.4 KiB
Go

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)
}