Files
Gardomatic/internal/api/care_instructions.go
T
kleiax 904d14b64c
CI / test (push) Canceled after 0s
Initial commit
2026-09-12 22:22:17 +02:00

158 lines
4.2 KiB
Go

package api
import (
"fmt"
"gardomatic.kleiax.de/internal/platform/validate"
"gardomatic.kleiax.de/internal/storage"
"net/http"
"strings"
)
type careInstructionInput struct {
Text *string `json:"text"`
Status *string `json:"status"`
}
func (i careInstructionInput) apply(v *storage.CareInstruction) {
if i.Text != nil {
v.Text = strings.TrimSpace(*i.Text)
}
if i.Status != nil {
v.Status = *i.Status
}
}
func (app *application) validateCareInstruction(w http.ResponseWriter, r *http.Request, item storage.CareInstruction) bool {
v := validate.New()
storage.ValidateCareInstruction(v, item)
if !v.Valid() {
app.failedValidationResponse(w, r, v.Errors)
return false
}
return true
}
func (app *application) listCareInstructionsHandler(w http.ResponseWriter, r *http.Request) {
g, _ := app.readGardenIDParam(r)
s, e := app.readIDParam(r)
if e != nil {
app.notFoundResponse(w, r)
return
}
items, e := app.models.CareInstructions.GetAllForSpecies(g, s)
if e != nil {
app.respondToEntityModelError(w, r, e)
return
}
if e = app.writeJSON(w, http.StatusOK, envelope{"care_instructions": items}, nil); e != nil {
app.serverErrorResponse(w, r, e)
}
}
func (app *application) createCareInstructionHandler(w http.ResponseWriter, r *http.Request) {
g, _ := app.readGardenIDParam(r)
s, e := app.readIDParam(r)
if e != nil {
app.notFoundResponse(w, r)
return
}
if !app.canWriteCareInstructions(w, r, g, s) {
return
}
var input careInstructionInput
if e = app.readJSON(w, r, &input); e != nil {
app.badRequestResponse(w, r, e)
return
}
u, _ := app.contextGetAuthenticatedUser(r)
item := storage.CareInstruction{SpeciesID: s, Status: "untested", CreatedBy: u.ID, UpdatedBy: u.ID}
input.apply(&item)
if !app.validateCareInstruction(w, r, item) {
return
}
item, e = app.models.CareInstructions.Insert(item)
if e != nil {
app.respondToEntityModelError(w, r, e)
return
}
h := make(http.Header)
h.Set("Location", fmt.Sprintf("/v1/gardens/%d/species/%d/care-instructions/%d", g, s, item.ID))
_ = app.writeJSON(w, http.StatusCreated, envelope{"care_instruction": item}, h)
}
func (app *application) updateCareInstructionHandler(w http.ResponseWriter, r *http.Request) {
g, _ := app.readGardenIDParam(r)
s, e := app.readIDParam(r)
if e != nil {
app.notFoundResponse(w, r)
return
}
if !app.canWriteCareInstructions(w, r, g, s) {
return
}
id, e := app.readNamedIDParam(r, "instructionID")
if e != nil {
app.notFoundResponse(w, r)
return
}
item, e := app.models.CareInstructions.Get(g, s, id)
if e != nil {
app.respondToEntityModelError(w, r, e)
return
}
var input careInstructionInput
if e = app.readJSON(w, r, &input); e != nil {
app.badRequestResponse(w, r, e)
return
}
input.apply(&item)
u, _ := app.contextGetAuthenticatedUser(r)
item.UpdatedBy = u.ID
if !app.validateCareInstruction(w, r, item) {
return
}
item, e = app.models.CareInstructions.Update(g, item)
if e != nil {
app.respondToEntityModelError(w, r, e)
return
}
_ = app.writeJSON(w, http.StatusOK, envelope{"care_instruction": item}, nil)
}
func (app *application) deleteCareInstructionHandler(w http.ResponseWriter, r *http.Request) {
g, _ := app.readGardenIDParam(r)
s, e := app.readIDParam(r)
if e != nil {
app.notFoundResponse(w, r)
return
}
if !app.canWriteCareInstructions(w, r, g, s) {
return
}
id, e := app.readNamedIDParam(r, "instructionID")
if e != nil {
app.notFoundResponse(w, r)
return
}
if e = app.models.CareInstructions.Delete(g, s, id); e != nil {
app.respondToEntityModelError(w, r, e)
return
}
w.WriteHeader(http.StatusNoContent)
}
func (app *application) canWriteCareInstructions(w http.ResponseWriter, r *http.Request, gardenID, speciesID int) bool {
species, err := app.models.Species.Get(gardenID, speciesID)
if err != nil {
app.respondToEntityModelError(w, r, err)
return false
}
member, _ := app.contextGetGardenMember(r)
user, _ := app.contextGetAuthenticatedUser(r)
if species.GardenID == nil {
if !user.Can(storage.ApplicationPermissionGlobalSpeciesWrite) {
app.permissionDeniedResponse(w, r)
return false
}
} else if !member.Can(storage.GardenPermissionSpeciesWrite) {
app.permissionDeniedResponse(w, r)
return false
}
return true
}