Files
document-server/backend/src/core/database.py
Hyungi Ahn 3e0a03f149 🐛 Fix Alpine.js SyntaxError and backlink visibility issues
- Fix SyntaxError in viewer.js line 2868 (.bind(this) issue in setTimeout)
- Resolve Alpine.js 'Can't find variable' errors (documentViewer, goBack, etc.)
- Fix backlink rendering and persistence during temporary highlights
- Add backlink protection and restoration mechanism in highlightAndScrollToText
- Implement Note Management System with hierarchical notebooks
- Add note highlights and memos functionality
- Update cache version to force browser refresh (v=2025012641)
- Add comprehensive logging for debugging backlink issues
2025-08-26 23:50:48 +09:00

123 lines
3.4 KiB
Python

"""
데이터베이스 설정 및 연결
"""
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from sqlalchemy.orm import DeclarativeBase, sessionmaker, Session
from sqlalchemy import MetaData, create_engine
from typing import AsyncGenerator, Generator
from .config import settings
# SQLAlchemy 메타데이터 설정
metadata = MetaData(
naming_convention={
"ix": "ix_%(column_0_label)s",
"uq": "uq_%(table_name)s_%(column_0_name)s",
"ck": "ck_%(table_name)s_%(constraint_name)s",
"fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
"pk": "pk_%(table_name)s"
}
)
class Base(DeclarativeBase):
"""SQLAlchemy Base 클래스"""
metadata = metadata
# 비동기 데이터베이스 엔진 생성
engine = create_async_engine(
settings.DATABASE_URL,
echo=settings.DEBUG,
future=True,
pool_pre_ping=True,
pool_recycle=300,
)
# 동기 데이터베이스 엔진 생성 (노트 API용)
sync_database_url = settings.DATABASE_URL.replace("postgresql+asyncpg://", "postgresql://")
sync_engine = create_engine(
sync_database_url,
echo=settings.DEBUG,
pool_pre_ping=True,
pool_recycle=300,
)
# 비동기 세션 팩토리
AsyncSessionLocal = async_sessionmaker(
engine,
class_=AsyncSession,
expire_on_commit=False,
)
# 동기 세션 팩토리
SyncSessionLocal = sessionmaker(
sync_engine,
class_=Session,
expire_on_commit=False,
)
async def get_db() -> AsyncGenerator[AsyncSession, None]:
"""비동기 데이터베이스 세션 의존성"""
async with AsyncSessionLocal() as session:
try:
yield session
except Exception:
await session.rollback()
raise
finally:
await session.close()
def get_sync_db() -> Generator[Session, None, None]:
"""동기 데이터베이스 세션 의존성 (노트 API용)"""
session = SyncSessionLocal()
try:
yield session
except Exception:
session.rollback()
raise
finally:
session.close()
async def init_db() -> None:
"""데이터베이스 초기화"""
from ..models import user, document, highlight, note, bookmark
async with engine.begin() as conn:
# 모든 테이블 생성
await conn.run_sync(Base.metadata.create_all)
# 관리자 계정 생성
await create_admin_user()
async def create_admin_user() -> None:
"""관리자 계정 생성 (존재하지 않을 경우)"""
from ..models.user import User
from .security import get_password_hash
from sqlalchemy import select
async with AsyncSessionLocal() as session:
# 관리자 계정 존재 확인
result = await session.execute(
select(User).where(User.email == settings.ADMIN_EMAIL)
)
admin_user = result.scalar_one_or_none()
if not admin_user:
# 관리자 계정 생성
admin_user = User(
email=settings.ADMIN_EMAIL,
hashed_password=get_password_hash(settings.ADMIN_PASSWORD),
is_active=True,
is_admin=True,
full_name="Administrator"
)
session.add(admin_user)
await session.commit()
print(f"관리자 계정이 생성되었습니다: {settings.ADMIN_EMAIL}")