package main import ( "encoding/json" "net/http" "strconv" ) func (app *App) handleListUsers(w http.ResponseWriter, r *http.Request) { users, err := app.listUsers() if err != nil { writeError(w, err.Error(), http.StatusInternalServerError) return } writeJSON(w, users) } func (app *App) handleCreateUser(w http.ResponseWriter, r *http.Request) { var body struct { Email string `json:"email"` PreferredName string `json:"preferred_name"` Password string `json:"password"` Roles []string `json:"roles"` DepartmentIDs []int `json:"department_ids"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { writeError(w, "invalid request", http.StatusBadRequest) return } if body.Email == "" || body.Password == "" || len(body.Roles) == 0 { writeError(w, "email, password, and at least one role are required", http.StatusBadRequest) return } hash, err := hashPassword(body.Password) if err != nil { writeError(w, "hash error", http.StatusInternalServerError) return } if body.DepartmentIDs == nil { body.DepartmentIDs = []int{} } user, err := app.createUser(body.Email, body.PreferredName, hash, body.Roles, body.DepartmentIDs) if err != nil { writeError(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) writeJSON(w, user) } func (app *App) handleUpdateUser(w http.ResponseWriter, r *http.Request) { id, err := strconv.Atoi(r.PathValue("id")) if err != nil { writeError(w, "invalid id", http.StatusBadRequest) return } target, _ := app.getUser(id) if target == nil { writeError(w, "not found", http.StatusNotFound) return } var body struct { Roles []string `json:"roles"` Password string `json:"password"` DepartmentIDs []int `json:"department_ids"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { writeError(w, "invalid request", http.StatusBadRequest) return } if body.DepartmentIDs == nil { body.DepartmentIDs = []int{} } if body.Roles != nil { if err := app.updateUserRoles(id, body.Roles, body.DepartmentIDs); err != nil { writeError(w, err.Error(), http.StatusInternalServerError) return } } if body.Password != "" { hash, err := hashPassword(body.Password) if err != nil { writeError(w, "hash error", http.StatusInternalServerError) return } if err := app.updateUserPassword(id, hash); err != nil { writeError(w, err.Error(), http.StatusInternalServerError) return } } user, _ := app.getUser(id) writeJSON(w, user) } func (app *App) handleDeleteUser(w http.ResponseWriter, r *http.Request) { id, err := strconv.Atoi(r.PathValue("id")) if err != nil { writeError(w, "invalid id", http.StatusBadRequest) return } claims := claimsFromContext(r) if claims.ParticipantID == id { writeError(w, "cannot delete yourself", http.StatusBadRequest) return } if err := app.removeUser(id); err != nil { writeError(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusNoContent) }