Fix: 페이지 간 이동 시 로그아웃 문제 해결 및 기능 개선

- 토큰 저장 키 통일 (access_token으로 일관성 확보)
- 일일공수 페이지 API 스크립트 로딩 순서 수정
- 프로젝트 관리 페이지 비활성 프로젝트 표시 문제 해결
- 업로드 카테고리에 '기타' 항목 추가 (백엔드 schemas.py 포함)
- 비밀번호 변경 기능 API 연동으로 수정
- 프로젝트 드롭다운 z-index 문제 해결
- CORS 설정 및 Nginx 구성 개선
- 비밀번호 해싱 방식 pbkdf2_sha256으로 변경 (bcrypt 72바이트 제한 해결)
This commit is contained in:
hyungi
2025-10-25 07:22:20 +09:00
parent 153603ed9d
commit 41b557a709
27 changed files with 1283 additions and 311 deletions

View File

@@ -1,5 +1,30 @@
// API 기본 설정
const API_BASE_URL = '/api';
// API 기본 설정 (Cloudflare 터널 + 로컬 환경 지원)
const API_BASE_URL = (() => {
const hostname = window.location.hostname;
const protocol = window.location.protocol;
const port = window.location.port;
console.log('🔧 API URL 생성 - hostname:', hostname, 'protocol:', protocol, 'port:', port);
// 로컬 환경 (포트 있음)
if (port === '16080') {
const url = `${protocol}//${hostname}:${port}/api`;
console.log('🏠 로컬 환경 URL:', url);
return url;
}
// Cloudflare 터널 환경 (m.hyungi.net) - 강제 HTTPS
if (hostname === 'm.hyungi.net') {
const url = `https://m-api.hyungi.net/api`;
console.log('☁️ Cloudflare 환경 URL:', url);
return url;
}
// 기타 환경
const url = '/api';
console.log('🌐 기타 환경 URL:', url);
return url;
})();
// 토큰 관리
const TokenManager = {
@@ -76,23 +101,29 @@ const AuthAPI = {
formData.append('username', username);
formData.append('password', password);
const response = await fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData.toString()
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || '로그인 실패');
try {
const response = await fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData.toString()
});
if (!response.ok) {
const error = await response.json();
console.error('로그인 에러:', error);
throw new Error(error.detail || '로그인 실패');
}
const data = await response.json();
TokenManager.setToken(data.access_token);
TokenManager.setUser(data.user);
return data;
} catch (error) {
console.error('로그인 요청 에러:', error);
throw error;
}
const data = await response.json();
TokenManager.setToken(data.access_token);
TokenManager.setUser(data.user);
return data;
},
logout: () => {
@@ -103,6 +134,8 @@ const AuthAPI = {
getMe: () => apiRequest('/auth/me'),
getCurrentUser: () => apiRequest('/auth/me'),
createUser: (userData) => apiRequest('/auth/users', {
method: 'POST',
body: JSON.stringify(userData)
@@ -252,12 +285,12 @@ function checkAdminAuth() {
const ProjectsAPI = {
getAll: (activeOnly = false) => {
const params = activeOnly ? '?active_only=true' : '';
return apiRequest(`/projects${params}`);
return apiRequest(`/projects/${params}`);
},
get: (id) => apiRequest(`/projects/${id}`),
create: (projectData) => apiRequest('/projects', {
create: (projectData) => apiRequest('/projects/', {
method: 'POST',
body: JSON.stringify(projectData)
}),