summaryrefslogtreecommitdiff
path: root/middleware.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-06-30 08:28:13 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-06-30 08:28:13 +0000
commit5b6313f16f508882a0ea67716b7dbaa1c6967f04 (patch)
tree3d1d8dafea2f31274ace3fbda08333e889e06d1c /middleware.ts
parent3f0fad18483a5c800c79c5e33946d9bb384c10e2 (diff)
(대표님) 20250630 16시 - 유저 도메인별 라우터 분리와 보안성검토 대응
Diffstat (limited to 'middleware.ts')
-rw-r--r--middleware.ts118
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);
}