diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-30 08:28:13 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-06-30 08:28:13 +0000 |
| commit | 5b6313f16f508882a0ea67716b7dbaa1c6967f04 (patch) | |
| tree | 3d1d8dafea2f31274ace3fbda08333e889e06d1c /middleware.ts | |
| parent | 3f0fad18483a5c800c79c5e33946d9bb384c10e2 (diff) | |
(대표님) 20250630 16시 - 유저 도메인별 라우터 분리와 보안성검토 대응
Diffstat (limited to 'middleware.ts')
| -rw-r--r-- | middleware.ts | 118 |
1 files changed, 91 insertions, 27 deletions
diff --git a/middleware.ts b/middleware.ts index ed471109..242f439b 100644 --- a/middleware.ts +++ b/middleware.ts @@ -13,6 +13,9 @@ acceptLanguage.languages(languages); // 로그인이 필요 없는 공개 경로 const publicPaths = [ '/evcp', + '/procurement', + '/sales', + '/engineering', '/partners', '/partners/repository', '/partners/signup', @@ -36,29 +39,87 @@ function isPublicPath(path: string, lng: string) { return false; } +// 도메인별 기본 대시보드 경로 정의 +function getDashboardPath(domain: string, lng: string): string { + switch (domain) { + case 'pending': + return `/${lng}/pending`; + case 'evcp': + return `/${lng}/evcp/report`; + case 'procurement': + return `/${lng}/procurement/dashboard`; + case 'sales': + return `/${lng}/sales/dashboard`; + case 'engineering': + return `/${lng}/engineering/dashboard`; + case 'partners': + return `/${lng}/partners/dashboard`; + default: + return `/${lng}/pending`; // 기본값 + } +} + +// 도메인별 로그인 페이지 경로 정의 +function getLoginPath(domain: string, lng: string): string { + switch (domain) { + case 'partners': + return `/${lng}/partners`; + case 'pending': + return `/${lng}/pending`; + case 'evcp': + case 'procurement': + case 'sales': + case 'engineering': + default: + return `/${lng}/evcp`; + } +} + // 도메인-URL 일치 여부 확인 및 올바른 리다이렉트 경로 반환 function getDomainRedirectPath(path: string, domain: string, lng: string) { // 도메인이 없는 경우 리다이렉트 없음 if (!domain) return null; - // URL에 partners가 있는지 확인 - const hasPartnersInPath = path.includes('/partners'); - // URL에 evcp가 있는지 확인 - const hasEvcpInPath = path.includes('/evcp'); + // 각 도메인 경로 패턴 확인 + const domainPatterns = { + pending: `/pending/`, + evcp: `/evcp/`, + procurement: `/procurement/`, + sales: `/sales/`, + engineering: `/engineering/`, + partners: `/partners/` + }; - // 1. 도메인이 'partners'인데 URL에 '/evcp/'가 있으면 - if (domain === 'partners' && hasEvcpInPath) { - // URL에서 '/evcp/'를 '/partners/'로 교체 - return path.replace('/evcp/', '/partners/'); + // 현재 경로가 어떤 도메인 패턴에 속하는지 확인 + let currentPathDomain = null; + for (const [domainName, pattern] of Object.entries(domainPatterns)) { + if (path.includes(pattern)) { + currentPathDomain = domainName; + break; + } } - - // 2. 도메인이 'evcp'인데 URL에 '/partners/'가 있으면 - if (domain === 'evcp' && hasPartnersInPath) { - // URL에서 '/partners/'를 '/evcp/'로 교체 - return path.replace('/partners/', '/evcp/'); + + // 도메인과 경로가 일치하지 않는 경우 + if (currentPathDomain && currentPathDomain !== domain) { + // pending 사용자는 오직 pending 경로만 접근 가능 + if (domain === 'pending') { + return getDashboardPath('pending', lng); + } + + // 다른 도메인 사용자가 pending에 접근하려는 경우 + if (currentPathDomain === 'pending') { + return getDashboardPath(domain, lng); + } + + // 일반적인 도메인 불일치 처리 + const targetPattern = domainPatterns[domain as keyof typeof domainPatterns]; + if (targetPattern && currentPathDomain) { + const sourcePattern = domainPatterns[currentPathDomain as keyof typeof domainPatterns]; + return path.replace(sourcePattern, targetPattern); + } } - // 불일치가 없으면 null 반환 (리다이렉트 필요 없음) + // 일치하거나 처리할 수 없는 경우 null 반환 return null; } @@ -86,7 +147,10 @@ function createLoginUrl(pathname: string, detectedLng: string, origin: string, r // 경로에 따라 적절한 로그인 페이지 선택 if (pathname.includes('/partners') || pathname.startsWith(`/${detectedLng}/vendor`)) { loginPath = `/${detectedLng}/partners`; + } else if (pathname.includes('/pending')) { + loginPath = `/${detectedLng}/pending`; } else { + // evcp, procurement, sales, engineering은 모두 evcp 로그인 사용 loginPath = `/${detectedLng}/evcp`; } @@ -165,8 +229,6 @@ export async function middleware(request: NextRequest) { const loginUrl = createLoginUrl(pathname, detectedLng, origin, request, 'expired'); return NextResponse.redirect(loginUrl); } - - // 세션 만료 경고를 위한 응답 헤더 설정은 나중에 적용 } /** @@ -192,18 +254,20 @@ export async function middleware(request: NextRequest) { const { isExpired } = checkSessionTimeout(token); if (!isExpired) { - // 로그인 페이지 경로 확인 (정확한 /ko/evcp 또는 /en/partners 등) - const isEvcpLoginPage = pathname === `/${detectedLng}/evcp`; - const isPartnersLoginPage = pathname === `/${detectedLng}/partners`; + // 모든 도메인의 로그인 페이지 확인 + const loginPages = [ + `/${detectedLng}/evcp`, + `/${detectedLng}/procurement`, + `/${detectedLng}/sales`, + `/${detectedLng}/engineering`, + `/${detectedLng}/partners`, + `/${detectedLng}/pending` + ]; - if (isEvcpLoginPage) { - // EVCP 로그인 페이지에 접근한 경우 report 페이지로 리다이렉트 - const redirectUrl = new URL(`/${detectedLng}/evcp/report`, origin); - redirectUrl.search = searchParams.toString(); - return NextResponse.redirect(redirectUrl); - } else if (isPartnersLoginPage) { - // Partners 로그인 페이지에 접근한 경우 dashboard 페이지로 리다이렉트 - const redirectUrl = new URL(`/${detectedLng}/partners/dashboard`, origin); + if (loginPages.includes(pathname)) { + // 사용자의 도메인에 맞는 대시보드로 리다이렉트 + const dashboardPath = getDashboardPath(token.domain as string, detectedLng); + const redirectUrl = new URL(dashboardPath, origin); redirectUrl.search = searchParams.toString(); return NextResponse.redirect(redirectUrl); } |
