Entscheidungen vom 04.10.2026: - Projekt-Routen (website-projects, preview, gitea, services, analyse) fuer jeden Mitarbeiter (Label mitarbeiter oder admin); Kunden-, Mitarbeiter- und Finanz-Verwaltung bleiben nur fuer Admins - Neue Repos aus der Vorlage werden privat angelegt - Archivierte Projekte sieht der Kunde nicht mehr: Projektliste, Projektdetails, Preview-Zugang, Funktionen (Mitarbeiter-Ansicht schon) - Projektliste des Kunden mit Limit (Appwrite liefert sonst nur 25) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
1.9 KiB
JavaScript
59 lines
1.9 KiB
JavaScript
import { config } from '../config.js'
|
|
import { ADMIN_LABEL, STAFF_LABELS } from '../services/staffLabels.js'
|
|
|
|
/**
|
|
* Prueft das Appwrite-JWT aus dem Ticketsystem und verlangt eines der Labels `allowed`.
|
|
* requireAppwriteStaff: nur "admin" (Kunden, Mitarbeiter, Finanzen ...).
|
|
* requireAppwriteTeam: jeder Mitarbeiter ("mitarbeiter" oder "admin") - Projekt-Aktionen
|
|
* (Anlegen, Zuordnen, Archivieren, Preview, Analyse, Gitea-Import), Entscheidung 2026-10-04.
|
|
*/
|
|
function requireAppwriteLabels(allowed, deniedMessage) {
|
|
return (req, res, next) => checkAppwriteJwt(req, res, next, allowed, deniedMessage)
|
|
}
|
|
|
|
export const requireAppwriteStaff = requireAppwriteLabels([ADMIN_LABEL], 'Admin-Berechtigung erforderlich')
|
|
export const requireAppwriteTeam = requireAppwriteLabels(STAFF_LABELS, 'Nur für Mitarbeiter')
|
|
|
|
async function checkAppwriteJwt(req, res, next, allowed, deniedMessage) {
|
|
const authHeader = req.get('Authorization') || ''
|
|
const match = authHeader.match(/^Bearer\s+(.+)$/i)
|
|
if (!match) {
|
|
return res.status(401).json({ error: 'Authorization Bearer JWT erforderlich' })
|
|
}
|
|
|
|
const jwt = match[1]
|
|
|
|
try {
|
|
const response = await fetch(`${config.appwrite.endpoint}/account`, {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Appwrite-Project': config.appwrite.projectId,
|
|
'X-Appwrite-JWT': jwt,
|
|
},
|
|
})
|
|
|
|
const text = await response.text()
|
|
let data = null
|
|
if (text) {
|
|
try {
|
|
data = JSON.parse(text)
|
|
} catch {
|
|
data = { message: text }
|
|
}
|
|
}
|
|
|
|
if (!response.ok) {
|
|
return res.status(401).json({ error: data?.message || 'Ungültiges JWT' })
|
|
}
|
|
|
|
if (!Array.isArray(data?.labels) || !allowed.some((label) => data.labels.includes(label))) {
|
|
return res.status(403).json({ error: deniedMessage })
|
|
}
|
|
|
|
req.appwriteUser = data
|
|
return next()
|
|
} catch (err) {
|
|
return res.status(500).json({ error: err.message || 'JWT-Validierung fehlgeschlagen' })
|
|
}
|
|
}
|