// /js/api-base.js // API 기본 설정 및 보안 유틸리티 - System 2 (신고 시스템) // 서비스 워커 해제 (push-sw.js 제외) if ('serviceWorker' in navigator) { navigator.serviceWorker.getRegistrations().then(function(registrations) { registrations.forEach(function(registration) { if (!registration.active || !registration.active.scriptURL.includes('push-sw.js')) { registration.unregister(); } }); }); if (typeof caches !== 'undefined') { caches.keys().then(function(names) { names.forEach(function(name) { caches.delete(name); }); }); } } (function() { 'use strict'; // ==================== SSO 쿠키 유틸리티 ==================== function cookieGet(name) { var match = document.cookie.match(new RegExp('(?:^|; )' + name + '=([^;]*)')); return match ? decodeURIComponent(match[1]) : null; } function cookieRemove(name) { var cookie = name + '=; path=/; max-age=0'; if (window.location.hostname.includes('technicalkorea.net')) { cookie += '; domain=.technicalkorea.net; secure; samesite=lax'; } document.cookie = cookie; } /** * SSO 토큰 가져오기 (쿠키 우선, localStorage 폴백) */ window.getSSOToken = function() { return cookieGet('sso_token'); }; window.getSSOUser = function() { var raw = cookieGet('sso_user'); try { return raw ? JSON.parse(raw) : null; } catch(e) { return null; } }; /** * 중앙 로그인 URL 반환 (System 2 → tkfb 도메인의 로그인으로) */ window.getLoginUrl = function() { var hostname = window.location.hostname; var t = Date.now(); if (hostname.includes('technicalkorea.net')) { return window.location.protocol + '//tkfb.technicalkorea.net/dashboard?redirect=' + encodeURIComponent(window.location.href) + '&_t=' + t; } return window.location.protocol + '//' + hostname + ':30780/dashboard?redirect=' + encodeURIComponent(window.location.href) + '&_t=' + t; }; window.clearSSOAuth = function() { cookieRemove('sso_token'); cookieRemove('sso_user'); cookieRemove('sso_refresh_token'); ['sso_token','sso_user','sso_refresh_token','token','user','access_token','currentUser','current_user','userInfo','userPageAccess'].forEach(function(k) { localStorage.removeItem(k); }); }; // ==================== 보안 유틸리티 (XSS 방지) ==================== window.escapeHtml = function(str) { if (str === null || str === undefined) return ''; if (typeof str !== 'string') str = String(str); var htmlEntities = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=' }; return str.replace(/[&<>"'`=\/]/g, function(char) { return htmlEntities[char]; }); }; window.escapeUrl = function(str) { if (str === null || str === undefined) return ''; return encodeURIComponent(String(str)); }; // ==================== API 설정 ==================== var API_PORT = 30105; var API_PATH = '/api'; function getApiBaseUrl() { var hostname = window.location.hostname; var protocol = window.location.protocol; // 프로덕션 환경 - 같은 도메인의 /api 경로 (system2-web nginx가 프록시) if (hostname.includes('technicalkorea.net')) { return protocol + '//' + hostname + API_PATH; } // 개발 환경 return protocol + '//' + hostname + ':' + API_PORT + API_PATH; } var apiUrl = getApiBaseUrl(); window.API_BASE_URL = apiUrl; window.API = apiUrl; // 인증 헤더 생성 - SSO 토큰 사용 (쿠키/localStorage) window.getAuthHeaders = function() { var token = window.getSSOToken(); return { 'Content-Type': 'application/json', 'Authorization': token ? 'Bearer ' + token : '' }; }; // API 호출 헬퍼 window.apiCall = async function(endpoint, method, data) { method = method || 'GET'; var url = window.API_BASE_URL + endpoint; var config = { method: method, headers: window.getAuthHeaders() }; if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE')) { config.body = JSON.stringify(data); } var response = await fetch(url, config); // 401 Unauthorized 처리 — 토큰만 정리하고 에러 throw (리다이렉트는 app-init이 처리) if (response.status === 401) { window.clearSSOAuth(); throw new Error('인증이 만료되었습니다.'); } return response.json(); }; // 알림 벨 로드 window._loadNotificationBell = function() { var h = window.location.hostname; var s = document.createElement('script'); s.src = (h.includes('technicalkorea.net') ? 'https://tkfb.technicalkorea.net' : window.location.protocol + '//' + h + ':30000') + '/shared/notification-bell.js?v=4'; document.head.appendChild(s); }; console.log('[System2] API 설정 완료:', window.API_BASE_URL); })();