Files
planer/src/app/(app)/verwaltung/api/page.tsx
T
Florian WildeandClaude Opus 5 b17c42af56 feat: Tokens verwalten
Anlegen ist Verwaltungssache: Ein Token ist ein Zugang zur ganzen
Anwendung, nicht zu einer Aufgabe.

Beim Anlegen erscheint der Wert ein einziges Mal, mit dem Hinweis, dass
er danach weg ist, und einem curl-Aufruf zum Ausprobieren. Ein Ablauf
laesst sich setzen — ein Token mit Ablauf ist einer, den man nicht
vergisst.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 11:09:36 +02:00

78 lines
2.4 KiB
TypeScript

import type { Metadata } from 'next'
import { KeyRound } from 'lucide-react'
import { TokenVerwaltung } from '@/app/(app)/verwaltung/api/token-verwaltung'
import {
Card,
CardBeschreibung,
CardInhalt,
CardKopf,
CardTitel,
} from '@/components/ui/card'
import { rechteLesen } from '@/lib/api'
import { alsDatumUhrzeit } from '@/lib/zeit'
import { verlangeRolle } from '@/server/berechtigung'
import { db } from '@/server/db'
import { umgebung } from '@/server/umgebung'
export const metadata: Metadata = { title: 'API-Tokens' }
export default async function ApiSeite() {
await verlangeRolle('ADMIN', '/verwaltung/api')
const tokens = await db.apiToken.findMany({
orderBy: [{ widerrufenAm: 'asc' }, { erstelltAm: 'desc' }],
select: {
id: true,
name: true,
praefix: true,
rechte: true,
gueltigBis: true,
letzteNutzung: true,
widerrufenAm: true,
erstelltAm: true,
},
})
const adresse = umgebung().APP_URL
return (
<div className="flex flex-col gap-6">
<div className="flex items-center gap-3">
<KeyRound className="text-gedaempft-vordergrund size-6" aria-hidden />
<div>
<h1 className="text-2xl font-semibold tracking-tight">API-Tokens</h1>
<p className="text-gedaempft-vordergrund text-sm">
Zugänge für fremde Anwendungen — mit so wenig Rechten wie möglich.
</p>
</div>
</div>
<Card>
<CardKopf>
<CardTitel className="text-base">Tokens</CardTitel>
<CardBeschreibung>
Ein Token ist ein Passwort. Er wird beim Anlegen ein einziges Mal angezeigt;
danach liegt in der Datenbank nur noch sein Fingerabdruck. Wer ihn verliert,
legt einen neuen an — nachschlagen lässt er sich nicht.
</CardBeschreibung>
</CardKopf>
<CardInhalt>
<TokenVerwaltung
adresse={adresse}
tokens={tokens.map((t) => ({
id: t.id,
name: t.name,
praefix: t.praefix,
rechte: rechteLesen(t.rechte),
gueltigBis: t.gueltigBis ? alsDatumUhrzeit(t.gueltigBis) : null,
letzteNutzung: t.letzteNutzung ? alsDatumUhrzeit(t.letzteNutzung) : null,
widerrufen: t.widerrufenAm !== null,
erstelltAm: alsDatumUhrzeit(t.erstelltAm),
}))}
/>
</CardInhalt>
</Card>
</div>
)
}