diff --git a/README.md b/README.md index 11041d56..a952ba30 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,9 @@ TBD: 交流群二维码 ## UI 展示 - - - + q&a - - - - -
SQLBot Demo1SQLBot Demo2
SQLBot Demo3SQLBot Demo4
## Star History diff --git a/backend/apps/chat/task/llm.py b/backend/apps/chat/task/llm.py index 577ecb22..b208f4e2 100644 --- a/backend/apps/chat/task/llm.py +++ b/backend/apps/chat/task/llm.py @@ -700,6 +700,8 @@ class LLMService: def check_save_chart(self, res: str) -> Dict[str, Any]: json_str = extract_nested_json(res) + if json_str is None: + raise Exception("Cannot parse chart config from answer") data = orjson.loads(json_str) chart: Dict[str, Any] = {} diff --git a/backend/apps/system/crud/user.py b/backend/apps/system/crud/user.py index d721ef50..3dcd4ccf 100644 --- a/backend/apps/system/crud/user.py +++ b/backend/apps/system/crud/user.py @@ -26,6 +26,8 @@ def get_user_by_account(*, session: Session, account: str) -> BaseUserDTO | None @cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="user_id") async def get_user_info(*, session: Session, user_id: int) -> UserInfoDTO | None: db_user: UserModel = get_db_user(session = session, user_id = user_id) + if not db_user: + return None userInfo = UserInfoDTO.model_validate(db_user.model_dump()) userInfo.isAdmin = userInfo.id == 1 and userInfo.account == 'admin' if userInfo.isAdmin: diff --git a/backend/apps/system/middleware/auth.py b/backend/apps/system/middleware/auth.py index 4f4d8706..be44d814 100644 --- a/backend/apps/system/middleware/auth.py +++ b/backend/apps/system/middleware/auth.py @@ -13,9 +13,11 @@ from apps.system.schemas.system_schema import AssistantHeader, UserInfoDTO from common.core import security from common.core.config import settings from common.core.schemas import TokenPayload +from common.utils.locale import I18n from common.utils.utils import SQLBotLogUtil from common.utils.whitelist import whiteUtils from fastapi.security.utils import get_authorization_scheme_param +from common.core.deps import get_i18n class TokenMiddleware(BaseHTTPMiddleware): @@ -29,6 +31,7 @@ class TokenMiddleware(BaseHTTPMiddleware): return await call_next(request) assistantTokenKey = settings.ASSISTANT_TOKEN_KEY assistantToken = request.headers.get(assistantTokenKey) + trans = await get_i18n(request) #if assistantToken and assistantToken.lower().startswith("assistant "): if assistantToken: validator: tuple[any] = await self.validateAssistant(assistantToken) @@ -36,20 +39,23 @@ class TokenMiddleware(BaseHTTPMiddleware): request.state.current_user = validator[1] request.state.assistant = validator[2] return await call_next(request) - return JSONResponse(f"Unauthorized:[{validator[1]}]", status_code=401, headers={"Access-Control-Allow-Origin": "*"}) + message = trans('i18n_permission.authenticate_invalid', msg = validator[1]) + return JSONResponse(message, status_code=401, headers={"Access-Control-Allow-Origin": "*"}) #validate pass tokenkey = settings.TOKEN_KEY token = request.headers.get(tokenkey) - validate_pass, data = await self.validateToken(token) + validate_pass, data = await self.validateToken(token, trans) if validate_pass: request.state.current_user = data return await call_next(request) - return JSONResponse(f"Unauthorized:[{data}]", status_code=401, headers={"Access-Control-Allow-Origin": "*"}) + + message = trans('i18n_permission.authenticate_invalid', msg = data) + return JSONResponse(message, status_code=401, headers={"Access-Control-Allow-Origin": "*"}) def is_options(self, request: Request): return request.method == "OPTIONS" - async def validateToken(self, token: Optional[str]): + async def validateToken(self, token: Optional[str], trans: I18n): if not token: return False, f"Miss Token[{settings.TOKEN_KEY}]!" schema, param = get_authorization_scheme_param(token) @@ -63,17 +69,15 @@ class TokenMiddleware(BaseHTTPMiddleware): with Session(engine) as session: session_user = await get_user_info(session = session, user_id = token_data.id) if not session_user: - raise Exception(f"User not found with id: {token_data.id}") + message = trans('i18n_not_exist', msg = trans('i18n_user.account')) + raise Exception(message) session_user = UserInfoDTO.model_validate(session_user) if session_user.status != 1: - raise Exception(f"User is not active!") + message = trans('i18n_login.user_disable', msg = trans('i18n_concat_admin')) + raise Exception(message) if not session_user.oid or session_user.oid == 0: - raise Exception(f"User default space is not set!") - """ if token_data.oid != session_user.oid: - raise HTTPException( - status_code=401, - detail="Default space has been changed, please login again!" - ) """ + message = trans('i18n_login.no_associated_ws', msg = trans('i18n_concat_admin')) + raise Exception(message) return True, session_user except Exception as e: SQLBotLogUtil.exception(f"Token validation error: {str(e)}") diff --git a/backend/locales/en.json b/backend/locales/en.json index 7b775419..ffe76fd3 100644 --- a/backend/locales/en.json +++ b/backend/locales/en.json @@ -24,7 +24,8 @@ }, "i18n_permission": { "only_admin": "Only administrators can call this!", - "no_permission": "No permission to access {url}{msg}" + "no_permission": "No permission to access {url}{msg}", + "authenticate_invalid": "Authenticate invalid [{msg}]" }, "i18n_llm": { "validate_error": "Validation failed [{msg}]", diff --git a/backend/locales/zh-CN.json b/backend/locales/zh-CN.json index abadd609..2a63da7f 100644 --- a/backend/locales/zh-CN.json +++ b/backend/locales/zh-CN.json @@ -24,7 +24,8 @@ }, "i18n_permission": { "only_admin": "仅支持管理员调用!", - "no_permission": "无权调用{url}{msg}" + "no_permission": "无权调用{url}{msg}", + "authenticate_invalid": "认证无效【{msg}】" }, "i18n_llm": { diff --git a/frontend/src/utils/request.ts b/frontend/src/utils/request.ts index 5cbdc90d..e9ae6c17 100644 --- a/frontend/src/utils/request.ts +++ b/frontend/src/utils/request.ts @@ -182,7 +182,7 @@ class HttpService { setTimeout(() => { wsCache.delete('user.token') window.location.reload() - }, 1000) + }, 2000) return // break case 403: diff --git a/frontend/src/views/system/embedded/index.vue b/frontend/src/views/system/embedded/index.vue index dc357d4e..977997c2 100644 --- a/frontend/src/views/system/embedded/index.vue +++ b/frontend/src/views/system/embedded/index.vue @@ -760,6 +760,7 @@ const saveHandler = () => { :name="ele.name" :type="ele.type" :type-name="ele.type_name" + :description="ele.description" :is-private="dsForm.private_list.includes(ele.id)" :num="ele.num" @active="handleActive(ele)"