Files
UserBaseService/src/main/java/com/yunhai/userbase/service/IGroupAuthzService.java
T
chenxing 99414e2887
ci-userbase-service / build-and-push (push) Successful in 43s
推送订阅添加批量删除功能
2026-08-20 09:31:50 +08:00

191 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.yunhai.userbase.service;
import com.yunhai.platform.utils.model.BoaModule;
import com.yunhai.userbase.model.groupauthz.*;
import java.util.List;
/**
* @author chenx
* @date 2026/7/23
* @description 组应用权限服务(应用开通 + 组授权 + 权限判定)。<br>
*/
public interface IGroupAuthzService {
/**
* 功能1回显:查询系统全量应用列表,并标记该组已开通的应用(checked)。<br>
*
* @param groupId 组ID
* @return 全量应用列表(含开通勾选状态)
*/
List<GroupAppVo> listGroupApps(Integer groupId);
/**
* 功能1保存:全量覆盖式更新组的应用开通记录(先删旧记录再批量插入)。<br>
* 被取消开通的应用,同步清理该组在其模块上的权限记录,避免残留脏数据。<br>
*
* @param request 组ID + 勾选的应用ID全量列表
*/
void assignAppsToGroup(GroupAppAssignRequest request);
/**
* 功能2数据加载:查询该组已开通的应用及其模块树,并回显勾选状态与子组继承开关。<br>
* 仅返回 sys_group_app_rel 中有记录的应用;未开通的应用不显示。<br>
*
* @param groupId 组ID
* @return 已开通应用列表(含模块权限树)
*/
List<GroupAuthzAppVo> findGroupAppsWithModules(Integer groupId);
/**
* 功能2数据加载(按应用分类分组版):与 {@link #findGroupAppsWithModules(Integer)} 数据一致,<br>
* 但按应用类型分类聚合,便于组授权页面按分类面板展示。<br>
* 返回全部分类(含空数组),保证前端分类筛选下拉完整。<br>
*
* @param groupId 组ID
* @return 按应用分类分组的已开通应用列表
*/
List<GroupAuthzCategoryVo> findGroupAppsWithModulesByCategory(Integer groupId);
/**
* 功能2保存:全量覆盖式更新组的模块权限。<br>
* 有旧记录则更新 inheritFlag,无则新增,不在传入列表中的旧记录物理删除。<br>
*
* @param request 组ID + 勾选的模块权限全量列表(moduleId + inheritFlag)
*/
void saveModulePermissions(GroupModulePermRequest request);
/**
* 权限判定(供登录/拦截器使用):判断用户对某模块是否有权限。<br>
* 规则:用户任一所属组,沿祖先链回溯——自身显式勾选即通过;祖先勾选且 inheritFlag=true 即通过。<br>
* 前置校验:该所属组必须已开通模块所属应用(最终权限 = 继承的模块权限 ∩ 该组已开通的应用)。<br>
* 角色授权并集:用户经「启用状态」业务角色获得该模块授权也通过,且不要求组已开通模块所属应用;禁用角色不参与判定。<br>
*
* @param userId 用户ID
* @param moduleId 模块ID
* @return true=有权限
*/
boolean hasModulePermission(Integer userId, Integer moduleId);
/**
* 权限一览:查询指定组下的直接用户列表(不含子组,不分页)。<br>
*
* @param groupId 组ID
* @return 用户列表
*/
List<UserPermissionUserVo> findGroupUsers(Integer groupId);
/**
* 权限一览:全局搜索用户(按账号/姓名/身份证模糊、手机号精确匹配),不分页。<br>
* 返回用户及其主归属部门/组织路径。
*
* @param keyword 搜索关键字
* @return 用户列表
*/
List<UserPermissionUserVo> searchUsers(String keyword);
/**
* 权限一览:根据用户ID聚合该用户的全部已授权应用模块树。<br>
* 只返回<b>有授权模块</b>的应用,并按应用类型分组;无授权的应用类型和应用不显示。<br>
* 权限判定复用 {@link #hasModulePermission(Integer, Integer)} 的祖先链继承逻辑。<br>
* 角色授权并集:最终模块权限 = 组授权模块 ∪ 启用角色授权模块;<br>
* 最终应用范围 = 组开通应用 ∪ 角色模块所属应用(角色模块不要求组必须先开通应用)。<br>
*
* @param groupId 组ID(上下文,可选;目前仅用于校验用户存在性,实际聚合以 userId 为准)
* @param userId 用户ID
* @return 按应用类型分组的已授权应用模块树
*/
List<UserPermissionCategoryVo> findUserPermissionTree(Integer groupId, Integer userId);
/**
* 权限一览:查询用户所属的业务角色列表(中间下方「所属角色」区域展示用)。<br>
* 返回该用户绑定的全部角色(含禁用角色,disabled 字段标记),普通角色回填所属应用名称。<br>
*
* @param userId 用户ID
* @return 用户所属角色列表
*/
List<UserRoleVo> findUserRoles(Integer userId);
/**
* 权限一览:查询用户所属部门树(左侧上方「所属部门」区域展示用)。<br>
* 树仅由「用户直接归属的组 + 其全部祖先组」构成(如:云平台-学校中学-语文组),
* 多个归属组时合并为一棵树(公共祖先只出现一次)。<br>
*
* @param userId 用户ID
* @return 所属部门树(根节点列表);用户无组归属时返回空列表
*/
List<UserGroupNodeVo> findUserGroupTree(Integer userId);
/**
* 开放接口专用:查询用户在<b>指定调用方应用</b>下的已授权模块(扁平化 BoaModule 列表)。<br>
* 与 {@link #findUserPermissionTree(Integer, Integer)} 的核心差别:<br>
* - 后者返回用户在全部已开通应用下的权限聚合(供管理端权限一览使用);<br>
* - 本方法只返回 {@code appId} 对应这一个应用下的模块,所有 SQL/集合构建均限定该应用(数据库层面过滤)。<br>
* <br>
* 上下文组(schId)语义与开放接口一致:schId 非空=只认该组链路;schId 为空=取用户主学校组(若仍空=用户主归属组 id)。<br>
* 超级管理员:不做组/继承判定,直接返回该应用下全部模块(但仍只返回该应用,不会跨应用返回)。<br>
* 角色授权并集:最终权限 = 组授权模块 ∪ 启用角色下属于该应用的模块(逻辑与权限一览保持一致)。
*
* @param appId 调用方应用ID(必填;查不到或该应用无开通=返回空列表)
* @param schId 学校/组上下文(可选;为 null 时按"主学校→主归属组"规则推断)
* @param userId 用户ID(必填)
* @return 该应用下用户有权限的模块(扁平化;无权限时返回空列表)
*/
List<BoaModule> findUserModulesForApp(Integer appId, Integer schId, Integer userId);
// ===================== 新增:树节点式增量授权(供左侧树 + 右侧 appAuthzList 的勾选交互) =====================
/**
* 获取某组「已开通的应用ID列表」,供前端右侧应用清单回显勾选状态。<br>
* <b>实现思路</b>:应用开通「不继承」(见 SysGroupAppRel 设计)——直接查 sys_group_app_rel 中 group_id=nodeId 的记录,<br>
* 返回其 app_id 集合;<b>不</b>沿祖先链回填父组开通的应用(父组开通不代表子组自动拥有)。<br>
* 与现有 GroupAppList(返回全量应用 + checked)的区别:本接口只返回已选 id 列表,更轻量,适合做勾选回显。
*
* @param nodeId 左侧树点击的组节点ID
* @return 该组已开通的应用ID列表(无则空列表)
*/
List<Integer> findAuthorizedAppIds(Integer nodeId);
/**
* 增量设置某组的应用开通/取消(对应前端「应用多选框」勾选/取消)。<br>
* <b>入参</b>:{@link SchoolAppAuthzRequest} 封装 schid / appids(逗号分隔字符串) / mode。<br>
* <b>实现思路</b>:<br>
* - mode=0(追加/APPEND):对 appids 中每个应用,若 sys_group_app_rel 尚无记录则插入(已存在则跳过,幂等)。<br>
* - mode=2(删除/DELETE):对每个应用删除开通记录,并<b>同步清理该组在该应用下模块的权限残留</b>(与现有 assignAppsToGroup 取消开通时行为一致,避免脏数据)。<br>
* - 应用开通「不继承」,故<b>仅操作传入的 schId 自身,不做子组级联</b>。<br>
* - mode=1(覆盖) 不适用于单条增量,直接拒绝。
*
* @param request 学校组应用授权请求(组ID + 应用ID字符串 + 操作模式)
*/
void setSchoolApps(SchoolAppAuthzRequest request);
/**
* 增量设置「组-应用-模块」的模块授权(对应前端「组授权」面板逐条勾选/取消)。<br>
* <b>实现思路</b>:逐条处理 items 列表(顺序即执行顺序,后者覆盖前者):<br>
* - mode=0(追加):对 (groupId, 展开后的 moduleId) upsert 一条 sys_group_module_perm,inherit_flag=isAll。<br>
* - mode=2(删除):删除对应权限记录。<br>
* - moduleId=0 表示「该应用下全部模块」,展开为应用下每个真实模块各写/删一条(不写 module_id=0 伪记录)。<br>
* - <b>isAll 的语义(重点)</b>:直接映射现有 sys_group_module_perm.inherit_flag 列。<br>
* &nbsp;&nbsp;isAll=1 → inherit_flag=true:子孙组在 hasModulePermission 判定时沿祖先链自动继承该模块权限(逻辑继承,不物理写子组);<br>
* &nbsp;&nbsp;isAll=0 → inherit_flag=false:仅本组生效。<br>
* 这与「应用不继承 / 模块可继承」的对称性一致,且复用现有权限判定逻辑,不破坏其他功能。<br>
* - 越权防护:模块必须属于该 appId;追加前要求该组已开通该应用(与现有 SaveModulePerms 边界一致)。<br>
* <br>
* <i>若产品实际想要「物理写子组」(子组各存一条 perm,而非逻辑继承),把 isAll=1 分支改成「对 groupId + 其全部子孙组分别 upsert」即可,详见实现类注释。</i>
*
* @param items 模块授权条目列表(groupId/appId/moduleId/mode/isAll)
*/
void setGroupModulePerms(List<GroupModuleAuthzItem> items);
/**
* 查询用户有权访问的应用ID集合(oapi 开放接口 getUserApp 权限过滤用)。<br>
* 规则与 {@link #hasModulePermission(Integer, Integer)} 对齐:<br>
* - 超级管理员:全部应用;<br>
* - 普通用户:用户所属组(沿祖先链)开通的应用 ∪ 启用角色模块所属应用。<br>
*
* @param userId 用户ID
* @return 有权应用ID列表(无则空列表)
*/
List<Integer> findUserAuthorizedAppIds(Integer userId);
}