基于ABAP或SQL的用户权限限制表行匹配扁平化实现方案
解决方案
通用算法逻辑(跨语言适用)
核心思路是把硬编码的IF判断全部替换为配置化逻辑,仅需要提前维护两个基础配置即可:
- 角色-限制映射表:即你现有的
lt_restrictions,每行存储「角色ID + 对应限制项ID」即可 - 可选配置:角色优先级表(如果需要处理权限冲突,比如高权限角色规则优先于低权限角色,可新增该配置,数字越小优先级越高)
针对你描述的业务场景,有两种成熟的冲突处理策略可选:
- 多角色限制取交集:符合你举的例子,多角色叠加后仅所有角色共同要求禁用的项才会最终禁用
// 1. 提取当前用户所有角色ID的集合 user_role_ids = [r.id for r in mt_user_roles] // 2. 过滤出所有匹配用户角色的限制项 matched_restrictions = [r for r in lt_restrictions if r.role_id in user_role_ids] // 3. 统计每个限制项出现的次数,出现次数等于用户拥有角色总数的即为所有角色共同要求的限制 restriction_count = count_by_group(matched_restrictions, group_key='restriction_id') for item in restriction_count: if item.count == len(user_role_ids): ms_restrictions[item.restriction_id] = '禁用标记' else: ms_restrictions[item.restriction_id] = '启用标记'
- 最高优先级角色规则优先:适合权限越高限制越少的场景,直接取用户最高权限角色对应的限制规则即可,计算效率更高
// 1. 把用户拥有的角色按优先级升序排序,第一位就是最高优先级角色 sorted_roles = sort(mt_user_roles, sort_key='priority', order='asc') highest_role = sorted_roles[0] // 2. 直接过滤出最高优先级角色对应的所有限制项赋值即可 matched_restrictions = [r for r in lt_restrictions if r.role_id == highest_role.id] for r in matched_restrictions: ms_restrictions[r.restriction_id] = '禁用标记'
ABAP环境专属实现方案
你提到的RANGE表、SQL查询都可以实现,完全不需要嵌套循环和硬编码每个限制项的IF判断:
实现步骤
- 先把用户拥有的角色转成RANGE表,用于后续过滤
DATA lr_role TYPE RANGE OF string. DATA ls_role LIKE LINE OF lr_role. LOOP AT mt_user_roles INTO DATA(ls_user_role). ls_role-sign = 'I'. ls_role-option = 'EQ'. ls_role-low = ls_user_role-low. " 对应你存储的角色ID:program_manager、entry_user等 APPEND ls_role TO lr_role. ENDLOOP.
- 过滤匹配的限制项,用动态赋值直接给结果结构赋值,新增限制项无需修改代码
" 先清空原有标记 CLEAR ms_restrictions. " 如果你用交集规则,用以下逻辑 LOOP AT lt_restrictions INTO DATA(ls_restriction) WHERE role IN @lr_role. " 动态匹配结果结构的对应字段,无需硬编码字段名 ASSIGN COMPONENT ls_restriction-restriction_id OF STRUCTURE ms_restrictions TO FIELD-SYMBOL(<fs_flag>). IF <fs_flag> IS ASSIGNED. " 统计当前限制项是否属于所有用户角色的公共限制 DATA(lv_role_count) = REDUCE i( INIT s = 0 FOR <ur> IN mt_user_roles WHERE ( low = ls_restriction-role ) NEXT s = s + 1 ). IF lv_role_count = lines( mt_user_roles ). <fs_flag> = 'X'. ENDIF. ENDIF. ENDLOOP.
如果lt_restrictions是数据库表,还可以直接用SQL查询代替内表循环,性能更好:
SELECT restriction_id FROM zt_restriction " 替换为你的权限限制表名 INTO TABLE @DATA(lt_matched_restrict) WHERE role IN @lr_role. " 后续赋值逻辑和上面一致
内容的提问来源于stack exchange,提问作者Jim22150
相关产品推荐
相关产品推荐

