func handleCreateTopic(ctx context.Context, w http.ResponseWriter, r *http.Request) { account, ok := auth.AuthRequired(pg.DB(ctx), w, r) if !ok { return } input := struct { Title string Tags []string Content string }{ Title: r.FormValue("title"), Tags: strings.Fields(r.FormValue("tags")), Content: r.FormValue("content"), } var errs []string if r.Method == "POST" { if input.Title == "" { errs = append(errs, `"title" is required`) } if input.Content == "" { errs = append(errs, `"content" is required`) } } if r.Method == "GET" || len(errs) != 0 { render(w, "topic_create.tmpl", input) return } db := pg.DB(ctx) tx, err := db.Beginx() if err != nil { log.Error("cannot start transaction", "error", err.Error()) respond500(w, r) return } defer tx.Rollback() topic := Topic{ AuthorID: int64(account.AccountID), Title: input.Title, Tags: input.Tags, } t, _, err := CreateTopicWithComment(tx, topic, input.Content) if err != nil { log.Error("cannot create topic with comment", "error", err.Error()) respond500(w, r) return } if err := tx.Commit(); err != nil { log.Error("cannot commit transaction", "error", err.Error()) respond500(w, r) return } http.Redirect(w, r, fmt.Sprintf("/t/%d", t.TopicID), http.StatusSeeOther) }
func HandleCreateNote(ctx context.Context, w http.ResponseWriter, r *http.Request) { var note Note if err := json.NewDecoder(r.Body).Decode(¬e); err != nil { web.JSONErr(w, err.Error(), http.StatusBadRequest) return } acc, ok := auth.AuthRequired(pg.DB(ctx), w, r) if !ok { return } if errs := validateNote(¬e); len(errs) > 0 { web.JSONErrs(w, errs, http.StatusBadRequest) return } note.OwnerID = acc.AccountID n, err := CreateNote(pg.DB(ctx), note) if err != nil { log.Printf("cannot create note: %s", err) web.StdJSONErr(w, http.StatusInternalServerError) return } web.JSONResp(w, n, http.StatusCreated) }
func HandleUpdateNote(ctx context.Context, w http.ResponseWriter, r *http.Request) { var input Note if err := json.NewDecoder(r.Body).Decode(&input); err != nil { web.JSONErr(w, err.Error(), http.StatusBadRequest) return } if errs := validateNote(&input); len(errs) > 0 { web.JSONErrs(w, errs, http.StatusBadRequest) return } tx, err := pg.DB(ctx).Beginx() if err != nil { log.Printf("cannot start transaction: %s", err) web.StdJSONErr(w, http.StatusInternalServerError) return } defer tx.Rollback() acc, ok := auth.AuthRequired(tx, w, r) if !ok { return } noteID := stoint(web.Args(ctx).ByIndex(0)) if ok, err := IsNoteOwner(tx, noteID, acc.AccountID); err != nil { log.Printf("cannot check %d note owner: %s", noteID, err) web.StdJSONErr(w, http.StatusInternalServerError) return } else if !ok { web.JSONErr(w, "you are not owner of this note", http.StatusUnauthorized) return } note, err := UpdateNote(tx, input) if err != nil { log.Printf("cannot update %d note: %s", noteID, err) web.StdJSONErr(w, http.StatusInternalServerError) return } if err := tx.Commit(); err != nil { log.Printf("cannot commit transaction: %s", err) web.StdJSONErr(w, http.StatusInternalServerError) return } web.JSONResp(w, note, http.StatusOK) }
func HandleDeleteNote(ctx context.Context, w http.ResponseWriter, r *http.Request) { tx, err := pg.DB(ctx).Beginx() if err != nil { log.Printf("cannot start transaction: %s", err) web.StdJSONErr(w, http.StatusInternalServerError) return } defer tx.Rollback() acc, ok := auth.AuthRequired(tx, w, r) if !ok { return } noteID := stoint(web.Args(ctx).ByIndex(0)) if ok, err := IsNoteOwner(tx, noteID, acc.AccountID); err != nil { if err == pg.ErrNotFound { web.StdJSONErr(w, http.StatusNotFound) } else { log.Printf("cannot check %d note owner: %s", noteID, err) web.StdJSONErr(w, http.StatusInternalServerError) } return } else if !ok { web.JSONErr(w, "you are not owner of this note", http.StatusUnauthorized) return } if err := DeleteNote(tx, noteID); err != nil { log.Printf("cannot delete %d note: %s", noteID, err) web.StdJSONErr(w, http.StatusInternalServerError) return } if err := tx.Commit(); err != nil { log.Printf("cannot commit transaction: %s", err) web.StdJSONErr(w, http.StatusInternalServerError) return } w.WriteHeader(http.StatusGone) }
func HandleListNotes(ctx context.Context, w http.ResponseWriter, r *http.Request) { db := pg.DB(ctx) acc, ok := auth.AuthRequired(db, w, r) if !ok { return } var offset int if raw := r.URL.Query().Get("offset"); raw != "" { if n, err := strconv.Atoi(raw); err != nil { web.JSONErr(w, "invalid 'offset' value", http.StatusBadRequest) return } else { offset = n } } notes, err := NotesByOwner(db, acc.AccountID, 300, offset) if err != nil { log.Printf("cannot fetch notes for %d: %s", acc.AccountID, err) web.StdJSONErr(w, http.StatusInternalServerError) return } if notes == nil { notes = make([]*Note, 0) // JSON api should return empty list } content := struct { Notes []*Note }{ Notes: notes, } web.JSONResp(w, content, http.StatusOK) }