feat: mehrere Rollen duerfen herein, nicht nur eine

Wer EINE der eingetragenen Rollen hat, kommt ins Dashboard. Mehrere sind der
Normalfall, sobald mehr als eine Person Zugang haben soll -- Admin und Fotograf
sind selten dieselbe Rolle.

Die bisherige einzelne Rolle geht NICHT verloren: der alte Schluessel
(discord.role_id) wird weitergelesen, bis die Liste einmal gepflegt wird; dann
raeumt das Speichern ihn weg. Zwei Quellen fuer dieselbe Frage laufen sonst
auseinander. Nachgemessen: die vorhandene Rolle stand nach dem Umbau
unveraendert drin, bereit blieb true.

Getrennt wird an Komma, Semikolon, Leerzeichen und Zeilenumbruch -- wer drei
IDs untereinander aus Discord kopiert, soll sie nicht erst zu einer Zeile
zusammenschieben. Doppelte fallen zusammen.

UND DIE SCHLECHTE WIRD BEIM NAMEN GENANNT: "123 ist keine Rollen-ID (17 bis 20
Ziffern)" statt "Rollen-ID ungueltig". Bei fuenf Eintraegen ist die zweite
Meldung eine Suchaufgabe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-11 18:53:28 +02:00
co-authored by Claude Opus 5
parent 1c5bf20eb0
commit 23405d68d3
5 changed files with 93 additions and 30 deletions
+32 -8
View File
@@ -597,7 +597,7 @@ dashRoutes.get('/settings', (c) => {
discord: {
clientId: d.clientId,
guildId: d.guildId,
roleId: d.roleId,
roleIds: d.roleIds,
hatGeheimnis: Boolean(d.clientSecret),
bereit: d.bereit,
// Die Stelle, an der der erste Anlauf fast immer scheitert.
@@ -607,7 +607,10 @@ dashRoutes.get('/settings', (c) => {
clientSecret:
Boolean(d.clientSecret) && !ausDatenbank(DISCORD_KEYS.clientSecret),
guildId: Boolean(d.guildId) && !ausDatenbank(DISCORD_KEYS.guildId),
roleId: Boolean(d.roleId) && !ausDatenbank(DISCORD_KEYS.roleId),
roleIds:
d.roleIds.length > 0 &&
!ausDatenbank(DISCORD_KEYS.roleIds) &&
!ausDatenbank(DISCORD_KEYS.roleIdAlt),
},
},
})
@@ -619,7 +622,7 @@ dashRoutes.post('/settings', async (c) => {
clientId?: string
clientSecret?: string
guildId?: string
roleId?: string
roleIds?: string | string[]
}
}>(c)
if (!body) return c.json(KEIN_JSON, 400)
@@ -642,10 +645,31 @@ dashRoutes.post('/settings', async (c) => {
if (v && !istId(v)) return c.json({ error: 'Server-ID: 17 bis 20 Ziffern' }, 400)
setSetting(DISCORD_KEYS.guildId, v)
}
if (d.roleId !== undefined) {
const v = d.roleId.trim()
if (v && !istId(v)) return c.json({ error: 'Rollen-ID: 17 bis 20 Ziffern' }, 400)
setSetting(DISCORD_KEYS.roleId, v)
if (d.roleIds !== undefined) {
// Komma, Semikolon, Leerzeichen, Zeilenumbruch — alles trennt. Wer
// drei IDs untereinander einfuegt, soll sie nicht erst zu einer Zeile
// zusammenschieben muessen.
const liste = (Array.isArray(d.roleIds) ? d.roleIds.join(',') : d.roleIds)
.split(/[\s,;]+/)
.map((t) => t.trim())
.filter(Boolean)
// JEDE einzeln pruefen und die schlechte BEIM NAMEN nennen. "Rollen-ID
// ungueltig" bei fuenf Eintraegen ist eine Suchaufgabe, keine Meldung.
for (const eintrag of liste) {
if (!istId(eintrag)) {
return c.json(
{ error: `"${eintrag}" ist keine Rollen-ID (17 bis 20 Ziffern)` },
400,
)
}
}
const eindeutig = [...new Set(liste)]
setSetting(DISCORD_KEYS.roleIds, eindeutig.join(','))
// Den alten Einzelwert raeumen wir weg, sobald die Liste gepflegt
// wird: zwei Quellen fuer dieselbe Frage laufen sonst auseinander.
setSetting(DISCORD_KEYS.roleIdAlt, '')
}
// Ein leeres Feld heisst "unveraendert lassen", nicht "loeschen" — sonst
// wuerde jedes Speichern das Geheimnis wegwerfen, weil es nie im Formular
@@ -664,7 +688,7 @@ dashRoutes.post('/settings', async (c) => {
!jetzt.clientId && 'Client-ID',
!jetzt.clientSecret && 'Client-Geheimnis',
!jetzt.guildId && 'Server-ID',
!jetzt.roleId && 'Rollen-ID',
jetzt.roleIds.length === 0 && 'mindestens eine Rollen-ID',
].filter(Boolean),
})
})
+9 -4
View File
@@ -144,10 +144,15 @@ discordRoutes.get('/discord/callback', async (c) => {
}
const member = (await memberAntwort.json()) as { roles?: string[] }
if (!Array.isArray(member.roles) || !member.roles.includes(d.roleId)) {
// Bewusst ohne den Namen der Rolle: wer sie nicht hat, muss auch
// nicht erfahren, wie sie heisst.
return zurueck(c, 'Dir fehlt die noetige Rolle auf dem Server.')
// EINE der eingetragenen Rollen reicht. Mehrere Rollen sind der
// Normalfall, sobald mehr als eine Person Zugang haben soll — Admin
// und Fotograf sind selten dieselbe Rolle.
const hatRolle =
Array.isArray(member.roles) && member.roles.some((r) => d.roleIds.includes(r))
if (!hatRolle) {
// Bewusst ohne die Namen der Rollen: wer keine hat, muss auch nicht
// erfahren, welche es gaebe.
return zurueck(c, 'Dir fehlt eine der noetigen Rollen auf dem Server.')
}
// -- Konto finden oder anlegen --------------------------------------