org.openea.eap.module.system.service.tenant.TenantServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eap-module-system-biz Show documentation
Show all versions of eap-module-system-biz Show documentation
system 模块下,我们放通用业务,支撑上层的核心业务。
例如说:用户、部门、权限、数据字典等等
The newest version!
package org.openea.eap.module.system.service.tenant;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import org.openea.eap.framework.common.enums.CommonStatusEnum;
import org.openea.eap.framework.common.pojo.PageResult;
import org.openea.eap.framework.common.util.collection.CollectionUtils;
import org.openea.eap.framework.common.util.date.DateUtils;
import org.openea.eap.framework.common.util.object.BeanUtils;
import org.openea.eap.framework.tenant.config.TenantProperties;
import org.openea.eap.framework.tenant.core.context.TenantContextHolder;
import org.openea.eap.framework.tenant.core.util.TenantUtils;
import org.openea.eap.module.system.controller.admin.permission.vo.role.RoleSaveReqVO;
import org.openea.eap.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
import org.openea.eap.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
import org.openea.eap.module.system.convert.tenant.TenantConvert;
import org.openea.eap.module.system.dal.dataobject.permission.MenuDO;
import org.openea.eap.module.system.dal.dataobject.permission.RoleDO;
import org.openea.eap.module.system.dal.dataobject.tenant.TenantDO;
import org.openea.eap.module.system.dal.dataobject.tenant.TenantPackageDO;
import org.openea.eap.module.system.dal.mysql.tenant.TenantMapper;
import org.openea.eap.module.system.enums.permission.RoleCodeEnum;
import org.openea.eap.module.system.enums.permission.RoleTypeEnum;
import org.openea.eap.module.system.service.permission.MenuService;
import org.openea.eap.module.system.service.permission.PermissionService;
import org.openea.eap.module.system.service.permission.RoleService;
import org.openea.eap.module.system.service.tenant.handler.TenantInfoHandler;
import org.openea.eap.module.system.service.tenant.handler.TenantMenuHandler;
import org.openea.eap.module.system.service.user.AdminUserService;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import static org.openea.eap.framework.common.exception.util.ServiceExceptionUtil.exception;
import static org.openea.eap.module.system.enums.ErrorCodeConstants.*;
import static java.util.Collections.singleton;
/**
* 租户 Service 实现类
*
*/
@Service
@Validated
@Slf4j
public class TenantServiceImpl implements TenantService {
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
@Autowired(required = false) // 由于 eap.tenant.enable 配置项,可以关闭多租户的功能,所以这里只能不强制注入
private TenantProperties tenantProperties;
@Resource
private TenantMapper tenantMapper;
@Resource
private TenantPackageService tenantPackageService;
@Resource
@Lazy // 延迟,避免循环依赖报错
private AdminUserService userService;
@Resource
private RoleService roleService;
@Resource
private MenuService menuService;
@Resource
private PermissionService permissionService;
@Override
public List getTenantIdList() {
List tenants = tenantMapper.selectList();
return CollectionUtils.convertList(tenants, TenantDO::getId);
}
@Override
public void validTenant(Long id) {
TenantDO tenant = getTenant(id);
if (tenant == null) {
throw exception(TENANT_NOT_EXISTS);
}
if (tenant.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) {
throw exception(TENANT_DISABLE, tenant.getName());
}
if (DateUtils.isExpired(tenant.getExpireTime())) {
throw exception(TENANT_EXPIRE, tenant.getName());
}
}
@Override
@DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
public Long createTenant(TenantSaveReqVO createReqVO) {
// 校验租户名称是否重复
validTenantNameDuplicate(createReqVO.getName(), null);
// 校验租户域名是否重复
validTenantWebsiteDuplicate(createReqVO.getWebsite(), null);
// 校验套餐被禁用
TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(createReqVO.getPackageId());
// 创建租户
TenantDO tenant = BeanUtils.toBean(createReqVO, TenantDO.class);
tenantMapper.insert(tenant);
// 创建租户的管理员
TenantUtils.execute(tenant.getId(), () -> {
// 创建角色
Long roleId = createRole(tenantPackage);
// 创建用户,并分配角色
Long userId = createUser(roleId, createReqVO);
// 修改租户的管理员
tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId));
});
return tenant.getId();
}
private Long createUser(Long roleId, TenantSaveReqVO createReqVO) {
// 创建用户
Long userId = userService.createUser(TenantConvert.INSTANCE.convert02(createReqVO));
// 分配角色
permissionService.assignUserRole(userId, singleton(roleId));
return userId;
}
private Long createRole(TenantPackageDO tenantPackage) {
// 创建角色
RoleSaveReqVO reqVO = new RoleSaveReqVO();
reqVO.setName(RoleCodeEnum.TENANT_ADMIN.getName()).setCode(RoleCodeEnum.TENANT_ADMIN.getCode())
.setSort(0).setRemark("系统自动生成");
Long roleId = roleService.createRole(reqVO, RoleTypeEnum.SYSTEM.getType());
// 分配权限
permissionService.assignRoleMenu(roleId, tenantPackage.getMenuIds());
return roleId;
}
@Override
@DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
public void updateTenant(TenantSaveReqVO updateReqVO) {
// 校验存在
TenantDO tenant = validateUpdateTenant(updateReqVO.getId());
// 校验租户名称是否重复
validTenantNameDuplicate(updateReqVO.getName(), updateReqVO.getId());
// 校验租户域名是否重复
validTenantWebsiteDuplicate(updateReqVO.getWebsite(), updateReqVO.getId());
// 校验套餐被禁用
TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId());
// 更新租户
TenantDO updateObj = BeanUtils.toBean(updateReqVO, TenantDO.class);
tenantMapper.updateById(updateObj);
// 如果套餐发生变化,则修改其角色的权限
if (ObjectUtil.notEqual(tenant.getPackageId(), updateReqVO.getPackageId())) {
updateTenantRoleMenu(tenant.getId(), tenantPackage.getMenuIds());
}
}
private void validTenantNameDuplicate(String name, Long id) {
TenantDO tenant = tenantMapper.selectByName(name);
if (tenant == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同名字的租户
if (id == null) {
throw exception(TENANT_NAME_DUPLICATE, name);
}
if (!tenant.getId().equals(id)) {
throw exception(TENANT_NAME_DUPLICATE, name);
}
}
private void validTenantWebsiteDuplicate(String website, Long id) {
if (StrUtil.isEmpty(website)) {
return;
}
TenantDO tenant = tenantMapper.selectByWebsite(website);
if (tenant == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同名字的租户
if (id == null) {
throw exception(TENANT_WEBSITE_DUPLICATE, website);
}
if (!tenant.getId().equals(id)) {
throw exception(TENANT_WEBSITE_DUPLICATE, website);
}
}
@Override
@DSTransactional
public void updateTenantRoleMenu(Long tenantId, Set menuIds) {
TenantUtils.execute(tenantId, () -> {
// 获得所有角色
List roles = roleService.getRoleList();
roles.forEach(role -> Assert.isTrue(tenantId.equals(role.getTenantId()), "角色({}/{}) 租户不匹配",
role.getId(), role.getTenantId(), tenantId)); // 兜底校验
// 重新分配每个角色的权限
roles.forEach(role -> {
// 如果是租户管理员,重新分配其权限为租户套餐的权限
if (Objects.equals(role.getCode(), RoleCodeEnum.TENANT_ADMIN.getCode())) {
permissionService.assignRoleMenu(role.getId(), menuIds);
log.info("[updateTenantRoleMenu][租户管理员({}/{}) 的权限修改为({})]", role.getId(), role.getTenantId(), menuIds);
return;
}
// 如果是其他角色,则去掉超过套餐的权限
Set roleMenuIds = permissionService.getRoleMenuListByRoleId(role.getId());
roleMenuIds = CollUtil.intersectionDistinct(roleMenuIds, menuIds);
permissionService.assignRoleMenu(role.getId(), roleMenuIds);
log.info("[updateTenantRoleMenu][角色({}/{}) 的权限修改为({})]", role.getId(), role.getTenantId(), roleMenuIds);
});
});
}
@Override
public void deleteTenant(Long id) {
// 校验存在
validateUpdateTenant(id);
// 删除
tenantMapper.deleteById(id);
}
private TenantDO validateUpdateTenant(Long id) {
TenantDO tenant = tenantMapper.selectById(id);
if (tenant == null) {
throw exception(TENANT_NOT_EXISTS);
}
// 内置租户,不允许删除
if (isSystemTenant(tenant)) {
throw exception(TENANT_CAN_NOT_UPDATE_SYSTEM);
}
return tenant;
}
@Override
public TenantDO getTenant(Long id) {
return tenantMapper.selectById(id);
}
@Override
public PageResult getTenantPage(TenantPageReqVO pageReqVO) {
return tenantMapper.selectPage(pageReqVO);
}
@Override
public TenantDO getTenantByName(String name) {
return tenantMapper.selectByName(name);
}
@Override
public TenantDO getTenantByWebsite(String website) {
return tenantMapper.selectByWebsite(website);
}
@Override
public Long getTenantCountByPackageId(Long packageId) {
return tenantMapper.selectCountByPackageId(packageId);
}
@Override
public List getTenantListByPackageId(Long packageId) {
return tenantMapper.selectListByPackageId(packageId);
}
@Override
public void handleTenantInfo(TenantInfoHandler handler) {
// 如果禁用,则不执行逻辑
if (isTenantDisable()) {
return;
}
// 获得租户
TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
// 执行处理器
handler.handle(tenant);
}
@Override
public void handleTenantMenu(TenantMenuHandler handler) {
// 如果禁用,则不执行逻辑
if (isTenantDisable()) {
return;
}
// 获得租户,然后获得菜单
TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId());
Set menuIds;
if (isSystemTenant(tenant)) { // 系统租户,菜单是全量的
menuIds = CollectionUtils.convertSet(menuService.getMenuList(), MenuDO::getId);
} else {
menuIds = tenantPackageService.getTenantPackage(tenant.getPackageId()).getMenuIds();
}
// 执行处理器
handler.handle(menuIds);
}
private static boolean isSystemTenant(TenantDO tenant) {
return Objects.equals(tenant.getPackageId(), TenantDO.PACKAGE_ID_SYSTEM);
}
private boolean isTenantDisable() {
return tenantProperties == null || Boolean.FALSE.equals(tenantProperties.getEnable());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy