As a project maintainer, I'd like to be able to control whether Discord users can use certain slash commands based on the permissions associated with their roles.
🧠 Context
At the time of writing this issue, we have 3 slash commands included in our Discord bot. Currently, any server member can run them, but we only actually process requests from users listed in data/githubDiscordMap.json.
Today, we use a method src/infrastructure/discord/authz.ts#can that simply checks whether the current Discord user's ID is found in githubDiscordMap.
We want to change this. Instead of just checking for inclusion, the can method should verify whether the current user has all required permissions like "githubIssue:write" or "githubIssue:read".
🔄 Proposed Design
We’ll split role definitions and user-role assignments into two files for maintainability.
data/roles.json
Defines named roles and their permissions:
{
"admin": {
"permissions": ["githubIssue:write", "githubIssue:read"]
},
"readonly": {
"permissions": ["githubIssue:read"]
}
}
data/githubDiscordMap.json
Maps Discord users to roles:
{
"AJaccP": {
"githubUsername": "...",
"githubId": "...",
"discordId": "...",
"roles": ["admin"]
},
"eros-mcguire": {
"githubUsername": "...",
"githubId": "...",
"discordId": "...",
"roles": ["readonly"]
}
}
🛠️ Implementation Plan
-
Update authz.ts
- Load both
roles.json and githubDiscordMap.json
- Update the
can method to check if the user’s roles include all required permissions
export const can = (interaction: any, requiredPermissions: string[]): boolean => {
const userId = interaction.user.id;
// Find user in githubDiscordMap
const userEntry = Object.values(githubDiscordMap).find(entry => entry.discordId === userId);
if (!userEntry || !userEntry.roles) return false;
// Aggregate permissions from all roles
const userPermissions = new Set(
userEntry.roles.flatMap(role => roles[role]?.permissions || [])
);
// Ensure user has all required permissions
return requiredPermissions.every(perm => userPermissions.has(perm));
};
-
Write Unit Tests
-
Create test/infrastructure/discord/authz.test.ts
-
Mock githubDiscordMap and roles.json data
-
Write test cases to verify:
- User with correct roles can access
- User with missing permissions is denied
- Users with multiple roles get merged permissions
-
Refactor existing uses of can()
- Update all invocations of
can(interaction) to use can(interaction, [...permissions])
✅ Acceptance Criteria
As a project maintainer, I'd like to be able to control whether Discord users can use certain slash commands based on the permissions associated with their roles.
🧠 Context
At the time of writing this issue, we have 3 slash commands included in our Discord bot. Currently, any server member can run them, but we only actually process requests from users listed in
data/githubDiscordMap.json.Today, we use a method
src/infrastructure/discord/authz.ts#canthat simply checks whether the current Discord user's ID is found ingithubDiscordMap.We want to change this. Instead of just checking for inclusion, the
canmethod should verify whether the current user has all required permissions like"githubIssue:write"or"githubIssue:read".🔄 Proposed Design
We’ll split role definitions and user-role assignments into two files for maintainability.
data/roles.jsonDefines named roles and their permissions:
{ "admin": { "permissions": ["githubIssue:write", "githubIssue:read"] }, "readonly": { "permissions": ["githubIssue:read"] } }data/githubDiscordMap.jsonMaps Discord users to roles:
{ "AJaccP": { "githubUsername": "...", "githubId": "...", "discordId": "...", "roles": ["admin"] }, "eros-mcguire": { "githubUsername": "...", "githubId": "...", "discordId": "...", "roles": ["readonly"] } }🛠️ Implementation Plan
Update
authz.tsroles.jsonandgithubDiscordMap.jsoncanmethod to check if the user’s roles include all required permissionsWrite Unit Tests
Create
test/infrastructure/discord/authz.test.tsMock
githubDiscordMapandroles.jsondataWrite test cases to verify:
Refactor existing uses of
can()can(interaction)to usecan(interaction, [...permissions])✅ Acceptance Criteria
A
roles.jsonfile exists indata/defining roles and associated permissionsThe structure of
githubDiscordMap.jsonincludes arolesarray per userauthz.ts#canfunction has been updated to check user permissions via rolesAt least 5 unit tests cover:
githubDiscordMapNo existing command functionality breaks due to the change (all existing tests should based once you update mock data)