import shutil from aerich import Command from fastapi import FastAPI from fastapi.middleware import Middleware from fastapi.middleware.cors import CORSMiddleware from tortoise.expressions import Q from app.api import api_router from app.controllers.api import api_controller from app.controllers.user import UserCreate, user_controller from app.core.exceptions import register_exception_handlers from app.log import logger from app.models.admin import Api, Menu, Role, Dept from app.models.automation import Task, Scenario from app.schemas.menus import MenuType from app.settings.config import settings from app.core.cache import redis_client from .middlewares import BackGroundTaskMiddleware, HttpAuditLogMiddleware def make_middlewares(): middleware = [ Middleware( CORSMiddleware, allow_origins=settings.CORS_ORIGINS, allow_credentials=settings.CORS_ALLOW_CREDENTIALS, allow_methods=settings.CORS_ALLOW_METHODS, allow_headers=settings.CORS_ALLOW_HEADERS, ), Middleware(BackGroundTaskMiddleware), Middleware( HttpAuditLogMiddleware, methods=["GET", "POST", "PUT", "DELETE"], exclude_paths=[ "/api/v1/msg/new_order", "/api/v1/weixin/jssdk-config", "/api/v1/base/access_token", "/docs", "/api-docs", "/openapi.json", "/static/*", "/gen/*", ], ), ] return middleware def mount_static_and_config_swagger(app: FastAPI): from fastapi.staticfiles import StaticFiles from fastapi.openapi.docs import get_swagger_ui_html app.mount("/static", StaticFiles(directory="static"), name="静态文件") @app.get(app.docs_url, include_in_schema=False) async def custom_swagger_ui_html(): print('访问文档') return get_swagger_ui_html( openapi_url=app.openapi_url, title=app.title, swagger_js_url="/static/swagger-ui/swagger-ui-bundle.js", swagger_css_url="/static/swagger-ui/swagger-ui.css" ) def register_exceptions(app: FastAPI): register_exception_handlers(app) print('注册异常处理完成') def register_routers(app: FastAPI, prefix: str = "/api"): app.include_router(api_router, prefix=prefix) async def init_superuser(): user = await user_controller.model.exists() if not user: await user_controller.create_user( UserCreate( username="admin", email="admin@admin.com", password="123456", is_active=True, is_superuser=True, ) ) async def init_menus(): menus = await Menu.exists() if not menus: parent_menu = await Menu.create( menu_type=MenuType.CATALOG, name="系统管理", path="/system", order=1, parent_id=0, icon="carbon:gui-management", is_hidden=False, component="Layout", keepalive=False, redirect="/system/user", ) children_menu = [ Menu( menu_type=MenuType.MENU, name="用户管理", path="user", order=1, parent_id=parent_menu.id, icon="material-symbols:person-outline-rounded", is_hidden=False, component="/system/user", keepalive=False, ), Menu( menu_type=MenuType.MENU, name="角色管理", path="role", order=2, parent_id=parent_menu.id, icon="carbon:user-role", is_hidden=False, component="/system/role", keepalive=False, ), Menu( menu_type=MenuType.MENU, name="菜单管理", path="menu", order=3, parent_id=parent_menu.id, icon="material-symbols:list-alt-outline", is_hidden=False, component="/system/menu", keepalive=False, ), Menu( menu_type=MenuType.MENU, name="API管理", path="api", order=4, parent_id=parent_menu.id, icon="ant-design:api-outlined", is_hidden=False, component="/system/api", keepalive=False, ), Menu( menu_type=MenuType.MENU, name="部门管理", path="dept", order=5, parent_id=parent_menu.id, icon="mingcute:department-line", is_hidden=False, component="/system/dept", keepalive=False, ), Menu( menu_type=MenuType.MENU, name="审计日志", path="auditlog", order=6, parent_id=parent_menu.id, icon="ph:clipboard-text-bold", is_hidden=False, component="/system/auditlog", keepalive=False, ), ] await Menu.bulk_create(children_menu) await Menu.create( menu_type=MenuType.MENU, name="一级菜单", path="/top-menu", order=2, parent_id=0, icon="material-symbols:featured-play-list-outline", is_hidden=False, component="/top-menu", keepalive=False, redirect="", ) async def init_apis(): apis = await api_controller.model.exists() if not apis: await api_controller.refresh_api() async def init_db(): command = Command(tortoise_config=settings.TORTOISE_ORM) try: await command.init_db(safe=True) except FileExistsError: pass await command.init() try: await command.migrate() except AttributeError: logger.warning("unable to retrieve model history from database, model history will be created from scratch") shutil.rmtree("migrations") await command.init_db(safe=True) await command.upgrade(run_in_transaction=True) async def init_roles(): roles = await Role.exists() if not roles: admin_role = await Role.create( name="管理员", desc="管理员角色", ) user_role = await Role.create( name="普通用户", desc="普通用户角色", ) await Dept.create(name="默认部门") # 分配所有API给管理员角色 all_apis = await Api.all() await admin_role.apis.add(*all_apis) # 分配所有菜单给管理员和普通用户 all_menus = await Menu.all() await admin_role.menus.add(*all_menus) await user_role.menus.add(*all_menus) # 为普通用户分配基本API basic_apis = await Api.filter(Q(method__in=["GET"]) | Q(tags="基础模块")) await user_role.apis.add(*basic_apis) async def init_cache(): await redis_client.init_redis(settings.REDIS_URL) async def init_task(): task = await Task.exists(title="系统待办") if task: return scenario = await Scenario.create( title="系统待办", visible=False, trigger={}, actions=[], enabled=False, notes="用于为所有存量数据创建的待办任务", ) task = await Task.create( title="系统待办", status='success', ui_schema={}, source_scenario=scenario, notes="当系统有新的待办任务时关联动作", ) async def init_data(): await init_db() await init_task() await init_cache() await init_superuser() await init_menus() await init_apis() await init_roles() async def tear_down(): await redis_client.close()