security: 보안 강제 시스템 구축 + 하드코딩 비밀번호 제거
보안 감사 결과 CRITICAL 2건, HIGH 5건 발견 → 수정 완료 + 자동화 구축. [보안 수정] - issue-view.js: 하드코딩 비밀번호 → crypto.getRandomValues() 랜덤 생성 - pushSubscriptionController.js: ntfy 비밀번호 → process.env.NTFY_SUB_PASSWORD - DEPLOY-GUIDE.md/PROGRESS.md/migration SQL: 평문 비밀번호 → placeholder - docker-compose.yml/.env.example: NTFY_SUB_PASSWORD 환경변수 추가 [보안 강제 시스템 - 신규] - scripts/security-scan.sh: 8개 규칙 (CRITICAL 2, HIGH 4, MEDIUM 2) 3모드(staged/all/diff), severity, .securityignore, MEDIUM 임계값 - .githooks/pre-commit: 로컬 빠른 피드백 - .githooks/pre-receive-server.sh: Gitea 서버 최종 차단 bypass 거버넌스([SECURITY-BYPASS: 사유] + 사용자 제한 + 로그) - SECURITY-CHECKLIST.md: 10개 카테고리 자동/수동 구분 - docs/SECURITY-GUIDE.md: 운영자 가이드 (워크플로우, bypass, FAQ) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
139
system3-nonconformance/web/public/static/js/date-utils.js
Normal file
139
system3-nonconformance/web/public/static/js/date-utils.js
Normal file
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* 날짜 관련 유틸리티 함수들
|
||||
* 한국 표준시(KST) 기준으로 처리
|
||||
*/
|
||||
|
||||
const DateUtils = {
|
||||
/**
|
||||
* UTC 시간을 KST로 변환
|
||||
* @param {string|Date} dateInput - UTC 날짜 문자열 또는 Date 객체
|
||||
* @returns {Date} KST 시간대의 Date 객체
|
||||
*/
|
||||
toKST(dateInput) {
|
||||
const date = typeof dateInput === 'string' ? new Date(dateInput) : dateInput;
|
||||
// UTC 시간에 9시간 추가 (KST = UTC+9)
|
||||
return new Date(date.getTime() + (date.getTimezoneOffset() * 60000) + (9 * 3600000));
|
||||
},
|
||||
|
||||
/**
|
||||
* 현재 KST 시간 가져오기
|
||||
* @returns {Date} 현재 KST 시간
|
||||
*/
|
||||
nowKST() {
|
||||
const now = new Date();
|
||||
return this.toKST(now);
|
||||
},
|
||||
|
||||
/**
|
||||
* KST 날짜를 한국식 문자열로 포맷
|
||||
* @param {string|Date} dateInput - 날짜
|
||||
* @param {boolean} includeTime - 시간 포함 여부
|
||||
* @returns {string} 포맷된 날짜 문자열
|
||||
*/
|
||||
formatKST(dateInput, includeTime = false) {
|
||||
const date = typeof dateInput === 'string' ? new Date(dateInput) : dateInput;
|
||||
|
||||
const options = {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
timeZone: 'Asia/Seoul'
|
||||
};
|
||||
|
||||
if (includeTime) {
|
||||
options.hour = '2-digit';
|
||||
options.minute = '2-digit';
|
||||
options.hour12 = false;
|
||||
}
|
||||
|
||||
return date.toLocaleString('ko-KR', options);
|
||||
},
|
||||
|
||||
/**
|
||||
* 상대적 시간 표시 (예: 3분 전, 2시간 전)
|
||||
* @param {string|Date} dateInput - 날짜
|
||||
* @returns {string} 상대적 시간 문자열
|
||||
*/
|
||||
getRelativeTime(dateInput) {
|
||||
const date = typeof dateInput === 'string' ? new Date(dateInput) : dateInput;
|
||||
const now = new Date();
|
||||
const diffMs = now - date;
|
||||
const diffSec = Math.floor(diffMs / 1000);
|
||||
const diffMin = Math.floor(diffSec / 60);
|
||||
const diffHour = Math.floor(diffMin / 60);
|
||||
const diffDay = Math.floor(diffHour / 24);
|
||||
|
||||
if (diffSec < 60) return '방금 전';
|
||||
if (diffMin < 60) return `${diffMin}분 전`;
|
||||
if (diffHour < 24) return `${diffHour}시간 전`;
|
||||
if (diffDay < 7) return `${diffDay}일 전`;
|
||||
|
||||
return this.formatKST(date);
|
||||
},
|
||||
|
||||
/**
|
||||
* 오늘 날짜인지 확인 (KST 기준)
|
||||
* @param {string|Date} dateInput - 날짜
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isToday(dateInput) {
|
||||
const date = typeof dateInput === 'string' ? new Date(dateInput) : dateInput;
|
||||
const today = new Date();
|
||||
|
||||
return date.toLocaleDateString('ko-KR', { timeZone: 'Asia/Seoul' }) ===
|
||||
today.toLocaleDateString('ko-KR', { timeZone: 'Asia/Seoul' });
|
||||
},
|
||||
|
||||
/**
|
||||
* 이번 주인지 확인 (KST 기준, 월요일 시작)
|
||||
* @param {string|Date} dateInput - 날짜
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isThisWeek(dateInput) {
|
||||
const date = typeof dateInput === 'string' ? new Date(dateInput) : dateInput;
|
||||
const now = new Date();
|
||||
|
||||
// 주의 시작일 (월요일) 계산
|
||||
const startOfWeek = new Date(now);
|
||||
const day = startOfWeek.getDay();
|
||||
const diff = startOfWeek.getDate() - day + (day === 0 ? -6 : 1);
|
||||
startOfWeek.setDate(diff);
|
||||
startOfWeek.setHours(0, 0, 0, 0);
|
||||
|
||||
// 주의 끝일 (일요일) 계산
|
||||
const endOfWeek = new Date(startOfWeek);
|
||||
endOfWeek.setDate(startOfWeek.getDate() + 6);
|
||||
endOfWeek.setHours(23, 59, 59, 999);
|
||||
|
||||
return date >= startOfWeek && date <= endOfWeek;
|
||||
},
|
||||
|
||||
/**
|
||||
* ISO 문자열을 로컬 date input 값으로 변환
|
||||
* @param {string} isoString - ISO 날짜 문자열
|
||||
* @returns {string} YYYY-MM-DD 형식
|
||||
*/
|
||||
toDateInputValue(isoString) {
|
||||
const date = new Date(isoString);
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}`;
|
||||
},
|
||||
|
||||
/**
|
||||
* 날짜 차이 계산 (일 단위)
|
||||
* @param {string|Date} date1 - 첫 번째 날짜
|
||||
* @param {string|Date} date2 - 두 번째 날짜
|
||||
* @returns {number} 일 수 차이
|
||||
*/
|
||||
getDaysDiff(date1, date2) {
|
||||
const d1 = typeof date1 === 'string' ? new Date(date1) : date1;
|
||||
const d2 = typeof date2 === 'string' ? new Date(date2) : date2;
|
||||
const diffMs = Math.abs(d2 - d1);
|
||||
return Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
||||
}
|
||||
};
|
||||
|
||||
// 전역으로 사용 가능하도록 export
|
||||
window.DateUtils = DateUtils;
|
||||
Reference in New Issue
Block a user