Fix: HTTPS Mixed Content 오류 수정 및 백업 시스템 구축

- Frontend: 하드코딩된 localhost API URL을 동적 URL 생성으로 변경
  - reports-daily.html: 3곳 수정 (프로젝트 로드, 미리보기, 보고서 생성)
  - issues-archive.html: 프로젝트 로드 함수 수정
  - issues-dashboard.html: 2곳 수정 (프로젝트 로드, 진행중 이슈 로드)
  - issues-inbox.html: 프로젝트 로드 함수 수정
  - daily-work.html: 프로젝트 로드 함수 수정
  - permissions.js: 2곳 수정 (권한 부여, 사용자 권한 조회)

- Backup System: 완전한 백업/복구 시스템 구축
  - backup_script.sh: 자동 백업 스크립트 (DB, 볼륨, 설정 파일)
  - restore_script.sh: 백업 복구 스크립트
  - setup_auto_backup.sh: 자동 백업 스케줄 설정 (매일 오후 9시)
  - 백업 정책: 최신 10개 버전만 유지하여 용량 절약

- Migration: 5장 사진 지원 마이그레이션 파일 업데이트

이제 Cloudflare 환경(m.hyungi.net)에서 HTTPS 프로토콜로 API 호출하여
Mixed Content 오류 없이 모든 기능이 정상 작동합니다.
This commit is contained in:
hyungi
2025-11-13 06:52:21 +09:00
parent 86a6d21a08
commit a820a164cb
10 changed files with 350 additions and 6 deletions

View File

@@ -341,6 +341,12 @@
// API에서 최신 프로젝트 데이터 가져오기
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}

View File

@@ -287,7 +287,19 @@
// 프로젝트 로드
async function loadProjects() {
try {
const apiUrl = window.API_BASE_URL || 'http://localhost:16080/api';
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}
return '/api';
})();
const response = await fetch(`${apiUrl}/projects/`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,

View File

@@ -325,6 +325,12 @@
try {
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}
@@ -342,6 +348,12 @@
try {
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}

View File

@@ -670,6 +670,12 @@
try {
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}

View File

@@ -234,7 +234,19 @@
// 프로젝트 목록 로드
async function loadProjects() {
try {
const apiUrl = window.API_BASE_URL || 'http://localhost:16080/api';
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}
return '/api';
})();
const response = await fetch(`${apiUrl}/projects/`, {
headers: {
@@ -302,7 +314,19 @@
}
try {
const apiUrl = window.API_BASE_URL || 'http://localhost:16080/api';
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}
return '/api';
})();
const response = await fetch(`${apiUrl}/reports/daily-preview?project_id=${selectedProjectId}`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`
@@ -427,7 +451,19 @@
button.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>생성 중...';
button.disabled = true;
const apiUrl = window.API_BASE_URL || 'http://localhost:16080/api';
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}
return '/api';
})();
const response = await fetch(`${apiUrl}/reports/daily-export`, {
method: 'POST',
headers: {

View File

@@ -205,7 +205,19 @@ class PagePermissionManager {
}
try {
const apiUrl = window.API_BASE_URL || 'http://localhost:16080/api';
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}
return '/api';
})();
const response = await fetch(`${apiUrl}/page-permissions/grant`, {
method: 'POST',
headers: {
@@ -238,7 +250,19 @@ class PagePermissionManager {
*/
async getUserPagePermissions(userId) {
try {
const apiUrl = window.API_BASE_URL || 'http://localhost:16080/api';
const apiUrl = window.API_BASE_URL || (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
if ((hostname === 'localhost' || hostname === '127.0.0.1') && port) {
return `${protocol}//${hostname}:${port}/api`;
}
if (hostname === 'm.hyungi.net') {
return 'https://m-api.hyungi.net/api';
}
return '/api';
})();
const response = await fetch(`${apiUrl}/users/${userId}/page-permissions`, {
headers: {
'Authorization': `Bearer ${localStorage.getItem('access_token')}`