fix(dev): Vite-API-Proxy, Auth, Stripe-Mails und Backend-Erweiterungen

- 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
This commit is contained in:
2026-04-03 00:23:01 +02:00
parent 61008b63bb
commit ecae89a79d
33 changed files with 1663 additions and 550 deletions

View File

@@ -11,6 +11,7 @@ import { products, questions, submissions, orders, onboardingState, emailAccount
import Stripe from 'stripe'
import { config } from '../config/index.mjs'
import { log } from '../middleware/logger.mjs'
import { requireAuth } from '../middleware/auth.mjs'
const router = express.Router()
const stripe = new Stripe(config.stripe.secretKey)
@@ -177,13 +178,9 @@ router.get('/config', (req, res) => {
* Get current onboarding state
*/
router.get('/onboarding/status',
validate({
query: {
userId: [rules.required('userId')],
},
}),
requireAuth,
asyncHandler(async (req, res) => {
const { userId } = req.query
const userId = req.appwriteUser.id
const state = await onboardingState.getByUser(userId)
respond.success(res, state)
})
@@ -194,15 +191,16 @@ router.get('/onboarding/status',
* Update onboarding step progress
*/
router.post('/onboarding/step',
requireAuth,
validate({
body: {
userId: [rules.required('userId')],
step: [rules.required('step')],
completedSteps: [rules.isArray('completedSteps')],
},
}),
asyncHandler(async (req, res) => {
const { userId, step, completedSteps = [] } = req.body
const userId = req.appwriteUser.id
const { step, completedSteps = [] } = req.body
await onboardingState.updateStep(userId, step, completedSteps)
respond.success(res, { step, completedSteps })
})
@@ -213,13 +211,9 @@ router.post('/onboarding/step',
* Skip onboarding
*/
router.post('/onboarding/skip',
validate({
body: {
userId: [rules.required('userId')],
},
}),
requireAuth,
asyncHandler(async (req, res) => {
const { userId } = req.body
const userId = req.appwriteUser.id
await onboardingState.skip(userId)
respond.success(res, { skipped: true })
})
@@ -230,13 +224,9 @@ router.post('/onboarding/skip',
* Resume onboarding
*/
router.post('/onboarding/resume',
validate({
body: {
userId: [rules.required('userId')],
},
}),
requireAuth,
asyncHandler(async (req, res) => {
const { userId } = req.body
const userId = req.appwriteUser.id
await onboardingState.resume(userId)
const state = await onboardingState.getByUser(userId)
respond.success(res, state)
@@ -248,13 +238,9 @@ router.post('/onboarding/resume',
* Delete all user data and account
*/
router.delete('/account/delete',
validate({
body: {
userId: [rules.required('userId')],
},
}),
requireAuth,
asyncHandler(async (req, res) => {
const { userId } = req.body
const userId = req.appwriteUser.id
log.info(`Account deletion requested for user ${userId}`)
@@ -301,7 +287,7 @@ router.delete('/account/delete',
}
// Delete subscription
const subscription = await subscriptions.getByUser(userId)
const subscription = await subscriptions.getByUser(userId, req.appwriteUser?.email)
if (subscription && subscription.$id) {
try {
await db.delete(Collections.SUBSCRIPTIONS, subscription.$id)
@@ -344,13 +330,9 @@ router.delete('/account/delete',
* Get or create referral code for user
*/
router.get('/referrals/code',
validate({
query: {
userId: [rules.required('userId')],
},
}),
requireAuth,
asyncHandler(async (req, res) => {
const { userId } = req.query
const userId = req.appwriteUser.id
const referral = await referrals.getOrCreateCode(userId)
respond.success(res, {
referralCode: referral.referralCode,
@@ -364,14 +346,15 @@ router.get('/referrals/code',
* Track a referral (when new user signs up with referral code)
*/
router.post('/referrals/track',
requireAuth,
validate({
body: {
userId: [rules.required('userId')],
referralCode: [rules.required('referralCode')],
},
}),
asyncHandler(async (req, res) => {
const { userId, referralCode } = req.body
const userId = req.appwriteUser.id
const { referralCode } = req.body
// Find referrer by code
const referrer = await referrals.getByCode(referralCode)