Feature 4: Webinterface — React-Frontend, Discord-OAuth2, REST-API
- Discord-OAuth2-Login (identify-Scope, CSRF-State, signierte Session-Cookies, keine Token-Speicherung) - REST-API: /api/devlogs (öffentlich), /api/commits (nur ADMIN_DISCORD_ID), /api/me - React + Vite Frontend: Devlog-Archiv mit Mini-Markdown-Renderer, Commit-Tabelle, dunkles EcoGame-Theme - Fastify liefert frontend/dist mit SPA-Fallback aus; Vite-Dev-Proxy für lokale Entwicklung - Multi-Stage-Dockerfile (Frontend-Build im Image), neue Env-Vars in Compose + .env.example - README: OAuth2-Setup (Redirect-URLs, Client Secret) und Frontend-Workflow Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
// REST-API fürs Webinterface: Devlogs öffentlich, Commits nur für den Admin
|
||||
import { listDevlogs, listCommits } from '../db.js';
|
||||
import { getSessionUser, isAdmin } from './auth.js';
|
||||
|
||||
const PAGE_SIZE = 20;
|
||||
|
||||
/** Query-Parameter ?page=1.. in LIMIT/OFFSET übersetzen */
|
||||
function paging(request) {
|
||||
const page = Math.max(1, Number(request.query.page) || 1);
|
||||
return { limit: PAGE_SIZE, offset: (page - 1) * PAGE_SIZE, page };
|
||||
}
|
||||
|
||||
export function registerApiRoutes(app) {
|
||||
// Wer bin ich? (fürs Frontend: Login-Status + Admin-Flag)
|
||||
app.get('/api/me', async (request) => {
|
||||
const user = getSessionUser(request);
|
||||
return user ? { user, admin: isAdmin(user) } : { user: null, admin: false };
|
||||
});
|
||||
|
||||
// Devlog-Archiv — öffentlich (wie der Discord-Kanal)
|
||||
app.get('/api/devlogs', async (request) => {
|
||||
const { limit, offset, page } = paging(request);
|
||||
const { items, total } = listDevlogs(limit, offset);
|
||||
return { items, total, page, pageSize: PAGE_SIZE };
|
||||
});
|
||||
|
||||
// Commit-Feed — nur für den Admin (spiegelt den privaten #-gitea-Kanal)
|
||||
app.get('/api/commits', async (request, reply) => {
|
||||
const user = getSessionUser(request);
|
||||
if (!user) return reply.code(401).send({ error: 'login required' });
|
||||
if (!isAdmin(user)) return reply.code(403).send({ error: 'admin only' });
|
||||
|
||||
const { limit, offset, page } = paging(request);
|
||||
const { items, total } = listCommits(limit, offset);
|
||||
return { items, total, page, pageSize: PAGE_SIZE };
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user