mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-23 05:10:57 +00:00
refactor: 移除多租户相关代码,重构为单租户架构
此次提交进行了大规模的架构重构: 1. 移除所有平台租户相关模块和代码,包括租户管理、套餐、订单、发票等功能 2. 将菜单模块从platform迁移到system模块,统一系统功能入口 3. 移除租户隔离相关的模型混入、中间件和配置 4. 简化文件上传、SSE事件总线、定时任务等模块的租户逻辑 5. 重构所有业务schema和模型,移除租户相关字段和关联 6. 清理初始化脚本、模板和常量中的租户相关代码 7. 简化认证和权限控制逻辑,移除数据范围检查相关代码
This commit is contained in:
@@ -4,8 +4,6 @@ from typing import Annotated
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Body, Depends, Path, Query, Request, status
|
||||
from fastapi.responses import JSONResponse, RedirectResponse
|
||||
from fastapi_cache import FastAPICache
|
||||
from fastapi_cache.decorator import cache
|
||||
from redis.asyncio.client import Redis
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
@@ -31,78 +29,26 @@ from .oauth_service import (
|
||||
)
|
||||
from .schema import (
|
||||
CaptchaOutSchema,
|
||||
EnterPlatformOutSchema,
|
||||
ImpersonateOutSchema,
|
||||
ImpersonateSchema,
|
||||
LoginWithTenantsSchema,
|
||||
SelectTenantOutSchema,
|
||||
SelectTenantSchema,
|
||||
LoginOutSchema,
|
||||
SliderCompleteOutSchema,
|
||||
SliderCompleteSchema,
|
||||
TenantLookupOutSchema,
|
||||
TenantOptionSchema,
|
||||
TenantRegisterOutSchema,
|
||||
TenantRegisterSchema,
|
||||
)
|
||||
from .service import (
|
||||
CaptchaService,
|
||||
LoginService,
|
||||
TenantLookupService,
|
||||
TenantRegisterService,
|
||||
)
|
||||
|
||||
AuthRouter = APIRouter(route_class=OperationLogRoute, prefix="/auth", tags=["认证授权"])
|
||||
|
||||
_AUTH_TENANTS_NS = "auth_tenants"
|
||||
|
||||
|
||||
@AuthRouter.get("/tenant/{code}", summary="通过编码查询租户", response_model=ResponseSchema[TenantLookupOutSchema])
|
||||
async def lookup_tenant_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
code: Annotated[str, Path(description="租户编码")],
|
||||
) -> JSONResponse:
|
||||
"""根据租户编码查询租户信息(用于登录页自动加载租户品牌配置)"""
|
||||
data = await TenantLookupService.lookup_by_code(db=db, code=code)
|
||||
return SuccessResponse(data=data, msg="查询成功")
|
||||
|
||||
|
||||
@AuthRouter.get("/tenant-by-domain", summary="通过域名查询租户", response_model=ResponseSchema[TenantLookupOutSchema])
|
||||
async def lookup_tenant_by_domain_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
domain: Annotated[str, Query(description="域名(如 tenant.example.com)")],
|
||||
) -> JSONResponse:
|
||||
"""根据域名查询租户信息(用于登录页通过访问域名自动识别租户品牌)"""
|
||||
data = await TenantLookupService.lookup_by_domain(db=db, domain=domain)
|
||||
return SuccessResponse(data=data, msg="查询成功")
|
||||
|
||||
|
||||
@AuthRouter.get("/tenant-options", summary="获取所有租户选项(登录页下拉选择)", response_model=ResponseSchema[list[TenantOptionSchema]])
|
||||
async def get_tenant_options_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
) -> JSONResponse:
|
||||
"""获取所有活跃租户下拉选项"""
|
||||
data = await TenantLookupService.list_options(db=db)
|
||||
return SuccessResponse(data=data, msg="查询成功")
|
||||
|
||||
|
||||
@AuthRouter.get("/tenant-search", summary="搜索租户(按编码/名称模糊匹配)", response_model=ResponseSchema[list[TenantOptionSchema]])
|
||||
async def search_tenant_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
q: Annotated[str, Query(description="搜索关键字")],
|
||||
) -> JSONResponse:
|
||||
"""模糊搜索租户"""
|
||||
data = await TenantLookupService.search(db=db, q=q)
|
||||
return SuccessResponse(data=data, msg="查询成功")
|
||||
|
||||
|
||||
@AuthRouter.post("/login", summary="登录", response_model=LoginWithTenantsSchema)
|
||||
@AuthRouter.post("/login", summary="登录", response_model=LoginOutSchema)
|
||||
async def login_for_access_token_controller(
|
||||
request: Request,
|
||||
background_tasks: BackgroundTasks,
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
login_form: Annotated[CustomOAuth2PasswordRequestForm, Depends()],
|
||||
) -> JSONResponse | LoginWithTenantsSchema:
|
||||
) -> JSONResponse | LoginOutSchema:
|
||||
login_result = await LoginService.authenticate_user(request=request, redis=redis, login_form=login_form, db=db, background_tasks=background_tasks)
|
||||
|
||||
logger.info(f"用户{login_form.username}登录成功")
|
||||
@@ -150,55 +96,6 @@ async def logout_controller(
|
||||
return ErrorResponse(msg="退出失败")
|
||||
|
||||
|
||||
@AuthRouter.post("/select-tenant", summary="选择租户", response_model=ResponseSchema[SelectTenantOutSchema], dependencies=[Depends(get_current_user)])
|
||||
async def select_tenant_controller(
|
||||
request: Request,
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
data: Annotated[SelectTenantSchema, Body(description="租户选择参数")],
|
||||
) -> JSONResponse:
|
||||
result = await LoginService(auth, db).select_tenant(request=request, redis=redis, tenant_id=data.tenant_id)
|
||||
await FastAPICache.clear(namespace=_AUTH_TENANTS_NS)
|
||||
return SuccessResponse(data=result, msg="租户切换成功")
|
||||
|
||||
|
||||
@AuthRouter.post("/enter-platform", summary="进入平台管理模式", response_model=ResponseSchema[EnterPlatformOutSchema], dependencies=[Depends(get_current_user)])
|
||||
async def enter_platform_controller(
|
||||
request: Request,
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
) -> JSONResponse:
|
||||
result = await LoginService(auth, db).enter_platform(request=request, redis=redis)
|
||||
await FastAPICache.clear(namespace=_AUTH_TENANTS_NS)
|
||||
return SuccessResponse(data=result, msg="已返回平台管理模式")
|
||||
|
||||
|
||||
@AuthRouter.get("/tenants", summary="获取可选租户列表", response_model=ResponseSchema[list[TenantOptionSchema]], dependencies=[Depends(get_current_user)])
|
||||
@cache(expire=120, namespace=_AUTH_TENANTS_NS)
|
||||
async def get_user_tenants_controller(
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
) -> JSONResponse:
|
||||
service = LoginService(auth, db)
|
||||
tenants = await service.get_user_tenants()
|
||||
return SuccessResponse(data=tenants, msg="获取租户列表成功")
|
||||
|
||||
|
||||
@AuthRouter.post("/impersonate", summary="平台管理员代签入", response_model=ResponseSchema[ImpersonateOutSchema], dependencies=[Depends(get_current_user)])
|
||||
async def impersonate_controller(
|
||||
request: Request,
|
||||
auth: Annotated[AuthSchema, Depends(get_current_user)],
|
||||
redis: Annotated[Redis, Depends(redis_getter)],
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
data: Annotated[ImpersonateSchema, Body(description="代签入参数")],
|
||||
) -> JSONResponse:
|
||||
result = await LoginService(auth, db).impersonate(request=request, redis=redis, tenant_id=data.tenant_id)
|
||||
await FastAPICache.clear(namespace=_AUTH_TENANTS_NS)
|
||||
return SuccessResponse(data=result, msg="代签入成功")
|
||||
|
||||
|
||||
@AuthRouter.get("/oauth/{provider}/login", summary="第三方OAuth跳转")
|
||||
async def oauth_login_redirect_controller(
|
||||
request: Request,
|
||||
@@ -281,19 +178,3 @@ async def oauth_callback_controller(
|
||||
except CustomException as e:
|
||||
fe = await resolve_frontend()
|
||||
return RedirectContentResponse(url=oauth_service_error_redirect(fe, e.msg), status_code=302)
|
||||
|
||||
|
||||
@AuthRouter.post("/tenant/register", status_code=status.HTTP_201_CREATED, summary="租户自助注册", response_model=ResponseSchema[TenantRegisterOutSchema])
|
||||
async def tenant_register_controller(
|
||||
db: Annotated[AsyncSession, Depends(db_getter)],
|
||||
data: Annotated[TenantRegisterSchema, Body(description="租户注册参数")],
|
||||
) -> JSONResponse:
|
||||
result = await TenantRegisterService.register(
|
||||
db=db,
|
||||
username=data.username,
|
||||
password=data.password,
|
||||
email=data.email,
|
||||
tenant_name=data.tenant_name,
|
||||
)
|
||||
logger.info(f"新租户注册: username={data.username} tenant={result.tenant_name}")
|
||||
return SuccessResponse(data=result, msg=result.message)
|
||||
|
||||
Reference in New Issue
Block a user