1st_fix_login_issue

This commit is contained in:
beabigegg
2025-09-02 10:31:35 +08:00
commit a60d965317
103 changed files with 12402 additions and 0 deletions

212
app/__init__.py Normal file
View File

@@ -0,0 +1,212 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Flask 應用程式工廠
Author: PANJIT IT Team
Created: 2024-01-28
Modified: 2024-01-28
"""
import os
import redis
from flask import Flask, request, make_response
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from flask_jwt_extended import JWTManager
from celery import Celery
from app.config import config
from app.utils.logger import init_logging
# 初始化擴展
db = SQLAlchemy()
cors = CORS()
jwt = JWTManager()
def make_celery(app):
"""創建 Celery 實例"""
celery = Celery(
app.import_name,
backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL']
)
celery.conf.update(app.config)
class ContextTask(celery.Task):
"""在 Flask 應用上下文中執行任務"""
def __call__(self, *args, **kwargs):
with app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
def create_app(config_name=None):
"""應用程式工廠"""
app = Flask(__name__)
# 載入配置
config_name = config_name or os.getenv('FLASK_ENV', 'default')
app.config.from_object(config[config_name])
# 載入 Dify API 配置
config[config_name].load_dify_config()
# 初始化必要目錄
config[config_name].init_directories()
# 初始化擴展
db.init_app(app)
# 不使用 Flask-CORS 避免衝突使用手動CORS處理
# 初始化 JWT
jwt.init_app(app)
app.logger.info(f"🔑 [JWT Config] JWT_SECRET_KEY: {app.config.get('JWT_SECRET_KEY')[:10]}...{app.config.get('JWT_SECRET_KEY')[-10:] if app.config.get('JWT_SECRET_KEY') else 'None'}")
app.logger.info(f"🔑 [JWT Config] JWT_ACCESS_TOKEN_EXPIRES: {app.config.get('JWT_ACCESS_TOKEN_EXPIRES')}")
app.logger.info(f"🔑 [JWT Config] JWT_REFRESH_TOKEN_EXPIRES: {app.config.get('JWT_REFRESH_TOKEN_EXPIRES')}")
app.logger.info("🔑 [JWT] Using JWT authentication")
# 設定 Redis用於Celery
try:
redis_client = redis.from_url(app.config['REDIS_URL'])
app.redis_client = redis_client
except Exception as e:
app.logger.warning(f"Redis initialization failed: {str(e)}")
app.redis_client = None
# 初始化日誌
init_logging(app)
# 註冊 API 路由
from app.api import api_v1
app.register_blueprint(api_v1)
# 註冊錯誤處理器
register_error_handlers(app)
# 添加 CORS 響應headers
@app.after_request
def after_request(response):
origin = request.headers.get('Origin')
allowed_origins = ['http://localhost:3000', 'http://127.0.0.1:3000']
if origin and origin in allowed_origins:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, X-Requested-With'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, PATCH'
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Max-Age'] = '86400'
return response
# 處理 OPTIONS 預檢請求
@app.before_request
def before_request():
if request.method == 'OPTIONS':
response = make_response()
origin = request.headers.get('Origin')
allowed_origins = ['http://localhost:3000', 'http://127.0.0.1:3000']
if origin and origin in allowed_origins:
response.headers['Access-Control-Allow-Origin'] = origin
response.headers['Access-Control-Allow-Headers'] = 'Content-Type, Authorization, X-Requested-With'
response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE, OPTIONS, PATCH'
response.headers['Access-Control-Allow-Credentials'] = 'true'
response.headers['Access-Control-Max-Age'] = '86400'
return response
# 建立資料表
with app.app_context():
# 導入模型
from app.models import User, TranslationJob, JobFile, TranslationCache, APIUsageStats, SystemLog
db.create_all()
# 創建默認管理員用戶(如果不存在)
create_default_admin()
# 創建 Celery 實例
app.celery = make_celery(app)
app.logger.info("Flask application created successfully")
return app
def register_error_handlers(app):
"""註冊錯誤處理器"""
@app.errorhandler(404)
def not_found(error):
return {
'success': False,
'error': 'NOT_FOUND',
'message': '請求的資源不存在'
}, 404
@app.errorhandler(403)
def forbidden(error):
return {
'success': False,
'error': 'FORBIDDEN',
'message': '權限不足'
}, 403
@app.errorhandler(401)
def unauthorized(error):
return {
'success': False,
'error': 'UNAUTHORIZED',
'message': '需要認證'
}, 401
@app.errorhandler(500)
def internal_server_error(error):
return {
'success': False,
'error': 'INTERNAL_SERVER_ERROR',
'message': '系統內部錯誤'
}, 500
@app.errorhandler(413)
def request_entity_too_large(error):
return {
'success': False,
'error': 'FILE_TOO_LARGE',
'message': '檔案大小超過限制'
}, 413
def create_default_admin():
"""創建默認管理員用戶"""
try:
from app.models import User
admin_email = os.environ.get('ADMIN_EMAIL', 'ymirliu@panjit.com.tw')
# 檢查是否已存在管理員
admin_user = User.query.filter_by(email=admin_email).first()
if not admin_user:
# 創建管理員用戶(待 LDAP 登入時完善資訊)
admin_user = User(
username=admin_email.split('@')[0],
display_name='系統管理員',
email=admin_email,
department='IT',
is_admin=True
)
db.session.add(admin_user)
db.session.commit()
print(f"Created default admin user: {admin_email}")
except Exception as e:
print(f"Failed to create default admin: {str(e)}")
# 導入模型在需要時才進行,避免循環導入