party/cmd/api/issues.go
2026-04-28 19:46:06 +02:00

296 lines
6.4 KiB
Go

package main
import (
// "encoding/json"
"fmt"
// "html/template"
// "log"
"net/http"
"time"
// "github.com/julienschmidt/httprouter"
// "strconv"
"errors"
"party.at/party/internal/data"
"party.at/party/internal/validator"
"encoding/hex"
)
func (app *application) listIssuesHandler(w http.ResponseWriter, r *http.Request) {
var input struct {
Title string
data.Filters
}
v := validator.New()
qs := r.URL.Query()
input.Title = app.readString(qs, "title", "")
// input.Genres = app.readCSV(qs, "genres", []string{})
input.Filters.Page = app.readInt(qs, "page", 1, v)
input.Filters.PageSize = app.readInt(qs, "page_size", 20, v)
input.Filters.Sort = app.readString(qs, "sort", "id")
input.Filters.SortSafelist = []string{"id", "-id", "title", "-title", "description", "-description"}
if data.ValidateFilters(v, input.Filters); !v.Valid() {
app.failedValidationResponse(w, r, v.Errors)
return
}
issues, metadata, err := app.models.Issues.GetAll(input.Title, input.Filters)
if err != nil {
app.serverErrorResponse(w, r, err)
return
}
err = app.writeJSON(w, http.StatusOK, envelope{"issues": issues, "metadata": metadata}, nil)
if err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) createIssueHandler(w http.ResponseWriter, r *http.Request) {
var input struct {
Title string `json:"title"`
Description string `json:"description"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
}
err := app.readJSON(w, r, &input)
if err != nil {
// Use the new badRequestResponse() helper.
app.badRequestResponse(w, r, err)
return
}
n, e, private_pem, err := GenerateIssueKey()
if err != nil {
app.serverErrorResponse(w, r, err)
return
}
issue := &data.Issue{
Title: input.Title,
Description: input.Description,
StartTime: input.StartTime,
EndTime: input.EndTime,
N: n,
E: e,
PrivatePem: private_pem,
}
v := validator.New()
if data.ValidateIssue(v, issue); !v.Valid() {
app.failedValidationResponse(w, r, v.Errors)
return
}
err = app.models.Issues.Insert(issue)
if err != nil {
app.serverErrorResponse(w, r, err)
return
}
headers := make(http.Header)
headers.Set("Location", fmt.Sprintf("/v1/issues/%d", issue.ID))
err = app.writeJSON(w, http.StatusCreated, envelope{"issue": issue}, headers)
if err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) readIssueHandler(w http.ResponseWriter, r *http.Request) {
id, err := app.readIDParam(r)
if err != nil {
app.notFoundResponse(w, r)
return
}
issue, err := app.models.Issues.Get(id)
if err != nil {
switch {
case errors.Is(err, data.ErrRecordNotFound):
app.notFoundResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
// Encode the struct to JSON and send it as the HTTP response.
err = app.writeJSON(w, http.StatusOK, envelope{"issue": issue}, nil)
if err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) updateIssueHandler(w http.ResponseWriter, r *http.Request) {
id, err := app.readIDParam(r)
if err != nil {
app.notFoundResponse(w, r)
return
}
issue, err := app.models.Issues.Get(id)
if err != nil {
switch {
case errors.Is(err, data.ErrRecordNotFound):
app.notFoundResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
var input struct {
Title *string `json:"title"`
Description *string `json:"description"`
StartTime *time.Time `json:"start_time"`
EndTime *time.Time `json:"end_time"`
}
err = app.readJSON(w, r, &input)
if err != nil {
app.badRequestResponse(w, r, err)
return
}
if input.Title != nil { issue.Title = *input.Title }
if input.Description != nil { issue.Description = *input.Description }
if input.StartTime != nil { issue.StartTime = *input.StartTime }
if input.StartTime != nil { issue.EndTime = *input.EndTime }
v := validator.New()
if data.ValidateIssue(v, issue); !v.Valid() {
app.failedValidationResponse(w, r, v.Errors)
return
}
err = app.models.Issues.Update(issue)
if err != nil {
switch {
case errors.Is(err, data.ErrEditConflict):
app.editConflictResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
// Write the updated issue record in a JSON response.
err = app.writeJSON(w, http.StatusOK, envelope{"issue": issue}, nil)
if err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) deleteIssueHandler(w http.ResponseWriter, r *http.Request) {
id, err := app.readIDParam(r)
if err != nil {
app.notFoundResponse(w, r)
return
}
// Delete the issue from the database, sending a 404 Not Found response to the
// client if there isn't a matching record.
err = app.models.Issues.Delete(id)
if err != nil {
switch {
case errors.Is(err, data.ErrRecordNotFound):
app.notFoundResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
// Return a 200 OK status code along with a success message.
err = app.writeJSON(w, http.StatusOK, envelope{"message": "issue successfully deleted"}, nil)
if err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) readIssuePubKeyHandler(w http.ResponseWriter, r *http.Request) {
id, err := app.readIDParam(r)
if err != nil {
app.notFoundResponse(w, r)
return
}
issue, err := app.models.Issues.Get(id)
if err != nil {
switch {
case errors.Is(err, data.ErrRecordNotFound):
app.notFoundResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
type response struct {
N string `json:"n"`
E int `json:"e"`
}
res := response{
N: hex.EncodeToString(issue.N),
E: issue.E,
}
err = app.writeJSON(w, http.StatusOK, envelope{"public_key": res}, nil)
if err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) blindSignIssueVoteHandler(w http.ResponseWriter, r *http.Request) {
id, err := app.readIDParam(r)
if err != nil {
app.notFoundResponse(w, r)
return
}
issue, err := app.models.Issues.Get(id)
if err != nil {
switch {
case errors.Is(err, data.ErrRecordNotFound):
app.notFoundResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
type response struct {
N string `json:"n"`
E int `json:"e"`
}
res := response{
N: hex.EncodeToString(issue.N),
E: issue.E,
}
err = app.writeJSON(w, http.StatusOK, envelope{"public_key": res}, nil)
if err != nil {
app.serverErrorResponse(w, r, err)
}
}