szabadpalya/api/internal/httpapi/admin.go

131 lines
3.3 KiB
Go

package httpapi
import (
"errors"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/szabadpalya/api/internal/hu"
"github.com/szabadpalya/api/internal/store"
)
func (s *Server) adminListCampaigns(c *gin.Context) {
rows, err := s.store.ListAdminCampaigns(c.Request.Context())
if err != nil {
s.fail(c, err)
return
}
c.JSON(http.StatusOK, rows)
}
func (s *Server) adminOwners(c *gin.Context) {
orgs, err := s.store.ListOwners(c.Request.Context())
if err != nil {
s.fail(c, err)
return
}
c.JSON(http.StatusOK, orgs)
}
func (s *Server) adminGetCampaign(c *gin.Context) {
campaign, err := s.store.GetAdminCampaign(c.Request.Context(), c.Param("slug"))
if errors.Is(err, store.ErrNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
if err != nil {
s.fail(c, err)
return
}
c.JSON(http.StatusOK, campaign)
}
var validStatus = map[string]bool{
"DRAFT": true, "BEADVA": true, "AKTIV": true,
"FINANSZIROZOTT": true, "LEZART": true, "ELUTASITVA": true,
}
var validTierType = map[string]bool{"DONATION": true, "DIGITAL": true, "PHYSICAL": true}
// adminSaveCampaign handles both create and update: a body carrying an id
// updates that campaign, a body without one creates it.
func (s *Server) adminSaveCampaign(c *gin.Context) {
var in store.CampaignInput
if err := c.ShouldBindJSON(&in); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "hianyzo"})
return
}
in.Title = strings.TrimSpace(in.Title)
in.Summary = strings.TrimSpace(in.Summary)
in.Slug = hu.Slugify(firstNonEmpty(in.Slug, in.Title))
if in.Title == "" || in.Slug == "" || in.GoalAmount <= 0 ||
in.EndsAt == "" || in.OwnerID == "" {
c.JSON(http.StatusBadRequest, gin.H{"error": "hianyzo"})
return
}
if !validStatus[in.Status] {
in.Status = "DRAFT"
}
// Enum values reach SQL as parameters, but an unknown one would surface as
// a Postgres cast error rather than something the editor can explain.
for i := range in.Tiers {
if !validTierType[in.Tiers[i].Type] {
in.Tiers[i].Type = "DONATION"
}
}
result, err := s.store.SaveCampaign(c.Request.Context(), in)
if errors.Is(err, store.ErrSlugTaken) {
c.JSON(http.StatusConflict, gin.H{"error": "slug"})
return
}
// The editor only ever saves a campaign it loaded, so a missing id means a
// request that was not made by it — an attempt to create one, which is a
// thing this API no longer does.
if errors.Is(err, store.ErrNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "nincs ilyen kampany"})
return
}
if err != nil {
s.fail(c, err)
return
}
c.JSON(http.StatusOK, result)
}
func (s *Server) adminDeleteCampaign(c *gin.Context) {
slug := c.Param("slug")
campaign, err := s.store.GetAdminCampaign(c.Request.Context(), slug)
if errors.Is(err, store.ErrNotFound) {
c.JSON(http.StatusNotFound, gin.H{"error": "not found"})
return
}
if err != nil {
s.fail(c, err)
return
}
err = s.store.DeleteCampaign(c.Request.Context(), campaign.ID)
if errors.Is(err, store.ErrHasPledges) {
c.JSON(http.StatusConflict, gin.H{"error": "van-tamogatas"})
return
}
if err != nil {
s.fail(c, err)
return
}
c.JSON(http.StatusOK, gin.H{"ok": true})
}
func firstNonEmpty(values ...string) string {
for _, v := range values {
if strings.TrimSpace(v) != "" {
return v
}
}
return ""
}