mirror of
https://github.com/fastapi-practices/fastapi_best_architecture.git
synced 2026-03-13 09:31:31 +08:00
Optimize api with semantic HTTP status codes (#681)
This commit is contained in:
@@ -93,7 +93,7 @@ class AuthService:
|
||||
user = await self.user_verify(db, obj.username, obj.password)
|
||||
captcha_code = await redis_client.get(f'{settings.CAPTCHA_LOGIN_REDIS_PREFIX}:{request.state.ip}')
|
||||
if not captcha_code:
|
||||
raise errors.ForbiddenError(msg='验证码失效,请重新获取')
|
||||
raise errors.RequestError(msg='验证码失效,请重新获取')
|
||||
if captcha_code.lower() != obj.captcha.lower():
|
||||
raise errors.CustomError(error=CustomErrorCode.CAPTCHA_ERROR)
|
||||
await redis_client.delete(f'{settings.CAPTCHA_LOGIN_REDIS_PREFIX}:{request.state.ip}')
|
||||
@@ -122,7 +122,7 @@ class AuthService:
|
||||
except errors.NotFoundError as e:
|
||||
log.error('登陆错误: 用户名不存在')
|
||||
raise errors.NotFoundError(msg=e.msg)
|
||||
except (errors.ForbiddenError, errors.CustomError) as e:
|
||||
except (errors.RequestError, errors.CustomError) as e:
|
||||
if not user:
|
||||
log.error('登陆错误: 用户密码有误')
|
||||
task = BackgroundTask(
|
||||
|
||||
@@ -87,7 +87,7 @@ class DataRuleService:
|
||||
async with async_db_session.begin() as db:
|
||||
data_rule = await data_rule_dao.get_by_name(db, obj.name)
|
||||
if data_rule:
|
||||
raise errors.ForbiddenError(msg='数据规则已存在')
|
||||
raise errors.ConflictError(msg='数据规则已存在')
|
||||
await data_rule_dao.create(db, obj)
|
||||
|
||||
@staticmethod
|
||||
@@ -105,7 +105,7 @@ class DataRuleService:
|
||||
raise errors.NotFoundError(msg='数据规则不存在')
|
||||
if data_rule.name != obj.name:
|
||||
if await data_rule_dao.get_by_name(db, obj.name):
|
||||
raise errors.ForbiddenError(msg='数据规则已存在')
|
||||
raise errors.ConflictError(msg='数据规则已存在')
|
||||
count = await data_rule_dao.update(db, pk, obj)
|
||||
return count
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ class DataScopeService:
|
||||
async with async_db_session.begin() as db:
|
||||
data_scope = await data_scope_dao.get_by_name(db, obj.name)
|
||||
if data_scope:
|
||||
raise errors.ForbiddenError(msg='数据范围已存在')
|
||||
raise errors.ConflictError(msg='数据范围已存在')
|
||||
await data_scope_dao.create(db, obj)
|
||||
|
||||
@staticmethod
|
||||
@@ -96,7 +96,7 @@ class DataScopeService:
|
||||
raise errors.NotFoundError(msg='数据范围不存在')
|
||||
if data_scope.name != obj.name:
|
||||
if await data_scope_dao.get_by_name(db, obj.name):
|
||||
raise errors.ForbiddenError(msg='数据范围已存在')
|
||||
raise errors.ConflictError(msg='数据范围已存在')
|
||||
count = await data_scope_dao.update(db, pk, obj)
|
||||
for role in await data_scope.awaitable_attrs.roles:
|
||||
for user in await role.awaitable_attrs.users:
|
||||
|
||||
@@ -61,7 +61,7 @@ class DeptService:
|
||||
async with async_db_session.begin() as db:
|
||||
dept = await dept_dao.get_by_name(db, obj.name)
|
||||
if dept:
|
||||
raise errors.ForbiddenError(msg='部门名称已存在')
|
||||
raise errors.ConflictError(msg='部门名称已存在')
|
||||
if obj.parent_id:
|
||||
parent_dept = await dept_dao.get(db, obj.parent_id)
|
||||
if not parent_dept:
|
||||
@@ -83,7 +83,7 @@ class DeptService:
|
||||
raise errors.NotFoundError(msg='部门不存在')
|
||||
if dept.name != obj.name:
|
||||
if await dept_dao.get_by_name(db, obj.name):
|
||||
raise errors.ForbiddenError(msg='部门名称已存在')
|
||||
raise errors.ConflictError(msg='部门名称已存在')
|
||||
if obj.parent_id:
|
||||
parent_dept = await dept_dao.get(db, obj.parent_id)
|
||||
if not parent_dept:
|
||||
@@ -104,10 +104,10 @@ class DeptService:
|
||||
async with async_db_session.begin() as db:
|
||||
dept = await dept_dao.get_with_relation(db, pk)
|
||||
if dept.users:
|
||||
raise errors.ForbiddenError(msg='部门下存在用户,无法删除')
|
||||
raise errors.ConflictError(msg='部门下存在用户,无法删除')
|
||||
children = await dept_dao.get_children(db, pk)
|
||||
if children:
|
||||
raise errors.ForbiddenError(msg='部门下存在子部门,无法删除')
|
||||
raise errors.ConflictError(msg='部门下存在子部门,无法删除')
|
||||
count = await dept_dao.delete(db, pk)
|
||||
for user in dept.users:
|
||||
await redis_client.delete(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
|
||||
@@ -78,7 +78,7 @@ class MenuService:
|
||||
async with async_db_session.begin() as db:
|
||||
title = await menu_dao.get_by_title(db, obj.title)
|
||||
if title:
|
||||
raise errors.ForbiddenError(msg='菜单标题已存在')
|
||||
raise errors.ConflictError(msg='菜单标题已存在')
|
||||
if obj.parent_id:
|
||||
parent_menu = await menu_dao.get(db, obj.parent_id)
|
||||
if not parent_menu:
|
||||
@@ -100,7 +100,7 @@ class MenuService:
|
||||
raise errors.NotFoundError(msg='菜单不存在')
|
||||
if menu.title != obj.title:
|
||||
if await menu_dao.get_by_title(db, obj.title):
|
||||
raise errors.ForbiddenError(msg='菜单标题已存在')
|
||||
raise errors.ConflictError(msg='菜单标题已存在')
|
||||
if obj.parent_id:
|
||||
parent_menu = await menu_dao.get(db, obj.parent_id)
|
||||
if not parent_menu:
|
||||
@@ -124,7 +124,7 @@ class MenuService:
|
||||
async with async_db_session.begin() as db:
|
||||
children = await menu_dao.get_children(db, pk)
|
||||
if children:
|
||||
raise errors.ForbiddenError(msg='菜单下存在子菜单,无法删除')
|
||||
raise errors.ConflictError(msg='菜单下存在子菜单,无法删除')
|
||||
menu = await menu_dao.get(db, pk)
|
||||
count = await menu_dao.delete(db, pk)
|
||||
if menu:
|
||||
|
||||
@@ -55,24 +55,24 @@ class PluginService:
|
||||
contents = await file.read()
|
||||
file_bytes = io.BytesIO(contents)
|
||||
if not zipfile.is_zipfile(file_bytes):
|
||||
raise errors.ForbiddenError(msg='插件压缩包格式非法')
|
||||
raise errors.RequestError(msg='插件压缩包格式非法')
|
||||
with zipfile.ZipFile(file_bytes) as zf:
|
||||
# 校验压缩包
|
||||
plugin_namelist = zf.namelist()
|
||||
plugin_name = plugin_namelist[0].split('/')[0]
|
||||
if not plugin_namelist or plugin_name not in file.filename:
|
||||
raise errors.ForbiddenError(msg='插件压缩包内容非法')
|
||||
raise errors.RequestError(msg='插件压缩包内容非法')
|
||||
if (
|
||||
len(plugin_namelist) <= 3
|
||||
or f'{plugin_name}/plugin.toml' not in plugin_namelist
|
||||
or f'{plugin_name}/README.md' not in plugin_namelist
|
||||
):
|
||||
raise errors.ForbiddenError(msg='插件压缩包内缺少必要文件')
|
||||
raise errors.RequestError(msg='插件压缩包内缺少必要文件')
|
||||
|
||||
# 插件是否可安装
|
||||
full_plugin_path = os.path.join(PLUGIN_DIR, plugin_name)
|
||||
if os.path.exists(full_plugin_path):
|
||||
raise errors.ForbiddenError(msg='此插件已安装')
|
||||
raise errors.ConflictError(msg='此插件已安装')
|
||||
else:
|
||||
os.makedirs(full_plugin_path, exist_ok=True)
|
||||
|
||||
@@ -99,11 +99,11 @@ class PluginService:
|
||||
"""
|
||||
match = is_git_url(repo_url)
|
||||
if not match:
|
||||
raise errors.ForbiddenError(msg='Git 仓库地址格式非法')
|
||||
raise errors.RequestError(msg='Git 仓库地址格式非法')
|
||||
repo_name = match.group('repo')
|
||||
plugins = await redis_client.lrange(settings.PLUGIN_REDIS_PREFIX, 0, -1)
|
||||
if repo_name in plugins:
|
||||
raise errors.ForbiddenError(msg=f'{repo_name} 插件已安装')
|
||||
raise errors.ConflictError(msg=f'{repo_name} 插件已安装')
|
||||
try:
|
||||
porcelain.clone(repo_url, os.path.join(PLUGIN_DIR, repo_name), checkout=True)
|
||||
except Exception as e:
|
||||
@@ -124,11 +124,11 @@ class PluginService:
|
||||
"""
|
||||
if type == PluginType.zip:
|
||||
if not file:
|
||||
raise errors.ForbiddenError(msg='ZIP 压缩包不能为空')
|
||||
raise errors.RequestError(msg='ZIP 压缩包不能为空')
|
||||
await self.install_zip(file=file)
|
||||
elif type == PluginType.git:
|
||||
if not repo_url:
|
||||
raise errors.ForbiddenError(msg='Git 仓库地址不能为空')
|
||||
raise errors.RequestError(msg='Git 仓库地址不能为空')
|
||||
await self.install_git(repo_url=repo_url)
|
||||
|
||||
@staticmethod
|
||||
@@ -141,7 +141,7 @@ class PluginService:
|
||||
"""
|
||||
plugin_dir = os.path.join(PLUGIN_DIR, plugin)
|
||||
if not os.path.exists(plugin_dir):
|
||||
raise errors.ForbiddenError(msg='插件不存在')
|
||||
raise errors.NotFoundError(msg='插件不存在')
|
||||
await uninstall_requirements_async(plugin)
|
||||
bacup_dir = os.path.join(PLUGIN_DIR, f'{plugin}.{timezone.now().strftime("%Y%m%d%H%M%S")}.backup')
|
||||
shutil.move(plugin_dir, bacup_dir)
|
||||
@@ -159,7 +159,7 @@ class PluginService:
|
||||
"""
|
||||
plugin_info = await redis_client.get(f'{settings.PLUGIN_REDIS_PREFIX}:info:{plugin}')
|
||||
if not plugin_info:
|
||||
raise errors.ForbiddenError(msg='插件不存在')
|
||||
raise errors.NotFoundError(msg='插件不存在')
|
||||
plugin_info = json.loads(plugin_info)
|
||||
|
||||
# 更新持久缓存状态
|
||||
@@ -184,7 +184,7 @@ class PluginService:
|
||||
"""
|
||||
plugin_dir = os.path.join(PLUGIN_DIR, plugin)
|
||||
if not os.path.exists(plugin_dir):
|
||||
raise errors.ForbiddenError(msg='插件不存在')
|
||||
raise errors.NotFoundError(msg='插件不存在')
|
||||
|
||||
bio = io.BytesIO()
|
||||
with zipfile.ZipFile(bio, 'w') as zf:
|
||||
|
||||
@@ -98,7 +98,7 @@ class RoleService:
|
||||
async with async_db_session.begin() as db:
|
||||
role = await role_dao.get_by_name(db, obj.name)
|
||||
if role:
|
||||
raise errors.ForbiddenError(msg='角色已存在')
|
||||
raise errors.ConflictError(msg='角色已存在')
|
||||
await role_dao.create(db, obj)
|
||||
|
||||
@staticmethod
|
||||
@@ -116,7 +116,7 @@ class RoleService:
|
||||
raise errors.NotFoundError(msg='角色不存在')
|
||||
if role.name != obj.name:
|
||||
if await role_dao.get_by_name(db, obj.name):
|
||||
raise errors.ForbiddenError(msg='角色已存在')
|
||||
raise errors.ConflictError(msg='角色已存在')
|
||||
count = await role_dao.update(db, pk, obj)
|
||||
for user in await role.awaitable_attrs.users:
|
||||
await redis_client.delete_prefix(f'{settings.JWT_USER_REDIS_PREFIX}:{user.id}')
|
||||
|
||||
@@ -81,10 +81,10 @@ class UserService:
|
||||
async with async_db_session.begin() as db:
|
||||
superuser_verify(request)
|
||||
if await user_dao.get_by_username(db, obj.username):
|
||||
raise errors.ForbiddenError(msg='用户名已注册')
|
||||
raise errors.ConflictError(msg='用户名已注册')
|
||||
obj.nickname = obj.nickname if obj.nickname else f'#{random.randrange(88888, 99999)}'
|
||||
if not obj.password:
|
||||
raise errors.ForbiddenError(msg='密码不允许为空')
|
||||
raise errors.RequestError(msg='密码不允许为空')
|
||||
if not await dept_dao.get(db, obj.dept_id):
|
||||
raise errors.NotFoundError(msg='部门不存在')
|
||||
for role_id in obj.roles:
|
||||
@@ -110,7 +110,7 @@ class UserService:
|
||||
raise errors.ForbiddenError(msg='只能修改自己的信息')
|
||||
if obj.username != user.username:
|
||||
if await user_dao.get_by_username(db, obj.username):
|
||||
raise errors.ForbiddenError(msg='用户名已注册')
|
||||
raise errors.ConflictError(msg='用户名已注册')
|
||||
for role_id in obj.roles:
|
||||
if not await role_dao.get(db, role_id):
|
||||
raise errors.NotFoundError(msg='角色不存在')
|
||||
@@ -222,16 +222,17 @@ class UserService:
|
||||
:param type: 权限类型
|
||||
:return:
|
||||
"""
|
||||
if type == UserPermissionType.superuser:
|
||||
count = await self.update_superuser(request=request, pk=pk)
|
||||
elif type == UserPermissionType.staff:
|
||||
count = await self.update_staff(request=request, pk=pk)
|
||||
elif type == UserPermissionType.status:
|
||||
count = await self.update_status(request=request, pk=pk)
|
||||
elif type == UserPermissionType.multi_login:
|
||||
count = await self.update_multi_login(request=request, pk=pk)
|
||||
else:
|
||||
raise errors.ForbiddenError(msg='权限类型不存在')
|
||||
match type:
|
||||
case UserPermissionType.superuser:
|
||||
count = await self.update_superuser(request=request, pk=pk)
|
||||
case UserPermissionType.staff:
|
||||
count = await self.update_staff(request=request, pk=pk)
|
||||
case UserPermissionType.status:
|
||||
count = await self.update_status(request=request, pk=pk)
|
||||
case UserPermissionType.multi_login:
|
||||
count = await self.update_multi_login(request=request, pk=pk)
|
||||
case _:
|
||||
raise errors.RequestError(msg='权限类型不存在')
|
||||
return count
|
||||
|
||||
@staticmethod
|
||||
@@ -248,9 +249,9 @@ class UserService:
|
||||
if not user:
|
||||
raise errors.NotFoundError(msg='用户不存在')
|
||||
if not password_verify(obj.old_password, user.password):
|
||||
raise errors.ForbiddenError(msg='原密码错误')
|
||||
raise errors.RequestError(msg='原密码错误')
|
||||
if obj.new_password != obj.confirm_password:
|
||||
raise errors.ForbiddenError(msg='密码输入不一致')
|
||||
raise errors.RequestError(msg='密码输入不一致')
|
||||
new_pwd = get_hash_password(obj.new_password, user.salt)
|
||||
count = await user_dao.reset_password(db, user.id, new_pwd)
|
||||
key_prefix = [
|
||||
|
||||
@@ -39,7 +39,7 @@ class TaskService:
|
||||
"""获取所有已注册的 Celery 任务列表"""
|
||||
registered_tasks = await run_in_threadpool(celery_app.control.inspect().registered)
|
||||
if not registered_tasks:
|
||||
raise errors.ForbiddenError(msg='Celery 服务未启动')
|
||||
raise errors.ServerError(msg='Celery 服务未启动')
|
||||
tasks = list(registered_tasks.values())[0]
|
||||
return tasks
|
||||
|
||||
|
||||
@@ -98,3 +98,12 @@ class TokenError(HTTPError):
|
||||
|
||||
def __init__(self, *, msg: str = 'Not Authenticated', headers: dict[str, Any] | None = None):
|
||||
super().__init__(code=self.code, msg=msg, headers=headers or {'WWW-Authenticate': 'Bearer'})
|
||||
|
||||
|
||||
class ConflictError(BaseExceptionMixin):
|
||||
"""资源冲突异常"""
|
||||
|
||||
code = StandardResponseCode.HTTP_409
|
||||
|
||||
def __init__(self, *, msg: str = 'Conflict', data: Any = None, background: BackgroundTask | None = None):
|
||||
super().__init__(msg=msg, data=data, background=background)
|
||||
|
||||
@@ -6,8 +6,9 @@ from datetime import timedelta
|
||||
from typing import Any
|
||||
from uuid import uuid4
|
||||
|
||||
from fastapi import Depends, Request
|
||||
from fastapi import Depends, HTTPException, Request
|
||||
from fastapi.security import HTTPBearer
|
||||
from fastapi.security.http import HTTPAuthorizationCredentials
|
||||
from fastapi.security.utils import get_authorization_scheme_param
|
||||
from jose import ExpiredSignatureError, JWTError, jwt
|
||||
from pwdlib import PasswordHash
|
||||
@@ -19,14 +20,32 @@ from backend.app.admin.model import User
|
||||
from backend.app.admin.schema.user import GetUserInfoWithRelationDetail
|
||||
from backend.common.dataclasses import AccessToken, NewToken, RefreshToken, TokenPayload
|
||||
from backend.common.exception import errors
|
||||
from backend.common.exception.errors import TokenError
|
||||
from backend.core.conf import settings
|
||||
from backend.database.db import async_db_session
|
||||
from backend.database.redis import redis_client
|
||||
from backend.utils.serializers import select_as_dict
|
||||
from backend.utils.timezone import timezone
|
||||
|
||||
|
||||
class CustomHTTPBearer(HTTPBearer):
|
||||
"""
|
||||
自定义 HTTPBearer 认证类
|
||||
|
||||
Issues: https://github.com/fastapi/fastapi/issues/10177
|
||||
"""
|
||||
|
||||
async def __call__(self, request: Request) -> HTTPAuthorizationCredentials | None:
|
||||
try:
|
||||
return await super().__call__(request)
|
||||
except HTTPException as e:
|
||||
if e.status_code == 403:
|
||||
raise TokenError()
|
||||
raise e
|
||||
|
||||
|
||||
# JWT authorizes dependency injection
|
||||
DependsJwtAuth = Depends(HTTPBearer())
|
||||
DependsJwtAuth = Depends(CustomHTTPBearer())
|
||||
|
||||
password_hash = PasswordHash((BcryptHasher(),))
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class GenBusinessService:
|
||||
async with async_db_session.begin() as db:
|
||||
business = await gen_business_dao.get_by_name(db, obj.table_name)
|
||||
if business:
|
||||
raise errors.ForbiddenError(msg='代码生成业务已存在')
|
||||
raise errors.ConflictError(msg='代码生成业务已存在')
|
||||
await gen_business_dao.create(db, obj)
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -76,7 +76,7 @@ class GenModelService:
|
||||
if obj.name != model.name:
|
||||
gen_models = await gen_model_dao.get_all_by_business(db, obj.gen_business_id)
|
||||
if obj.name in [gen_model.name for gen_model in gen_models]:
|
||||
raise errors.ForbiddenError(msg='模型列名已存在')
|
||||
raise errors.ConflictError(msg='模型列名已存在')
|
||||
|
||||
pd_type = sql_type_to_pydantic(obj.type)
|
||||
return await gen_model_dao.update(db, pk, obj, pd_type=pd_type)
|
||||
|
||||
@@ -55,7 +55,7 @@ class GenService:
|
||||
|
||||
business_info = await gen_business_dao.get_by_name(db, obj.table_name)
|
||||
if business_info:
|
||||
raise errors.ForbiddenError(msg='已存在相同数据库表业务')
|
||||
raise errors.ConflictError(msg='已存在相同数据库表业务')
|
||||
|
||||
table_name = table_info[0]
|
||||
new_business = GenBusiness(
|
||||
|
||||
@@ -52,10 +52,10 @@ class ConfigService:
|
||||
"""
|
||||
async with async_db_session.begin() as db:
|
||||
if obj.type in settings.CONFIG_BUILT_IN_TYPES:
|
||||
raise errors.ForbiddenError(msg='非法类型参数')
|
||||
raise errors.RequestError(msg='非法类型参数')
|
||||
config = await config_dao.get_by_key(db, obj.key)
|
||||
if config:
|
||||
raise errors.ForbiddenError(msg=f'参数配置 {obj.key} 已存在')
|
||||
raise errors.ConflictError(msg=f'参数配置 {obj.key} 已存在')
|
||||
await config_dao.create(db, obj)
|
||||
|
||||
@staticmethod
|
||||
@@ -74,7 +74,7 @@ class ConfigService:
|
||||
if config.key != obj.key:
|
||||
config = await config_dao.get_by_key(db, obj.key)
|
||||
if config:
|
||||
raise errors.ForbiddenError(msg=f'参数配置 {obj.key} 已存在')
|
||||
raise errors.ConflictError(msg=f'参数配置 {obj.key} 已存在')
|
||||
count = await config_dao.update(db, pk, obj)
|
||||
return count
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ class DictDataService:
|
||||
async with async_db_session.begin() as db:
|
||||
dict_data = await dict_data_dao.get_by_label(db, obj.label)
|
||||
if dict_data:
|
||||
raise errors.ForbiddenError(msg='字典数据已存在')
|
||||
raise errors.ConflictError(msg='字典数据已存在')
|
||||
dict_type = await dict_type_dao.get(db, obj.type_id)
|
||||
if not dict_type:
|
||||
raise errors.NotFoundError(msg='字典类型不存在')
|
||||
@@ -79,7 +79,7 @@ class DictDataService:
|
||||
raise errors.NotFoundError(msg='字典数据不存在')
|
||||
if dict_data.label != obj.label:
|
||||
if await dict_data_dao.get_by_label(db, obj.label):
|
||||
raise errors.ForbiddenError(msg='字典数据已存在')
|
||||
raise errors.ConflictError(msg='字典数据已存在')
|
||||
dict_type = await dict_type_dao.get(db, obj.type_id)
|
||||
if not dict_type:
|
||||
raise errors.NotFoundError(msg='字典类型不存在')
|
||||
|
||||
@@ -49,7 +49,7 @@ class DictTypeService:
|
||||
async with async_db_session.begin() as db:
|
||||
dict_type = await dict_type_dao.get_by_code(db, obj.code)
|
||||
if dict_type:
|
||||
raise errors.ForbiddenError(msg='字典类型已存在')
|
||||
raise errors.ConflictError(msg='字典类型已存在')
|
||||
await dict_type_dao.create(db, obj)
|
||||
|
||||
@staticmethod
|
||||
@@ -67,7 +67,7 @@ class DictTypeService:
|
||||
raise errors.NotFoundError(msg='字典类型不存在')
|
||||
if dict_type.code != obj.code:
|
||||
if await dict_type_dao.get_by_code(db, obj.code):
|
||||
raise errors.ForbiddenError(msg='字典类型已存在')
|
||||
raise errors.ConflictError(msg='字典类型已存在')
|
||||
count = await dict_type_dao.update(db, pk, obj)
|
||||
return count
|
||||
|
||||
|
||||
@@ -331,4 +331,4 @@ class PluginStatusChecker:
|
||||
log.error(f'插件 {self.plugin} 状态未初始化或丢失,需重启服务自动修复')
|
||||
raise PluginInjectError(f'插件 {self.plugin} 状态未初始化或丢失,请联系系统管理员')
|
||||
if not int(plugin_status.get(self.plugin)):
|
||||
raise errors.ForbiddenError(msg=f'插件 {self.plugin} 未启用,请联系系统管理员')
|
||||
raise errors.ServerError(msg=f'插件 {self.plugin} 未启用,请联系系统管理员')
|
||||
|
||||
@@ -38,18 +38,18 @@ def file_verify(file: UploadFile) -> None:
|
||||
filename = file.filename
|
||||
file_ext = filename.split('.')[-1].lower()
|
||||
if not file_ext:
|
||||
raise errors.ForbiddenError(msg='未知的文件类型')
|
||||
raise errors.RequestError(msg='未知的文件类型')
|
||||
|
||||
if file_ext == FileType.image:
|
||||
if file_ext not in settings.UPLOAD_IMAGE_EXT_INCLUDE:
|
||||
raise errors.ForbiddenError(msg='此图片格式暂不支持')
|
||||
raise errors.RequestError(msg='此图片格式暂不支持')
|
||||
if file.size > settings.UPLOAD_IMAGE_SIZE_MAX:
|
||||
raise errors.ForbiddenError(msg='图片超出最大限制,请重新选择')
|
||||
raise errors.RequestError(msg='图片超出最大限制,请重新选择')
|
||||
elif file_ext == FileType.video:
|
||||
if file_ext not in settings.UPLOAD_VIDEO_EXT_INCLUDE:
|
||||
raise errors.ForbiddenError(msg='此视频格式暂不支持')
|
||||
raise errors.RequestError(msg='此视频格式暂不支持')
|
||||
if file.size > settings.UPLOAD_VIDEO_SIZE_MAX:
|
||||
raise errors.ForbiddenError(msg='视频超出最大限制,请重新选择')
|
||||
raise errors.RequestError(msg='视频超出最大限制,请重新选择')
|
||||
|
||||
|
||||
async def upload_file(file: UploadFile) -> str:
|
||||
|
||||
@@ -54,9 +54,9 @@ class Snowflake:
|
||||
:param sequence: 起始序列号
|
||||
"""
|
||||
if cluster_id < 0 or cluster_id > SnowflakeConfig.MAX_DATACENTER_ID:
|
||||
raise errors.ForbiddenError(msg=f'集群编号必须在 0-{SnowflakeConfig.MAX_DATACENTER_ID} 之间')
|
||||
raise errors.RequestError(msg=f'集群编号必须在 0-{SnowflakeConfig.MAX_DATACENTER_ID} 之间')
|
||||
if node_id < 0 or node_id > SnowflakeConfig.MAX_WORKER_ID:
|
||||
raise errors.ForbiddenError(msg=f'节点编号必须在 0-{SnowflakeConfig.MAX_WORKER_ID} 之间')
|
||||
raise errors.RequestError(msg=f'节点编号必须在 0-{SnowflakeConfig.MAX_WORKER_ID} 之间')
|
||||
|
||||
self.node_id = node_id
|
||||
self.cluster_id = cluster_id
|
||||
|
||||
Reference in New Issue
Block a user