Skip to content

Commit e30ffb8

Browse files
committed
Merge branch 'main' of https://github.com/dataease/SQLBot
2 parents 95cfeed + 4687a1e commit e30ffb8

File tree

7 files changed

+53
-54
lines changed

7 files changed

+53
-54
lines changed

backend/apps/datasource/crud/datasource.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
from fastapi import HTTPException
66
from sqlalchemy import and_, text, cast, or_, func
77
from sqlalchemy.dialects.postgresql import JSONB
8-
from sqlbot_xpack.permissions.models.ds_permission import DsPermission
8+
from sqlbot_xpack.permissions.api.permission import transRecord2DTO
9+
from sqlbot_xpack.permissions.models.ds_permission import DsPermission, PermissionDTO
910
from sqlbot_xpack.permissions.models.ds_rules import DsRules
1011
from sqlmodel import select
1112

13+
from apps.datasource.crud.row_permission import transFilterTree
1214
from apps.datasource.utils.utils import aes_decrypt
1315
from apps.db.constant import DB
1416
from apps.db.db import get_engine, get_tables, get_fields, exec_sql
@@ -238,6 +240,9 @@ def updateField(session: SessionDep, field: CoreField):
238240

239241

240242
def preview(session: SessionDep, current_user: CurrentUser, id: int, data: TableObj):
243+
ds = session.query(CoreDatasource).filter(CoreDatasource.id == id).first()
244+
check_status(session, ds, True)
245+
241246
if data.fields is None or len(data.fields) == 0:
242247
return {"fields": [], "data": [], "sql": ''}
243248

