package handlers import ( "encoding/json" "fmt" "justguestbook/internal/guestbook" "justguestbook/pkg/server" "justguestbook/pkg/server/justcaptcha" "net/http" "strconv" "strings" ) type GuestbookHandlers struct { owner string password string anonymousName string defaultPageSize int64 db guestbook.Guestbook captchaAddr string } func New(owner, password, anonymousName string, defaultPageSize int64, guestbook guestbook.Guestbook, captchaAddr string) (*GuestbookHandlers, error) { return &GuestbookHandlers{ owner: owner, password: password, anonymousName: anonymousName, defaultPageSize: defaultPageSize, db: guestbook, captchaAddr: captchaAddr}, nil } func (h *GuestbookHandlers) Entries(w http.ResponseWriter, r *http.Request) { var err error var page_num int64 = 1 var page_size int64 = h.defaultPageSize if r.URL.Query().Get("p") != "" { page_num, err = strconv.ParseInt(r.URL.Query().Get("p"), 10, 32) if err != nil { page_num = 1 } } if r.URL.Query().Get("ps") != "" { page_size, err = strconv.ParseInt(r.URL.Query().Get("ps"), 10, 32) if err != nil { page_size = h.defaultPageSize } } entries, err := h.db.Entries(page_num, page_size) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) } if len(entries) == 0 { w.WriteHeader(http.StatusNotFound) return } guestbookEntries := struct { Owner string `json:"owner"` Entries []*guestbook.Entry `json:"entries"` }{ Owner: h.owner, Entries: entries} w.Header().Add("Content-Type", "application/json") json.NewEncoder(w).Encode(&guestbookEntries) } func (h *GuestbookHandlers) New(w http.ResponseWriter, r *http.Request) { var entry *guestbook.Entry var err error if r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" { r.ParseForm() if r.FormValue("captcha_id") == "" { w.WriteHeader(http.StatusForbidden) return } solved, err := justcaptcha.CheckCaptcha(r.FormValue("captcha_id"), h.captchaAddr) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) return } if !solved { w.WriteHeader(http.StatusForbidden) return } name := r.FormValue("name") if name == "" { name = h.anonymousName } entry, err = guestbook.NewEntry(name, r.FormValue("website"), r.FormValue("message"), len(r.FormValue("hide_website")) != 0) if err != nil { w.WriteHeader(http.StatusUnprocessableEntity) fmt.Fprint(w, err) return } } else if r.Header.Get("Content-Type") == "application/json" { cid := struct { CaptchaID string `json:"captcha_id"` }{} if err := json.NewDecoder(r.Body).Decode(&cid); err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) return } solved, err := justcaptcha.CheckCaptcha(cid.CaptchaID, h.captchaAddr) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) return } if !solved { w.WriteHeader(http.StatusForbidden) return } if err := json.NewDecoder(r.Body).Decode(entry); err != nil { w.WriteHeader(http.StatusUnprocessableEntity) fmt.Fprint(w, err) return } } err = h.db.NewEntry(entry) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, entry.Message) return } w.WriteHeader(http.StatusCreated) } func (h *GuestbookHandlers) Reply(w http.ResponseWriter, r *http.Request) { var reply *guestbook.Reply if r.Header.Get("X-Password") != h.password { w.WriteHeader(http.StatusForbidden) return } id, err := strconv.ParseInt(server.GetURLParam(r, "entry"), 10, 64) if err != nil { w.WriteHeader(http.StatusUnprocessableEntity) fmt.Fprint(w, err) } if r.Header.Get("Content-Type") == "application/x-www-form-urlencoded" { r.ParseForm() reply, err = guestbook.NewReply(id, r.FormValue("reply")) if err != nil { w.WriteHeader(http.StatusUnprocessableEntity) fmt.Fprint(w, err) } } else if r.Header.Get("Content-Type") == "application/json" { if err := json.NewDecoder(r.Body).Decode(reply); err != nil { w.WriteHeader(http.StatusUnprocessableEntity) fmt.Fprint(w, err) return } } if err := h.db.NewReply(reply); err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) } } func (h *GuestbookHandlers) Delete(w http.ResponseWriter, r *http.Request) { if r.Header.Get("X-Password") != h.password { w.WriteHeader(http.StatusForbidden) return } entryID, err := strconv.ParseInt(server.GetURLParam(r, "entry"), 10, 64) if err != nil { w.WriteHeader(http.StatusUnprocessableEntity) fmt.Fprint(w, err) return } if strings.HasSuffix(r.URL.Path, "reply") { if err := h.db.DeleteReply(entryID); err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) } } else { if err := h.db.DeleteEntry(entryID); err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprint(w, err) } } }