ReviewOS

also looking at this

stacks/pet-store

umbrella: pet-store storefront fixes (rolling)

#3
Merged glennmichael123 wants to merge umbrella/pet-store into main
586 files +38082 -7487
app/Gates.tsmodified+29-2
Changes to app/Gates.ts
@@ -25,10 +25,37 @@ import type { UserModel } from '@stacksjs/orm'
2525 */
2626export const gates = {
2727 /**
28 * Check if user can access admin area
28 * Check if a user can access the admin area.
29 *
30 * Driven by two env vars; either one matching is enough:
31 * - ADMIN_EMAILS comma-separated list of exact emails
32 * (e.g. `chris@barebowl.com,glenn@example.com`)
33 * - ADMIN_EMAIL_DOMAINS comma-separated list of email domains
34 * (with or without leading `@`, e.g.
35 * `barebowl.com,stacksjs.org`)
36 *
37 * Default is deny-all when neither is set — safer than carrying a
38 * hardcoded `@stacksjs.org` allowlist into apps that aren't run by
39 * stacksjs. Comparison is case-insensitive on the email side and
40 * matched against the suffix `@<domain>` so a user typing
41 * `Chris@BareBowl.com` still matches an `ADMIN_EMAIL_DOMAINS=barebowl.com`
42 * entry.
2943 */
3044 'access-admin': (user: UserModel | null) => {
31 return user?.email?.endsWith('@stacksjs.org') ?? false
45 const email = user?.email?.toLowerCase()
46 if (!email) return false
47
48 const explicit = (process.env.ADMIN_EMAILS ?? '')
49 .split(',')
50 .map(s => s.trim().toLowerCase())
51 .filter(Boolean)
52 if (explicit.includes(email)) return true
53
54 const domains = (process.env.ADMIN_EMAIL_DOMAINS ?? '')
55 .split(',')
56 .map(s => s.trim().toLowerCase().replace(/^@/, ''))
57 .filter(Boolean)
58 return domains.some(domain => email.endsWith(`@${domain}`))
3259 },
3360
3461 /**