mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 09:17:06 +08:00
perf: Optimize page embedding mechanism
This commit is contained in:
@@ -8,7 +8,7 @@ from starlette.middleware.base import BaseHTTPMiddleware
|
||||
from apps.system.models.system_model import AssistantModel
|
||||
from common.core.db import engine
|
||||
from apps.system.crud.assistant import get_assistant_info, get_assistant_user
|
||||
from apps.system.crud.user import get_user_info
|
||||
from apps.system.crud.user import get_user_by_account, get_user_info
|
||||
from apps.system.schemas.system_schema import AssistantHeader, UserInfoDTO
|
||||
from common.core import security
|
||||
from common.core.config import settings
|
||||
@@ -34,7 +34,7 @@ class TokenMiddleware(BaseHTTPMiddleware):
|
||||
trans = await get_i18n(request)
|
||||
#if assistantToken and assistantToken.lower().startswith("assistant "):
|
||||
if assistantToken:
|
||||
validator: tuple[any] = await self.validateAssistant(assistantToken)
|
||||
validator: tuple[any] = await self.validateAssistant(assistantToken, trans)
|
||||
if validator[0]:
|
||||
request.state.current_user = validator[1]
|
||||
request.state.assistant = validator[2]
|
||||
@@ -87,14 +87,17 @@ class TokenMiddleware(BaseHTTPMiddleware):
|
||||
return False, e
|
||||
|
||||
|
||||
async def validateAssistant(self, assistantToken: Optional[str]) -> tuple[any]:
|
||||
async def validateAssistant(self, assistantToken: Optional[str], trans: I18n) -> tuple[any]:
|
||||
if not assistantToken:
|
||||
return False, f"Miss Token[{settings.TOKEN_KEY}]!"
|
||||
schema, param = get_authorization_scheme_param(assistantToken)
|
||||
if schema.lower() != "assistant":
|
||||
return False, f"Token schema error!"
|
||||
|
||||
try:
|
||||
|
||||
try:
|
||||
if schema.lower() == 'embedded':
|
||||
return await self.validateEmbedded(param, trans)
|
||||
if schema.lower() != "assistant":
|
||||
return False, f"Token schema error!"
|
||||
payload = jwt.decode(
|
||||
param, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
|
||||
)
|
||||
@@ -112,4 +115,45 @@ class TokenMiddleware(BaseHTTPMiddleware):
|
||||
except Exception as e:
|
||||
SQLBotLogUtil.exception(f"Assistant validation error: {str(e)}")
|
||||
# Return False and the exception message
|
||||
return False, e
|
||||
|
||||
async def validateEmbedded(self, param: str, trans: I18n) -> tuple[any]:
|
||||
try:
|
||||
""" payload = jwt.decode(
|
||||
param, settings.SECRET_KEY, algorithms=[security.ALGORITHM]
|
||||
) """
|
||||
payload: dict = jwt.decode(
|
||||
param,
|
||||
options={"verify_signature": False, "verify_exp": False},
|
||||
algorithms=[security.ALGORITHM]
|
||||
)
|
||||
if not payload['embeddedId']:
|
||||
return False, f"Miss embeddedId payload error!"
|
||||
if not payload['account']:
|
||||
return False, f"Miss account payload error!"
|
||||
embeddedId = payload['embeddedId']
|
||||
account = payload['account']
|
||||
with Session(engine) as session:
|
||||
""" session_user = await get_user_info(session = session, user_id = token_data.id)
|
||||
session_user = UserInfoDTO.model_validate(session_user) """
|
||||
session_user = get_user_by_account(session = session, account=account)
|
||||
if not session_user:
|
||||
message = trans('i18n_not_exist', msg = trans('i18n_user.account'))
|
||||
raise Exception(message)
|
||||
session_user = await get_user_info(session = session, user_id = session_user.id)
|
||||
|
||||
session_user = UserInfoDTO.model_validate(session_user)
|
||||
if session_user.status != 1:
|
||||
message = trans('i18n_login.user_disable', msg = trans('i18n_concat_admin'))
|
||||
raise Exception(message)
|
||||
if not session_user.oid or session_user.oid == 0:
|
||||
message = trans('i18n_login.no_associated_ws', msg = trans('i18n_concat_admin'))
|
||||
raise Exception(message)
|
||||
assistant_info = await get_assistant_info(session=session, assistant_id=embeddedId)
|
||||
assistant_info = AssistantModel.model_validate(assistant_info)
|
||||
assistant_info = AssistantHeader.model_validate(assistant_info.model_dump(exclude_unset=True))
|
||||
return True, session_user, assistant_info
|
||||
except Exception as e:
|
||||
SQLBotLogUtil.exception(f"Embedded validation error: {str(e)}")
|
||||
# Return False and the exception message
|
||||
return False, e
|
||||
@@ -27,11 +27,11 @@ wlist = [
|
||||
"/system/config/key",
|
||||
"/images/*",
|
||||
"/sse",
|
||||
"/system/appearance*",
|
||||
"/system/appearance/ui",
|
||||
"/system/appearance/picture/*",
|
||||
"/system/assistant/validator*",
|
||||
"/system/assistant/info/*",
|
||||
"/system/assistant/picture/*",
|
||||
"/system/embedded*",
|
||||
"/datasource/uploadExcel"
|
||||
]
|
||||
|
||||
|
||||
@@ -36,28 +36,21 @@ dependencies = [
|
||||
"pyyaml (>=6.0.2,<7.0.0)",
|
||||
"fastapi-mcp (>=0.3.4,<0.4.0)",
|
||||
"tabulate>=0.9.0",
|
||||
"sqlbot-xpack>=0.0.3.19,<1.0.0",
|
||||
"fastapi-cache2>=0.2.2",
|
||||
"sqlparse>=0.5.3",
|
||||
"redis>=6.2.0",
|
||||
"xlsxwriter>=3.2.5",
|
||||
"python-calamine>=0.4.0",
|
||||
"xlrd>=2.0.2",
|
||||
"clickhouse-sqlalchemy>=0.3.2",
|
||||
"dmpython>=2.5.22",
|
||||
"sqlbot-xpack",
|
||||
]
|
||||
[[tool.uv.index]]
|
||||
name = "default"
|
||||
url = "https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple"
|
||||
default = true
|
||||
|
||||
[[tool.uv.index]]
|
||||
name = "testpypi"
|
||||
url = "https://test.pypi.org/simple"
|
||||
explicit = true
|
||||
|
||||
[tool.uv.sources]
|
||||
sqlbot-xpack = { index = "testpypi" }
|
||||
sqlbot-xpack = { path = "../../sqlbot-xpack/dist/sqlbot_xpack-0.0.3.19-cp311-cp311-macosx_11_0_arm64.whl" }
|
||||
|
||||
[tool.uv]
|
||||
dev-dependencies = [
|
||||
|
||||
@@ -252,7 +252,7 @@ export const useAppearanceStore = defineStore('appearanceStore', {
|
||||
setLinkIcon()
|
||||
return
|
||||
}
|
||||
const resData = await request.get('/system/appearance')
|
||||
const resData = await request.get('/system/appearance/ui')
|
||||
this.loaded = true
|
||||
if (!resData?.length) {
|
||||
return
|
||||
|
||||
@@ -80,14 +80,19 @@ class HttpService {
|
||||
config.headers['X-SQLBOT-TOKEN'] = `Bearer ${token}`
|
||||
}
|
||||
if (assistantStore.getToken) {
|
||||
config.headers['X-SQLBOT-ASSISTANT-TOKEN'] = `Assistant ${assistantStore.getToken}`
|
||||
const prefix = assistantStore.getType === 4 ? 'Embedded ' : 'Assistant '
|
||||
config.headers['X-SQLBOT-ASSISTANT-TOKEN'] = `${prefix}${assistantStore.getToken}`
|
||||
if (config.headers['X-SQLBOT-TOKEN']) config.headers.delete('X-SQLBOT-TOKEN')
|
||||
if (assistantStore.getType && assistantStore.getCertificate) {
|
||||
if (
|
||||
assistantStore.getType &&
|
||||
!!(assistantStore.getType % 2) &&
|
||||
assistantStore.getCertificate
|
||||
) {
|
||||
config.headers['X-SQLBOT-ASSISTANT-CERTIFICATE'] = btoa(
|
||||
encodeURIComponent(assistantStore.getCertificate)
|
||||
)
|
||||
}
|
||||
if (!assistantStore.getType) {
|
||||
if (!assistantStore.getType || assistantStore.getType === 2) {
|
||||
config.headers['X-SQLBOT-ASSISTANT-ONLINE'] = assistantStore.getOnline
|
||||
}
|
||||
}
|
||||
@@ -270,15 +275,20 @@ class HttpService {
|
||||
heads['X-SQLBOT-TOKEN'] = `Bearer ${token}`
|
||||
}
|
||||
if (assistantStore.getToken) {
|
||||
heads['X-SQLBOT-ASSISTANT-TOKEN'] = `Assistant ${assistantStore.getToken}`
|
||||
const prefix = assistantStore.getType === 4 ? 'Embedded ' : 'Assistant '
|
||||
heads['X-SQLBOT-ASSISTANT-TOKEN'] = `${prefix}${assistantStore.getToken}`
|
||||
if (heads['X-SQLBOT-TOKEN']) delete heads['X-SQLBOT-TOKEN']
|
||||
if (assistantStore.getType && assistantStore.getCertificate) {
|
||||
if (
|
||||
assistantStore.getType &&
|
||||
!!(assistantStore.getType % 2) &&
|
||||
assistantStore.getCertificate
|
||||
) {
|
||||
await assistantStore.refreshCertificate()
|
||||
heads['X-SQLBOT-ASSISTANT-CERTIFICATE'] = btoa(
|
||||
encodeURIComponent(assistantStore.getCertificate)
|
||||
)
|
||||
}
|
||||
if (!assistantStore.getType) {
|
||||
if (!assistantStore.getType || assistantStore.getType === 2) {
|
||||
heads['X-SQLBOT-ASSISTANT-ONLINE'] = assistantStore.getOnline
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,15 +22,22 @@ const validator = ref({
|
||||
token: '',
|
||||
})
|
||||
const loading = ref(true)
|
||||
const eventName = 'sqlbot_assistant_event'
|
||||
const eventName = 'sqlbot_embedded_event'
|
||||
const communicationCb = async (event: any) => {
|
||||
if (event.data?.eventName === eventName) {
|
||||
if (event.data?.messageId !== route.query.id) {
|
||||
return
|
||||
}
|
||||
if (event.data?.busi == 'certificate') {
|
||||
const type = parseInt(event.data['type'])
|
||||
const certificate = event.data['certificate']
|
||||
assistantStore.setType(1)
|
||||
assistantStore.setType(type || 3)
|
||||
if (type === 4) {
|
||||
assistantStore.setToken(certificate)
|
||||
assistantStore.setAssistant(true)
|
||||
loading.value = false
|
||||
return
|
||||
}
|
||||
assistantStore.setCertificate(certificate)
|
||||
assistantStore.resolveCertificate(certificate)
|
||||
}
|
||||
@@ -55,13 +62,29 @@ const setFormatOnline = (text?: any) => {
|
||||
assistantStore.setOnline(false)
|
||||
}
|
||||
|
||||
const registerReady = (assistantId: any) => {
|
||||
window.addEventListener('message', communicationCb)
|
||||
const readyData = {
|
||||
eventName: 'sqlbot_embedded_event',
|
||||
busi: 'ready',
|
||||
ready: true,
|
||||
messageId: assistantId,
|
||||
}
|
||||
window.parent.postMessage(readyData, '*')
|
||||
}
|
||||
|
||||
onBeforeMount(async () => {
|
||||
debugger
|
||||
const assistantId = route.query.id
|
||||
if (!assistantId) {
|
||||
ElMessage.error('Miss embedded id, please check embedded url')
|
||||
return
|
||||
}
|
||||
const typeParam = route.query.type
|
||||
let assistantType = 2
|
||||
if (typeParam) {
|
||||
assistantType = parseInt(typeParam.toString())
|
||||
assistantStore.setType(assistantType)
|
||||
}
|
||||
const online = route.query.online
|
||||
setFormatOnline(online)
|
||||
|
||||
@@ -72,6 +95,11 @@ onBeforeMount(async () => {
|
||||
const now = Date.now()
|
||||
assistantStore.setFlag(now)
|
||||
assistantStore.setId(assistantId?.toString() || '')
|
||||
if (assistantType === 4) {
|
||||
assistantStore.setAssistant(true)
|
||||
registerReady(assistantId)
|
||||
return
|
||||
}
|
||||
const param = {
|
||||
id: assistantId,
|
||||
virtual: assistantStore.getFlag,
|
||||
@@ -82,14 +110,7 @@ onBeforeMount(async () => {
|
||||
assistantStore.setAssistant(true)
|
||||
loading.value = false
|
||||
|
||||
window.addEventListener('message', communicationCb)
|
||||
const readyData = {
|
||||
eventName: 'sqlbot_embedded_event',
|
||||
busi: 'ready',
|
||||
ready: true,
|
||||
messageId: assistantId,
|
||||
}
|
||||
window.parent.postMessage(readyData, '*')
|
||||
registerReady(assistantId)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
@@ -402,7 +402,7 @@ const buildParam = () => {
|
||||
return formData
|
||||
}
|
||||
const init = () => {
|
||||
const url = '/system/appearance'
|
||||
const url = '/system/appearance/ui'
|
||||
changedItemArray.value = []
|
||||
fileList.value = []
|
||||
request
|
||||
|
||||
Reference in New Issue
Block a user