Skip to content

Commit

Permalink
Add poll events creating in admin endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Zaptoss committed Jul 24, 2024
1 parent e1272c2 commit 77b805e
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 7 deletions.
9 changes: 9 additions & 0 deletions docs/spec/components/schemas/EventStaticMeta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,12 @@ properties:
format: int
description: Number of uses. Only available to the administrator.
example: 1002
poll_event_id:
type: string
description: Decimal value of the Event ID
example: "123456789987654321"
poll_contract:
type: string
description: Hex voting contract address with 0x.
example: "0x123...123"
pattern: '^0x[0-9a-fA-F]{40}$'
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ put:
summary: Update event type
description: |
Update an existing event type. Requires **admin** role in JWT.
**All attributes** are updated, ensure to pass every existing field too.
**All attributes** except QR code, Poll Event ID and Poll Contract are
updated, ensure to pass every existing field too.
Although this is not JSON:API compliant, it is much easier to work with
in Go, because differentiating between `{}` and `{"field": null}`
requires custom unmarshalling implementation.
Expand Down
3 changes: 2 additions & 1 deletion internal/data/evtypes/models/event_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ func ResourceToModel(r resources.EventStaticMeta) EventType {
ActionURL: r.ActionUrl,
Logo: r.Logo,
QRCodeValue: r.QrCodeValue,
PollEventID: r.PollEventId,
PollContract: r.PollContract,
}
}

Expand Down Expand Up @@ -92,7 +94,6 @@ func (e EventType) ForUpdate() map[string]any {
"disabled": e.Disabled,
"action_url": e.ActionURL,
"logo": e.Logo,
"qr_code_value": e.QRCodeValue,
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/service/handlers/create_event_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ func CreateEventType(w http.ResponseWriter, r *http.Request) {
if evtypes.FilterNotOpenable(typeModel) {
return nil
}
return openQREvents(r, typeModel)
return openEvents(r, typeModel)
})