@@ -261,20 +266,41 @@ def preview(session: SessionDep, current_user: CurrentUser, id: int, data: Table
261266
if fields is None or len(fields) == 0:
262267
return {"fields": [], "data": [], "sql": ''}
263268

264-
ds = session.query(CoreDatasource).filter(CoreDatasource.id == id).first()
265-
check_status(session, ds, True)
269+
# row permission tree
270+
row_permissions = session.query(DsPermission).filter(
271+
and_(DsPermission.table_id == data.table.id, DsPermission.type == 'row')).all()
272+
res: List[PermissionDTO] = []
273+
if row_permissions is not None:
274+
for permission in row_permissions:
275+
# check permission and user in same rules
276+
obj = session.query(DsRules).filter(
277+
and_(DsRules.permission_list.op('@>')(cast([permission.id], JSONB)),
278+
or_(DsRules.user_list.op('@>')(cast([f'{current_user.id}'], JSONB)),
279+
DsRules.user_list.op('@>')(cast([current_user.id], JSONB))))
280+
).first()
281+
if obj is not None:
282+
res.append(transRecord2DTO(session, permission))
283+
wheres = transFilterTree(session, res, ds)
284+
where = (' where ' + wheres) if wheres is not None and wheres != '' else ''
285+
266286
conf = DatasourceConf(**json.loads(aes_decrypt(ds.configuration))) if ds.type != "excel" else get_engine_config()
267287
sql: str = ""
268288
if ds.type == "mysql":
269-
sql = f"""SELECT `{"`, `".join(fields)}` FROM `{data.table.table_name}` LIMIT 100"""
289+
sql = f"""SELECT `{"`, `".join(fields)}` FROM `{data.table.table_name}`
290+
{where}
291+
LIMIT 100"""
270292
elif ds.type == "sqlServer":
271293
sql = f"""SELECT [{"], [".join(fields)}] FROM [{conf.dbSchema}].[{data.table.table_name}]
294+
{where}
272295
ORDER BY [{data.fields[0].field_name}]
273296
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY"""
274297
elif ds.type == "pg" or ds.type == "excel":
275-
sql = f"""SELECT "{'", "'.join(fields)}" FROM "{conf.dbSchema}"."{data.table.table_name}" LIMIT 100"""
298+
sql = f"""SELECT "{'", "'.join(fields)}" FROM "{conf.dbSchema}"."{data.table.table_name}"
299+
{where}
300+
LIMIT 100"""
276301
elif ds.type == "oracle":
277302
sql = f"""SELECT "{'", "'.join(fields)}" FROM "{conf.dbSchema}"."{data.table.table_name}"
303+
{where}
278304
ORDER BY "{data.fields[0].field_name}"
279305
OFFSET 0 ROWS FETCH NEXT 100 ROWS ONLY"""
280306
return exec_sql(ds, sql)

backend/apps/datasource/crud/row_permission.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
from typing import List, Dict
55

6-
from apps.datasource.models.datasource import CoreField, CoreDatasource
76
from sqlbot_xpack.permissions.models.ds_permission import PermissionTree, PermissionDTO
7+
8+
from apps.datasource.models.datasource import CoreField, CoreDatasource
9+
from apps.db.constant import DB
810
from common.core.deps import SessionDep
911

1012

@@ -48,7 +50,8 @@ def transTreeItem(session: SessionDep, item: Dict, ds: CoreDatasource) -> str |
4850
if field is None:
4951
return None
5052

51-
whereName = field.field_name
53+
db = DB.get_db(ds.type)
54+
whereName = db.prefix + field.field_name + db.suffix
5255
if item['filter_type'] == 'enum':
5356
if len(item['enum_value']) > 0:
5457
if ds['type'] == 'sqlServer' and (

backend/apps/system/api/user.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ async def ws_options(session: SessionDep, current_user: CurrentUser, trans: Tran
9595
return await user_ws_options(session, current_user.id, trans)
9696

9797
@router.put("/ws/{oid}")
98-
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
98+
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
9999
async def ws_change(session: SessionDep, current_user: CurrentUser, oid: int):
100100
ws_list: list[UserWs] = await user_ws_options(session, current_user.id)
101101
if not any(x.id == oid for x in ws_list):
@@ -137,7 +137,7 @@ async def create(session: SessionDep, creator: UserCreator):
137137
session.commit()
138138

139139
@router.put("")
140-
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="editor.id")
140+
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="editor.id")
141141
async def update(session: SessionDep, editor: UserEditor):
142142
user_model: UserModel = get_db_user(session = session, user_id = editor.id)
143143
origin_oid: int = user_model.oid
@@ -173,7 +173,7 @@ async def batch_del(session: SessionDep, id_list: list[int]):
173173
await single_delete(session, id)
174174

175175
@router.put("/language")
176-
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
176+
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
177177
async def langChange(session: SessionDep, current_user: CurrentUser, language: UserLanguage):
178178
lang = language.language
179179
if lang not in ["zh-CN", "en"]:
@@ -184,7 +184,7 @@ async def langChange(session: SessionDep, current_user: CurrentUser, language: U
184184
session.commit()
185185

186186
@router.patch("/pwd/{id}")
187-
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
187+
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
188188
async def pwdReset(session: SessionDep, current_user: CurrentUser, id: int):
189189
if not current_user.isAdmin:
190190
raise HTTPException('only for admin')
@@ -194,7 +194,7 @@ async def pwdReset(session: SessionDep, current_user: CurrentUser, id: int):
194194
session.commit()
195195

196196
@router.put("/pwd")
197-
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
197+
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="current_user.id")
198198
async def pwdUpdate(session: SessionDep, current_user: CurrentUser, editor: PwdEditor):
199199
db_user: UserModel = get_db_user(session=session, user_id=current_user.id)
200200
if not verify_md5pwd(editor.pwd, db_user.password):

backend/apps/system/crud/user.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def get_user_by_account(*, session: Session, account: str) -> BaseUserDTO | None
2222
return None
2323
return BaseUserDTO.model_validate(db_user.model_dump())
2424

25-
#@cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="user_id")
25+
@cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="user_id")
2626
async def get_user_info(*, session: Session, user_id: int) -> UserInfoDTO | None:
2727
db_user: UserModel = get_db_user(session = session, user_id = user_id)
2828
userInfo = UserInfoDTO.model_validate(db_user.model_dump())
@@ -58,14 +58,14 @@ async def user_ws_options(session: Session, uid: int, trans: Optional[I18n] = No
5858
for id, name in result.all()
5959
]
6060

