Kundenansicht neu P10: Umschalt-Weiche liefert öffentliche Seiten, Manifest und Fassung-6-Adresse bei on
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4a75d7aba0
commit
416ebee18a
3 files changed
+220
No files matched your search
@@ -66,6 +66,7 @@ import legacyAdminRedirect from './routes/legacyAdminRedirect.js'
|
||||
import { corsMiddleware } from './middleware/cors.js'
|
||||
import { kundenansichtGuard } from './middleware/kundenansichtGuard.js'
|
||||
import { dashboardWeiche, neuDirektWeiche, oeffentlicheSeiteWeiche } from './services/kundenansicht/dashboardWeiche.js'
|
||||
import { umschaltSeitenRouter } from './routes/umschaltSeiten.js'
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
||||
const publicDir = path.join(__dirname, '..', 'public')
|
||||
@@ -168,6 +169,8 @@ app.get('/dashboard.html', dashboardWeiche({ publicDir }))
|
||||
app.get('/neu/dashboard.html', neuDirektWeiche())
|
||||
// Kuendigen und Widerrufen: im Pilot die neuen Seiten aus public/neu/oeffentlich/, sobald die Dateien dort liegen
|
||||
app.get(['/kuendigen.html', '/widerrufen.html'], oeffentlicheSeiteWeiche({ publicDir }))
|
||||
// Umschalten (P10): erst bei KUNDENANSICHT_NEU=on die neuen oeffentlichen Seiten, das Manifest und die Fassung-6-Adresse, auch ohne Sitzung
|
||||
app.use(umschaltSeitenRouter({ publicDir }))
|
||||
app.use(express.static(publicDir))
|
||||
|
||||
app.get('/dashboard.html', (req, res, next) => {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
import { stat } from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import express from 'express'
|
||||
import { config } from '../config.js'
|
||||
import { termsDocFor } from '../services/products.js'
|
||||
import { neueAnsichtModus } from '../services/kundenansicht/schalter.js'
|
||||
|
||||
/**
|
||||
* Umschalt-Weiche der neuen Kundenansicht (P10): erst bei KUNDENANSICHT_NEU=on liefert sie die neuen oeffentlichen Seiten,
|
||||
* das Manifest und die Fassung-6-Adresse der Abo-Bedingungen, auch Besuchern ohne Sitzung. In off und pilot (auch mit '*')
|
||||
* ruft jede Zeile next(); die alten Dateien kommen dann unveraendert von express.static. server/index.js haengt den Router
|
||||
* hinter die Weichen von P0 (dashboardWeiche, oeffentlicheSeiteWeiche) und vor express.static ein.
|
||||
*/
|
||||
|
||||
/** Adresse -> Datei unter public/, die bei on an ihre Stelle tritt. */
|
||||
export const UMSCHALT_SEITEN = Object.freeze({
|
||||
'/dashboard.html': 'neu/dashboard.html', // greift nur, wo P0s Weiche nicht gegriffen hat, also ohne Sitzung
|
||||
'/login.html': 'neu/oeffentlich/login.html',
|
||||
'/kuendigen.html': 'neu/oeffentlich/kuendigen.html',
|
||||
'/widerrufen.html': 'neu/oeffentlich/widerrufen.html',
|
||||
'/offline.html': 'neu/oeffentlich/offline.html',
|
||||
'/manifest.webmanifest': 'neu/manifest.webmanifest',
|
||||
})
|
||||
|
||||
const ABO_SEITE = '/abo-bedingungen.html'
|
||||
const ABO_PDF = '/WEBklar-Abo-Vertragsunterlagen.pdf'
|
||||
|
||||
/** { url, pdfFile } der Fassung 6 aus config.abo.termsVersionNeu; ohne gesetzte Neu-Fassung null. */
|
||||
export function fassung6Aus() {
|
||||
return config.abo.termsVersionNeu ? termsDocFor(config.abo.termsVersionNeu) : null
|
||||
}
|
||||
|
||||
/**
|
||||
* Absoluter Pfad zu rel (Adresse oder Dateiname, mit oder ohne fuehrenden Schraegstrich) unter publicDir.
|
||||
* Null, wenn rel kein Text ist, aus public/ herausfuehren wuerde oder der aufgeloeste Pfad nicht darunter liegt.
|
||||
*/
|
||||
function unterPublic(publicDir, rel) {
|
||||
if (typeof rel !== 'string' || rel === '' || rel.includes('\0')) return null
|
||||
const relativ = path.posix.normalize(rel.replace(/^\/+/, ''))
|
||||
if (relativ === '..' || relativ.startsWith('../')) return null
|
||||
const wurzel = path.resolve(publicDir)
|
||||
const ziel = path.resolve(wurzel, '.' + path.posix.normalize('/' + rel))
|
||||
return ziel.startsWith(wurzel + path.sep) ? ziel : null
|
||||
}
|
||||
|
||||
/**
|
||||
* Router der Weiche. modus() und fassung6() werden je Anfrage gelesen (Schalter wirkt ohne Neustart der Weiche);
|
||||
* fassung6() liefert { url, pdfFile } oder null (dann bleibt die Datei von heute).
|
||||
*/
|
||||
export function umschaltSeitenRouter({ publicDir, modus = neueAnsichtModus, fassung6 = fassung6Aus }) {
|
||||
// Wie express.static: Gross-/Kleinschreibung und Schraegstrich am Ende zaehlen
|
||||
const router = express.Router({ caseSensitive: true, strict: true })
|
||||
|
||||
/** Zieldatei senden (no-cache); fehlt sie, laeuft die Anfrage unveraendert zu express.static weiter. */
|
||||
const sende = (ziel, res, next) =>
|
||||
stat(ziel).then(
|
||||
(info) => {
|
||||
if (!info.isFile()) return next()
|
||||
res.set('Cache-Control', 'no-cache')
|
||||
res.sendFile(ziel, { dotfiles: 'deny' }, (err) => {
|
||||
if (!err) return
|
||||
if (res.headersSent) return
|
||||
res.removeHeader('Cache-Control')
|
||||
next(err.code === 'ENOENT' ? undefined : err)
|
||||
})
|
||||
},
|
||||
() => next()
|
||||
)
|
||||
|
||||
for (const [adresse, rel] of Object.entries(UMSCHALT_SEITEN)) {
|
||||
router.get(adresse, (_req, res, next) => {
|
||||
if (modus() !== 'on') return next()
|
||||
const ziel = unterPublic(publicDir, rel)
|
||||
return ziel ? sende(ziel, res, next) : next()
|
||||
})
|
||||
}
|
||||
|
||||
// Stripe-Checkout und die neuen Seiten verlinken diese zwei Adressen; im Fassung-6-Weg muessen sie Fassung 6 zeigen
|
||||
for (const [adresse, feld] of [[ABO_SEITE, 'url'], [ABO_PDF, 'pdfFile']]) {
|
||||
router.get(adresse, (_req, res, next) => {
|
||||
if (modus() !== 'on') return next()
|
||||
const ziel = unterPublic(publicDir, fassung6()?.[feld])
|
||||
return ziel ? sende(ziel, res, next) : next()
|
||||
})
|
||||
}
|
||||
|
||||
return router
|
||||
}
|
||||
Reference in new issue
Block a user