diff --git a/backend/auth/__pycache__/config.cpython-313.pyc b/backend/auth/__pycache__/config.cpython-313.pyc index ae47fc4..35d0e4e 100644 Binary files a/backend/auth/__pycache__/config.cpython-313.pyc and b/backend/auth/__pycache__/config.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/database.cpython-313.pyc b/backend/auth/__pycache__/database.cpython-313.pyc index 3b87193..2287ee9 100644 Binary files a/backend/auth/__pycache__/database.cpython-313.pyc and b/backend/auth/__pycache__/database.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/init_data.cpython-313.pyc b/backend/auth/__pycache__/init_data.cpython-313.pyc index 0aa8522..7d0677c 100644 Binary files a/backend/auth/__pycache__/init_data.cpython-313.pyc and b/backend/auth/__pycache__/init_data.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/main.cpython-313.pyc b/backend/auth/__pycache__/main.cpython-313.pyc index 963da4e..ec7e23b 100644 Binary files a/backend/auth/__pycache__/main.cpython-313.pyc and b/backend/auth/__pycache__/main.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/middleware.cpython-313.pyc b/backend/auth/__pycache__/middleware.cpython-313.pyc index 28de8f7..b90a696 100644 Binary files a/backend/auth/__pycache__/middleware.cpython-313.pyc and b/backend/auth/__pycache__/middleware.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/models.cpython-313.pyc b/backend/auth/__pycache__/models.cpython-313.pyc index add5f0f..1b67dee 100644 Binary files a/backend/auth/__pycache__/models.cpython-313.pyc and b/backend/auth/__pycache__/models.cpython-313.pyc differ diff --git a/backend/auth/__pycache__/schemas.cpython-313.pyc b/backend/auth/__pycache__/schemas.cpython-313.pyc index 26e947c..f97bbcc 100644 Binary files a/backend/auth/__pycache__/schemas.cpython-313.pyc and b/backend/auth/__pycache__/schemas.cpython-313.pyc differ diff --git a/backend/auth/apps/__pycache__/__init__.cpython-313.pyc b/backend/auth/apps/__pycache__/__init__.cpython-313.pyc index 7cc2196..c795f91 100644 Binary files a/backend/auth/apps/__pycache__/__init__.cpython-313.pyc and b/backend/auth/apps/__pycache__/__init__.cpython-313.pyc differ diff --git a/backend/auth/apps/__pycache__/urls.cpython-313.pyc b/backend/auth/apps/__pycache__/urls.cpython-313.pyc index b51d6bc..657e403 100644 Binary files a/backend/auth/apps/__pycache__/urls.cpython-313.pyc and b/backend/auth/apps/__pycache__/urls.cpython-313.pyc differ diff --git a/backend/auth/apps/roles/__pycache__/__init__.cpython-313.pyc b/backend/auth/apps/roles/__pycache__/__init__.cpython-313.pyc index d4458d5..a75f804 100644 Binary files a/backend/auth/apps/roles/__pycache__/__init__.cpython-313.pyc and b/backend/auth/apps/roles/__pycache__/__init__.cpython-313.pyc differ diff --git a/backend/auth/apps/roles/__pycache__/urls.cpython-313.pyc b/backend/auth/apps/roles/__pycache__/urls.cpython-313.pyc index 6ef269a..7c34d77 100644 Binary files a/backend/auth/apps/roles/__pycache__/urls.cpython-313.pyc and b/backend/auth/apps/roles/__pycache__/urls.cpython-313.pyc differ diff --git a/backend/auth/apps/roles/urls.py b/backend/auth/apps/roles/urls.py index 61be315..6442ea7 100644 --- a/backend/auth/apps/roles/urls.py +++ b/backend/auth/apps/roles/urls.py @@ -14,52 +14,97 @@ role_crud = FastCRUD(Role, RoleResponse) @router.post("/", response_model=RoleResponse) -async def create_role(role_data: RoleCreate, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def create_role( + role_data: RoleCreate, + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): """创建角色""" - # 创建角色实例 - db_role = Role( - name=role_data.name, - creator=role_data.creator - ) - + # 检查角色名是否已存在 + from sqlalchemy import select + + result = await db.execute(select(Role).filter(Role.name == role_data.name)) + existing_role = result.scalar_one_or_none() + if existing_role: + raise HTTPException(status_code=400, detail="角色名已存在") + + # 准备创建数据 + create_data = role_data.model_dump() + # 使用FastCRUD创建角色 - created_role = await role_crud.create(db, db_role) + created_role = await role_crud.create(db, create_data) return created_role @router.get("/", response_model=list[RoleResponse]) -async def get_roles(db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def get_roles( + db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user) +): """获取所有角色""" - roles = await role_crud.get_multi(db) - return roles + result = await role_crud.get_multi(db) + return result["data"] @router.get("/{role_id}", response_model=RoleResponse) -async def get_role(role_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def get_role( + role_id: int, + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): """获取单个角色""" - role = await role_crud.get(db, role_id) + role = await role_crud.get(db, {"id": role_id}) if not role: raise HTTPException(status_code=404, detail="角色不存在") return role @router.put("/{role_id}", response_model=RoleResponse) -async def update_role(role_id: int, role_data: RoleCreate, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def update_role( + role_id: int, + role_data: RoleCreate, + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): """更新角色""" + # 检查角色名是否被其他角色使用 + from sqlalchemy import select + + result = await db.execute( + select(Role).filter(Role.name == role_data.name, Role.id != role_id) + ) + existing_role = result.scalar_one_or_none() + if existing_role: + raise HTTPException(status_code=400, detail="角色名已存在") + # 准备更新数据 - update_data = role_data.dict() - + update_data = role_data.model_dump() + # 使用FastCRUD更新角色 - updated_role = await role_crud.update(db, role_id, update_data) + updated_role = await role_crud.update(db, {"id": role_id}, update_data) if not updated_role: raise HTTPException(status_code=404, detail="角色不存在") return updated_role @router.delete("/{role_id}") -async def delete_role(role_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def delete_role( + role_id: int, + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): """删除角色""" - deleted = await role_crud.delete(db, role_id) + # 检查是否有用户使用此角色 + from sqlalchemy import select + + result = await db.execute(select(User).filter(User.role_id == role_id)) + users = result.scalars().all() + if users: + raise HTTPException( + status_code=400, detail=f"该角色正在被 {len(users)} 个用户使用,无法删除" + ) + + # 使用FastCRUD删除角色 + deleted = await role_crud.delete(db, {"id": role_id}) if not deleted: raise HTTPException(status_code=404, detail="角色不存在") - return {"message": "角色删除成功"} \ No newline at end of file + return {"message": "角色删除成功"} diff --git a/backend/auth/apps/users/__pycache__/__init__.cpython-313.pyc b/backend/auth/apps/users/__pycache__/__init__.cpython-313.pyc index 5a8fb8f..5614060 100644 Binary files a/backend/auth/apps/users/__pycache__/__init__.cpython-313.pyc and b/backend/auth/apps/users/__pycache__/__init__.cpython-313.pyc differ diff --git a/backend/auth/apps/users/__pycache__/urls.cpython-313.pyc b/backend/auth/apps/users/__pycache__/urls.cpython-313.pyc index a2d0fc9..7cd7496 100644 Binary files a/backend/auth/apps/users/__pycache__/urls.cpython-313.pyc and b/backend/auth/apps/users/__pycache__/urls.cpython-313.pyc differ diff --git a/backend/auth/apps/users/urls.py b/backend/auth/apps/users/urls.py index c004a01..8feaa15 100644 --- a/backend/auth/apps/users/urls.py +++ b/backend/auth/apps/users/urls.py @@ -1,12 +1,20 @@ from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy import select from fastcrud import FastCRUD -from datetime import timedelta +from datetime import timedelta, datetime import redis.asyncio as redis from database import get_db from models import User -from schemas import UserCreate, UserResponse, UserLogin, Token +from schemas import ( + UserCreate, + UserResponse, + UserLogin, + Token, + UserCreateRequest, + UserUpdate, +) from utils.password import verify_password, get_password_hash from utils.jwt import create_access_token from config import app_settings @@ -20,11 +28,16 @@ user_crud = FastCRUD(User, UserResponse) @router.post("/login", response_model=Token) -async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db), redis_conn: redis.Redis = Depends(get_redis)): +async def login( + user_data: UserLogin, + db: AsyncSession = Depends(get_db), + redis_conn: redis.Redis = Depends(get_redis), +): """用户登录""" # 查找用户 - user = await db.query(User).filter(User.username == user_data.username).first() - + result = await db.execute(select(User).filter(User.username == user_data.username)) + user = result.scalar_one_or_none() + # 验证用户是否存在且密码正确 if not user or not verify_password(user_data.password, user.password_hash): raise HTTPException( @@ -32,91 +45,139 @@ async def login(user_data: UserLogin, db: AsyncSession = Depends(get_db), redis_ detail="用户名或密码错误", headers={"WWW-Authenticate": "Bearer"}, ) - + # 创建访问令牌 access_token_expires = timedelta(minutes=app_settings.access_token_expire_minutes) access_token = create_access_token( data={"sub": str(user.id), "username": user.username}, - expires_delta=access_token_expires + expires_delta=access_token_expires, ) - + # 将令牌存储到Redis expire_seconds = int(access_token_expires.total_seconds()) await set_token_in_redis(redis_conn, user.id, access_token, expire_seconds) - + + # 更新用户最后登录时间 + user.lastlogintime = datetime.utcnow() + await db.commit() + return {"access_token": access_token, "token_type": "bearer"} @router.post("/", response_model=UserResponse) -async def create_user(user_data: UserCreate, db: AsyncSession = Depends(get_db)): +async def create_user(user_data: UserCreateRequest, db: AsyncSession = Depends(get_db)): """创建用户""" + # 检查用户名是否已存在 + result = await db.execute(select(User).filter(User.username == user_data.username)) + existing_user = result.scalar_one_or_none() + if existing_user: + raise HTTPException(status_code=400, detail="用户名已存在") + # 生成密码哈希值 hashed_password = get_password_hash(user_data.password) - - # 创建用户实例,使用密码哈希值 - db_user = User( - username=user_data.username, - nickname=user_data.nickname, - email=user_data.email, - phone=user_data.phone, - wx_openid=user_data.wx_openid, - avatar=user_data.avatar, - password_hash=hashed_password, - role_id=user_data.role_id - ) - + + # 准备创建数据 + create_data = user_data.model_dump() + create_data["password_hash"] = hashed_password + del create_data["password"] # 删除明文密码 + # 转换为UserCreate模型 + user_data_create = UserCreate(**create_data) + # 使用FastCRUD创建用户 - created_user = await user_crud.create(db, db_user) + created_user = await user_crud.create( + db, user_data_create, schema_to_select=UserResponse, return_as_model=True + ) return created_user @router.get("/", response_model=list[UserResponse]) -async def get_users(db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def get_users( + db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user) +): """获取所有用户""" - users = await user_crud.get_multi(db) - return users + result = await user_crud.get_multi(db) + return result["data"] @router.get("/{user_id}", response_model=UserResponse) -async def get_user(user_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def get_user( + user_id: int, + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): """获取单个用户""" - user = await user_crud.get(db, user_id) + user = await user_crud.get(db, id=user_id) if not user: raise HTTPException(status_code=404, detail="用户不存在") return user @router.put("/{user_id}", response_model=UserResponse) -async def update_user(user_id: int, user_data: UserCreate, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def update_user( + user_id: int, + user_data: UserUpdate, + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): """更新用户""" + # 检查用户名是否被其他用户使用 + result = await db.execute( + select(User).filter(User.username == user_data.username, User.id != user_id) + ) + existing_user = result.scalar_one_or_none() + if existing_user: + raise HTTPException(status_code=400, detail="用户名已存在") + # 生成密码哈希值 - hashed_password = get_password_hash(user_data.password) - + hashed_password = ( + get_password_hash(user_data.password) if user_data.password else None + ) + # 准备更新数据 - update_data = user_data.dict() - update_data["password_hash"] = hashed_password + update_data = user_data.model_dump() + if hashed_password: + update_data["password_hash"] = hashed_password del update_data["password"] # 删除明文密码 - + # 使用FastCRUD更新用户 - updated_user = await user_crud.update(db, user_id, update_data) + updated_user = await user_crud.update( + db, update_data, id=user_id, schema_to_select=UserResponse, return_as_model=True + ) if not updated_user: raise HTTPException(status_code=404, detail="用户不存在") return updated_user @router.delete("/{user_id}") -async def delete_user(user_id: int, db: AsyncSession = Depends(get_db), current_user: User = Depends(get_current_user)): +async def delete_user( + user_id: int, + db: AsyncSession = Depends(get_db), + current_user: User = Depends(get_current_user), +): """删除用户""" - deleted = await user_crud.delete(db, user_id) - if not deleted: + # 检查用户是否存在 + result = await db.execute(select(User).filter(User.id == user_id)) + existing_user = result.scalar_one_or_none() + if not existing_user: raise HTTPException(status_code=404, detail="用户不存在") - return {"message": "用户删除成功"} + elif existing_user.id == current_user.id: + raise HTTPException(status_code=400, detail="不能删除当前登录用户") + elif existing_user.role_id == 1: + raise HTTPException(status_code=400, detail="不能删除管理员用户") + else: + # 使用FastCRUD删除用户 + deleted = await user_crud.delete(db, id=user_id) + return {"message": "用户删除成功"} @router.post("/logout") -async def logout(current_user: User = Depends(get_current_user), redis_conn: redis.Redis = Depends(get_redis)): +async def logout( + current_user: User = Depends(get_current_user), + redis_conn: redis.Redis = Depends(get_redis), +): """用户登出""" from utils.redis_client import delete_token_from_redis + await delete_token_from_redis(redis_conn, current_user.id) return {"message": "登出成功"} @@ -124,4 +185,5 @@ async def logout(current_user: User = Depends(get_current_user), redis_conn: red @router.get("/me", response_model=UserResponse) async def get_current_user_info(current_user: User = Depends(get_current_user)): """获取当前用户信息""" - return current_user \ No newline at end of file + print(current_user.id) + return user diff --git a/backend/auth/config.py b/backend/auth/config.py index f6a4a44..ad2cb2a 100644 --- a/backend/auth/config.py +++ b/backend/auth/config.py @@ -5,6 +5,7 @@ from urllib.parse import quote_plus class PostgreSQLSettings(BaseSettings): """PostgreSQL数据库配置""" + host: str = "127.0.0.1" port: int = 5432 user: str = "admin" @@ -12,44 +13,46 @@ class PostgreSQLSettings(BaseSettings): database: str = "booksystem" min_size: int = 5 max_size: int = 20 - + @property def url(self) -> str: """生成数据库连接URL""" encoded_password = quote_plus(self.password) return f"postgresql+asyncpg://{self.user}:{encoded_password}@{self.host}:{self.port}/{self.database}" - + class Config: env_prefix = "POSTGRES_" class RedisSettings(BaseSettings): """Redis配置""" + host: str = "127.0.0.1" port: int = 6379 password: Optional[str] = "RedisAdmin@123" db: int = 0 - + @property def url(self) -> str: """生成Redis连接URL""" if self.password: return f"redis://:{self.password}@{self.host}:{self.port}/{self.db}" return f"redis://{self.host}:{self.port}/{self.db}" - + class Config: env_prefix = "REDIS_" class AppSettings(BaseSettings): """应用配置""" + name: str = "Book System API" version: str = "1.0.0" debug: bool = False secret_key: str = "BookSystemAPIQRAdmin123" algorithm: str = "HS256" - access_token_expire_minutes: int = 30 - + access_token_expire_minutes: int = 10080 + class Config: env_prefix = "APP_" @@ -57,4 +60,4 @@ class AppSettings(BaseSettings): # 创建设置实例 postgres_settings = PostgreSQLSettings() redis_settings = RedisSettings() -app_settings = AppSettings() \ No newline at end of file +app_settings = AppSettings() diff --git a/backend/auth/init_data.py b/backend/auth/init_data.py index 1aed75b..2229e6a 100644 --- a/backend/auth/init_data.py +++ b/backend/auth/init_data.py @@ -6,36 +6,57 @@ from utils.password import get_password_hash async def init_roles(db: AsyncSession): """初始化角色数据""" - # 检查是否已经存在角色数据 - result = await db.execute(select(Role)) - existing_roles = result.scalars().all() - if existing_roles: - print("角色数据已存在,跳过初始化") - return - - # 创建初始角色 - roles = [ - Role(name="管理员", creator="system"), - Role(name="普通用户", creator="system"), - Role(name="访客", creator="system"), + # 定义需要初始化的角色 + required_roles = [ + {"name": "管理员", "creator": "system"}, + {"name": "普通用户", "creator": "system"}, + {"name": "访客", "creator": "system"}, + {"name": "会员", "creator": "system"}, ] - for role in roles: - db.add(role) + # 检查现有角色 + result = await db.execute(select(Role)) + existing_roles = result.scalars().all() + existing_role_names = {role.name for role in existing_roles} - await db.commit() - print("角色数据初始化完成") + # 检查需要创建或更新的角色 + roles_to_add = [] + roles_to_update = [] + + for role_data in required_roles: + role_name = role_data["name"] + if role_name not in existing_role_names: + # 角色不存在,需要创建 + roles_to_add.append(Role(**role_data)) + else: + # 角色存在,检查是否需要更新 + existing_role = next( + role for role in existing_roles if role.name == role_name + ) + if existing_role.creator != role_data["creator"]: + # 需要更新 + existing_role.creator = role_data["creator"] + roles_to_update.append(existing_role) + + # 执行创建和更新操作 + if roles_to_add: + for role in roles_to_add: + db.add(role) + await db.commit() + print(f"创建了 {len(roles_to_add)} 个角色") + + if roles_to_update: + await db.commit() + print(f"更新了 {len(roles_to_update)} 个角色") + + if not roles_to_add and not roles_to_update: + print("角色数据已存在且无需更新,跳过初始化") + + print("角色数据初始化/更新完成") async def init_admin_user(db: AsyncSession): """初始化管理员用户""" - # 检查是否已经存在管理员用户 - result = await db.execute(select(User).filter(User.username == "admin")) - existing_admin = result.scalar_one_or_none() - if existing_admin: - print("管理员用户已存在,跳过初始化") - return - # 获取管理员角色 result = await db.execute(select(Role).filter(Role.name == "管理员")) admin_role = result.scalar_one_or_none() @@ -43,32 +64,63 @@ async def init_admin_user(db: AsyncSession): print("管理员角色不存在,请先初始化角色数据") return - # 创建管理员用户 - admin_user = User( - username="admin", - nickname="系统管理员", - email="admin@example.com", - phone="13800138000", - password_hash=get_password_hash("admin"), - role_id=admin_role.id, - avatar="", - wx_openid="" - ) + # 定义需要的管理员用户数据 + admin_data = { + "username": "admin", + "nickname": "系统管理员", + "email": "admin@example.com", + "phone": "13800138000", + "password_hash": get_password_hash("admin"), + "role_id": admin_role.id, + "avatar": "", + "wx_openid": "", + } - db.add(admin_user) - await db.commit() - print("管理员用户初始化完成") + # 检查管理员用户是否存在 + result = await db.execute(select(User).filter(User.username == "admin")) + existing_admin = result.scalar_one_or_none() + + if not existing_admin: + # 管理员不存在,创建 + admin_user = User(**admin_data) + db.add(admin_user) + await db.commit() + print("创建了管理员用户") + else: + # 管理员存在,检查是否需要更新 + update_needed = False + + # 检查字段是否需要更新(不包括密码,因为密码只在首次创建时设置) + if existing_admin.nickname != admin_data["nickname"]: + existing_admin.nickname = admin_data["nickname"] + update_needed = True + if existing_admin.email != admin_data["email"]: + existing_admin.email = admin_data["email"] + update_needed = True + if existing_admin.phone != admin_data["phone"]: + existing_admin.phone = admin_data["phone"] + update_needed = True + if existing_admin.role_id != admin_data["role_id"]: + existing_admin.role_id = admin_data["role_id"] + update_needed = True + if existing_admin.avatar != admin_data["avatar"]: + existing_admin.avatar = admin_data["avatar"] + update_needed = True + if existing_admin.wx_openid != admin_data["wx_openid"]: + existing_admin.wx_openid = admin_data["wx_openid"] + update_needed = True + + if update_needed: + await db.commit() + print("更新了管理员用户") + else: + print("管理员用户已存在且无需更新,跳过初始化") + + print("管理员用户初始化/更新完成") async def init_test_user(db: AsyncSession): """初始化测试用户""" - # 检查是否已经存在测试用户 - result = await db.execute(select(User).filter(User.username == "test")) - existing_test_user = result.scalar_one_or_none() - if existing_test_user: - print("测试用户已存在,跳过初始化") - return - # 获取普通用户角色 result = await db.execute(select(Role).filter(Role.name == "普通用户")) user_role = result.scalar_one_or_none() @@ -76,21 +128,59 @@ async def init_test_user(db: AsyncSession): print("普通用户角色不存在,请先初始化角色数据") return - # 创建测试用户 - test_user = User( - username="test", - nickname="测试用户", - email="test@example.com", - phone="13800138001", - password_hash=get_password_hash("test"), - role_id=user_role.id, - avatar="", - wx_openid="" - ) + # 定义需要的测试用户数据 + test_data = { + "username": "test", + "nickname": "测试用户", + "email": "test@example.com", + "phone": "13800138001", + "password_hash": get_password_hash("test"), + "role_id": user_role.id, + "avatar": "", + "wx_openid": "", + } - db.add(test_user) - await db.commit() - print("测试用户初始化完成") + # 检查测试用户是否存在 + result = await db.execute(select(User).filter(User.username == "test")) + existing_test_user = result.scalar_one_or_none() + + if not existing_test_user: + # 测试用户不存在,创建 + test_user = User(**test_data) + db.add(test_user) + await db.commit() + print("创建了测试用户") + else: + # 测试用户存在,检查是否需要更新 + update_needed = False + + # 检查字段是否需要更新(不包括密码,因为密码只在首次创建时设置) + if existing_test_user.nickname != test_data["nickname"]: + existing_test_user.nickname = test_data["nickname"] + update_needed = True + if existing_test_user.email != test_data["email"]: + existing_test_user.email = test_data["email"] + update_needed = True + if existing_test_user.phone != test_data["phone"]: + existing_test_user.phone = test_data["phone"] + update_needed = True + if existing_test_user.role_id != test_data["role_id"]: + existing_test_user.role_id = test_data["role_id"] + update_needed = True + if existing_test_user.avatar != test_data["avatar"]: + existing_test_user.avatar = test_data["avatar"] + update_needed = True + if existing_test_user.wx_openid != test_data["wx_openid"]: + existing_test_user.wx_openid = test_data["wx_openid"] + update_needed = True + + if update_needed: + await db.commit() + print("更新了测试用户") + else: + print("测试用户已存在且无需更新,跳过初始化") + + print("测试用户初始化/更新完成") async def init_all_data(db: AsyncSession): diff --git a/backend/auth/main.py b/backend/auth/main.py index 0a528e1..38f0b25 100644 --- a/backend/auth/main.py +++ b/backend/auth/main.py @@ -1,9 +1,12 @@ from fastapi import FastAPI +from fastapi.staticfiles import StaticFiles +from fastapi.responses import HTMLResponse from contextlib import asynccontextmanager from apps.urls import api_router from database import engine, get_db from models import Base from init_data import init_all_data +from pathlib import Path @asynccontextmanager @@ -12,39 +15,102 @@ async def lifespan(app: FastAPI): async with engine.begin() as conn: # 创建所有表 await conn.run_sync(Base.metadata.create_all) - + # 初始化数据 async for db in get_db(): await init_all_data(db) break - + yield # 关闭时的清理工作 await engine.dispose() + # 实例化FastAPI app = FastAPI( - title="Book System API", - description="图书系统API", + title="图书系统授权服务API", + description="""图书系统授权服务API是一套用于用户认证和授权的服务,提供用户注册、登录、权限校验等功能。 + 同时实现了基于角色的访问控制(RBAC),支持自定义角色和权限。还增加了日志记录功能,方便监控和调试。""", version="1.0.0", - lifespan=lifespan + lifespan=lifespan, + docs_url=None, + redoc_url="/redoc", ) +# 挂载swagger-ui静态文件目录 +swagger_ui_path = Path(__file__).parent.parent / "swagger-ui" +app.mount("/static", StaticFiles(directory=str(swagger_ui_path)), name="static") + + +# 自定义Swagger UI页面 +@app.get("/docs", include_in_schema=False) +async def custom_swagger_ui_html(): + html_content = """ + + +
+ + +