if err != nil {
Expand All @@ -62,7 +62,7 @@ func CreateEventType(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
}

func openQREvents(r *http.Request, evType models.EventType) error {
func openEvents(r *http.Request, evType models.EventType) error {
balances, err := BalancesQ(r).Select()
if err != nil {
return fmt.Errorf("select balances: %w", err)
Expand Down
10 changes: 9 additions & 1 deletion internal/service/handlers/update_event_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ func UpdateEventType(w http.ResponseWriter, r *http.Request) {
}
}

if evType.QRCodeValue == nil && (evType.PollEventID == nil || evType.PollContract == nil) {
Log(r).Debugf("The event should be either a QR code or a poll")
ape.RenderErr(w, problems.Forbidden())
return
}

typeModel := models.ResourceToModel(req.Data.Attributes)

var updated []models.EventType
Expand All @@ -58,7 +64,7 @@ func UpdateEventType(w http.ResponseWriter, r *http.Request) {
}
// Open events if we have enabled the type, otherwise clean them up.
if !typeModel.Disabled {
return openQREvents(r, typeModel)
return openEvents(r, typeModel)
}

deleted, err := EventsQ(r).
Expand All @@ -82,6 +88,8 @@ func UpdateEventType(w http.ResponseWriter, r *http.Request) {
EventTypes(r).Push(typeModel)
resp := newEventTypeResponse(updated[0], r.Header.Get(langHeader))
resp.Data.Attributes.QrCodeValue = typeModel.QRCodeValue
resp.Data.Attributes.PollEventId = typeModel.PollEventID
resp.Data.Attributes.PollContract = typeModel.PollContract
ape.Render(w, resp)
}

Expand Down
14 changes: 12 additions & 2 deletions internal/service/requests/create_event_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func NewCreateEventType(r *http.Request) (req resources.EventTypeResponse, err e

attr := req.Data.Attributes
return req, val.Errors{
// only QR code events can be currently created or updated
// only QR code and poll events can be currently created or updated
// localization is not supported currently
"data/id": val.Validate(req.Data.ID, val.Required),
"data/type": val.Validate(req.Data.Type, val.Required, val.In(resources.EVENT_TYPE)),
Expand All @@ -27,10 +27,20 @@ func NewCreateEventType(r *http.Request) (req resources.EventTypeResponse, err e
"data/attributes/frequency": val.Validate(attr.Frequency, val.Required, val.In(string(models.Unlimited))),
"data/attributes/logo": val.Validate(attr.Logo, is.URL),
"data/attributes/name": val.Validate(attr.Name, val.Required, val.In(req.Data.ID)),
"data/attributes/qr_code_value": val.Validate(attr.QrCodeValue, val.Required, is.Base64),
"data/attributes/reward": val.Validate(attr.Reward, val.Required, val.Min(1)),
"data/attributes/short_description": val.Validate(attr.ShortDescription, val.Required),
"data/attributes/title": val.Validate(attr.Title, val.Required),
// for poll event
"data/attributes/poll_event_id": val.Validate(attr.PollEventId, is.Digit,
val.When(attr.QrCodeValue == nil, val.Required),
val.When(attr.QrCodeValue != nil, val.Nil)),
"data/attributes/poll_contract": val.Validate(attr.PollContract, val.Match(addressRegexp),
val.When(attr.QrCodeValue == nil, val.Required),
val.When(attr.QrCodeValue != nil, val.Nil)),
// for QR code event
"data/attributes/qr_code_value": val.Validate(attr.QrCodeValue, is.Base64,
val.When(attr.PollContract == nil || attr.PollEventId == nil, val.Required),
val.When(attr.PollContract != nil || attr.PollEventId != nil, val.Nil)),
// these fields are not currently supported, because cron jobs implementation is required
"data/attributes/starts_at": val.Validate(attr.StartsAt, val.Empty),
"data/attributes/expires_at": val.Validate(attr.ExpiresAt, val.Empty),
Expand Down
3 changes: 3 additions & 0 deletions internal/service/requests/update_event_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ func NewUpdateEventType(r *http.Request) (req resources.EventTypeResponse, err e
"data/attributes/reward": val.Validate(attr.Reward, val.Min(1)),
// not updatable, as QR code includes event type name
"data/attributes/qr_code_value": val.Validate(attr.QrCodeValue, val.Empty),

"data/attributes/poll_event_id": val.Validate(attr.PollEventId, val.Nil),
"data/attributes/poll_contract": val.Validate(attr.PollContract, val.Nil),
// these fields are not currently supported, because cron jobs implementation is required
"data/attributes/starts_at": val.Validate(attr.StartsAt, val.Empty),
"data/attributes/expires_at": val.Validate(attr.ExpiresAt, val.Empty),
Expand Down
1 change: 1 addition & 0 deletions internal/service/requests/verify_passport.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (

var (
nullifierRegexp = regexp.MustCompile("^0x[0-9a-fA-F]{64}$")
addressRegexp = regexp.MustCompile("^0x[0-9a-fA-F]{40}$")
hex32bRegexp = regexp.MustCompile("^[0-9a-f]{64}$")
// endpoint is hardcoded to reuse handlers.VerifyPassport
joinProgramPathRegexp = regexp.MustCompile("^/integrations/geo-points-svc/v1/public/balances/0x[0-9a-fA-F]{64}/join_program$")
Expand Down
4 changes: 4 additions & 0 deletions resources/model_event_static_meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ type EventStaticMeta struct {
Logo *string `json:"logo,omitempty"`
// Unique event code name
Name string `json:"name"`
// Hex voting contract address with 0x.
PollContract *string `json:"poll_contract,omitempty"`
// Decimal value of the Event ID
PollEventId *string `json:"poll_event_id,omitempty"`
// Base64-encoded QR code. Must match the code provided in event type.
QrCodeValue *string `json:"qr_code_value,omitempty"`
// Reward amount in points
Expand Down

0 comments on commit 77b805e

Please sign in to comment.