Ripped out literally everything to simplify the backend as much as possible. Some of the code was so horrifically complicated it's insaneeee
198 lines
4.5 KiB
Go
198 lines
4.5 KiB
Go
package stacks
|
|
|
|
import (
|
|
"database/sql"
|
|
"net/http"
|
|
"os"
|
|
"screenmark/screenmark/limits"
|
|
"screenmark/screenmark/middleware"
|
|
"screenmark/screenmark/models"
|
|
|
|
"github.com/charmbracelet/log"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type StackHandler struct {
|
|
logger *log.Logger
|
|
|
|
imageModel models.ImageModel
|
|
stackModel models.StackModel
|
|
|
|
limitsManager limits.LimitsManagerMethods
|
|
|
|
jwtManager *middleware.JwtManager
|
|
}
|
|
|
|
func (h *StackHandler) getAllStacks(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
userID, err := middleware.GetUserID(ctx, h.logger, w)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
lists, err := h.stackModel.List(ctx, userID)
|
|
if err != nil {
|
|
h.logger.Warn("could not get stacks", "err", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
middleware.WriteJsonOrError(h.logger, lists, w)
|
|
}
|
|
|
|
func (h *StackHandler) getStackItems(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
_, err := middleware.GetUserID(ctx, h.logger, w)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
listID, err := middleware.GetPathParamID(h.logger, "listID", w, r)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
// TODO: must check for permission here.
|
|
|
|
lists, err := h.stackModel.ListItems(ctx, listID)
|
|
if err != nil {
|
|
h.logger.Warn("could not get list items", "err", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
middleware.WriteJsonOrError(h.logger, lists, w)
|
|
}
|
|
|
|
type EditStack struct {
|
|
Hello string `json:"hello"`
|
|
}
|
|
|
|
func (h *StackHandler) editStack(req EditStack, w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusNotImplemented)
|
|
}
|
|
|
|
func (h *StackHandler) deleteStack(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
userID, err := middleware.GetUserID(ctx, h.logger, w)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
listID, err := middleware.GetPathParamID(h.logger, "listID", w, r)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
err = h.stackModel.Delete(ctx, listID, userID)
|
|
if err != nil {
|
|
h.logger.Warn("could not delete stack", "err", err)
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
|
|
func (h *StackHandler) deleteImageFromStack(w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
|
|
stringImageID := chi.URLParam(r, "imageID")
|
|
stringListID := chi.URLParam(r, "listID")
|
|
|
|
imageID, err := uuid.Parse(stringImageID)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
listID, err := uuid.Parse(stringListID)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// TODO: this should be extracted into a middleware of sorts
|
|
userID, err := middleware.GetUserID(ctx, h.logger, w)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
stack, err := h.stackModel.Get(ctx, listID)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if stack.UserID != userID {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
err = h.stackModel.DeleteImage(ctx, listID, imageID)
|
|
if err != nil {
|
|
h.logger.Warn("failed to delete image from list", "error", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
|
|
type CreateStackBody struct {
|
|
Title string `json:"title"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
func (h *StackHandler) createStack(body CreateStackBody, w http.ResponseWriter, r *http.Request) {
|
|
ctx := r.Context()
|
|
userID, err := middleware.GetUserID(ctx, h.logger, w)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
_, err = h.stackModel.Save(ctx, userID, body.Title, body.Description)
|
|
if err != nil {
|
|
h.logger.Warn("could not save stack", "err", err)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
}
|
|
|
|
func (h *StackHandler) CreateRoutes(r chi.Router) {
|
|
h.logger.Info("Mounting stack router")
|
|
|
|
r.Group(func(r chi.Router) {
|
|
r.Use(middleware.ProtectedRoute(h.jwtManager))
|
|
r.Use(middleware.SetJson)
|
|
|
|
r.Get("/", h.getAllStacks)
|
|
r.Get("/{listID}", h.getStackItems)
|
|
|
|
r.Post("/", middleware.WithLimit(h.logger, h.limitsManager.HasReachedStackLimit, middleware.WithValidatedPost(h.createStack)))
|
|
r.Patch("/{listID}", middleware.WithValidatedPost(h.editStack))
|
|
r.Delete("/{listID}", h.deleteStack)
|
|
r.Delete("/{listID}/{imageID}", h.deleteImageFromStack)
|
|
})
|
|
}
|
|
|
|
func CreateStackHandler(db *sql.DB, limitsManager limits.LimitsManagerMethods, jwtManager *middleware.JwtManager) StackHandler {
|
|
stackModel := models.NewListModel(db)
|
|
imageModel := models.NewImageModel(db)
|
|
logger := log.New(os.Stdout).WithPrefix("Stacks")
|
|
|
|
return StackHandler{
|
|
logger: logger,
|
|
imageModel: imageModel,
|
|
stackModel: stackModel,
|
|
limitsManager: limitsManager,
|
|
jwtManager: jwtManager,
|
|
}
|
|
}
|