mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-11-04 10:57:10 +08:00 
			
		
		
		
	fix: 修复租户登陆时的权限问题,租户套餐更新时租户菜单权限同步更新
This commit is contained in:
		@@ -70,20 +70,15 @@ public class RegexConstants {
 | 
			
		||||
     * 域名、IPV4、IPV6
 | 
			
		||||
     * </p>
 | 
			
		||||
     */
 | 
			
		||||
    public static final String HTTP_HOST =
 | 
			
		||||
            "^(" +
 | 
			
		||||
    public static final String HTTP_HOST = "^(" +
 | 
			
		||||
        // ① 域名
 | 
			
		||||
                    "(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\\.)+[A-Za-z]{2,63}" +
 | 
			
		||||
                    "|" +
 | 
			
		||||
        "(?:[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?\\.)+[A-Za-z]{2,63}" + "|" +
 | 
			
		||||
        // ② IPv4
 | 
			
		||||
                    "(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)" +
 | 
			
		||||
                    "|" +
 | 
			
		||||
        "(?:(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d\\d?)" + "|" +
 | 
			
		||||
        // ③ IPv6(8 组 1-4 位十六进制,用 : 分隔,支持压缩 0)
 | 
			
		||||
                    "(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}" +
 | 
			
		||||
                    "|" +
 | 
			
		||||
        "(?:[0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}" + "|" +
 | 
			
		||||
        // ④ IPv6 压缩形式(::)
 | 
			
		||||
                    "(?:[0-9A-Fa-f]{1,4}:){0,6}::(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4}" +
 | 
			
		||||
                    ")$";
 | 
			
		||||
        "(?:[0-9A-Fa-f]{1,4}:){0,6}::(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4}" + ")$";
 | 
			
		||||
 | 
			
		||||
    private RegexConstants() {
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -64,9 +64,9 @@ public class CommonController {
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @TenantIgnore
 | 
			
		||||
    @GetMapping("/id/domain")
 | 
			
		||||
    public Long getTenantIdByUrl(@RequestParam("domain") String domain){
 | 
			
		||||
    public Long getTenantIdByUrl(@RequestParam("domain") String domain) {
 | 
			
		||||
        TenantDO tenantDO = tenantService.getByDomain(domain);
 | 
			
		||||
        if (tenantDO != null){
 | 
			
		||||
        if (tenantDO != null) {
 | 
			
		||||
            return tenantDO.getId();
 | 
			
		||||
        }
 | 
			
		||||
        return null;
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,6 @@ import top.continew.admin.system.mapper.user.UserPasswordHistoryMapper;
 | 
			
		||||
import top.continew.admin.system.mapper.user.UserSocialMapper;
 | 
			
		||||
import top.continew.admin.system.model.entity.DeptDO;
 | 
			
		||||
import top.continew.admin.system.model.entity.FileDO;
 | 
			
		||||
import top.continew.admin.system.model.entity.MenuDO;
 | 
			
		||||
import top.continew.admin.system.model.entity.RoleDO;
 | 
			
		||||
import top.continew.admin.system.model.entity.user.UserDO;
 | 
			
		||||
import top.continew.admin.system.service.FileService;
 | 
			
		||||
@@ -96,8 +95,6 @@ public class TenantDataHandlerForSystem implements TenantDataHandler {
 | 
			
		||||
            Long deptId = this.initDeptData(tenant);
 | 
			
		||||
            // 初始化菜单
 | 
			
		||||
            List<Long> menuIds = packageMenuService.listMenuIdsByPackageId(tenant.getPackageId());
 | 
			
		||||
            List<MenuDO> menuList = menuMapper.lambdaQuery().in(MenuDO::getId, menuIds).list();
 | 
			
		||||
            this.initMenuData(menuList, 0L, 0L);
 | 
			
		||||
            // 初始化角色
 | 
			
		||||
            Long roleId = this.initRoleData(tenant);
 | 
			
		||||
            // 角色绑定菜单
 | 
			
		||||
@@ -165,24 +162,6 @@ public class TenantDataHandlerForSystem implements TenantDataHandler {
 | 
			
		||||
        return dept.getId();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 递归初始化菜单数据
 | 
			
		||||
     *
 | 
			
		||||
     * @param menuList    菜单列表
 | 
			
		||||
     * @param oldParentId 旧父级 ID
 | 
			
		||||
     * @param newParentId 新父级 ID
 | 
			
		||||
     */
 | 
			
		||||
    private void initMenuData(List<MenuDO> menuList, Long oldParentId, Long newParentId) {
 | 
			
		||||
        List<MenuDO> children = menuList.stream().filter(menuDO -> menuDO.getParentId().equals(oldParentId)).toList();
 | 
			
		||||
        for (MenuDO menu : children) {
 | 
			
		||||
            Long oldId = menu.getId();
 | 
			
		||||
            menu.setId(null);
 | 
			
		||||
            menu.setParentId(newParentId);
 | 
			
		||||
            menuMapper.insert(menu);
 | 
			
		||||
            initMenuData(menuList, oldId, menu.getId());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 初始化角色数据
 | 
			
		||||
     *
 | 
			
		||||
 
 | 
			
		||||
@@ -18,13 +18,18 @@ package top.continew.admin.tenant.service.impl;
 | 
			
		||||
 | 
			
		||||
import cn.hutool.core.collection.CollUtil;
 | 
			
		||||
import com.alicp.jetcache.anno.Cached;
 | 
			
		||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 | 
			
		||||
import lombok.RequiredArgsConstructor;
 | 
			
		||||
import me.ahoo.cosid.provider.IdGeneratorProvider;
 | 
			
		||||
import org.springframework.stereotype.Service;
 | 
			
		||||
import top.continew.admin.common.base.service.BaseServiceImpl;
 | 
			
		||||
import top.continew.admin.common.constant.CacheConstants;
 | 
			
		||||
import top.continew.admin.common.constant.SysConstants;
 | 
			
		||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
 | 
			
		||||
import top.continew.admin.system.model.entity.MenuDO;
 | 
			
		||||
import top.continew.admin.system.service.MenuService;
 | 
			
		||||
import top.continew.admin.system.model.entity.RoleDO;
 | 
			
		||||
import top.continew.admin.system.model.entity.RoleMenuDO;
 | 
			
		||||
import top.continew.admin.system.service.RoleMenuService;
 | 
			
		||||
import top.continew.admin.system.service.RoleService;
 | 
			
		||||
import top.continew.admin.tenant.config.TenantExtensionProperties;
 | 
			
		||||
import top.continew.admin.tenant.constant.TenantCacheConstants;
 | 
			
		||||
import top.continew.admin.tenant.constant.TenantConstants;
 | 
			
		||||
@@ -35,16 +40,15 @@ import top.continew.admin.tenant.model.query.TenantQuery;
 | 
			
		||||
import top.continew.admin.tenant.model.req.TenantReq;
 | 
			
		||||
import top.continew.admin.tenant.model.resp.TenantDetailResp;
 | 
			
		||||
import top.continew.admin.tenant.model.resp.TenantResp;
 | 
			
		||||
import top.continew.admin.tenant.service.PackageMenuService;
 | 
			
		||||
import top.continew.admin.tenant.service.PackageService;
 | 
			
		||||
import top.continew.admin.tenant.service.TenantService;
 | 
			
		||||
import top.continew.starter.cache.redisson.util.RedisUtils;
 | 
			
		||||
import top.continew.starter.core.constant.StringConstants;
 | 
			
		||||
import top.continew.starter.core.util.validation.CheckUtils;
 | 
			
		||||
import top.continew.starter.extension.tenant.util.TenantUtils;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.time.LocalDateTime;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -62,8 +66,8 @@ public class TenantServiceImpl extends BaseServiceImpl<TenantMapper, TenantDO, T
 | 
			
		||||
    private final PackageService packageService;
 | 
			
		||||
    private final IdGeneratorProvider idGeneratorProvider;
 | 
			
		||||
    private final TenantDataHandler tenantDataHandler;
 | 
			
		||||
    private final PackageMenuService packageMenuService;
 | 
			
		||||
    private final MenuService menuService;
 | 
			
		||||
    private final RoleMenuService roleMenuService;
 | 
			
		||||
    private final RoleService roleService;
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Long create(TenantReq req) {
 | 
			
		||||
@@ -147,26 +151,20 @@ public class TenantServiceImpl extends BaseServiceImpl<TenantMapper, TenantDO, T
 | 
			
		||||
        if (CollUtil.isEmpty(tenantIdList)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        List<Long> oldMenuIds = packageMenuService.listMenuIdsByPackageId(packageId);
 | 
			
		||||
        // 如果有删除的菜单则绑定了套餐的租户对应的菜单也会删除
 | 
			
		||||
        List<Long> deleteMenuIds = new ArrayList<>(oldMenuIds);
 | 
			
		||||
        deleteMenuIds.removeAll(newMenuIds);
 | 
			
		||||
        if (CollUtil.isNotEmpty(deleteMenuIds)) {
 | 
			
		||||
            List<MenuDO> deleteMenus = menuService.listByIds(deleteMenuIds);
 | 
			
		||||
            tenantIdList.forEach(tenantId -> TenantUtils.execute(tenantId, () -> menuService
 | 
			
		||||
                .deleteTenantMenus(deleteMenus)));
 | 
			
		||||
        }
 | 
			
		||||
        // 如果有新增的菜单则绑定了套餐的租户对应的菜单也会新增
 | 
			
		||||
        List<Long> addMenuIds = new ArrayList<>(newMenuIds);
 | 
			
		||||
        addMenuIds.removeAll(oldMenuIds);
 | 
			
		||||
        if (CollUtil.isNotEmpty(addMenuIds)) {
 | 
			
		||||
            List<MenuDO> addMenus = menuService.listByIds(addMenuIds);
 | 
			
		||||
            for (MenuDO addMenu : addMenus) {
 | 
			
		||||
                MenuDO parentMenu = addMenu.getParentId() != 0 ? menuService.getById(addMenu.getParentId()) : null;
 | 
			
		||||
                tenantIdList.forEach(tenantId -> TenantUtils.execute(tenantId, () -> menuService
 | 
			
		||||
                    .addTenantMenu(addMenu, parentMenu)));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //删除旧菜单
 | 
			
		||||
        tenantIdList.forEach(tenantId -> TenantUtils.execute(tenantId, () -> roleMenuService.remove(Wrappers
 | 
			
		||||
            .lambdaQuery(RoleMenuDO.class)
 | 
			
		||||
            .notIn(RoleMenuDO::getMenuId, newMenuIds))));
 | 
			
		||||
        //新增菜单
 | 
			
		||||
        tenantIdList.forEach(tenantId -> TenantUtils.execute(tenantId, () -> {
 | 
			
		||||
            RoleDO roleDO = roleService.getByCode(SysConstants.TENANT_ADMIN_ROLE_CODE);
 | 
			
		||||
            List<Long> oldMenuIds = roleMenuService.list(Wrappers.lambdaQuery(RoleMenuDO.class)
 | 
			
		||||
                .eq(RoleMenuDO::getRoleId, roleDO.getId())).stream().map(RoleMenuDO::getMenuId).toList();
 | 
			
		||||
            newMenuIds.removeAll(oldMenuIds);
 | 
			
		||||
            roleMenuService.add(newMenuIds, roleDO.getId());
 | 
			
		||||
        }));
 | 
			
		||||
        //清理角色菜单缓存
 | 
			
		||||
        RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -223,6 +223,7 @@ continew-starter.tenant:
 | 
			
		||||
    - sys_sms_log # 短信日志表
 | 
			
		||||
    - sys_client # 客户端表
 | 
			
		||||
    - sys_app # 应用表
 | 
			
		||||
    - sys_menu
 | 
			
		||||
  # 忽略菜单 ID(租户不能使用的菜单)
 | 
			
		||||
  ignore-menus:
 | 
			
		||||
    - 1130 # 字典管理
 | 
			
		||||
 
 | 
			
		||||
@@ -48,9 +48,6 @@ CREATE TABLE IF NOT EXISTS `tenant_package_menu` (
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租户套餐和菜单关联表';
 | 
			
		||||
 | 
			
		||||
-- 为已有表增加租户字段
 | 
			
		||||
ALTER TABLE `sys_menu`
 | 
			
		||||
    ADD COLUMN `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户ID',
 | 
			
		||||
    ADD INDEX `idx_tenant_id` (`tenant_id`);
 | 
			
		||||
ALTER TABLE `sys_dept`
 | 
			
		||||
    ADD COLUMN `tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户ID',
 | 
			
		||||
    ADD INDEX `idx_tenant_id` (`tenant_id`);
 | 
			
		||||
@@ -98,9 +95,6 @@ ALTER TABLE `sys_app`
 | 
			
		||||
    ADD INDEX `idx_tenant_id` (`tenant_id`);
 | 
			
		||||
 | 
			
		||||
-- 调整唯一索引
 | 
			
		||||
ALTER TABLE `sys_menu`
 | 
			
		||||
    DROP INDEX `uk_title_parent_id`,
 | 
			
		||||
    ADD UNIQUE INDEX `uk_title_parent_id` (`title`, `parent_id`, `tenant_id`);
 | 
			
		||||
ALTER TABLE `sys_dept`
 | 
			
		||||
    DROP INDEX `uk_name_parent_id`,
 | 
			
		||||
    ADD UNIQUE INDEX `uk_name_parent_id` (`name`, `parent_id`, `tenant_id`);
 | 
			
		||||
 
 | 
			
		||||
@@ -72,7 +72,10 @@ public class AccountLoginHandler extends AbstractLoginHandler<AccountLoginReq> {
 | 
			
		||||
        super.checkUserStatus(user);
 | 
			
		||||
        // 执行认证
 | 
			
		||||
        String token = this.authenticate(user, client);
 | 
			
		||||
        return LoginResp.builder().token(token).tenantId(TenantContextHolder.isTenantEnabled()? TenantContextHolder.getTenantId():null).build();
 | 
			
		||||
        return LoginResp.builder()
 | 
			
		||||
            .token(token)
 | 
			
		||||
            .tenantId(TenantContextHolder.isTenantEnabled() ? TenantContextHolder.getTenantId() : null)
 | 
			
		||||
            .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,11 @@ public class EmailLoginHandler extends AbstractLoginHandler<EmailLoginReq> {
 | 
			
		||||
        super.checkUserStatus(user);
 | 
			
		||||
        // 执行认证
 | 
			
		||||
        String token = super.authenticate(user, client);
 | 
			
		||||
        return LoginResp.builder().token(token).tenantId(TenantContextHolder.isTenantEnabled()? TenantContextHolder.getTenantId():null).build();    }
 | 
			
		||||
        return LoginResp.builder()
 | 
			
		||||
            .token(token)
 | 
			
		||||
            .tenantId(TenantContextHolder.isTenantEnabled() ? TenantContextHolder.getTenantId() : null)
 | 
			
		||||
            .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void preLogin(EmailLoginReq req, ClientResp client, HttpServletRequest request) {
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,11 @@ public class PhoneLoginHandler extends AbstractLoginHandler<PhoneLoginReq> {
 | 
			
		||||
        super.checkUserStatus(user);
 | 
			
		||||
        // 执行认证
 | 
			
		||||
        String token = super.authenticate(user, client);
 | 
			
		||||
        return LoginResp.builder().token(token).tenantId(TenantContextHolder.isTenantEnabled()? TenantContextHolder.getTenantId():null).build();    }
 | 
			
		||||
        return LoginResp.builder()
 | 
			
		||||
            .token(token)
 | 
			
		||||
            .tenantId(TenantContextHolder.isTenantEnabled() ? TenantContextHolder.getTenantId() : null)
 | 
			
		||||
            .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void preLogin(PhoneLoginReq req, ClientResp client, HttpServletRequest request) {
 | 
			
		||||
 
 | 
			
		||||
@@ -128,7 +128,10 @@ public class SocialLoginHandler extends AbstractLoginHandler<SocialLoginReq> {
 | 
			
		||||
        userSocialService.saveOrUpdate(userSocial);
 | 
			
		||||
        // 执行认证
 | 
			
		||||
        String token = super.authenticate(user, client);
 | 
			
		||||
        return LoginResp.builder().token(token).tenantId(TenantContextHolder.isTenantEnabled()? TenantContextHolder.getTenantId():null).build();
 | 
			
		||||
        return LoginResp.builder()
 | 
			
		||||
            .token(token)
 | 
			
		||||
            .tenantId(TenantContextHolder.isTenantEnabled() ? TenantContextHolder.getTenantId() : null)
 | 
			
		||||
            .build();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 
 | 
			
		||||
@@ -130,10 +130,10 @@ public class CommonController {
 | 
			
		||||
 | 
			
		||||
    @TenantIgnore
 | 
			
		||||
    @SaIgnore
 | 
			
		||||
    @Operation(summary = "查询租户开启状态",description = "查询租户开启状态")
 | 
			
		||||
    @Operation(summary = "查询租户开启状态", description = "查询租户开启状态")
 | 
			
		||||
    @GetMapping("/dict/option/tenant")
 | 
			
		||||
    @Cached(key = "'TENANT'", name = CacheConstants.OPTION_KEY_PREFIX)
 | 
			
		||||
    public Boolean tenantEnabled(){
 | 
			
		||||
    public Boolean tenantEnabled() {
 | 
			
		||||
        return TenantContextHolder.isTenantEnabled();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user