From 1e130223a354cc22c0ba0fb0913e88026b390e5f Mon Sep 17 00:00:00 2001 From: junjun Date: Thu, 16 Jul 2026 17:09:08 +0800 Subject: [PATCH] refactor: Optimize the type of permission field --- .../versions/071_modify_permission_jsonb.py | 45 +++++++++++++ backend/apps/datasource/crud/permission.py | 63 +++++++++++-------- backend/pyproject.toml | 5 +- 3 files changed, 86 insertions(+), 27 deletions(-) create mode 100644 backend/alembic/versions/071_modify_permission_jsonb.py diff --git a/backend/alembic/versions/071_modify_permission_jsonb.py b/backend/alembic/versions/071_modify_permission_jsonb.py new file mode 100644 index 00000000..0798f0a1 --- /dev/null +++ b/backend/alembic/versions/071_modify_permission_jsonb.py @@ -0,0 +1,45 @@ +"""071_modify_permission_jsonb + +Revision ID: a2e2ecfa5a9c +Revises: 070a1b2c3d4e5 +Create Date: 2026-07-16 16:56:47.093944 + +""" +from alembic import op +import sqlalchemy as sa +import sqlmodel.sql.sqltypes +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = 'a2e2ecfa5a9c' +down_revision = '070a1b2c3d4e5' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('ds_rules', 'permission_list', + existing_type=sa.Text(), + type_=postgresql.JSONB(astext_type=sa.Text()), + existing_nullable=True, + postgresql_using='permission_list::jsonb') + op.alter_column('ds_rules', 'user_list', + existing_type=sa.Text(), + type_=postgresql.JSONB(astext_type=sa.Text()), + existing_nullable=True, + postgresql_using='permission_list::jsonb') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('ds_rules', 'permission_list', + existing_type=postgresql.JSONB(astext_type=sa.Text()), + type_=sa.Text(), + existing_nullable=True) + op.alter_column('ds_rules', 'user_list', + existing_type=postgresql.JSONB(astext_type=sa.Text()), + type_=sa.Text(), + existing_nullable=True) + # ### end Alembic commands ### diff --git a/backend/apps/datasource/crud/permission.py b/backend/apps/datasource/crud/permission.py index 3e38d044..dfa56c75 100644 --- a/backend/apps/datasource/crud/permission.py +++ b/backend/apps/datasource/crud/permission.py @@ -1,7 +1,7 @@ import json from typing import List, Optional -from sqlalchemy import and_ +from sqlalchemy import and_, cast, or_ 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 @@ -9,6 +9,7 @@ from sqlbot_xpack.permissions.models.ds_rules import DsRules from apps.datasource.crud.row_permission import transFilterTree from apps.datasource.models.datasource import CoreDatasource, CoreField, CoreTable from common.core.deps import CurrentUser, SessionDep +from sqlalchemy.dialects.postgresql import JSONB def get_row_permission_filters(session: SessionDep, current_user: CurrentUser, ds: CoreDatasource, @@ -22,7 +23,7 @@ def get_row_permission_filters(session: SessionDep, current_user: CurrentUser, d filters = [] if is_normal_user(current_user): - contain_rules = session.query(DsRules).all() + # contain_rules = session.query(DsRules).all() for table in table_list: row_permissions = session.query(DsPermission).filter( and_(DsPermission.table_id == table.id, DsPermission.type == 'row')).all() @@ -30,16 +31,24 @@ def get_row_permission_filters(session: SessionDep, current_user: CurrentUser, d if row_permissions is not None: for permission in row_permissions: # check permission and user in same rules - flag = False - for r in contain_rules: - p_list = json.loads(r.permission_list) - u_list = json.loads(r.user_list) - if p_list is not None and u_list is not None and permission.id in p_list and ( - current_user.id in u_list or f'{current_user.id}' in u_list): - flag = True - break - if flag: + 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)) + + # flag = False + # for r in contain_rules: + # p_list = json.loads(r.permission_list) + # u_list = json.loads(r.user_list) + # if p_list is not None and u_list is not None and permission.id in p_list and ( + # current_user.id in u_list or f'{current_user.id}' in u_list): + # flag = True + # break + # if flag: + # res.append(transRecord2DTO(session, permission)) where_str = transFilterTree(session, current_user, res, ds) if where_str: filters.append({"table": table.table_name, "filter": where_str}) @@ -54,22 +63,26 @@ def get_column_permission_fields(session: SessionDep, current_user: CurrentUser, if column_permissions is not None: for permission in column_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() - flag = False - for r in contain_rules: - p_list = json.loads(r.permission_list) - u_list = json.loads(r.user_list) - if p_list is not None and u_list is not None and permission.id in p_list and ( - current_user.id in u_list or f'{current_user.id}' in u_list): - flag = True - break - if flag: + 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: permission_list = json.loads(permission.permissions) fields = filter_list(fields, permission_list) + + # flag = False + # for r in contain_rules: + # p_list = json.loads(r.permission_list) + # u_list = json.loads(r.user_list) + # if p_list is not None and u_list is not None and permission.id in p_list and ( + # current_user.id in u_list or f'{current_user.id}' in u_list): + # flag = True + # break + # if flag: + # permission_list = json.loads(permission.permissions) + # fields = filter_list(fields, permission_list) return fields diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 79093eb2..1c38a592 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -39,7 +39,7 @@ dependencies = [ "pyyaml (>=6.0.2,<7.0.0)", "fastapi-mcp (>=0.3.4,<0.4.0)", "tabulate>=0.9.0", - "sqlbot-xpack>=0.0.5.27,<0.0.6.0", + "sqlbot-xpack>=0.0.5.32,<0.0.6.0", "fastapi-cache2>=0.2.2", "sqlparse>=0.5.3", "redis>=6.2.0", @@ -55,7 +55,8 @@ dependencies = [ "sqlglot>=28.6.0", "numpy==2.3.5", "pyhive[hive_pure_sasl]>=0.7.0", - "thrift-sasl" + "thrift-sasl", + "dbutils>=3.1.2", ] [project.optional-dependencies]