soyailabs / app /__init__.py
SOY NV AI
๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ƒ์„ฑ ๊ธฐ๋Šฅ ๊ฐœ์„ : ๊ธฐ์กด ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ๋ณ‘ํ•ฉ ๋ฐ ํšŒ์ฐจ ์ •๋ณด ์œ ์ง€
d234e06
raw
history blame
6.64 kB
"""
Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ดˆ๊ธฐํ™”
"""
from flask import Flask
from flask_login import LoginManager
import sqlite3
from pathlib import Path
from typing import Optional
from app.database import db, User
from app.core.config import Config, get_config
from app.core.logger import get_logger
logger = get_logger(__name__)
login_manager = LoginManager()
login_manager.login_view = 'main.login'
login_manager.login_message = '๋กœ๊ทธ์ธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.'
login_manager.login_message_category = 'info'
@login_manager.user_loader
def load_user(user_id: str) -> Optional[User]:
"""
์‚ฌ์šฉ์ž ๋กœ๋“œ ํ•จ์ˆ˜ (Flask-Login์šฉ)
Args:
user_id: ์‚ฌ์šฉ์ž ID (๋ฌธ์ž์—ด)
Returns:
User ๊ฐ์ฒด ๋˜๋Š” None
"""
try:
return User.query.get(int(user_id))
except (ValueError, TypeError):
return None
def create_app() -> Flask:
"""
Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํŒฉํ† ๋ฆฌ ํ•จ์ˆ˜
Returns:
์„ค์ •๋œ Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธ์Šคํ„ด์Šค
"""
config = get_config()
# ํ•„์ˆ˜ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
config.ensure_directories()
# ํ…œํ”Œ๋ฆฟ ํด๋” ๋ฐ static ํด๋” ๊ฒฝ๋กœ ์„ค์ •
template_folder = str(config.TEMPLATES_FOLDER)
static_folder = str(config.STATIC_FOLDER)
app = Flask(__name__, template_folder=template_folder, static_folder=static_folder)
# Flask ์„ค์ • ์ ์šฉ
app.config['SECRET_KEY'] = config.SECRET_KEY
app.config['SQLALCHEMY_DATABASE_URI'] = config.SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = config.SQLALCHEMY_TRACK_MODIFICATIONS
app.config['MAX_CONTENT_LENGTH'] = config.MAX_CONTENT_LENGTH
# ํ™•์žฅ ์ดˆ๊ธฐํ™”
db.init_app(app)
login_manager.init_app(app)
# Blueprint ๋“ฑ๋ก
from app.routes import main_bp
app.register_blueprint(main_bp)
# ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ดˆ๊ธฐํ™” ๋ฐ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜
with app.app_context():
db.create_all()
migrate_database(app)
create_admin_user()
logger.info("Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์ดˆ๊ธฐํ™”๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
return app
def migrate_database(app: Flask) -> None:
"""
๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰
Args:
app: Flask ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ธ์Šคํ„ด์Šค
"""
try:
db_uri = app.config['SQLALCHEMY_DATABASE_URI']
if not db_uri.startswith('sqlite:///'):
logger.warning(f"SQLite๊ฐ€ ์•„๋‹Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ž๋™ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์ง€์›๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: {db_uri}")
return
db_path_str = db_uri.replace('sqlite:///', '')
db_path = Path(db_path_str)
# ์ƒ๋Œ€ ๊ฒฝ๋กœ์ธ ๊ฒฝ์šฐ instance ํด๋” ๊ธฐ์ค€์œผ๋กœ ์ฒ˜๋ฆฌ
if not db_path.is_absolute():
db_path = Path(app.instance_path) / db_path
if not db_path.exists():
logger.info(f"๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค (์ƒˆ๋กœ ์ƒ์„ฑ๋จ): {db_path}")
return
logger.info(f"๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹œ์ž‘: {db_path}")
conn = sqlite3.connect(str(db_path))
cursor = conn.cursor()
# user ํ…Œ์ด๋ธ”์— nickname ์ปฌ๋Ÿผ์ด ์žˆ๋Š”์ง€ ํ™•์ธ
cursor.execute("PRAGMA table_info(user)")
user_columns = [column[1] for column in cursor.fetchall()]
if 'nickname' not in user_columns:
logger.info("user ํ…Œ์ด๋ธ”์— nickname ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์ค‘...")
cursor.execute("ALTER TABLE user ADD COLUMN nickname VARCHAR(80)")
conn.commit()
logger.info("user.nickname ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์™„๋ฃŒ")
# uploaded_file ํ…Œ์ด๋ธ”์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='uploaded_file'")
if cursor.fetchone():
cursor.execute("PRAGMA table_info(uploaded_file)")
uploaded_file_columns = [column[1] for column in cursor.fetchall()]
if 'uploaded_by' not in uploaded_file_columns:
logger.info("uploaded_file ํ…Œ์ด๋ธ”์— uploaded_by ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์ค‘...")
cursor.execute("ALTER TABLE uploaded_file ADD COLUMN uploaded_by INTEGER")
conn.commit()
logger.info("uploaded_file.uploaded_by ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์™„๋ฃŒ")
if 'parent_file_id' not in uploaded_file_columns:
logger.info("uploaded_file ํ…Œ์ด๋ธ”์— parent_file_id ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์ค‘...")
cursor.execute("ALTER TABLE uploaded_file ADD COLUMN parent_file_id INTEGER")
conn.commit()
logger.info("uploaded_file.parent_file_id ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์™„๋ฃŒ")
# document_chunk ํ…Œ์ด๋ธ”์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธ
cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='document_chunk'")
if cursor.fetchone():
cursor.execute("PRAGMA table_info(document_chunk)")
document_chunk_columns = [column[1] for column in cursor.fetchall()]
if 'chunk_metadata' not in document_chunk_columns:
logger.info("document_chunk ํ…Œ์ด๋ธ”์— chunk_metadata ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์ค‘...")
cursor.execute("ALTER TABLE document_chunk ADD COLUMN chunk_metadata TEXT")
conn.commit()
logger.info("document_chunk.chunk_metadata ์ปฌ๋Ÿผ ์ถ”๊ฐ€ ์™„๋ฃŒ")
conn.close()
logger.info("๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์™„๋ฃŒ")
except sqlite3.Error as e:
logger.error(f"๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ค‘ SQLite ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}", exc_info=True)
except Exception as e:
logger.error(f"๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}", exc_info=True)
def create_admin_user() -> None:
"""
์ดˆ๊ธฐ ๊ด€๋ฆฌ์ž ๊ณ„์ • ์ƒ์„ฑ
"""
admin_username = 'soymedia'
admin_password = 's0ymedi@1@34'
try:
admin = User.query.filter_by(username=admin_username).first()
if not admin:
admin = User(username=admin_username, is_admin=True, is_active=True)
admin.set_password(admin_password)
db.session.add(admin)
db.session.commit()
logger.info(f'๊ด€๋ฆฌ์ž ๊ณ„์ •์ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค: {admin_username}')
else:
logger.debug(f'๊ด€๋ฆฌ์ž ๊ณ„์ •์ด ์ด๋ฏธ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค: {admin_username}')
except Exception as e:
logger.error(f'๊ด€๋ฆฌ์ž ๊ณ„์ • ์ƒ์„ฑ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}', exc_info=True)
db.session.rollback()