package stacks import ( "database/sql" "encoding/json" "net/http" "os" "screenmark/screenmark/middleware" "screenmark/screenmark/models" "github.com/charmbracelet/log" "github.com/go-chi/chi/v5" "github.com/google/uuid" ) func writeJsonOrError[K any](logger *log.Logger, object K, w http.ResponseWriter) { jsonObject, err := json.Marshal(object) if err != nil { logger.Warn("could not marshal json object", "err", err) w.WriteHeader(http.StatusBadRequest) return } w.Write(jsonObject) w.WriteHeader(http.StatusOK) } type StackHandler struct { logger *log.Logger stackModel models.ListModel } func (h *StackHandler) withUserID( fn func(userID uuid.UUID, w http.ResponseWriter, r *http.Request), ) func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() userID, err := middleware.GetUserID(ctx) if err != nil { h.logger.Warn("could not get users in get all stacks", "err", err) w.WriteHeader(http.StatusUnauthorized) return } fn(userID, w, r) } } func (h *StackHandler) getAllStacks(userID uuid.UUID, w http.ResponseWriter, r *http.Request) { ctx := r.Context() lists, err := h.stackModel.List(ctx, userID) if err != nil { h.logger.Warn("could not get stacks", "err", err) w.WriteHeader(http.StatusBadRequest) return } writeJsonOrError(h.logger, lists, w) } func (h *StackHandler) getStackItems(userID uuid.UUID, w http.ResponseWriter, r *http.Request) { ctx := r.Context() listID := r.PathValue("listID") if len(listID) == 0 { h.logger.Warn("listID is not present in path") w.WriteHeader(http.StatusBadRequest) return } uuidListID, err := uuid.Parse(listID) if err != nil { h.logger.Warn("could not parse list id uuid", "err", err) w.WriteHeader(http.StatusUnauthorized) return } // TODO: must check for permission here. lists, err := h.stackModel.ListItems(ctx, uuidListID) if err != nil { h.logger.Warn("could not get list items", "err", err) w.WriteHeader(http.StatusBadRequest) return } writeJsonOrError(h.logger, lists, w) } func (h *StackHandler) CreateRoutes(r chi.Router) { h.logger.Info("Mounting stack router") r.Group(func(r chi.Router) { r.Use(middleware.ProtectedRoute) r.Use(middleware.SetJson) r.Get("/", h.withUserID(h.getAllStacks)) r.Get("/{listID}", h.withUserID(h.getStackItems)) }) } func CreateStackHandler(db *sql.DB) StackHandler { stackModel := models.NewListModel(db) logger := log.New(os.Stdout).WithPrefix("Stacks") return StackHandler{ logger, stackModel, } }