fix discord admin id stuff

This commit is contained in:
legop3
2026-09-15 13:18:24 -04:00
parent 3b585b06b4
commit 73255831f1
3 changed files with 34 additions and 12 deletions
+1
View File
@@ -473,6 +473,7 @@ Implemented on 2026-09-14:
- Fixed production WAL-mode snapshots creating unmanifested SQLite `-wal` and `-shm` files during schema inspection. Backup and restore validation now remove only those temporary staged sidecars before archiving or applying data, and the regression fixture uses WAL mode to match the real databases. - Fixed production WAL-mode snapshots creating unmanifested SQLite `-wal` and `-shm` files during schema inspection. Backup and restore validation now remove only those temporary staged sidecars before archiving or applying data, and the regression fixture uses WAL mode to match the real databases.
- Added the early streaming `/video` middleware with `http-proxy-middleware`. Express removes the public prefix before forwarding WHEP/WHIP requests to `127.0.0.1:8889`, while root-relative MediaMTX session locations receive the prefix again so subsequent browser `PATCH` and `DELETE` requests follow the same path. MediaMTX signaling now binds to loopback; its ICE UDP/TCP listener remains directly reachable on port 8189. - Added the early streaming `/video` middleware with `http-proxy-middleware`. Express removes the public prefix before forwarding WHEP/WHIP requests to `127.0.0.1:8889`, while root-relative MediaMTX session locations receive the prefix again so subsequent browser `PATCH` and `DELETE` requests follow the same path. MediaMTX signaling now binds to loopback; its ICE UDP/TCP listener remains directly reachable on port 8189.
- Replaced Discord's `siteUrl`, the inter-instance profile's `publicUrl`, and media `whepBaseUrl` with one top-level `publicUrl`. A numbered internal database migration transforms every saved configuration revision before current validation, and the media section now contains only optional additional ICE hosts. WHEP and microphone WHIP URLs are fixed relative paths, so they work through the current origin without knowing its hostname. - Replaced Discord's `siteUrl`, the inter-instance profile's `publicUrl`, and media `whepBaseUrl` with one top-level `publicUrl`. A numbered internal database migration transforms every saved configuration revision before current validation, and the media section now contains only optional additional ICE hosts. WHEP and microphone WHIP URLs are fixed relative paths, so they work through the current origin without knowing its hostname.
- Discord command authorization and lockdown moderation recipients now read the live administrator registry, so setup imports and later Discord-ID or role edits take effect without restarting the server.
- Fixed inter-instance public payload generation to read feature flags and social links from the same live configuration revision. Social links enabled through the new configuration system no longer trigger an undefined legacy-config reference and an HTTP 500 response. - Fixed inter-instance public payload generation to read feature flags and social links from the same live configuration revision. Social links enabled through the new configuration system no longer trigger an undefined legacy-config reference and an HTTP 500 response.
Local verification completed: Local verification completed:
+26 -9
View File
@@ -90,12 +90,7 @@ const {
const config = structuredClone(loadConfig()); const config = structuredClone(loadConfig());
const discordConfig = config.discord || {}; const discordConfig = config.discord || {};
let enabled = Boolean(discordConfig.enabled); let enabled = Boolean(discordConfig.enabled);
// These normalized command names mirror the command router. Bridge-channel const configurationDatabase = getConfigurationDatabase();
// command replies are mirrored into web chat, so this entrypoint needs to know
// the configured command names before it wraps message.reply.
const configuredAdministrators = getConfigurationDatabase().listAdministrators();
const adminIds = new Set(configuredAdministrators.map((admin) => String(admin.discordId || '').trim()).filter(Boolean));
const lockdownAdminIds = new Set(configuredAdministrators.filter((admin) => admin.role === 'lockdown').map((admin) => String(admin.discordId || '').trim()).filter(Boolean));
if (!enabled) logger.info('Discord disabled by config'); if (!enabled) logger.info('Discord disabled by config');
@@ -122,12 +117,34 @@ function sanitizeMentions(text) {
.replace(/@here/gi, '[here]'); .replace(/@here/gi, '[here]');
} }
function findDiscordAdministrator(discordId) {
const normalizedDiscordId = String(discordId || '').trim();
if (!normalizedDiscordId) return null;
// Read the administrator registry at the moment Discord checks permission.
// Setup imports and administrator edits happen after this module starts, so
// a startup-only Set would remain stale until the whole server restarted.
return configurationDatabase.listAdministrators().find(
(administrator) => String(administrator.discordId || '').trim() === normalizedDiscordId,
) || null;
}
function isAdminUser(discordId) { function isAdminUser(discordId) {
return adminIds.has(String(discordId || '').trim()); return Boolean(findDiscordAdministrator(discordId));
} }
function isLockdownAdminUser(discordId) { function isLockdownAdminUser(discordId) {
return lockdownAdminIds.has(String(discordId || '').trim()); return findDiscordAdministrator(discordId)?.role === 'lockdown';
}
function getLockdownAdminIds() {
// Moderation requests use the same live registry as command authorization,
// ensuring newly imported or edited lockdown accounts receive DMs without a
// restart or a second cache-synchronization system.
return configurationDatabase.listAdministrators()
.filter((administrator) => administrator.role === 'lockdown')
.map((administrator) => String(administrator.discordId || '').trim())
.filter(Boolean);
} }
function countReady() { function countReady() {
@@ -301,7 +318,7 @@ const commands = createCommandHandlers(commandDependencies);
getPrivateAccessRequestByMessageId, getPrivateAccessRequestByMessageId,
approvePrivateAccessRequest, approvePrivateAccessRequest,
denyPrivateAccessRequest, denyPrivateAccessRequest,
lockdownAdminIds, getLockdownAdminIds,
isAdminUser, isAdminUser,
isLockdownAdminUser, isLockdownAdminUser,
sendToChannel: channelIO.sendToChannel, sendToChannel: channelIO.sendToChannel,
@@ -5,7 +5,7 @@ function createDmModerationHandlers(deps) {
const { const {
logger, logger,
client, client,
lockdownAdminIds, getLockdownAdminIds,
attachDmMessage, attachDmMessage,
getRequestByMessageId, getRequestByMessageId,
approveRequest, approveRequest,
@@ -36,7 +36,9 @@ function createDmModerationHandlers(deps) {
'', '',
`React with ${APPROVE} to approve or ${DENY} to deny.`, `React with ${APPROVE} to approve or ${DENY} to deny.`,
].join('\n'); ].join('\n');
await Promise.all(Array.from(lockdownAdminIds).map(async (adminId) => { // Resolve recipients when the request occurs so setup imports and account
// edits take effect immediately instead of waiting for a server restart.
await Promise.all(getLockdownAdminIds().map(async (adminId) => {
try { try {
const user = await client.users.fetch(String(adminId)); const user = await client.users.fetch(String(adminId));
if (!user) return; if (!user) return;
@@ -69,7 +71,9 @@ function createDmModerationHandlers(deps) {
'', '',
`React with ${APPROVE} to approve or ${DENY} to deny.`, `React with ${APPROVE} to approve or ${DENY} to deny.`,
].join('\n'); ].join('\n');
await Promise.all(Array.from(lockdownAdminIds).map(async (adminId) => { // Keep private-access moderation on the same live administrator registry
// used by command authorization and verification requests.
await Promise.all(getLockdownAdminIds().map(async (adminId) => {
try { try {
const user = await client.users.fetch(String(adminId)); const user = await client.users.fetch(String(adminId));
if (!user) return; if (!user) return;