1st_fix_login_issue
This commit is contained in:
212
app/__init__.py
Normal file
212
app/__init__.py
Normal 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)}")
|
||||
|
||||
|
||||
# 導入模型在需要時才進行,避免循環導入
|
Reference in New Issue
Block a user