package routes import ( "net/http" "strconv" "owo.codes/whats-this/api/lib/apierrors" "owo.codes/whats-this/api/lib/db" "owo.codes/whats-this/api/lib/middleware" "owo.codes/whats-this/api/lib/ratelimiter" "github.com/go-chi/render" "github.com/rs/zerolog/log" "github.com/spf13/viper" ) // Maximum objects per page const maxOffset = 100 // listObjectsResponse is the response format for ListObjects. type listObjectsResponse struct { Success bool `json:"success"` Data []db.Object `json:"data"` } // ListObjects returns a paginated list of all objects owned by a user. func ListObjects(w http.ResponseWriter, r *http.Request) { // Only authorized users can use this route user := middleware.GetAuthorizedUser(r) if user.ID == "" || user.IsBlocked { panic(apierrors.Unauthorized) } // Apply ratelimits bucket := middleware.GetBucket(r) err := bucket.TakeWithHeaders(w, viper.GetInt64("ratelimiter.listObjectsCost")) if err == ratelimiter.InsufficientTokens { panic(apierrors.InsufficientTokens) } if err != nil { panic(apierrors.InternalServerError) } // Determine offset and limit information query := r.URL.Query() l := query.Get("limit") limit, err := strconv.Atoi(l) if err != nil { panic(apierrors.InvalidOffsetOrLimit) } o := query.Get("offset") offset, err := strconv.Atoi(o) if err != nil { panic(apierrors.InvalidOffsetOrLimit) } if limit > maxOffset { panic(apierrors.OffsetTooLarge) } asc := false if query.Get("order") == "asc" { asc = true } // Get the data objects, err := db.ListObjectsByAssociatedUser(user.ID, asc, offset, limit) if err != nil { log.Error().Err(err).Msg("failed to list objects for user") panic(apierrors.InternalServerError) } associatedWithCurrentUser := true for i := 0; i < len(objects); i++ { objects[i].AssociatedWithCurrentUser = &associatedWithCurrentUser } // Return response w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) render.JSON(w, r, listObjectsResponse{true, objects}) }