Commit feba904fd88fce6815d54c832d46af122ebed48a
1 parent
c162b39e
多租户:登录界面,根据 host 域名获取对应的租户编号
Showing
9 changed files
with
83 additions
and
14 deletions
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| ... | ... | @@ -104,6 +104,7 @@ public interface ErrorCodeConstants { |
| 104 | 104 | ErrorCode TENANT_EXPIRE = new ErrorCode(1_002_015_002, "名字为【{}】的租户已过期"); |
| 105 | 105 | ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1_002_015_003, "系统租户不能进行修改、删除等操作!"); |
| 106 | 106 | ErrorCode TENANT_NAME_DUPLICATE = new ErrorCode(1_002_015_004, "名字为【{}】的租户已存在"); |
| 107 | + ErrorCode TENANT_WEBSITE_DUPLICATE = new ErrorCode(1_002_015_005, "域名为【{}】的租户已存在"); | |
| 107 | 108 | |
| 108 | 109 | // ========== 租户套餐 1-002-016-000 ========== |
| 109 | 110 | ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1_002_016_000, "租户套餐不存在"); | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.java
| ... | ... | @@ -37,8 +37,17 @@ public class TenantController { |
| 37 | 37 | @Operation(summary = "使用租户名,获得租户编号", description = "登录界面,根据用户的租户名,获得租户编号") |
| 38 | 38 | @Parameter(name = "name", description = "租户名", required = true, example = "1024") |
| 39 | 39 | public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) { |
| 40 | - TenantDO tenantDO = tenantService.getTenantByName(name); | |
| 41 | - return success(tenantDO != null ? tenantDO.getId() : null); | |
| 40 | + TenantDO tenant = tenantService.getTenantByName(name); | |
| 41 | + return success(tenant != null ? tenant.getId() : null); | |
| 42 | + } | |
| 43 | + | |
| 44 | + @GetMapping("/get-by-website") | |
| 45 | + @PermitAll | |
| 46 | + @Operation(summary = "使用域名,获得租户信息", description = "登录界面,根据用户的域名,获得租户信息") | |
| 47 | + @Parameter(name = "website", description = "域名", required = true, example = "www.iocoder.cn") | |
| 48 | + public CommonResult<TenantSimpleRespVO> getTenantByWebsite(@RequestParam("website") String website) { | |
| 49 | + TenantDO tenant = tenantService.getTenantByWebsite(website); | |
| 50 | + return success(TenantConvert.INSTANCE.convert03(tenant)); | |
| 42 | 51 | } |
| 43 | 52 | |
| 44 | 53 | @PostMapping("/create") |
| ... | ... | @@ -94,5 +103,4 @@ public class TenantController { |
| 94 | 103 | ExcelUtils.write(response, "租户.xls", "数据", TenantExcelVO.class, datas); |
| 95 | 104 | } |
| 96 | 105 | |
| 97 | - | |
| 98 | 106 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantSimpleRespVO.java
0 → 100755
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; | |
| 2 | + | |
| 3 | +import io.swagger.v3.oas.annotations.media.Schema; | |
| 4 | +import lombok.Data; | |
| 5 | +import lombok.EqualsAndHashCode; | |
| 6 | +import lombok.ToString; | |
| 7 | + | |
| 8 | +@Schema(description = "管理后台 - 租户精简 Response VO") | |
| 9 | +@Data | |
| 10 | +@EqualsAndHashCode(callSuper = true) | |
| 11 | +@ToString(callSuper = true) | |
| 12 | +public class TenantSimpleRespVO extends TenantBaseVO { | |
| 13 | + | |
| 14 | + @Schema(description = "租户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | |
| 15 | + private Long id; | |
| 16 | + | |
| 17 | + @Schema(description = "租户名", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道") | |
| 18 | + private String name; | |
| 19 | + | |
| 20 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java
| 1 | 1 | package cn.iocoder.yudao.module.system.convert.tenant; |
| 2 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; | |
| 5 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExcelVO; | |
| 6 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; | |
| 7 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; | |
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.*; | |
| 8 | 5 | import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserCreateReqVO; |
| 9 | 6 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; |
| 10 | 7 | import org.mapstruct.Mapper; |
| ... | ... | @@ -28,6 +25,8 @@ public interface TenantConvert { |
| 28 | 25 | |
| 29 | 26 | TenantRespVO convert(TenantDO bean); |
| 30 | 27 | |
| 28 | + TenantSimpleRespVO convert03(TenantDO bean); | |
| 29 | + | |
| 31 | 30 | List<TenantRespVO> convertList(List<TenantDO> list); |
| 32 | 31 | |
| 33 | 32 | PageResult<TenantRespVO> convertPage(PageResult<TenantDO> page); | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantMapper.java
| ... | ... | @@ -42,6 +42,10 @@ public interface TenantMapper extends BaseMapperX<TenantDO> { |
| 42 | 42 | return selectOne(TenantDO::getName, name); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | + default TenantDO selectByWebsite(String website) { | |
| 46 | + return selectOne(TenantDO::getWebsite, website); | |
| 47 | + } | |
| 48 | + | |
| 45 | 49 | default Long selectCountByPackageId(Long packageId) { |
| 46 | 50 | return selectCount(TenantDO::getPackageId, packageId); |
| 47 | 51 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantService.java
| ... | ... | @@ -78,12 +78,20 @@ public interface TenantService { |
| 78 | 78 | /** |
| 79 | 79 | * 获得名字对应的租户 |
| 80 | 80 | * |
| 81 | - * @param name 组户名 | |
| 81 | + * @param name 租户名 | |
| 82 | 82 | * @return 租户 |
| 83 | 83 | */ |
| 84 | 84 | TenantDO getTenantByName(String name); |
| 85 | 85 | |
| 86 | 86 | /** |
| 87 | + * 获得域名对应的租户 | |
| 88 | + * | |
| 89 | + * @param website 域名 | |
| 90 | + * @return 租户 | |
| 91 | + */ | |
| 92 | + TenantDO getTenantByWebsite(String website); | |
| 93 | + | |
| 94 | + /** | |
| 87 | 95 | * 获得使用指定套餐的租户数量 |
| 88 | 96 | * |
| 89 | 97 | * @param packageId 租户套餐编号 |
| ... | ... | @@ -128,4 +136,5 @@ public interface TenantService { |
| 128 | 136 | * @param id 租户编号 |
| 129 | 137 | */ |
| 130 | 138 | void validTenant(Long id); |
| 139 | + | |
| 131 | 140 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
| ... | ... | @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.tenant; |
| 3 | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | 4 | import cn.hutool.core.lang.Assert; |
| 5 | 5 | import cn.hutool.core.util.ObjectUtil; |
| 6 | +import cn.hutool.core.util.StrUtil; | |
| 6 | 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 7 | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 8 | 9 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| ... | ... | @@ -99,6 +100,8 @@ public class TenantServiceImpl implements TenantService { |
| 99 | 100 | public Long createTenant(TenantCreateReqVO createReqVO) { |
| 100 | 101 | // 校验租户名称是否重复 |
| 101 | 102 | validTenantNameDuplicate(createReqVO.getName(), null); |
| 103 | + // 校验租户域名是否重复 | |
| 104 | + validTenantWebsiteDuplicate(createReqVO.getWebsite(), null); | |
| 102 | 105 | // 校验套餐被禁用 |
| 103 | 106 | TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(createReqVO.getPackageId()); |
| 104 | 107 | |
| ... | ... | @@ -143,6 +146,8 @@ public class TenantServiceImpl implements TenantService { |
| 143 | 146 | TenantDO tenant = validateUpdateTenant(updateReqVO.getId()); |
| 144 | 147 | // 校验租户名称是否重复 |
| 145 | 148 | validTenantNameDuplicate(updateReqVO.getName(), updateReqVO.getId()); |
| 149 | + // 校验租户域名是否重复 | |
| 150 | + validTenantWebsiteDuplicate(updateReqVO.getWebsite(), updateReqVO.getId()); | |
| 146 | 151 | // 校验套餐被禁用 |
| 147 | 152 | TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId()); |
| 148 | 153 | |
| ... | ... | @@ -169,6 +174,23 @@ public class TenantServiceImpl implements TenantService { |
| 169 | 174 | } |
| 170 | 175 | } |
| 171 | 176 | |
| 177 | + private void validTenantWebsiteDuplicate(String website, Long id) { | |
| 178 | + if (StrUtil.isEmpty(website)) { | |
| 179 | + return; | |
| 180 | + } | |
| 181 | + TenantDO tenant = tenantMapper.selectByWebsite(website); | |
| 182 | + if (tenant == null) { | |
| 183 | + return; | |
| 184 | + } | |
| 185 | + // 如果 id 为空,说明不用比较是否为相同名字的租户 | |
| 186 | + if (id == null) { | |
| 187 | + throw exception(TENANT_WEBSITE_DUPLICATE, website); | |
| 188 | + } | |
| 189 | + if (!tenant.getId().equals(id)) { | |
| 190 | + throw exception(TENANT_WEBSITE_DUPLICATE, website); | |
| 191 | + } | |
| 192 | + } | |
| 193 | + | |
| 172 | 194 | @Override |
| 173 | 195 | @DSTransactional |
| 174 | 196 | public void updateTenantRoleMenu(Long tenantId, Set<Long> menuIds) { |
| ... | ... | @@ -235,6 +257,11 @@ public class TenantServiceImpl implements TenantService { |
| 235 | 257 | } |
| 236 | 258 | |
| 237 | 259 | @Override |
| 260 | + public TenantDO getTenantByWebsite(String website) { | |
| 261 | + return tenantMapper.selectByWebsite(website); | |
| 262 | + } | |
| 263 | + | |
| 264 | + @Override | |
| 238 | 265 | public Long getTenantCountByPackageId(Long packageId) { |
| 239 | 266 | return tenantMapper.selectCountByPackageId(packageId); |
| 240 | 267 | } | ... | ... |
yudao-server/src/main/resources/application-local.yaml
| ... | ... | @@ -49,18 +49,18 @@ spring: |
| 49 | 49 | datasource: |
| 50 | 50 | master: |
| 51 | 51 | name: ruoyi-vue-pro |
| 52 | - # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 | |
| 52 | + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 | |
| 53 | 53 | # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 |
| 54 | 54 | # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.master.name} # PostgreSQL 连接的示例 |
| 55 | 55 | # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 |
| 56 | 56 | # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 |
| 57 | - url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 | |
| 58 | -# username: root | |
| 59 | -# password: 123456 | |
| 57 | +# url: jdbc:dm://10.211.55.4:5236?schema=RUOYI_VUE_PRO # DM 连接的示例 | |
| 58 | + username: root | |
| 59 | + password: 123456 | |
| 60 | 60 | # username: sa |
| 61 | 61 | # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W |
| 62 | - username: SYSDBA # DM 连接的示例 | |
| 63 | - password: SYSDBA # DM 连接的示例 | |
| 62 | +# username: SYSDBA # DM 连接的示例 | |
| 63 | +# password: SYSDBA # DM 连接的示例 | |
| 64 | 64 | slave: # 模拟从库,可根据自己需要修改 |
| 65 | 65 | name: ruoyi-vue-pro |
| 66 | 66 | lazy: true # 开启懒加载,保证启动速度 | ... | ... |
yudao-server/src/main/resources/application.yaml
| ... | ... | @@ -175,6 +175,7 @@ yudao: |
| 175 | 175 | enable: true |
| 176 | 176 | ignore-urls: |
| 177 | 177 | - /admin-api/system/tenant/get-id-by-name # 基于名字获取租户,不许带租户编号 |
| 178 | + - /admin-api/system/tenant/get-by-website # 基于域名获取租户,不许带租户编号 | |
| 178 | 179 | - /admin-api/system/captcha/get # 获取图片验证码,和租户无关 |
| 179 | 180 | - /admin-api/system/captcha/check # 校验图片验证码,和租户无关 |
| 180 | 181 | - /admin-api/infra/file/*/get/** # 获取图片,和租户无关 | ... | ... |