Skip to content
Snippets Groups Projects
object.go 1.96 KiB
Newer Older
package routes

import (
	"database/sql"
	"net/http"
	"strings"

	"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/pkg/errors"
	"github.com/rs/zerolog/log"
	"github.com/spf13/viper"
)

Dean's avatar
Dean committed
// objectResponse is the response format for Object.
type objectResponse struct {
	Success bool      `json:"success"`
	Data    db.Object `json:"data"`
}

// Object returns metadata about any object (even objects a user isn't
// associated with).
func Object(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.objectCost"))
	if err == ratelimiter.InsufficientTokens {
		panic(apierrors.InsufficientTokens)
	}
	if err != nil {
		panic(apierrors.InternalServerError)
	}

	// Get the key
	key := r.URL.Path
	if strings.HasPrefix(key, "/objects/") {
		key = key[9:]
	}

	// Get the object
	object, err := db.GetObject(viper.GetString("database.objectBucket"), key)
	switch {
	case errors.Cause(err) == sql.ErrNoRows:
		panic(apierrors.NoObjectFound)
	case err != nil:
		log.Error().Err(err).Msg("failed to get object")
		panic(apierrors.InternalServerError)
	}
Dean's avatar
Dean committed
	if object.Type == 2 { // tombstone
		object.MD5HashBytes = nil
		object.SHA256HashBytes = nil
		object.MD5Hash = nil
		object.SHA256Hash = nil
		object.AssociatedUser = nil
	}
	associatedWithCurrentUser := false
	if object.AssociatedUser != nil && *object.AssociatedUser == user.ID {
		associatedWithCurrentUser = true
	}
	object.AssociatedWithCurrentUser = &associatedWithCurrentUser

	// Return response
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	render.JSON(w, r, objectResponse{true, object})
}