133 lines
3.4 KiB
Go
133 lines
3.4 KiB
Go
package api
|
|
|
|
import (
|
|
"database/sql"
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/google/uuid"
|
|
|
|
"work-queue-api/internal/model"
|
|
)
|
|
|
|
type createProjectRequest struct {
|
|
Name string `json:"name"`
|
|
ExternalRef *string `json:"external_ref"`
|
|
}
|
|
|
|
type patchProjectRequest struct {
|
|
Name *string `json:"name"`
|
|
ExternalRef *string `json:"external_ref"`
|
|
}
|
|
|
|
func (s *Server) handleCreateProject(w http.ResponseWriter, r *http.Request) {
|
|
var req createProjectRequest
|
|
if err := decodeJSON(r, &req); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid json body")
|
|
return
|
|
}
|
|
if req.Name == "" {
|
|
writeError(w, http.StatusBadRequest, "name is required")
|
|
return
|
|
}
|
|
|
|
now := nowUTC()
|
|
project := model.Project{
|
|
ID: uuid.NewString(),
|
|
Name: req.Name,
|
|
ExternalRef: req.ExternalRef,
|
|
CreatedAt: now,
|
|
UpdatedAt: now,
|
|
}
|
|
|
|
_, err := s.db.Exec(`INSERT INTO projects (id, name, external_ref, created_at, updated_at) VALUES (?, ?, ?, ?, ?)`,
|
|
project.ID, project.Name, project.ExternalRef, project.CreatedAt.Format(timeLayout), project.UpdatedAt.Format(timeLayout),
|
|
)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusCreated, project)
|
|
}
|
|
|
|
func (s *Server) handleListProjects(w http.ResponseWriter, r *http.Request) {
|
|
rows, err := s.db.Query(`SELECT id, name, external_ref, created_at, updated_at FROM projects ORDER BY created_at ASC`)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
var projects []model.Project
|
|
for rows.Next() {
|
|
project, err := scanProject(rows)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
projects = append(projects, project)
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, projects)
|
|
}
|
|
|
|
func (s *Server) handleGetProject(w http.ResponseWriter, r *http.Request) {
|
|
project, err := s.fetchProject(chi.URLParam(r, "id"))
|
|
if err == sql.ErrNoRows {
|
|
writeError(w, http.StatusNotFound, "project not found")
|
|
return
|
|
}
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
writeJSON(w, http.StatusOK, project)
|
|
}
|
|
|
|
func (s *Server) handlePatchProject(w http.ResponseWriter, r *http.Request) {
|
|
id := chi.URLParam(r, "id")
|
|
project, err := s.fetchProject(id)
|
|
if err == sql.ErrNoRows {
|
|
writeError(w, http.StatusNotFound, "project not found")
|
|
return
|
|
}
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
var req patchProjectRequest
|
|
if err := decodeJSON(r, &req); err != nil {
|
|
writeError(w, http.StatusBadRequest, "invalid json body")
|
|
return
|
|
}
|
|
|
|
if req.Name != nil {
|
|
if *req.Name == "" {
|
|
writeError(w, http.StatusBadRequest, "name cannot be empty")
|
|
return
|
|
}
|
|
project.Name = *req.Name
|
|
}
|
|
if req.ExternalRef != nil {
|
|
project.ExternalRef = req.ExternalRef
|
|
}
|
|
project.UpdatedAt = nowUTC()
|
|
|
|
_, err = s.db.Exec(`UPDATE projects SET name = ?, external_ref = ?, updated_at = ? WHERE id = ?`,
|
|
project.Name, project.ExternalRef, project.UpdatedAt.Format(timeLayout), project.ID,
|
|
)
|
|
if err != nil {
|
|
writeError(w, http.StatusInternalServerError, err.Error())
|
|
return
|
|
}
|
|
|
|
writeJSON(w, http.StatusOK, project)
|
|
}
|
|
|
|
func (s *Server) fetchProject(id string) (model.Project, error) {
|
|
row := s.db.QueryRow(`SELECT id, name, external_ref, created_at, updated_at FROM projects WHERE id = ?`, id)
|
|
return scanProject(row)
|
|
}
|