Skip to content

Commit eb8a0c7

Browse files
update endpoint to use apiRequest and adjust payload in admin pluto image endpoint
1 parent ed8dfc1 commit eb8a0c7

11 files changed

+109
-46
lines changed

api/admin_create_event.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ import (
1717
"github.com/sndcds/uranus/model"
1818
)
1919

20+
// TODO: Insert event, add ticket_link
21+
// TODO: Implement simulation mode without inserting data
22+
2023
type eventPayload struct {
2124
ContentLanguage string `json:"content_language" binding:"required"`
2225
ReleaseStatus *string `json:"release_status" binding:"required"`
@@ -27,6 +30,7 @@ type eventPayload struct {
2730
Summary *string `json:"summary"`
2831
Tags []string `json:"tags"`
2932
SourceUrl *string `json:"source_url"`
33+
SourceImageUrl *string `json:"source_image_url"`
3034
OnlineLink *string `json:"online_link"`
3135
OrganizationId *int `json:"organization_id" binding:"required"`
3236
OrganizationKey *string `json:"organization_key" binding:"required"`
@@ -42,6 +46,7 @@ type eventPayload struct {
4246
MaxAttendees *int `json:"max_attendees"`
4347
PriceType model.PriceType `json:"price_type"`
4448
Currency *string `json:"currency"`
49+
TicketLink *string `json:"ticket_link"`
4550
TicketFlags []string `json:"ticket_flags"`
4651
Custom *string `json:"custom"`
4752
Style *string `json:"style"`
@@ -59,10 +64,12 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
5964
// Read the body
6065
body, err := io.ReadAll(gc.Request.Body)
6166
if err != nil {
67+
debugf("Error: %v", err)
6268
apiRequest.Error(http.StatusBadRequest, "failed to read request body")
6369
return
6470
}
6571
if len(body) == 0 {
72+
debugf("empty request body")
6673
apiRequest.Error(http.StatusBadRequest, "empty request body")
6774
return
6875
}
@@ -75,6 +82,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
7582
if err != nil {
7683
var syntaxErr *json.SyntaxError
7784
var typeErr *json.UnmarshalTypeError
85+
debugf("Error: %v", err)
7886

7987
switch {
8088
case errors.As(err, &syntaxErr):
@@ -95,6 +103,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
95103
return
96104
}
97105
if decoder.More() {
106+
debugf("Error decoder.More()")
98107
apiRequest.Error(http.StatusBadRequest, "multiple JSON objects are not allowed")
99108
return
100109
}
@@ -105,6 +114,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
105114
var unmarshalTypeError *json.UnmarshalTypeError
106115
var syntaxErr *json.SyntaxError
107116
var invalidUnmarshalError *json.InvalidUnmarshalError
117+
debugf("Error: %v", err)
108118

109119
switch {
110120
case errors.As(err, &syntaxErr):
@@ -136,11 +146,13 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
136146
// Validation
137147
validationErr := payload.Validate()
138148
if validationErr != nil {
149+
debugf("Error: %v", validationErr)
139150
apiRequest.Error(http.StatusBadRequest, validationErr.Error())
140151
return
141152
}
142153

143154
if payload.OrganizationId == nil {
155+
debugf("payload.OrganizationId == nil")
144156
apiRequest.Error(http.StatusBadRequest, "organizationId is required")
145157
return
146158
}
@@ -159,6 +171,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
159171
if payload.VenueId != nil {
160172
venuePermissions, err := h.GetUserEffectiveVenuePermissions(gc, tx, userId, *payload.VenueId)
161173
if err != nil {
174+
debugf("Error: %v", err)
162175
return &ApiTxError{Code: http.StatusForbidden, Err: err}
163176
}
164177
if !venuePermissions.Has(app.PermChooseVenue) {
@@ -229,6 +242,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
229242
return &ApiTxError{Code: http.StatusInternalServerError, Err: err}
230243
}
231244
if !venuePermissions.Has(app.PermChooseVenue) {
245+
debugf("Forbidden userId %d, venueId: %d", userId, *d.VenueId)
232246
return ApiErrForbidden("")
233247
}
234248

@@ -259,6 +273,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
259273
d.AllDay,
260274
userId)
261275
if err != nil {
276+
debugf("Error: %v", err)
262277
return &ApiTxError{
263278
Code: http.StatusInternalServerError,
264279
Err: fmt.Errorf("failed to insert event_date: %v", err),
@@ -287,6 +302,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
287302

288303
err = RefreshEventProjections(ctx, tx, "event", []int{newEventId})
289304
if err != nil {
305+
debugf("Error: %v", err)
290306
return &ApiTxError{
291307
Code: http.StatusInternalServerError,
292308
Err: fmt.Errorf("refresh projection tables failed: %v", err),
@@ -295,6 +311,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
295311

296312
err = RefreshEventProjections(ctx, tx, "event", []int{newEventId})
297313
if err != nil {
314+
debugf("Error: %v", err)
298315
return &ApiTxError{
299316
Code: http.StatusInternalServerError,
300317
Err: fmt.Errorf("refresh projection tables failed: %v", err),
@@ -308,8 +325,7 @@ func (h *ApiHandler) AdminCreateEvent(gc *gin.Context) {
308325
return
309326
}
310327

311-
apiRequest.Metadata["created_event_id"] = newEventId
312-
apiRequest.SuccessNoData(http.StatusCreated, "")
328+
apiRequest.Success(http.StatusCreated, gin.H{"created_event_id": newEventId}, "")
313329
}
314330

315331
// Validate validates the eventPayload struct
@@ -365,9 +381,11 @@ func (e *eventPayload) Validate() error {
365381
}
366382

367383
// Validate VenueId
384+
/* 2026-03-01, venueId not neccessary anymore in event
368385
if !e.hasVenue() {
369386
errs = append(errs, "event must have venueId")
370387
}
388+
*/
371389

372390
// Validate ExternalId (optional)
373391
if err := app.ValidateOptionalNonEmptyString("external_id", e.ExternalId); err != nil {

api/admin_get_event.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package api
22

33
import (
4-
"fmt"
54
"net/http"
65

76
"github.com/gin-gonic/gin"
@@ -113,7 +112,7 @@ func (h *ApiHandler) AdminGetEvent(gc *gin.Context) {
113112
for rows.Next() {
114113
var img model.Image
115114
rows.Scan(&img.Id, &img.Identifier, &img.FocusX, &img.FocusY, &img.Alt, &img.Copyright, &img.Creator, &img.License)
116-
img.Url = fmt.Sprintf("%s/api/image/%d", h.Config.BaseApiUrl, img.Id)
115+
img.Url = ImageUrl(img.Id)
117116
event.Images = append(event.Images, img)
118117
}
119118

api/admin_pluto_image.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ func (h *ApiHandler) AdminUpsertPlutoImage(gc *gin.Context) {
6262
userId := h.userId(gc)
6363
apiRequest := grains_api.NewRequest(gc, "admin-upsert-pluto-image")
6464

65+
// TODO: Check user permissions for different contexts
66+
6567
context := gc.Param("context")
6668
debugf("context: %s", context)
6769
apiRequest.SetMeta("pluto_context", context)
@@ -99,16 +101,20 @@ func (h *ApiHandler) AdminUpsertPlutoImage(gc *gin.Context) {
99101
apiRequest.InternalServerError()
100102
return
101103
}
104+
debugf("fileNamePrefix: %s", fileNamePrefix)
102105

103106
// Upsert image in Pluto
104107
plutoUpsertImageResult, err := pluto.UpsertImage(
105108
gc, context, contextId, identifier, &fileNamePrefix, userId,
106109
refresher(context, []int{contextId}))
107110
if err != nil || plutoUpsertImageResult.HttpStatus != http.StatusOK {
111+
debugf("err: %v", err)
108112
gc.JSON(plutoUpsertImageResult.HttpStatus, gin.H{"error": plutoUpsertImageResult.Message})
109113
return
110114
}
111115

116+
debugf("ok")
117+
112118
apiRequest.SetMeta("file_replaced", plutoUpsertImageResult.FileRemovedFlag)
113119
apiRequest.SetMeta("cache_removed_count", plutoUpsertImageResult.CacheFilesRemoved)
114120
apiRequest.SetMeta("image_id", plutoUpsertImageResult.ImageId)

api/api_image_helper.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/gin-gonic/gin"
7+
"github.com/sndcds/uranus/app"
78
)
89

910
func IsEventImageIdentifier(identifier string) bool {
@@ -85,3 +86,11 @@ func (h *ApiHandler) UpsertImage(
8586

8687
return plutoImageId, nil
8788
}
89+
90+
func ImageUrl(imageID int) string {
91+
return fmt.Sprintf(
92+
"%s/api/image/%d",
93+
app.UranusInstance.Config.BaseApiUrl,
94+
imageID,
95+
)
96+
}

api/get_event.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package api
22

33
import (
44
"encoding/json"
5-
"fmt"
65
"net/http"
76

87
"github.com/gin-gonic/gin"
@@ -166,15 +165,15 @@ func (h *ApiHandler) GetEventByDateId(gc *gin.Context) {
166165

167166
// Generate VenueLogoUrl if logo exists
168167
if edd.VenueLogoImageId != nil {
169-
url := fmt.Sprintf("%s/api/image/%d", app.UranusInstance.Config.BaseApiUrl, *edd.VenueLogoImageId)
168+
url := ImageUrl(*edd.VenueLogoImageId)
170169
edd.VenueLogoUrl = &url
171170
}
172171
if edd.VenueLightThemeLogoImageId != nil {
173-
url := fmt.Sprintf("%s/api/image/%d", app.UranusInstance.Config.BaseApiUrl, *edd.VenueLightThemeLogoImageId)
172+
url := ImageUrl(*edd.VenueLightThemeLogoImageId)
174173
edd.VenueLightThemeLogoUrl = &url
175174
}
176175
if edd.VenueDarkThemeLogoImageId != nil {
177-
url := fmt.Sprintf("%s/api/image/%d", app.UranusInstance.Config.BaseApiUrl, *edd.VenueDarkThemeLogoImageId)
176+
url := ImageUrl(*edd.VenueDarkThemeLogoImageId)
178177
edd.VenueDarkThemeLogoUrl = &url
179178
}
180179

api/get_events.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,13 @@ func (h *ApiHandler) GetEvents(gc *gin.Context) {
331331
query = strings.Replace(query, "{{conditions}}", conditionsStr, 1)
332332
query = strings.Replace(query, "{{limit}}", limitClause, 1)
333333

334-
fmt.Println(query)
335-
fmt.Printf("ARGS (%d):\n", len(args))
336-
for i, arg := range args {
337-
fmt.Printf(" $%d = %#v (type %T)\n", i+1, arg, arg)
338-
}
334+
/*
335+
fmt.Println(query)
336+
fmt.Printf("ARGS (%d):\n", len(args))
337+
for i, arg := range args {
338+
fmt.Printf(" $%d = %#v (type %T)\n", i+1, arg, arg)
339+
}
340+
*/
339341

340342
rows, err := h.DbPool.Query(ctx, query, args...)
341343
if err != nil {
@@ -410,7 +412,7 @@ func (h *ApiHandler) GetEvents(gc *gin.Context) {
410412
}
411413

412414
if e.ImageId != nil {
413-
path := fmt.Sprintf("%s/api/image/%d", h.Config.BaseApiUrl, *e.ImageId)
415+
path := ImageUrl(*e.ImageId)
414416
e.ImagePath = &path
415417
}
416418

api/get_organization.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,47 @@ import (
44
"net/http"
55

66
"github.com/gin-gonic/gin"
7+
"github.com/sndcds/grains/grains_api"
78
"github.com/sndcds/uranus/app"
89
)
910

10-
// TODO: Review code
11-
1211
func (h *ApiHandler) GetOrganization(gc *gin.Context) {
1312
ctx := gc.Request.Context()
13+
apiRequest := grains_api.NewRequest(gc, "get-organization")
1414

1515
organizationId, ok := ParamInt(gc, "organizationId")
1616
if !ok {
17-
gc.JSON(http.StatusBadRequest, gin.H{"error": "organization Id is required"})
17+
apiRequest.Error(http.StatusBadRequest, "organizationId is required")
1818
return
1919
}
20+
apiRequest.SetMeta("organizationId", organizationId)
2021

2122
query := app.UranusInstance.SqlGetOrganization
2223
rows, err := h.DbPool.Query(ctx, query, organizationId)
2324
if err != nil {
24-
gc.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
25+
apiRequest.InternalServerError()
2526
return
2627
}
2728
defer rows.Close()
2829

2930
if !rows.Next() {
30-
gc.JSON(http.StatusNotFound, gin.H{"error": "organization not found"})
31+
apiRequest.NotFound("organization not found")
3132
return
3233
}
3334

3435
fieldDescriptions := rows.FieldDescriptions()
3536
values, err := rows.Values()
3637
if err != nil {
37-
gc.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
38+
apiRequest.InternalServerError()
3839
return
3940
}
4041

41-
result := make(map[string]interface{}, len(values))
42+
response := make(map[string]interface{}, len(values))
4243
for i, fd := range fieldDescriptions {
43-
result[string(fd.Name)] = values[i]
44+
if values[i] != nil {
45+
response[string(fd.Name)] = values[i]
46+
}
4447
}
4548

46-
gc.JSON(http.StatusOK, result)
49+
apiRequest.Success(http.StatusOK, response, "")
4750
}

api/get_organizations.go

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,29 @@ import (
66
"strings"
77

88
"github.com/gin-gonic/gin"
9+
"github.com/sndcds/grains/grains_api"
910
)
1011

11-
// TODO: Review code
12-
13-
type Organization struct {
14-
ID int `json:"id"`
15-
Name *string `json:"name"`
16-
City *string `json:"city"`
17-
Country *string `json:"country"`
18-
ContactEmail *string `json:"contact_email"`
19-
}
12+
// TODO: Add filter options, e.g. lat/lon/radius
2013

2114
func (h *ApiHandler) GetOrganizations(gc *gin.Context) {
2215
ctx := gc.Request.Context()
16+
apiRequest := grains_api.NewRequest(gc, "get organizations")
17+
18+
type OrganizationResult struct {
19+
Id int `json:"id"`
20+
Name *string `json:"name"`
21+
City *string `json:"city"`
22+
Country *string `json:"country"`
23+
ContactEmail *string `json:"contact_email"`
24+
}
2325

2426
searchStr := strings.TrimSpace(gc.Query("search"))
2527
if len(searchStr) < 1 {
26-
gc.JSON(http.StatusBadRequest, gin.H{"error": "URL argument search is required"})
28+
apiRequest.Error(http.StatusBadRequest, "URL argument search is required")
2729
return
2830
}
31+
apiRequest.SetMeta("search", searchStr)
2932
var isEmail = strings.Contains(searchStr, "@")
3033

3134
var query string
@@ -38,20 +41,24 @@ func (h *ApiHandler) GetOrganizations(gc *gin.Context) {
3841
searchPattern := "%" + searchStr + "%"
3942
rows, err := h.DbPool.Query(ctx, query, searchPattern)
4043
if err != nil {
41-
gc.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
44+
apiRequest.InternalServerError()
4245
return
4346
}
4447
defer rows.Close()
4548

46-
var organizations []Organization
49+
var organizations []OrganizationResult
4750
for rows.Next() {
48-
var o Organization
49-
if err := rows.Scan(&o.ID, &o.Name, &o.City, &o.Country, &o.ContactEmail); err != nil {
50-
gc.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
51+
var o OrganizationResult
52+
if err := rows.Scan(&o.Id, &o.Name, &o.City, &o.Country, &o.ContactEmail); err != nil {
53+
apiRequest.InternalServerError()
5154
return
5255
}
5356
organizations = append(organizations, o)
5457
}
55-
56-
gc.JSON(http.StatusOK, organizations)
58+
if len(organizations) == 0 {
59+
apiRequest.NotFound("no organizations found")
60+
return
61+
}
62+
apiRequest.SetMeta("organization_count", len(organizations))
63+
apiRequest.Success(http.StatusOK, organizations, "")
5764
}

api/get_venues_for_map.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import (
88
"github.com/sndcds/uranus/app"
99
)
1010

11-
// TODO: Review code
12-
// TODO: Add url parameter
11+
// TODO: Add query parameters for filtering
1312

1413
func (h *ApiHandler) GetVenuesGeoJSON(gc *gin.Context) {
1514
ctx := gc.Request.Context()

0 commit comments

Comments
 (0)