func (c *Controller) SetMood(ctx context.Context, w http.ResponseWriter, r *http.Request) { userID := mustUserID(ctx) name := pat.Param(ctx, "mood") var mood Mood r.ParseForm() err := decoder.Decode(&mood, r.PostForm) if err != nil { panic(err) // I believe this is unreachable } var uerr usererrors.InvalidParams if !(mood.Eyes == "" || utf8.RuneCountInString(mood.Eyes) == 2) { uerr = append(uerr, usererrors.InvalidParamsEntry{ Params: []string{"eyes"}, Message: "must be a string containing two characters", }) } if !(mood.Tongue == "" || utf8.RuneCountInString(mood.Tongue) == 2) { uerr = append(uerr, usererrors.InvalidParamsEntry{ Params: []string{"tongue"}, Message: "must be a string containing two characters", }) } if uerr != nil { respond.Error(ctx, w, http.StatusBadRequest, uerr) return } mood.Name = name mood.UserDefined = true err = c.repo.SetMood(userID, &mood) if err == errBuiltinMood { respond.Error(ctx, w, http.StatusBadRequest, usererrors.ActionNotAllowed{ Action: fmt.Sprintf("update built-in mood %s", name), }) return } else if err != nil { panic(err) } respond.Data(ctx, w, http.StatusOK, mood) }
// WrapC wraps a handler and only passes requests with valid Bearer authorization. func (c *Controller) WrapC(inner goji.Handler) goji.Handler { return goji.HandlerFunc(func(ctx context.Context, w http.ResponseWriter, r *http.Request) { auth := r.Header.Get("Authorization") if !strings.HasPrefix(auth, "Bearer ") { respond.Error(ctx, w, http.StatusUnauthorized, usererrors.BearerAuthRequired{}) return } auth = strings.TrimPrefix(auth, "Bearer ") if user := c.getUser(auth); user != nil { ctx = context.WithValue(ctx, ctxKey, user) reqlog.SetContext(ctx, "user_id", user.ID) inner.ServeHTTPC(ctx, w, r) } else { respond.Error(ctx, w, http.StatusUnauthorized, usererrors.AuthInvalid{}) } }) }
func respondCursorNotFound(ctx context.Context, w http.ResponseWriter, args listArgs) { var cursorParam string if args.After == "" { cursorParam = "ending_before" } else { cursorParam = "starting_after" } respond.Error(ctx, w, http.StatusBadRequest, usererrors.InvalidParams{{ Params: []string{cursorParam}, Message: "must refer to an existing object", }}) }
func (c *Controller) DeleteMood(ctx context.Context, w http.ResponseWriter, r *http.Request) { userID := mustUserID(ctx) name := pat.Param(ctx, "mood") if err := c.repo.DeleteMood(userID, name); err == errBuiltinMood { respond.Error(ctx, w, http.StatusBadRequest, usererrors.ActionNotAllowed{ Action: fmt.Sprintf("delete built-in mood %s", name), }) return } else if err != nil { panic(err) } w.WriteHeader(http.StatusNoContent) }
func (c *Controller) CreateConversation(ctx context.Context, w http.ResponseWriter, r *http.Request) { userID := mustUserID(ctx) heading := r.PostFormValue("heading") if cnt := utf8.RuneCountInString(heading); cnt > maxHeadingLength { respond.Error(ctx, w, http.StatusBadRequest, usererrors.InvalidParams{{ Params: []string{"heading"}, Message: fmt.Sprintf("must be a string of less than %d characters", maxHeadingLength), }}) return } convo, err := c.repo.NewConversation(userID, heading) if err != nil { panic(err) } respond.Data(ctx, w, http.StatusOK, convo) }
func (c *Controller) ListConversations(ctx context.Context, w http.ResponseWriter, r *http.Request) { userID := mustUserID(ctx) lArgs, uerr := getListArgs(r) if uerr != nil { respond.Error(ctx, w, http.StatusBadRequest, uerr) return } convos, hasMore, err := c.repo.ListConversations(userID, lArgs) if err == errCursorNotFound { respondCursorNotFound(ctx, w, lArgs) return } else if err != nil { panic(err) } respond.Data(ctx, w, http.StatusOK, listRes{ Cursor: convos[len(convos)-1].ID, Type: "conversation", HasMore: hasMore, Data: convos, }) }
func (c *Controller) CreateLine(ctx context.Context, w http.ResponseWriter, r *http.Request) { userID := mustUserID(ctx) convoID := pat.Param(ctx, "conversation") var uerr usererrors.InvalidParams var think bool switch r.PostFormValue("think") { case "", "false": think = false case "true": think = true default: uerr = append(uerr, usererrors.InvalidParamsEntry{ Params: []string{"think"}, Message: "must be either 'true' or 'false'", }) } animal := r.PostFormValue("animal") if animal == "" { animal = "default" } if _, ok := c.cows[animal]; !ok { uerr = append(uerr, usererrors.InvalidParamsEntry{ Params: []string{"animal"}, Message: fmt.Sprintf("%q does not exist", animal), }) } // Sanitize null bytes for the database moodName := strings.Replace(r.PostFormValue("mood"), "\x00", "", -1) text := strings.Replace(r.PostFormValue("text"), "\x00", "", -1) if moodName == "" { moodName = "default" } mood, err := c.repo.GetMood(userID, moodName) if err != nil { panic(err) } if mood == nil { uerr = append(uerr, usererrors.InvalidParamsEntry{ Params: []string{"mood"}, Message: fmt.Sprintf("%q does not exist", moodName), }) } if uerr != nil { respond.Error(ctx, w, http.StatusBadRequest, uerr) return } line := Line{ Animal: animal, Think: think, MoodName: moodName, Text: text, mood: mood, } if err := c.repo.InsertLine(userID, convoID, &line); err == sql.ErrNoRows { // The underlying conversation does not exist respond.NotFound(ctx, w, r) } else if err != nil { panic(err) } line.Output, err = c.renderLine(&line) if err != nil { panic(err) } respond.Data(ctx, w, http.StatusOK, line) }