Files
document-server/frontend/static/js/auth.js
Hyungi Ahn 3036b8f0fb 🎉 Initial commit: Document Server MVP
 Features implemented:
- FastAPI backend with JWT authentication
- PostgreSQL database with async SQLAlchemy
- HTML document viewer with smart highlighting
- Note system connected to highlights (1:1 relationship)
- Bookmark system for quick navigation
- Integrated search (documents + notes)
- Tag system for document organization
- Docker containerization with Nginx

🔧 Technical stack:
- Backend: FastAPI + PostgreSQL + Redis
- Frontend: Alpine.js + Tailwind CSS
- Authentication: JWT tokens
- File handling: HTML + PDF support
- Search: Full-text search with relevance scoring

📋 Core functionality:
- Text selection → Highlight creation
- Highlight → Note attachment
- Note management with search/filtering
- Bookmark creation at scroll positions
- Document upload with metadata
- User management (admin creates accounts)
2025-08-21 16:09:17 +09:00

91 lines
2.7 KiB
JavaScript

/**
* 인증 관련 Alpine.js 컴포넌트
*/
// 인증 모달 컴포넌트
window.authModal = () => ({
showLogin: false,
loginForm: {
email: '',
password: ''
},
loginError: '',
loginLoading: false,
async login() {
this.loginLoading = true;
this.loginError = '';
try {
const response = await api.login(this.loginForm.email, this.loginForm.password);
// 토큰 저장
api.setToken(response.access_token);
localStorage.setItem('refresh_token', response.refresh_token);
// 사용자 정보 로드
const user = await api.getCurrentUser();
// 전역 상태 업데이트
window.dispatchEvent(new CustomEvent('auth-changed', {
detail: { isAuthenticated: true, user }
}));
// 모달 닫기
this.showLogin = false;
this.loginForm = { email: '', password: '' };
} catch (error) {
this.loginError = error.message;
} finally {
this.loginLoading = false;
}
},
async logout() {
try {
await api.logout();
} catch (error) {
console.error('Logout error:', error);
} finally {
// 로컬 스토리지 정리
localStorage.removeItem('refresh_token');
// 전역 상태 업데이트
window.dispatchEvent(new CustomEvent('auth-changed', {
detail: { isAuthenticated: false, user: null }
}));
}
}
});
// 자동 토큰 갱신
async function refreshTokenIfNeeded() {
const refreshToken = localStorage.getItem('refresh_token');
if (!refreshToken || !api.token) return;
try {
// 토큰 만료 확인 (JWT 디코딩)
const tokenPayload = JSON.parse(atob(api.token.split('.')[1]));
const now = Date.now() / 1000;
// 토큰이 5분 내에 만료되면 갱신
if (tokenPayload.exp - now < 300) {
const response = await api.refreshToken(refreshToken);
api.setToken(response.access_token);
localStorage.setItem('refresh_token', response.refresh_token);
}
} catch (error) {
console.error('Token refresh failed:', error);
// 갱신 실패시 로그아웃
api.setToken(null);
localStorage.removeItem('refresh_token');
window.dispatchEvent(new CustomEvent('auth-changed', {
detail: { isAuthenticated: false, user: null }
}));
}
}
// 5분마다 토큰 갱신 체크
setInterval(refreshTokenIfNeeded, 5 * 60 * 1000);