feat(customers): customer portal (#354) on top of feature-flags reorg
Implements the recurring-customer login surface from the-luap/picpeak#354 plugged into the maintainer's new feature-flag infrastructure (PR #443) instead of a parallel toggle. * New `customerPortal` feature flag (foundation flag for the not-yet-built calendar/quotes/bills/messaging customer surfaces). Defaults FALSE on fresh installs, TRUE on existing installs (events > 0) via migration 095 so live customer accounts don't disappear mid-deployment. * Foundation schema: customer_accounts, customer_invitations, event_customer_assignments, customer_password_resets, plus RBAC permissions customers.view / .create / .delete granted to super_admin + admin system roles. * Backend: /api/admin/customers (invite, list, search, assign, deactivate, reset password) + /api/customer/auth/* + /api/customer/* (login, dashboard, accept-invite, reset). Customer JWT bypass minted via /api/customer/events/:slug/access-token so existing gallery middleware stays untouched. * Frontend: /customer/* route tree gated by RequireFeature flag customerPortal, with login / dashboard / accept-invite / reset pages and a customer-side sidebar layout. /admin/customers and /admin/customers/:id gated identically. * Settings → Features grows a "Customers" section with a Customer portal card. The maintainer's Features tab stays the single source of truth — no parallel Advanced features tab. * CustomerAccountPicker on event create/edit forms hides itself when the flag is off; backend ignores customer_account_ids in that case instead of erroring the whole event save. Translations: en + de hand-translated. nl/pt/ru fall through to en — flagged here as needing native review. Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
+15
-1
@@ -555,7 +555,6 @@ app.use('/api/gallery', require('./src/routes/galleryGuests'));
|
||||
app.use('/api/admin', adminRoutes);
|
||||
app.use('/api/admin/auth', adminAuthRoutes);
|
||||
app.use('/api/admin/system', require('./src/routes/adminSystem'));
|
||||
app.use('/api/admin/feature-flags', require('./src/routes/adminFeatureFlags'));
|
||||
app.use('/api/admin/backup', require('./src/routes/adminBackup'));
|
||||
app.use('/api/admin/database-backup', require('./src/routes/adminDatabaseBackup'));
|
||||
app.use('/api/admin/feedback', require('./src/routes/adminFeedback'));
|
||||
@@ -568,6 +567,21 @@ app.use('/api/admin/photo-export', require('./src/routes/adminPhotoExport'));
|
||||
app.use('/api/admin/css-templates', require('./src/routes/adminCssTemplates'));
|
||||
app.use('/api/admin/events', require('./src/routes/adminEventRename'));
|
||||
app.use('/api/admin/users', require('./src/routes/adminUsers'));
|
||||
// Customer-portal feature gate (#354 follow-up). When the master
|
||||
// toggle in Settings → Advanced features is OFF, the customer surface
|
||||
// returns 410 Gone for end-user routes and 403 for admin-side
|
||||
// management routes. The gate fires before the route handler so we
|
||||
// don't pay for auth checks against a disabled feature.
|
||||
const {
|
||||
requireCustomerPortalEnabled,
|
||||
requireCustomerPortalEnabledAdmin,
|
||||
} = require('./src/middleware/requireCustomerPortal');
|
||||
|
||||
app.use('/api/admin/customers', requireCustomerPortalEnabledAdmin, require('./src/routes/adminCustomers'));
|
||||
// Customer-side surface (#354). Strictly separate from /api/admin/* —
|
||||
// distinct token type, distinct cookie, distinct middleware.
|
||||
app.use('/api/customer/auth', requireCustomerPortalEnabled, require('./src/routes/customerAuth'));
|
||||
app.use('/api/customer', requireCustomerPortalEnabled, require('./src/routes/customer'));
|
||||
app.use('/api/admin/event-types', require('./src/routes/adminEventTypes'));
|
||||
app.use('/api/admin/api-tokens', require('./src/routes/adminApiTokens'));
|
||||
app.use('/api/admin/webhooks', require('./src/routes/adminWebhooks'));
|
||||
|
||||
Reference in New Issue
Block a user