Files
TK-FB-Project/api.hyungi.net/models/projectModel.js
Hyungi Ahn 36f110c90a fix: 보안 취약점 수정 및 XSS 방지 적용
## 백엔드 보안 수정
- 하드코딩된 비밀번호 및 JWT 시크릿 폴백 제거
- SQL Injection 방지를 위한 화이트리스트 검증 추가
- 인증 미적용 API 라우트에 requireAuth 미들웨어 적용
- CSRF 보호 미들웨어 구현 (csrf.js)
- 파일 업로드 보안 유틸리티 추가 (fileUploadSecurity.js)
- 비밀번호 정책 검증 유틸리티 추가 (passwordValidator.js)

## 프론트엔드 XSS 방지
- api-base.js에 전역 escapeHtml() 함수 추가
- 17개 주요 JS 파일에 escapeHtml 적용:
  - tbm.js, daily-patrol.js, daily-work-report.js
  - task-management.js, workplace-status.js
  - equipment-detail.js, equipment-management.js
  - issue-detail.js, issue-report.js
  - vacation-common.js, worker-management.js
  - safety-report-list.js, nonconformity-list.js
  - project-management.js, workplace-management.js

## 정리
- 백업 폴더 및 빈 파일 삭제
- SECURITY_GUIDE.md 문서 추가

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 06:33:10 +09:00

97 lines
2.8 KiB
JavaScript

const { getDb } = require('../dbPool');
const create = async (project) => {
const db = await getDb();
const {
job_no, project_name,
contract_date, due_date,
delivery_method, site, pm,
is_active = true,
project_status = 'active',
completed_date = null
} = project;
const [result] = await db.query(
`INSERT INTO projects
(job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date]
);
return result.insertId;
};
const getAll = async () => {
const db = await getDb();
const [rows] = await db.query(
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects ORDER BY project_id DESC`
);
return rows;
};
// 활성 프로젝트만 조회 (작업보고서용)
const getActiveProjects = async () => {
const db = await getDb();
const [rows] = await db.query(
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects
WHERE is_active = TRUE
ORDER BY project_name ASC`
);
return rows;
};
const getById = async (project_id) => {
const db = await getDb();
const [rows] = await db.query(
`SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects WHERE project_id = ?`,
[project_id]
);
return rows[0];
};
const update = async (project) => {
const db = await getDb();
const {
project_id, job_no, project_name,
contract_date, due_date,
delivery_method, site, pm,
is_active, project_status, completed_date
} = project;
const [result] = await db.query(
`UPDATE projects
SET job_no = ?,
project_name = ?,
contract_date = ?,
due_date = ?,
delivery_method= ?,
site = ?,
pm = ?,
is_active = ?,
project_status = ?,
completed_date = ?
WHERE project_id = ?`,
[job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, project_id]
);
return result.affectedRows;
};
const remove = async (project_id) => {
const db = await getDb();
const [result] = await db.query(
`DELETE FROM projects WHERE project_id = ?`,
[project_id]
);
return result.affectedRows;
};
module.exports = {
create,
getAll,
getActiveProjects,
getById,
update,
remove
};