131 lines
3.3 KiB
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 ""
|
|
}
|