Add multi-guild Discord OAuth support

- Users can now login via Bacanaks OR Piccadilly Discord server
- Highest role from all servers is used (superadmin > moderator > user)
- Lazy initialization fixes env loading timing issue
- Updated documentation with implementation details and troubleshooting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-08 00:30:15 +01:00
parent 4fcc111def
commit 20ba93b26f
3 changed files with 260 additions and 31 deletions

23
auth.js
View File

@@ -2,7 +2,7 @@ import { Router } from 'express';
import jwt from 'jsonwebtoken';
import { db, VALID_ROLES, initDiscordUsers } from '../db/init.js';
import { authenticateToken, requireRole } from '../middleware/auth.js';
import { getDiscordAuthUrl, exchangeCode, getDiscordUser, getGuildMember, getUserRole } from '../services/discord.js';
import { getDiscordAuthUrl, exchangeCode, getDiscordUser, getGuildMember, getGuildMemberships, getUserRole, getUserRoleFromMemberships } from '../services/discord.js';
const router = Router();
@@ -38,15 +38,18 @@ router.get('/discord/callback', async (req, res) => {
// Get Discord user info
const discordUser = await getDiscordUser(tokenData.access_token);
// Check if user is in the guild
const member = await getGuildMember(discordUser.id);
// Check if user is in any of the configured guilds
const memberships = await getGuildMemberships(discordUser.id);
if (!member) {
if (!memberships) {
return res.redirect(`${frontendUrl}/login?error=not_in_guild`);
}
// Determine role based on Discord roles
const role = getUserRole(member.roles);
// Determine role based on Discord roles (highest role from all servers)
const role = getUserRoleFromMemberships(memberships);
// Use first membership for display name
const member = memberships[0].member;
// Get display name (nickname or username)
const displayName = member.nick || discordUser.global_name || discordUser.username;
@@ -126,13 +129,13 @@ router.post('/refresh-role', authenticateToken, async (req, res) => {
}
try {
const member = await getGuildMember(req.user.discordId);
const memberships = await getGuildMemberships(req.user.discordId);
if (!member) {
return res.status(403).json({ error: 'No longer in guild' });
if (!memberships) {
return res.status(403).json({ error: 'No longer in any guild' });
}
const newRole = getUserRole(member.roles);
const newRole = getUserRoleFromMemberships(memberships);
db.prepare('UPDATE discord_users SET role = ?, updated_at = CURRENT_TIMESTAMP WHERE discord_id = ?')
.run(newRole, req.user.discordId);