Kundenansicht: Einmal-Link aus dem Ticketsystem, Sitzung und Preview-Zugang fuer 2 Stunden, Protokoll

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-01 19:27:21 +00:00
1 parent fdf594706d
commit 1cd776a2ee
10 files changed
+277 -7

No files matched your search

+25
View File
@@ -28,6 +28,9 @@ import {
} from '../services/previewSession.js'
import { isPreviewProjectReady } from '../services/previewReadiness.js'
import { consumeStaffPreviewToken } from '../services/staffPreviewTokens.js'
import { getPortalAccessStatus } from '../services/portalAccessStatus.js'
import { startKundenansicht } from '../services/kundenansicht.js'
import { logViewAction } from '../services/customerViewLog.js'
import { resolveStaffAccount } from '../services/staffAccount.js'
import { MFA_COOKIE, MFA_TTL_MS, resendStaffMfa, startStaffMfa, verifyStaffMfa } from '../services/staffMfa.js'
@@ -343,6 +346,28 @@ router.get('/staff-switch', async (req, res) => {
return res.redirect('/admin.html')
})
// Kundenansicht aus dem Ticketsystem (POST /api/team/customers/:id/kundenansicht): Einmal-Link -> Portal des Kunden
router.get('/kundenansicht', async (req, res) => {
const gone = (text) => res.status(410).type('text/plain; charset=utf-8').send(text)
const tokenData = consumeStaffPreviewToken(String(req.query.token || ''), 'kundenansicht')
if (!tokenData) return gone('Der Link ist abgelaufen. Bitte die Kundenansicht im Ticketsystem erneut öffnen.')
try {
const { customer, hasAccess } = await getPortalAccessStatus(tokenData.customerId)
if (!customer || !hasAccess) return gone('Kein Portal-Zugang. Bitte die Kundenansicht im Ticketsystem erneut öffnen.')
const session = await startKundenansicht(res, { staff: tokenData.staff, customer })
await logViewAction({
customerId: customer.$id,
staffUserId: session.appwriteUserId,
staffName: session.adminName,
action: 'geoeffnet',
})
return res.redirect('/dashboard.html')
} catch (err) {
console.error('[kundenansicht] Öffnen fehlgeschlagen:', err.message)
return res.status(500).type('text/plain; charset=utf-8').send('Die Kundenansicht konnte nicht geöffnet werden.')
}
})
// Selbstheilung: Portal-Session lebt oft laenger als das preview_session-Cookie
// (bzw. das Cookie fehlt nach WebView-/Browser-Datenverlust). Ohne gueltiges
// Preview-Cookie laufen die *.project.webklar.com-Hosts in eine 302-Schleife.