summaryrefslogtreecommitdiff
path: root/app/api
diff options
context:
space:
mode:
Diffstat (limited to 'app/api')
-rw-r--r--app/api/vendors/attachments/download-all/route.ts35
-rw-r--r--app/api/vendors/attachments/download/route.ts34
2 files changed, 59 insertions, 10 deletions
diff --git a/app/api/vendors/attachments/download-all/route.ts b/app/api/vendors/attachments/download-all/route.ts
index 4520cb2d..a1e56bba 100644
--- a/app/api/vendors/attachments/download-all/route.ts
+++ b/app/api/vendors/attachments/download-all/route.ts
@@ -44,8 +44,11 @@ export async function GET(request: NextRequest) {
);
}
- // 업로드 기본 경로
- const basePath = process.env.UPLOAD_DIR || path.join(process.cwd(), 'public');
+ // 환경에 따른 기본 경로 설정 (/api/files/ 와 동일한 로직)
+ const nasPath = process.env.NAS_PATH || "/evcp_nas";
+ const basePath = process.env.NODE_ENV === 'production'
+ ? nasPath
+ : path.join(process.cwd(), 'public');
// ZIP 생성
const zip = new JSZip();
@@ -60,16 +63,34 @@ export async function GET(request: NextRequest) {
return;
}
- // filePath는 이미 /로 시작하므로 public 폴더에서의 상대 경로로 처리
- const normalizedPath = attachment.filePath.startsWith('/')
- ? attachment.filePath.slice(1) // 앞의 '/' 제거
- : attachment.filePath;
+ // DB에 저장된 경로가 /api/files/vendors/[id]/[filename] 형태인 경우 처리
+ let normalizedPath: string;
+
+ if (attachment.filePath.startsWith('/api/files/')) {
+ // /api/files/vendors/[id]/[filename] -> vendors/[id]/[filename]
+ normalizedPath = attachment.filePath.replace('/api/files/', '');
+ } else if (attachment.filePath.startsWith('/')) {
+ // 기존 방식: /vendors/[id]/[filename] -> vendors/[id]/[filename]
+ normalizedPath = attachment.filePath.slice(1);
+ } else {
+ // 상대 경로 그대로 사용
+ normalizedPath = attachment.filePath;
+ }
+
+ // 보안 검증: 경로 탐색 공격 방지
+ if (normalizedPath.includes('..') || normalizedPath.includes('~')) {
+ console.warn(`위험한 경로 패턴: ${normalizedPath}`);
+ return;
+ }
+
const filePath = path.join(basePath, normalizedPath);
+ console.log(`파일 경로 확인: ${attachment.filePath} -> ${filePath}`);
+
// 파일 존재 확인
try {
await fs.promises.access(filePath, fs.constants.F_OK);
- } catch (e) {
+ } catch {
console.warn(`파일이 존재하지 않습니다: ${filePath}`);
return; // 파일이 없으면 건너뜀
}
diff --git a/app/api/vendors/attachments/download/route.ts b/app/api/vendors/attachments/download/route.ts
index 0151a699..1c9e5ddf 100644
--- a/app/api/vendors/attachments/download/route.ts
+++ b/app/api/vendors/attachments/download/route.ts
@@ -31,9 +31,37 @@ export async function GET(request: NextRequest) {
);
}
- // 파일 경로 구성
- const basePath = process.env.UPLOAD_DIR || path.join(process.cwd(), 'public');
- const filePath = path.join(basePath, attachment.filePath);
+ // 환경에 따른 기본 경로 설정 (/api/files/ 와 동일한 로직)
+ const nasPath = process.env.NAS_PATH || "/evcp_nas";
+ const basePath = process.env.NODE_ENV === 'production'
+ ? nasPath
+ : path.join(process.cwd(), 'public');
+
+ // DB에 저장된 경로가 /api/files/vendors/[id]/[filename] 형태인 경우 처리
+ let normalizedPath: string;
+
+ if (attachment.filePath.startsWith('/api/files/')) {
+ // /api/files/vendors/[id]/[filename] -> vendors/[id]/[filename]
+ normalizedPath = attachment.filePath.replace('/api/files/', '');
+ } else if (attachment.filePath.startsWith('/')) {
+ // 기존 방식: /vendors/[id]/[filename] -> vendors/[id]/[filename]
+ normalizedPath = attachment.filePath.slice(1);
+ } else {
+ // 상대 경로 그대로 사용
+ normalizedPath = attachment.filePath;
+ }
+
+ // 보안 검증: 경로 탐색 공격 방지
+ if (normalizedPath.includes('..') || normalizedPath.includes('~')) {
+ return NextResponse.json(
+ { error: "안전하지 않은 파일 경로입니다." },
+ { status: 400 }
+ );
+ }
+
+ const filePath = path.join(basePath, normalizedPath);
+
+ console.log(`파일 경로 확인: ${attachment.filePath} -> ${filePath}`);
// 파일 존재 확인
try {