feat: Discord-Anmeldung -- im Panel einrichtbar, nicht in der .env
Auf Wunsch ueber die Oberflaeche statt ueber Umgebungsvariablen. Der Gewinn ist
nicht nur Bequemlichkeit: das Panel legt die REDIRECT-URI zum Kopieren hin, und
genau daran scheitert ein OAuth-Anlauf fast immer.
settings.ts Schluessel/Wert in SQLite, mit Umgebung als Rueckfall. Wer
schon Stack-Variablen gesetzt hat, behaelt sie; das Panel
uebersteuert. In der Umgebung bleibt, was den Dienst ueberhaupt
erreichbar macht (PUBLIC_URL, PORT, DATA_DIR) -- wer das per
Formular verstellen koennte, sperrt sich mit einem Klick aus.
discord.ts Der Weg in drei Schritten, ohne Bibliothek und OHNE BOT-TOKEN:
die Rolle wird mit dem Merkmal des BENUTZERS geholt
(guilds.members.read). Kein Bot, keine Bot-Rechte, kein zweites
Geheimnis, das ablaufen kann.
DAS GEHEIMNIS GEHT NIE HERAUS -- auch nicht an eine angemeldete Sitzung. Das
Panel bekommt nur "hatGeheimnis: true". Ein Formular, das den Client-Schluessel
im Klartext zurueckschickt, streut ihn in jeden Browser-Cache. Ein leeres Feld
heisst "unveraendert", nicht "loeschen"; zum Entfernen gibt es "-".
JEDER ABBRUCH IST SICHTBAR: kein weisser Bildschirm, sondern zurueck aufs
Formular mit dem Grund im Adressfeld -- "Du bist nicht auf diesem Server",
"Dir fehlt die noetige Rolle", oder bei 4xx vom Tausch der Hinweis auf die
Redirect-URI. Die IDs werden schon beim Speichern geprueft (17-20 Ziffern),
damit ein halber Link nicht erst beim Anmelden auffaellt.
Das Passwort bleibt als Notausgang. Ein ueber Discord angelegtes Konto bekommt
KEIN brauchbares Passwort ("nur-ueber-discord"): verifyPassword scheitert an
allem, was nicht dem scrypt-Format entspricht -- nachgesehen, nicht vermutet.
Dazu der Verlauf, wie gewuenscht: Suche nach Pfad (mit derselben
LIKE-Maskierung wie in der Galerie -- Suche nach "_" findet 0 statt allem),
waehlbare Seitengroesse (25/50/100/200, Standard 50) und mehr Luft zwischen
"Groesse" und "Von wem".
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -91,8 +91,33 @@ CREATE TABLE IF NOT EXISTS events (
|
||||
actor TEXT NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS events_at ON events(at DESC);
|
||||
|
||||
-- Einstellungen, die zur Laufzeit aenderbar sein sollen.
|
||||
--
|
||||
-- Bewusst NICHT alles: was den Dienst ueberhaupt hochfahren laesst (PUBLIC_URL,
|
||||
-- Port, Datenordner) bleibt in der Umgebung, damit ein falscher Klick den
|
||||
-- Dienst nicht unerreichbar macht. Hier liegt nur, was ohne Neustart
|
||||
-- verstellbar sein soll -- derzeit die Discord-Anmeldung.
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
key TEXT PRIMARY KEY,
|
||||
value TEXT NOT NULL,
|
||||
updated_at INTEGER NOT NULL
|
||||
);
|
||||
`)
|
||||
|
||||
// Nachtraegliche Spalten. SQLite kann kein "ADD COLUMN IF NOT EXISTS", also
|
||||
// wird nachgesehen — das ist die ganze Wanderung, die dieses Projekt braucht.
|
||||
{
|
||||
const spalten = db.prepare('PRAGMA table_info(users)').all() as { name: string }[]
|
||||
if (!spalten.some((s) => s.name === 'discord_id')) {
|
||||
db.exec('ALTER TABLE users ADD COLUMN discord_id TEXT')
|
||||
// Kein UNIQUE in der Spaltendefinition: SQLite erlaubt das bei ADD
|
||||
// COLUMN nicht. Der Index danach leistet dasselbe.
|
||||
db.exec('CREATE UNIQUE INDEX IF NOT EXISTS users_discord ON users(discord_id)')
|
||||
console.log('[db] Spalte users.discord_id angelegt')
|
||||
}
|
||||
}
|
||||
|
||||
// Den Verlauf aus dem vorhandenen Bestand nachtragen -- einmalig, und nur
|
||||
// wenn er leer ist.
|
||||
//
|
||||
@@ -123,6 +148,9 @@ export type User = {
|
||||
username: string
|
||||
password_hash: string
|
||||
created_at: number
|
||||
/** Gesetzt, wenn dieses Konto ueber Discord hereinkommt. Ein solches Konto
|
||||
* hat kein brauchbares Passwort — verifyPassword scheitert daran sauber. */
|
||||
discord_id: string | null
|
||||
}
|
||||
|
||||
export type Token = {
|
||||
|
||||
Reference in New Issue
Block a user