Grundgerüst mit Server, PIN-Anmeldung und Docker-Deploy aufbauen
Die alte Clip-Auswahl-Oberfläche entfällt. Neu sind ein Express-Server, der im Entwicklungsbetrieb Vite einbindet, eine PIN-Anmeldung mit signiertem Sitzungs-Cookie und ein Docker-Image mit ffmpeg für VCH. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
8ed1396b1c
commit
f7d249f28b
23 files changed
+4456
-1358
No files matched your search
@@ -0,0 +1,61 @@
|
||||
import express from 'express';
|
||||
import {
|
||||
SESSION_COOKIE,
|
||||
SESSION_MAX_AGE_MS,
|
||||
createLoginLimiter,
|
||||
createToken,
|
||||
pinMatches,
|
||||
readCookie,
|
||||
verifyToken,
|
||||
} from './auth.js';
|
||||
|
||||
export function createApp({ config, secret }) {
|
||||
const app = express();
|
||||
app.disable('x-powered-by');
|
||||
app.set('trust proxy', true);
|
||||
|
||||
const limiter = createLoginLimiter();
|
||||
const isAuthenticated = (req) =>
|
||||
verifyToken(secret, config.pin, readCookie(req, SESSION_COOKIE));
|
||||
|
||||
app.get('/healthz', (req, res) => res.json({ ok: true }));
|
||||
|
||||
app.use('/api', express.json({ limit: '100kb' }));
|
||||
|
||||
app.get('/api/session', (req, res) => {
|
||||
res.json({ authenticated: isAuthenticated(req), pinConfigured: Boolean(config.pin) });
|
||||
});
|
||||
|
||||
app.post('/api/login', (req, res) => {
|
||||
if (limiter.isBlocked()) {
|
||||
return res.status(429).json({ error: 'Zu viele Fehlversuche. Bitte später erneut versuchen.' });
|
||||
}
|
||||
if (!pinMatches(config.pin, req.body?.pin)) {
|
||||
limiter.recordFailure();
|
||||
return res.status(401).json({ error: 'PIN falsch.' });
|
||||
}
|
||||
limiter.reset();
|
||||
res.cookie(SESSION_COOKIE, createToken(secret, config.pin), {
|
||||
httpOnly: true,
|
||||
sameSite: 'lax',
|
||||
secure: req.secure,
|
||||
maxAge: SESSION_MAX_AGE_MS,
|
||||
path: '/',
|
||||
});
|
||||
res.json({ authenticated: true });
|
||||
});
|
||||
|
||||
app.post('/api/logout', (req, res) => {
|
||||
res.clearCookie(SESSION_COOKIE, { path: '/' });
|
||||
res.json({ authenticated: false });
|
||||
});
|
||||
|
||||
app.use('/api', (req, res, next) => {
|
||||
if (!isAuthenticated(req)) return res.status(401).json({ error: 'Nicht angemeldet.' });
|
||||
next();
|
||||
});
|
||||
|
||||
app.use('/api', (req, res) => res.status(404).json({ error: 'Nicht gefunden.' }));
|
||||
|
||||
return app;
|
||||
}
|
||||
Reference in new issue
Block a user