diff --git a/backend/app/admin/schema/user.py b/backend/app/admin/schema/user.py index 13720972..23638edf 100644 --- a/backend/app/admin/schema/user.py +++ b/backend/app/admin/schema/user.py @@ -22,6 +22,7 @@ class AuthLoginParam(AuthSchemaBase): uuid: str | None = Field(None, description='验证码 UUID') captcha: str | None = Field(None, description='验证码') + tenant_id: int | None = Field(None, description='租户 ID') class AddUserParam(AuthSchemaBase): diff --git a/backend/app/admin/service/auth_service.py b/backend/app/admin/service/auth_service.py index 859b22d1..1b9b6996 100644 --- a/backend/app/admin/service/auth_service.py +++ b/backend/app/admin/service/auth_service.py @@ -18,6 +18,7 @@ from backend.common.i18n import t from backend.common.log import log from backend.common.response.response_code import CustomErrorCode from backend.common.security.jwt import ( + check_tenant_status, create_access_token, create_new_token, create_refresh_token, @@ -110,6 +111,7 @@ class AuthService: raise errors.CustomError(error=CustomErrorCode.CAPTCHA_ERROR) await redis_client.delete(f'{settings.LOGIN_CAPTCHA_REDIS_PREFIX}:{obj.uuid}') + await check_tenant_status(db, obj.tenant_id) user, days_remaining = await self.user_verify(db, obj.username, obj.password) await user_dao.update_login_time(db, obj.username) await db.refresh(user) diff --git a/backend/common/security/jwt.py b/backend/common/security/jwt.py index bc364afb..f71089ae 100644 --- a/backend/common/security/jwt.py +++ b/backend/common/security/jwt.py @@ -190,6 +190,38 @@ def get_token(request: Request) -> str: return token +async def check_tenant_status(db: AsyncSession, tenant_id: int) -> None: + """ + 校验租户状态 + + :param db: 数据库会话 + :param tenant_id: 租户 ID + :return: + """ + if not settings.TENANT_ENABLED or tenant_id is None or tenant_id == settings.TENANT_DEFAULT_ID: + return + + try: + from backend.plugin.tenant.crud.crud_package import tenant_package_dao + from backend.plugin.tenant.crud.crud_tenant import tenant_dao + except ImportError: + raise errors.ServerError(msg='租户插件用法导入失败,请联系系统管理员') + + tenant = await tenant_dao.get(db, tenant_id) + if not tenant: + raise errors.NotFoundError(msg='租户不存在,请联系系统管理员') + + if tenant.status == 0: + raise errors.AuthorizationError(msg='租户已被禁用,请联系系统管理员') + + if tenant.expire_time and tenant.expire_time < timezone.now(): + raise errors.AuthorizationError(msg='租户已过期,请联系系统管理员') + + package = await tenant_package_dao.get(db, tenant.package_id) + if package and package.status == 0: + raise errors.AuthorizationError(msg='租户套餐已被禁用,请联系系统管理员') + + async def get_current_user(db: AsyncSession, pk: int) -> User: """ 获取当前用户 @@ -214,6 +246,10 @@ async def get_current_user(db: AsyncSession, pk: int) -> User: role_status = [role.status for role in user.roles] if all(status == 0 for status in role_status): raise errors.AuthorizationError(msg='用户所属角色已被锁定,请联系系统管理员') + + if hasattr(user, 'tenant_id'): + await check_tenant_status(db, user.tenant_id) + return user diff --git a/backend/core/registrar.py b/backend/core/registrar.py index e55afede..0904a69f 100644 --- a/backend/core/registrar.py +++ b/backend/core/registrar.py @@ -147,15 +147,6 @@ def register_middleware(app: FastAPI) -> None: # State app.add_middleware(StateMiddleware) - # Tenant - if settings.TENANT_ENABLED: - try: - from backend.plugin.tenant.middleware.tenant_middleware import TenantMiddleware - except ImportError: - raise ImportError('租户插件中间件导入失败,请联系系统管理员') - else: - app.add_middleware(TenantMiddleware) - # JWT auth app.add_middleware( AuthenticationMiddleware,