/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
*
* 1. This software is for development use only under a valid license
* from BladeX.
*
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
*
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
*
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
*
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
*
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.system.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springblade.core.cache.utils.CacheUtil;
import org.springblade.core.literule.engine.RuleEngineExecutor;
import org.springblade.core.literule.provider.LiteRuleResponse;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.mp.enums.StatusType;
import org.springblade.core.tenant.TenantId;
import org.springblade.core.tool.constant.BladeConstant;
import org.springblade.core.tool.jackson.JsonUtil;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.DesUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.mapper.TenantMapper;
import org.springblade.system.pojo.entity.*;
import org.springblade.system.rule.context.TenantContext;
import org.springblade.system.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import static org.springblade.common.constant.TenantConstant.DES_KEY;
import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE;
import static org.springblade.system.cache.SysCache.TENANT_TENANT_ID;
import static org.springblade.system.rule.constant.TenantRuleConstant.TENANT_CHAIN_ID;
/**
* 服务实现类
*
* @author Chill
*/
@Service
@AllArgsConstructor
public class TenantServiceImpl extends BaseServiceImpl implements ITenantService {
private final TenantId tenantIdGenerator;
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 IUserService userService;
private final IUserDeptService userDeptService;
private final RuleEngineExecutor ruleExecutor;
@Override
public IPage selectTenantPage(IPage page, Tenant tenant) {
return page.setRecords(baseMapper.selectTenantPage(page, tenant));
}
@Override
public Tenant getByTenantId(String tenantId) {
return getOne(Wrappers.query().lambda().eq(Tenant::getTenantId, tenantId));
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean submitTenant(Tenant tenant) {
if (Func.isEmpty(tenant.getId())) {
LiteRuleResponse resp = ruleExecutor.execute(
TENANT_CHAIN_ID,
TenantContext.builder()
.tenantIdGenerator(tenantIdGenerator)
.tenant(tenant)
.menuService(menuService)
.dictBizService(dictBizService)
.tenantService(this)
.build()
);
if (resp.isSuccess()) {
TenantContext tenantContext = resp.getContext();
Role role = tenantContext.getRole();
roleService.save(role);
Long roleId = role.getId();
List roleMenuList = tenantContext.getRoleMenuList();
roleMenuList.forEach(roleMenu -> roleMenu.setRoleId(roleId));
roleMenuService.saveBatch(roleMenuList);
Dept dept = tenantContext.getDept();
deptService.save(dept);
Post post = tenantContext.getPost();
postService.save(post);
List dictBizList = tenantContext.getDictBizList();
dictBizService.saveBatch(dictBizList);
User user = tenantContext.getUser();
user.setRoleId(String.valueOf(role.getId()));
user.setDeptId(String.valueOf(dept.getId()));
user.setPostId(String.valueOf(post.getId()));
userService.submit(user);
} else {
throw new ServiceException("租户业务数据构建异常");
}
}
CacheUtil.clear(SYS_CACHE, tenant.getTenantId());
CacheUtil.evict(SYS_CACHE, TENANT_TENANT_ID, tenant.getTenantId(), Boolean.FALSE);
return super.saveOrUpdate(tenant);
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean recycleTenant(List ids) {
List tenantIds = this.list(Wrappers.query().lambda().in(Tenant::getId, ids))
.stream().map(tenant -> Func.toStr(tenant.getTenantId())).distinct().collect(Collectors.toList());
if (tenantIds.contains(BladeConstant.ADMIN_TENANT_ID)) {
throw new ServiceException("不可删除管理租户!");
}
int disabledType = StatusType.DISABLED.getType();
int activeType = StatusType.ACTIVE.getType();
boolean temp = this.changeStatus(ids, disabledType);
if (temp) {
// 删除角色至回收站
roleService.update(Wrappers.update().lambda().set(Role::getStatus, disabledType).eq(Role::getStatus, activeType).in(Role::getTenantId, tenantIds));
// 删除部门至回收站
deptService.update(Wrappers.update().lambda().set(Dept::getStatus, disabledType).eq(Dept::getStatus, activeType).in(Dept::getTenantId, tenantIds));
// 删除岗位至回收站
postService.update(Wrappers.update().lambda().set(Post::getStatus, disabledType).eq(Post::getStatus, activeType).in(Post::getTenantId, tenantIds));
// 删除业务字典至回收站
dictBizService.update(Wrappers.update().lambda().set(DictBiz::getStatus, disabledType).eq(DictBiz::getStatus, activeType).in(DictBiz::getTenantId, tenantIds));
// 获取需要删除的用户主键集合
List userIds = userService.list(Wrappers.query().lambda().eq(User::getStatus, activeType).in(User::getTenantId, tenantIds)
.select(User::getId)).stream().map(User::getId).collect(Collectors.toList());
// 删除用户部门及拓展部分至回收站
userService.update(Wrappers.update().lambda().set(User::getStatus, disabledType).in(User::getId, userIds));
userDeptService.update(Wrappers.update().lambda().set(UserDept::getStatus, disabledType).in(UserDept::getUserId, userIds));
// 删除用户自定义部分至回收站
new UserOauth().update(Wrappers.update().lambda().set(UserOauth::getStatus, disabledType).in(UserOauth::getUserId, userIds));
new UserWeb().update(Wrappers.update().lambda().set(UserWeb::getStatus, disabledType).in(UserWeb::getUserId, userIds));
new UserApp().update(Wrappers.update().lambda().set(UserApp::getStatus, disabledType).in(UserApp::getUserId, userIds));
new UserOther().update(Wrappers.update().lambda().set(UserOther::getStatus, disabledType).in(UserOther::getUserId, userIds));
CacheUtil.clear(SYS_CACHE, tenantIds);
return true;
} else {
throw new ServiceException("删除租户失败!");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean passTenant(List ids) {
List tenantIds = this.list(Wrappers.query().lambda().in(Tenant::getId, ids))
.stream().map(tenant -> Func.toStr(tenant.getTenantId())).distinct().collect(Collectors.toList());
int disabledType = StatusType.DISABLED.getType();
int activeType = StatusType.ACTIVE.getType();
boolean temp = this.changeStatus(ids, activeType);
if (temp) {
// 恢复角色至正常状态
roleService.update(Wrappers.update().lambda().set(Role::getStatus, activeType).eq(Role::getStatus, disabledType).in(Role::getTenantId, tenantIds));
// 恢复部门至正常状态
deptService.update(Wrappers.update().lambda().set(Dept::getStatus, activeType).eq(Dept::getStatus, disabledType).in(Dept::getTenantId, tenantIds));
// 恢复岗位至正常状态
postService.update(Wrappers.update().lambda().set(Post::getStatus, activeType).eq(Post::getStatus, disabledType).in(Post::getTenantId, tenantIds));
// 恢复业务字典至正常状态
dictBizService.update(Wrappers.update().lambda().set(DictBiz::getStatus, activeType).eq(DictBiz::getStatus, disabledType).in(DictBiz::getTenantId, tenantIds));
// 获取需要恢复的用户主键集合
List userIds = userService.list(Wrappers.query().lambda().eq(User::getStatus, disabledType).in(User::getTenantId, tenantIds)
.select(User::getId)).stream().map(User::getId).collect(Collectors.toList());
// 恢复用户部门及拓展部分至正常状态
userService.update(Wrappers.update().lambda().set(User::getStatus, activeType).in(User::getId, userIds));
userDeptService.update(Wrappers.update().lambda().set(UserDept::getStatus, activeType).in(UserDept::getUserId, userIds));
// 恢复用户自定义部分至正常状态
new UserOauth().update(Wrappers.update().lambda().set(UserOauth::getStatus, activeType).in(UserOauth::getUserId, userIds));
new UserWeb().update(Wrappers.update().lambda().set(UserWeb::getStatus, activeType).in(UserWeb::getUserId, userIds));
new UserApp().update(Wrappers.update().lambda().set(UserApp::getStatus, activeType).in(UserApp::getUserId, userIds));
new UserOther().update(Wrappers.update().lambda().set(UserOther::getStatus, activeType).in(UserOther::getUserId, userIds));
CacheUtil.clear(SYS_CACHE, tenantIds);
return true;
} else {
throw new ServiceException("恢复租户失败!");
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public boolean removeTenant(List ids) {
List tenantIds = this.list(Wrappers.query().lambda().in(Tenant::getId, ids))
.stream().map(tenant -> Func.toStr(tenant.getTenantId())).distinct().collect(Collectors.toList());
if (tenantIds.contains(BladeConstant.ADMIN_TENANT_ID)) {
throw new ServiceException("不可删除管理租户!");
}
boolean temp = this.deleteLogic(ids);
if (temp) {
// 删除角色不可再恢复
roleService.remove(Wrappers.query().lambda().in(Role::getTenantId, tenantIds));
// 删除部门不可再恢复
deptService.remove(Wrappers.query().lambda().in(Dept::getTenantId, tenantIds));
// 删除岗位不可再恢复
postService.remove(Wrappers.query().lambda().in(Post::getTenantId, tenantIds));
// 删除业务字典不可再恢复
dictBizService.remove(Wrappers.query().lambda().in(DictBiz::getTenantId, tenantIds));
// 获取需要删除的用户主键集合
List userIds = userService.list(Wrappers.query().lambda().in(User::getTenantId, tenantIds)
.select(User::getId)).stream().map(User::getId).collect(Collectors.toList());
// 删除用户部门及拓展部分不可再恢复
userService.removeByIds(userIds);
userDeptService.remove(Wrappers.query().lambda().in(UserDept::getUserId, userIds));
// 删除用户自定义部分不可再恢复
new UserOauth().delete(Wrappers.query().lambda().in(UserOauth::getUserId, userIds));
new UserWeb().delete(Wrappers.query().lambda().in(UserWeb::getUserId, userIds));
new UserApp().delete(Wrappers.query().lambda().in(UserApp::getUserId, userIds));
new UserOther().delete(Wrappers.query().lambda().in(UserOther::getUserId, userIds));
CacheUtil.clear(SYS_CACHE, tenantIds);
return true;
} else {
throw new ServiceException("删除租户失败!");
}
}
@Override
public boolean setting(Integer accountNumber, Date expireTime, String ids) {
List tenantIds = this.list(Wrappers.query().lambda().in(Tenant::getId, ids))
.stream().map(tenant -> Func.toStr(tenant.getTenantId())).distinct().toList();
tenantIds.forEach(tenantId -> {
CacheUtil.clear(SYS_CACHE, tenantId);
CacheUtil.evict(SYS_CACHE, TENANT_TENANT_ID, tenantId, Boolean.FALSE);
});
Func.toLongList(ids).forEach(id -> {
Kv kv = Kv.create().set("accountNumber", accountNumber).set("expireTime", expireTime).set("id", id);
String licenseKey = DesUtil.encryptToHex(JsonUtil.toJson(kv), DES_KEY);
update(
Wrappers.update().lambda()
.set(Tenant::getAccountNumber, accountNumber)
.set(Tenant::getExpireTime, expireTime)
.set(Tenant::getLicenseKey, licenseKey)
.eq(Tenant::getId, id)
);
});
return true;
}
}