Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 8 additions & 16 deletions api/v1_grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ type createGrantBody struct {
}

type addManagerBody struct {
ManagerUserId string `json:"manager_user_id"`
ManagerUserId trashid.HashId `json:"manager_user_id" validate:"required,min=1"`
}

type approveGrantBody struct {
GrantorUserId string `json:"grantor_user_id"`
GrantorUserId trashid.HashId `json:"grantor_user_id" validate:"required,min=1"`
}

// postV1UsersGrant creates a grant from the user to an app (user authorizes app to act on their behalf)
Expand Down Expand Up @@ -162,17 +162,13 @@ func (app *ApiServer) postV1UsersManager(c *fiber.Ctx) error {
"error": "Invalid request body",
})
}
managerUserID, err := trashid.DecodeHashId(body.ManagerUserId)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Invalid manager_user_id",
})
if err := app.requestValidator.Validate(&body); err != nil {
return err
}

// Get manager's wallet (grantee_address)
users, err := app.queries.Users(c.Context(), dbv1.GetUsersParams{
MyID: 0,
Ids: []int32{int32(managerUserID)},
Ids: []int32{int32(body.ManagerUserId)},
})
if err != nil || len(users) == 0 {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
Expand Down Expand Up @@ -316,20 +312,16 @@ func (app *ApiServer) postV1UsersApproveGrant(c *fiber.Ctx) error {
"error": "Invalid request body",
})
}
grantorUserID, err := trashid.DecodeHashId(body.GrantorUserId)
if err != nil {
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{
"error": "Invalid grantor_user_id",
})
if err := app.requestValidator.Validate(&body); err != nil {
return err
}

signer, err := app.getApiSigner(c)
if err != nil {
return err
}

nonce := time.Now().UnixNano()
metadata := map[string]interface{}{"grantor_user_id": int64(grantorUserID)}
metadata := map[string]interface{}{"grantor_user_id": int64(body.GrantorUserId)}
metadataBytes, _ := json.Marshal(metadata)

manageEntityTx := &corev1.ManageEntityLegacy{
Expand Down
6 changes: 3 additions & 3 deletions api/v1_playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ import (
)

type PlaylistTrackInfo struct {
TrackId string `json:"track_id" validate:"required"`
Timestamp int64 `json:"timestamp" validate:"required,min=0"`
MetadataTimestamp *int64 `json:"metadata_timestamp,omitempty" validate:"omitempty,min=0"`
TrackId trashid.IntId `json:"track_id" validate:"required,min=1"`
Timestamp int64 `json:"timestamp" validate:"required,min=0"`
MetadataTimestamp *int64 `json:"metadata_timestamp,omitempty" validate:"omitempty,min=0"`
}

type CreatePlaylistRequest struct {
Expand Down
24 changes: 24 additions & 0 deletions trashid/hashid.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,30 @@ func MustDecodeHashID(id string) int {
return val
}

// IntId accepts a hash ID or raw int on input (JSON unmarshal) but
// always marshals back as a plain integer. Use this for fields that are
// part of chain metadata where the indexer expects numeric IDs.
type IntId int

func (num IntId) MarshalJSON() ([]byte, error) {
return []byte(strconv.Itoa(int(num))), nil
}

func (num *IntId) UnmarshalJSON(data []byte) error {
if data[0] == '"' {
idStr := strings.Trim(string(data), `"`)
id, err := DecodeHashId(idStr)
if err != nil {
return err
}
*num = IntId(id)
return nil
}
val, err := strconv.Atoi(string(data))
*num = IntId(val)
return err
}

// type alias for int that will do hashid on the way out the door
type HashId int

Expand Down
35 changes: 35 additions & 0 deletions trashid/hashid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,38 @@ func TestHashId(t *testing.T) {
assert.Equal(t, 0, int(h))
}
}

func TestIntId(t *testing.T) {

// when we serialize... it emits a plain number (not a hash string)
{
i := IntId(44)
j, err := json.Marshal(i)
assert.NoError(t, err)
assert.Equal(t, `44`, string(j))
}

// when we parse a hashid string... it decodes to the numeric value
{
var i IntId
err := json.Unmarshal([]byte(`"eYorL"`), &i)
assert.NoError(t, err)
assert.Equal(t, 44, int(i))
}

// when we parse a raw number... it works as-is
{
var i IntId
err := json.Unmarshal([]byte("33"), &i)
assert.NoError(t, err)
assert.Equal(t, 33, int(i))
}

// errors on bad hashid string
{
var i IntId
err := json.Unmarshal([]byte(`"asdjkfalksdjfaklsdjf"`), &i)
assert.Error(t, err)
assert.Equal(t, 0, int(i))
}
}
Loading