Files
Webklar-Kundenbereich/server/middleware/session.js
Kenso Grimm 177ee6a13d feat: Admin-Bereich im Kundenportal (Ticketsystem-Login, Projektsuche, Kundenverwaltung)
- Login: Appwrite-User mit Label 'admin' (Ticketsystem-Mitarbeiter) bekommen
  eine Admin-Session und landen auf /admin.html
- Admin-Dashboard: Statistik-Uebersicht, Projektsuche ueber alle Projekte
  (inkl. Preview-/Gitea-Links, Vorschau ohne Kunden-Login), Kundenliste mit
  Portal-Status, letztem Login und Projektanzahl
- Kundennummer (code) direkt im Admin-Bereich pflegbar
- 'Als Kunde ansehen': Admin sieht das Portal exakt wie der Kunde (Banner
  mit Rueckweg zur Admin-Uebersicht)
- Kunden-Dashboard: neue Bereiche 'Meine Rechnungen' (InvoiceNinja inkl.
  Link ins Rechnungsportal) und 'Was wurde gemacht' (Tickets + Worksheets
  aus dem Ticketsystem, ohne interne Akquise-Tickets); Kundennummer im Header
- Admin-API /api/portal-admin/* (Session-basiert), Kunden-API /api/invoices
  und /api/activity
- appwriteClient: uebrig gebliebene Debug-Instrumentierung entfernt

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 17:09:39 +00:00

64 lines
1.6 KiB
JavaScript

import cookieParser from 'cookie-parser'
import { config } from '../config.js'
const SESSION_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000
export function sessionMiddleware() {
return cookieParser(config.sessionSecret)
}
export function setPortalSession(res, data) {
res.cookie(config.cookieName, JSON.stringify(data), {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
maxAge: SESSION_MAX_AGE_MS,
signed: true,
})
}
export function clearPortalSession(res) {
res.clearCookie(config.cookieName, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'lax',
signed: true,
})
}
export function parsePortalSession(req) {
const raw = req.signedCookies?.[config.cookieName]
if (!raw) return null
try {
return JSON.parse(raw)
} catch {
return null
}
}
export function requireSession(req, res, next) {
const session = parsePortalSession(req)
if (!session) {
return res.status(401).json({ error: 'Nicht angemeldet' })
}
if (!session.customerId || !session.appwriteUserId) {
return res.status(401).json({ error: 'Ungültige Session' })
}
req.session = session
next()
}
/** Admin-Session: Ticketsystem-Mitarbeiter (Appwrite-Label "admin") im Portal. */
export function requireAdminSession(req, res, next) {
const session = parsePortalSession(req)
if (!session?.appwriteUserId || session.role !== 'admin') {
return res.status(401).json({ error: 'Admin-Anmeldung erforderlich' })
}
req.session = session
next()
}
export function getSessionCustomerId(req) {
return req.session?.customerId
}