handlers.go (view raw)
1package main
2
3import (
4 "encoding/json"
5 "errors"
6 "fmt"
7 "net/http"
8 "strconv"
9 "time"
10)
11
12const errJson = "{\"error\": %s}"
13
14func returnError(w http.ResponseWriter, err error, status int) {
15 http.Error(w, fmt.Sprintf(errJson, err.Error()), status)
16}
17
18func validateDate(month, day uint, year *uint) error {
19 if month < 1 || month > 12 {
20 return errors.New("invalid month: must be between 1 and 12")
21 }
22
23 if day < 1 || day > 31 {
24 return errors.New("invalid day: must be between 1 and 31")
25 }
26
27 var testYear uint
28 if year == nil {
29 testYear = 2023
30 } else {
31 testYear = *year
32 }
33
34 // Construct a date and use time package to validate
35 dateStr := fmt.Sprintf("%04d-%02d-%02d", testYear, month, day)
36 _, err := time.Parse("2006-01-02", dateStr)
37 if err != nil {
38 return errors.New("invalid day for the given month")
39 }
40
41 return nil
42}
43
44func updateOccurrence(w http.ResponseWriter, input Occurrence) {
45 var occurrence Occurrence
46 if err := db.First(&occurrence, input.ID).Error; err != nil {
47 returnError(w, err, http.StatusBadRequest)
48 return
49 }
50
51 // Update existing record with new values
52 if input.Day != 0 || input.Month != 0 {
53 if err := validateDate(input.Month, input.Day, input.Year); err != nil {
54 returnError(w, err, http.StatusBadRequest)
55 return
56 }
57 occurrence.Day = input.Day
58 occurrence.Month = input.Month
59 occurrence.Year = input.Year
60 }
61 if input.Name != "" {
62 occurrence.Name = input.Name
63 }
64 if input.Description != "" {
65 occurrence.Description = input.Description
66 }
67 occurrence.Notify = input.Notify
68 occurrence.Notified = input.Notified
69 db.Save(&occurrence)
70 json.NewEncoder(w).Encode(occurrence)
71}
72
73func addOccurrence(w http.ResponseWriter, r *http.Request) {
74 var input Occurrence
75 if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
76 returnError(w, err, http.StatusBadRequest)
77 return
78 }
79
80 if input.ID != 0 {
81 updateOccurrence(w, input)
82 return
83 }
84
85 if err := validateDate(input.Month, input.Day, input.Year); err != nil {
86 returnError(w, err, http.StatusBadRequest)
87 return
88 }
89
90 db.Create(&input)
91 json.NewEncoder(w).Encode(input)
92}
93
94func getOccurrences(w http.ResponseWriter, r *http.Request) {
95 var occurrences []Occurrence
96 db.Find(&occurrences)
97 json.NewEncoder(w).Encode(occurrences)
98}
99
100func deleteOccurrence(w http.ResponseWriter, r *http.Request) {
101 id, err := strconv.ParseUint(r.PathValue("id"), 10, 64)
102 if err != nil {
103 returnError(w, err, http.StatusBadRequest)
104 return
105 }
106
107 var occurrence Occurrence
108
109 if err := db.First(&occurrence, id).Error; err != nil {
110 returnError(w, err, http.StatusNotFound)
111 return
112 }
113
114 db.Delete(&occurrence)
115 w.WriteHeader(http.StatusNoContent)
116}