From a93ad7decfed3d03505f72c76d4e3133386617bb Mon Sep 17 00:00:00 2001 From: junjun Date: Thu, 24 Jul 2025 10:20:22 +0800 Subject: [PATCH] feat: datasource table preview add permission --- backend/apps/datasource/crud/datasource.py | 36 ++++++++++++++++--- .../apps/datasource/crud/row_permission.py | 7 ++-- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/backend/apps/datasource/crud/datasource.py b/backend/apps/datasource/crud/datasource.py index 9a7e8a6f..74933ed1 100644 --- a/backend/apps/datasource/crud/datasource.py +++ b/backend/apps/datasource/crud/datasource.py @@ -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) diff --git a/backend/apps/datasource/crud/row_permission.py b/backend/apps/datasource/crud/row_permission.py index b9b84558..84f79cca 100644 --- a/backend/apps/datasource/crud/row_permission.py +++ b/backend/apps/datasource/crud/row_permission.py @@ -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 (