mirror of
https://gh-proxy.org/https://github.com/klinsmaya/SQLBot.git
synced 2026-11-08 01:06:59 +08:00
Merge branch 'main' of https://github.com/dataease/SQLBot
This commit is contained in:
@@ -5,10 +5,12 @@ from typing import List
|
||||
from fastapi import HTTPException
|
||||
from sqlalchemy import and_, text, cast, or_, func
|
||||
from sqlalchemy.dialects.postgresql import JSONB
|
||||
from sqlbot_xpack.permissions.models.ds_permission import DsPermission
|
||||
from sqlbot_xpack.permissions.api.permission import transRecord2DTO
|
||||
from sqlbot_xpack.permissions.models.ds_permission import DsPermission, PermissionDTO
|
||||
from sqlbot_xpack.permissions.models.ds_rules import DsRules
|
||||
from sqlmodel import select
|
||||
|
||||
from apps.datasource.crud.row_permission import transFilterTree
|
||||
from apps.datasource.utils.utils import aes_decrypt
|
||||
from apps.db.constant import DB
|
||||
from apps.db.db import get_engine, get_tables, get_fields, exec_sql
|
||||
@@ -238,6 +240,9 @@ def updateField(session: SessionDep, field: CoreField):
|
||||
|
||||
|
||||
def preview(session: SessionDep, current_user: CurrentUser, id: int, data: TableObj):
|
||||
ds = session.query(CoreDatasource).filter(CoreDatasource.id == id).first()
|
||||
check_status(session, ds, True)
|
||||
|
||||
if data.fields is None or len(data.fields) == 0:
|
||||
return {"fields": [], "data": [], "sql": ''}
|
||||
|
||||
@@ -261,20 +266,41 @@ def preview(session: SessionDep, current_user: CurrentUser, id: int, data: Table
|
||||
if fields is None or len(fields) == 0:
|
||||
return {"fields": [], "data": [], "sql": ''}
|
||||
|
||||
ds = session.query(CoreDatasource).filter(CoreDatasource.id == id).first()
|
||||
check_status(session, ds, True)
|
||||
# row permission tree
|
||||
row_permissions = session.query(DsPermission).filter(
|
||||
and_(DsPermission.table_id == data.table.id, DsPermission.type == 'row')).all()
|
||||
res: List[PermissionDTO] = []
|
||||
if row_permissions is not None:
|
||||
for permission in row_permissions:
|
||||
# check permission and user in same rules
|
||||
obj = session.query(DsRules).filter(
|
||||
and_(DsRules.permission_list.op('@>')(cast([permission.id], JSONB)),
|
||||
or_(DsRules.user_list.op('@>')(cast([f'{current_user.id}'], JSONB)),
|
||||
DsRules.user_list.op('@>')(cast([current_user.id], JSONB))))
|
||||
).first()
|
||||
if obj is not None:
|
||||
res.append(transRecord2DTO(session, permission))
|
||||
wheres = transFilterTree(session, res, ds)
|
||||
where = (' where ' + wheres) if wheres is not None and wheres != '' else ''
|
||||
|
||||
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration))) if ds.type != "excel" else get_engine_config()
|
||||
sql: str = ""
|
||||
if ds.type == "mysql":
|
||||
sql = f"""SELECT `{"`, `".join(fields)}` FROM `{data.table.table_name}` LIMIT 100"""
|
||||
sql = f"""SELECT `{"`, `".join(fields)}` FROM `{data.table.table_name}`
|
||||
{where}
|
||||
LIMIT 100"""
|
||||
elif ds.type == "sqlServer":
|
||||
sql = f"""SELECT [{"], [".join(fields)}] FROM [{conf.dbSchema}].[{data.table.table_name}]
|
||||
{where}
|
||||
ORDER BY [{data.fields[0].field_name}]
|
||||
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY"""
|
||||
elif ds.type == "pg" or ds.type == "excel":
|
||||
sql = f"""SELECT "{'", "'.join(fields)}" FROM "{conf.dbSchema}"."{data.table.table_name}" LIMIT 100"""
|
||||
sql = f"""SELECT "{'", "'.join(fields)}" FROM "{conf.dbSchema}"."{data.table.table_name}"
|
||||
{where}
|
||||
LIMIT 100"""
|
||||
elif ds.type == "oracle":
|
||||
sql = f"""SELECT "{'", "'.join(fields)}" FROM "{conf.dbSchema}"."{data.table.table_name}"
|
||||
{where}
|
||||
ORDER BY "{data.fields[0].field_name}"
|
||||
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY"""
|
||||
return exec_sql(ds, sql)
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
|
||||
from typing import List, Dict
|
||||
|
||||
from apps.datasource.models.datasource import CoreField, CoreDatasource
|
||||
from sqlbot_xpack.permissions.models.ds_permission import PermissionTree, PermissionDTO
|
||||
|
||||
from apps.datasource.models.datasource import CoreField, CoreDatasource
|
||||
from apps.db.constant import DB
|
||||
from common.core.deps import SessionDep
|
||||
|
||||
|
||||
@@ -48,7 +50,8 @@ def transTreeItem(session: SessionDep, item: Dict, ds: CoreDatasource) -> str |
|
||||
if field is None:
|
||||
return None
|
||||
|
||||
whereName = field.field_name
|
||||
db = DB.get_db(ds.type)
|
||||
whereName = db.prefix + field.field_name + db.suffix
|
||||
if item['filter_type'] == 'enum':
|
||||
if len(item['enum_value']) > 0:
|
||||
if ds['type'] == 'sqlServer' and (
|
||||
|
||||
@@ -95,7 +95,7 @@ async def ws_options(session: SessionDep, current_user: CurrentUser, trans: Tran
|
||||
return await user_ws_options(session, current_user.id, trans)
|
||||
|
||||
@router.put("/ws/{oid}")
|
||||
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
|
||||
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
|
||||
async def ws_change(session: SessionDep, current_user: CurrentUser, oid: int):
|
||||
ws_list: list[UserWs] = await user_ws_options(session, current_user.id)
|
||||
if not any(x.id == oid for x in ws_list):
|
||||
@@ -137,7 +137,7 @@ async def create(session: SessionDep, creator: UserCreator):
|
||||
session.commit()
|
||||
|
||||
@router.put("")
|
||||
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="editor.id")
|
||||
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="editor.id")
|
||||
async def update(session: SessionDep, editor: UserEditor):
|
||||
user_model: UserModel = get_db_user(session = session, user_id = editor.id)
|
||||
origin_oid: int = user_model.oid
|
||||
@@ -173,7 +173,7 @@ async def batch_del(session: SessionDep, id_list: list[int]):
|
||||
await single_delete(session, id)
|
||||
|
||||
@router.put("/language")
|
||||
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
|
||||
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
|
||||
async def langChange(session: SessionDep, current_user: CurrentUser, language: UserLanguage):
|
||||
lang = language.language
|
||||
if lang not in ["zh-CN", "en"]:
|
||||
@@ -184,7 +184,7 @@ async def langChange(session: SessionDep, current_user: CurrentUser, language: U
|
||||
session.commit()
|
||||
|
||||
@router.patch("/pwd/{id}")
|
||||
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
|
||||
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
|
||||
async def pwdReset(session: SessionDep, current_user: CurrentUser, id: int):
|
||||
if not current_user.isAdmin:
|
||||
raise HTTPException('only for admin')
|
||||
@@ -194,7 +194,7 @@ async def pwdReset(session: SessionDep, current_user: CurrentUser, id: int):
|
||||
session.commit()
|
||||
|
||||
@router.put("/pwd")
|
||||
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
|
||||
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
|
||||
async def pwdUpdate(session: SessionDep, current_user: CurrentUser, editor: PwdEditor):
|
||||
db_user: UserModel = get_db_user(session=session, user_id=current_user.id)
|
||||
if not verify_md5pwd(editor.pwd, db_user.password):
|
||||
|
||||
@@ -22,7 +22,7 @@ def get_user_by_account(*, session: Session, account: str) -> BaseUserDTO | None
|
||||
return None
|
||||
return BaseUserDTO.model_validate(db_user.model_dump())
|
||||
|
||||
#@cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="user_id")
|
||||
@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)
|
||||
userInfo = UserInfoDTO.model_validate(db_user.model_dump())
|
||||
@@ -58,7 +58,7 @@ async def user_ws_options(session: Session, uid: int, trans: Optional[I18n] = No
|
||||
for id, name in result.all()
|
||||
]
|
||||
|
||||
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
|
||||
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
|
||||
async def single_delete(session: SessionDep, id: int):
|
||||
user_model: UserModel = get_db_user(session = session, user_id = id)
|
||||
del_stmt = sqlmodel_delete(UserWsModel).where(UserWsModel.uid == id)
|
||||
@@ -66,6 +66,6 @@ async def single_delete(session: SessionDep, id: int):
|
||||
session.delete(user_model)
|
||||
session.commit()
|
||||
|
||||
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
|
||||
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
|
||||
async def clean_user_cache(id: int):
|
||||
SQLBotLogUtil.info(f"User cache for [{id}] has been cleaned")
|
||||
|
||||
@@ -6,13 +6,11 @@ import icon_done_outlined from '@/assets/svg/icon_done_outlined.svg'
|
||||
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
|
||||
import { userApi } from '@/api/auth'
|
||||
import { ElMessage } from 'element-plus-secondary'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
|
||||
const userStore = useUserStore()
|
||||
const { t } = useI18n()
|
||||
const router = useRouter()
|
||||
defineProps({
|
||||
collapse: { type: [Boolean], required: true },
|
||||
})
|
||||
@@ -46,7 +44,6 @@ const handleDefaultWorkspaceChange = (item: any) => {
|
||||
currentWorkspace.value = { id: item.id, name: item.name }
|
||||
userApi.ws_change(item.id).then(() => {
|
||||
ElMessage.success(t('common.switch_success'))
|
||||
router.push('/chat/index')
|
||||
setTimeout(() => {
|
||||
location.reload()
|
||||
}, 300)
|
||||
|
||||
@@ -114,38 +114,6 @@ const router = createRouter({
|
||||
component: DashboardPreview,
|
||||
meta: { title: 'DashboardPreview', icon: 'dashboard' },
|
||||
},
|
||||
/* {
|
||||
path: "/setting",
|
||||
component: Layout,
|
||||
redirect: "/setting/index",
|
||||
children: [
|
||||
{
|
||||
path: "index",
|
||||
name: "setting",
|
||||
component: setting,
|
||||
meta: { title: "Settings", icon: "setting" },
|
||||
},
|
||||
],
|
||||
}, */
|
||||
// {
|
||||
// path: '/system',
|
||||
// component: Layout,
|
||||
// redirect: '/system/model',
|
||||
// children: [
|
||||
// /* {
|
||||
// path: "user",
|
||||
// name: "user",
|
||||
// component: User,
|
||||
// meta: { title: "User Management", icon: "icon_user" },
|
||||
// }, */
|
||||
// {
|
||||
// path: 'model',
|
||||
// name: 'model',
|
||||
// component: Model,
|
||||
// meta: { title: 'AI Model Configuration', icon: 'icon_ai' },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
{
|
||||
path: '/system',
|
||||
component: LayoutDsl,
|
||||
|
||||
@@ -26,10 +26,7 @@ export const watchRouter = (router: any) => {
|
||||
if (!userStore.getUid) {
|
||||
await userStore.info()
|
||||
}
|
||||
/* if (!wsCache.get('user.uid')) {
|
||||
await userStore.info()
|
||||
} */
|
||||
if (to.path === '/') {
|
||||
if (to.path === '/' || accessCrossPermission(to)) {
|
||||
next('/chat')
|
||||
return
|
||||
}
|
||||
@@ -41,6 +38,14 @@ export const watchRouter = (router: any) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const accessCrossPermission = (to: any) => {
|
||||
if (!to?.path) return false
|
||||
return (
|
||||
(to.path.startsWith('/system') && !userStore.isAdmin) ||
|
||||
(to.path.startsWith('/set') && !userStore.isSpaceAdmin)
|
||||
)
|
||||
}
|
||||
const loadXpackStatic = () => {
|
||||
if (document.getElementById('sqlbot_xpack_static')) {
|
||||
return Promise.resolve()
|
||||
|
||||
Reference in New Issue
Block a user