From d3890cc191f2daa586784973124bf2e4dc460343 Mon Sep 17 00:00:00 2001 From: Z8MB1E Date: Wed, 19 Aug 2026 19:48:28 -0400 Subject: [PATCH] feat(discord): integrate RBAC into Discord bot Replace legacy role-name checks in isStaff with hasPermission(discord:staff). Auto-assign the 'user' role document on signup. Import hasPermission in announce command for future permission gating. --- src/bot/commands/announce.ts | 1 + src/bot/lib/roles.ts | 3 ++- src/bot/services/signup.ts | 11 +++++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/bot/commands/announce.ts b/src/bot/commands/announce.ts index b3d8816..2b566ce 100644 --- a/src/bot/commands/announce.ts +++ b/src/bot/commands/announce.ts @@ -7,6 +7,7 @@ import { import type { BotCommand } from "./index"; import { botConfig } from "@/bot/config"; import { isStaff } from "@/bot/lib/roles"; +import { hasPermission } from "@/utils/access-control/hasPermission"; const ANNOUNCE_COLOR = 0xf59e0b; diff --git a/src/bot/lib/roles.ts b/src/bot/lib/roles.ts index e5abde1..9c485c0 100644 --- a/src/bot/lib/roles.ts +++ b/src/bot/lib/roles.ts @@ -2,6 +2,7 @@ import type { GuildMember } from "discord.js"; import type { Payload } from "payload"; import { botConfig } from "@/bot/config"; import { findUserByDiscordId } from "@/bot/lib/resolve"; +import { hasPermission } from "@/utils/access-control/hasPermission"; export const isStaff = async (member: GuildMember, payload: Payload): Promise => { if (member.roles.cache.some((role) => botConfig.staffRoleIds.includes(role.id))) { @@ -9,5 +10,5 @@ export const isStaff = async (member: GuildMember, payload: Payload): Promise role === "admin" || role === "developer"); + return await hasPermission(payload, user, "discord:staff"); }; diff --git a/src/bot/services/signup.ts b/src/bot/services/signup.ts index 3505885..ebca8b6 100644 --- a/src/bot/services/signup.ts +++ b/src/bot/services/signup.ts @@ -48,6 +48,16 @@ export const createDiscordUser = async ( input: SignupInput, ): Promise<{ user: User; tempPassword: string }> => { const tempPassword = generateTempPassword(); + + const userRole = await payload.find({ + collection: "roles", + where: { slug: { equals: "user" } }, + limit: 1, + depth: 0, + overrideAccess: true, + }); + const userRoleId = userRole.docs[0]?.id; + const user = await payload.create({ collection: "users", data: { @@ -57,6 +67,7 @@ export const createDiscordUser = async ( displayName: input.displayName, steamId: input.steamId, roles: ["user"], + roleDocs: userRoleId ? [userRoleId] : [], password: tempPassword, }, overrideAccess: true,