fix payment customer and dashboard settings
Build & Deploy / Build & Push Docker Image (push) Successful in 12m39s
Test / Type Check (all packages) (push) Successful in 5m8s
Build & Deploy / Deploy to VPS (push) Successful in 7s
Test / API Unit Tests (push) Failing after 4m24s
Test / Homepage Unit Tests (push) Successful in 3m27s
Test / Storefront Unit Tests (push) Successful in 4m48s
Test / Admin Unit Tests (push) Successful in 3m0s
Test / Dashboard Unit Tests (push) Successful in 4m18s
Test / API Integration Tests (push) Failing after 4m34s
Build & Deploy / Build & Push Docker Image (push) Successful in 12m39s
Test / Type Check (all packages) (push) Successful in 5m8s
Build & Deploy / Deploy to VPS (push) Successful in 7s
Test / API Unit Tests (push) Failing after 4m24s
Test / Homepage Unit Tests (push) Successful in 3m27s
Test / Storefront Unit Tests (push) Successful in 4m48s
Test / Admin Unit Tests (push) Successful in 3m0s
Test / Dashboard Unit Tests (push) Successful in 4m18s
Test / API Integration Tests (push) Failing after 4m34s
This commit is contained in:
@@ -116,6 +116,20 @@ export function routeIdFromSlug(locale: Locale, slug: string): RouteId | null {
|
||||
return route?.id ?? null;
|
||||
}
|
||||
|
||||
export function routeIdFromAnyLocaleSlug(slug: string): RouteId | null {
|
||||
let decoded: string;
|
||||
try {
|
||||
decoded = decodeURIComponent(slug);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
const normalized = decoded.replace(/^\/+|\/+$/g, '');
|
||||
const route = routeManifest.routes.find((item) =>
|
||||
locales.some((locale) => item.slugs[locale] === normalized),
|
||||
);
|
||||
return route?.id ?? null;
|
||||
}
|
||||
|
||||
export function routeIdFromPathname(pathname: string): RouteId | null {
|
||||
const [localeValue, ...segments] = pathname.split('/').filter(Boolean);
|
||||
if (!isLocale(localeValue)) return null;
|
||||
|
||||
@@ -4,11 +4,16 @@ import {
|
||||
localeCookie,
|
||||
localeCookieMaxAgeSeconds,
|
||||
localeFromAcceptLanguage,
|
||||
localizedPath,
|
||||
routeIdFromAnyLocaleSlug,
|
||||
routeIdFromSlug,
|
||||
} from '@/lib/localization/config';
|
||||
import { buildContentSecurityPolicy, createNonce } from '@/lib/security/csp';
|
||||
import type { NextRequest } from 'next/server';
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
const dashboardLanguageCookie = 'rentaldrivego-language';
|
||||
|
||||
function applySecurityHeaders(response: NextResponse, contentSecurityPolicy: string): NextResponse {
|
||||
response.headers.set('Content-Security-Policy', contentSecurityPolicy);
|
||||
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
||||
@@ -73,6 +78,40 @@ export function proxy(request: NextRequest): NextResponse {
|
||||
return applySecurityHeaders(NextResponse.redirect(destination), csp);
|
||||
}
|
||||
|
||||
if (isLocale(firstSegment) && request.nextUrl.pathname === `/${firstSegment}/subscription`) {
|
||||
const destination = request.nextUrl.clone();
|
||||
destination.pathname = '/dashboard/subscription';
|
||||
const response = NextResponse.redirect(destination);
|
||||
response.cookies.set(localeCookie, firstSegment, {
|
||||
path: '/',
|
||||
sameSite: 'lax',
|
||||
maxAge: localeCookieMaxAgeSeconds,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
httpOnly: false,
|
||||
});
|
||||
response.cookies.set(dashboardLanguageCookie, firstSegment, {
|
||||
path: '/',
|
||||
sameSite: 'lax',
|
||||
maxAge: localeCookieMaxAgeSeconds,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
httpOnly: false,
|
||||
});
|
||||
return applySecurityHeaders(response, csp);
|
||||
}
|
||||
|
||||
if (isLocale(firstSegment)) {
|
||||
const segments = request.nextUrl.pathname.split('/').filter(Boolean);
|
||||
const slug = segments.slice(1).join('/');
|
||||
if (slug && !routeIdFromSlug(firstSegment, slug)) {
|
||||
const routeId = routeIdFromAnyLocaleSlug(slug);
|
||||
if (routeId) {
|
||||
const destination = request.nextUrl.clone();
|
||||
destination.pathname = localizedPath(routeId, firstSegment);
|
||||
return applySecurityHeaders(NextResponse.redirect(destination), csp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const response = NextResponse.next({ request: { headers: requestHeaders } });
|
||||
const explicitLocale = request.nextUrl.pathname.split('/')[1];
|
||||
if (isLocale(explicitLocale)) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
localeSwitchUrl,
|
||||
localizedPath,
|
||||
routeById,
|
||||
routeIdFromAnyLocaleSlug,
|
||||
routeIdFromPathname,
|
||||
routeIdFromSlug,
|
||||
} from '@/lib/localization/config';
|
||||
@@ -30,6 +31,10 @@ describe('localization foundations', () => {
|
||||
expect(localizedPath('privacy', 'fr')).toBe('/fr/confidentialite');
|
||||
expect(localizedPath('sign-in', 'ar')).toBe('/ar/تسجيل-الدخول');
|
||||
expect(routeIdFromSlug('fr', 'confidentialite')).toBe('privacy');
|
||||
expect(routeIdFromSlug('fr', 'privacy')).toBeNull();
|
||||
expect(routeIdFromAnyLocaleSlug('privacy')).toBe('privacy');
|
||||
expect(routeIdFromAnyLocaleSlug('confidentialite')).toBe('privacy');
|
||||
expect(routeIdFromAnyLocaleSlug('unknown')).toBeNull();
|
||||
expect(routeIdFromPathname('/ar/%D8%A7%D9%84%D8%AE%D8%B5%D9%88%D8%B5%D9%8A%D8%A9')).toBe(
|
||||
'privacy',
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user