fix cors production
Build & Push / Pipeline Tests (push) Successful in 1m58s
Test / Type Check (all packages) (push) Successful in 59s
Build & Push / Build & Push Docker Image (push) Successful in 4m9s
Test / API Unit Tests (push) Successful in 1m13s
Test / Homepage Unit Tests (push) Successful in 50s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 44s
Test / Dashboard Unit Tests (push) Successful in 46s
Test / API Integration Tests (push) Successful in 1m7s
Build & Push / Pipeline Tests (push) Successful in 1m58s
Test / Type Check (all packages) (push) Successful in 59s
Build & Push / Build & Push Docker Image (push) Successful in 4m9s
Test / API Unit Tests (push) Successful in 1m13s
Test / Homepage Unit Tests (push) Successful in 50s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 44s
Test / Dashboard Unit Tests (push) Successful in 46s
Test / API Integration Tests (push) Successful in 1m7s
This commit is contained in:
+41
-3
@@ -55,9 +55,47 @@ const defaultCorsOrigins = [
|
||||
'http://127.0.0.1:4000',
|
||||
]
|
||||
|
||||
export const corsOrigins = process.env.CORS_ORIGINS
|
||||
? process.env.CORS_ORIGINS.split(',').map((o) => o.trim()).filter(Boolean)
|
||||
: defaultCorsOrigins
|
||||
const frontendOriginEnvKeys = [
|
||||
'SITE_ORIGIN',
|
||||
'WEBSITE_URL',
|
||||
'HOMEPAGE_URL',
|
||||
'DASHBOARD_URL',
|
||||
'ADMIN_URL',
|
||||
'CARPLACE_URL',
|
||||
'NEXT_PUBLIC_HOMEPAGE_URL',
|
||||
'NEXT_PUBLIC_WEBSITE_URL',
|
||||
'NEXT_PUBLIC_DASHBOARD_URL',
|
||||
'NEXT_PUBLIC_ADMIN_URL',
|
||||
'NEXT_PUBLIC_CARPLACE_URL',
|
||||
] as const
|
||||
|
||||
function normalizeConfiguredOrigin(value: string): string | null {
|
||||
try {
|
||||
return new URL(value).origin
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export function getConfiguredCorsOrigins(env: NodeJS.ProcessEnv = process.env) {
|
||||
const configuredOrigins = (env.CORS_ORIGINS ?? '')
|
||||
.split(',')
|
||||
.map((origin) => origin.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
const frontendOrigins = frontendOriginEnvKeys
|
||||
.flatMap((key) => (env[key] ?? '').split(','))
|
||||
.map((origin) => origin.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
const rawOrigins = configuredOrigins.length > 0 || frontendOrigins.length > 0
|
||||
? [...configuredOrigins, ...frontendOrigins]
|
||||
: defaultCorsOrigins
|
||||
|
||||
return Array.from(new Set(rawOrigins.map(normalizeConfiguredOrigin).filter((origin): origin is string => Boolean(origin))))
|
||||
}
|
||||
|
||||
export const corsOrigins = getConfiguredCorsOrigins()
|
||||
|
||||
function isAllowedLocalDevOrigin(origin: string) {
|
||||
if (process.env.NODE_ENV === 'production') return false
|
||||
|
||||
@@ -5,10 +5,13 @@ const SESSION_COOKIE_PATTERN = /(?:^|;\s*)(?:admin_session|employee_session|rent
|
||||
|
||||
function configuredOrigins() {
|
||||
return [
|
||||
process.env.SITE_ORIGIN,
|
||||
process.env.DASHBOARD_URL,
|
||||
process.env.ADMIN_URL,
|
||||
process.env.CARPLACE_URL,
|
||||
process.env.HOMEPAGE_URL,
|
||||
process.env.WEBSITE_URL,
|
||||
process.env.NEXT_PUBLIC_HOMEPAGE_URL,
|
||||
process.env.NEXT_PUBLIC_DASHBOARD_URL,
|
||||
process.env.NEXT_PUBLIC_ADMIN_URL,
|
||||
process.env.NEXT_PUBLIC_CARPLACE_URL,
|
||||
|
||||
@@ -16,7 +16,7 @@ vi.mock('../../lib/redis', () => ({
|
||||
|
||||
import request from 'supertest'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { createApp, isCorsOriginAllowed } from '../../app'
|
||||
import { createApp, getConfiguredCorsOrigins, isCorsOriginAllowed } from '../../app'
|
||||
import { isTrustedBrowserOrigin } from '../../middleware/csrf'
|
||||
|
||||
const app = createApp()
|
||||
@@ -88,6 +88,22 @@ describe('API foundation integration', () => {
|
||||
expect(res.headers['access-control-allow-credentials']).toBe('true')
|
||||
})
|
||||
|
||||
it('derives production CORS origins from configured frontend URLs when CORS_ORIGINS is absent', () => {
|
||||
expect(getConfiguredCorsOrigins({
|
||||
NODE_ENV: 'production',
|
||||
SITE_ORIGIN: 'https://rentaldrivego.ma',
|
||||
NEXT_PUBLIC_DASHBOARD_URL: 'https://rentaldrivego.ma/dashboard',
|
||||
NEXT_PUBLIC_ADMIN_URL: 'https://rentaldrivego.ma/admin',
|
||||
})).toEqual(['https://rentaldrivego.ma'])
|
||||
})
|
||||
|
||||
it('normalizes explicit CORS origins and frontend URL origins without duplicates', () => {
|
||||
expect(getConfiguredCorsOrigins({
|
||||
CORS_ORIGINS: 'https://rentaldrivego.ma, https://www.rentaldrivego.ma',
|
||||
NEXT_PUBLIC_DASHBOARD_URL: 'https://rentaldrivego.ma/dashboard',
|
||||
})).toEqual(['https://rentaldrivego.ma', 'https://www.rentaldrivego.ma'])
|
||||
})
|
||||
|
||||
it('trusts private LAN app origins during local development only on known app ports', () => {
|
||||
expect(isCorsOriginAllowed('http://192.168.3.3:3000')).toBe(true)
|
||||
expect(isTrustedBrowserOrigin('http://192.168.3.3:3000')).toBe(true)
|
||||
|
||||
Reference in New Issue
Block a user