Restrict platform-list edits to admins
Anyone authenticated can still read the shared platform list, but only an
admin may add, rename or delete from it.
- users.is_admin boolean, defaulting to false. The very first account ever
registered becomes an admin automatically (CreateUser's INSERT uses
NOT EXISTS (SELECT 1 FROM users) for is_admin), so there's always at
least one without manual setup; promoting anyone beyond that is a manual
UPDATE for now (documented in the migration's comment on the column).
- GetSessionAndUser, GetUserByEmail and GetUserByID now also select
is_admin, and it flows through to model.User (and so to
/api/auth/{register,login,me}'s response) and to the auth middleware's
authedUser.
- New requireAdminMiddleware + addAdminAuth, layered on top of the existing
auth middleware. Wired onto create/update/delete-platform; list/get stay
on plain addAuth, since reading the list only requires being logged in.
Verified end to end: the first registered user comes back is_admin:true,
the second false; the non-admin gets 403 on create/update/delete-platform
but 200 on list; the admin can do all of it.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7fbd403d30
commit
384c4a7217
12 files changed
+110
-35
No files matched your search
@@ -42,10 +42,12 @@ func RegisterRoutes(api huma.API, queries db.Querier) {
|
||||
|
||||
// --- Platform Routes ---
|
||||
//
|
||||
// Platforms are a shared list: every authenticated user reads and writes
|
||||
// the same rows, unlike games, which are private per user. Routes still
|
||||
// require auth (so the list isn't public), but none of the queries below
|
||||
// filter by user_id, because platform has no such column.
|
||||
// Platforms are a shared list: every authenticated user reads the same
|
||||
// rows, unlike games, which are private per user. None of the queries
|
||||
// below filter by user_id, because platform has no such column. Reading
|
||||
// the list only requires being logged in (addAuth); adding, renaming or
|
||||
// deleting a platform requires being an admin (addAdminAuth), since that
|
||||
// changes what everyone else sees.
|
||||
|
||||
func registerPlatformRoutes(api huma.API, queries db.Querier) {
|
||||
listOp := huma.Operation{
|
||||
@@ -90,7 +92,7 @@ func registerPlatformRoutes(api huma.API, queries db.Querier) {
|
||||
Path: "/api/platforms",
|
||||
Summary: "Create Platform",
|
||||
}
|
||||
addAuth(&createOp, api, queries)
|
||||
addAdminAuth(&createOp, api, queries)
|
||||
huma.Register(api, createOp, func(ctx context.Context, input *struct{ Body model.PlatformInput }) (*struct{ Body model.Platform }, error) {
|
||||
platform, err := queries.CreatePlatform(ctx, input.Body.Name)
|
||||
if err != nil {
|
||||
@@ -105,7 +107,7 @@ func registerPlatformRoutes(api huma.API, queries db.Querier) {
|
||||
Path: "/api/platforms/{id}",
|
||||
Summary: "Update Platform",
|
||||
}
|
||||
addAuth(&updateOp, api, queries)
|
||||
addAdminAuth(&updateOp, api, queries)
|
||||
huma.Register(api, updateOp, func(ctx context.Context, input *struct {
|
||||
ID uuid.UUID `path:"id"`
|
||||
Body model.PlatformInput
|
||||
@@ -126,7 +128,7 @@ func registerPlatformRoutes(api huma.API, queries db.Querier) {
|
||||
Path: "/api/platforms/{id}",
|
||||
Summary: "Delete Platform",
|
||||
}
|
||||
addAuth(&deleteOp, api, queries)
|
||||
addAdminAuth(&deleteOp, api, queries)
|
||||
huma.Register(api, deleteOp, func(ctx context.Context, input *struct {
|
||||
ID uuid.UUID `path:"id"`
|
||||
}) (*struct{}, error) {
|
||||
|
||||
Reference in new issue
Block a user