feat(groups): add fail-closed admission management
CI / validate (push) Successful in 5m13s
Release / release (push) Successful in 7m8s

This commit is contained in:
dmg
2026-08-01 18:36:45 -04:00
parent 19a5d04178
commit b88097c15a
32 changed files with 1910 additions and 29 deletions
@@ -0,0 +1,25 @@
CREATE TABLE "groups" (
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid() NOT NULL,
"name" varchar(50) NOT NULL,
"slug" varchar(50) NOT NULL,
"description" text,
"access_enabled" boolean DEFAULT false NOT NULL,
"is_default" boolean DEFAULT false NOT NULL,
"created_at" timestamp (3) with time zone DEFAULT now() NOT NULL,
"updated_at" timestamp (3) with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
CREATE TABLE "user_group_memberships" (
"user_id" uuid NOT NULL,
"group_id" uuid NOT NULL,
"created_at" timestamp (3) with time zone DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "user_group_memberships" ADD CONSTRAINT "user_group_memberships_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "user_group_memberships" ADD CONSTRAINT "user_group_memberships_group_id_groups_id_fk" FOREIGN KEY ("group_id") REFERENCES "public"."groups"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
CREATE UNIQUE INDEX "groups_slug_uidx" ON "groups" USING btree (lower("slug"));--> statement-breakpoint
CREATE UNIQUE INDEX "groups_one_default_uidx" ON "groups" USING btree ("is_default") WHERE "groups"."is_default" = true;--> statement-breakpoint
CREATE UNIQUE INDEX "user_group_memberships_user_group_uidx" ON "user_group_memberships" USING btree ("user_id","group_id");--> statement-breakpoint
CREATE INDEX "user_group_memberships_group_idx" ON "user_group_memberships" USING btree ("group_id");--> statement-breakpoint
INSERT INTO "groups" ("name", "slug", "description", "access_enabled", "is_default")
VALUES ('everyone', 'everyone', 'Default group containing every registered user.', false, true);
File diff suppressed because it is too large Load Diff
@@ -15,6 +15,13 @@
"when": 1785605590058,
"tag": "0001_silent_ultragirl",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1785623198008,
"tag": "0002_simple_queen_noir",
"breakpoints": true
}
]
}
+1
View File
@@ -113,6 +113,7 @@ export async function findUserBySessionToken(db: Database, tokenHash: string, no
id: users.id,
discordUserId: users.discordUserId,
discordUsername: users.discordUsername,
discordGlobalName: users.discordGlobalName,
firstName: users.firstName,
onboardingCompletedAt: users.onboardingCompletedAt,
sessionExpiresAt: sessions.expiresAt,
+34
View File
@@ -62,6 +62,40 @@ export const users = pgTable(
(table) => [uniqueIndex("users_discord_user_id_uidx").on(table.discordUserId)],
);
export const groups = pgTable(
"groups",
{
id: uuid("id").primaryKey().defaultRandom(),
name: varchar("name", { length: 50 }).notNull(),
slug: varchar("slug", { length: 50 }).notNull(),
description: text("description"),
accessEnabled: boolean("access_enabled").notNull().default(false),
isDefault: boolean("is_default").notNull().default(false),
...timestamps(),
},
(table) => [
uniqueIndex("groups_slug_uidx").on(sql`lower(${table.slug})`),
uniqueIndex("groups_one_default_uidx").on(table.isDefault).where(sql`${table.isDefault} = true`),
],
);
export const userGroupMemberships = pgTable(
"user_group_memberships",
{
userId: uuid("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
groupId: uuid("group_id")
.notNull()
.references(() => groups.id, { onDelete: "cascade" }),
createdAt: createdAt(),
},
(table) => [
uniqueIndex("user_group_memberships_user_group_uidx").on(table.userId, table.groupId),
index("user_group_memberships_group_idx").on(table.groupId),
],
);
export const minecraftAccounts = pgTable(
"minecraft_accounts",
{