61-
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
61+
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
6262
async def single_delete(session: SessionDep, id: int):
6363
user_model: UserModel = get_db_user(session = session, user_id = id)
6464
del_stmt = sqlmodel_delete(UserWsModel).where(UserWsModel.uid == id)
6565
session.exec(del_stmt)
6666
session.delete(user_model)
6767
session.commit()
6868

69-
#@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
69+
@clear_cache(namespace=CacheNamespace.AUTH_INFO, cacheName=CacheName.USER_INFO, keyExpression="id")
7070
async def clean_user_cache(id: int):
7171
SQLBotLogUtil.info(f"User cache for [{id}] has been cleaned")

frontend/src/components/layout/Workspace.vue

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ import icon_done_outlined from '@/assets/svg/icon_done_outlined.svg'
66
import icon_searchOutline_outlined from '@/assets/svg/icon_search-outline_outlined.svg'
77
import { userApi } from '@/api/auth'
88
import { ElMessage } from 'element-plus-secondary'
9-
import { useRouter } from 'vue-router'
109
import { useI18n } from 'vue-i18n'
1110
import { useUserStore } from '@/stores/user'
1211
1312
const userStore = useUserStore()
1413
const { t } = useI18n()
15-
const router = useRouter()
1614
defineProps({
1715
collapse: { type: [Boolean], required: true },
1816
})
@@ -46,7 +44,6 @@ const handleDefaultWorkspaceChange = (item: any) => {
4644
currentWorkspace.value = { id: item.id, name: item.name }
4745
userApi.ws_change(item.id).then(() => {
4846
ElMessage.success(t('common.switch_success'))
49-
router.push('/chat/index')
5047
setTimeout(() => {
5148
location.reload()
5249
}, 300)

frontend/src/router/index.ts

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -114,38 +114,6 @@ const router = createRouter({
114114
component: DashboardPreview,
115115
meta: { title: 'DashboardPreview', icon: 'dashboard' },
116116
},
117-
/* {
118-
path: "/setting",
119-
component: Layout,
120-
redirect: "/setting/index",
121-
children: [
122-
{
123-
path: "index",
124-
name: "setting",
125-
component: setting,
126-
meta: { title: "Settings", icon: "setting" },
127-
},
128-
],
129-
}, */
130-
// {
131-
// path: '/system',
132-
// component: Layout,
133-
// redirect: '/system/model',
134-
// children: [
135-
// /* {
136-
// path: "user",
137-
// name: "user",
138-
// component: User,
139-
// meta: { title: "User Management", icon: "icon_user" },
140-
// }, */
141-
// {
142-
// path: 'model',
143-
// name: 'model',
144-
// component: Model,
145-
// meta: { title: 'AI Model Configuration', icon: 'icon_ai' },
146-
// },
147-
// ],
148-
// },
149117
{
150118
path: '/system',
151119
component: LayoutDsl,

frontend/src/router/watch.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ export const watchRouter = (router: any) => {
2626
if (!userStore.getUid) {
2727
await userStore.info()
2828
}
29-
/* if (!wsCache.get('user.uid')) {
30-
await userStore.info()
31-
} */
32-
if (to.path === '/') {
29+
if (to.path === '/' || accessCrossPermission(to)) {
3330
next('/chat')
3431
return
3532
}
@@ -41,6 +38,14 @@ export const watchRouter = (router: any) => {
4138
}
4239
})
4340
}
41+
42+
const accessCrossPermission = (to: any) => {
43+
if (!to?.path) return false
44+
return (
45+
(to.path.startsWith('/system') && !userStore.isAdmin) ||
46+
(to.path.startsWith('/set') && !userStore.isSpaceAdmin)
47+
)
48+
}
4449
const loadXpackStatic = () => {
4550
if (document.getElementById('sqlbot_xpack_static')) {
4651
return Promise.resolve()

0 commit comments

Comments
 (0)