import json from typing import List, Optional from sqlalchemy import and_ 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 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 def get_row_permission_filters(session: SessionDep, current_user: CurrentUser, ds: CoreDatasource, tables: Optional[list] = None, single_table: Optional[CoreTable] = None): if single_table: table_list = [session.get(CoreTable, single_table.id)] else: table_list = session.query(CoreTable).filter( and_(CoreTable.ds_id == ds.id, CoreTable.table_name.in_(tables)) ).all() filters = [] if is_normal_user(current_user): for table in table_list: row_permissions = session.query(DsPermission).filter( and_(DsPermission.table_id == table.id, DsPermission.type == 'row')).all() contain_rules = session.query(DsRules).all() res: List[PermissionDTO] = [] 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 if flag: res.append(transRecord2DTO(session, permission)) where_str = transFilterTree(session, res, ds) filters.append({"table": table.table_name, "filter": where_str}) return filters def get_column_permission_fields(session: SessionDep, current_user: CurrentUser, table: CoreTable, fields: list[CoreField]): if is_normal_user(current_user): column_permissions = session.query(DsPermission).filter( and_(DsPermission.table_id == table.id, DsPermission.type == 'column')).all() contain_rules = session.query(DsRules).all() 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 if flag: permission_list = json.loads(permission.permissions) fields = filter_list(fields, permission_list) return fields def is_normal_user(current_user: CurrentUser): return current_user.id != 1 def filter_list(list_a, list_b): id_to_invalid = {} for b in list_b: if not b['enable']: id_to_invalid[b['field_id']] = True return [a for a in list_a if not id_to_invalid.get(a.id, False)]