- Client: API-Basis-URL (joinApiUrl, /v1-Falle), Vite strictPort + Proxy 127.0.0.1, Nicht-JSON-Fehler - Server: /api-404 ohne Wildcard-Bug, SPA-Fallback, Auth-Middleware, Cron, Mailer, Crypto - Routen: OAuth-State, Email/Stripe/Analytics; client/.env.example Made-with: Cursor
59 lines
1.5 KiB
JavaScript
59 lines
1.5 KiB
JavaScript
/**
|
|
* Appwrite JWT verification for user-scoped API routes.
|
|
*/
|
|
|
|
import { Client, Account } from 'node-appwrite'
|
|
import { config } from '../config/index.mjs'
|
|
import { AuthenticationError } from './errorHandler.mjs'
|
|
|
|
/**
|
|
* Verify Authorization: Bearer <jwt> and attach Appwrite user to req.appwriteUser
|
|
*/
|
|
export function requireAuth(req, res, next) {
|
|
;(async () => {
|
|
try {
|
|
const header = req.headers.authorization || ''
|
|
const m = /^Bearer\s+(.+)$/i.exec(header)
|
|
if (!m?.[1]) {
|
|
throw new AuthenticationError('Authorization Bearer token required')
|
|
}
|
|
const jwt = m[1].trim()
|
|
const client = new Client()
|
|
.setEndpoint(config.appwrite.endpoint)
|
|
.setProject(config.appwrite.projectId)
|
|
.setJWT(jwt)
|
|
|
|
const account = new Account(client)
|
|
const user = await account.get()
|
|
|
|
if (!user || !user.$id) {
|
|
throw new AuthenticationError('Ungültige Appwrite-Sitzung')
|
|
}
|
|
|
|
req.appwriteUser = {
|
|
id: user.$id,
|
|
email: user.email || '',
|
|
name: user.name || '',
|
|
}
|
|
next()
|
|
} catch (err) {
|
|
if (err instanceof AuthenticationError) {
|
|
next(err)
|
|
return
|
|
}
|
|
next(new AuthenticationError(err.message || 'Invalid or expired session'))
|
|
}
|
|
})()
|
|
}
|
|
|
|
/**
|
|
* Skip auth for email provider inbound webhooks only.
|
|
*/
|
|
export function requireAuthUnlessEmailWebhook(req, res, next) {
|
|
const p = req.path || ''
|
|
if (p === '/webhook/gmail' || p === '/webhook/outlook') {
|
|
return next()
|
|
}
|
|
return requireAuth(req, res, next)
|
|
}
|