SaasRoleMenuHandler.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. package com.persagy.account.manage;
  2. import java.util.ArrayList;
  3. import java.util.Comparator;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.stream.Collectors;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.stereotype.Component;
  9. import org.springframework.transaction.annotation.Transactional;
  10. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  11. import com.google.common.collect.Lists;
  12. import com.persagy.account.pojo.dto.SaasAccountRole;
  13. import com.persagy.account.pojo.dto.SaasFunction;
  14. import com.persagy.account.pojo.dto.SaasMenu;
  15. import com.persagy.account.pojo.dto.SaasProduct;
  16. import com.persagy.account.pojo.dto.SaasRole;
  17. import com.persagy.account.pojo.dto.SaasRoleMenu;
  18. import com.persagy.account.pojo.vo.auth.SaasMenuFunctionPageVO;
  19. import com.persagy.account.pojo.vo.auth.SaasMenuFunctionVO;
  20. import com.persagy.account.pojo.vo.menu.SaasMenuQueryVO;
  21. import com.persagy.account.pojo.vo.role.SaasRoleDeleteVO;
  22. import com.persagy.account.service.ISaasAccountRoleService;
  23. import com.persagy.account.service.ISaasFunctionService;
  24. import com.persagy.account.service.ISaasMenuService;
  25. import com.persagy.account.service.ISaasProductService;
  26. import com.persagy.account.service.ISaasRoleMenuService;
  27. import com.persagy.account.service.ISaasRoleService;
  28. import com.persagy.common.constant.SaasCommonConstant;
  29. import com.persagy.common.exception.BusinessException;
  30. import com.persagy.common.utils.StringUtil;
  31. import com.persagy.security.constant.CipherConstants;
  32. import cn.hutool.core.collection.CollectionUtil;
  33. /**
  34. * 角色菜单管理
  35. *
  36. * @version
  37. * @description
  38. * @company persagy
  39. * @author zhangqiankun
  40. * @since 2021年3月15日: 上午10:49:15
  41. */
  42. @Component
  43. public class SaasRoleMenuHandler {
  44. @Autowired
  45. private SaasAuthHandler saasAuthHandler;
  46. @Autowired
  47. private ISaasRoleService saasRoleService;
  48. @Autowired
  49. private ISaasMenuService saasMenuService;
  50. @Autowired
  51. private SaasProductHandler saasProductHandler;
  52. @Autowired
  53. private ISaasProductService saasProductService;
  54. @Autowired
  55. private ISaasFunctionService saasFunctionService;
  56. @Autowired
  57. private ISaasRoleMenuService saasRoleMenuService;
  58. @Autowired
  59. private ISaasAccountRoleService saasAccountRoleService;
  60. /**
  61. * 获取菜单权限树,权限过滤,需要判断视角,1-集团视角,2-项目视角 项目ID存在即为项目视角
  62. *
  63. * @param queryVO
  64. * @return
  65. */
  66. public List<SaasMenu> querySaasMenuTree(SaasMenuQueryVO queryVO) {
  67. // 获取此账号对应的菜单范围
  68. Map<String, String> menuAuth = this.saasAuthHandler.validAccountAuth(queryVO.getAccountId(), queryVO.getGroupCode());
  69. if (StringUtil.isNotBlank(menuAuth.get(CipherConstants.GROUP_CODE))) {
  70. queryVO.setGroupCode(menuAuth.get(CipherConstants.GROUP_CODE));
  71. }
  72. // 添加数据访问控制,账号可见域,0-所有集团项目,1-单集团所有项目(此时,集团编码需存在),2-其他
  73. String accountType = menuAuth.get(SaasCommonConstant.ACCOUNT_TYPE);
  74. // 账号所属,0-运维系统,1-业务系统账号
  75. String accountBelong = menuAuth.get(SaasCommonConstant.ACCOUNT_BELONG);
  76. List<SaasMenu> menuTree = null;
  77. if (SaasCommonConstant.STR_STATUS_0.equals(accountType) && SaasCommonConstant.STR_STATUS_0.equals(accountBelong)) {
  78. // 如果是运维系统的账号,accountType为0的情况下查询所有菜单权限,其余情况走表关联查询,为1时,后续可添加
  79. menuTree = this.querySaasMenuTree(null, null, queryVO.getProjectId(), queryVO.getAppId(), true, queryVO.isMenu());
  80. } else {
  81. menuTree = this.querySaasMenuTree(queryVO.getAccountId(), queryVO.getGroupCode(), queryVO.getProjectId(), queryVO.getAppId(), false, queryVO.isMenu());
  82. }
  83. return menuTree;
  84. }
  85. /**
  86. * 查询账号菜单功能权限树,菜单定义和角色定义编码相同,所以这里应该同步传递
  87. *
  88. * @param accountId
  89. * @param groupCode
  90. * @param projectId
  91. * @param appId
  92. * @param isAdmin 是否为超管 true-是,此为系统超管
  93. * @param isMenu 是否仅查询出菜单树,true-是
  94. * @return 空集合或数据菜单树
  95. */
  96. public List<SaasMenu> querySaasMenuTree(String accountId, String groupCode, String projectId, String appId, boolean isAdmin, boolean isMenu) {
  97. // 1.获取此账号对应菜单集合
  98. List<SaasMenu> menuTree = null;
  99. if (isAdmin) {
  100. LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper().appIdEq(appId).menuTypeEq(SaasCommonConstant.STR_STATUS_0).builderQueryWrapper();
  101. menuTree = this.saasMenuService.list(queryWrapper);
  102. } else {
  103. menuTree = this.saasMenuService.querySaasMenuTree(accountId, groupCode, appId, null, SaasCommonConstant.STATUS_1);
  104. }
  105. if (CollectionUtil.isEmpty(menuTree)) {
  106. return Lists.newArrayList();
  107. }
  108. // 2.转为菜单树
  109. List<SaasMenu> topMenus = new ArrayList<SaasMenu>();
  110. for (int i = menuTree.size() - 1; i >= 0; i--) {
  111. SaasMenu saasMenu = menuTree.get(i);
  112. if (StringUtil.isBlank(saasMenu.getParentId())) {
  113. topMenus.add(saasMenu);
  114. menuTree.remove(i);
  115. }
  116. }
  117. List<SaasMenu> parents = topMenus.stream().sorted(Comparator.comparing(SaasMenu::getMenuSort)).collect(Collectors.toList());
  118. this.setMenuChildrens(accountId, groupCode, projectId, menuTree, parents, isAdmin, !isMenu);
  119. return parents;
  120. }
  121. /**
  122. * 生成菜单树
  123. * @param accountId 为null时,isAdmin 为true
  124. * @param angle 1-集团视角,2-项目视角
  125. * @param groupCode
  126. * @param menuTree 为空时,会去查询,但是不会做权限过滤
  127. * @param parents
  128. * @param isAdmin 是否为超管 true-是
  129. * @param menuAndFun
  130. */
  131. public void setMenuChildrens(String accountId, String groupCode, String projectId, List<SaasMenu> menuTree, List<SaasMenu> parents, boolean isAdmin, boolean menuAndFun) {
  132. for (SaasMenu parent : parents) {
  133. if (StringUtil.isBlank(parent.getMenuId())) {
  134. parent.setMenuId(parent.getId());
  135. }
  136. if (StringUtil.isNotBlank(parent.getMenuUrl())) {
  137. this.saasProductHandler.queryMenuProductAuths(parent, accountId, groupCode, projectId, isAdmin, menuAndFun);
  138. }
  139. List<SaasMenu> childrens = null;
  140. if (menuTree == null) {
  141. LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper().parentIdEq(parent.getId())
  142. .menuTypeEq(parent.getMenuType()).appIdEq(parent.getAppId()).builderQueryWrapper();
  143. childrens = this.saasMenuService.list(queryWrapper.orderByAsc(SaasMenu::getMenuSort));
  144. childrens = CollectionUtil.isEmpty(childrens) ? Lists.newArrayList() : childrens;
  145. } else {
  146. childrens = new ArrayList<SaasMenu>();
  147. for (int i = menuTree.size() - 1; i >= 0; i--) {
  148. SaasMenu saasMenu = menuTree.get(i);
  149. if (parent.getMenuId().equals(saasMenu.getParentId())) {
  150. childrens.add(saasMenu);
  151. menuTree.remove(i);
  152. }
  153. }
  154. }
  155. parent.setChildrens(childrens);
  156. this.setMenuChildrens(accountId, groupCode, projectId, menuTree, childrens, isAdmin, menuAndFun);
  157. }
  158. }
  159. /**
  160. * 删除角色,级联删除账号角色,角色菜单的关联关系
  161. *
  162. * @param deleteVO
  163. */
  164. @Transactional
  165. public boolean deleteSaasRole(SaasRoleDeleteVO deleteVO) {
  166. LambdaQueryWrapper<SaasRole> updateWrapper = new SaasRole.Builder().createQueryWrapper().idEq(deleteVO.getId())
  167. .validEq(SaasCommonConstant.STATUS_1).builderQueryWrapper();
  168. boolean result = this.saasRoleService.remove(updateWrapper);
  169. if (result) {
  170. // 1.级联删除账号和角色关联关系
  171. LambdaQueryWrapper<SaasAccountRole> accountRoleWrapper = new SaasAccountRole.Builder().createQueryWrapper().roleIdEq(deleteVO.getId()).builderQueryWrapper();
  172. this.saasAccountRoleService.remove(accountRoleWrapper);
  173. // 2.级联删除角色和菜单的关联关系
  174. LambdaQueryWrapper<SaasRoleMenu> roleMenuWrapper = new SaasRoleMenu.Builder().createQueryWrapper().roleIdEq(deleteVO.getId()).builderQueryWrapper();
  175. this.saasRoleMenuService.remove(roleMenuWrapper);
  176. }
  177. return result;
  178. }
  179. /**
  180. * 删除菜单,级联删除,角色、菜单、功能三者关联关系数据
  181. *
  182. * @param menuId
  183. * @param productId
  184. * @param updateProduct 是否更新产品关联菜单字段
  185. * @return
  186. */
  187. @Transactional
  188. public boolean deleteSaasMenu(String menuId, String productId, boolean updateProduct) {
  189. if (StringUtil.isBlank(menuId)) {
  190. return true;
  191. }
  192. boolean result = this.saasMenuService.removeById(menuId);
  193. if (result) {
  194. if (updateProduct) {
  195. // 更新产品是否已关联菜单字段
  196. SaasProduct saasProduct = new SaasProduct();
  197. saasProduct.setId(productId);
  198. saasProduct.setProductMenu(SaasCommonConstant.STR_STATUS_0);
  199. result = this.saasProductService.updateById(saasProduct);
  200. }
  201. // 1.删除此菜单下功能
  202. LambdaQueryWrapper<SaasFunction> funWrapper = new SaasFunction.Builder().createQueryWrapper().menuIdEq(menuId).builderQueryWrapper();
  203. this.saasFunctionService.remove(funWrapper);
  204. // 2.删除此功能对应的菜单、角色关系数据
  205. LambdaQueryWrapper<SaasRoleMenu> roleMenuWrapper = new SaasRoleMenu.Builder().createQueryWrapper().menuIdEq(menuId).builderQueryWrapper();
  206. this.saasRoleMenuService.remove(roleMenuWrapper);
  207. // 级联删除此菜单下的所有子菜单和对应的功能点信息
  208. this.casDeleteChildrenMenu(menuId);
  209. return true;
  210. }
  211. throw new BusinessException("菜单信息删除失败");
  212. }
  213. /**
  214. * 级联删除所有的子菜单和对应的权限信息
  215. * @param menuId
  216. * @param productId
  217. */
  218. @Transactional
  219. public void casDeleteChildrenMenu(String parentId) {
  220. LambdaQueryWrapper<SaasMenu> queryWrapper = new SaasMenu.Builder().createQueryWrapper().parentIdEq(parentId).builderQueryWrapper();
  221. List<SaasMenu> saasMenus = this.saasMenuService.list(queryWrapper.select(SaasMenu::getId, SaasMenu::getProductId));
  222. if (CollectionUtil.isEmpty(saasMenus)) {
  223. return;
  224. }
  225. for (SaasMenu saasMenu : saasMenus) {
  226. boolean updateProduct = false;
  227. if (StringUtil.isNotBlank(saasMenu.getProductId())) {
  228. // 判断此产品是否仅被此菜单使用
  229. queryWrapper = new SaasMenu.Builder().createQueryWrapper().productId(saasMenu.getProductId()).builderQueryWrapper();
  230. int count = this.saasMenuService.count(queryWrapper);
  231. if (count < 2) {
  232. updateProduct = true;
  233. }
  234. }
  235. // 删除此菜单
  236. this.deleteSaasMenu(saasMenu.getId(), saasMenu.getProductId(), updateProduct);
  237. }
  238. }
  239. /**
  240. * 删除功能,级联删除菜单、功能关系
  241. *
  242. * @param funId
  243. * @return
  244. */
  245. @Transactional
  246. public boolean deleteSaasFunction(String funId) {
  247. LambdaQueryWrapper<SaasFunction> queryWrapper = new SaasFunction.Builder().createQueryWrapper().idEq(funId).builderQueryWrapper();
  248. boolean result = this.saasFunctionService.remove(queryWrapper);
  249. if (result) {
  250. // 1.删除此功能对应的菜单、角色关系数据
  251. LambdaQueryWrapper<SaasRoleMenu> roleMenuWrapper = new SaasRoleMenu.Builder().createQueryWrapper().functionIdEq(funId).builderQueryWrapper();
  252. this.saasRoleMenuService.remove(roleMenuWrapper);
  253. }
  254. return result;
  255. }
  256. /**
  257. * 先删后新增,仅删除此账号角色下的所有菜单功能点的关联关系,并重新新增
  258. *
  259. * @param batchVO
  260. * @return
  261. */
  262. @Transactional
  263. public boolean resetSaasRoleMenu(String groupCode, String roleId, List<SaasMenuFunctionVO> auths) {
  264. LambdaQueryWrapper<SaasRoleMenu> roleMenuWrapper = new SaasRoleMenu.Builder().createQueryWrapper().roleIdEq(roleId).builderQueryWrapper();
  265. this.saasRoleMenuService.remove(roleMenuWrapper);
  266. // 1.批量新增
  267. boolean result = this.saasRoleMenuService.batchCreateSaasRoleMenu(groupCode, roleId, auths);
  268. if (!result) {
  269. throw new BusinessException("重置角色菜单功能权限失败");
  270. }
  271. return result;
  272. }
  273. /**
  274. * 创建角色,同时添加菜单关联关系
  275. * @param saasRole
  276. * @param auths
  277. * @return
  278. */
  279. @Transactional
  280. public boolean createSaasRole(SaasRole saasRole, List<SaasMenuFunctionVO> auths) {
  281. // 1.创建角色信息
  282. boolean result = this.saasRoleService.save(saasRole);
  283. if (result && CollectionUtil.isNotEmpty(auths)) {
  284. // 2.删除并创建角色信息
  285. this.resetSaasRoleMenu(saasRole.getGroupCode(), saasRole.getId(), auths);
  286. }
  287. return result;
  288. }
  289. /**
  290. * 更新角色,同时更新菜单关联关系
  291. * @param saasRole
  292. * @param auths
  293. * @return
  294. */
  295. @Transactional
  296. public boolean updateSaasRole(SaasRole saasRole, List<SaasMenuFunctionVO> auths) {
  297. boolean result = this.saasRoleService.updateById(saasRole);
  298. if (result && CollectionUtil.isNotEmpty(auths)) {
  299. this.resetSaasRoleMenu(saasRole.getGroupCode(), saasRole.getId(), auths);
  300. }
  301. return result;
  302. }
  303. /**
  304. * 删除新增角色菜单页面关联关系
  305. * @param groupCode
  306. * @param roleId
  307. * @param auths
  308. * @return
  309. */
  310. @Transactional
  311. public boolean resetSaasRoleMenuPage(String groupCode, String roleId, List<SaasMenuFunctionPageVO> auths) {
  312. LambdaQueryWrapper<SaasRoleMenu> roleMenuWrapper = new SaasRoleMenu.Builder().createQueryWrapper().roleIdEq(roleId).builderQueryWrapper();
  313. this.saasRoleMenuService.remove(roleMenuWrapper);
  314. // 1.批量新增
  315. boolean result = this.saasRoleMenuService.batchCreateSaasRoleMenuPage(groupCode, roleId, auths);
  316. if (!result) {
  317. throw new BusinessException("重置角色菜单页面功能权限失败");
  318. }
  319. return result;
  320. }
  321. }