Commit 75928525ca13f0b8c211954c9dd4a64dad3c398a
1 parent
fa62ace6
1. 增加【默认】的系统租户的概念,禁止修改与删除等操作
2. 修复定时任务在刷新本地缓存时,会过滤租户的问题 3. 调整短信的回调地址,并进行租户的白名单
Showing
13 changed files
with
77 additions
and
40 deletions
yudao-module-pay/yudao-module-pay-impl/src/main/java/cn/iocoder/yudao/module/pay/service/merchant/PayChannelServiceImpl.java
| ... | ... | @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.pay.dal.dataobject.merchant.PayChannelDO; |
| 20 | 20 | import cn.iocoder.yudao.module.pay.dal.mysql.merchant.PayChannelMapper; |
| 21 | 21 | import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants; |
| 22 | 22 | import lombok.extern.slf4j.Slf4j; |
| 23 | +import org.springframework.context.annotation.Lazy; | |
| 23 | 24 | import org.springframework.scheduling.annotation.Scheduled; |
| 24 | 25 | import org.springframework.stereotype.Service; |
| 25 | 26 | import org.springframework.validation.annotation.Validated; |
| ... | ... | @@ -65,6 +66,10 @@ public class PayChannelServiceImpl implements PayChannelService { |
| 65 | 66 | @Resource |
| 66 | 67 | private Validator validator; |
| 67 | 68 | |
| 69 | + @Resource | |
| 70 | + @Lazy // 注入自己,所以延迟加载 | |
| 71 | + private PayChannelService self; | |
| 72 | + | |
| 68 | 73 | @Override |
| 69 | 74 | @PostConstruct |
| 70 | 75 | @TenantIgnore // 忽略自动化租户,全局初始化本地缓存 |
| ... | ... | @@ -86,7 +91,7 @@ public class PayChannelServiceImpl implements PayChannelService { |
| 86 | 91 | |
| 87 | 92 | @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) |
| 88 | 93 | public void schedulePeriodicRefresh() { |
| 89 | - initPayClients(); | |
| 94 | + self.initPayClients(); | |
| 90 | 95 | } |
| 91 | 96 | |
| 92 | 97 | /** | ... | ... |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| ... | ... | @@ -108,6 +108,7 @@ public interface ErrorCodeConstants { |
| 108 | 108 | ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002014000, "租户不存在"); |
| 109 | 109 | ErrorCode TENANT_DISABLE = new ErrorCode(1002014001, "名字为【{}】的租户已被禁用"); |
| 110 | 110 | ErrorCode TENANT_EXPIRE = new ErrorCode(1002014002, "名字为【{}】的租户已过期"); |
| 111 | + ErrorCode TENANT_CAN_NOT_UPDATE_SYSTEM = new ErrorCode(1002014003, "系统租户不能进行修改、删除等操作!"); | |
| 111 | 112 | |
| 112 | 113 | // ========== 租户套餐 1002015000 ========== |
| 113 | 114 | ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1002015000, "租户套餐不存在"); | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java
| ... | ... | @@ -19,7 +19,6 @@ import javax.servlet.http.HttpServletRequest; |
| 19 | 19 | |
| 20 | 20 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| 21 | 21 | |
| 22 | -// TODO 芋艿:这块的接口命名,在纠结下 | |
| 23 | 22 | @Api(tags = "管理后台 - 短信回调") |
| 24 | 23 | @RestController |
| 25 | 24 | @RequestMapping("/system/sms/callback") |
| ... | ... | @@ -28,7 +27,7 @@ public class SmsCallbackController { |
| 28 | 27 | @Resource |
| 29 | 28 | private SmsSendService smsSendService; |
| 30 | 29 | |
| 31 | - @PostMapping("/sms/yunpian") | |
| 30 | + @PostMapping("/yunpian") | |
| 32 | 31 | @ApiOperation(value = "云片短信的回调", notes = "参见 https://www.yunpian.com/official/document/sms/zh_cn/domestic_push_report 文档") |
| 33 | 32 | @ApiImplicitParam(name = "sms_status", value = "发送状态", required = true, example = "[{具体内容}]", dataTypeClass = String.class) |
| 34 | 33 | @OperateLog(enable = false) |
| ... | ... | @@ -38,7 +37,7 @@ public class SmsCallbackController { |
| 38 | 37 | return "SUCCESS"; // 约定返回 SUCCESS 为成功 |
| 39 | 38 | } |
| 40 | 39 | |
| 41 | - @PostMapping("/sms/aliyun") | |
| 40 | + @PostMapping("/aliyun") | |
| 42 | 41 | @ApiOperation(value = "阿里云短信的回调", notes = "参见 https://help.aliyun.com/document_detail/120998.html 文档") |
| 43 | 42 | @OperateLog(enable = false) |
| 44 | 43 | public CommonResult<Boolean> receiveAliyunSmsStatus(HttpServletRequest request) throws Throwable { | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java
| ... | ... | @@ -16,7 +16,6 @@ import org.springframework.web.bind.annotation.*; |
| 16 | 16 | |
| 17 | 17 | import javax.annotation.Resource; |
| 18 | 18 | import javax.validation.Valid; |
| 19 | -import java.util.Collection; | |
| 20 | 19 | import java.util.List; |
| 21 | 20 | |
| 22 | 21 | import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; |
| ... | ... | @@ -63,15 +62,6 @@ public class TenantPackageController { |
| 63 | 62 | return success(TenantPackageConvert.INSTANCE.convert(tenantPackage)); |
| 64 | 63 | } |
| 65 | 64 | |
| 66 | - @GetMapping("/list") | |
| 67 | - @ApiOperation("获得租户套餐列表") | |
| 68 | - @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class) | |
| 69 | - @PreAuthorize("@ss.hasPermission('system:tenant-package:query')") | |
| 70 | - public CommonResult<List<TenantPackageRespVO>> getTenantPackageList(@RequestParam("ids") Collection<Long> ids) { | |
| 71 | - List<TenantPackageDO> list = tenantPackageService.getTenantPackageList(ids); | |
| 72 | - return success(TenantPackageConvert.INSTANCE.convertList(list)); | |
| 73 | - } | |
| 74 | - | |
| 75 | 65 | @GetMapping("/page") |
| 76 | 66 | @ApiOperation("获得租户套餐分页") |
| 77 | 67 | @PreAuthorize("@ss.hasPermission('system:tenant-package:query')") | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/tenant/TenantDO.java
| ... | ... | @@ -23,6 +23,11 @@ import java.util.Date; |
| 23 | 23 | public class TenantDO extends BaseDO { |
| 24 | 24 | |
| 25 | 25 | /** |
| 26 | + * 套餐编号 - 系统 | |
| 27 | + */ | |
| 28 | + public static final Long PACKAGE_ID_SYSTEM = 0L; | |
| 29 | + | |
| 30 | + /** | |
| 26 | 31 | * 租户编号,自增 |
| 27 | 32 | */ |
| 28 | 33 | private Long id; |
| ... | ... | @@ -60,6 +65,7 @@ public class TenantDO extends BaseDO { |
| 60 | 65 | * 租户套餐编号 |
| 61 | 66 | * |
| 62 | 67 | * 关联 {@link TenantPackageDO#getId()} |
| 68 | + * 特殊逻辑:系统内置租户,不使用套餐,暂时使用 {@link #PACKAGE_ID_SYSTEM} 标识 | |
| 63 | 69 | */ |
| 64 | 70 | private Long packageId; |
| 65 | 71 | /** | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
| ... | ... | @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableMultimap; |
| 24 | 24 | import com.google.common.collect.Multimap; |
| 25 | 25 | import com.google.common.collect.Sets; |
| 26 | 26 | import lombok.extern.slf4j.Slf4j; |
| 27 | +import org.springframework.context.annotation.Lazy; | |
| 27 | 28 | import org.springframework.scheduling.annotation.Scheduled; |
| 28 | 29 | import org.springframework.stereotype.Service; |
| 29 | 30 | import org.springframework.transaction.annotation.Transactional; |
| ... | ... | @@ -90,6 +91,10 @@ public class PermissionServiceImpl implements PermissionService { |
| 90 | 91 | @Resource |
| 91 | 92 | private PermissionProducer permissionProducer; |
| 92 | 93 | |
| 94 | + @Resource | |
| 95 | + @Lazy // 注入自己,所以延迟加载 | |
| 96 | + private PermissionService self; | |
| 97 | + | |
| 93 | 98 | /** |
| 94 | 99 | * 初始化 {@link #roleMenuCache} 和 {@link #menuRoleCache} 缓存 |
| 95 | 100 | */ |
| ... | ... | @@ -118,7 +123,7 @@ public class PermissionServiceImpl implements PermissionService { |
| 118 | 123 | |
| 119 | 124 | @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) |
| 120 | 125 | public void schedulePeriodicRefresh() { |
| 121 | - initLocalCache(); | |
| 126 | + self.initLocalCache(); | |
| 122 | 127 | } |
| 123 | 128 | |
| 124 | 129 | /** | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java
| ... | ... | @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; |
| 20 | 20 | import cn.iocoder.yudao.module.system.mq.producer.permission.RoleProducer; |
| 21 | 21 | import com.google.common.annotations.VisibleForTesting; |
| 22 | 22 | import lombok.extern.slf4j.Slf4j; |
| 23 | +import org.springframework.context.annotation.Lazy; | |
| 23 | 24 | import org.springframework.lang.Nullable; |
| 24 | 25 | import org.springframework.scheduling.annotation.Scheduled; |
| 25 | 26 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -72,6 +73,10 @@ public class RoleServiceImpl implements RoleService { |
| 72 | 73 | @Resource |
| 73 | 74 | private RoleProducer roleProducer; |
| 74 | 75 | |
| 76 | + @Resource | |
| 77 | + @Lazy // 注入自己,所以延迟加载 | |
| 78 | + private RoleService self; | |
| 79 | + | |
| 75 | 80 | /** |
| 76 | 81 | * 初始化 {@link #roleCache} 缓存 |
| 77 | 82 | */ |
| ... | ... | @@ -93,7 +98,7 @@ public class RoleServiceImpl implements RoleService { |
| 93 | 98 | |
| 94 | 99 | @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD) |
| 95 | 100 | public void schedulePeriodicRefresh() { |
| 96 | - initLocalCache(); | |
| 101 | + self.initLocalCache(); | |
| 97 | 102 | } |
| 98 | 103 | |
| 99 | 104 | /** | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java
| ... | ... | @@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.Tenant |
| 7 | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; |
| 8 | 8 | |
| 9 | 9 | import javax.validation.Valid; |
| 10 | -import java.util.Collection; | |
| 11 | 10 | import java.util.List; |
| 12 | 11 | |
| 13 | 12 | /** |
| ... | ... | @@ -48,14 +47,6 @@ public interface TenantPackageService { |
| 48 | 47 | TenantPackageDO getTenantPackage(Long id); |
| 49 | 48 | |
| 50 | 49 | /** |
| 51 | - * 获得租户套餐列表 | |
| 52 | - * | |
| 53 | - * @param ids 编号 | |
| 54 | - * @return 租户套餐列表 | |
| 55 | - */ | |
| 56 | - List<TenantPackageDO> getTenantPackageList(Collection<Long> ids); | |
| 57 | - | |
| 58 | - /** | |
| 59 | 50 | * 获得租户套餐分页 |
| 60 | 51 | * |
| 61 | 52 | * @param pageReqVO 分页查询 | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java
| ... | ... | @@ -16,7 +16,6 @@ import org.springframework.transaction.annotation.Transactional; |
| 16 | 16 | import org.springframework.validation.annotation.Validated; |
| 17 | 17 | |
| 18 | 18 | import javax.annotation.Resource; |
| 19 | -import java.util.Collection; | |
| 20 | 19 | import java.util.List; |
| 21 | 20 | |
| 22 | 21 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -92,11 +91,6 @@ public class TenantPackageServiceImpl implements TenantPackageService { |
| 92 | 91 | } |
| 93 | 92 | |
| 94 | 93 | @Override |
| 95 | - public List<TenantPackageDO> getTenantPackageList(Collection<Long> ids) { | |
| 96 | - return tenantPackageMapper.selectBatchIds(ids); | |
| 97 | - } | |
| 98 | - | |
| 99 | - @Override | |
| 100 | 94 | public PageResult<TenantPackageDO> getTenantPackagePage(TenantPackagePageReqVO pageReqVO) { |
| 101 | 95 | return tenantPackageMapper.selectPage(pageReqVO); |
| 102 | 96 | } | ... | ... |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
| ... | ... | @@ -16,6 +16,7 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantEx |
| 16 | 16 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; |
| 17 | 17 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; |
| 18 | 18 | import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; |
| 19 | +import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; | |
| 19 | 20 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; |
| 20 | 21 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; |
| 21 | 22 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; |
| ... | ... | @@ -23,6 +24,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; |
| 23 | 24 | import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; |
| 24 | 25 | import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; |
| 25 | 26 | import cn.iocoder.yudao.module.system.mq.producer.tenant.TenantProducer; |
| 27 | +import cn.iocoder.yudao.module.system.service.permission.MenuService; | |
| 26 | 28 | import cn.iocoder.yudao.module.system.service.permission.PermissionService; |
| 27 | 29 | import cn.iocoder.yudao.module.system.service.permission.RoleService; |
| 28 | 30 | import cn.iocoder.yudao.module.system.service.tenant.handler.TenantInfoHandler; |
| ... | ... | @@ -86,6 +88,8 @@ public class TenantServiceImpl implements TenantService { |
| 86 | 88 | @Resource |
| 87 | 89 | private RoleService roleService; |
| 88 | 90 | @Resource |
| 91 | + private MenuService menuService; | |
| 92 | + @Resource | |
| 89 | 93 | private PermissionService permissionService; |
| 90 | 94 | |
| 91 | 95 | @Resource |
| ... | ... | @@ -205,7 +209,7 @@ public class TenantServiceImpl implements TenantService { |
| 205 | 209 | @Transactional(rollbackFor = Exception.class) |
| 206 | 210 | public void updateTenant(TenantUpdateReqVO updateReqVO) { |
| 207 | 211 | // 校验存在 |
| 208 | - TenantDO tenant = validateTenantExists(updateReqVO.getId()); | |
| 212 | + TenantDO tenant = checkUpdateTenant(updateReqVO.getId()); | |
| 209 | 213 | // 校验套餐被禁用 |
| 210 | 214 | TenantPackageDO tenantPackage = tenantPackageService.validTenantPackage(updateReqVO.getPackageId()); |
| 211 | 215 | |
| ... | ... | @@ -253,16 +257,20 @@ public class TenantServiceImpl implements TenantService { |
| 253 | 257 | @Override |
| 254 | 258 | public void deleteTenant(Long id) { |
| 255 | 259 | // 校验存在 |
| 256 | - validateTenantExists(id); | |
| 260 | + checkUpdateTenant(id); | |
| 257 | 261 | // 删除 |
| 258 | 262 | tenantMapper.deleteById(id); |
| 259 | 263 | } |
| 260 | 264 | |
| 261 | - private TenantDO validateTenantExists(Long id) { | |
| 265 | + private TenantDO checkUpdateTenant(Long id) { | |
| 262 | 266 | TenantDO tenant = tenantMapper.selectById(id); |
| 263 | 267 | if (tenant == null) { |
| 264 | 268 | throw exception(TENANT_NOT_EXISTS); |
| 265 | 269 | } |
| 270 | + // 内置租户,不允许删除 | |
| 271 | + if (isSystemTenant(tenant)) { | |
| 272 | + throw exception(TENANT_CAN_NOT_UPDATE_SYSTEM); | |
| 273 | + } | |
| 266 | 274 | return tenant; |
| 267 | 275 | } |
| 268 | 276 | |
| ... | ... | @@ -321,9 +329,18 @@ public class TenantServiceImpl implements TenantService { |
| 321 | 329 | } |
| 322 | 330 | // 获得租户,然后获得菜单 |
| 323 | 331 | TenantDO tenant = getTenant(TenantContextHolder.getRequiredTenantId()); |
| 324 | - TenantPackageDO tenantPackage = tenantPackageService.getTenantPackage(tenant.getPackageId()); | |
| 332 | + Set<Long> menuIds; | |
| 333 | + if (isSystemTenant(tenant)) { // 系统租户,菜单是全量的 | |
| 334 | + menuIds = CollectionUtils.convertSet(menuService.getMenus(), MenuDO::getId); | |
| 335 | + } else { | |
| 336 | + menuIds = tenantPackageService.getTenantPackage(tenant.getPackageId()).getMenuIds(); | |
| 337 | + } | |
| 325 | 338 | // 执行处理器 |
| 326 | - handler.handle(tenantPackage.getMenuIds()); | |
| 339 | + handler.handle(menuIds); | |
| 340 | + } | |
| 341 | + | |
| 342 | + private static boolean isSystemTenant(TenantDO tenant) { | |
| 343 | + return Objects.equals(tenant.getPackageId(), TenantDO.PACKAGE_ID_SYSTEM); | |
| 327 | 344 | } |
| 328 | 345 | |
| 329 | 346 | } | ... | ... |
yudao-server/src/main/resources/application.yaml
| ... | ... | @@ -79,8 +79,31 @@ yudao: |
| 79 | 79 | - cn.iocoder.yudao.module.tool.enums.ErrorCodeConstants |
| 80 | 80 | tenant: # 多租户相关配置项 |
| 81 | 81 | enable: true |
| 82 | - ignore-urls: /admin-api/system/tenant/get-id-by-name, /admin-api/system/captcha/get-image, /admin-api/infra/file/get/* | |
| 83 | - ignore-tables: infra_config, infra_file, infra_job, infra_job_log, infra_job_log, system_tenant, system_tenant_package, system_dict_data, system_dict_type, system_error_code, system_menu, system_sms_channel, system_sms_template, tool_codegen_column, tool_codegen_table, tool_test_demo, tables, columns | |
| 82 | + ignore-urls: | |
| 83 | + - /admin-api/system/tenant/get-id-by-name | |
| 84 | + - /admin-api/system/captcha/get-image | |
| 85 | + - /admin-api/infra/file/get/* | |
| 86 | + - /admin-api/system/sms/callback/* | |
| 87 | + ignore-tables: | |
| 88 | + - infra_config | |
| 89 | + - infra_file | |
| 90 | + - infra_job | |
| 91 | + - infra_job_log | |
| 92 | + - infra_job_log | |
| 93 | + - system_tenant | |
| 94 | + - system_tenant_package | |
| 95 | + - system_dict_data | |
| 96 | + - system_dict_type | |
| 97 | + - system_error_code | |
| 98 | + - system_menu | |
| 99 | + - system_sms_channel | |
| 100 | + - system_sms_template | |
| 101 | + - system_sms_log | |
| 102 | + - tool_codegen_column | |
| 103 | + - tool_codegen_table | |
| 104 | + - tool_test_demo | |
| 105 | + - tables | |
| 106 | + - columns | |
| 84 | 107 | sms-code: # 短信验证码相关的配置项 |
| 85 | 108 | expire-times: 10m |
| 86 | 109 | send-frequency: 1m | ... | ... |
yudao-ui-admin/src/views/system/tenant/index.vue
| ... | ... | @@ -43,7 +43,8 @@ |
| 43 | 43 | <el-table-column label="租户名" align="center" prop="name" /> |
| 44 | 44 | <el-table-column label="租户套餐" align="center" prop="packageId"> |
| 45 | 45 | <template slot-scope="scope"> |
| 46 | - <el-tag> {{getPackageName(scope.row.packageId)}} </el-tag> | |
| 46 | + <el-tag v-if="scope.row.packageId === 0" type="danger">系统租户</el-tag> | |
| 47 | + <el-tag v-else> {{getPackageName(scope.row.packageId)}} </el-tag> | |
| 47 | 48 | </template> |
| 48 | 49 | </el-table-column> |
| 49 | 50 | <el-table-column label="联系人" align="center" prop="contactName" /> | ... | ... |