diff --git a/api/resolve_middleware.go b/api/resolve_middleware.go index a19809f0..51ca1d88 100644 --- a/api/resolve_middleware.go +++ b/api/resolve_middleware.go @@ -45,7 +45,6 @@ func (app *ApiServer) getUserId(c *fiber.Ctx) int32 { } func (app *ApiServer) requireUserIdMiddleware(c *fiber.Ctx) error { - // Allow /users/me/* routes to pass through without userId resolution if c.Params("userId") == "me" { return c.Next() } diff --git a/api/server.go b/api/server.go index 8674f83d..49bd7315 100644 --- a/api/server.go +++ b/api/server.go @@ -406,7 +406,7 @@ func NewApiServer(config config.Config) *ApiServer { g.Get("/users/genre/top", app.v1UsersGenreTop) g.Get("/users/account/:wallet", app.requireAuthMiddleware, app.v1UsersAccount) g.Get("/users/verify_token", app.v1UsersVerifyToken) - g.Post("/users/me/ping", app.requireAuthMiddleware, app.postV1UsersPing) + g.Post("/users/me/ping", app.postV1UsersPing) g.Use("/users/handle/:handle", app.requireHandleMiddleware) g.Get("/users/handle/:handle", app.v1User) diff --git a/api/v1_users_ping.go b/api/v1_users_ping.go index c222b726..4c2f7a71 100644 --- a/api/v1_users_ping.go +++ b/api/v1_users_ping.go @@ -10,14 +10,17 @@ func (app *ApiServer) postV1UsersPing(c *fiber.Ctx) error { return fiber.NewError(fiber.StatusServiceUnavailable, "writes not available") } - wallet := app.getAuthedWallet(c) + myId := app.getMyId(c) + if myId == 0 { + return fiber.NewError(fiber.StatusBadRequest, "user_id query param is required") + } _, err := app.writePool.Exec(c.Context(), ` UPDATE users SET last_active_at = now() - WHERE wallet = $1 + WHERE user_id = $1 AND is_current = true - `, wallet) + `, myId) if err != nil { app.logger.Error("postV1UsersPing: failed to update last_active_at", zap.Error(err)) return fiber.NewError(fiber.StatusInternalServerError, "failed to record activity") diff --git a/api/v1_users_ping_test.go b/api/v1_users_ping_test.go new file mode 100644 index 00000000..33b978c5 --- /dev/null +++ b/api/v1_users_ping_test.go @@ -0,0 +1,32 @@ +package api + +import ( + "testing" + + "api.audius.co/database" + "api.audius.co/api/testdata" + "github.com/stretchr/testify/assert" +) + +func TestPostV1UsersPing(t *testing.T) { + app := emptyTestApp(t) + database.SeedTable(app.pool.Replicas[0], "users", testdata.UserFixtures) + + // user 1 = wallet 0x7d273271690538cf855e5b3002a0dd8c154bb060, encoded = 7eP5n + wallet := "0x7d273271690538cf855e5b3002a0dd8c154bb060" + + t.Run("authenticated request returns 200", func(t *testing.T) { + status, body := testPostWithWallet(t, app, "/v1/users/me/ping?user_id=7eP5n", wallet, nil, nil) + assert.Equal(t, 200, status, "body: %s", string(body)) + }) + + t.Run("missing user_id returns 400", func(t *testing.T) { + status, _ := testPostWithWallet(t, app, "/v1/users/me/ping", wallet, nil, nil) + assert.Equal(t, 400, status) + }) + + t.Run("unauthenticated request with user_id returns 403", func(t *testing.T) { + status, _ := testPost(t, app, "/v1/users/me/ping?user_id=7eP5n", nil, nil) + assert.Equal(t, 403, status) + }) +} diff --git a/ddl/migrations/0218_create_event_routes.sql b/ddl/migrations/0218_create_event_routes.sql index 3fbb9e3b..a0c1b521 100644 --- a/ddl/migrations/0218_create_event_routes.sql +++ b/ddl/migrations/0218_create_event_routes.sql @@ -4,7 +4,6 @@ -- indexer when an event is created, owner_id points to the event's host user, -- and is_current flags the canonical row so a LEFT JOIN ON is_current = true -- always lands on at most one row per event. - CREATE TABLE IF NOT EXISTS public.event_routes ( slug character varying NOT NULL, owner_id integer NOT NULL, @@ -12,11 +11,8 @@ CREATE TABLE IF NOT EXISTS public.event_routes ( is_current boolean NOT NULL, blockhash character varying NOT NULL, blocknumber integer NOT NULL, - txhash character varying NOT NULL + txhash character varying NOT NULL, + CONSTRAINT event_routes_pkey PRIMARY KEY (owner_id, slug) ); - -ALTER TABLE ONLY public.event_routes - ADD CONSTRAINT event_routes_pkey PRIMARY KEY (owner_id, slug); - CREATE INDEX IF NOT EXISTS event_routes_event_id_idx ON public.event_routes USING btree (event_id);