diff --git a/api/resolve_middleware.go b/api/resolve_middleware.go index a2f478f5..a19809f0 100644 --- a/api/resolve_middleware.go +++ b/api/resolve_middleware.go @@ -45,6 +45,10 @@ 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() + } userId, err := trashid.DecodeHashId(c.Params("userId")) if err != nil || userId == 0 { return fiber.NewError(fiber.StatusBadRequest, "invalid userId") diff --git a/api/server.go b/api/server.go index 1c1197de..8674f83d 100644 --- a/api/server.go +++ b/api/server.go @@ -406,6 +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.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 new file mode 100644 index 00000000..c222b726 --- /dev/null +++ b/api/v1_users_ping.go @@ -0,0 +1,27 @@ +package api + +import ( + "github.com/gofiber/fiber/v2" + "go.uber.org/zap" +) + +func (app *ApiServer) postV1UsersPing(c *fiber.Ctx) error { + if app.writePool == nil { + return fiber.NewError(fiber.StatusServiceUnavailable, "writes not available") + } + + wallet := app.getAuthedWallet(c) + + _, err := app.writePool.Exec(c.Context(), ` + UPDATE users + SET last_active_at = now() + WHERE wallet = $1 + AND is_current = true + `, wallet) + 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") + } + + return c.JSON(fiber.Map{"status": "ok"}) +} diff --git a/ddl/migrations/0221_add_users_last_active_at.sql b/ddl/migrations/0221_add_users_last_active_at.sql new file mode 100644 index 00000000..93ec9cdd --- /dev/null +++ b/ddl/migrations/0221_add_users_last_active_at.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE users ADD COLUMN IF NOT EXISTS last_active_at TIMESTAMPTZ DEFAULT NULL; +COMMENT ON COLUMN users.last_active_at IS 'Timestamp of the user''s most recent app-open event, updated by POST /v1/users/me/ping.'; + +COMMIT;