Abo-API: Nachweis-ID nach Appwrite-Regeln, Webhook bei dauerhaften Fehlern, Tests
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
7df0b72019
commit
887e1e54a0
10 files changed
+409
-107
No files matched your search
+18
-15
@@ -1,44 +1,47 @@
|
||||
import http from 'node:http'
|
||||
import express from 'express'
|
||||
import cookieParser from 'cookie-parser'
|
||||
import signature from 'cookie-signature'
|
||||
import Stripe from 'stripe'
|
||||
import { config } from '../../server/config.js'
|
||||
import { sessionMiddleware } from '../../server/middleware/session.js'
|
||||
|
||||
/**
|
||||
* Express-App für Routen-Tests: wie server/index.js mit cookieParser(SESSION_SECRET) und
|
||||
* express.json samt rawBody (Stripe-Webhook), aber nur mit den Routern, die der Test übergibt:
|
||||
* Express-App für Routen-Tests: wie server/index.js mit sessionMiddleware() (cookieParser mit
|
||||
* SESSION_SECRET) und express.json samt rawBody (Stripe-Webhook), aber nur mit den Routern, die der
|
||||
* Test übergibt:
|
||||
* const app = await startTestApp({ '/api/abo': aboRoutes, '/api/portal-admin': portalAdminRoutes })
|
||||
*
|
||||
* Reihenfolge im Test: Nachbauten starten, useTestEnv(), dann dieses Modul und die Server-Module
|
||||
* dynamisch importieren (assertTestEnv() weigert sich sonst, weil config.js die Umgebung beim
|
||||
* ersten Import liest). Die Anfrage-Helfer sprechen die zuletzt gestartete App an.
|
||||
* dynamisch importieren. config.js liest die Umgebung beim ersten Import; zeigt sie nicht auf die
|
||||
* Nachbauten, weigert sich dieses Modul beim Laden. Die Anfrage-Helfer sprechen die zuletzt
|
||||
* gestartete App an.
|
||||
*/
|
||||
|
||||
function assertTestEnv() {
|
||||
for (const name of ['APPWRITE_ENDPOINT', 'STRIPE_API_BASE']) {
|
||||
for (const [name, value] of [
|
||||
['APPWRITE_ENDPOINT', config.appwrite.endpoint],
|
||||
['STRIPE_API_BASE', config.stripe.apiBase],
|
||||
]) {
|
||||
let host = null
|
||||
try {
|
||||
host = new URL(process.env[name] || '').hostname
|
||||
host = new URL(value || '').hostname
|
||||
} catch {
|
||||
host = null
|
||||
}
|
||||
if (host !== '127.0.0.1') {
|
||||
throw new Error(`testApp: ${name} zeigt nicht auf 127.0.0.1 – useTestEnv() vor dem Import aufrufen`)
|
||||
throw new Error(`testApp: ${name} zeigt nicht auf 127.0.0.1 – useTestEnv() muss vor dem ersten Import von config.js laufen`)
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTestEnv()
|
||||
|
||||
const cookieName = () => process.env.SESSION_COOKIE_NAME || 'webklar_portal_session'
|
||||
const sessionSecret = () => process.env.SESSION_SECRET || ''
|
||||
|
||||
/**
|
||||
* Signierter Session-Cookie wie setPortalSession (cookie-parser: Praefix "s:" + cookie-signature).
|
||||
* Kunde: { customerId, appwriteUserId }. Admin: { role: 'admin', appwriteUserId, name, email }.
|
||||
*/
|
||||
export function sessionCookie(session) {
|
||||
const value = `s:${signature.sign(JSON.stringify(session), sessionSecret())}`
|
||||
return `${cookieName()}=${encodeURIComponent(value)}`
|
||||
const value = `s:${signature.sign(JSON.stringify(session), config.sessionSecret)}`
|
||||
return `${config.cookieName}=${encodeURIComponent(value)}`
|
||||
}
|
||||
|
||||
let baseUrl = null
|
||||
@@ -47,7 +50,7 @@ let baseUrl = null
|
||||
export async function startTestApp(routers = {}) {
|
||||
const app = express()
|
||||
app.set('trust proxy', 1)
|
||||
app.use(cookieParser(sessionSecret()))
|
||||
app.use(sessionMiddleware())
|
||||
app.use(
|
||||
express.json({
|
||||
limit: '2mb',
|
||||
@@ -110,7 +113,7 @@ export const post = (path, body, opts = {}) => request('POST', path, { ...opts,
|
||||
const webhookSigner = new Stripe('sk_test_fake')
|
||||
|
||||
/** Stripe-Ereignis signiert an den Webhook schicken (F25) -> { status, body }. */
|
||||
export function postWebhook(event, { path = '/api/abo/webhook', secret = process.env.STRIPE_WEBHOOK_SECRET || 'whsec_test' } = {}) {
|
||||
export function postWebhook(event, { path = '/api/abo/webhook', secret = config.stripe.webhookSecret || 'whsec_test' } = {}) {
|
||||
const payload = JSON.stringify(event)
|
||||
const stripeSignature = webhookSigner.webhooks.generateTestHeaderString({ payload, secret })
|
||||
return request('POST', path, { body: payload, headers: { 'stripe-signature': stripeSignature } })
|
||||
|
||||
Reference in new issue
Block a user