Skip to content
Snippets Groups Projects
listobjects.go 2.58 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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"
    
    Dean's avatar
    Dean committed
    	"owo.codes/whats-this/api/lib/ratelimiter"
    
    
    	"github.com/go-chi/render"
    	"github.com/rs/zerolog/log"
    
    Dean's avatar
    Dean committed
    	"github.com/spf13/viper"
    
    const (
    	// Maximum objects per page
    	maxLimit = 100
    
    	// filter keys for file vs short link.
    	filterFiles = "file"
    	filterLinks = "link"
    )
    
    
    // listObjectsResponse is the response format for ListObjects.
    type listObjectsResponse struct {
    
    Spotlight Deveaux's avatar
    Spotlight Deveaux committed
    	Success      bool        `json:"success"`
    	TotalObjects int         `json:"total_objects"`
    	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)
    	}
    
    
    Dean's avatar
    Dean committed
    	// 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, limit and filter params
    
    	query := r.URL.Query()
    	l := query.Get("limit")
    	limit, err := strconv.Atoi(l)
    
    	if err != nil || limit < 0 {
    
    		panic(apierrors.InvalidOffsetOrLimit)
    	}
    
    	if limit > maxLimit {
    		panic(apierrors.LimitTooLarge)
    	}
    
    	o := query.Get("offset")
    	offset, err := strconv.Atoi(o)
    
    	if err != nil || offset < 0 {
    
    		panic(apierrors.InvalidOffsetOrLimit)
    	}
    	asc := false
    	if query.Get("order") == "asc" {
    		asc = true
    	}
    
    	filter := query.Get("type")
    	if filter != "" && filter != filterFiles && filter != filterLinks {
    		panic(apierrors.InvalidObjectFilter)
    	}
    
    	f := -1
    	if filter == filterFiles {
    		f = 0
    	} else if filter == filterLinks {
    		f = 1
    	}
    
    
    	// Get the data
    
    Spotlight Deveaux's avatar
    Spotlight Deveaux committed
    	count, err := db.CountObjectsByAssociatedUser(user.ID, f)
    	if err != nil {
    		log.Error().Err(err).Msg("failed to count objects for user")
    		panic(apierrors.InternalServerError)
    	}
    
    
    	objects, err := db.ListObjectsByAssociatedUser(user.ID, f, 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)
    
    Spotlight Deveaux's avatar
    Spotlight Deveaux committed
    	render.JSON(w, r, listObjectsResponse{true, count, objects})