/*
|
* Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
|
*
|
* Redistribution and use in source and binary forms, with or without
|
* modification, are permitted provided that the following conditions are met:
|
*
|
* Redistributions of source code must retain the above copyright notice,
|
* this list of conditions and the following disclaimer.
|
* Redistributions in binary form must reproduce the above copyright
|
* notice, this list of conditions and the following disclaimer in the
|
* documentation and/or other materials provided with the distribution.
|
* Neither the name of the dreamlu.net developer nor the names of its
|
* contributors may be used to endorse or promote products derived from
|
* this software without specific prior written permission.
|
* Author: Chill 庄骞 (smallchill@163.com)
|
*/
|
package org.springblade.system.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import lombok.RequiredArgsConstructor;
|
import org.springblade.common.constant.CommonConstant;
|
import org.springblade.core.cache.utils.CacheUtil;
|
import org.springblade.core.log.exception.ServiceException;
|
import org.springblade.core.mp.base.BaseServiceImpl;
|
import org.springblade.core.tenant.TenantId;
|
import org.springblade.core.tool.api.R;
|
import org.springblade.core.tool.constant.BladeConstant;
|
import org.springblade.core.tool.utils.Func;
|
import org.springblade.core.tool.utils.StringUtil;
|
import org.springblade.system.cache.ParamCache;
|
import org.springblade.system.entity.*;
|
import org.springblade.system.mapper.TenantMapper;
|
import org.springblade.system.service.*;
|
import org.springblade.system.user.entity.User;
|
import org.springblade.system.user.enums.UserEnum;
|
import org.springblade.system.user.feign.IUserClient;
|
import org.springblade.system.vo.TenantVO;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
import static org.springblade.common.constant.TenantConstant.*;
|
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
|
|
/**
|
* 服务实现类
|
*
|
* @author Chill
|
*/
|
@Service
|
@RequiredArgsConstructor
|
public class TenantServiceImpl extends BaseServiceImpl<TenantMapper, Tenant> implements ITenantService {
|
|
private final TenantId tenantId;
|
private final IRoleService roleService;
|
private final IMenuService menuService;
|
private final IDeptService deptService;
|
private final IPostService postService;
|
private final IRoleMenuService roleMenuService;
|
private final IDictBizService dictBizService;
|
private final IUserClient userClient;
|
private final IStrategyService strategyService;
|
private final IUserPwdstrategyService userPwdstrategyService;
|
|
/**
|
* 获取是否允许自行控制三员是否开启
|
*/
|
@Value("${ssa.ssa-enable}")
|
private Boolean ssaEnable;
|
/**
|
* 获取默认三员管理员的名称
|
*/
|
@Value("#{'${ssa.ssa-names}'.split(',')}")
|
private List<String> ssaNames;
|
/**
|
* 三员管理菜单配置
|
*/
|
@Value("#{'${ssa.sys-menus}'.split(',')}")
|
private List<String> sysMenus;
|
@Value("#{'${ssa.sec-menus}'.split(',')}")
|
private List<String> secMenus;
|
@Value("#{'${ssa.audit-menus}'.split(',')}")
|
private List<String> auditMenus;
|
|
@Override
|
public IPage<Tenant> selectTenantPage(IPage<Tenant> page, Tenant tenant) {
|
return page.setRecords(baseMapper.selectTenantPage(page, tenant));
|
}
|
|
@Override
|
public Tenant getByTenantId(String tenantId) {
|
return getOne(Wrappers.<Tenant>query().lambda().eq(Tenant::getTenantId, tenantId));
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean submitTenant(TenantVO tenant) {
|
if (Func.isEmpty(tenant.getId())) {
|
// 获取到未删除租户总数,生成新的租户id
|
List<Tenant> tenants = baseMapper.selectList(Wrappers.<Tenant>query().lambda().eq(Tenant::getIsDeleted, BladeConstant.DB_NOT_DELETED));
|
List<String> codes = tenants.stream().map(Tenant::getTenantId).collect(Collectors.toList());
|
String tenantId = getTenantId(codes);
|
tenant.setTenantId(tenantId);
|
// 配置为false,并且前端传输的参数为1(未选择开启)就不需要创建三员
|
if(!this.ssaEnable && tenant.getSsaEnable()==1){
|
// 不开启三员管理时直接创建一个最高权限的管理员
|
Role role = new Role(tenantId,BladeConstant.TOP_PARENT_ID,"超级管理员",1,"admin",BladeConstant.DB_NOT_DELETED);
|
roleService.save(role);
|
// 新建租户对应的角色菜单权限
|
saveRoleMenus(role, MENU_CODES);
|
// 新建租户对应的默认部门
|
Dept dept = generateDept(tenantId, tenant);
|
deptService.save(dept);
|
// 新建租户对应的默认岗位
|
Post postInfo = generatePost(tenantId, 1, "admin", "管理员", 1);
|
postService.save(postInfo);
|
// 新建租户对应的默认业务字典
|
LinkedList<DictBiz> dictBizs = new LinkedList<>();
|
List<DictBiz> dictBizList = getDictBizs(tenantId, dictBizs);
|
dictBizService.saveBatch(dictBizList);
|
// 新建租户对应的默认管理用
|
User user = generateUser(tenantId, role, dept, postInfo);
|
// 先保存租户
|
boolean temp = super.saveOrUpdate(tenant);
|
// 创建用户
|
R<Boolean> result = userClient.saveUser(user);
|
//生成用户密码策略管理记录
|
if (!result.isSuccess()) {
|
throw new ServiceException(result.getMsg());
|
}
|
return temp;
|
}else {
|
// 新建租户对应的默认角色
|
List<Role> roles = new ArrayList<>();
|
Role roleSys = new Role(tenantId,BladeConstant.TOP_PARENT_ID,"系统管理员",1,this.ssaNames.get(0),BladeConstant.DB_NOT_DELETED);
|
Role roleSec = new Role(tenantId,BladeConstant.TOP_PARENT_ID,"安全管理员",2,this.ssaNames.get(1),BladeConstant.DB_NOT_DELETED);
|
Role roleAudit = new Role(tenantId,BladeConstant.TOP_PARENT_ID,"审计管理员",3,this.ssaNames.get(2),BladeConstant.DB_NOT_DELETED);
|
roles.add(roleSys);
|
roles.add(roleSec);
|
roles.add(roleAudit);
|
roleService.saveBatch(roles);
|
// 新建租户对应的角色菜单权限
|
saveRoleMenus(roleSys,this.sysMenus); //系统管理员角色菜单权限
|
saveRoleMenus(roleSec,this.secMenus); //安全管理员角色菜单权限
|
saveRoleMenus(roleAudit,this.auditMenus); //审计管理员角色菜单权限
|
// 新建租户对应的默认部门
|
Dept dept = generateDept(tenantId, tenant);
|
deptService.save(dept);
|
// 新建租户对应的默认岗位
|
Post postSys = generatePost(tenantId, 1, this.ssaNames.get(0), "系统管理员", 1);
|
Post postSec = generatePost(tenantId,1,this.ssaNames.get(1),"安全管理员",4);
|
Post postAudit = generatePost(tenantId,1,this.ssaNames.get(2),"审计管理员",5);
|
postService.saveBatch(Arrays.asList(postSys,postSec,postAudit));
|
// 新建租户对应的默认业务字典
|
LinkedList<DictBiz> dictBizs = new LinkedList<>();
|
List<DictBiz> dictBizList = getDictBizs(tenantId, dictBizs);
|
dictBizService.saveBatch(dictBizList);
|
// 新建租户对应的默认管理用户
|
User userSys = generateUser(tenantId, roleSys, dept, postSys);
|
User userSec = generateUser(tenantId,roleSec,dept,postSec);
|
User userAudit = generateUser(tenantId,roleAudit,dept,postAudit);
|
// 先保存租户
|
boolean temp = super.saveOrUpdate(tenant);
|
// 创建用户
|
R<Boolean> result = userClient.saveUserList(Arrays.asList(userSys,userSec,userAudit));
|
if (!result.isSuccess()) {
|
throw new ServiceException(result.getMsg());
|
}
|
return temp;
|
}
|
} else {
|
CacheUtil.clear(SYS_CACHE, tenant.getTenantId());
|
return super.saveOrUpdate(tenant);
|
}
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public boolean removeTenant(List<Long> ids) {
|
List<String> tenantIds = this.list(Wrappers.<Tenant>query().lambda().in(Tenant::getId, ids))
|
.stream().map(tenant -> Func.toStr(tenant.getTenantId())).distinct().collect(Collectors.toList());
|
CacheUtil.clear(SYS_CACHE, tenantIds);
|
if (tenantIds.contains(BladeConstant.ADMIN_TENANT_ID)) {
|
throw new ServiceException("不可删除管理租户!");
|
}
|
boolean tenantTemp = this.deleteLogic(ids);
|
R<Boolean> result = userClient.removeUser(StringUtil.join(tenantIds));
|
if (!result.isSuccess()) {
|
throw new ServiceException(result.getMsg());
|
}
|
return tenantTemp;
|
}
|
|
@Override
|
public List<Map<String,Object>> selectMaps(){
|
List<Map<String, Object>> maps = listMaps(new QueryWrapper<Tenant>().select("TENANT_ID", "TENANT_NAME"));
|
return maps;
|
}
|
|
@Override
|
public boolean findIsOpen() {
|
return this.ssaEnable;
|
}
|
|
/**
|
* 创建租户下的默认岗位
|
* @param tenantId
|
* @param sort
|
*/
|
private Post generatePost(String tenantId,Integer categ,String postCode,String postName,Integer sort){
|
Post post = new Post();
|
post.setTenantId(tenantId);
|
post.setCategory(categ);
|
post.setPostCode(postCode);
|
post.setPostName(postName);
|
post.setSort(sort);
|
return post;
|
}
|
|
/**
|
* 创建默认用户,并进行相关权限设置
|
*/
|
private User generateUser(String tenantId, Role role, Dept dept, Post post){
|
User user = new User();
|
user.setTenantId(tenantId);
|
user.setName(role.getRoleAlias());
|
user.setRealName(role.getRoleName());
|
user.setAccount(role.getRoleAlias());
|
user.setStrategyUpdateStatus(CommonConstant.TOP_PARENT_ID);
|
user.setPwdUpdateTime(new Date());
|
// 获取参数配置的密码
|
String password = Func.toStr(ParamCache.getValue(PASSWORD_KEY), DEFAULT_PASSWORD);
|
user.setPassword(password);
|
user.setRoleId(String.valueOf(role.getId()));
|
user.setDeptId(String.valueOf(dept.getId()));
|
user.setPostId(String.valueOf(post.getId()));
|
user.setBirthday(new Date());
|
user.setSex(1);
|
user.setUserType(UserEnum.WEB.getCategory());
|
user.setIsDeleted(BladeConstant.DB_NOT_DELETED);
|
return user;
|
}
|
|
/**
|
* 保存用户对应的关联信息
|
* @param role
|
*/
|
private void saveRoleMenus(Role role,List<String> stringMenus){
|
LinkedList<Menu> userMenus = new LinkedList<>();
|
// 获取参数配置的默认菜单集合,逗号隔开
|
//List<String> menuCodes = Func.toStrList(ParamCache.getValue(ACCOUNT_MENU_CODE_KEY));
|
List<Menu> menus = getMenus((stringMenus), userMenus);
|
List<RoleMenu> roleMenus = new ArrayList<>();
|
//创建所有菜单角色关联对象
|
menus.forEach(menu -> {
|
roleMenus.add(new RoleMenu(menu.getId(),role.getId()));
|
});
|
roleMenuService.saveBatch(roleMenus);
|
}
|
|
/**
|
* 创建默认部门
|
* @param tenantId
|
* @param tenant
|
*/
|
private Dept generateDept(String tenantId,Tenant tenant){
|
Dept dept = new Dept();
|
dept.setTenantId(tenantId);
|
dept.setParentId(BladeConstant.TOP_PARENT_ID);
|
dept.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID));
|
dept.setDeptName(tenant.getTenantName());
|
dept.setFullName(tenant.getTenantName());
|
dept.setDeptCategory(1);
|
dept.setSort(2);
|
dept.setIsDeleted(BladeConstant.DB_NOT_DELETED);
|
return dept;
|
}
|
|
private String getTenantId(List<String> codes) {
|
String code = tenantId.generate();
|
if (codes.contains(code)) {
|
return getTenantId(codes);
|
}
|
return code;
|
}
|
|
private List<Menu> getMenus(List<String> codes, LinkedList<Menu> menus) {
|
codes.forEach(code -> {
|
Menu menu = menuService.getOne(Wrappers.<Menu>query().lambda().eq(Menu::getCode, code).eq(Menu::getIsDeleted, BladeConstant.DB_NOT_DELETED));
|
if (menu != null) {
|
menus.add(menu);
|
recursionMenu(menu.getId(), menus);
|
}
|
});
|
return menus;
|
}
|
|
private void recursionMenu(Long parentId, LinkedList<Menu> menus) {
|
List<Menu> menuList = menuService.list(Wrappers.<Menu>query().lambda().eq(Menu::getParentId, parentId).eq(Menu::getIsDeleted, BladeConstant.DB_NOT_DELETED));
|
menus.addAll(menuList);
|
menuList.forEach(menu -> recursionMenu(menu.getId(), menus));
|
}
|
|
private List<DictBiz> getDictBizs(String tenantId, LinkedList<DictBiz> dictBizs) {
|
List<DictBiz> dictBizList = dictBizService.list(Wrappers.<DictBiz>query().lambda().eq(DictBiz::getParentId, BladeConstant.TOP_PARENT_ID).eq(DictBiz::getIsDeleted, BladeConstant.DB_NOT_DELETED));
|
dictBizList.forEach(dictBiz -> {
|
Long oldParentId = dictBiz.getId();
|
Long newParentId = IdWorker.getId();
|
dictBiz.setId(newParentId);
|
dictBiz.setTenantId(tenantId);
|
dictBizs.add(dictBiz);
|
recursionDictBiz(tenantId, oldParentId, newParentId, dictBizs);
|
});
|
return dictBizs;
|
}
|
|
private void recursionDictBiz(String tenantId, Long oldParentId, Long newParentId, LinkedList<DictBiz> dictBizs) {
|
List<DictBiz> dictBizList = dictBizService.list(Wrappers.<DictBiz>query().lambda().eq(DictBiz::getParentId, oldParentId).eq(DictBiz::getIsDeleted, BladeConstant.DB_NOT_DELETED));
|
dictBizList.forEach(dictBiz -> {
|
Long oldSubParentId = dictBiz.getId();
|
Long newSubParentId = IdWorker.getId();
|
dictBiz.setId(newSubParentId);
|
dictBiz.setTenantId(tenantId);
|
dictBiz.setParentId(newParentId);
|
dictBizs.add(dictBiz);
|
recursionDictBiz(tenantId, oldSubParentId, newSubParentId, dictBizs);
|
});
|
}
|
|
}
|