#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 應用程式配置模組 Author: PANJIT IT Team Created: 2024-01-28 Modified: 2024-01-28 """ import os import secrets from pathlib import Path from datetime import timedelta from dotenv import load_dotenv # 載入環境變數 load_dotenv() class Config: """基礎配置類別""" # 基本應用配置 SECRET_KEY = os.environ.get('SECRET_KEY') or secrets.token_hex(32) APP_NAME = os.environ.get('APP_NAME', 'PANJIT Document Translator') # 資料庫配置 DATABASE_URL = os.environ.get('DATABASE_URL') if DATABASE_URL and DATABASE_URL.startswith("mysql://"): DATABASE_URL = DATABASE_URL.replace("mysql://", "mysql+pymysql://", 1) SQLALCHEMY_DATABASE_URI = DATABASE_URL SQLALCHEMY_TRACK_MODIFICATIONS = False SQLALCHEMY_ENGINE_OPTIONS = { 'pool_pre_ping': True, 'pool_recycle': 3600, 'connect_args': { 'charset': os.environ.get('MYSQL_CHARSET', 'utf8mb4'), 'connect_timeout': 30, 'read_timeout': 30, 'write_timeout': 30, } } # JWT 配置 - 改用 JWT 認證 JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY') or SECRET_KEY JWT_ACCESS_TOKEN_EXPIRES = timedelta(hours=8) JWT_REFRESH_TOKEN_EXPIRES = timedelta(days=30) JWT_ALGORITHM = 'HS256' # Redis 配置 REDIS_URL = os.environ.get('REDIS_URL', 'redis://localhost:6379/0') # Celery 配置 CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0') CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0') CELERY_TASK_SERIALIZER = 'json' CELERY_RESULT_SERIALIZER = 'json' CELERY_ACCEPT_CONTENT = ['json'] CELERY_TIMEZONE = 'Asia/Taipei' CELERY_ENABLE_UTC = False # 改為 False,讓 Celery 使用本地時區 # LDAP 配置 LDAP_SERVER = os.environ.get('LDAP_SERVER') LDAP_PORT = int(os.environ.get('LDAP_PORT', 389)) LDAP_USE_SSL = os.environ.get('LDAP_USE_SSL', 'false').lower() == 'true' LDAP_BIND_USER_DN = os.environ.get('LDAP_BIND_USER_DN') LDAP_BIND_USER_PASSWORD = os.environ.get('LDAP_BIND_USER_PASSWORD') LDAP_SEARCH_BASE = os.environ.get('LDAP_SEARCH_BASE') LDAP_USER_LOGIN_ATTR = os.environ.get('LDAP_USER_LOGIN_ATTR', 'userPrincipalName') # SMTP 配置 SMTP_SERVER = os.environ.get('SMTP_SERVER') SMTP_PORT = int(os.environ.get('SMTP_PORT', 587)) SMTP_USE_TLS = os.environ.get('SMTP_USE_TLS', 'false').lower() == 'true' SMTP_USE_SSL = os.environ.get('SMTP_USE_SSL', 'false').lower() == 'true' SMTP_AUTH_REQUIRED = os.environ.get('SMTP_AUTH_REQUIRED', 'false').lower() == 'true' SMTP_SENDER_EMAIL = os.environ.get('SMTP_SENDER_EMAIL') SMTP_SENDER_PASSWORD = os.environ.get('SMTP_SENDER_PASSWORD', '') # 檔案上傳配置 UPLOAD_FOLDER = Path(os.environ.get('UPLOAD_FOLDER', 'uploads')).absolute() MAX_CONTENT_LENGTH = int(os.environ.get('MAX_CONTENT_LENGTH', 26214400)) # 25MB ALLOWED_EXTENSIONS = {'.docx', '.doc', '.pptx', '.xlsx', '.xls', '.pdf'} FILE_RETENTION_DAYS = int(os.environ.get('FILE_RETENTION_DAYS', 7)) # Dify API 配置(從 api.txt 載入) DIFY_API_BASE_URL = '' DIFY_API_KEY = '' # 日誌配置 LOG_LEVEL = os.environ.get('LOG_LEVEL', 'INFO') LOG_FILE = Path(os.environ.get('LOG_FILE', 'logs/app.log')).absolute() # 管理員配置 ADMIN_EMAIL = os.environ.get('ADMIN_EMAIL', 'ymirliu@panjit.com.tw') @classmethod def load_dify_config(cls): """從 api.txt 載入 Dify API 配置""" api_file = Path('api.txt') if api_file.exists(): try: with open(api_file, 'r', encoding='utf-8') as f: for line in f: if line.startswith('base_url:'): cls.DIFY_API_BASE_URL = line.split(':', 1)[1].strip() elif line.startswith('api:'): cls.DIFY_API_KEY = line.split(':', 1)[1].strip() except Exception: pass @classmethod def init_directories(cls): """初始化必要目錄""" directories = [ cls.UPLOAD_FOLDER, cls.LOG_FILE.parent, ] for directory in directories: directory.mkdir(parents=True, exist_ok=True) class DevelopmentConfig(Config): """開發環境配置""" DEBUG = True FLASK_ENV = 'development' class ProductionConfig(Config): """生產環境配置""" DEBUG = False FLASK_ENV = 'production' # 生產環境的額外配置 SQLALCHEMY_ENGINE_OPTIONS = { **Config.SQLALCHEMY_ENGINE_OPTIONS, 'pool_size': 10, 'max_overflow': 20, } class TestingConfig(Config): """測試環境配置""" TESTING = True WTF_CSRF_ENABLED = False SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:' # 配置映射 config = { 'development': DevelopmentConfig, 'production': ProductionConfig, 'testing': TestingConfig, 'default': DevelopmentConfig }