191 lines
11 KiB
Java
191 lines
11 KiB
Java
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>
|
||
* isAll=1 → inherit_flag=true:子孙组在 hasModulePermission 判定时沿祖先链自动继承该模块权限(逻辑继承,不物理写子组);<br>
|
||
* 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);
|
||
}
|