Browse Source

新建

master
1 week ago
commit
a817943dde
  1. 17
      application-tenant/pom.xml
  2. 152
      application-tenant/tenant-admin/pom.xml
  3. 26
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/TenantAdminApplication.java
  4. 59
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/ApplicationConfig.java
  5. 50
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/DataSourceType.java
  6. 61
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/FilterConfig.java
  7. 24
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/InterceptorConfig.java
  8. 66
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/MultiDataSourceConfig.java
  9. 167
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/interceptor/AuthenticationInterceptor.java
  10. 37
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/Enum/FunctionTypeEnum.java
  11. 252
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DeployPluginController.java
  12. 58
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysMessageController.java
  13. 195
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantController.java
  14. 204
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantDatasourceController.java
  15. 167
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantMenuController.java
  16. 171
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantPermCodeController.java
  17. 156
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantPermController.java
  18. 174
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantPermModuleController.java
  19. 621
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantRoleController.java
  20. 506
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/TenantGlobalDictController.java
  21. 20
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/DeployPluginMapper.java
  22. 13
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantDatasourceMapper.java
  23. 13
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantExtMapper.java
  24. 83
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantMapper.java
  25. 36
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantMenuMapper.java
  26. 22
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantMenuPermCodeMapper.java
  27. 13
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermCodeMapper.java
  28. 22
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermCodePermMapper.java
  29. 13
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermMapper.java
  30. 22
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermModuleMapper.java
  31. 26
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleMapper.java
  32. 22
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleMenuMapper.java
  33. 22
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleOnlinePageMapper.java
  34. 22
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleReportDatasetMapper.java
  35. 22
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleTenantMapper.java
  36. 10
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/DeployPluginMapper.xml
  37. 19
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantDatasourceMapper.xml
  38. 8
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantExtMapper.xml
  39. 184
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantMapper.xml
  40. 52
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantMenuMapper.xml
  41. 15
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantMenuPermCodeMapper.xml
  42. 17
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermCodeMapper.xml
  43. 15
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermCodePermMapper.xml
  44. 16
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermMapper.xml
  45. 44
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermModuleMapper.xml
  46. 33
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleMapper.xml
  47. 15
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleMenuMapper.xml
  48. 15
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleOnlinePageMapper.xml
  49. 15
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleReportDatasetMapper.xml
  50. 15
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleTenantMapper.xml
  51. 81
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantDatasourceDto.java
  52. 66
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantDto.java
  53. 86
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantMenuDto.java
  54. 63
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantPermCodeDto.java
  55. 54
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantPermDto.java
  56. 56
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantPermModuleDto.java
  57. 33
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantRoleDto.java
  58. 27
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantRoleMenuDto.java
  59. 27
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantRoleTenantDto.java
  60. 101
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/DeployPlugin.java
  61. 89
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenant.java
  62. 74
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantDatasource.java
  63. 30
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantExt.java
  64. 127
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantMenu.java
  65. 28
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantMenuPermCode.java
  66. 66
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPerm.java
  67. 98
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPermCode.java
  68. 28
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPermCodePerm.java
  69. 60
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPermModule.java
  70. 46
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRole.java
  71. 28
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleMenu.java
  72. 28
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleOnlinePage.java
  73. 28
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleReportDataset.java
  74. 28
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleTenant.java
  75. 13
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/plugin/Plugin.java
  76. 200
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/plugin/PluginService.java
  77. 33
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/quartz/job/MySyncEasFlowQuartzJob.java
  78. 34
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/quartz/job/MySyncEasUserQuartzJob.java
  79. 46
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/IDeployPluginService.java
  80. 40
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantDatasourceService.java
  81. 82
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantMenuService.java
  82. 65
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantPermCodeService.java
  83. 66
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantPermModuleService.java
  84. 51
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantPermService.java
  85. 179
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantRoleService.java
  86. 100
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantService.java
  87. 226
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/DeployPluginServiceImpl.java
  88. 73
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantDatasourceServiceImpl.java
  89. 287
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantMenuServiceImpl.java
  90. 228
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantPermCodeServiceImpl.java
  91. 175
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantPermModuleServiceImpl.java
  92. 190
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantPermServiceImpl.java
  93. 644
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantRoleServiceImpl.java
  94. 245
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantServiceImpl.java
  95. 129
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/test/Tt.java
  96. 21
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/DeployPluginVo.java
  97. 72
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantDatasourceVo.java
  98. 93
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantMenuVo.java
  99. 63
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantPermCodeVo.java
  100. 57
      application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantPermModuleVo.java
  101. Some files were not shown because too many files have changed in this diff Show More

17
application-tenant/pom.xml

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>apelet</groupId>
<artifactId>apelet_saas</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>application-tenant</artifactId>
<packaging>pom</packaging>
<modules>
<module>tenant-admin</module>
</modules>
</project>

152
application-tenant/tenant-admin/pom.xml

@ -0,0 +1,152 @@ @@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>application-tenant</artifactId>
<groupId>apelet</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tenant-admin</artifactId>
<version>1.0.0</version>
<name>tenant-admin</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.anji-plus</groupId>
<artifactId>spring-boot-starter-captcha</artifactId>
<version>${ajcaptcha.version}</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-qy</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-redis</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-ext</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-dict</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-datafilter</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-mobile</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-core</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-log</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-datasync</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-aliyun-oss</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-dbutil</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-swagger</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-generator</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-eas</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>apelet</groupId>
<artifactId>common-online</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatisplus.version}</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-base</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-web</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>cn.afterturn</groupId>
<artifactId>easypoi-annotation</artifactId>
<version>4.4.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.0.1</version>
</dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.3.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version> <!-- 确保使用最新的稳定版本 -->
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
</plugin>
</plugins>
</build>
</project>

26
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/TenantAdminApplication.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package apelet.tenantadmin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* 租户运营管理服务启动类
*
* @author guifc
* @date 2023-08-04
*/
@ComponentScan("apelet")
@EnableScheduling
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@MapperScan("apelet.common.**.dao")
public class TenantAdminApplication {
public static void main(String[] args) {
SpringApplication.run(TenantAdminApplication.class, args);
}
}

59
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/ApplicationConfig.java

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
package apelet.tenantadmin.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 租户运营管理服务的配置类
*
* @author guifc
* @date 2023-08-04
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "application")
public class ApplicationConfig {
/**
* token的Http Request Header的key
*/
private String tokenHeaderKey;
/**
* token在过期之前但是已经需要被刷新时response返回的header信息的key
*/
private String refreshedTokenHeaderKey;
/**
* token 加密用的密钥该值的长度最少10个字符(过短会报错)
*/
private String tokenSigningKey;
/**
* 令牌的过期时间单位毫秒
*/
private Long expiration;
/**
* 用户密码被重置之后的缺省密码
*/
private String defaultUserPassword;
/**
* 上传文件的基础目录
*/
private String uploadFileBaseDir;
/**
* 授信ip列表没有填写表示全部信任多个ip之间逗号分隔: http://10.10.10.1:8080,http://10.10.10.2:8080
*/
private String credentialIpList;
/**
* 发送租户的同步数据到消息队列的主题
*/
private String tenantSyncTopic;
/**
* Session会话和用户权限在Redis中的过期时间()
* 缺省值是 one day
*/
private int sessionExpiredSeconds = 86400;
/**
* 是否排他登录
*/
private Boolean excludeLogin = false;
}

50
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/DataSourceType.java

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
package apelet.tenantadmin.config;
import apelet.common.core.constant.ApplicationConstant;
import java.util.HashMap;
import java.util.Map;
/**
* 表示数据源类型的常量对象
*
* @author guifc
* @date 2023-08-04
*/
public final class DataSourceType {
/**
* 租户管理数据源
*/
public static final int TENANT_ADMIN = ApplicationConstant.TENANT_ADMIN_DATASOURCE_TYPE;
/**
* 租户业务通用数据源如全局编码字典在线表单流程和报表等数据
*/
public static final int TENANT_COMMON = ApplicationConstant.TENANT_COMMON_DATASOURCE_TYPE;
public static final int OPERATION_LOG = ApplicationConstant.OPERATION_LOG_DATASOURCE_TYPE;
public static final int GLOBAL_DICT = ApplicationConstant.COMMON_GLOBAL_DICT_TYPE;
private static final Map<String, Integer> TYPE_MAP = new HashMap<>(2);
static {
TYPE_MAP.put("tenant-admin", TENANT_ADMIN);
TYPE_MAP.put("tenant-common", TENANT_COMMON);
TYPE_MAP.put("operation-log", OPERATION_LOG);
TYPE_MAP.put("global-dict", GLOBAL_DICT);
}
/**
* 根据名称获取字典类型
*
* @param name 数据源在配置中的名称
* @return 返回可用于多数据源切换的数据源类型
*/
public static Integer getDataSourceTypeByName(String name) {
return TYPE_MAP.get(name);
}
/**
* 私有构造函数明确标识该常量类的作用
*/
private DataSourceType() {
}
}

61
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/FilterConfig.java

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
package apelet.tenantadmin.config;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import javax.servlet.Filter;
import java.nio.charset.StandardCharsets;
/**
* 这里主要配置Web的各种过滤器和监听器等Servlet容器组件
*
* @author guifc
* @date 2023-08-04
*/
@Configuration
public class FilterConfig {
/**
* 配置Ajax跨域过滤器
*/
@Bean
public CorsFilter corsFilterRegistration(ApplicationConfig applicationConfig) {
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
if (StringUtils.isNotBlank(applicationConfig.getCredentialIpList())) {
if ("*".equals(applicationConfig.getCredentialIpList())) {
corsConfiguration.addAllowedOriginPattern("*");
} else {
String[] credentialIpList = StringUtils.split(applicationConfig.getCredentialIpList(), ",");
if (credentialIpList.length > 0) {
for (String ip : credentialIpList) {
corsConfiguration.addAllowedOrigin(ip);
}
}
}
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addExposedHeader(applicationConfig.getRefreshedTokenHeaderKey());
corsConfiguration.setAllowCredentials(true);
configSource.registerCorsConfiguration("/**", corsConfiguration);
}
return new CorsFilter(configSource);
}
@Bean
public FilterRegistrationBean<Filter> characterEncodingFilterRegistration() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(
new org.springframework.web.filter.CharacterEncodingFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("encoding", StandardCharsets.UTF_8.name());
// forceEncoding强制response也被编码,另外即使request中已经设置encoding,forceEncoding也会重新设置
filterRegistrationBean.addInitParameter("forceEncoding", "true");
filterRegistrationBean.setAsyncSupported(true);
return filterRegistrationBean;
}
}

24
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/InterceptorConfig.java

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
package apelet.tenantadmin.config;
import apelet.tenantadmin.interceptor.AuthenticationInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 所有的项目拦截器都在这里集中配置
*
* @author guifc
* @date 2023-08-04
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthenticationInterceptor())
.addPathPatterns("/tenantadmin/**")
.addPathPatterns("/botp/**")
.addPathPatterns("/api/data-move/**");
}
}

66
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/config/MultiDataSourceConfig.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
package apelet.tenantadmin.config;
import apelet.common.core.config.BaseMultiDataSourceConfig;
import apelet.common.core.config.DynamicDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* 多数据源配置对象
*
* @author guifc
* @date 2023-08-04
*/
@Configuration
@EnableTransactionManagement
@MapperScan(value = {"apelet.tenantadmin.upms.dao","apelet.tenantadmin.tenant.dao", "apelet.common.*.dao"})
public class MultiDataSourceConfig extends BaseMultiDataSourceConfig {
@Bean(initMethod = "init", destroyMethod = "close")
@ConfigurationProperties(prefix = "spring.datasource.druid.tenant-admin")
public DataSource tenantAdminDataSource() {
return super.applyCommonProps(DruidDataSourceBuilder.create().build());
}
/**
* 默认生成的用于保存租户业务通用数据的数据源如全局编码字典在线表单工作流和报表打印等基础数据
* 我们还是非常推荐使用独立的数据源这样便于今后的数据迁移
*/
@Bean(initMethod = "init", destroyMethod = "close")
@ConfigurationProperties(prefix = "spring.datasource.druid.tenant-common")
public DataSource tenantCommonDataSource() {
return super.applyCommonProps(DruidDataSourceBuilder.create().build());
}
/**
* 默认生成的用于保存操作日志的数据源可根据需求修改
* 我们还是非常推荐使用独立的数据源这样便于今后的数据迁移
*/
@Bean(initMethod = "init", destroyMethod = "close")
@ConfigurationProperties(prefix = "spring.datasource.druid.operation-log")
public DataSource operationLogDataSource() {
return super.applyCommonProps(DruidDataSourceBuilder.create().build());
}
@Bean
@Primary
public DynamicDataSource dataSource() {
Map<Object, Object> targetDataSources = new HashMap<>(3);
targetDataSources.put(DataSourceType.TENANT_ADMIN, tenantAdminDataSource());
targetDataSources.put(DataSourceType.TENANT_COMMON, tenantCommonDataSource());
targetDataSources.put(DataSourceType.OPERATION_LOG, operationLogDataSource());
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(tenantAdminDataSource());
return dynamicDataSource;
}
}

167
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/interceptor/AuthenticationInterceptor.java

@ -0,0 +1,167 @@ @@ -0,0 +1,167 @@
package apelet.tenantadmin.interceptor;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.common.core.cache.CacheConfig;
import apelet.common.core.annotation.NoAuthInterface;
import apelet.common.core.constant.ApplicationConstant;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.ResponseResult;
import apelet.common.core.object.TokenData;
import apelet.common.core.util.ApplicationContextHolder;
import apelet.common.core.util.JwtUtil;
import apelet.common.core.util.RedisKeyUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RSet;
import org.redisson.api.RedissonClient;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.util.Assert;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 登录用户Token验证生成和权限验证的拦截器
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
public class AuthenticationInterceptor implements HandlerInterceptor {
private final ApplicationConfig appConfig =
ApplicationContextHolder.getBean("applicationConfig");
private final RedissonClient redissonClient = ApplicationContextHolder.getBean(RedissonClient.class);
private final CacheManager cacheManager = ApplicationContextHolder.getBean("caffeineCacheManager");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String url = request.getRequestURI();
String token = this.getTokenFromRequest(request);
boolean noLoginUrl = this.isNoAuthInterface(handler);
// 如果接口方法标记NoAuthInterface注解,可以直接跳过Token鉴权验证,这里主要为了测试接口方便
if (noLoginUrl && StrUtil.isBlank(token)) {
return true;
}
Claims c = JwtUtil.parseToken(token, appConfig.getTokenSigningKey());
if (JwtUtil.isNullOrExpired(c)) {
// 如果免登陆接口携带的是过期的Token,这个时候直接返回给Controller即可。
// 这样可以规避不必要的重新登录,而对于Controller,可以将本次请求视为未登录用户的请求。
if (noLoginUrl) {
return true;
}
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
this.outputResponseMessage(response,
ResponseResult.error(ErrorCodeEnum.UNAUTHORIZED_LOGIN, "用户会话已过期或尚未登录,请重新登录!"));
return false;
}
String sessionId = (String) c.get("sessionId");
String sessionIdKey = RedisKeyUtil.makeSessionIdKey(sessionId);
RBucket<String> sessionData = redissonClient.getBucket(sessionIdKey);
TokenData tokenData = null;
if (sessionData.isExists()) {
tokenData = JSON.parseObject(sessionData.get(), TokenData.class);
}
if (tokenData == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
this.outputResponseMessage(response,
ResponseResult.error(ErrorCodeEnum.UNAUTHORIZED_LOGIN, "用户会话已失效,请重新登录!"));
return false;
}
tokenData.setToken(token);
TokenData.addToRequest(tokenData);
// 如果url是免登陆、白名单中,则不需要进行鉴权操作
if (!noLoginUrl && Boolean.FALSE.equals(tokenData.getIsAdmin()) && !this.hasPermission(sessionId, url)) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
this.outputResponseMessage(response, ResponseResult.error(ErrorCodeEnum.NO_OPERATION_PERMISSION));
return false;
}
if (JwtUtil.needToRefresh(c)) {
Map<String, Object> newClains = new HashMap<>(c.size());
newClains.putAll(c);
String refreshedToken = JwtUtil.generateToken(newClains, appConfig.getExpiration(), appConfig.getTokenSigningKey());
response.addHeader(appConfig.getRefreshedTokenHeaderKey(), refreshedToken);
}
return true;
}
@SuppressWarnings("unchecked")
private boolean hasPermission(String sessionId, String url) {
// 为了提升效率,先检索Caffeine的一级缓存,如果不存在,再检索Redis的二级缓存,并将结果存入一级缓存。
Set<String> localPermSet;
String permKey = RedisKeyUtil.makeSessionPermIdKey(sessionId);
Cache cache = cacheManager.getCache(CacheConfig.CacheEnum.USER_PERMISSION_CACHE.name());
Assert.notNull(cache, "Cache USER_PERMISSION_CACHE can't be NULL.");
Cache.ValueWrapper wrapper = cache.get(permKey);
if (wrapper == null) {
RSet<String> permSet = redissonClient.getSet(permKey);
localPermSet = permSet.readAll();
cache.put(permKey, localPermSet);
} else {
localPermSet = (Set<String>) wrapper.get();
}
return CollUtil.contains(localPermSet, url);
}
private boolean isNoAuthInterface(Object handler) {
if (handler instanceof HandlerMethod) {
HandlerMethod hm = (HandlerMethod) handler;
return hm.getBeanType().getAnnotation(NoAuthInterface.class) != null
|| hm.getMethodAnnotation(NoAuthInterface.class) != null;
}
return false;
}
private String getTokenFromRequest(HttpServletRequest request) {
String token = request.getHeader(appConfig.getTokenHeaderKey());
if (StrUtil.isBlank(token)) {
token = request.getParameter(appConfig.getTokenHeaderKey());
}
if (StrUtil.isBlank(token)) {
token = request.getHeader(ApplicationConstant.HTTP_HEADER_INTERNAL_TOKEN);
}
return token;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 这里需要空注解,否则sonar会不happy。
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// 这里需要空注解,否则sonar会不happy。
}
private void outputResponseMessage(HttpServletResponse response, ResponseResult<Object> respObj) {
PrintWriter out;
try {
out = response.getWriter();
} catch (IOException e) {
log.error("Failed to call OutputResponseMessage.", e);
return;
}
response.setContentType("application/json; charset=utf-8");
out.print(JSON.toJSONString(respObj));
out.flush();
out.close();
}
}

37
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/Enum/FunctionTypeEnum.java

@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
package apelet.tenantadmin.tenant.Enum;
/**
* 参数类型
*/
public enum FunctionTypeEnum {
VARCHAR(1, "字符串"),
INT(2, "数值"),
DATE(3, "日期"),
LONG(4, "整型"),
OBJECT(5, "对象"),
VARCHAR_ARRAY(6, "字符串数组"),
INT_ARRAY(7, "数值数组"),
DATE_ARRAY(8, "日期数组"),
LONG_ARRAY(9, "整型数组"),
OBJECT_ARRAY(10, "对象数组");
private final Integer code;
private final String description;
FunctionTypeEnum(Integer code, String description) {
this.code = code;
this.description = description;
}
public Integer getCode() {
return code;
}
public String getDescription() {
return description;
}
}

252
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/DeployPluginController.java

@ -0,0 +1,252 @@ @@ -0,0 +1,252 @@
package apelet.tenantadmin.tenant.controller;
import apelet.common.aliyun.oss.util.AliyunOssUpDownloader;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.*;
import apelet.common.core.upload.*;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyModelUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.common.online.config.OnlineProperties;
import apelet.common.redis.cache.SessionCacheHelper;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.model.DeployPlugin;
import apelet.tenantadmin.tenant.plugin.PluginService;
import apelet.tenantadmin.tenant.service.IDeployPluginService;
import apelet.tenantadmin.upms.model.SysUser;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.page.PageMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.servlet.http.HttpServletResponse;
import javax.validation.groups.Default;
import java.io.*;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* <p>
* 热部署插件表 前端控制器
* </p>
*
* @author admin
* @since 2024-06-27 14:58:01
*/
@RestController
@RequestMapping("/tenantadmin/tenant/deployPlugin")
public class DeployPluginController {
@Autowired
private IDeployPluginService deployPluginService;
@Autowired
PluginService pluginService;
@Autowired
private ApplicationConfig appConfig;
@Autowired
private SessionCacheHelper cacheHelper;
@Autowired
private UpDownloaderFactory upDownloaderFactory;
@Autowired
LocalUpDownloader localUpDownloader;
@Autowired
private OnlineProperties onlineProperties;
// @Autowired
// AliyunOssUpDownloader aliyunOssUpDownloader;
/**
* 列表接口
*
* @param DeployPlugin
* @param orderParam
* @param pageParam
* @return
*/
@PostMapping(value = "/list")
public ResponseResult<?> list(@MyRequestBody DeployPlugin DeployPlugin,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
List<DeployPlugin> deployPluginList = deployPluginService.getDeployPluginList(
DeployPlugin, MyOrderParam.buildOrderBy(orderParam, DeployPlugin.class)
);
return ResponseResult.success(MyPageUtil.makeResponseData(deployPluginList, DeployPlugin.INSTANCE));
}
/**
* 新增
*
* @param deployPlugin
* @return
*/
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<?> add(@RequestBody DeployPlugin deployPlugin) {
deployPlugin.setCreateTime(new Date());
String errorMessage = MyCommonUtil.getModelValidationError(deployPlugin);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
deployPlugin.setSubmitTime(new Date());
deployPluginService.save(deployPlugin);
return ResponseResult.success(deployPlugin);
}
/**
* 修改
*
* @param deployPlugin
* @return
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<?> update(@RequestBody DeployPlugin deployPlugin) {
String errorMessage = MyCommonUtil.getModelValidationError(deployPlugin, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!deployPluginService.updateById(deployPlugin)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除
*
* @param id
* @return
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<?> delete(@RequestBody Long id) {
if (MyCommonUtil.existBlankArgument(id)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
if (!deployPluginService.removeById(id)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
@PostMapping("/reloadPlugin")
public ResponseResult<?> reloadPlugin(@MyRequestBody List<Long> ids) {
List<String> pluginNameList = deployPluginService.reloadPlugin(ids);
return ResponseResult.success(pluginNameList);
}
@PostMapping("/executePlugin")
public ResponseResult<?> executePlugin(@RequestBody String s) {
JSONObject jsonObject = JSON.parseObject(s);
String pluginName = jsonObject.getString("pluginName");
Map<String, Object> params = (Map<String, Object>) jsonObject.get("pluginData");
Object value = deployPluginService.executePlugin(pluginName, params);
return ResponseResult.success(value);
}
/**
* 文件上传操作
*
* @param fieldName 上传文件名
* @param asImage 是否作为图片上传如果是图片今后下载的时候无需权限验证否则就是附件上传下载时需要权限验证
* @param uploadFile 上传文件对象
*/
@OperationLog(type = SysOperationLogType.UPLOAD, saveResponse = false)
@PostMapping("/upload")
public void upload(
@RequestParam String fieldName,
@RequestParam Boolean asImage,
@RequestParam("file") MultipartFile uploadFile) throws Exception {
InputStream inputStream = uploadFile.getInputStream();
// 生成密钥
SecretKey secretKey = generateKey();
// 加密数据
byte[] encryptedData = encrypt(inputStream, secretKey);
// 将加密后的数据转换为InputStream
InputStream encryptedInputStream = new ByteArrayInputStream(encryptedData);
// 解密数据
InputStream decryptedInputStream = decrypt(encryptedInputStream, secretKey);
UploadStoreTypeEnum uploadStoreType = UploadStoreTypeEnum.values()[onlineProperties.getDistributeStoreType()];
BaseUpDownloader upDownloader = upDownloaderFactory.get(uploadStoreType);
UploadResponseInfo responseInfo = upDownloader.doUpload(
"",
appConfig.getUploadFileBaseDir(),
DeployPlugin.class.getSimpleName(),
"",
false,
uploadFile);
if (Boolean.TRUE.equals(responseInfo.getUploadFailed())) {
ResponseResult.output(HttpServletResponse.SC_FORBIDDEN,
ResponseResult.error(ErrorCodeEnum.UPLOAD_FAILED, responseInfo.getErrorMessage()));
return;
}
cacheHelper.putSessionUploadFile(responseInfo.getFilename());
ResponseResult.output(ResponseResult.success(responseInfo));
}
private static SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
return keyGenerator.generateKey();
}
private static byte[] encrypt(InputStream inputStream, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(cipher.update(buffer, 0, bytesRead));
}
outputStream.write(cipher.doFinal());
return outputStream.toByteArray();
}
private static InputStream decrypt(InputStream encryptedInputStream, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = encryptedInputStream.read(buffer)) != -1) {
outputStream.write(cipher.update(buffer, 0, bytesRead));
}
outputStream.write(cipher.doFinal());
return new ByteArrayInputStream(outputStream.toByteArray());
}
}

58
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysMessageController.java

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
package apelet.tenantadmin.tenant.controller;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.object.*;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.common.online.service.SysMessageService;
import com.github.pagehelper.page.PageMethod;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/tenantadmin/tenant/sysMessage")
public class SysMessageController {
@Autowired
private SysMessageService sysMessageService;
/**
* 消息列表接口
*
* @param
* @param pageParam
* @return
*/
@PostMapping(value = "/list")
public ResponseResult<?> list(
@MyRequestBody MyPageParam pageParam,
@MyRequestBody(required =false) String readStatus) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
Map<String, Object> pammap= new HashMap<String, Object>();
if(readStatus!=null){
pammap.put("readStatus",readStatus);
}
TokenData tokenData = TokenData.takeFromRequest();
pammap.put("receiveUserId",tokenData.getUserId());
MyPageData<Map<String, Object>> list = sysMessageService.getUserMessagelist(pammap,pageParam);
return ResponseResult.success(list);
}
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(
@MyRequestBody String entryId){
Map<String, Object> map = new HashMap<String, Object>();
map.put("entryId",entryId);
sysMessageService.updateMessageStatus(map);
return ResponseResult.success();
}
}

195
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantController.java

@ -0,0 +1,195 @@ @@ -0,0 +1,195 @@
package apelet.tenantadmin.tenant.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import apelet.common.core.util.MyModelUtil;
import apelet.tenantadmin.tenant.dto.SysTenantDto;
import apelet.tenantadmin.tenant.model.SysTenant;
import apelet.tenantadmin.tenant.service.SysTenantService;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.*;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.tenantadmin.tenant.vo.SysTenantVo;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Map;
/**
* 租户管理接口控制器类
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "租户管理接口控制器类。")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/sysTenant")
public class SysTenantController {
@Autowired
private SysTenantService sysTenantService;
/**
* 新增租户操作
*
* @param sysTenantDto 新增租户对象
* @return 应答结果对象包含新增租户的主键Id
*/
@ApiOperationSupport(ignoreParameters = {"sysTenantDto.tenantId"})
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(@MyRequestBody SysTenantDto sysTenantDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenant sysTenant = MyModelUtil.copyTo(sysTenantDto, SysTenant.class);
sysTenantService.saveNew(sysTenant);
return ResponseResult.success(sysTenant.getTenantId());
}
/**
* 更新租户操作
*
* @param sysTenantDto 更新租户对象
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(@MyRequestBody SysTenantDto sysTenantDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenant originalSysTenant = sysTenantService.getById(sysTenantDto.getTenantId());
if (originalSysTenant == null) {
errorMessage = "数据验证失败,当前租户并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
SysTenant sysTenant = MyModelUtil.copyTo(sysTenantDto, SysTenant.class);
if (!sysTenantService.update(sysTenant, originalSysTenant)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除指定租户操作
*
* @param tenantId 指定租户主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody Long tenantId) {
if (MyCommonUtil.existBlankArgument(tenantId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
String errorMessage;
SysTenant tenant = sysTenantService.getById(tenantId);
if (tenant == null) {
errorMessage = "数据验证失败,当前租户并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
if (!sysTenantService.remove(tenant)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 查看租户列表
*
* @param sysTenantDtoFilter 租户过滤对象
* @param orderParam 排序参数
* @param pageParam 分页参数
* @return 应答结果对象包含租户列表
*/
@PostMapping("/list")
public ResponseResult<MyPageData<SysTenantVo>> list(
@MyRequestBody SysTenantDto sysTenantDtoFilter,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
SysTenant sysTenantFilter = MyModelUtil.copyTo(sysTenantDtoFilter, SysTenant.class);
List<SysTenant> tenantList = sysTenantService.getSysTenantList(
sysTenantFilter, MyOrderParam.buildOrderBy(orderParam, SysTenant.class));
return ResponseResult.success(MyPageUtil.makeResponseData(tenantList, SysTenant.INSTANCE));
}
/**
* 查看租户详情
*
* @param tenantId 指定租户主键Id
* @return 应答结果对象包含租户详情对象
*/
@GetMapping("/view")
public ResponseResult<SysTenantVo> view(@RequestParam Long tenantId) {
if (MyCommonUtil.existBlankArgument(tenantId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
SysTenant sysTenant = sysTenantService.getByIdWithRelation(tenantId, MyRelationParam.normal());
if (sysTenant == null) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
SysTenantVo sysTenantVo = SysTenant.INSTANCE.fromModel(sysTenant);
return ResponseResult.success(sysTenantVo);
}
/**
* 查询租户的权限资源列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param url url过滤条件
* @return 应答对象包含从租户到权限资源的权限分配路径信息的查询结果列表
*/
@GetMapping("/listSysTenantPermWithDetail")
public ResponseResult<List<Map<String, Object>>> listSysTenantPermWithDetail(Long tenantId, String url) {
if (MyCommonUtil.isBlankOrNull(tenantId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
return ResponseResult.success(sysTenantService.getSysTenantPermListWithDetail(tenantId, url));
}
/**
* 查询租户的权限字列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param permCode 权限字称过滤条件
* @return 应答对象包含从租户到权限字的权限分配路径信息的查询结果列表
*/
@GetMapping("/listSysTenantPermCodeWithDetail")
public ResponseResult<List<Map<String, Object>>> listSysTenantPermCodeWithDetail(Long tenantId, String permCode) {
if (MyCommonUtil.isBlankOrNull(tenantId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
return ResponseResult.success(sysTenantService.getSysTenantPermCodeListWithDetail(tenantId, permCode));
}
/**
* 查询租户的菜单列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param menuName 菜单名称过滤条件
* @return 应答对象包含从租户到菜单的权限分配路径信息的查询结果列表
*/
@GetMapping("/listSysTenantMenuWithDetail")
public ResponseResult<List<Map<String, Object>>> listSysTenantMenuWithDetail(Long tenantId, String menuName) {
if (MyCommonUtil.isBlankOrNull(tenantId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
return ResponseResult.success(sysTenantService.getSysTenantMenuListWithDetail(tenantId, menuName));
}
}

204
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantDatasourceController.java

@ -0,0 +1,204 @@ @@ -0,0 +1,204 @@
package apelet.tenantadmin.tenant.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import cn.hutool.core.util.StrUtil;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.annotation.NoAuthInterface;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.exception.MyRuntimeException;
import apelet.common.core.object.MyPageData;
import apelet.common.core.object.MyPageParam;
import apelet.common.core.object.ResponseResult;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyModelUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.common.dbutil.util.DataSourceUtil;
import apelet.common.dbutil.constant.DblinkType;
import apelet.tenantadmin.tenant.dto.SysTenantDatasourceDto;
import apelet.tenantadmin.tenant.dto.SysTenantPermDto;
import apelet.tenantadmin.tenant.model.SysTenant;
import apelet.tenantadmin.tenant.model.SysTenantDatasource;
import apelet.tenantadmin.tenant.service.SysTenantDatasourceService;
import apelet.tenantadmin.tenant.service.SysTenantService;
import apelet.tenantadmin.tenant.vo.SysTenantDatasourceVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Map;
/**
* 租户数据源管理接口控制器类
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "租户数据源管理接口控制器类。")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/sysTenantDatasource")
public class SysTenantDatasourceController {
@Autowired
private SysTenantDatasourceService sysTenantDatasourceService;
@Autowired
private SysTenantService sysTenantService;
@Autowired
private RedissonClient redissonClient;
/**
* 测试链接
*
* @param sysTenantDatasourceDto 数据源参数对象
* @return 测试结果应答
*/
@PostMapping("/testConnection")
public ResponseResult<Void> testConnection(@MyRequestBody SysTenantDatasourceDto sysTenantDatasourceDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantDatasourceDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
try {
DataSourceUtil.testConnection(
DblinkType.MYSQL,
sysTenantDatasourceDto.getDatabaseHost(),
sysTenantDatasourceDto.getPort(),
sysTenantDatasourceDto.getSchemaName(),
sysTenantDatasourceDto.getDatabaseName(),
sysTenantDatasourceDto.getUsername(),
sysTenantDatasourceDto.getPassword());
} catch (MyRuntimeException e) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, e.getMessage());
}
return ResponseResult.success();
}
/**
* 新增租户数据源操作
*
* @param sysTenantDatasourceDto 新增租户数据源对象
* @return 应答结果对象包含新租户数据源的主键Id
*/
@ApiOperationSupport(ignoreParameters = {"sysTenantDatasourceDto.datasourceId"})
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(@MyRequestBody SysTenantDatasourceDto sysTenantDatasourceDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantDatasourceDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantDatasource sysTenantDatasource = MyModelUtil.copyTo(sysTenantDatasourceDto, SysTenantDatasource.class);
sysTenantDatasourceService.saveNew(sysTenantDatasource);
return ResponseResult.success(sysTenantDatasource.getDatasourceId());
}
/**
* 更新租户数据源操作
*
* @param sysTenantDatasourceDto 更新租户数据源对象
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(@MyRequestBody SysTenantDatasourceDto sysTenantDatasourceDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantDatasourceDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantDatasource originalSysTenantDatasource =
sysTenantDatasourceService.getById(sysTenantDatasourceDto.getDatasourceId());
if (originalSysTenantDatasource == null) {
errorMessage = "数据验证失败,当前租户数据源并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
SysTenantDatasource sysTenantDatasource = MyModelUtil.copyTo(sysTenantDatasourceDto, SysTenantDatasource.class);
if (!sysTenantDatasource.getDatasourceType().equals(originalSysTenantDatasource.getDatasourceType())) {
errorMessage = "数据验证失败,多数据源类型值不能修改!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
String password = sysTenantDatasource.getPassword();
if (StrUtil.isNotBlank(password) && StrUtil.isAllCharMatch(password, c -> '*' == c)) {
sysTenantDatasource.setPassword(originalSysTenantDatasource.getPassword());
}
if (!sysTenantDatasourceService.update(sysTenantDatasource, originalSysTenantDatasource)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除指定租户数据源操作
*
* @param datasourceId 指定的租户数据源主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody(required = true) Long datasourceId) {
String errorMessage;
SysTenantDatasource originalSysTenantDatasource = sysTenantDatasourceService.getById(datasourceId);
if (originalSysTenantDatasource == null) {
errorMessage = "数据验证失败,当前租户数据源并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
SysTenant filter = new SysTenant();
filter.setDatasourceType(originalSysTenantDatasource.getDatasourceType());
if (sysTenantService.existByFilter(filter)) {
errorMessage = "数据验证失败,存在使用该租户数据源的租户,不能直接删除该租户数据源!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!sysTenantDatasourceService.removeById(datasourceId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 查看租户数据源列表
*
* @param sysTenantDatasourceDtoFilter 过滤对象
* @param pageParam 分页参数
* @return 应答结果对象包含租户权限资源列表
*/
@PostMapping("/list")
public ResponseResult<MyPageData<SysTenantDatasourceVo>> list(
@MyRequestBody SysTenantPermDto sysTenantDatasourceDtoFilter, @MyRequestBody MyPageParam pageParam) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
SysTenantDatasource filter = MyModelUtil.copyTo(sysTenantDatasourceDtoFilter, SysTenantDatasource.class);
List<SysTenantDatasource> resultList = sysTenantDatasourceService.getSysTenantDatasourceList(filter);
for (SysTenantDatasource datasource : resultList) {
datasource.setPassword(StrUtil.repeat('*', datasource.getPassword().length()));
}
List<SysTenantDatasourceVo> resultVoList = MyModelUtil.copyCollectionTo(resultList, SysTenantDatasourceVo.class);
long totalCount = 0L;
if (resultList instanceof Page) {
totalCount = ((Page<SysTenantDatasource>) resultList).getTotal();
}
return ResponseResult.success(MyPageUtil.makeResponseData(resultVoList, totalCount));
}
/**
* 获取租户数据源的字典列表
*
* @return 租户数据源的字典列表
*/
@NoAuthInterface
@GetMapping("/listDict")
public ResponseResult<List<Map<String, Object>>> listDict() {
List<SysTenantDatasource> resultList = sysTenantDatasourceService.getAllList();
return ResponseResult.success(MyCommonUtil.toDictDataList(
resultList, SysTenantDatasource::getDatasourceType, SysTenantDatasource::getDatasourceName));
}
}

167
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantMenuController.java

@ -0,0 +1,167 @@ @@ -0,0 +1,167 @@
package apelet.tenantadmin.tenant.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import apelet.common.core.util.MyModelUtil;
import apelet.tenantadmin.tenant.dto.SysTenantMenuDto;
import apelet.tenantadmin.tenant.model.SysTenantMenu;
import apelet.tenantadmin.tenant.service.SysTenantMenuService;
import apelet.tenantadmin.tenant.service.SysTenantPermCodeService;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.CallResult;
import apelet.common.core.object.MyRelationParam;
import apelet.common.core.object.ResponseResult;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.tenantadmin.tenant.vo.SysTenantMenuVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Set;
/**
* 租户菜单管理接口控制器类
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "租户菜单管理接口控制器类。")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/sysTenantMenu")
public class SysTenantMenuController {
@Autowired
private SysTenantMenuService sysTenantMenuService;
@Autowired
private SysTenantPermCodeService sysTenantPermCodeService;
/**
* 添加新租户菜单操作
*
* @param sysTenantMenuDto 新租户菜单对象
* @param permCodeIdListString 与当前菜单Id绑定的权限Id列表多个权限之间逗号分隔
* @return 应答结果对象包含新增菜单的主键Id
*/
@ApiOperationSupport(ignoreParameters = {"sysTenantMenuDto.menuId"})
@SuppressWarnings("unchecked")
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(
@MyRequestBody SysTenantMenuDto sysTenantMenuDto,
@MyRequestBody String permCodeIdListString) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantMenuDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantMenu sysTenantMenu = MyModelUtil.copyTo(sysTenantMenuDto, SysTenantMenu.class);
CallResult verifyResult =
sysTenantMenuService.verifyRelatedData(sysTenantMenu, null, permCodeIdListString);
if (!verifyResult.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, verifyResult.getErrorMessage());
}
Set<Long> permCodeIdSet = null;
if (verifyResult.getData() != null) {
permCodeIdSet = (Set<Long>) verifyResult.getData().get("permCodeIdSet");
}
sysTenantMenuService.saveNew(sysTenantMenu, permCodeIdSet);
return ResponseResult.success(sysTenantMenu.getMenuId());
}
/**
* 更新租户菜单数据的操作
*
* @param sysTenantMenuDto 更新租户菜单对象
* @param permCodeIdListString 与当前租户菜单Id绑定的权限Id列表多个权限之间逗号分隔
* @return 应答结果对象
*/
@SuppressWarnings("unchecked")
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(
@MyRequestBody SysTenantMenuDto sysTenantMenuDto,
@MyRequestBody String permCodeIdListString) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantMenuDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantMenu originalSysTenantMenu = sysTenantMenuService.getById(sysTenantMenuDto.getMenuId());
if (originalSysTenantMenu == null) {
errorMessage = "数据验证失败,当前租户菜单并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
SysTenantMenu sysTenantMenu = MyModelUtil.copyTo(sysTenantMenuDto, SysTenantMenu.class);
CallResult verifyResult = sysTenantMenuService.verifyRelatedData(sysTenantMenu, originalSysTenantMenu, permCodeIdListString);
if (!verifyResult.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, verifyResult.getErrorMessage());
}
Set<Long> permCodeIdSet = null;
if (verifyResult.getData() != null) {
permCodeIdSet = (Set<Long>) verifyResult.getData().get("permCodeIdSet");
}
if (!sysTenantMenuService.update(sysTenantMenu, originalSysTenantMenu, permCodeIdSet)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除指定租户菜单的操作
*
* @param menuId 指定租户菜单主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody Long menuId) {
if (MyCommonUtil.existBlankArgument(menuId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
String errorMessage;
if (sysTenantMenuService.hasChildren(menuId)) {
errorMessage = "数据验证失败,当前租户菜单存在下级菜单!";
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
}
if (!sysTenantMenuService.remove(menuId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 获取全部菜单列表
*
* @return 应答结果对象包含全部菜单数据列表
*/
@PostMapping("/list")
public ResponseResult<List<SysTenantMenuVo>> list() {
List<SysTenantMenu> menuList =
sysTenantMenuService.getAllListByOrder("menuType", "showOrder");
return ResponseResult.success(SysTenantMenu.INSTANCE.fromModelList(menuList));
}
/**
* 查看指定租户菜单数据详情
*
* @param menuId 指定租户菜单主键Id
* @return 应答结果对象包含菜单详情
*/
@GetMapping("/view")
public ResponseResult<SysTenantMenuVo> view(@RequestParam Long menuId) {
if (MyCommonUtil.existBlankArgument(menuId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
SysTenantMenu sysMenu = sysTenantMenuService.getByIdWithRelation(menuId, MyRelationParam.full());
if (sysMenu == null) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
SysTenantMenuVo sysMenuVo = SysTenantMenu.INSTANCE.fromModel(sysMenu);
return ResponseResult.success(sysMenuVo);
}
}

171
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantPermCodeController.java

@ -0,0 +1,171 @@ @@ -0,0 +1,171 @@
package apelet.tenantadmin.tenant.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import apelet.common.core.util.MyModelUtil;
import apelet.tenantadmin.tenant.dto.SysTenantPermCodeDto;
import apelet.tenantadmin.tenant.model.SysTenantPermCode;
import apelet.tenantadmin.tenant.service.SysTenantPermCodeService;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.CallResult;
import apelet.common.core.object.MyRelationParam;
import apelet.common.core.object.ResponseResult;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.tenantadmin.tenant.vo.SysTenantPermCodeVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.web.bind.annotation.*;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Set;
/**
* 租户权限字管理接口控制器类
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "租户权限字管理接口控制器类。")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/sysTenantPermCode")
public class SysTenantPermCodeController {
@Autowired
private SysTenantPermCodeService sysTenantPermCodeService;
/**
* 新增租户权限字操作
*
* @param sysTenantPermCodeDto 新增租户权限字对象
* @param permIdListString 与当前租户权限字Id绑定租户的权限资源Id列表多个权限资源之间逗号分隔
* @return 应答结果对象包含新增权限字的主键Id
*/
@ApiOperationSupport(ignoreParameters = {"sysTenantPermCodeDto.permCodeId"})
@SuppressWarnings("unchecked")
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(
@MyRequestBody SysTenantPermCodeDto sysTenantPermCodeDto,
@MyRequestBody String permIdListString) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantPermCodeDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantPermCode sysTenantPermCode = MyModelUtil.copyTo(sysTenantPermCodeDto, SysTenantPermCode.class);
CallResult verifyResult =
sysTenantPermCodeService.verifyRelatedData(sysTenantPermCode, null, permIdListString);
if (!verifyResult.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, verifyResult.getErrorMessage());
}
Set<Long> permIdSet = null;
if (verifyResult.getData() != null) {
permIdSet = (Set<Long>) verifyResult.getData().get("permIdSet");
}
sysTenantPermCodeService.saveNew(sysTenantPermCode, permIdSet);
return ResponseResult.success(sysTenantPermCode.getPermCodeId());
}
/**
* 更新租户权限字操作
*
* @param sysTenantPermCodeDto 更新租户权限字对象
* @param permIdListString 与当前租户权限字Id绑定的租户权限资源Id列表多个权限资源之间逗号分隔
* @return 应答结果对象
*/
@SuppressWarnings("unchecked")
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(
@MyRequestBody SysTenantPermCodeDto sysTenantPermCodeDto,
@MyRequestBody String permIdListString) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantPermCodeDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantPermCode originalSysTenantPermCode = sysTenantPermCodeService.getById(sysTenantPermCodeDto.getPermCodeId());
if (originalSysTenantPermCode == null) {
errorMessage = "数据验证失败,当前权限字并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
SysTenantPermCode sysTenantPermCode = MyModelUtil.copyTo(sysTenantPermCodeDto, SysTenantPermCode.class);
CallResult verifyResult =
sysTenantPermCodeService.verifyRelatedData(sysTenantPermCode, originalSysTenantPermCode, permIdListString);
if (!verifyResult.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, verifyResult.getErrorMessage());
}
Set<Long> permIdSet = null;
if (verifyResult.getData() != null) {
permIdSet = (Set<Long>) verifyResult.getData().get("permIdSet");
}
try {
if (!sysTenantPermCodeService.update(sysTenantPermCode, originalSysTenantPermCode, permIdSet)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
} catch (DuplicateKeyException e) {
errorMessage = "数据操作失败,权限字编码已经存在!";
return ResponseResult.error(ErrorCodeEnum.DUPLICATED_UNIQUE_KEY, errorMessage);
}
return ResponseResult.success();
}
/**
* 删除指定租户权限字操作
*
* @param permCodeId 指定的租户权限字主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody Long permCodeId) {
String errorMessage;
if (MyCommonUtil.existBlankArgument(permCodeId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
if (sysTenantPermCodeService.hasChildren(permCodeId)) {
errorMessage = "数据验证失败,当前租户权限字存在下级权限字!";
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
}
if (!sysTenantPermCodeService.remove(permCodeId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 查看权限字列表
*
* @return 应答结果对象包含权限字列表
*/
@PostMapping("/list")
public ResponseResult<List<SysTenantPermCodeVo>> list() {
List<SysTenantPermCode> permCodeList =
sysTenantPermCodeService.getAllListByOrder("permCodeType", "showOrder");
return ResponseResult.success(SysTenantPermCode.INSTANCE.fromModelList(permCodeList));
}
/**
* 查看权限字对象详情
*
* @param permCodeId 指定权限字主键Id
* @return 应答结果对象包含权限字对象详情
*/
@GetMapping("/view")
public ResponseResult<SysTenantPermCodeVo> view(@RequestParam Long permCodeId) {
if (MyCommonUtil.existBlankArgument(permCodeId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
SysTenantPermCode sysPermCode = sysTenantPermCodeService.getByIdWithRelation(permCodeId, MyRelationParam.full());
if (sysPermCode == null) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
SysTenantPermCodeVo sysPermCodeVo = SysTenantPermCode.INSTANCE.fromModel(sysPermCode);
return ResponseResult.success(sysPermCodeVo);
}
}

156
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantPermController.java

@ -0,0 +1,156 @@ @@ -0,0 +1,156 @@
package apelet.tenantadmin.tenant.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import apelet.common.core.util.MyModelUtil;
import apelet.tenantadmin.tenant.dto.SysTenantPermDto;
import apelet.tenantadmin.tenant.model.SysTenantPerm;
import apelet.tenantadmin.tenant.service.SysTenantPermService;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.CallResult;
import apelet.common.core.object.MyPageData;
import apelet.common.core.object.MyPageParam;
import apelet.common.core.object.ResponseResult;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.tenantadmin.tenant.vo.SysTenantPermVo;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.groups.Default;
import java.util.List;
/**
* 租户权限资源管理接口控制器类
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "租户权限资源管理接口控制器类。")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/sysTenantPerm")
public class SysTenantPermController {
@Autowired
private SysTenantPermService sysTenantPermService;
/**
* 新增租户权限资源操作
*
* @param sysTenantPermDto 新增租户权限资源对象
* @return 应答结果对象包含新租户增权限资源的主键Id
*/
@ApiOperationSupport(ignoreParameters = {"sysTenantPermDto.permId"})
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(@MyRequestBody SysTenantPermDto sysTenantPermDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantPermDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantPerm sysTenantPerm = MyModelUtil.copyTo(sysTenantPermDto, SysTenantPerm.class);
CallResult verifyResult = sysTenantPermService.verifyRelatedData(sysTenantPerm, null);
if (!verifyResult.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, verifyResult.getErrorMessage());
}
sysTenantPermService.saveNew(sysTenantPerm);
return ResponseResult.success(sysTenantPerm.getPermId());
}
/**
* 更新租户权限资源操作
*
* @param sysTenantPermDto 更新租户权限资源对象
* @return 应答结果对象包含更新租户权限资源的主键Id
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(@MyRequestBody SysTenantPermDto sysTenantPermDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantPermDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantPerm originalSysTenantPerm = sysTenantPermService.getById(sysTenantPermDto.getPermId());
if (originalSysTenantPerm == null) {
errorMessage = "数据验证失败,当前租户权限资源并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
SysTenantPerm sysTenantPerm = MyModelUtil.copyTo(sysTenantPermDto, SysTenantPerm.class);
CallResult verifyResult = sysTenantPermService.verifyRelatedData(sysTenantPerm, originalSysTenantPerm);
if (!verifyResult.isSuccess()) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, verifyResult.getErrorMessage());
}
if (!sysTenantPermService.update(sysTenantPerm, originalSysTenantPerm)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除指定租户权限资源操作
*
* @param permId 指定的租户权限资源主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody Long permId) {
if (MyCommonUtil.existBlankArgument(permId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
if (!sysTenantPermService.remove(permId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 查看租户权限资源对象详情
*
* @param permId 指定租户权限资源主键Id
* @return 应答结果对象包含租户权限资源对象详情
*/
@GetMapping("/view")
public ResponseResult<SysTenantPermVo> view(@RequestParam Long permId) {
if (MyCommonUtil.existBlankArgument(permId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
SysTenantPerm perm = sysTenantPermService.getById(permId);
if (perm == null) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
SysTenantPermVo permVo = MyModelUtil.copyTo(perm, SysTenantPermVo.class);
return ResponseResult.success(permVo);
}
/**
* 查看租户权限资源列表
*
* @param sysPermDtoFilter 过滤对象
* @param pageParam 分页参数
* @return 应答结果对象包含租户权限资源列表
*/
@PostMapping("/list")
public ResponseResult<MyPageData<SysTenantPermVo>> list(
@MyRequestBody SysTenantPermDto sysPermDtoFilter, @MyRequestBody MyPageParam pageParam) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
SysTenantPerm sysPermFilter = MyModelUtil.copyTo(sysPermDtoFilter, SysTenantPerm.class);
List<SysTenantPerm> resultList = sysTenantPermService.getPermListWithRelation(sysPermFilter);
List<SysTenantPermVo> resultVoList = MyModelUtil.copyCollectionTo(resultList, SysTenantPermVo.class);
long totalCount = 0L;
if (resultList instanceof Page) {
totalCount = ((Page<SysTenantPerm>) resultList).getTotal();
}
return ResponseResult.success(MyPageUtil.makeResponseData(resultVoList, totalCount));
}
}

174
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantPermModuleController.java

@ -0,0 +1,174 @@ @@ -0,0 +1,174 @@
package apelet.tenantadmin.tenant.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import apelet.common.core.util.MyModelUtil;
import apelet.tenantadmin.tenant.dto.SysTenantPermModuleDto;
import apelet.tenantadmin.tenant.model.SysTenantPerm;
import apelet.tenantadmin.tenant.model.SysTenantPermModule;
import apelet.tenantadmin.tenant.service.SysTenantPermModuleService;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.ResponseResult;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.tenantadmin.tenant.vo.SysTenantPermModuleVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.groups.Default;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 权限资源模块管理接口控制器类
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "权限资源模块管理接口控制器类。")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/sysTenantPermModule")
public class SysTenantPermModuleController {
@Autowired
private SysTenantPermModuleService sysTenantPermModuleService;
/**
* 新增租户权限资源模块操作
*
* @param sysTenantPermModuleDto 新增租户权限资源模块对象
* @return 应答结果对象包含新增租户权限资源模块的主键Id
*/
@ApiOperationSupport(ignoreParameters = {"sysTenantPermModuleDto.moduleId"})
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(
@MyRequestBody SysTenantPermModuleDto sysTenantPermModuleDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantPermModuleDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantPermModule sysTenantPermModule =
MyModelUtil.copyTo(sysTenantPermModuleDto, SysTenantPermModule.class);
if (sysTenantPermModule.getParentId() != null
&& sysTenantPermModuleService.getById(sysTenantPermModule.getParentId()) == null) {
errorMessage = "数据验证失败,关联的上级租户权限模块并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_PARENT_ID_NOT_EXIST, errorMessage);
}
sysTenantPermModuleService.saveNew(sysTenantPermModule);
return ResponseResult.success(sysTenantPermModule.getModuleId());
}
/**
* 更新租户权限资源模块操作
*
* @param sysTenantPermModuleDto 更新租户权限资源模块对象
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(
@MyRequestBody SysTenantPermModuleDto sysTenantPermModuleDto) {
String errorMessage =
MyCommonUtil.getModelValidationError(sysTenantPermModuleDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantPermModule originalSysTenantPermModule =
sysTenantPermModuleService.getById(sysTenantPermModuleDto.getModuleId());
if (originalSysTenantPermModule == null) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
SysTenantPermModule sysTenantPermModule = MyModelUtil.copyTo(sysTenantPermModuleDto, SysTenantPermModule.class);
if (sysTenantPermModule.getParentId() != null
&& !sysTenantPermModule.getParentId().equals(originalSysTenantPermModule.getParentId())
&& !sysTenantPermModuleService.existId(sysTenantPermModule.getParentId())) {
errorMessage = "数据验证失败,关联的上级权限模块并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_PARENT_ID_NOT_EXIST, errorMessage);
}
if (!sysTenantPermModuleService.update(sysTenantPermModule, originalSysTenantPermModule)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 删除指定租户权限资源模块操作
*
* @param moduleId 指定的租户权限资源模块主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody Long moduleId) {
if (MyCommonUtil.existBlankArgument(moduleId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
String errorMessage;
if (sysTenantPermModuleService.hasChildren(moduleId)
|| sysTenantPermModuleService.hasModulePerms(moduleId)) {
errorMessage = "数据验证失败,当前租户权限模块存在子模块或权限资源,请先删除关联数据!";
return ResponseResult.error(ErrorCodeEnum.HAS_CHILDREN_DATA, errorMessage);
}
if (!sysTenantPermModuleService.remove(moduleId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
return ResponseResult.success();
}
/**
* 查看全部租户权限资源模块列表
*
* @return 应答结果对象包含租户权限资源模块列表
*/
@PostMapping("/list")
public ResponseResult<List<SysTenantPermModuleVo>> list() {
List<SysTenantPermModule> permModuleList =
sysTenantPermModuleService.getAllListByOrder("showOrder");
return ResponseResult.success(MyModelUtil.copyCollectionTo(permModuleList, SysTenantPermModuleVo.class));
}
/**
* 列出全部租户权限资源模块及其下级关联的权限资源列表
*
* @return 应答结果对象包含树状列表结构为租户权限资源模块和租户权限资源之间的树状关系
*/
@PostMapping("/listAll")
public ResponseResult<List<Map<String, Object>>> listAll() {
List<SysTenantPermModule> sysPermModuleList = sysTenantPermModuleService.getPermModuleAndPermList();
List<Map<String, Object>> resultList = new LinkedList<>();
for (SysTenantPermModule sysPermModule : sysPermModuleList) {
Map<String, Object> permModuleMap = new HashMap<>(5);
permModuleMap.put("id", sysPermModule.getModuleId());
permModuleMap.put("name", sysPermModule.getModuleName());
permModuleMap.put("type", sysPermModule.getModuleType());
permModuleMap.put("isPerm", false);
if (MyCommonUtil.isNotBlankOrNull(sysPermModule.getParentId())) {
permModuleMap.put("parentId", sysPermModule.getParentId());
}
resultList.add(permModuleMap);
if (CollectionUtils.isNotEmpty(sysPermModule.getSysPermList())) {
for (SysTenantPerm sysPerm : sysPermModule.getSysPermList()) {
Map<String, Object> permMap = new HashMap<>(4);
permMap.put("id", sysPerm.getPermId());
permMap.put("name", sysPerm.getPermName());
permMap.put("isPerm", true);
permMap.put("url", sysPerm.getUrl());
permMap.put("parentId", sysPermModule.getModuleId());
resultList.add(permMap);
}
}
}
return ResponseResult.success(resultList);
}
}

621
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/SysTenantRoleController.java

@ -0,0 +1,621 @@ @@ -0,0 +1,621 @@
package apelet.tenantadmin.tenant.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import cn.hutool.core.util.BooleanUtil;
import cn.hutool.core.util.ObjectUtil;
import apelet.tenantadmin.tenant.dto.SysTenantDto;
import apelet.tenantadmin.tenant.dto.SysTenantRoleDto;
import apelet.tenantadmin.tenant.dto.SysTenantRoleMenuDto;
import apelet.tenantadmin.tenant.dto.SysTenantRoleTenantDto;
import apelet.tenantadmin.tenant.model.*;
import apelet.tenantadmin.tenant.service.SysTenantMenuService;
import apelet.tenantadmin.tenant.service.SysTenantRoleService;
import apelet.tenantadmin.tenant.service.SysTenantService;
import apelet.tenantadmin.tenant.vo.SysTenantMenuVo;
import apelet.tenantadmin.tenant.vo.SysTenantRoleVo;
import apelet.tenantadmin.tenant.vo.SysTenantVo;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.*;
import apelet.common.core.util.MyModelUtil;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.common.report.dto.ReportDatasetDto;
import apelet.common.report.model.ReportDataset;
import apelet.common.report.service.ReportDatasetService;
import apelet.common.report.vo.ReportDatasetVo;
import apelet.common.online.dto.OnlinePageDto;
import apelet.common.online.model.OnlinePage;
import apelet.common.online.service.OnlinePageService;
import apelet.common.online.vo.OnlinePageVo;
import apelet.common.tenant.annotation.SwitchTenantCommonDatasource;
import com.github.pagehelper.page.PageMethod;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.groups.Default;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* 租户角色管理接口控制器类
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "租户角色管理接口控制器类。")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/sysTenantRole")
public class SysTenantRoleController {
@Autowired
private SysTenantRoleService sysTenantRoleService;
@Autowired
private SysTenantMenuService sysTenantMenuService;
@Autowired
private SysTenantService sysTenantService;
@Autowired
private ReportDatasetService reportDatasetService;
@Autowired
private OnlinePageService onlinePageService;
/**
* 新增租户角色操作
*
* @param sysTenantRoleDto 新增租户角色对象
* @return 应答结果对象包含新增角色的主键Id
*/
@ApiOperationSupport(ignoreParameters = {"sysTenantRoleDto.tenantRoleId"})
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(@MyRequestBody SysTenantRoleDto sysTenantRoleDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantRoleDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantRole sysTenantRole = MyModelUtil.copyTo(sysTenantRoleDto, SysTenantRole.class);
sysTenantRoleService.saveNew(sysTenantRole);
return ResponseResult.success(sysTenantRole.getTenantRoleId());
}
/**
* 更新租户角色操作
*
* @param sysTenantRoleDto 更新租户角色对象
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(@MyRequestBody SysTenantRoleDto sysTenantRoleDto) {
String errorMessage = MyCommonUtil.getModelValidationError(sysTenantRoleDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
SysTenantRole originalSysTenantRole = sysTenantRoleService.getById(sysTenantRoleDto.getTenantRoleId());
if (originalSysTenantRole == null) {
errorMessage = "数据验证失败,当前租户角色并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
SysTenantRole sysTenantRole = MyModelUtil.copyTo(sysTenantRoleDto, SysTenantRole.class);
if (!sysTenantRoleService.update(sysTenantRole, originalSysTenantRole)) {
errorMessage = "更新失败,租户角色数据不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
return ResponseResult.success();
}
/**
* 删除指定租户角色操作
*
* @param tenantRoleId 指定租户角色主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody Long tenantRoleId) {
if (MyCommonUtil.existBlankArgument(tenantRoleId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
// 如果租户角色中,同时包含租户及其关联数据时,不能直接删除租户角色数据。
// 需要提示用户先把菜单等数据逐条删除,毕竟菜单数据可能相对较少,这个需要视实际数据
// 情况而定,总之租户角色如果只是包含菜单和租户其中一个关联时,是可以直接删除,
// 且不用同步远程租户数据库的。
if (sysTenantRoleService.hasTenantByRoleId(tenantRoleId)
&& sysTenantRoleService.hasTenantRelatedDataByTenantRoleId(tenantRoleId)) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED,
"数据操作失败,当前租户角色同时包含租户及其关联数据,不能直接删除!");
}
if (!sysTenantRoleService.remove(tenantRoleId)) {
String errorMessage = "数据操作失败,租户角色不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
return ResponseResult.success();
}
/**
* 查看租户角色列表
*
* @param sysTenantRoleDtoFilter 租户角色过滤对象
* @param orderParam 排序参数
* @param pageParam 分页参数
* @return 应答结果对象包含租户角色列表
*/
@PostMapping("/list")
public ResponseResult<MyPageData<SysTenantRoleVo>> list(
@MyRequestBody SysTenantRole sysTenantRoleDtoFilter,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
SysTenantRole sysTenantRoleFilter = MyModelUtil.copyTo(sysTenantRoleDtoFilter, SysTenantRole.class);
List<SysTenantRole> roleList = sysTenantRoleService.getSysTenantRoleList(
sysTenantRoleFilter, MyOrderParam.buildOrderBy(orderParam, SysTenantRole.class));
return ResponseResult.success(MyPageUtil.makeResponseData(roleList, SysTenantRole.INSTANCE));
}
/**
* 查看租户角色详情
*
* @param tenantRoleId 指定租户角色主键Id
* @return 应答结果对象包含租户角色详情对象
*/
@GetMapping("/view")
public ResponseResult<SysTenantRoleVo> view(@RequestParam Long tenantRoleId) {
if (MyCommonUtil.existBlankArgument(tenantRoleId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
SysTenantRole sysRole = sysTenantRoleService.getById(tenantRoleId);
if (sysRole == null) {
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST);
}
SysTenantRoleVo sysRoleVo = SysTenantRole.INSTANCE.fromModel(sysRole);
return ResponseResult.success(sysRoleVo);
}
/**
* 列出指定租户角色没有包含的租户菜单列表
*
* @param tenantRoleId 租户角色主键Id
* @param sysTenantDtoFilter 租户过滤对象
* @param orderParam 排序参数
* @param pageParam 分页参数
* @return 应答结果对象指定租户角色没有包含的租户列表
*/
@PostMapping("/listNotInTenantRoleTenant")
public ResponseResult<MyPageData<SysTenantVo>> listNotInTenantRoleTenant(
@MyRequestBody Long tenantRoleId,
@MyRequestBody SysTenantDto sysTenantDtoFilter,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
SysTenant sysTenantFilter = MyModelUtil.copyTo(sysTenantDtoFilter, SysTenant.class);
String orderBy = MyOrderParam.buildOrderBy(orderParam, SysTenant.class);
List<SysTenant> resultList =
sysTenantService.getNotInSysTenantListByRoleId(tenantRoleId, sysTenantFilter, orderBy);
return ResponseResult.success(MyPageUtil.makeResponseData(resultList, SysTenant.INSTANCE));
}
/**
* 列出指定租户角色的租户菜单列表
*
* @param tenantRoleId 租户角色主键Id
* @param sysTenantDtoFilter 租户过滤对象
* @param orderParam 排序参数
* @param pageParam 分页参数
* @return 应答结果对象指定租户角色包含租户菜单列表
*/
@PostMapping("/listTenantRoleTenant")
public ResponseResult<MyPageData<SysTenantVo>> listTenantRoleTenant(
@MyRequestBody Long tenantRoleId,
@MyRequestBody SysTenantDto sysTenantDtoFilter,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
SysTenant sysTenantFilter = MyModelUtil.copyTo(sysTenantDtoFilter, SysTenant.class);
String orderBy = MyOrderParam.buildOrderBy(orderParam, SysTenant.class);
List<SysTenant> resultList =
sysTenantService.getSysTenantListByRoleId(tenantRoleId, sysTenantFilter, orderBy);
return ResponseResult.success(MyPageUtil.makeResponseData(resultList, SysTenant.INSTANCE));
}
/**
* 为指定租户角色添加租户菜单列表
*
* @param tenantRoleId 租户角色主键Id
* @param sysTenantRoleTenantDtoList 租户角色与租户的关联列表
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.ADD_M2M)
@PostMapping("/addTenantRoleTenant")
public ResponseResult<Void> addTenantRoleTenant(
@MyRequestBody Long tenantRoleId,
@MyRequestBody List<SysTenantRoleTenantDto> sysTenantRoleTenantDtoList) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, sysTenantRoleTenantDtoList)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
Set<Long> tenantIdSet = sysTenantRoleTenantDtoList.stream()
.map(SysTenantRoleTenantDto::getTenantId).collect(Collectors.toSet());
if (!sysTenantRoleService.existId(tenantRoleId)
|| !sysTenantService.existUniqueKeyList("tenantId", tenantIdSet)) {
return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID);
}
List<SysTenantRoleTenant> sysTenantRoleTenantList =
MyModelUtil.copyCollectionTo(sysTenantRoleTenantDtoList, SysTenantRoleTenant.class);
sysTenantRoleService.addTenantRoleTenantList(tenantRoleId, sysTenantRoleTenantList);
return ResponseResult.success();
}
/**
* 为指定租户角色移除指定租户
*
* @param tenantRoleId 指定租户角色主键Id
* @param tenantId 指定租户主键Id
* @param force 是否强制移除
* @return 应答数据结果
*/
@OperationLog(type = SysOperationLogType.DELETE_M2M)
@PostMapping("/deleteTenantRoleTenant")
public ResponseResult<Void> deleteTenantRoleTenant(
@MyRequestBody Long tenantRoleId, @MyRequestBody Long tenantId, @MyRequestBody Boolean force) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, tenantId, force)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
// 判断该租户角色是否包含租户关联数据,如果不包含,就只是删除本地关联数据即可。
if (!sysTenantRoleService.hasTenantRelatedDataByTenantRoleId(tenantRoleId)) {
sysTenantRoleService.removeTenantRoleTenant(tenantRoleId, tenantId);
return ResponseResult.success();
}
// 租户角色包含菜单,如果不是强制删除,就给出错误提示即可。
if (BooleanUtil.isFalse(force)) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED,
"数据操作失败,当前租户角色包含租户及其关联数据,是否强制删除!");
}
sysTenantRoleService.removeTenantRoleTenantAndSync(tenantRoleId, tenantId);
return ResponseResult.success();
}
/**
* 列出指定租户角色没有包含的租户菜单列表
*
* @param tenantRoleId 租户角色主键Id
* @param orderParam 排序参数
* @return 应答结果对象指定租户角色没有包含的菜单列表
*/
@PostMapping("/listNotInTenantRoleMenu")
public ResponseResult<MyPageData<SysTenantMenuVo>> listNotInTenantRoleMenu(
@MyRequestBody Long tenantRoleId, @MyRequestBody MyOrderParam orderParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
String orderBy = MyOrderParam.buildOrderBy(orderParam, SysTenantMenu.class);
List<SysTenantMenu> resultList =
sysTenantMenuService.getNotInSysTenantMenuListByRoleId(tenantRoleId, orderBy);
return ResponseResult.success(MyPageUtil.makeResponseData(resultList, SysTenantMenu.INSTANCE));
}
/**
* 列出指定租户角色的租户菜单列表
*
* @param tenantRoleId 租户角色主键Id
* @param orderParam 排序参数
* @return 应答结果对象指定租户角色包含租户菜单列表
*/
@PostMapping("/listTenantRoleMenu")
public ResponseResult<MyPageData<SysTenantMenuVo>> listTenantRoleMenu(
@MyRequestBody Long tenantRoleId, @MyRequestBody MyOrderParam orderParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
String orderBy = MyOrderParam.buildOrderBy(orderParam, SysTenantMenu.class);
List<SysTenantMenu> resultList = sysTenantMenuService.getSysTenantMenuListByRoleId(tenantRoleId, orderBy);
return ResponseResult.success(MyPageUtil.makeResponseData(resultList, SysTenantMenu.INSTANCE));
}
private ResponseResult<Void> doTenantRoleVerify(Long tenantRoleId) {
if (MyCommonUtil.existBlankArgument(tenantRoleId)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
if (!sysTenantRoleService.existId(tenantRoleId)) {
return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID);
}
return ResponseResult.success();
}
/**
* 为指定租户角色添加租户菜单列表
*
* @param tenantRoleId 租户角色主键Id
* @param sysTenantRoleMenuDtoList 租户角色菜单关联列表
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.ADD_M2M)
@PostMapping("/addTenantRoleMenu")
public ResponseResult<Void> addTenantRoleMenu(
@MyRequestBody Long tenantRoleId,
@MyRequestBody List<SysTenantRoleMenuDto> sysTenantRoleMenuDtoList) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, sysTenantRoleMenuDtoList)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
Set<Long> menuIdSet =
sysTenantRoleMenuDtoList.stream().map(SysTenantRoleMenuDto::getMenuId).collect(Collectors.toSet());
if (!sysTenantRoleService.existId(tenantRoleId)
|| !sysTenantMenuService.existUniqueKeyList("menuId", menuIdSet)) {
return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID);
}
List<SysTenantRoleMenu> sysTenantRoleMenuList =
MyModelUtil.copyCollectionTo(sysTenantRoleMenuDtoList, SysTenantRoleMenu.class);
sysTenantRoleService.addTenantRoleMenuList(tenantRoleId, sysTenantRoleMenuList);
return ResponseResult.success();
}
/**
* 为指定租户角色移除指定租户菜单
*
* @param tenantRoleId 指定租户角色主键Id
* @param menuId 指定租户菜单主键Id
* @param force 是否强制移除
* @return 应答数据结果
*/
@OperationLog(type = SysOperationLogType.DELETE_M2M)
@PostMapping("/deleteTenantRoleMenu")
public ResponseResult<Void> deleteTenantRoleMenu(
@MyRequestBody Long tenantRoleId, @MyRequestBody Long menuId, @MyRequestBody Boolean force) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, menuId, force)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
// 判断该租户角色是否包含租户,如果不包含,就只是删除本地关联数据即可。
if (!sysTenantRoleService.hasTenantByRoleId(tenantRoleId)) {
sysTenantRoleService.removeTenantRoleMenu(tenantRoleId, menuId);
return ResponseResult.success();
}
// 租户角色包含租户,如果不是强制删除,就给出错误提示即可。
if (BooleanUtil.isFalse(force)) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED,
"数据操作失败,当前租户角色包含租户数据,是否强制删除!");
}
sysTenantRoleService.removeTenantRoleMenuAndSync(tenantRoleId, menuId);
return ResponseResult.success();
}
/**
* 列出指定租户角色没有包含的报表数据集列表
*
* @param tenantRoleId 租户角色主键Id
* @param reportDatasetDtoFilter 过滤对象
* @param orderParam 排序参数
* @return 应答结果对象指定租户角色没有包含的报表数据集列表
*/
@SwitchTenantCommonDatasource
@PostMapping("/listNotInTenantRoleReportDataset")
public ResponseResult<MyPageData<ReportDatasetVo>> listNotInTenantRoleReportDataset(
@MyRequestBody Long tenantRoleId,
@MyRequestBody ReportDatasetDto reportDatasetDtoFilter,
@MyRequestBody MyOrderParam orderParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
List<Long> datasetIds = sysTenantRoleService.getSysTenantRoleReportDatasetIdList(tenantRoleId);
String orderBy = MyOrderParam.buildOrderBy(orderParam, ReportDataset.class);
// SwitchTenantReportDatasource注解会将数据源切换到ApplicationConstant.TENANT_COMMON_DATASOURCE_TYPE
// 所指向的数据库,既租户业务的通用数据库。
List<ReportDataset> reportDatasetList =
reportDatasetService.getNotInList("datasetId", new HashSet<>(datasetIds), orderBy);
if (reportDatasetDtoFilter != null && reportDatasetDtoFilter.getGroupId() != null) {
reportDatasetList = reportDatasetList.stream()
.filter(d -> d.getGroupId().equals(reportDatasetDtoFilter.getGroupId()))
.collect(Collectors.toList());
}
reportDatasetList = reportDatasetList.stream()
.filter(d -> ObjectUtil.equal(d.getAppCode(), TokenData.takeFromRequest().getAppCode()))
.collect(Collectors.toList());
reportDatasetService.buildRelationForDataList(reportDatasetList, MyRelationParam.dictOnly());
return ResponseResult.success(MyPageUtil.makeResponseData(reportDatasetList, ReportDataset.INSTANCE));
}
/**
* 列出指定租户角色的报表数据集列表
*
* @param tenantRoleId 租户角色主键Id
* @param orderParam 排序参数
* @return 应答结果对象指定租户角色包含报表数据集列表
*/
@SwitchTenantCommonDatasource
@PostMapping("/listTenantRoleReportDataset")
public ResponseResult<MyPageData<ReportDatasetVo>> listTenantRoleReportDataset(
@MyRequestBody Long tenantRoleId, @MyRequestBody MyOrderParam orderParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
List<Long> datasetIds = sysTenantRoleService.getSysTenantRoleReportDatasetIdList(tenantRoleId);
String orderBy = MyOrderParam.buildOrderBy(orderParam, ReportDataset.class);
// SwitchTenantReportDatasource注解会将数据源切换到ApplicationConstant.TENANT_COMMON_DATASOURCE_TYPE
// 所指向的数据库,既租户业务的通用数据库。
List<ReportDataset> reportDatasetList =
reportDatasetService.getInList("datasetId", new HashSet<>(datasetIds), orderBy);
reportDatasetService.buildRelationForDataList(reportDatasetList, MyRelationParam.dictOnly());
return ResponseResult.success(MyPageUtil.makeResponseData(reportDatasetList, ReportDataset.INSTANCE));
}
/**
* 为指定租户角色添加报表数据集列表
*
* @param tenantRoleId 租户角色主键Id
* @param datasetIds 报表数据集Id集合
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.ADD_M2M)
@PostMapping("/addTenantRoleReportDataset")
public ResponseResult<Void> addTenantRoleReportDataset(
@MyRequestBody Long tenantRoleId, @MyRequestBody Set<Long> datasetIds) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, datasetIds)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
if (!sysTenantRoleService.existId(tenantRoleId)) {
return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID);
}
sysTenantRoleService.addTenantRoleReportDatasetList(tenantRoleId, datasetIds);
return ResponseResult.success();
}
/**
* 为指定租户角色移除指定报表数据集
*
* @param tenantRoleId 指定租户角色主键Id
* @param datasetId 指定报表数据集主键Id
* @param force 是否强制移除
* @return 应答数据结果
*/
@OperationLog(type = SysOperationLogType.DELETE_M2M)
@PostMapping("/deleteTenantRoleReportDataset")
public ResponseResult<Void> deleteTenantRoleReportDataset(
@MyRequestBody Long tenantRoleId, @MyRequestBody Long datasetId, @MyRequestBody Boolean force) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, datasetId, force)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
// 判断该租户角色是否包含租户,如果不包含,就只是删除本地关联数据即可。
if (!sysTenantRoleService.hasTenantByRoleId(tenantRoleId)) {
sysTenantRoleService.removeTenantRoleReportDataset(tenantRoleId, datasetId);
return ResponseResult.success();
}
// 租户角色包含租户,如果不是强制删除,就给出错误提示即可。
if (BooleanUtil.isFalse(force)) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED,
"数据操作失败,当前租户角色包含租户数据,是否强制删除!");
}
sysTenantRoleService.removeTenantRoleReportDatasetAndSync(tenantRoleId, datasetId);
return ResponseResult.success();
}
/**
* 列出指定租户角色没有包含的在线表单页面列表
*
* @param tenantRoleId 租户角色主键Id
* @param onlinePageDtoFilter 过滤对象
* @param orderParam 排序参数
* @return 应答结果对象指定租户角色没有包含的在线表单页面列表
*/
@SwitchTenantCommonDatasource
@PostMapping("/listNotInTenantRoleOnlinePage")
public ResponseResult<MyPageData<OnlinePageVo>> listNotInTenantRoleOnlinePage(
@MyRequestBody Long tenantRoleId,
@MyRequestBody OnlinePageDto onlinePageDtoFilter,
@MyRequestBody MyOrderParam orderParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
List<Long> pageIds = sysTenantRoleService.getSysTenantRoleOnlinePageIdList(tenantRoleId);
String orderBy = MyOrderParam.buildOrderBy(orderParam, OnlinePage.class);
// SwitchTenantReportDatasource注解会将数据源切换到ApplicationConstant.TENANT_COMMON_DATASOURCE_TYPE
// 所指向的数据库,既租户业务的通用数据库。
List<OnlinePage> onlinePageList = onlinePageService.getNotInListWithNonTenant(pageIds, orderBy);
if (onlinePageDtoFilter != null && onlinePageDtoFilter.getPageType() != null) {
onlinePageList = onlinePageList.stream()
.filter(d -> d.getPageType().equals(onlinePageDtoFilter.getPageType())).collect(Collectors.toList());
}
onlinePageList = onlinePageList.stream()
.filter(d -> ObjectUtil.equal(d.getAppCode(), TokenData.takeFromRequest().getAppCode()))
.collect(Collectors.toList());
onlinePageService.buildRelationForDataList(onlinePageList, MyRelationParam.dictOnly());
return ResponseResult.success(MyPageUtil.makeResponseData(onlinePageList, OnlinePage.INSTANCE));
}
/**
* 列出指定租户角色的在线表单页面列表
*
* @param tenantRoleId 租户角色主键Id
* @param orderParam 排序参数
* @return 应答结果对象指定租户角色包含在线表单页面列表
*/
@SwitchTenantCommonDatasource
@PostMapping("/listTenantRoleOnlinePage")
public ResponseResult<MyPageData<OnlinePageVo>> listTenantRoleOnlinePage(
@MyRequestBody Long tenantRoleId, @MyRequestBody MyOrderParam orderParam) {
ResponseResult<Void> verifyResult = this.doTenantRoleVerify(tenantRoleId);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
List<Long> pageIds = sysTenantRoleService.getSysTenantRoleOnlinePageIdList(tenantRoleId);
String orderBy = MyOrderParam.buildOrderBy(orderParam, OnlinePage.class);
// SwitchTenantReportDatasource注解会将数据源切换到ApplicationConstant.TENANT_COMMON_DATASOURCE_TYPE
// 所指向的数据库,既租户业务的通用数据库。
List<OnlinePage> onlinePageList = onlinePageService.getInListWithNonTenant(pageIds, orderBy);
onlinePageService.buildRelationForDataList(onlinePageList, MyRelationParam.dictOnly());
return ResponseResult.success(MyPageUtil.makeResponseData(onlinePageList, OnlinePage.INSTANCE));
}
/**
* 为指定租户角色添加在线表单页面列表
*
* @param tenantRoleId 租户角色主键Id
* @param pageIds 在线表单页面Id集合
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.ADD_M2M)
@PostMapping("/addTenantRoleOnlinePage")
public ResponseResult<Void> addTenantRoleOnlinePage(
@MyRequestBody Long tenantRoleId, @MyRequestBody Set<Long> pageIds) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, pageIds)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
if (!sysTenantRoleService.existId(tenantRoleId)) {
return ResponseResult.error(ErrorCodeEnum.INVALID_RELATED_RECORD_ID);
}
sysTenantRoleService.addTenantRoleOnlinePageList(tenantRoleId, pageIds);
return ResponseResult.success();
}
/**
* 为指定租户角色移除指定在线表单页面
*
* @param tenantRoleId 指定租户角色主键Id
* @param pageId 指定在线表单页面主键Id
* @param force 是否强制移除
* @return 应答数据结果
*/
@OperationLog(type = SysOperationLogType.DELETE_M2M)
@PostMapping("/deleteTenantRoleOnlinePage")
public ResponseResult<Void> deleteTenantRoleOnlinePage(
@MyRequestBody Long tenantRoleId, @MyRequestBody Long pageId, @MyRequestBody Boolean force) {
if (MyCommonUtil.existBlankArgument(tenantRoleId, pageId, force)) {
return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST);
}
// 判断该租户角色是否包含租户,如果不包含,就只是删除本地关联数据即可。
if (!sysTenantRoleService.hasTenantByRoleId(tenantRoleId)) {
sysTenantRoleService.removeTenantRoleOnlinePage(tenantRoleId, pageId);
return ResponseResult.success();
}
// 租户角色包含租户,如果不是强制删除,就给出错误提示即可。
if (BooleanUtil.isFalse(force)) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED,
"数据操作失败,当前租户角色包含租户数据,是否强制删除!");
}
sysTenantRoleService.removeTenantRoleOnlinePageAndSync(tenantRoleId, pageId);
return ResponseResult.success();
}
}

506
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/controller/TenantGlobalDictController.java

@ -0,0 +1,506 @@ @@ -0,0 +1,506 @@
package apelet.tenantadmin.tenant.controller;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.BooleanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import apelet.common.core.annotation.MyRequestBody;
import apelet.common.core.constant.ApplicationConstant;
import apelet.common.core.constant.ErrorCodeEnum;
import apelet.common.core.object.MyOrderParam;
import apelet.common.core.object.MyPageData;
import apelet.common.core.object.MyPageParam;
import apelet.common.core.object.ResponseResult;
import apelet.common.core.util.MyCommonUtil;
import apelet.common.core.util.MyModelUtil;
import apelet.common.core.util.MyPageUtil;
import apelet.common.core.validator.UpdateGroup;
import apelet.common.dict.dto.TenantGlobalDictDto;
import apelet.common.dict.dto.TenantGlobalDictItemDto;
import apelet.common.dict.model.TenantGlobalDict;
import apelet.common.dict.model.TenantGlobalDictItem;
import apelet.common.dict.service.TenantGlobalDictItemService;
import apelet.common.dict.service.TenantGlobalDictService;
import apelet.common.dict.vo.TenantGlobalDictVo;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.common.log.annotation.OperationLog;
import apelet.common.log.model.constant.SysOperationLogType;
import apelet.tenantadmin.tenant.model.SysTenant;
import apelet.tenantadmin.tenant.service.SysTenantService;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.groups.Default;
import java.util.*;
import java.util.stream.Collectors;
/**
* 租户全局通用字典操作接口
*
* @author guifc
* @date 2023-08-04
*/
@Tag(name = "租户全局字典管理接口")
@Slf4j
@RestController
@RequestMapping("/tenantadmin/tenant/tenantGlobalDict")
public class TenantGlobalDictController {
@Autowired
private TenantGlobalDictService tenantGlobalDictService;
@Autowired
private TenantGlobalDictItemService tenantGlobalDictItemService;
@Autowired
private SysTenantService sysTenantService;
@Autowired
private IdGeneratorWrapper idGenerator;
private static final String ID = "id";
private static final String ITEM_ID = "itemId";
/**
* 新增租户全局字典接口
*
* @param tenantGlobalDictDto 新增字典对象
* @return 保存后的字典对象
*/
@ApiOperationSupport(ignoreParameters = {"tenantGlobalDictDto.dictId"})
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/add")
public ResponseResult<Long> add(@MyRequestBody TenantGlobalDictDto tenantGlobalDictDto) {
String errorMessage = MyCommonUtil.getModelValidationError(tenantGlobalDictDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
// 这里必须手动校验字典编码是否存在,因为我们缺省的实现是逻辑删除,所以字典编码字段没有设置为唯一索引。
if (tenantGlobalDictService.existDictCode(tenantGlobalDictDto.getDictCode())) {
errorMessage = "数据验证失败,租户字典编码已经存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
TenantGlobalDict tenantGlobalDict = MyModelUtil.copyTo(tenantGlobalDictDto, TenantGlobalDict.class);
Set<Long> tenantIdSet = null;
if (BooleanUtil.isFalse(tenantGlobalDict.getTenantCommon())) {
tenantIdSet = sysTenantService.getAllList().stream().map(SysTenant::getTenantId).collect(Collectors.toSet());
}
tenantGlobalDictService.saveNew(tenantGlobalDict, tenantIdSet);
return ResponseResult.success(tenantGlobalDict.getDictId());
}
/**
* 更新租户全局字典操作
*
* @param tenantGlobalDictDto 更新全局字典对象
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/update")
public ResponseResult<Void> update(@MyRequestBody TenantGlobalDictDto tenantGlobalDictDto) {
String errorMessage = MyCommonUtil.getModelValidationError(
tenantGlobalDictDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
TenantGlobalDict originalTenantGlobalDict =
tenantGlobalDictService.getById(tenantGlobalDictDto.getDictId());
if (originalTenantGlobalDict == null) {
errorMessage = "数据验证失败,当前租户全局字典并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
TenantGlobalDict tenantGlobalDict = MyModelUtil.copyTo(tenantGlobalDictDto, TenantGlobalDict.class);
if (ObjectUtil.notEqual(tenantGlobalDict.getDictCode(), originalTenantGlobalDict.getDictCode())) {
errorMessage = "数据验证失败,租户字典编码已经存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (ObjectUtil.notEqual(tenantGlobalDict.getTenantCommon(), originalTenantGlobalDict.getTenantCommon())) {
errorMessage = "数据验证失败,该字典已存在字典数据,不能修改是否为租户共用字典标记!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!tenantGlobalDictService.update(tenantGlobalDict, originalTenantGlobalDict)) {
errorMessage = "更新失败,数据不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
return ResponseResult.success();
}
/**
* 删除指定的租户全局字典
*
* @param dictId 指定全局字典主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/delete")
public ResponseResult<Void> delete(@MyRequestBody(required = true) Long dictId) {
if (!tenantGlobalDictService.remove(dictId)) {
String errorMessage = "数据操作失败,租户全局字典Id不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
return ResponseResult.success();
}
/**
* 查看租户全局字典列表
*
* @param tenantGlobalDictDtoFilter 过滤对象
* @param orderParam 排序参数
* @param pageParam 分页参数
* @return 应答结果对象包含角色列表
*/
@PostMapping("/list")
public ResponseResult<MyPageData<TenantGlobalDictVo>> list(
@MyRequestBody TenantGlobalDictDto tenantGlobalDictDtoFilter,
@MyRequestBody MyOrderParam orderParam,
@MyRequestBody MyPageParam pageParam) {
if (pageParam != null) {
PageMethod.startPage(pageParam.getPageNum(), pageParam.getPageSize());
}
TenantGlobalDict filter = MyModelUtil.copyTo(tenantGlobalDictDtoFilter, TenantGlobalDict.class);
List<TenantGlobalDict> tenantGlobalDictList =
tenantGlobalDictService.getGlobalDictList(
filter, MyOrderParam.buildOrderBy(orderParam, TenantGlobalDict.class));
List<TenantGlobalDictVo> tenantGlobalDictVoList =
MyModelUtil.copyCollectionTo(tenantGlobalDictList, TenantGlobalDictVo.class);
long totalCount = 0L;
if (tenantGlobalDictList instanceof Page) {
totalCount = ((Page<TenantGlobalDict>) tenantGlobalDictList).getTotal();
}
return ResponseResult.success(MyPageUtil.makeResponseData(tenantGlobalDictVoList, totalCount));
}
/**
* 获取字典详情
*
* @param dictId 字典主键
* @return 获取字典详情
*/
@GetMapping("/view")
public ResponseResult<TenantGlobalDictVo> view(@RequestParam Long dictId) {
TenantGlobalDict globalDict = tenantGlobalDictService.getById(dictId);
if (globalDict == null) {
String errorMessage = "数据操作失败,租户全局字典Id不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
return ResponseResult.success(MyModelUtil.copyTo(globalDict, TenantGlobalDictVo.class));
}
/**
* 新增租户全局字典项目接口
*
* @param tenantGlobalDictItemDto 新增字典项目对象
* @return 保存后的字典对象
*/
@ApiOperationSupport(ignoreParameters = {"tenantGlobalDictItemDto.id"})
@OperationLog(type = SysOperationLogType.ADD)
@PostMapping("/addItem")
public ResponseResult<Long> addItem(@MyRequestBody TenantGlobalDictItemDto tenantGlobalDictItemDto) {
String errorMessage = MyCommonUtil.getModelValidationError(tenantGlobalDictItemDto);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
ResponseResult<TenantGlobalDict> verifyResult =
this.doVerifyTenantGlobalDict(tenantGlobalDictItemDto.getDictCode());
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
TenantGlobalDict dict = verifyResult.getData();
TenantGlobalDictItem dictItem = MyModelUtil.copyTo(tenantGlobalDictItemDto, TenantGlobalDictItem.class);
Long id = null;
if (BooleanUtil.isTrue(dict.getTenantCommon())) {
if (tenantGlobalDictItemService.existDictCodeAndItemId(dict, tenantGlobalDictItemDto.getItemId())) {
errorMessage = "数据验证失败,该租户字典编码的项目Id已存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
tenantGlobalDictItemService.saveNew(dict, dictItem);
id = dictItem.getId();
} else {
if (this.existItemForTenantDict(dict, dictItem)) {
errorMessage = "数据验证失败,该租户字典编码的项目Id已存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
// 对于非租户公共字典,这里添加的字典数据,都是该编码字典的初始化数据,只会在新建租户的时候,
// 将这里的数据同步到租户的编码字典中,后面所有的修改,都不会再同步到租户的字典数据了,也避免
// 了数据冲突。
this.addInitialData(dict, dictItem);
MyModelUtil.fillCommonsForUpdate(dict, dict);
tenantGlobalDictService.updateById(dict);
}
return ResponseResult.success(id);
}
/**
* 更新租户全局字典项目
*
* @param tenantGlobalDictItemDto 更新全局字典项目对象
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/updateItem")
public ResponseResult<Void> updateItem(@MyRequestBody TenantGlobalDictItemDto tenantGlobalDictItemDto) {
String errorMessage = MyCommonUtil.getModelValidationError(
tenantGlobalDictItemDto, Default.class, UpdateGroup.class);
if (errorMessage != null) {
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
ResponseResult<TenantGlobalDict> verifyResult =
this.doVerifyTenantGlobalDict(tenantGlobalDictItemDto.getDictCode());
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
TenantGlobalDictItem dictItem = MyModelUtil.copyTo(tenantGlobalDictItemDto, TenantGlobalDictItem.class);
TenantGlobalDict dict = verifyResult.getData();
if (BooleanUtil.isTrue(dict.getTenantCommon())) {
TenantGlobalDictItem originalDictItem =
tenantGlobalDictItemService.getById(tenantGlobalDictItemDto.getId());
if (originalDictItem == null) {
errorMessage = "数据验证失败,当前租户全局字典项目并不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
if (ObjectUtil.notEqual(dictItem.getDictCode(), originalDictItem.getDictCode())) {
errorMessage = "数据验证失败,租户字典项目的字典编码不能修改!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (ObjectUtil.notEqual(dictItem.getItemId(), originalDictItem.getItemId())
&& tenantGlobalDictItemService.existDictCodeAndItemId(dict, dictItem.getItemId())) {
errorMessage = "数据验证失败,该租户字典编码的项目Id已存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (!tenantGlobalDictItemService.update(dict, dictItem, originalDictItem)) {
errorMessage = "更新失败,数据不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
} else {
if (this.existItemForTenantDict(dict, dictItem)) {
errorMessage = "数据验证失败,该租户字典编码的项目Id已存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
// 对于非租户公共字典,这里添加的字典数据,都是该编码字典的初始化数据,只会在新建租户的时候,
// 将这里的数据同步到租户的编码字典中,后面所有的修改,都不会再同步到租户的字典数据了,也避免
// 了数据冲突。
this.updateInitialData(dict, dictItem);
MyModelUtil.fillCommonsForUpdate(dict, dict);
tenantGlobalDictService.updateById(dict);
}
return ResponseResult.success();
}
/**
* 更新租户全局字典项目的状态
*
* @param id 更新全局字典项目主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.UPDATE)
@PostMapping("/updateItemStatus")
public ResponseResult<Void> updateItemStatus(
@MyRequestBody(required = true) Long id, @MyRequestBody(required = true) Integer status) {
String errorMessage;
TenantGlobalDictItem dictItem = tenantGlobalDictItemService.getById(id);
if (dictItem == null) {
errorMessage = "数据操作失败,全局字典项目Id不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
ResponseResult<TenantGlobalDict> verifyResult = this.doVerifyTenantGlobalDict(dictItem.getDictCode());
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
TenantGlobalDict dict = verifyResult.getData();
if (BooleanUtil.isFalse(dict.getTenantCommon())) {
errorMessage = "数据验证失败,非公用租户编码字典,不能调用该接口!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
if (ObjectUtil.notEqual(dictItem.getStatus(), status)) {
tenantGlobalDictItemService.updateStatus(dict, dictItem, status);
}
return ResponseResult.success();
}
/**
* 删除指定编码的租户全局字典项目
*
* @param dictCode 字典编码
* @param id 字典项目主键Id
* @return 应答结果对象
*/
@OperationLog(type = SysOperationLogType.DELETE)
@PostMapping("/deleteItem")
public ResponseResult<Void> deleteItem(
@MyRequestBody(required = true) String dictCode,
@MyRequestBody(required = true) Long id) {
ResponseResult<TenantGlobalDict> verifyResult = this.doVerifyTenantGlobalDict(dictCode);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
String errorMessage;
TenantGlobalDict dict = verifyResult.getData();
if (BooleanUtil.isTrue(dict.getTenantCommon())) {
TenantGlobalDictItem dictItem = tenantGlobalDictItemService.getById(id);
if (dictItem == null) {
errorMessage = "数据操作失败,全局字典项目Id不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
if (!tenantGlobalDictItemService.remove(dict, dictItem)) {
errorMessage = "数据操作失败,全局字典项目Id不存在,请刷新后重试!";
return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, errorMessage);
}
} else {
// 对于非租户公共字典,这里添加的字典数据,都是该编码字典的初始化数据,只会在新建租户的时候,
// 将这里的数据同步到租户的编码字典中,后面所有的修改,都不会再同步到租户的字典数据了,也避免
// 了数据冲突。
this.removeInitialData(dict, id);
MyModelUtil.fillCommonsForUpdate(dict, dict);
tenantGlobalDictService.updateById(dict);
}
return ResponseResult.success();
}
/**
* 白名单接口登录用户均可访问以字典形式返回全部租户字典数据集合
* fullResultList中的字典列表全部取自于数据库而cachedResultList全部取自于缓存前端负责比对
*
* @return 应答结果对象包含字典形式的数据集合
*/
@GetMapping("/listAll")
public ResponseResult<JSONObject> listAll(@RequestParam String dictCode) {
ResponseResult<TenantGlobalDict> verifyResult = this.doVerifyTenantGlobalDict(dictCode);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
String errorMessage;
TenantGlobalDict dict = verifyResult.getData();
if (BooleanUtil.isFalse(dict.getTenantCommon())) {
errorMessage = "数据验证失败,非公用租户编码字典,不能调用该接口!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
List<TenantGlobalDictItem> fullResultList = tenantGlobalDictItemService.getGlobalDictItemList(dict);
List<TenantGlobalDictItem> cachedList =
tenantGlobalDictService.getGlobalDictItemListFromCache(dict, null);
JSONObject jsonObject = new JSONObject();
jsonObject.put("fullResultList", this.toDictDataList(fullResultList));
jsonObject.put("cachedResultList", this.toDictDataList(cachedList));
return ResponseResult.success(jsonObject);
}
/**
* 将当前租户通用字典表的数据重新加载到缓存中
* 由于缓存的数据更新在add/update/delete等接口均有同步处理因此该接口仅当同步过程中出现问题时
* 可手工调用或者每天晚上定时同步一次
*/
@OperationLog(type = SysOperationLogType.RELOAD_CACHE)
@GetMapping("/reloadCachedData")
public ResponseResult<Boolean> reloadCachedData(@RequestParam String dictCode) {
ResponseResult<TenantGlobalDict> verifyResult = this.doVerifyTenantGlobalDict(dictCode);
if (!verifyResult.isSuccess()) {
return ResponseResult.errorFrom(verifyResult);
}
TenantGlobalDict dict = verifyResult.getData();
if (BooleanUtil.isTrue(dict.getTenantCommon())) {
tenantGlobalDictService.reloadCachedData(dict);
} else {
tenantGlobalDictService.reloadAllTenantCachedData(dict);
}
return ResponseResult.success(true);
}
private List<Map<String, Object>> toDictDataList(List<TenantGlobalDictItem> resultList) {
return resultList.stream().map(item -> {
Map<String, Object> dataMap = new HashMap<>(2);
dataMap.put(ApplicationConstant.DICT_ID, item.getId());
dataMap.put(ApplicationConstant.DICT_NAME, item.getItemName());
dataMap.put(ITEM_ID, item.getItemId());
dataMap.put("status", item.getStatus());
dataMap.put("showOrder", item.getShowOrder());
return dataMap;
}).collect(Collectors.toList());
}
private ResponseResult<TenantGlobalDict> doVerifyTenantGlobalDict(String dictCode) {
String errorMessage;
TenantGlobalDict tenantGlobalDict =
tenantGlobalDictService.getTenantGlobalDictByDictCode(dictCode);
if (tenantGlobalDict == null) {
errorMessage = "数据验证失败,租户字典编码不存在!";
return ResponseResult.error(ErrorCodeEnum.DATA_VALIDATED_FAILED, errorMessage);
}
return ResponseResult.success(tenantGlobalDict);
}
private boolean existItemForTenantDict(TenantGlobalDict dict, TenantGlobalDictItem dictItem) {
if (StrUtil.isBlank(dict.getInitialData())) {
return false;
}
// 解析并迭代数组数据,要求每个JSON对象中必须包含id和name。
JSONArray initialDataArray = JSONArray.parseArray(dict.getInitialData());
for (int i = 0; i < initialDataArray.size(); i++) {
JSONObject data = initialDataArray.getJSONObject(i);
if (StrUtil.equals(data.getString(ITEM_ID), dictItem.getItemId())
&& ObjectUtil.notEqual(data.getLong(ID), dictItem.getId())) {
return true;
}
}
return false;
}
private void addInitialData(TenantGlobalDict dict, TenantGlobalDictItem dictItem) {
JSONArray dataArray;
if (StrUtil.isBlank(dict.getInitialData())) {
dataArray = new JSONArray();
} else {
dataArray = JSON.parseArray(dict.getInitialData());
}
dataArray.add(this.convertToDictItemData(dictItem));
dict.setInitialData(dataArray.toJSONString());
}
private void updateInitialData(TenantGlobalDict dict, TenantGlobalDictItem dictItem) {
if (StrUtil.isBlank(dict.getInitialData())) {
return;
}
JSONArray resultArray = new JSONArray();
JSONArray dataArray = JSON.parseArray(dict.getInitialData());
for (int i = 0; i < dataArray.size(); i++) {
JSONObject data = dataArray.getJSONObject(i);
Long id = data.getLong(ID);
if (ObjectUtil.equals(id, dictItem.getId())) {
resultArray.add(this.convertToDictItemData(dictItem));
} else {
resultArray.add(data);
}
}
dict.setInitialData(resultArray.toJSONString());
}
private void removeInitialData(TenantGlobalDict dict, Long id) {
if (StrUtil.isBlank(dict.getInitialData())) {
return;
}
JSONArray resultArray = new JSONArray();
JSONArray dataArray = JSON.parseArray(dict.getInitialData());
for (int i = 0; i < dataArray.size(); i++) {
JSONObject data = dataArray.getJSONObject(i);
if (ObjectUtil.notEqual(data.getLong(ID), id)) {
resultArray.add(data);
}
}
dict.setInitialData(resultArray.toJSONString());
}
private JSONObject convertToDictItemData(TenantGlobalDictItem dictItem) {
JSONObject newData = new JSONObject();
if (dictItem.getId() == null) {
newData.put(ID, idGenerator.nextLongId());
} else {
newData.put(ID, dictItem.getId());
}
newData.put(ITEM_ID, dictItem.getItemId());
newData.put("itemName", dictItem.getItemName());
newData.put("showOrder", dictItem.getShowOrder());
return newData;
}
}

20
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/DeployPluginMapper.java

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.DeployPlugin;
import java.util.List;
/**
* <p>
* 热部署插件表 Mapper 接口
* </p>
*
* @author admin
* @since 2024-06-27 14:58:01
*/
public interface DeployPluginMapper extends BaseDaoMapper<DeployPlugin> {
List<DeployPlugin> getDeployPluginList(DeployPlugin deployPlugin, String orderBy);
}

13
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantDatasourceMapper.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantDatasource;
/**
* 租户数据源数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantDatasourceMapper extends BaseDaoMapper<SysTenantDatasource> {
}

13
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantExtMapper.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantExt;
/**
* 租户扩展数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantExtMapper extends BaseDaoMapper<SysTenantExt> {
}

83
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantMapper.java

@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenant;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 租户数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantMapper extends BaseDaoMapper<SysTenant> {
/**
* 根据租户过滤对象获取匹配的租户对象列表
*
* @param sysTenantFilter 租户过滤条件对象
* @param orderBy order by从句的参数
* @return 查询的租户列表
*/
List<SysTenant> getSysTenantList(
@Param("sysTenantFilter") SysTenant sysTenantFilter, @Param("orderBy") String orderBy);
/**
* 根据租户角色Id获取关联的租户菜单从表中没有和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序字符串order by从句的参数
* @return 与主表没有建立关联的从表数据列表
*/
List<SysTenant> getNotInSysTenantListByRoleId(
@Param("tenantRoleId") Long tenantRoleId,
@Param("sysTenantFilter") SysTenant sysTenantFilter,
@Param("orderBy") String orderBy);
/**
* 根据租户角色Id获取关联的租户菜单从表中和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序字符串order by从句的参数
* @return 与主表建立关联的从表数据列表
*/
List<SysTenant> getSysTenantListByRoleId(
@Param("tenantRoleId") Long tenantRoleId,
@Param("sysTenantFilter") SysTenant sysTenantFilter,
@Param("orderBy") String orderBy);
/**
* 查询租户的权限资源地址列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param url url过滤条件
* @return 包含从租户到权限资源的完整权限分配路径信息的查询结果列表
*/
List<Map<String, Object>> getSysTenantPermListWithDetail(
@Param("tenantId") Long tenantId, @Param("url") String url);
/**
* 查询租户的权限字列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param permCode 权限字名称过滤条件
* @return 包含从租户到权限字的权限分配路径信息的查询结果列表
*/
List<Map<String, Object>> getSysTenantPermCodeListWithDetail(
@Param("tenantId") Long tenantId, @Param("permCode") String permCode);
/**
* 查询租户的菜单列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param menuName 菜单名称过滤条件
* @return 包含从租户到菜单的权限分配路径信息的查询结果列表
*/
List<Map<String, Object>> getSysTenantMenuListWithDetail(
@Param("tenantId") Long tenantId, @Param("menuName") String menuName);
}

36
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantMenuMapper.java

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantMenu;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 租户菜单数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantMenuMapper extends BaseDaoMapper<SysTenantMenu> {
/**
* 根据租户角色Id获取关联的租户菜单从表中没有和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param orderBy 排序字符串order by从句的参数
* @return 与主表没有建立关联的从表数据列表
*/
List<SysTenantMenu> getNotInSysTenantMenuListByRoleId(
@Param("tenantRoleId") Long tenantRoleId, @Param("orderBy") String orderBy);
/**
* 根据租户角色Id获取关联的租户菜单从表和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param orderBy 排序字符串order by从句的参数
* @return 与主表建立关联的从表数据列表
*/
List<SysTenantMenu> getSysTenantMenuListByRoleId(
@Param("tenantRoleId") Long tenantRoleId, @Param("orderBy") String orderBy);
}

22
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantMenuPermCodeMapper.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantMenuPermCode;
import java.util.List;
/**
* 菜单与权限字关系数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantMenuPermCodeMapper extends BaseDaoMapper<SysTenantMenuPermCode> {
/**
* 批量插入租户菜单和权限字的关联关系
*
* @param sysMenuPermCodeList 租户菜单和权限字的关联列表
*/
void insertList(List<SysTenantMenuPermCode> sysMenuPermCodeList);
}

13
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermCodeMapper.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantPermCode;
/**
* 权限字数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantPermCodeMapper extends BaseDaoMapper<SysTenantPermCode> {
}

22
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermCodePermMapper.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantPermCodePerm;
import java.util.List;
/**
* 权限字与权限资源关系数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantPermCodePermMapper extends BaseDaoMapper<SysTenantPermCodePerm> {
/**
* 批量插入租户权限字和租户权限资源的关联关系
*
* @param sysPermCodePermList 租户权限字和租户权限资源的关联关系列表
*/
void insertList(List<SysTenantPermCodePerm> sysPermCodePermList);
}

13
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermMapper.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantPerm;
/**
* 权限资源数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantPermMapper extends BaseDaoMapper<SysTenantPerm> {
}

22
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantPermModuleMapper.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantPermModule;
import java.util.List;
/**
* 权限资源模块数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantPermModuleMapper extends BaseDaoMapper<SysTenantPermModule> {
/**
* 获取整个权限模块和权限关联后的全部数据
*
* @return 关联的权限模块和权限资源列表
*/
List<SysTenantPermModule> getPermModuleAndPermList();
}

26
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleMapper.java

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantRole;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 租户角色数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantRoleMapper extends BaseDaoMapper<SysTenantRole> {
/**
* 获取租户角色列表
*
* @param sysTenantRoleFilter 过滤对象
* @param orderBy 排序字符串order by从句的参数
* @return 租户角色列表
*/
List<SysTenantRole> getSysTenantRoleList(
@Param("sysTenantRoleFilter") SysTenantRole sysTenantRoleFilter, @Param("orderBy") String orderBy);
}

22
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleMenuMapper.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantRoleMenu;
import java.util.List;
/**
* 租户角色菜单数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantRoleMenuMapper extends BaseDaoMapper<SysTenantRoleMenu> {
/**
* 批量插入租户角色和租户菜单之间的关联关系列表
*
* @param sysTenantRoleMenuList 租户角色和租户菜单关联关系列表
*/
void insertList(List<SysTenantRoleMenu> sysTenantRoleMenuList);
}

22
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleOnlinePageMapper.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantRoleOnlinePage;
import java.util.List;
/**
* 租户角色在线表单页面访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantRoleOnlinePageMapper extends BaseDaoMapper<SysTenantRoleOnlinePage> {
/**
* 批量插入租户角色和在线表单页面之间的关联关系列表
*
* @param dataList 租户角色和在线表单页面关联关系列表
*/
void insertList(List<SysTenantRoleOnlinePage> dataList);
}

22
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleReportDatasetMapper.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantRoleReportDataset;
import java.util.List;
/**
* 租户角色报表数据集访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantRoleReportDatasetMapper extends BaseDaoMapper<SysTenantRoleReportDataset> {
/**
* 批量插入租户角色和报表数据集之间的关联关系列表
*
* @param dataList 租户角色和报表数据集关联关系列表
*/
void insertList(List<SysTenantRoleReportDataset> dataList);
}

22
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/SysTenantRoleTenantMapper.java

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
package apelet.tenantadmin.tenant.dao;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.tenantadmin.tenant.model.SysTenantRoleTenant;
import java.util.List;
/**
* 租户角色租户数据访问操作接口
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantRoleTenantMapper extends BaseDaoMapper<SysTenantRoleTenant> {
/**
* 批量新增租户角色和租户的关联关系
*
* @param sysTenantRoleTenantList 租户角色和租户的关联关系列表
*/
void insertList(List<SysTenantRoleTenant> sysTenantRoleTenantList);
}

10
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/DeployPluginMapper.xml

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.DeployPluginMapper">
<select id="getDeployPluginList" resultType="apelet.tenantadmin.tenant.model.DeployPlugin">
SELECT * FROM deploy_plugin
</select>
</mapper>

19
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantDatasourceMapper.xml

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantDatasourceMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantDatasource">
<id column="datasource_id" jdbcType="BIGINT" property="datasourceId"/>
<result column="datasource_name" jdbcType="VARCHAR" property="datasourceName"/>
<result column="datasource_type" jdbcType="INTEGER" property="datasourceType"/>
<result column="database_host" jdbcType="VARCHAR" property="databaseHost"/>
<result column="port" jdbcType="INTEGER" property="port"/>
<result column="username" jdbcType="VARCHAR" property="username"/>
<result column="password" jdbcType="VARCHAR" property="password"/>
<result column="schema_name" jdbcType="VARCHAR" property="schemaName"/>
<result column="database_name" jdbcType="VARCHAR" property="databaseName"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
</resultMap>
</mapper>

8
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantExtMapper.xml

@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantExtMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantExt">
<id column="tenant_id" jdbcType="BIGINT" property="tenantId"/>
<result column="tenant_online_page_ids" jdbcType="VARCHAR" property="tenantOnlinePageIds"/>
</resultMap>
</mapper>

184
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantMapper.xml

@ -0,0 +1,184 @@ @@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenant">
<id column="tenant_id" jdbcType="BIGINT" property="tenantId"/>
<result column="tenant_code" jdbcType="VARCHAR" property="tenantCode"/>
<result column="show_name" jdbcType="VARCHAR" property="showName"/>
<result column="datasource_type" jdbcType="INTEGER" property="datasourceType"/>
<result column="available" jdbcType="BOOLEAN" property="available"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
</resultMap>
<sql id="filterRef">
<!-- 这里必须加上全包名,否则当filterRef被其他Mapper.xml包含引用的时候,就会调用Mapper.xml中的该SQL片段 -->
<include refid="apelet.tenantadmin.tenant.dao.SysTenantMapper.inputFilterRef"/>
AND xy_sys_tenant.deleted_flag = ${@apelet.common.core.constant.GlobalDeletedFlag@NORMAL}
</sql>
<sql id="inputFilterRef">
<if test="sysTenantFilter != null">
<if test="sysTenantFilter.tenantCode != null and sysTenantFilter.tenantCode != ''">
AND xy_sys_tenant.tenant_code = #{sysTenantFilter.tenantCode}
</if>
<if test="sysTenantFilter.showName != null and sysTenantFilter.showName != ''">
<bind name = "safeShowName" value = "'%' + sysTenantFilter.showName + '%'" />
AND xy_sys_tenant.show_name LIKE #{safeShowName}
</if>
<if test="sysTenantFilter.datasourceType != null">
AND xy_sys_tenant.datasource_type = #{sysTenantFilter.datasourceType}
</if>
<if test="sysTenantFilter.available != null">
AND xy_sys_tenant.available = #{sysTenantFilter.available}
</if>
<if test="sysTenantFilter.createTimeStart != null and sysTenantFilter.createTimeStart != ''">
AND xy_sys_tenant.create_time &gt;= #{sysTenantFilter.createTimeStart}
</if>
<if test="sysTenantFilter.createTimeEnd != null and sysTenantFilter.createTimeEnd != ''">
AND xy_sys_tenant.create_time &lt;= #{sysTenantFilter.createTimeEnd}
</if>
</if>
</sql>
<select id="getSysTenantList" resultMap="BaseResultMap">
SELECT
xy_sys_tenant.*
FROM
xy_sys_tenant
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getNotInSysTenantListByRoleId" resultMap="BaseResultMap">
SELECT
xy_sys_tenant.*
FROM
xy_sys_tenant
<where>
AND NOT EXISTS (SELECT * FROM xy_sys_tenant_role_tenant
WHERE xy_sys_tenant_role_tenant.tenant_role_id = #{tenantRoleId} AND xy_sys_tenant_role_tenant.tenant_id = xy_sys_tenant.tenant_id)
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getSysTenantListByRoleId" resultMap="BaseResultMap">
SELECT
xy_sys_tenant.*
FROM
xy_sys_tenant,
xy_sys_tenant_role_tenant
<where>
AND xy_sys_tenant_role_tenant.tenant_role_id = #{tenantRoleId}
AND xy_sys_tenant_role_tenant.tenant_id = xy_sys_tenant.tenant_id
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<!-- 以下查询仅用于权限分配的问题定位,由于关联表较多,可能会给系统运行带来性能影响 -->
<select id="getSysTenantPermListWithDetail" resultType="map">
SELECT
tr.tenant_role_id roleId,
tr.role_name roleName,
tm.menu_id menuId,
tm.menu_name menuName,
tm.menu_type menuType,
tpc.perm_code_id permCodeId,
tpc.perm_code permCode,
tpc.perm_code_type permCodeType,
tp.url url
FROM
xy_sys_tenant_role_tenant trt,
xy_sys_tenant_role tr,
xy_sys_tenant_role_menu trm,
xy_sys_tenant_menu tm,
xy_sys_tenant_menu_perm_code tmpc,
xy_sys_tenant_perm_code tpc,
xy_sys_tenant_perm_code_perm tpcp,
xy_sys_tenant_perm tp
<where>
AND trt.tenant_id = #{tenantId}
AND trt.tenant_role_id = tr.tenant_role_id
AND trt.tenant_role_id = trm.tenant_role_id
AND trm.menu_id = tm.menu_id
AND trm.menu_id = tmpc.menu_id
AND tmpc.perm_code_id = tpc.perm_code_id
AND tmpc.perm_code_id = tpcp.perm_code_id
AND tpcp.perm_id = tp.perm_id
<if test="url != null and url != ''">
AND tp.url = #{url}
</if>
</where>
ORDER BY
tr.tenant_role_id, tm.menu_id, tpc.perm_code_id, tp.url
</select>
<select id="getSysTenantPermCodeListWithDetail" resultType="map">
SELECT
tr.tenant_role_id roleId,
tr.role_name roleName,
tm.menu_id menuId,
tm.menu_name menuName,
tm.menu_type menuType,
tpc.perm_code_id permCodeId,
tpc.perm_code permCode,
tpc.perm_code_type permCodeType
FROM
xy_sys_tenant_role_tenant trt,
xy_sys_tenant_role tr,
xy_sys_tenant_role_menu trm,
xy_sys_tenant_menu tm,
xy_sys_tenant_menu_perm_code tmpc,
xy_sys_tenant_perm_code tpc
<where>
AND trt.tenant_id = #{tenantId}
AND trt.tenant_role_id = tr.tenant_role_id
AND trt.tenant_role_id = trm.tenant_role_id
AND trm.menu_id = tm.menu_id
AND trm.menu_id = tmpc.menu_id
AND tmpc.perm_code_id = tpc.perm_code_id
<if test="permCode != null and permCode != ''">
AND tpc.perm_code = #{permCode}
</if>
</where>
ORDER BY
tr.tenant_role_id, tm.menu_id, tpc.perm_code_id
</select>
<select id="getSysTenantMenuListWithDetail" resultType="map">
SELECT
tr.tenant_role_id tenantRoleId,
tr.role_name roleName,
tm.menu_id menuId,
tm.menu_name menuName,
tm.menu_type menuType
FROM
xy_sys_tenant_role_tenant trt,
xy_sys_tenant_role tr,
xy_sys_tenant_role_menu trm,
xy_sys_tenant_menu tm
<where>
AND trt.tenant_id = #{tenantId}
AND trt.tenant_role_id = tr.tenant_role_id
AND trt.tenant_role_id = trm.tenant_role_id
AND trm.menu_id = tm.menu_id
<if test="menuName != null and menuName != ''">
AND tm.menu_name = #{menuName}
</if>
</where>
ORDER BY
tr.tenant_role_id, tm.menu_id
</select>
</mapper>

52
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantMenuMapper.xml

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantMenuMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantMenu">
<id column="menu_id" jdbcType="BIGINT" property="menuId"/>
<result column="parent_id" jdbcType="BIGINT" property="parentId"/>
<result column="menu_name" jdbcType="VARCHAR" property="menuName"/>
<result column="menu_type" jdbcType="INTEGER" property="menuType"/>
<result column="form_router_name" jdbcType="VARCHAR" property="formRouterName"/>
<result column="online_form_id" jdbcType="BIGINT" property="onlineFormId"/>
<result column="online_menu_perm_type" jdbcType="INTEGER" property="onlineMenuPermType"/>
<result column="report_page_id" jdbcType="BIGINT" property="reportPageId"/>
<result column="show_order" jdbcType="INTEGER" property="showOrder"/>
<result column="icon" jdbcType="VARCHAR" property="icon"/>
<result column="extra_data" jdbcType="VARCHAR" property="extraData"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
</resultMap>
<select id="getSysTenantMenuListByRoleId" resultMap="BaseResultMap">
SELECT
xy_sys_tenant_menu.*
FROM
xy_sys_tenant_menu,
xy_sys_tenant_role_menu
<where>
AND xy_sys_tenant_role_menu.tenant_role_id = #{tenantRoleId}
AND xy_sys_tenant_role_menu.menu_id = xy_sys_tenant_menu.menu_id
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
<select id="getNotInSysTenantMenuListByRoleId" resultMap="BaseResultMap">
SELECT
xy_sys_tenant_menu.*
FROM
xy_sys_tenant_menu
<where>
AND NOT EXISTS (SELECT * FROM xy_sys_tenant_role_menu
WHERE xy_sys_tenant_role_menu.tenant_role_id = #{tenantRoleId} AND xy_sys_tenant_role_menu.menu_id = xy_sys_tenant_menu.menu_id)
AND xy_sys_tenant_menu.deleted_flag = ${@apelet.common.core.constant.GlobalDeletedFlag@NORMAL}
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

15
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantMenuPermCodeMapper.xml

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantMenuPermCodeMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantMenuPermCode">
<id column="menu_id" jdbcType="BIGINT" property="menuId"/>
<id column="perm_code_id" jdbcType="BIGINT" property="permCodeId"/>
</resultMap>
<insert id="insertList">
INSERT INTO xy_sys_tenant_menu_perm_code(menu_id, perm_code_id) VALUES
<foreach collection="list" index="index" item="item" separator=",">
(#{item.menuId}, #{item.permCodeId})
</foreach>
</insert>
</mapper>

17
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermCodeMapper.xml

@ -0,0 +1,17 @@ @@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantPermCodeMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantPermCode">
<id column="perm_code_id" jdbcType="BIGINT" property="permCodeId"/>
<result column="parent_id" jdbcType="BIGINT" property="parentId"/>
<result column="perm_code" jdbcType="VARCHAR" property="permCode"/>
<result column="perm_code_type" jdbcType="INTEGER" property="permCodeType"/>
<result column="show_name" jdbcType="VARCHAR" property="showName"/>
<result column="show_order" jdbcType="INTEGER" property="showOrder"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
</resultMap>
</mapper>

15
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermCodePermMapper.xml

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantPermCodePermMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantPermCodePerm">
<id column="perm_code_id" jdbcType="BIGINT" property="permCodeId"/>
<id column="perm_id" jdbcType="BIGINT" property="permId"/>
</resultMap>
<insert id="insertList">
INSERT INTO xy_sys_tenant_perm_code_perm(perm_code_id, perm_id) VALUES
<foreach collection="list" index="index" item="item" separator=",">
(#{item.permCodeId}, #{item.permId})
</foreach>
</insert>
</mapper>

16
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermMapper.xml

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantPermMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantPerm">
<id column="perm_id" jdbcType="BIGINT" property="permId"/>
<result column="module_id" jdbcType="BIGINT" property="moduleId"/>
<result column="perm_name" jdbcType="VARCHAR" property="permName"/>
<result column="url" jdbcType="VARCHAR" property="url"/>
<result column="show_order" jdbcType="INTEGER" property="showOrder"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
</resultMap>
</mapper>

44
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantPermModuleMapper.xml

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantPermModuleMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantPermModule">
<id column="module_id" jdbcType="BIGINT" property="moduleId"/>
<result column="parent_id" jdbcType="BIGINT" property="parentId"/>
<result column="module_name" jdbcType="VARCHAR" property="moduleName"/>
<result column="module_type" jdbcType="INTEGER" property="moduleType"/>
<result column="show_order" jdbcType="INTEGER" property="showOrder"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
</resultMap>
<resultMap id="BaseResultMapEx" type="apelet.tenantadmin.tenant.model.SysTenantPermModule" extends="BaseResultMap">
<collection property="sysPermList" column="module_id" javaType="ArrayList"
ofType="apelet.tenantadmin.tenant.model.SysTenantPerm" notNullColumn="perm_id"
resultMap="apelet.tenantadmin.tenant.dao.SysTenantPermMapper.BaseResultMap">
</collection>
</resultMap>
<select id="getPermModuleAndPermList" resultMap="BaseResultMapEx">
SELECT
pm.module_id,
pm.module_name,
pm.parent_id,
pm.module_type,
p.perm_id,
p.perm_name,
p.module_id,
p.url
FROM
xy_sys_tenant_perm_module pm
LEFT JOIN
xy_sys_tenant_perm p ON pm.module_id = p.module_id AND p.deleted_flag = ${@apelet.common.core.constant.GlobalDeletedFlag@NORMAL}
<where>
AND pm.deleted_flag = ${@apelet.common.core.constant.GlobalDeletedFlag@NORMAL}
</where>
ORDER BY
pm.show_order, p.show_order
</select>
</mapper>

33
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleMapper.xml

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantRoleMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantRole">
<id column="tenant_role_id" jdbcType="BIGINT" property="tenantRoleId"/>
<result column="role_name" jdbcType="VARCHAR" property="roleName"/>
<result column="create_user_id" jdbcType="BIGINT" property="createUserId"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_user_id" jdbcType="BIGINT" property="updateUserId"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
<result column="deleted_flag" jdbcType="INTEGER" property="deletedFlag"/>
</resultMap>
<sql id="filterRef">
<if test="sysTenantRoleFilter != null">
<if test="sysTenantRoleFilter.roleName != null and sysTenantRoleFilter.roleName != ''">
<bind name= "safeRoleName" value= "'%' + sysTenantRoleFilter.roleName + '%'"/>
AND role_name LIKE #{safeRoleName}
</if>
</if>
AND xy_sys_tenant_role.deleted_flag = ${@apelet.common.core.constant.GlobalDeletedFlag@NORMAL}
</sql>
<select id="getSysTenantRoleList" resultMap="BaseResultMap" parameterType="apelet.tenantadmin.tenant.model.SysTenantRole">
SELECT * FROM xy_sys_tenant_role
<where>
<include refid="filterRef"/>
</where>
<if test="orderBy != null and orderBy != ''">
ORDER BY ${orderBy}
</if>
</select>
</mapper>

15
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleMenuMapper.xml

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantRoleMenuMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantRoleMenu">
<id column="tenant_role_id" jdbcType="BIGINT" property="tenantRoleId"/>
<id column="menu_id" jdbcType="BIGINT" property="menuId"/>
</resultMap>
<insert id="insertList">
INSERT INTO xy_sys_tenant_role_menu(tenant_role_id, menu_id) VALUES
<foreach collection="list" index="index" item="item" separator=",">
(#{item.tenantRoleId}, #{item.menuId})
</foreach>
</insert>
</mapper>

15
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleOnlinePageMapper.xml

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantRoleOnlinePageMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantRoleOnlinePage">
<id column="tenant_role_id" jdbcType="BIGINT" property="tenantRoleId"/>
<id column="page_id" jdbcType="BIGINT" property="pageId"/>
</resultMap>
<insert id="insertList">
INSERT INTO xy_sys_tenant_role_online_page(tenant_role_id, page_id) VALUES
<foreach collection="list" index="index" item="item" separator=",">
(#{item.tenantRoleId}, #{item.pageId})
</foreach>
</insert>
</mapper>

15
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleReportDatasetMapper.xml

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantRoleReportDatasetMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantRoleReportDataset">
<id column="tenant_role_id" jdbcType="BIGINT" property="tenantRoleId"/>
<id column="dataset_id" jdbcType="BIGINT" property="datasetId"/>
</resultMap>
<insert id="insertList">
INSERT INTO xy_sys_tenant_role_report_ds(tenant_role_id, dataset_id) VALUES
<foreach collection="list" index="index" item="item" separator=",">
(#{item.tenantRoleId}, #{item.datasetId})
</foreach>
</insert>
</mapper>

15
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dao/mapper/SysTenantRoleTenantMapper.xml

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="apelet.tenantadmin.tenant.dao.SysTenantRoleTenantMapper">
<resultMap id="BaseResultMap" type="apelet.tenantadmin.tenant.model.SysTenantRoleTenant">
<id column="tenant_role_id" jdbcType="BIGINT" property="tenantRoleId"/>
<id column="tenant_id" jdbcType="BIGINT" property="tenantId"/>
</resultMap>
<insert id="insertList">
INSERT INTO xy_sys_tenant_role_tenant(tenant_role_id, tenant_id) VALUES
<foreach collection="list" index="index" item="item" separator=",">
(#{item.tenantRoleId}, #{item.tenantId})
</foreach>
</insert>
</mapper>

81
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantDatasourceDto.java

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
package apelet.tenantadmin.tenant.dto;
import apelet.common.core.validator.UpdateGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 租户数据源Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户数据源Dto对象")
@Data
public class SysTenantDatasourceDto {
/**
* 租户数据源Id
*/
@Schema(description = "租户数据源Id")
@NotNull(message = "租户数据源Id不能为空!", groups = {UpdateGroup.class})
private Long datasourceId;
/**
* 租户数据源名称
*/
@Schema(description = "租户数据源名称")
@NotBlank(message = "租户数据源名称不能为空!")
private String datasourceName;
/**
* 租户所在数据源的类型值
*/
@Schema(description = "租户所在数据源的类型值")
@NotNull(message = "租户所在数据源的类型值不能为空!")
private Integer datasourceType;
/**
* 主机名
*/
@Schema(description = "主机名")
@NotBlank(message = "主机名不能为空!")
private String databaseHost;
/**
* 端口号
*/
@Schema(description = "端口号")
@NotNull(message = "端口号不能为空!")
private Integer port;
/**
* 用户名
*/
@Schema(description = "用户名")
@NotBlank(message = "用户名不能为空!")
private String username;
/**
* 密码
*/
@Schema(description = "密码")
@NotBlank(message = "密码不能为空!")
private String password;
/**
* 模式名
*/
@Schema(description = "模式名")
private String schemaName;
/**
* 数据库名
*/
@Schema(description = "数据库名")
@NotBlank(message = "数据库名不能为空!")
private String databaseName;
}

66
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantDto.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
package apelet.tenantadmin.tenant.dto;
import apelet.common.core.validator.UpdateGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 租户Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户Dto对象")
@Data
public class SysTenantDto {
/**
* 租户Id
*/
@Schema(description = "租户Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户Id不能为空!", groups = {UpdateGroup.class})
private Long tenantId;
/**
* 租户的英文编码
*/
@Schema(description = "租户的英文编码", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户编码不能为空!")
private String tenantCode;
/**
* 租户的中文显示名称
*/
@Schema(description = "租户的中文显示名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户编码不能为空!")
private String showName;
/**
* 租户所在数据源的类型值
*/
@Schema(description = "租户所在数据源的类型值", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户所在数据源的类型值不能为空!")
private Integer datasourceType;
/**
* 是否可用标记
*/
@Schema(description = "是否可用标记", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户是否可用标记不能为空!", groups = {UpdateGroup.class})
private Boolean available;
/**
* [创建时间] 范围过滤起始值(>=)
*/
@Schema(description = "[创建时间] 范围过滤起始值(>=)")
private String createTimeStart;
/**
* [创建时间] 范围过滤结束值(<=)
*/
@Schema(description = "[创建时间] 范围过滤结束值(<=)")
private String createTimeEnd;
}

86
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantMenuDto.java

@ -0,0 +1,86 @@ @@ -0,0 +1,86 @@
package apelet.tenantadmin.tenant.dto;
import apelet.common.core.validator.ConstDictRef;
import apelet.common.core.validator.UpdateGroup;
import apelet.tenantadmin.upms.model.constant.SysMenuType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 租户菜单资源Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户菜单资源Dto对象")
@Data
public class SysTenantMenuDto {
/**
* 租户菜单Id
*/
@Schema(description = "租户菜单Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户菜单Id不能为空!", groups = {UpdateGroup.class})
private Long menuId;
/**
* 菜单显示名称
*/
@Schema(description = "菜单显示名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "菜单显示名称不能为空!")
private String menuName;
/**
* 菜单类型(0: 目录 1: 菜单 2: 按钮 3: UI片段)
*/
@Schema(description = "菜单类型(0: 目录 1: 菜单 2: 按钮 3: UI片段)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "菜单类型不能为空!")
@ConstDictRef(constDictClass = SysMenuType.class, message = "数据验证失败,菜单类型为无效值!")
private Integer menuType;
/**
* 父菜单Id目录菜单的父菜单为null
*/
@Schema(description = "父菜单Id,目录菜单的父菜单为null")
private Long parentId;
/**
* 前端表单路由名称仅用于menu_type为1的菜单类型
*/
@Schema(description = "前端表单路由名称,仅用于menu_type为1的菜单类型")
private String formRouterName;
/**
* 统计页面主键Id仅用于统计页面绑定的菜单
*/
@Schema(description = "统计页面主键Id")
private Long reportPageId;
/**
* 在线表单主键Id仅用于在线表单绑定的菜单
*/
@Schema(description = "在线表单主键Id")
private Long onlineFormId;
/**
* 菜单显示顺序 (值越小排序越靠前)
*/
@Schema(description = "菜单显示顺序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "菜单显示顺序不能为空!")
private Integer showOrder;
/**
* 菜单图标
*/
@Schema(description = "菜单图标")
private String icon;
/**
* 附加信息
*/
@Schema(description = "附加信息")
private String extraData;
}

63
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantPermCodeDto.java

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
package apelet.tenantadmin.tenant.dto;
import apelet.common.core.validator.ConstDictRef;
import apelet.common.core.validator.UpdateGroup;
import apelet.tenantadmin.upms.model.constant.SysPermCodeType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 租户权限字Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户权限字Dto对象")
@Data
public class SysTenantPermCodeDto {
/**
* 租户权限字Id
*/
@Schema(description = "租户权限字Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户权限字Id不能为空!", groups = {UpdateGroup.class})
private Long permCodeId;
/**
* 上级权限字Id
*/
@Schema(description = "租户权限模块Id")
private Long parentId;
/**
* 租户权限字标识(一般为有含义的英文字符串)
*/
@Schema(description = "租户权限字标识(一般为有含义的英文字符串)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户权限字编码不能为空!")
private String permCode;
/**
* 租户权限类型(0: 表单 1: UI片段 2: 操作)
*/
@Schema(description = "租户权限类型(0: 表单 1: UI片段 2: 操作)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户权限字类型不能为空!")
@ConstDictRef(constDictClass = SysPermCodeType.class, message = "数据验证失败,权限类型为无效值!")
private Integer permCodeType;
/**
* 租户权限字显示顺序(数值越小越靠前)
*/
@Schema(description = "租户权限字显示顺序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户权限字显示顺序不能为空!")
private Integer showOrder;
/**
* 租户权限字显示名称
*/
@Schema(description = "租户权限字显示名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户权限字显示名称不能为空!")
private String showName;
}

54
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantPermDto.java

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
package apelet.tenantadmin.tenant.dto;
import apelet.common.core.validator.UpdateGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 租户权限资源Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户权限资源Dto对象")
@Data
public class SysTenantPermDto {
/**
* 租户权限资源Id
*/
@Schema(description = "租户权限模块Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户权限Id不能为空!", groups = {UpdateGroup.class})
private Long permId;
/**
* 租户权限所在的权限模块Id
*/
@Schema(description = "租户权限所在的权限模块Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户权限模块Id不能为空!")
private Long moduleId;
/**
* 租户权限名称
*/
@Schema(description = "租户权限名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户权限名称不能为空!")
private String permName;
/**
* 租户权限关联的URL
*/
@Schema(description = "租户权限关联的URL", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户权限关联的url不能为空!")
private String url;
/**
* 权限在当前模块下的顺序由小到大
*/
@Schema(description = "权限在当前模块下的顺序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "权限显示顺序不能为空!")
private Integer showOrder;
}

56
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantPermModuleDto.java

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
package apelet.tenantadmin.tenant.dto;
import apelet.common.core.validator.ConstDictRef;
import apelet.common.core.validator.UpdateGroup;
import apelet.tenantadmin.upms.model.constant.SysPermModuleType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 租户权限模块Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户权限模块Dto对象")
@Data
public class SysTenantPermModuleDto {
/**
* 租户权限模块Id
*/
@Schema(description = "租户权限模块Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户权限模块Id不能为空!", groups = {UpdateGroup.class})
private Long moduleId;
/**
* 上级权限模块Id
*/
@Schema(description = "上级权限模块Id")
private Long parentId;
/**
* 租户权限模块名称
*/
@Schema(description = "租户权限模块名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户权限模块名称不能为空!")
private String moduleName;
/**
* 租户权限模块类型(0: 普通模块 1: Controller模块)
*/
@Schema(description = "租户权限模块类型(0: 普通模块 1: Controller模块)", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "模块类型不能为空!")
@ConstDictRef(constDictClass = SysPermModuleType.class, message = "数据验证失败,租户权限模块类型为无效值!")
private Integer moduleType;
/**
* 权限模块在当前层级下的顺序由小到大
*/
@Schema(description = "权限模块在当前层级下的顺序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "权限模块显示顺序不能为空!")
private Integer showOrder;
}

33
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantRoleDto.java

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
package apelet.tenantadmin.tenant.dto;
import apelet.common.core.validator.UpdateGroup;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
/**
* 租户角色Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户角色Dto对象")
@Data
public class SysTenantRoleDto {
/**
* 租户角色Id
*/
@Schema(description = "租户角色Id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "租户角色Id不能为空!", groups = {UpdateGroup.class})
private Long tenantRoleId;
/**
* 租户角色名称
*/
@Schema(description = "租户角色名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "租户角色名称不能为空!")
private String roleName;
}

27
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantRoleMenuDto.java

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
package apelet.tenantadmin.tenant.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 租户角色和租户菜单多对多关联Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户角色和租户菜单多对多关联Dto对象")
@Data
public class SysTenantRoleMenuDto {
/**
* 租户角色Id
*/
@Schema(description = "租户角色Id", requiredMode = Schema.RequiredMode.REQUIRED)
private Long tenantRoleId;
/**
* 租户菜单Id
*/
@Schema(description = "租户菜单Id", requiredMode = Schema.RequiredMode.REQUIRED)
private Long menuId;
}

27
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/dto/SysTenantRoleTenantDto.java

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
package apelet.tenantadmin.tenant.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* 租户角色与租户多对多关联Dto对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户角色与租户多对多关联Dto对象")
@Data
public class SysTenantRoleTenantDto {
/**
* 租户角色Id
*/
@Schema(description = "租户角色Id", requiredMode = Schema.RequiredMode.REQUIRED)
private Long tenantRoleId;
/**
* 租户Id
*/
@Schema(description = "租户Id", requiredMode = Schema.RequiredMode.REQUIRED)
private Long tenantId;
}

101
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/DeployPlugin.java

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.base.mapper.BaseModelMapper;
import apelet.common.core.base.model.BaseModel;
import apelet.tenantadmin.tenant.vo.DeployPluginVo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.io.Serializable;
import java.util.Date;
/**
* <p>
* 自定义模板
* 热部署插件表
* </p>
*
* @author admin
* @since 2024-06-27 14:58:01
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("deploy_plugin")
public class DeployPlugin extends BaseModel implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id")
private Long id;
@TableField(value = "deleted_flag")
private Integer deletedFlag;
@TableField(value = "number")
private String number;
@TableField(value = "name")
private String name;
//运维工单号
@TableField(value = "work_number")
private String workNumber;
//任务类型
@TableField(value = "task_type")
private String taskType;
//数据中心
@TableField(value = "data_center")
private String dataCenter;
//上传文件地址
@TableField(value = "files")
private String files;
//附件下载地址
@TableField(value = "files_list")
private String fileList;
private String filename;
//状态
@TableField(value = "status")
private Integer status;
//提交时间
@TableField(value = "submit_time")
private Date submitTime;
//处理时间
@TableField(value = "handle_time")
private Date handleTime;
//部署说明
@TableField(value = "deploy_explain")
private String deployExplain;
//提单人
@TableField(value = "delivery_user")
private String deliveryUser;
//处理人
@TableField(value = "handle_user")
private String handleUser;
//异常信息
@TableField(value = "abnormal")
private String abnormal;
@Mapper
public interface DeployPluginModelMapper extends BaseModelMapper<DeployPluginVo, DeployPlugin> {
}
public static final DeployPluginModelMapper INSTANCE = Mappers.getMapper(DeployPluginModelMapper.class);
}

89
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenant.java

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.annotation.RelationDict;
import apelet.common.core.base.mapper.BaseModelMapper;
import apelet.common.core.base.model.BaseModel;
import apelet.tenantadmin.tenant.vo.SysTenantVo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.Map;
/**
* 租户实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "xy_sys_tenant")
public class SysTenant extends BaseModel {
/**
* 租户Id
*/
@TableId(value = "tenant_id")
private Long tenantId;
/**
* 租户的英文编码
*/
@TableField(value = "tenant_code")
private String tenantCode;
/**
* 租户的中文显示名称
*/
@TableField(value = "show_name")
private String showName;
/**
* 租户所在数据源的类型值
*/
@TableField(value = "datasource_type")
private Integer datasourceType;
/**
* 是否可用标记
*/
private Boolean available;
/**
* 逻辑删除标记字段(1: 正常 -1: 已删除)
*/
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
/**
* [创建时间] 范围过滤起始值(>=)
*/
@TableField(exist = false)
private String createTimeStart;
/**
* [创建时间] 范围过滤结束值(<=)
*/
@TableField(exist = false)
private String createTimeEnd;
/**
* 租户数据源字典关联数据
*/
@RelationDict(
masterIdField = "datasourceType",
slaveModelClass = SysTenantDatasource.class,
slaveIdField = "datasourceType",
slaveNameField = "datasourceName")
@TableField(exist = false)
private Map<String, Object> datasourceTypeDictMap;
@Mapper
public interface SysTenantModelMapper extends BaseModelMapper<SysTenantVo, SysTenant> {
}
public static final SysTenantModelMapper INSTANCE = Mappers.getMapper(SysTenantModelMapper.class);
}

74
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantDatasource.java

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.base.model.BaseModel;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 租户数据源实体对象
*
* @author guifc
* @date 2023-08-04
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName(value = "xy_sys_tenant_datasource")
public class SysTenantDatasource extends BaseModel {
/**
* 租户数据源Id
*/
@TableId(value = "datasource_id")
private Long datasourceId;
/**
* 租户数据源名
*/
@TableField(value = "datasource_name")
private String datasourceName;
/**
* 租户所在数据源的类型值
*/
@TableField(value = "datasource_type")
private Integer datasourceType;
/**
* 主机名
*/
@TableField(value = "database_host")
private String databaseHost;
/**
* 端口号
*/
@TableField(value = "port")
private Integer port;
/**
* 用户名
*/
@TableField(value = "username")
private String username;
/**
* 密码
*/
@TableField(value = "password")
private String password;
/**
* 模式名
*/
@TableField(value = "schema_name")
private String schemaName;
/**
* 数据库名
*/
@TableField(value = "database_name")
private String databaseName;
}

30
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantExt.java

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
package apelet.tenantadmin.tenant.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 租户扩展信息的实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@TableName(value = "xy_sys_tenant_ext")
public class SysTenantExt {
/**
* 租户Id
*/
@TableId(value = "tenant_id")
private Long tenantId;
/**
* 租户的在线表单页面Id
* 为了保证每个租户的在线表单页面Id的唯一性和永久一致性这里会保存一份
*/
@TableField(value = "tenant_online_page_ids")
private String tenantOnlinePageIds;
}

127
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantMenu.java

@ -0,0 +1,127 @@ @@ -0,0 +1,127 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.annotation.RelationManyToMany;
import apelet.common.core.base.mapper.BaseModelMapper;
import apelet.common.core.base.model.BaseModel;
import apelet.tenantadmin.tenant.vo.SysTenantMenuVo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 租户菜单资源实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "xy_sys_tenant_menu")
public class SysTenantMenu extends BaseModel {
/**
* 租户菜单Id
*/
@TableId(value = "menu_id")
private Long menuId;
/**
* 菜单显示名称
*/
@TableField(value = "menu_name")
private String menuName;
/**
* 菜单类型(0: 目录 1: 菜单 2: 按钮 3: UI片段)
*/
@TableField(value = "menu_type")
private Integer menuType;
/**
* 父菜单Id目录菜单的父菜单为null
*/
@TableField(value = "parent_id")
private Long parentId;
/**
* 前端表单路由名称仅用于menu_type为1的菜单类型
*/
@TableField(value = "form_router_name")
private String formRouterName;
/**
* 统计页面主键Id仅用于统计页面绑定的菜单
*/
@TableField(value = "report_page_id")
private Long reportPageId;
/**
* 在线表单主键Id仅用于在线表单绑定的菜单
*/
@TableField(value = "online_form_id")
private Long onlineFormId;
/**
* 在线表单菜单的权限控制类型具体值可参考SysOnlineMenuPermType常量对象
*/
@TableField(value = "online_menu_perm_type")
private Integer onlineMenuPermType;
/**
* 菜单显示顺序 (值越小排序越靠前)
*/
@TableField(value = "show_order")
private Integer showOrder;
/**
* 菜单图标
*/
private String icon;
/**
* 附加信息
*/
@TableField(value = "extra_data")
private String extraData;
/**
* 逻辑删除标记字段(1: 正常 -1: 已删除)
*/
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
@RelationManyToMany(
relationMasterIdField = "menuId",
relationModelClass = SysTenantMenuPermCode.class)
@TableField(exist = false)
private List<SysTenantMenuPermCode> sysMenuPermCodeList;
@Mapper
public interface SysTenantMenuModelMapper extends BaseModelMapper<SysTenantMenuVo, SysTenantMenu> {
/**
* 转换VO对象到实体对象
*
* @param sysMenuVo 域对象
* @return 实体对象
*/
@Mapping(target = "sysMenuPermCodeList", expression = "java(mapToBean(sysMenuVo.getSysMenuPermCodeList(), apelet.tenantadmin.tenant.model.SysTenantMenuPermCode.class))")
@Override
SysTenantMenu toModel(SysTenantMenuVo sysMenuVo);
/**
* 转换实体对象到VO对象
*
* @param sysMenu 实体对象
* @return 域对象
*/
@Mapping(target = "sysMenuPermCodeList", expression = "java(beanToMap(sysMenu.getSysMenuPermCodeList(), false))")
@Override
SysTenantMenuVo fromModel(SysTenantMenu sysMenu);
}
public static final SysTenantMenuModelMapper INSTANCE = Mappers.getMapper(SysTenantMenuModelMapper.class);
}

28
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantMenuPermCode.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package apelet.tenantadmin.tenant.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 租户菜单与租户权限字关联实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@TableName(value = "xy_sys_tenant_menu_perm_code")
public class SysTenantMenuPermCode {
/**
* 关联租户菜单Id
*/
@TableField(value = "menu_id")
private Long menuId;
/**
* 关联租户权限字Id
*/
@TableField(value = "perm_code_id")
private Long permCodeId;
}

66
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPerm.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.annotation.RelationDict;
import apelet.common.core.base.model.BaseModel;
import apelet.tenantadmin.upms.model.SysPermModule;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Map;
/**
* 租户权限资源实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "xy_sys_tenant_perm")
public class SysTenantPerm extends BaseModel {
/**
* 租户权限资源Id
*/
@TableId(value = "perm_id")
private Long permId;
/**
* 租户权限所在的权限模块Id
*/
@TableField(value = "module_id")
private Long moduleId;
/**
* 租户权限名称
*/
@TableField(value = "perm_name")
private String permName;
/**
* 权限在当前模块下的顺序由小到大
*/
@TableField(value = "show_order")
private Integer showOrder;
/**
* 租户权限关联的URL
*/
private String url;
/**
* 逻辑删除标记字段(1: 正常 -1: 已删除)
*/
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
@RelationDict(
masterIdField = "moduleId",
slaveModelClass = SysPermModule.class,
slaveIdField = "moduleId",
slaveNameField = "moduleName")
@TableField(exist = false)
private Map<String, Object> moduleIdDictMap;
}

98
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPermCode.java

@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.annotation.RelationManyToMany;
import apelet.common.core.base.mapper.BaseModelMapper;
import apelet.common.core.base.model.BaseModel;
import apelet.tenantadmin.tenant.vo.SysTenantPermCodeVo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 租户权限字实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "xy_sys_tenant_perm_code")
public class SysTenantPermCode extends BaseModel {
/**
* 租户权限字Id
*/
@TableId(value = "perm_code_id")
private Long permCodeId;
/**
* 租户权限字标识(一般为有含义的英文字符串)
*/
@TableField(value = "perm_code")
private String permCode;
/**
* 租户权限类型(0: 表单 1: UI片段 2: 操作)
*/
@TableField(value = "perm_code_type")
private Integer permCodeType;
/**
* 上级权限字Id
*/
@TableField(value = "parent_id")
private Long parentId;
/**
* 租户权限字显示顺序(数值越小越靠前)
*/
@TableField(value = "show_order")
private Integer showOrder;
/**
* 租户权限字显示名称
*/
@TableField(value = "show_name")
private String showName;
/**
* 逻辑删除标记字段(1: 正常 -1: 已删除)
*/
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
@RelationManyToMany(
relationMasterIdField = "permCodeId",
relationModelClass = SysTenantPermCodePerm.class)
@TableField(exist = false)
private List<SysTenantPermCodePerm> sysPermCodePermList;
@Mapper
public interface SysTenantPermCodeModelMapper extends BaseModelMapper<SysTenantPermCodeVo, SysTenantPermCode> {
/**
* 转换VO对象到实体对象
*
* @param sysPermCodeVo 域对象
* @return 实体对象
*/
@Mapping(target = "sysPermCodePermList", expression = "java(mapToBean(sysPermCodeVo.getSysPermCodePermList(), apelet.tenantadmin.tenant.model.SysTenantPermCodePerm.class))")
@Override
SysTenantPermCode toModel(SysTenantPermCodeVo sysPermCodeVo);
/**
* 转换实体对象到VO对象
*
* @param sysPermCode 实体对象
* @return 域对象
*/
@Mapping(target = "sysPermCodePermList", expression = "java(beanToMap(sysPermCode.getSysPermCodePermList(), false))")
@Override
SysTenantPermCodeVo fromModel(SysTenantPermCode sysPermCode);
}
public static final SysTenantPermCodeModelMapper INSTANCE = Mappers.getMapper(SysTenantPermCodeModelMapper.class);
}

28
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPermCodePerm.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package apelet.tenantadmin.tenant.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 权限字与权限资源关联实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@TableName(value = "xy_sys_tenant_perm_code_perm")
public class SysTenantPermCodePerm {
/**
* 权限字Id
*/
@TableField(value = "perm_code_id")
private Long permCodeId;
/**
* 权限Id
*/
@TableField(value = "perm_id")
private Long permId;
}

60
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantPermModule.java

@ -0,0 +1,60 @@ @@ -0,0 +1,60 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.base.model.BaseModel;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
/**
* 租户权限模块实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "xy_sys_tenant_perm_module")
public class SysTenantPermModule extends BaseModel {
/**
* 租户权限模块Id
*/
@TableId(value = "module_id")
private Long moduleId;
/**
* 租户权限模块名称
*/
@TableField(value = "module_name")
private String moduleName;
/**
* 上级权限模块Id
*/
@TableField(value = "parent_id")
private Long parentId;
/**
* 租户权限模块类型(0: 普通模块 1: Controller模块)
*/
@TableField(value = "module_type")
private Integer moduleType;
/**
* 权限模块在当前层级下的顺序由小到大
*/
@TableField(value = "show_order")
private Integer showOrder;
/**
* 逻辑删除标记字段(1: 正常 -1: 已删除)
*/
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
@TableField(exist = false)
private List<SysTenantPerm> sysPermList;
}

46
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRole.java

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
package apelet.tenantadmin.tenant.model;
import apelet.common.core.base.mapper.BaseModelMapper;
import apelet.common.core.base.model.BaseModel;
import apelet.tenantadmin.tenant.vo.SysTenantRoleVo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
/**
* 租户角色实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@EqualsAndHashCode(callSuper = true)
@TableName(value = "xy_sys_tenant_role")
public class SysTenantRole extends BaseModel {
/**
* 租户角色Id
*/
@TableId(value = "tenant_role_id")
private Long tenantRoleId;
/**
* 租户角色名称
*/
@TableField(value = "role_name")
private String roleName;
/**
* 逻辑删除标记字段(1: 正常 -1: 已删除)
*/
@TableLogic
@TableField(value = "deleted_flag")
private Integer deletedFlag;
@Mapper
public interface SysTenantRoleModelMapper extends BaseModelMapper<SysTenantRoleVo, SysTenantRole> {
}
public static final SysTenantRoleModelMapper INSTANCE = Mappers.getMapper(SysTenantRoleModelMapper.class);
}

28
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleMenu.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package apelet.tenantadmin.tenant.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 租户角色与菜单多对多关联实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@TableName(value = "xy_sys_tenant_role_menu")
public class SysTenantRoleMenu {
/**
* 租户角色Id
*/
@TableField(value = "tenant_role_id")
private Long tenantRoleId;
/**
* 租户菜单Id
*/
@TableField(value = "menu_id")
private Long menuId;
}

28
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleOnlinePage.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package apelet.tenantadmin.tenant.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 租户角色与在线表单页面多对多关联实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@TableName(value = "xy_sys_tenant_role_online_page")
public class SysTenantRoleOnlinePage {
/**
* 租户角色Id
*/
@TableField(value = "tenant_role_id")
private Long tenantRoleId;
/**
* 在线表单页面Id
*/
@TableField(value = "page_id")
private Long pageId;
}

28
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleReportDataset.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package apelet.tenantadmin.tenant.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 租户角色与报表数据集多对多关联实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@TableName(value = "xy_sys_tenant_role_report_ds")
public class SysTenantRoleReportDataset {
/**
* 租户角色Id
*/
@TableField(value = "tenant_role_id")
private Long tenantRoleId;
/**
* 报表数据集Id
*/
@TableField(value = "dataset_id")
private Long datasetId;
}

28
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/model/SysTenantRoleTenant.java

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
package apelet.tenantadmin.tenant.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
/**
* 租户角色与租户多对多关联实体对象
*
* @author guifc
* @date 2023-08-04
*/
@Data
@TableName(value = "xy_sys_tenant_role_tenant")
public class SysTenantRoleTenant {
/**
* 权限字Id
*/
@TableField(value = "tenant_role_id")
private Long tenantRoleId;
/**
* 租户Id
*/
@TableField(value = "tenant_id")
private Long tenantId;
}

13
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/plugin/Plugin.java

@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
package apelet.tenantadmin.tenant.plugin;
import java.util.Map;
/**
* @author: HF
* @description: TODO
* @date: 2024/5/27 18:43
*/
public interface Plugin {
Map<String, Object> process(Map<String, Object> params);
}

200
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/plugin/PluginService.java

@ -0,0 +1,200 @@ @@ -0,0 +1,200 @@
package apelet.tenantadmin.tenant.plugin;
import apelet.common.core.exception.MyRuntimeException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.*;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* 热部署插件服务
*/
@Service
public class PluginService {
private URLClassLoader urlClassLoader;
private final Map<String, String> packageNameMap = new HashMap<>();
public List<String> reloadPlugin(String jarPath) {
List<String> pluginList = new ArrayList<>();
// 1. 创建一个File对象,指向外部jar包的路径
File externalJar = new File(jarPath);
try {
JarFile jar = new JarFile(externalJar);
Enumeration<JarEntry> entries = jar.entries();
String s = "jar:file:" + externalJar.getAbsolutePath() + "!/";
URL[] urls = {new URL(s)};
urlClassLoader = URLClassLoader.newInstance(urls);
while (entries.hasMoreElements()) {
JarEntry je = entries.nextElement();
if (je.isDirectory() || !je.getName().endsWith(".class")) {
continue;
}
String className = je.getName().substring(0, je.getName().length() - 6);
className = className.replace('/', '.');
Class<?> c = urlClassLoader.loadClass(className);
if (implementsPlugin(c, Plugin.class)) {
List<String> list = Arrays.asList(c.getName().split("\\."));
packageNameMap.put(list.get(list.size() - 1), c.getName());
pluginList.add(c.getName());
}
// 在这里你可以使用反射来调用类的方法,例如:
// Method method = c.getMethod("methodName", parameterTypes);
// Object result = method.invoke(null, arguments);
}
jar.close();
} catch (Exception e) {
e.printStackTrace();
throw new MyRuntimeException(e.getMessage());
}
return pluginList;
}
//根据指定plug名称,在缓存中查找插件class,并反射执行
public Object process(String pluginName, Map<String, Object> params) {
try {
Class<?> clazz = urlClassLoader.loadClass(packageNameMap.get(pluginName));
Object o = clazz.newInstance();
Method method = clazz.getMethod("process", Map.class);
return method.invoke(o, params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public boolean implementsPlugin(Class c, Class pluginClass) {
boolean implementsPlugin = false;
for (Class<?> iface : c.getInterfaces()) {
if (iface.getName().equals(pluginClass.getName())) {
implementsPlugin = true;
break;
}
}
return implementsPlugin;
}
public List<String> reloadPlugin(String rootPath, String packageName) {
List<String> result = new ArrayList<>();
try {
URL[] urls = new URL[]{new URL("file:" + rootPath)};
URLClassLoader urlClassLoader = new URLClassLoader(urls);
String plugDirPath = rootPath + StringUtils.replace(packageName, ".", "\\");
File plugDir = new File(plugDirPath);
List<File> classFiles = getClassFiles(plugDir);
for (File classFile : classFiles) {
String path = classFile.getPath();
path = path.substring(0, path.length() - 6);
String s = "apelet" + path.split("apelet")[1];
s = s.replace('\\', '.');
Class<?> pluginClass = urlClassLoader.loadClass(s);
if (implementsPlugin(pluginClass, Plugin.class)) {
result.add(pluginClass.getSimpleName());
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static List<File> getClassFiles(File directory) {
List<File> classFiles = new ArrayList<>();
if (directory.isDirectory()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
classFiles.addAll(getClassFiles(file));
} else if (file.getName().endsWith(".class")) {
classFiles.add(file);
}
}
}
}
return classFiles;
}
/*public static void main(String[] args) {
// 生成密钥
SecretKey secretKey = null;
try {
secretKey = generateKey();
// 加密文件并保存到指定位置
encryptFile("D:\\Temp\\xxl-job-admin.jar", "D:\\Temp\\xxl-job-admin-jiami.jar", secretKey);
// 解密文件并保存到指定位置
decryptFile("D:\\Temp\\xxl-job-admin-jiami.jar", "D:\\Temp\\xxl-job-admin-2.jar", secretKey);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (Exception e) {
throw new RuntimeException(e);
}
}*/
public SecretKey generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
return keyGenerator.generateKey();
}
// 加密文件
public void encryptFile(String inputFile, String outputFile, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
try (InputStream inputStream = new FileInputStream(inputFile);
OutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] outputBuffer = cipher.update(buffer, 0, bytesRead);
if (outputBuffer != null) {
outputStream.write(outputBuffer);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
}
}
public void decryptFile(String inputFile, String outputFile, SecretKey secretKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
try (InputStream inputStream = new FileInputStream(inputFile);
OutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[64];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
byte[] outputBuffer = cipher.update(buffer, 0, bytesRead);
if (outputBuffer != null) {
outputStream.write(outputBuffer);
}
}
byte[] outputBytes = cipher.doFinal();
if (outputBytes != null) {
outputStream.write(outputBytes);
}
}
}
}

33
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/quartz/job/MySyncEasFlowQuartzJob.java

@ -0,0 +1,33 @@ @@ -0,0 +1,33 @@
package apelet.tenantadmin.tenant.quartz.job;
import apelet.common.eas.service.IEasFlowService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Configuration
@EnableScheduling
@Slf4j
public class MySyncEasFlowQuartzJob implements Job{
@Autowired
private IEasFlowService easFlowService;
@Override
public void execute(JobExecutionContext context) {
easFlowService.syncEasFlow("");
}
// @Scheduled(cron = "0 0/20 6-22 * * ?")
public void sync(){
log.warn("==========================================");
log.warn("===============开始同步eas流程===============");
log.warn("==========================================");
easFlowService.syncEasFlow("");
}
}

34
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/quartz/job/MySyncEasUserQuartzJob.java

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
package apelet.tenantadmin.tenant.quartz.job;
import apelet.tenantadmin.upms.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@EnableScheduling
public class MySyncEasUserQuartzJob implements Job{
@Autowired
private SysUserService sysUserService;
@Override
public void execute(JobExecutionContext context) {
sysUserService.syncEasUSer();
}
// @Scheduled(cron = "0 0/10 6-22 * * ?")
public void sync(){
log.warn("==========================================");
log.warn("===============开始同步eas用户==============");
log.warn("==========================================");
sysUserService.syncEasUSer();
}
}

46
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/IDeployPluginService.java

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.tenantadmin.tenant.model.DeployPlugin;
import java.util.List;
import java.util.Map;
/**
* <p>
* 热部署插件表 服务类
* </p>
*
* @author admin
* @since 2024-06-27 14:58:01
*/
public interface IDeployPluginService extends IBaseService<DeployPlugin, Long> {
/**
* 分页 获取插件
* @param deployPlugin
* @param s
* @return
*/
List<DeployPlugin> getDeployPluginList(DeployPlugin deployPlugin, String s);
/**
* 加载插件
*
* @param id
* @return
*/
List<String> reloadPlugin(List<Long> id);
/**
* 执行插件
*
* @param pluginName 插件全包名 ( apelet.tenantadmin.tenant.plugin.MyTestPlugin)
* @param map 插件方法参数
* @return
*/
Object executePlugin(String pluginName, Map<String, Object> map);
}

40
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantDatasourceService.java

@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.tenantadmin.tenant.model.SysTenantDatasource;
import java.util.List;
/**
* 租户权限资源数据服务类
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantDatasourceService extends IBaseService<SysTenantDatasource, Long> {
/**
* 新增的租户数据源
*
* @param datasource 新增的租户数据源实体对象
* @return 新增的租户数据源对象
*/
SysTenantDatasource saveNew(SysTenantDatasource datasource);
/**
* 更新租户数据源
*
* @param datasource 更新的租户数据源对象
* @param originalDatasource 原有的租户数据源对象
* @return 更新数据操作和同步发送消息的结果
*/
boolean update(SysTenantDatasource datasource, SysTenantDatasource originalDatasource);
/**
* 获取租户数据源列表
*
* @param filter 过滤对象
* @return 租户数据源列表
*/
List<SysTenantDatasource> getSysTenantDatasourceList(SysTenantDatasource filter);
}

82
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantMenuService.java

@ -0,0 +1,82 @@ @@ -0,0 +1,82 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.common.core.object.CallResult;
import apelet.tenantadmin.tenant.model.SysTenantMenu;
import java.util.*;
/**
* 租户菜单数据服务类
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantMenuService extends IBaseService<SysTenantMenu, Long> {
/**
* 填充租户菜单实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param sysMenu 新增的租户菜单对象
* @param permCodeIdSet 租户权限字Id列表
* @return 新增数据操作和同步发送消息的结果
*/
SysTenantMenu saveNew(SysTenantMenu sysMenu, Set<Long> permCodeIdSet);
/**
* 填充租户菜单实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysMenu 更新的租户菜单对象
* @param originalSysMenu 原有的租户菜单对象
* @param permCodeIdSet 租户权限字Id列表
* @return 更新数据操作和同步发送消息的结果
*/
boolean update(SysTenantMenu sysMenu, SysTenantMenu originalSysMenu, Set<Long> permCodeIdSet);
/**
* 填充租户菜单实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param menuId 租户菜单主键Id
* @return 删除数据操作和同步发送消息的结果
*/
boolean remove(Long menuId);
/**
* 根据租户角色Id获取关联的租户菜单从表中没有和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param orderBy 排序字符串order by从句的参数
* @return 与主表没有建立关联的租户菜单数据列表
*/
List<SysTenantMenu> getNotInSysTenantMenuListByRoleId(Long tenantRoleId, String orderBy);
/**
* 根据租户角色Id获取关联的租户菜单从表中和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param orderBy 排序字符串order by从句的参数
* @return 与主表建立关联的租户菜单数据列表
*/
List<SysTenantMenu> getSysTenantMenuListByRoleId(Long tenantRoleId, String orderBy);
/**
* 判断当前租户菜单是否存在子菜单
*
* @param menuId 租户菜单主键Id
* @return 存在返回true否则false
*/
boolean hasChildren(Long menuId);
/**
* 验证租户菜单对象关联的数据是否都合法
*
* @param sysMenu 当前操作的对象
* @param originalSysMenu 原有对象
* @param permCodeIdListString 逗号分隔的权限Id列表
* @return 验证结果
*/
CallResult verifyRelatedData(SysTenantMenu sysMenu, SysTenantMenu originalSysMenu, String permCodeIdListString);
}

65
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantPermCodeService.java

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.common.core.object.CallResult;
import apelet.tenantadmin.tenant.model.SysTenantPermCode;
import java.util.*;
/**
* 租户权限字数据服务类
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantPermCodeService extends IBaseService<SysTenantPermCode, Long> {
/**
* 填充租户权限字实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param permCode 新增的租户权限字实体对象
* @param permIdSet 租户权限资源Id列表
* @return 新增数据操作和同步发送消息的结果
*/
SysTenantPermCode saveNew(SysTenantPermCode permCode, Set<Long> permIdSet);
/**
* 填充租户权限字实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysPermCode 更新的租户权限字对象
* @param originalSysPermCode 原有的租户权限字对象
* @param permIdSet 租户权限资源Id列表
* @return 更新数据操作和同步发送消息的结果
*/
boolean update(SysTenantPermCode sysPermCode, SysTenantPermCode originalSysPermCode, Set<Long> permIdSet);
/**
* 填充租户权限字实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param permCodeId 租户权限字主键Id
* @return 删除数据操作和同步发送消息的结果
*/
boolean remove(Long permCodeId);
/**
* 判断当前租户权限字是否存在下级权限字对象
*
* @param permCodeId 租户权限字主键Id
* @return 存在返回true否则false
*/
boolean hasChildren(Long permCodeId);
/**
* 验证租户权限字对象关联的数据是否都合法
*
* @param sysPermCode 当前操作的对象
* @param originalSysPermCode 原有对象
* @param permIdListString 逗号分隔的权限资源Id列表
* @return 验证结果
*/
CallResult verifyRelatedData(
SysTenantPermCode sysPermCode, SysTenantPermCode originalSysPermCode, String permIdListString);
}

66
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantPermModuleService.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.tenantadmin.tenant.model.SysTenantPermModule;
import java.util.List;
/**
* 租户权限资源模块数据服务类
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantPermModuleService extends IBaseService<SysTenantPermModule, Long> {
/**
* 填充租户权限资源模块实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param sysPermModule 新增的租户权限资源模块实体对象
* @return 新增数据操作和同步发送消息的结果
*/
SysTenantPermModule saveNew(SysTenantPermModule sysPermModule);
/**
* 填充租户权限资源模块实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysPermModule 更新的租户权限资源模块对象
* @param originalSysPermModule 原有的租户权限资源模块对象
* @return 更新数据操作和同步发送消息的结果
*/
boolean update(SysTenantPermModule sysPermModule, SysTenantPermModule originalSysPermModule);
/**
* 填充租户权限资源模块实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param moduleId 待删除的租户权限资源模块主键Id
* @return 删除数据操作和同步发送消息的结果
*/
boolean remove(Long moduleId);
/**
* 获取权限模块资源及其关联的权限资源列表
*
* @return 权限资源模块及其关联的权限资源列表
*/
List<SysTenantPermModule> getPermModuleAndPermList();
/**
* 判断是否存在下级租户权限资源模块
*
* @param moduleId 租户权限资源模块主键Id
* @return 存在返回true否则false
*/
boolean hasChildren(Long moduleId);
/**
* 判断是否存在租户权限数据
*
* @param moduleId 租户权限资源模块主键Id
* @return 存在返回true否则false
*/
boolean hasModulePerms(Long moduleId);
}

51
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantPermService.java

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.tenantadmin.tenant.model.SysTenantPerm;
import java.util.List;
/**
* 租户权限资源数据服务类
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantPermService extends IBaseService<SysTenantPerm, Long> {
/**
* 填充租户权限资源实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param perm 新增的租户权限资源实体对象
* @return 新增数据操作和同步发送消息的结果
*/
SysTenantPerm saveNew(SysTenantPerm perm);
/**
* 填充租户权限资源实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param perm 更新的租户权限资源对象
* @param originalPerm 原有的租户权限资源对象
* @return 更新数据操作和同步发送消息的结果
*/
boolean update(SysTenantPerm perm, SysTenantPerm originalPerm);
/**
* 填充租户权限资源实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param permId 待删除的租户权限资源主键Id
* @return 删除数据操作和同步发送消息的结果
*/
boolean remove(Long permId);
/**
* 获取租户权限数据列表
*
* @param sysPermFilter 过滤对象
* @return 权限列表
*/
List<SysTenantPerm> getPermListWithRelation(SysTenantPerm sysPermFilter);
}

179
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantRoleService.java

@ -0,0 +1,179 @@ @@ -0,0 +1,179 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.tenantadmin.tenant.model.*;
import java.util.*;
/**
* 租户角色数据服务类
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantRoleService extends IBaseService<SysTenantRole, Long> {
/**
* 填充租户角色实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param tenantRole 新增的租户角色对象
* @return 新增数据操作和同步发送消息的结果
*/
SysTenantRole saveNew(SysTenantRole tenantRole);
/**
* 更新租户角色对象
*
* @param tenantRole 更新的租户角色对象
* @param originalTenantRole 原有的租户角色对象
* @return 更新成功返回true否则false
*/
boolean update(SysTenantRole tenantRole, SysTenantRole originalTenantRole);
/**
* 删除指定的租户角色及其关联数据
*
* @param tenantRoleId 租户角色主键Id
* @return 删除成功返回true否则false
*/
boolean remove(Long tenantRoleId);
/**
* 获取租户角色列表
*
* @param filter 租户角色过滤对象
* @param orderBy 排序参数
* @return 租户角色列表
*/
List<SysTenantRole> getSysTenantRoleList(SysTenantRole filter, String orderBy);
/**
* 判断指定租户角色下是否包含租户数据
*
* @param tenantRoleId 租户角色主键Id
* @return 包含返回true否则false
*/
boolean hasTenantByRoleId(Long tenantRoleId);
/**
* 添加租户角色和租户之间的多对多关系
*
* @param tenantRoleId 租户角色主键Id
* @param sysTenantRoleTenantList 租户角色和租户的关联对象列表
*/
void addTenantRoleTenantList(Long tenantRoleId, List<SysTenantRoleTenant> sysTenantRoleTenantList);
/**
* 移除租户角色和租户之间的多对多关系
*
* @param tenantRoleId 租户角色Id
* @param tenantId 租户Id
*/
void removeTenantRoleTenant(Long tenantRoleId, Long tenantId);
/**
* 移除租户角色和租户之间的多对多关系
*
* @param tenantRoleId 租户角色Id
* @param tenantId 租户Id
*/
void removeTenantRoleTenantAndSync(Long tenantRoleId, Long tenantId);
/**
* 判断指定租户角色下是否包含租户关联数据
*
* @param tenantRoleId 租户角色主键Id
* @return 包含返回true否则false
*/
boolean hasTenantRelatedDataByTenantRoleId(Long tenantRoleId);
/**
* 添加租户角色和租户菜单之间的多对多关系
*
* @param tenantRoleId 租户角色主键Id
* @param sysTenantRoleMenuList 租户角色和租户菜单的关联对象列表
*/
void addTenantRoleMenuList(Long tenantRoleId, List<SysTenantRoleMenu> sysTenantRoleMenuList);
/**
* 移除租户角色和租户菜单之间的多对多关系
*
* @param tenantRoleId 租户角色Id
* @param tenantMenuId 租户菜单Id
*/
void removeTenantRoleMenu(Long tenantRoleId, Long tenantMenuId);
/**
* 填充租户角色与菜单多对多关联实体对象中的数据并发送消息到RocketMQ同步远程数据
* 移除租户角色和租户菜单之间的多对多关系
*
* @param tenantRoleId 租户角色Id
* @param menuId 租户菜单Id
*/
void removeTenantRoleMenuAndSync(Long tenantRoleId, Long menuId);
/**
* 添加租户角色和报表数据集之间的多对多关系
*
* @param tenantRoleId 租户角色主键Id
* @param datasetIds 报表数据集Id集合
*/
void addTenantRoleReportDatasetList(Long tenantRoleId, Set<Long> datasetIds);
/**
* 移除租户角色和报表数据集之间的多对多关系
*
* @param tenantRoleId 租户角色Id
* @param datasetId 报表数据集Id
*/
void removeTenantRoleReportDataset(Long tenantRoleId, Long datasetId);
/**
* 移除租户角色和报表数据集之间的多对多关系并发送消息到RocketMQ同步远程数据
*
* @param tenantRoleId 租户角色Id
* @param datasetId 报表数据集Id
*/
void removeTenantRoleReportDatasetAndSync(Long tenantRoleId, Long datasetId);
/**
* 获取指定租户角色关联的报表数据集Id集合
*
* @param tenantRoleId 租户角色主键Id
* @return 指定租户角色关联的报表数据集Id集合
*/
List<Long> getSysTenantRoleReportDatasetIdList(Long tenantRoleId);
/**
* 获取指定租户角色关联的在线表单页面Id集合
*
* @param tenantRoleId 租户角色主键Id
* @return 指定租户角色关联的在线表单页面Id集合
*/
List<Long> getSysTenantRoleOnlinePageIdList(Long tenantRoleId);
/**
* 添加租户角色和在线表单页面之间的多对多关系
*
* @param tenantRoleId 租户角色主键Id
* @param pageIds 在线表单页面Id集合
*/
void addTenantRoleOnlinePageList(Long tenantRoleId, Set<Long> pageIds);
/**
* 移除租户角色和在线表单页面之间的多对多关系
*
* @param tenantRoleId 租户角色Id
* @param pageId 在线表单页面Id
*/
void removeTenantRoleOnlinePage(Long tenantRoleId, Long pageId);
/**
* 移除租户角色和线表单页面之间的多对多关系并发送消息到RocketMQ同步远程数据
*
* @param tenantRoleId 租户角色Id
* @param pageId 在线表单页面Id
*/
void removeTenantRoleOnlinePageAndSync(Long tenantRoleId, Long pageId);
}

100
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/SysTenantService.java

@ -0,0 +1,100 @@ @@ -0,0 +1,100 @@
package apelet.tenantadmin.tenant.service;
import apelet.common.core.base.service.IBaseService;
import apelet.tenantadmin.tenant.model.SysTenant;
import java.util.List;
import java.util.Map;
/**
* 租户数据服务类
*
* @author guifc
* @date 2023-08-04
*/
public interface SysTenantService extends IBaseService<SysTenant, Long> {
/**
* 填充租户实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param tenant 新增的租户实体对象
* @return 新增数据操作和同步发送消息的结果
*/
SysTenant saveNew(SysTenant tenant);
/**
* 填充租户实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param tenant 更新的租户对象
* @param originalTenant 原有的租户对象
* @return 更新数据操作和同步发送消息的结果
*/
boolean update(SysTenant tenant, SysTenant originalTenant);
/**
* 填充租户实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param sysTenant 租户实体对象
* @return 删除数据操作和同步发送消息的结果
*/
boolean remove(SysTenant sysTenant);
/**
* 获取租户列表及其关联数据
*
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序参数
* @return 查询结果列表
*/
List<SysTenant> getSysTenantList(SysTenant sysTenantFilter, String orderBy);
/**
* 根据租户角色Id获取关联的租户从表中没有和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序字符串order by从句的参数
* @return 与主表没有建立关联的租户数据列表
*/
List<SysTenant> getNotInSysTenantListByRoleId(Long tenantRoleId, SysTenant sysTenantFilter, String orderBy);
/**
* 根据租户角色Id获取关联的租户从表中和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序字符串order by从句的参数
* @return 与主表建立关联的租户数据列表
*/
List<SysTenant> getSysTenantListByRoleId(Long tenantRoleId, SysTenant sysTenantFilter, String orderBy);
/**
* 查询租户的权限资源地址列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param url url过滤条件
* @return 包含从租户到权限资源的完整权限分配路径信息的查询结果列表
*/
List<Map<String, Object>> getSysTenantPermListWithDetail(Long tenantId, String url);
/**
* 查询租户的权限字列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param permCode 权限字名称过滤条件
* @return 包含从租户到权限字的权限分配路径信息的查询结果列表
*/
List<Map<String, Object>> getSysTenantPermCodeListWithDetail(Long tenantId, String permCode);
/**
* 查询租户的菜单列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param menuName 菜单名称过滤条件
* @return 包含从租户到菜单的权限分配路径信息的查询结果列表
*/
List<Map<String, Object>> getSysTenantMenuListWithDetail(Long tenantId, String menuName);
}

226
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/DeployPluginServiceImpl.java

@ -0,0 +1,226 @@ @@ -0,0 +1,226 @@
package apelet.tenantadmin.tenant.service.impl;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.exception.MyRuntimeException;
import apelet.common.core.object.MyRelationParam;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.plugin.Plugin;
import apelet.tenantadmin.tenant.dao.DeployPluginMapper;
import apelet.tenantadmin.tenant.model.DeployPlugin;
import apelet.tenantadmin.tenant.plugin.PluginService;
import apelet.tenantadmin.tenant.service.IDeployPluginService;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import apelet.common.core.base.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* <p>
* 热部署插件表 服务实现类
* </p>
*
* @author admin
* @since 2024-06-27 14:58:01
*/
@Service
@Slf4j
public class DeployPluginServiceImpl extends BaseService<DeployPlugin, Long> implements IDeployPluginService {
@Autowired
DeployPluginMapper deployPluginMapper;
@Autowired
PluginService pluginService;
@Autowired
private ApplicationConfig appConfig;
@Override
public List<DeployPlugin> getDeployPluginList(DeployPlugin deployPlugin, String orderBy) {
List<DeployPlugin> sysTenantList = deployPluginMapper.getDeployPluginList(deployPlugin, orderBy);
this.buildRelationForDataList(sysTenantList, MyRelationParam.dictOnly());
return sysTenantList;
}
@Override
public List<String> reloadPlugin(List<Long> ids) {
List<String> result = new ArrayList<>();
Set<Long> idList = new HashSet<>(ids);
List<DeployPlugin> deployPluginList = this.getInList(idList);
deployPluginList.forEach(f -> {
try {
InputStream in = new URL(f.getFiles()).openStream();
write(appConfig.getUploadFileBaseDir(), f.getFilename(), in);
List<String> strings = pluginService.reloadPlugin(appConfig.getUploadFileBaseDir() + "\\" + f.getFilename());
result.addAll(strings);
} catch (Exception e) {
throw new MyRuntimeException(e.getMessage());
}
});
ids.forEach(f -> {
DeployPlugin deployPlugin = new DeployPlugin();
deployPlugin.setId(f);
deployPlugin.setStatus(2);
deployPlugin.setHandleTime(new Date());
deployPluginMapper.updateById(deployPlugin);
});
return result;
}
//根据指定plug名称,反射执行
@Override
public Object executePlugin(String pluginName, Map<String, Object> params) {
try {
return pluginService.process(pluginName, params);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
void write(String folderPath, String fileName, InputStream in) {
File outputFolder = new File(folderPath);
if (!outputFolder.exists()) {
outputFolder.mkdirs(); // 如果文件夹不存在,则创建它
}
File outputFile = new File(outputFolder, fileName);
try {
// 创建FileOutputStream对象
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
// 从InputStream中读取数据并写入到FileOutputStream中
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
fileOutputStream.write(buffer, 0, bytesRead);
}
// 关闭输入流和输出流
in.close();
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*public static void main(String[] args) throws Exception {
// 读取ZIP文件中的JAR文件
File zipFile = new File("D:\\work-file\\ttt\\test.zip");
JarInputStream jarInputStream = new JarInputStream(new FileInputStream(zipFile));
JarEntry jarEntry;
while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
if (!jarEntry.isDirectory() && jarEntry.getName().endsWith(".jar")) {
// 加载JAR文件
URL url = new URL("jar", "", "file:" + zipFile.getAbsolutePath() + "/" + jarEntry.getName());
URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
// 扫描JAR文件中的所有类文件
JarInputStream innerJarInputStream = new JarInputStream(new FileInputStream(new File(url.getFile())));
while ((jarEntry = innerJarInputStream.getNextJarEntry()) != null) {
if (jarEntry.getName().endsWith(".class")) {
// 通过反射获取类对象
String className = jarEntry.getName().replace("/", ".").replace(".class", "");
Class<?> clazz = classLoader.loadClass(className);
System.out.println("Loaded class: " + clazz.getName());
}
}
innerJarInputStream.close();
}
}
jarInputStream.close();
}*/
public static void main(String[] args) throws IOException {
try {
// 读取ZIP文件
File zipFile = new File("D:\\tmp\\test.zip");
JarInputStream jarInputStream = new JarInputStream(new FileInputStream(zipFile));
JarEntry jarEntry;
while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
// 检查是否为JAR文件
if (!jarEntry.isDirectory() && jarEntry.getName().endsWith(".jar")) {
// 创建临时目录并将JAR文件解压到该目录
File tempDir = new File("temp");
tempDir.mkdir();
File tempJar = new File(tempDir, jarEntry.getName());
copyStreamToFile(jarInputStream, tempJar);
// 创建URL表示JAR文件
URL url = new URL("file:" + tempJar.getAbsolutePath());
URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, DeployPluginServiceImpl.class.getClassLoader());
// 加载JAR文件中的主类并执行main方法
String mainClassName = "apelet.tenantadmin.tenant.plugin.MyTestPlugin"; // 替换成你的主类名
Class<?> mainClass = classLoader.loadClass(mainClassName);
Object o1 = mainClass.newInstance();
Method mainMethod = mainClass.getMethod("process", Map.class);
Object invoke = mainMethod.invoke(o1, new HashMap<>());
System.out.println(invoke);
// 关闭classLoader,释放资源
classLoader.close();
tempJar.delete();
tempDir.delete();
}
}
jarInputStream.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
void t1() throws IOException {
URLClassLoader classLoader = null;
JarInputStream jarInputStream = null;
try {
// 读取ZIP文件
File zipFile = new File("D:\\tmp\\test.zip");
jarInputStream = new JarInputStream(Files.newInputStream(zipFile.toPath()));
JarEntry jarEntry;
while ((jarEntry = jarInputStream.getNextJarEntry()) != null) {
// 检查是否为JAR文件
if (!jarEntry.isDirectory() && jarEntry.getName().endsWith(".jar")) {
// 创建URL表示JAR文件
URL url = new URL("jar", "", "file:" + zipFile.getAbsolutePath() + "!/" + jarEntry.getName());
classLoader = new URLClassLoader(new URL[]{url});
// 加载JAR文件中的主类并执行main方法
String mainClassName = "apelet.tenantadmin.tenant.plugin.MyTestPlugin"; // 替换成你的主类名
Class<?> mainClass = classLoader.loadClass(mainClassName);
Object o1 = mainClass.newInstance();
Method mainMethod = mainClass.getMethod("process", Map.class);
mainMethod.invoke(o1, new HashMap<>());
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
classLoader.close();
jarInputStream.close();
}
}
private static void copyStreamToFile(InputStream inputStream, File outputFile) throws IOException {
try (OutputStream outputStream = new FileOutputStream(outputFile)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
@Override
protected BaseDaoMapper<DeployPlugin> mapper() {
return deployPluginMapper;
}
}

73
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantDatasourceServiceImpl.java

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
package apelet.tenantadmin.tenant.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import apelet.common.core.annotation.MyDataSource;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.util.MyModelUtil;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.config.DataSourceType;
import apelet.tenantadmin.tenant.dao.SysTenantDatasourceMapper;
import apelet.tenantadmin.tenant.dao.SysTenantMapper;
import apelet.tenantadmin.tenant.model.*;
import apelet.tenantadmin.tenant.service.SysTenantDatasourceService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 租户权限资源数据服务实现类
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
@MyDataSource(DataSourceType.TENANT_ADMIN)
@Service("sysTenantDatasourceService")
public class SysTenantDatasourceServiceImpl extends BaseService<SysTenantDatasource, Long> implements SysTenantDatasourceService {
@Autowired
private SysTenantDatasourceMapper sysTenantDatasourceMapper;
@Autowired
private SysTenantMapper sysTenantMapper;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private ApplicationConfig applicationConfig;
@Autowired
private RedissonClient redissonClient;
@Override
protected BaseDaoMapper<SysTenantDatasource> mapper() {
return sysTenantDatasourceMapper;
}
@Transactional(rollbackFor = Exception.class)
@Override
public SysTenantDatasource saveNew(SysTenantDatasource datasource) {
datasource.setDatasourceId(idGenerator.nextLongId());
MyModelUtil.fillCommonsForInsert(datasource);
sysTenantDatasourceMapper.insert(datasource);
return datasource;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(SysTenantDatasource datasource, SysTenantDatasource originalDatasource) {
MyModelUtil.fillCommonsForUpdate(datasource, originalDatasource);
return sysTenantDatasourceMapper.updateById(datasource) != 0;
}
@Override
public List<SysTenantDatasource> getSysTenantDatasourceList(SysTenantDatasource filter) {
LambdaQueryWrapper<SysTenantDatasource> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.setEntity(filter);
queryWrapper.orderByDesc(SysTenantDatasource::getDatasourceId);
return sysTenantDatasourceMapper.selectList(queryWrapper);
}
}

287
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantMenuServiceImpl.java

@ -0,0 +1,287 @@ @@ -0,0 +1,287 @@
package apelet.tenantadmin.tenant.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.annotation.MyDataSource;
import apelet.common.core.constant.GlobalDeletedFlag;
import apelet.common.core.object.CallResult;
import apelet.common.core.util.MyModelUtil;
import apelet.common.datasync.constant.DataSyncCommandType;
import apelet.common.datasync.producer.DataSyncRocketMqProducer;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.common.tenant.constant.TenantConstant;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.dao.SysTenantMenuMapper;
import apelet.tenantadmin.tenant.dao.SysTenantMenuPermCodeMapper;
import apelet.tenantadmin.tenant.dao.SysTenantRoleMenuMapper;
import apelet.tenantadmin.tenant.model.SysTenantMenu;
import apelet.tenantadmin.tenant.model.SysTenantMenuPermCode;
import apelet.tenantadmin.tenant.model.SysTenantRoleMenu;
import apelet.tenantadmin.tenant.service.SysTenantMenuService;
import apelet.tenantadmin.tenant.service.SysTenantPermCodeService;
import apelet.tenantadmin.upms.model.constant.SysMenuType;
import apelet.tenantadmin.config.DataSourceType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 租户菜单数据服务类
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
@MyDataSource(DataSourceType.TENANT_ADMIN)
@Service("sysTenantMenuService")
public class SysTenantMenuServiceImpl extends BaseService<SysTenantMenu, Long> implements SysTenantMenuService {
@Autowired
private SysTenantMenuMapper sysTenantMenuMapper;
@Autowired
private SysTenantRoleMenuMapper sysTenantRoleMenuMapper;
@Autowired
private SysTenantMenuPermCodeMapper sysTenantMenuPermCodeMapper;
@Autowired
private SysTenantPermCodeService sysTenantPermCodeService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private DataSyncRocketMqProducer dataSyncProducer;
@Autowired
private ApplicationConfig applicationConfig;
/**
* 返回主对象的Mapper对象
*
* @return 主对象的Mapper对象
*/
@Override
protected BaseDaoMapper<SysTenantMenu> mapper() {
return sysTenantMenuMapper;
}
/**
* 填充租户菜单实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param sysMenu 新增的租户菜单对象
* @param permCodeIdSet 租户权限字Id列表
* @return 新增数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public SysTenantMenu saveNew(SysTenantMenu sysMenu, Set<Long> permCodeIdSet) {
sysMenu.setMenuId(idGenerator.nextLongId());
sysMenu.setDeletedFlag(GlobalDeletedFlag.NORMAL);
MyModelUtil.fillCommonsForInsert(sysMenu);
sysTenantMenuMapper.insert(sysMenu);
List<SysTenantMenuPermCode> sysMenuPermCodeList = new LinkedList<>();
if (CollectionUtils.isNotEmpty(permCodeIdSet)) {
permCodeIdSet.forEach(permCodeId -> {
SysTenantMenuPermCode menuPermCode = new SysTenantMenuPermCode();
menuPermCode.setMenuId(sysMenu.getMenuId());
menuPermCode.setPermCodeId(permCodeId);
sysMenuPermCodeList.add(menuPermCode);
});
sysTenantMenuPermCodeMapper.insertList(sysMenuPermCodeList);
}
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantMenu", sysMenu);
messageJsonData.put("sysTenantMenuPermCodeList", sysMenuPermCodeList);
dataSyncProducer.sendOrderly(
sysMenu.getMenuId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.INSERT.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return sysMenu;
}
/**
* 填充租户菜单实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysMenu 更新的租户菜单对象
* @param originalSysMenu 原有的租户菜单对象
* @param permCodeIdSet 租户权限字Id列表
* @return 更新数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(SysTenantMenu sysMenu, SysTenantMenu originalSysMenu, Set<Long> permCodeIdSet) {
MyModelUtil.fillCommonsForUpdate(sysMenu, originalSysMenu);
UpdateWrapper<SysTenantMenu> updateWrapper =
this.createUpdateQueryForNullValue(sysMenu, sysMenu.getMenuId());
if (sysTenantMenuMapper.update(sysMenu, updateWrapper) == 0) {
return false;
}
SysTenantMenuPermCode deletedMenuPermCode = new SysTenantMenuPermCode();
deletedMenuPermCode.setMenuId(sysMenu.getMenuId());
sysTenantMenuPermCodeMapper.delete(new QueryWrapper<>(deletedMenuPermCode));
List<SysTenantMenuPermCode> sysMenuPermCodeList = new LinkedList<>();
if (CollectionUtils.isNotEmpty(permCodeIdSet)) {
for (Long permCodeId : permCodeIdSet) {
SysTenantMenuPermCode menuPermCode = new SysTenantMenuPermCode();
menuPermCode.setMenuId(sysMenu.getMenuId());
menuPermCode.setPermCodeId(permCodeId);
sysMenuPermCodeList.add(menuPermCode);
}
sysTenantMenuPermCodeMapper.insertList(sysMenuPermCodeList);
}
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantMenu", sysMenu);
messageJsonData.put("originalSysTenantMenu", originalSysMenu);
messageJsonData.put("sysTenantMenuPermCodeList", sysMenuPermCodeList);
dataSyncProducer.sendOrderly(
sysMenu.getMenuId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.UPDATE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 填充租户菜单实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param menuId 租户菜单主键Id
* @return 删除数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long menuId) {
if (!this.removeById(menuId)) {
return false;
}
SysTenantRoleMenu roleMenu = new SysTenantRoleMenu();
roleMenu.setMenuId(menuId);
sysTenantRoleMenuMapper.delete(new QueryWrapper<>(roleMenu));
SysTenantMenuPermCode menuPermCode = new SysTenantMenuPermCode();
menuPermCode.setMenuId(menuId);
sysTenantMenuPermCodeMapper.delete(new QueryWrapper<>(menuPermCode));
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("menuId", menuId);
dataSyncProducer.sendOrderly(
menuId,
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.DELETE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 根据租户角色Id获取关联的租户菜单从表中没有和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param orderBy 排序字符串order by从句的参数
* @return 与主表没有建立关联的租户菜单数据列表
*/
@Override
public List<SysTenantMenu> getNotInSysTenantMenuListByRoleId(Long tenantRoleId, String orderBy) {
return sysTenantMenuMapper.getNotInSysTenantMenuListByRoleId(tenantRoleId, orderBy);
}
/**
* 根据租户角色Id获取关联的租户菜单从表中和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param orderBy 排序字符串order by从句的参数
* @return 与主表建立关联的租户菜单数据列表
*/
@Override
public List<SysTenantMenu> getSysTenantMenuListByRoleId(Long tenantRoleId, String orderBy) {
return sysTenantMenuMapper.getSysTenantMenuListByRoleId(tenantRoleId, orderBy);
}
/**
* 判断当前租户菜单是否存在子菜单
*
* @param menuId 租户菜单主键Id
* @return 存在返回true否则false
*/
@Override
public boolean hasChildren(Long menuId) {
SysTenantMenu menu = new SysTenantMenu();
menu.setParentId(menuId);
return this.getCountByFilter(menu) > 0;
}
/**
* 验证租户菜单对象关联的数据是否都合法
*
* @param sysMenu 当前操作的对象
* @param originalSysMenu 原有对象
* @param permCodeIdListString 逗号分隔的权限Id列表
* @return 验证结果
*/
@Override
public CallResult verifyRelatedData(
SysTenantMenu sysMenu, SysTenantMenu originalSysMenu, String permCodeIdListString) {
// menu、ui fragment和button类型的menu不能没有parentId
if (sysMenu.getParentId() == null && sysMenu.getMenuType() != SysMenuType.TYPE_DIRECTORY) {
return CallResult.error("数据验证失败,当前类型菜单项的上级菜单不能为空!");
}
if (this.needToVerify(sysMenu, originalSysMenu, SysTenantMenu::getParentId)) {
String errorMessage = checkErrorOfNonDirectoryMenu(sysMenu);
if (errorMessage != null) {
return CallResult.error(errorMessage);
}
}
JSONObject jsonObject = null;
if (StringUtils.isNotBlank(permCodeIdListString)) {
Set<Long> permCodeIdSet = Arrays.stream(
permCodeIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet());
if (!sysTenantPermCodeService.existAllPrimaryKeys(permCodeIdSet)) {
return CallResult.error("数据验证失败,存在不合法的权限字,请刷新后重试!");
}
jsonObject = new JSONObject();
jsonObject.put("permCodeIdSet", permCodeIdSet);
}
return CallResult.ok(jsonObject);
}
private String checkErrorOfNonDirectoryMenu(SysTenantMenu sysMenu) {
// 判断父节点是否存在
SysTenantMenu parentSysMenu = getById(sysMenu.getParentId());
if (parentSysMenu == null) {
return "数据验证失败,关联的上级菜单并不存在,请刷新后重试!";
}
// 逐个判断每种类型的菜单,他的父菜单的合法性,先从目录类型和菜单类型开始
if (sysMenu.getMenuType() == SysMenuType.TYPE_DIRECTORY
|| sysMenu.getMenuType() == SysMenuType.TYPE_MENU) {
// 他们的上级只能是目录
if (parentSysMenu.getMenuType() != SysMenuType.TYPE_DIRECTORY) {
return "数据验证失败,当前类型菜单项的上级菜单只能是目录类型!";
}
} else if (sysMenu.getMenuType() == SysMenuType.TYPE_BUTTON) {
// button的上级只能是menu和ui fragment
if (parentSysMenu.getMenuType() != SysMenuType.TYPE_MENU
&& parentSysMenu.getMenuType() != SysMenuType.TYPE_UI_FRAGMENT) {
return "数据验证失败,当前类型菜单项的上级菜单只能是菜单类型和UI片段类型!";
}
} else if (sysMenu.getMenuType() == SysMenuType.TYPE_UI_FRAGMENT) {
// ui fragment的上级只能是menu类型
if (parentSysMenu.getMenuType() != SysMenuType.TYPE_MENU) {
return "数据验证失败,当前类型菜单项的上级菜单只能是菜单类型和按钮类型!";
}
} else {
return "数据验证失败,不支持的菜单类型!";
}
return null;
}
}

228
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantPermCodeServiceImpl.java

@ -0,0 +1,228 @@ @@ -0,0 +1,228 @@
package apelet.tenantadmin.tenant.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.annotation.MyDataSource;
import apelet.common.core.constant.GlobalDeletedFlag;
import apelet.common.core.object.CallResult;
import apelet.common.core.util.MyModelUtil;
import apelet.common.datasync.constant.DataSyncCommandType;
import apelet.common.datasync.producer.DataSyncRocketMqProducer;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.common.tenant.constant.TenantConstant;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.dao.SysTenantMenuPermCodeMapper;
import apelet.tenantadmin.tenant.dao.SysTenantPermCodeMapper;
import apelet.tenantadmin.tenant.dao.SysTenantPermCodePermMapper;
import apelet.tenantadmin.tenant.model.SysTenantMenuPermCode;
import apelet.tenantadmin.tenant.model.SysTenantPermCode;
import apelet.tenantadmin.tenant.model.SysTenantPermCodePerm;
import apelet.tenantadmin.tenant.service.SysTenantPermCodeService;
import apelet.tenantadmin.tenant.service.SysTenantPermService;
import apelet.tenantadmin.config.DataSourceType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 租户权限字数据服务类
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
@MyDataSource(DataSourceType.TENANT_ADMIN)
@Service("sysTenantPermCodeService")
public class SysTenantPermCodeServiceImpl extends BaseService<SysTenantPermCode, Long> implements SysTenantPermCodeService {
@Autowired
private SysTenantPermCodeMapper sysTenantPermCodeMapper;
@Autowired
private SysTenantPermCodePermMapper sysTenantPermCodePermMapper;
@Autowired
private SysTenantMenuPermCodeMapper sysTenantMenuPermCodeMapper;
@Autowired
private SysTenantPermService sysTenantPermService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private DataSyncRocketMqProducer dataSyncProducer;
@Autowired
private ApplicationConfig applicationConfig;
/**
* 返回主对象的Mapper对象
*
* @return 主对象的Mapper对象
*/
@Override
protected BaseDaoMapper<SysTenantPermCode> mapper() {
return sysTenantPermCodeMapper;
}
/**
* 填充租户权限字实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param sysPermCode 新增的租户权限字实体对象
* @param permIdSet 租户权限资源Id列表
* @return 新增数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public SysTenantPermCode saveNew(SysTenantPermCode sysPermCode, Set<Long> permIdSet) {
sysPermCode.setPermCodeId(idGenerator.nextLongId());
sysPermCode.setDeletedFlag(GlobalDeletedFlag.NORMAL);
MyModelUtil.fillCommonsForInsert(sysPermCode);
sysTenantPermCodeMapper.insert(sysPermCode);
List<SysTenantPermCodePerm> sysPermCodePermList = new LinkedList<>();
if (permIdSet != null) {
permIdSet.forEach(permId -> {
SysTenantPermCodePerm permCodePerm = new SysTenantPermCodePerm();
permCodePerm.setPermCodeId(sysPermCode.getPermCodeId());
permCodePerm.setPermId(permId);
sysPermCodePermList.add(permCodePerm);
});
sysTenantPermCodePermMapper.insertList(sysPermCodePermList);
}
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantPermCode", sysPermCode);
messageJsonData.put("sysTenantPermCodePermList", sysPermCodePermList);
dataSyncProducer.sendOrderly(
sysPermCode.getPermCodeId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.INSERT.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return sysPermCode;
}
/**
* 填充租户权限字实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysPermCode 更新的租户权限字对象
* @param originalSysPermCode 原有的租户权限字对象
* @param permIdSet 租户权限资源Id列表
* @return 更新数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(SysTenantPermCode sysPermCode, SysTenantPermCode originalSysPermCode, Set<Long> permIdSet) {
sysPermCode.setParentId(originalSysPermCode.getParentId());
MyModelUtil.fillCommonsForUpdate(sysPermCode, originalSysPermCode);
UpdateWrapper<SysTenantPermCode> updateWrapper =
this.createUpdateQueryForNullValue(sysPermCode, sysPermCode.getPermCodeId());
if (sysTenantPermCodeMapper.update(sysPermCode, updateWrapper) == 0) {
return false;
}
SysTenantPermCodePerm deletedPermCodePerm = new SysTenantPermCodePerm();
deletedPermCodePerm.setPermCodeId(sysPermCode.getPermCodeId());
sysTenantPermCodePermMapper.delete(new QueryWrapper<>(deletedPermCodePerm));
List<SysTenantPermCodePerm> sysPermCodePermList = new LinkedList<>();
if (permIdSet != null) {
for (Long permId : permIdSet) {
SysTenantPermCodePerm permCodePerm = new SysTenantPermCodePerm();
permCodePerm.setPermCodeId(sysPermCode.getPermCodeId());
permCodePerm.setPermId(permId);
sysPermCodePermList.add(permCodePerm);
}
sysTenantPermCodePermMapper.insertList(sysPermCodePermList);
}
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantPermCode", sysPermCode);
messageJsonData.put("sysTenantPermCodePermList", sysPermCodePermList);
dataSyncProducer.sendOrderly(
sysPermCode.getPermCodeId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.UPDATE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 填充租户权限字实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param permCodeId 租户权限字主键Id
* @return 删除数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long permCodeId) {
// 这里先删除主数据
if (!this.removeById(permCodeId)) {
return false;
}
SysTenantMenuPermCode menuPermCode = new SysTenantMenuPermCode();
menuPermCode.setPermCodeId(permCodeId);
sysTenantMenuPermCodeMapper.delete(new QueryWrapper<>(menuPermCode));
SysTenantPermCodePerm permCodePerm = new SysTenantPermCodePerm();
permCodePerm.setPermCodeId(permCodeId);
sysTenantPermCodePermMapper.delete(new QueryWrapper<>(permCodePerm));
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("permCodeId", permCodeId);
dataSyncProducer.sendOrderly(
permCodeId,
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.DELETE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 判断当前租户权限字是否存在下级权限字对象
*
* @param permCodeId 租户权限字主键Id
* @return 存在返回true否则false
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean hasChildren(Long permCodeId) {
SysTenantPermCode permCode = new SysTenantPermCode();
permCode.setParentId(permCodeId);
return this.getCountByFilter(permCode) > 0;
}
/**
* 验证租户权限字对象关联的数据是否都合法
*
* @param sysPermCode 当前操作的对象
* @param originalSysPermCode 原有对象
* @param permIdListString 逗号分隔的权限资源Id列表
* @return 验证结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public CallResult verifyRelatedData(
SysTenantPermCode sysPermCode, SysTenantPermCode originalSysPermCode, String permIdListString) {
if (this.needToVerify(sysPermCode, originalSysPermCode, SysTenantPermCode::getParentId)
&& !existId(sysPermCode.getParentId())) {
return CallResult.error("数据验证失败,关联的上级权限字并不存在,请刷新后重试!");
}
JSONObject jsonObject = null;
if (StringUtils.isNotBlank(permIdListString)) {
Set<Long> permIdSet = Arrays.stream(
permIdListString.split(",")).map(Long::valueOf).collect(Collectors.toSet());
if (!sysTenantPermService.existAllPrimaryKeys(permIdSet)) {
return CallResult.error("数据验证失败,存在不合法的权限资源,请刷新后重试!");
}
jsonObject = new JSONObject();
jsonObject.put("permIdSet", permIdSet);
}
return CallResult.ok(jsonObject);
}
}

175
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantPermModuleServiceImpl.java

@ -0,0 +1,175 @@ @@ -0,0 +1,175 @@
package apelet.tenantadmin.tenant.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.annotation.MyDataSource;
import apelet.common.core.constant.GlobalDeletedFlag;
import apelet.common.core.util.MyModelUtil;
import apelet.common.datasync.constant.DataSyncCommandType;
import apelet.common.datasync.producer.DataSyncRocketMqProducer;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.common.tenant.constant.TenantConstant;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.dao.SysTenantPermModuleMapper;
import apelet.tenantadmin.tenant.model.SysTenantPerm;
import apelet.tenantadmin.tenant.model.SysTenantPermModule;
import apelet.tenantadmin.tenant.service.SysTenantPermModuleService;
import apelet.tenantadmin.tenant.service.SysTenantPermService;
import apelet.tenantadmin.config.DataSourceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 租户权限资源模块数据服务类
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
@MyDataSource(DataSourceType.TENANT_ADMIN)
@Service("sysTenantPermModuleService")
public class SysTenantPermModuleServiceImpl extends BaseService<SysTenantPermModule, Long> implements SysTenantPermModuleService {
@Autowired
private SysTenantPermModuleMapper sysTenantPermModuleMapper;
@Autowired
private SysTenantPermService sysTenantPermService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private DataSyncRocketMqProducer dataSyncProducer;
@Autowired
private ApplicationConfig applicationConfig;
/**
* 返回主对象的Mapper对象
*
* @return 主对象的Mapper对象
*/
@Override
protected BaseDaoMapper<SysTenantPermModule> mapper() {
return sysTenantPermModuleMapper;
}
/**
* 填充租户权限资源模块实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param sysPermModule 新增的租户权限资源模块实体对象
* @return 新增数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public SysTenantPermModule saveNew(SysTenantPermModule sysPermModule) {
sysPermModule.setModuleId(idGenerator.nextLongId());
sysPermModule.setDeletedFlag(GlobalDeletedFlag.NORMAL);
MyModelUtil.fillCommonsForInsert(sysPermModule);
sysTenantPermModuleMapper.insert(sysPermModule);
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantPermModule", sysPermModule);
dataSyncProducer.sendOrderly(
sysPermModule.getModuleId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.INSERT.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return sysPermModule;
}
/**
* 填充租户权限资源模块实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysPermModule 更新的租户权限资源模块对象
* @param originalSysPermModule 原有的租户权限资源模块对象
* @return 更新数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(SysTenantPermModule sysPermModule, SysTenantPermModule originalSysPermModule) {
MyModelUtil.fillCommonsForUpdate(sysPermModule, originalSysPermModule);
UpdateWrapper<SysTenantPermModule> updateWrapper =
this.createUpdateQueryForNullValue(sysPermModule, sysPermModule.getModuleId());
if (sysTenantPermModuleMapper.update(sysPermModule, updateWrapper) == 0) {
return false;
}
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantPermModule", sysPermModule);
dataSyncProducer.sendOrderly(
sysPermModule.getModuleId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.UPDATE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 填充租户权限资源模块实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param moduleId 待删除的租户权限资源模块主键Id
* @return 删除数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long moduleId) {
if (!this.removeById(moduleId)) {
return false;
}
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("moduleId", moduleId);
dataSyncProducer.sendOrderly(
moduleId,
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.DELETE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 获取权限模块资源及其关联的权限资源列表
*
* @return 权限资源模块及其关联的权限资源列表
*/
@Override
public List<SysTenantPermModule> getPermModuleAndPermList() {
return sysTenantPermModuleMapper.getPermModuleAndPermList();
}
/**
* 判断是否存在下级租户权限资源模块
*
* @param moduleId 租户权限资源模块主键Id
* @return 存在返回true否则false
*/
@Override
public boolean hasChildren(Long moduleId) {
SysTenantPermModule permModule = new SysTenantPermModule();
permModule.setParentId(moduleId);
return this.getCountByFilter(permModule) > 0;
}
/**
* 判断是否存在租户权限数据
*
* @param moduleId 租户权限资源模块主键Id
* @return 存在返回true否则false
*/
@Override
public boolean hasModulePerms(Long moduleId) {
SysTenantPerm filter = new SysTenantPerm();
filter.setModuleId(moduleId);
return sysTenantPermService.getCountByFilter(filter) > 0;
}
}

190
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantPermServiceImpl.java

@ -0,0 +1,190 @@ @@ -0,0 +1,190 @@
package apelet.tenantadmin.tenant.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.annotation.MyDataSource;
import apelet.common.core.constant.GlobalDeletedFlag;
import apelet.common.core.object.CallResult;
import apelet.common.core.object.MyRelationParam;
import apelet.common.core.util.MyModelUtil;
import apelet.common.datasync.constant.DataSyncCommandType;
import apelet.common.datasync.producer.DataSyncRocketMqProducer;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.common.tenant.constant.TenantConstant;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.dao.SysTenantPermCodePermMapper;
import apelet.tenantadmin.tenant.dao.SysTenantPermMapper;
import apelet.tenantadmin.tenant.model.SysTenantPerm;
import apelet.tenantadmin.tenant.model.SysTenantPermCodePerm;
import apelet.tenantadmin.tenant.model.SysTenantPermModule;
import apelet.tenantadmin.tenant.service.SysTenantPermModuleService;
import apelet.tenantadmin.tenant.service.SysTenantPermService;
import apelet.tenantadmin.config.DataSourceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* 租户权限资源数据服务类
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
@MyDataSource(DataSourceType.TENANT_ADMIN)
@Service("sysTenantPermService")
public class SysTenantPermServiceImpl extends BaseService<SysTenantPerm, Long> implements SysTenantPermService {
@Autowired
private SysTenantPermMapper sysTenantPermMapper;
@Autowired
private SysTenantPermCodePermMapper sysTenantPermCodePermMapper;
@Autowired
private SysTenantPermModuleService sysTenantPermModuleService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private DataSyncRocketMqProducer dataSyncProducer;
@Autowired
private ApplicationConfig applicationConfig;
/**
* 返回主对象的Mapper对象
*
* @return 主对象的Mapper对象
*/
@Override
protected BaseDaoMapper<SysTenantPerm> mapper() {
return sysTenantPermMapper;
}
/**
* 填充租户权限资源实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param sysPerm 新增的租户权限资源实体对象
* @return 新增数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public SysTenantPerm saveNew(SysTenantPerm sysPerm) {
sysPerm.setPermId(idGenerator.nextLongId());
sysPerm.setDeletedFlag(GlobalDeletedFlag.NORMAL);
MyModelUtil.fillCommonsForInsert(sysPerm);
sysTenantPermMapper.insert(sysPerm);
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantPerm", sysPerm);
dataSyncProducer.sendOrderly(
sysPerm.getPermId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.INSERT.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return sysPerm;
}
/**
* 填充租户权限资源实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysPerm 更新的租户权限资源对象
* @param originalSysPerm 原有的租户权限资源对象
* @return 更新数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(SysTenantPerm sysPerm, SysTenantPerm originalSysPerm) {
MyModelUtil.fillCommonsForUpdate(sysPerm, originalSysPerm);
UpdateWrapper<SysTenantPerm> updateWrapper =
this.createUpdateQueryForNullValue(sysPerm, sysPerm.getPermId());
if (sysTenantPermMapper.update(sysPerm, updateWrapper) == 0) {
return false;
}
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenantPerm", sysPerm);
dataSyncProducer.sendOrderly(
sysPerm.getPermId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.UPDATE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 填充租户权限资源实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param permId 待删除的租户权限资源主键Id
* @return 删除数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long permId) {
if (!this.removeById(permId)) {
return false;
}
SysTenantPermCodePerm permCodePerm = new SysTenantPermCodePerm();
permCodePerm.setPermId(permId);
sysTenantPermCodePermMapper.delete(new QueryWrapper<>(permCodePerm));
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("permId", permId);
dataSyncProducer.sendOrderly(
permId,
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.DELETE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 获取租户权限数据列表
*
* @param sysPermFilter 过滤对象
* @return 权限列表
*/
@Override
public List<SysTenantPerm> getPermListWithRelation(SysTenantPerm sysPermFilter) {
QueryWrapper<SysTenantPerm> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc(this.safeMapToColumnName("showOrder"));
if (ObjectUtil.isNotNull(sysPermFilter.getModuleId())) {
queryWrapper.eq(this.safeMapToColumnName("moduleId"), sysPermFilter.getModuleId());
}
if (ObjectUtil.isNotNull(sysPermFilter.getUrl())) {
queryWrapper.like("url", "%" + sysPermFilter.getUrl() + "%");
}
List<SysTenantPerm> permList = sysTenantPermMapper.selectList(queryWrapper);
// 这里因为权限只有字典数据,所以仅仅做字典关联。
this.buildRelationForDataList(permList, MyRelationParam.dictOnly());
return permList;
}
/**
* 验证租户权限资源对象关联的数据是否都合法
*
* @param sysPerm 当前操作的对象
* @param originalSysPerm 原有对象
* @return 验证结果
*/
@Override
public CallResult verifyRelatedData(SysTenantPerm sysPerm, SysTenantPerm originalSysPerm) {
if (this.needToVerify(sysPerm, originalSysPerm, SysTenantPerm::getModuleId)) {
SysTenantPermModule permModule = sysTenantPermModuleService.getById(sysPerm.getModuleId());
if (permModule == null) {
return CallResult.error("数据验证失败,关联的租户权限模块Id并不存在,请刷新后重试!");
}
}
return CallResult.ok();
}
}

644
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantRoleServiceImpl.java

@ -0,0 +1,644 @@ @@ -0,0 +1,644 @@
package apelet.tenantadmin.tenant.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.annotation.MyDataSource;
import apelet.common.core.constant.GlobalDeletedFlag;
import apelet.common.core.util.MyModelUtil;
import apelet.common.datasync.producer.DataSyncRocketMqProducer;
import apelet.common.online.model.OnlinePage;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.common.tenant.constant.TenantConstant;
import apelet.common.report.model.ReportTenantDataset;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.dao.*;
import apelet.tenantadmin.tenant.model.*;
import apelet.tenantadmin.tenant.service.SysTenantRoleService;
import apelet.tenantadmin.tenant.service.SysTenantService;
import apelet.tenantadmin.config.DataSourceType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.stream.Collectors;
/**
* 租户角色数据服务类
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
@MyDataSource(DataSourceType.TENANT_ADMIN)
@Service("sysTenantRoleService")
public class SysTenantRoleServiceImpl extends BaseService<SysTenantRole, Long> implements SysTenantRoleService {
@Autowired
private SysTenantRoleMapper sysTenantRoleMapper;
@Autowired
private SysTenantRoleMenuMapper sysTenantRoleMenuMapper;
@Autowired
private SysTenantRoleTenantMapper sysTenantRoleTenantMapper;
@Autowired
private SysTenantRoleReportDatasetMapper sysTenantRoleReportDatasetMapper;
@Autowired
private SysTenantRoleOnlinePageMapper sysTenantRoleOnlinePageMapper;
@Autowired
private SysTenantExtMapper sysTenantExtMapper;
@Autowired
private SysTenantService sysTenantService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private DataSyncRocketMqProducer dataSyncProducer;
@Autowired
private ApplicationConfig applicationConfig;
private static final String TENANT_ID_KEY = "tenantId";
private static final String TENANT_ID_SET_KEY = "tenantIdSet";
private static final String TENANT_LIST_KEY = "tenantList";
private static final String TENANT_EXT_LIST_KEY = "tenantExtList";
private static final String MENU_ID_KEY = "menuId";
private static final String MENU_ID_SET_KEY = "menuIdSet";
private static final String REPORT_DATASET_ID_KEY = "datasetId";
private static final String REPORT_DATASET_ID_SET_KEY = "datasetIdSet";
private static final String ONLINE_PAGE_ID_SET_KEY = "pageIdSet";
/**
* 返回主对象的Mapper对象
*
* @return 主对象的Mapper对象
*/
@Override
protected BaseDaoMapper<SysTenantRole> mapper() {
return sysTenantRoleMapper;
}
@Transactional(rollbackFor = Exception.class)
@Override
public SysTenantRole saveNew(SysTenantRole sysTenantRole) {
sysTenantRole.setTenantRoleId(idGenerator.nextLongId());
sysTenantRole.setDeletedFlag(GlobalDeletedFlag.NORMAL);
MyModelUtil.fillCommonsForInsert(sysTenantRole);
sysTenantRoleMapper.insert(sysTenantRole);
return sysTenantRole;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(SysTenantRole sysTenantRole, SysTenantRole originalSysTenantRole) {
MyModelUtil.fillCommonsForUpdate(sysTenantRole, originalSysTenantRole);
return sysTenantRoleMapper.updateById(sysTenantRole) == 1;
}
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(Long tenantRoleId) {
if (!this.removeById(tenantRoleId)) {
return false;
}
SysTenantRoleTenant tenantRoleTenant = new SysTenantRoleTenant();
tenantRoleTenant.setTenantRoleId(tenantRoleId);
sysTenantRoleTenantMapper.delete(new QueryWrapper<>(tenantRoleTenant));
SysTenantRoleMenu tenantRoleMenu = new SysTenantRoleMenu();
tenantRoleMenu.setTenantRoleId(tenantRoleId);
sysTenantRoleMenuMapper.delete(new QueryWrapper<>(tenantRoleMenu));
SysTenantRoleReportDataset tenantRoleReportDataset = new SysTenantRoleReportDataset();
tenantRoleReportDataset.setTenantRoleId(tenantRoleId);
sysTenantRoleReportDatasetMapper.delete(new QueryWrapper<>(tenantRoleReportDataset));
SysTenantRoleOnlinePage tenantRoleOnlinePage = new SysTenantRoleOnlinePage();
tenantRoleOnlinePage.setTenantRoleId(tenantRoleId);
sysTenantRoleOnlinePageMapper.delete(new QueryWrapper<>(tenantRoleOnlinePage));
return true;
}
@Override
public List<SysTenantRole> getSysTenantRoleList(SysTenantRole filter, String orderBy) {
return sysTenantRoleMapper.getSysTenantRoleList(filter, orderBy);
}
@Override
public boolean hasTenantByRoleId(Long tenantRoleId) {
SysTenantRoleTenant tenantRoleTenant = new SysTenantRoleTenant();
tenantRoleTenant.setTenantRoleId(tenantRoleId);
return sysTenantRoleTenantMapper.selectCount(new QueryWrapper<>(tenantRoleTenant)) > 0;
}
@Override
public boolean hasTenantRelatedDataByTenantRoleId(Long tenantRoleId) {
SysTenantRoleMenu tenantRoleMenu = new SysTenantRoleMenu();
tenantRoleMenu.setTenantRoleId(tenantRoleId);
if (sysTenantRoleMenuMapper.selectCount(new QueryWrapper<>(tenantRoleMenu)) > 0) {
return true;
}
SysTenantRoleReportDataset tenantRoleReportDataset = new SysTenantRoleReportDataset();
tenantRoleReportDataset.setTenantRoleId(tenantRoleId);
if (sysTenantRoleReportDatasetMapper.selectCount(new QueryWrapper<>(tenantRoleReportDataset)) > 0) {
return true;
}
SysTenantRoleOnlinePage tenantRoleOnlinePage = new SysTenantRoleOnlinePage();
tenantRoleOnlinePage.setTenantRoleId(tenantRoleId);
return sysTenantRoleOnlinePageMapper.selectCount(new QueryWrapper<>(tenantRoleOnlinePage)) > 0;
}
@Transactional(rollbackFor = Exception.class)
@Override
public void addTenantRoleTenantList(Long tenantRoleId, List<SysTenantRoleTenant> sysTenantRoleTenantList) {
for (SysTenantRoleTenant sysTenantRoleTenant : sysTenantRoleTenantList) {
sysTenantRoleTenant.setTenantRoleId(tenantRoleId);
}
sysTenantRoleTenantMapper.insertList(sysTenantRoleTenantList);
Set<Long> tenantIds = sysTenantRoleTenantList.stream()
.map(SysTenantRoleTenant::getTenantId).collect(Collectors.toSet());
// 如果当前租户角色下没有租户菜单,就不需要在同步到远程租户数据库了。
SysTenantRoleMenu tenantRoleMenu = new SysTenantRoleMenu();
tenantRoleMenu.setTenantRoleId(tenantRoleId);
List<SysTenantRoleMenu> menuList = sysTenantRoleMenuMapper.selectList(new QueryWrapper<>(tenantRoleMenu));
if (CollUtil.isNotEmpty(menuList)) {
Set<Long> menuIdSet = menuList.stream().map(SysTenantRoleMenu::getMenuId).collect(Collectors.toSet());
List<SysTenant> tenantList = sysTenantService.getInList(tenantIds);
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(TENANT_LIST_KEY, tenantList);
messageJsonData.put(MENU_ID_SET_KEY, menuIdSet);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
SysTenantMenu.class.getSimpleName(),
TenantConstant.INSERT_TENANT_ROLE_TENANT_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
List<Long> datasetIds = this.getSysTenantRoleReportDatasetIdList(tenantRoleId);
if (CollUtil.isNotEmpty(datasetIds)) {
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(TENANT_ID_SET_KEY, tenantIds);
messageJsonData.put(REPORT_DATASET_ID_SET_KEY, datasetIds);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
ReportTenantDataset.class.getSimpleName(),
TenantConstant.INSERT_TENANT_REPORT_DATASET_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
List<Long> pageIds = this.getSysTenantRoleOnlinePageIdList(tenantRoleId);
if (CollUtil.isNotEmpty(pageIds)) {
this.processAddTenantOnlinePageAndSync(tenantRoleId, tenantIds, pageIds);
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void removeTenantRoleTenant(Long tenantRoleId, Long tenantId) {
SysTenantRoleTenant sysTenantRoleTenant = new SysTenantRoleTenant();
sysTenantRoleTenant.setTenantRoleId(tenantRoleId);
sysTenantRoleTenant.setTenantId(tenantId);
sysTenantRoleTenantMapper.delete(new QueryWrapper<>(sysTenantRoleTenant));
}
@Transactional(rollbackFor = Exception.class)
@Override
public void removeTenantRoleTenantAndSync(Long tenantRoleId, Long tenantId) {
// 获取当前租户角色关联哪些菜单,当前租户角色肯定是包含菜单的,因为在外面已经做了判断。
SysTenantRoleMenu tenantRoleMenu = new SysTenantRoleMenu();
tenantRoleMenu.setTenantRoleId(tenantRoleId);
Set<Long> menuIdSet = sysTenantRoleMenuMapper.selectList(new QueryWrapper<>(tenantRoleMenu))
.stream().map(SysTenantRoleMenu::getMenuId).collect(Collectors.toSet());
// 获取当前租户还有哪些其他角色。
// select tenant_role_id from zz_tenant_role_tenant where tenant_id = tenantId and tenant_role_id != roleId
LambdaQueryWrapper<SysTenantRoleTenant> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysTenantRoleTenant::getTenantId, tenantId);
queryWrapper.ne(SysTenantRoleTenant::getTenantRoleId, tenantRoleId);
Set<Long> otherRoleIdSet = sysTenantRoleTenantMapper.selectList(queryWrapper)
.stream().map(SysTenantRoleTenant::getTenantRoleId).collect(Collectors.toSet());
Set<Long> resultMenuIdSet = this.filterTenantMenuIdSet(menuIdSet, otherRoleIdSet);
// 本地租户管理数据库中移除他们的关联关系即可了。
if (CollUtil.isNotEmpty(resultMenuIdSet)) {
SysTenant sysTenant = sysTenantService.getById(tenantId);
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenant", sysTenant);
messageJsonData.put(MENU_ID_SET_KEY, resultMenuIdSet);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
SysTenantMenu.class.getSimpleName(),
TenantConstant.DELETE_TENANT_ROLE_TENANT_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
List<Long> reportDatasetIdSet = this.getSysTenantRoleReportDatasetIdList(tenantRoleId);
Set<Long> resultReportDatasetIdSet =
this.filterTenantReportDatasetIdSet(new HashSet<>(reportDatasetIdSet), otherRoleIdSet);
if (CollUtil.isNotEmpty(resultReportDatasetIdSet)) {
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(TENANT_ID_KEY, tenantId);
messageJsonData.put(REPORT_DATASET_ID_SET_KEY, resultReportDatasetIdSet);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
ReportTenantDataset.class.getSimpleName(),
TenantConstant.DELETE_TENANT_REPORT_DATASET_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
this.processRemoveTenantOnlinePageAndSync(tenantRoleId, tenantId, otherRoleIdSet);
this.removeTenantRoleTenant(tenantRoleId, tenantId);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void addTenantRoleMenuList(Long tenantRoleId, List<SysTenantRoleMenu> sysTenantRoleMenuList) {
for (SysTenantRoleMenu sysTenantRoleMenu : sysTenantRoleMenuList) {
sysTenantRoleMenu.setTenantRoleId(tenantRoleId);
}
sysTenantRoleMenuMapper.insertList(sysTenantRoleMenuList);
// 判断该租户角色是否包含租户,如果包含需要同步远程数据。
List<SysTenant> tenantList =
sysTenantService.getSysTenantListByRoleId(tenantRoleId, null, null);
if (CollUtil.isNotEmpty(tenantList)) {
Set<Long> menuIdSet = sysTenantRoleMenuList.stream()
.map(SysTenantRoleMenu::getMenuId).collect(Collectors.toSet());
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(TENANT_LIST_KEY, tenantList);
messageJsonData.put(MENU_ID_SET_KEY, menuIdSet);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
SysTenantMenu.class.getSimpleName(),
TenantConstant.INSERT_TENANT_ROLE_MENU_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void removeTenantRoleMenu(Long tenantRoleId, Long tenantMenuId) {
SysTenantRoleMenu sysTenantRoleMenu = new SysTenantRoleMenu();
sysTenantRoleMenu.setTenantRoleId(tenantRoleId);
sysTenantRoleMenu.setMenuId(tenantMenuId);
sysTenantRoleMenuMapper.delete(new QueryWrapper<>(sysTenantRoleMenu));
}
@Transactional(rollbackFor = Exception.class)
@Override
public void removeTenantRoleMenuAndSync(Long tenantRoleId, Long menuId) {
// 获取还有哪些其他租户角色关联了该菜单,得到租户角色Id列表。
// select * from zz_tenant_role_menu where tenant_role_id != roleId and menu_id = menuId
LambdaQueryWrapper<SysTenantRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysTenantRoleMenu::getMenuId, menuId);
queryWrapper.ne(SysTenantRoleMenu::getTenantRoleId, tenantRoleId);
Set<Long> otherTenantRoleIds = sysTenantRoleMenuMapper.selectList(queryWrapper)
.stream().map(SysTenantRoleMenu::getTenantRoleId).collect(Collectors.toSet());
Set<Long> resultTenantIdSet = this.filterTenantIdSet(tenantRoleId, otherTenantRoleIds);
// 如果没有需要同步删除的租户菜单数据列表,仅执行本地关联数据删除即可。
this.removeTenantRoleMenu(tenantRoleId, menuId);
if (CollUtil.isEmpty(resultTenantIdSet)) {
return;
}
List<SysTenant> tenantList = sysTenantService.getInList(resultTenantIdSet);
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(MENU_ID_KEY, menuId);
messageJsonData.put(TENANT_LIST_KEY, tenantList);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
SysTenantMenu.class.getSimpleName(),
TenantConstant.DELETE_TENANT_ROLE_MENU_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
@Transactional(rollbackFor = Exception.class)
@Override
public void addTenantRoleReportDatasetList(Long tenantRoleId, Set<Long> datasetIds) {
List<SysTenantRoleReportDataset> dataList = datasetIds.stream().map(datasetId -> {
SysTenantRoleReportDataset data = new SysTenantRoleReportDataset();
data.setTenantRoleId(tenantRoleId);
data.setDatasetId(datasetId);
return data;
}).collect(Collectors.toList());
sysTenantRoleReportDatasetMapper.insertList(dataList);
List<Long> tenantIds = this.getSysTenantRoleTenantIdsByTenantRoleId(tenantRoleId);
if (CollUtil.isNotEmpty(tenantIds)) {
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(TENANT_ID_SET_KEY, tenantIds);
messageJsonData.put(REPORT_DATASET_ID_SET_KEY, datasetIds);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
ReportTenantDataset.class.getSimpleName(),
TenantConstant.INSERT_TENANT_REPORT_DATASET_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void removeTenantRoleReportDataset(Long tenantRoleId, Long datasetId) {
SysTenantRoleReportDataset filter = new SysTenantRoleReportDataset();
filter.setTenantRoleId(tenantRoleId);
filter.setDatasetId(datasetId);
sysTenantRoleReportDatasetMapper.delete(new QueryWrapper<>(filter));
}
@Transactional(rollbackFor = Exception.class)
@Override
public void removeTenantRoleReportDatasetAndSync(Long tenantRoleId, Long datasetId) {
// 获取还有哪些其他租户角色关联了该报表数据集Id,得到租户角色Id列表。
// select * from zz_tenant_role_report_dataset where tenant_role_id != roleId and dataset_id = datasetId
LambdaQueryWrapper<SysTenantRoleReportDataset> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysTenantRoleReportDataset::getDatasetId, datasetId);
queryWrapper.ne(SysTenantRoleReportDataset::getTenantRoleId, tenantRoleId);
Set<Long> otherTenantRoleIds = sysTenantRoleReportDatasetMapper.selectList(queryWrapper)
.stream().map(SysTenantRoleReportDataset::getTenantRoleId).collect(Collectors.toSet());
Set<Long> resultTenantIdSet = this.filterTenantIdSet(tenantRoleId, otherTenantRoleIds);
this.removeTenantRoleReportDataset(tenantRoleId, datasetId);
if (CollUtil.isNotEmpty(resultTenantIdSet)) {
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(TENANT_ID_SET_KEY, resultTenantIdSet);
messageJsonData.put(REPORT_DATASET_ID_KEY, datasetId);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
ReportTenantDataset.class.getSimpleName(),
TenantConstant.DELETE_TENANT_REPORT_DATASET_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
}
@Override
public List<Long> getSysTenantRoleReportDatasetIdList(Long tenantRoleId) {
List<SysTenantRoleReportDataset> resultList = sysTenantRoleReportDatasetMapper.selectList(
new LambdaQueryWrapper<SysTenantRoleReportDataset>().eq(SysTenantRoleReportDataset::getTenantRoleId, tenantRoleId));
return resultList.stream().map(SysTenantRoleReportDataset::getDatasetId).collect(Collectors.toList());
}
@Override
public List<Long> getSysTenantRoleOnlinePageIdList(Long tenantRoleId) {
List<SysTenantRoleOnlinePage> resultList = sysTenantRoleOnlinePageMapper.selectList(
new LambdaQueryWrapper<SysTenantRoleOnlinePage>().eq(SysTenantRoleOnlinePage::getTenantRoleId, tenantRoleId));
return resultList.stream().map(SysTenantRoleOnlinePage::getPageId).collect(Collectors.toList());
}
@Override
public void addTenantRoleOnlinePageList(Long tenantRoleId, Set<Long> pageIds) {
List<SysTenantRoleOnlinePage> dataList = pageIds.stream().map(pageId -> {
SysTenantRoleOnlinePage data = new SysTenantRoleOnlinePage();
data.setTenantRoleId(tenantRoleId);
data.setPageId(pageId);
return data;
}).collect(Collectors.toList());
sysTenantRoleOnlinePageMapper.insertList(dataList);
List<Long> tenantIds = this.getSysTenantRoleTenantIdsByTenantRoleId(tenantRoleId);
if (CollUtil.isNotEmpty(tenantIds)) {
this.processAddTenantOnlinePageAndSync(tenantRoleId, tenantIds, pageIds);
}
}
@Override
public void removeTenantRoleOnlinePage(Long tenantRoleId, Long pageId) {
SysTenantRoleOnlinePage filter = new SysTenantRoleOnlinePage();
filter.setTenantRoleId(tenantRoleId);
filter.setPageId(pageId);
sysTenantRoleOnlinePageMapper.delete(new QueryWrapper<>(filter));
}
@Override
public void removeTenantRoleOnlinePageAndSync(Long tenantRoleId, Long pageId) {
// 获取还有哪些其他租户角色关联了该在线表单页面Id,得到租户角色Id列表。
LambdaQueryWrapper<SysTenantRoleOnlinePage> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SysTenantRoleOnlinePage::getPageId, pageId);
queryWrapper.ne(SysTenantRoleOnlinePage::getTenantRoleId, tenantRoleId);
Set<Long> otherTenantRoleIds = sysTenantRoleOnlinePageMapper.selectList(queryWrapper)
.stream().map(SysTenantRoleOnlinePage::getTenantRoleId).collect(Collectors.toSet());
Set<Long> resultTenantIdSet = this.filterTenantIdSet(tenantRoleId, otherTenantRoleIds);
this.removeTenantRoleOnlinePage(tenantRoleId, pageId);
if (CollUtil.isEmpty(resultTenantIdSet)) {
return;
}
List<Long> tenantPageIds = new LinkedList<>();
List<SysTenantExt> tenantExtList = this.getSysTenantExtListWithOnlinePageIds(resultTenantIdSet);
for (SysTenantExt tenantExt : tenantExtList) {
List<TenantOnlinePageIdMap> tenantOnlinePageIdMapList =
this.parseTenantExtOnlinePageIdMap(tenantExt.getTenantOnlinePageIds());
TenantOnlinePageIdMap foundData = tenantOnlinePageIdMapList.stream()
.filter(d -> d.getPageId().equals(pageId)).findFirst().orElse(null);
if (foundData != null) {
tenantPageIds.add(foundData.getTenantPageId());
tenantOnlinePageIdMapList.remove(foundData);
tenantExt.setTenantOnlinePageIds(JSON.toJSONString(tenantOnlinePageIdMapList));
sysTenantExtMapper.updateById(tenantExt);
}
}
if (CollUtil.isNotEmpty(tenantPageIds)) {
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(ONLINE_PAGE_ID_SET_KEY, tenantPageIds);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
OnlinePage.class.getSimpleName(),
TenantConstant.DELETE_TENANT_ONLINE_PAGE_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
}
private void processAddTenantOnlinePageAndSync(
Long tenantRoleId, Collection<Long> tenantIds, Collection<Long> pageIds) {
List<SysTenantExt> tenantExtList = this.getSysTenantExtListWithOnlinePageIds(tenantIds);
List<SysTenantExt> resultTenantExtList = new LinkedList<>();
for (SysTenantExt tenantExt : tenantExtList) {
List<TenantOnlinePageIdMap> tenantOnlinePageIdMapList =
this.parseTenantExtOnlinePageIdMap(tenantExt.getTenantOnlinePageIds());
List<TenantOnlinePageIdMap> resultList = new LinkedList<>(tenantOnlinePageIdMapList);
Map<Long, TenantOnlinePageIdMap> m =
tenantOnlinePageIdMapList.stream().collect(Collectors.toMap(TenantOnlinePageIdMap::getPageId, c -> c));
for (Long pageId : pageIds) {
if (!m.containsKey(pageId)) {
resultList.add(new TenantOnlinePageIdMap(pageId, idGenerator.nextLongId()));
}
}
if (resultList.size() != tenantOnlinePageIdMapList.size()) {
tenantExt.setTenantOnlinePageIds(JSON.toJSONString(resultList));
sysTenantExtMapper.updateById(tenantExt);
resultTenantExtList.add(tenantExt);
}
}
if (CollUtil.isNotEmpty(resultTenantExtList)) {
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(TENANT_EXT_LIST_KEY, tenantExtList);
messageJsonData.put(ONLINE_PAGE_ID_SET_KEY, pageIds);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
OnlinePage.class.getSimpleName(),
TenantConstant.INSERT_TENANT_ONLINE_PAGE_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
}
private void processRemoveTenantOnlinePageAndSync(Long tenantRoleId, Long tenantId, Set<Long> otherRoleIdSet) {
List<Long> pageIdSet = this.getSysTenantRoleOnlinePageIdList(tenantRoleId);
Set<Long> resultOnlinePageIdSet = this.filterTenantOnlinePageIdSet(new HashSet<>(pageIdSet), otherRoleIdSet);
if (CollUtil.isEmpty(resultOnlinePageIdSet)) {
return;
}
List<Long> tenantPageIds = new LinkedList<>();
SysTenantExt tenantExt = sysTenantExtMapper.selectById(tenantId);
List<TenantOnlinePageIdMap> tenantOnlinePageIdMapList =
this.parseTenantExtOnlinePageIdMap(tenantExt.getTenantOnlinePageIds());
for (Long pageId : resultOnlinePageIdSet) {
TenantOnlinePageIdMap foundData = tenantOnlinePageIdMapList.stream()
.filter(d -> d.getPageId().equals(pageId)).findFirst().orElse(null);
if (foundData != null) {
tenantPageIds.add(foundData.getTenantPageId());
tenantOnlinePageIdMapList.remove(foundData);
}
}
if (CollUtil.isNotEmpty(tenantPageIds)) {
tenantExt.setTenantOnlinePageIds(JSON.toJSONString(tenantOnlinePageIdMapList));
sysTenantExtMapper.updateById(tenantExt);
JSONObject messageJsonData = new JSONObject();
messageJsonData.put(ONLINE_PAGE_ID_SET_KEY, tenantPageIds);
dataSyncProducer.sendOrderly(
tenantRoleId,
applicationConfig.getTenantSyncTopic(),
OnlinePage.class.getSimpleName(),
TenantConstant.DELETE_TENANT_ONLINE_PAGE_COMMAND,
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
}
}
private List<TenantOnlinePageIdMap> parseTenantExtOnlinePageIdMap(String onlinePageIdMap) {
return StrUtil.isNotEmpty(onlinePageIdMap)
? JSON.parseArray(onlinePageIdMap, TenantOnlinePageIdMap.class) : new LinkedList<>();
}
private List<Long> getSysTenantRoleTenantIdsByTenantRoleId(Long tenantRoleId) {
SysTenantRoleTenant filter = new SysTenantRoleTenant();
filter.setTenantRoleId(tenantRoleId);
return sysTenantRoleTenantMapper.selectList(new QueryWrapper<>(filter))
.stream().map(SysTenantRoleTenant::getTenantId).collect(Collectors.toList());
}
private List<SysTenantExt> getSysTenantExtListWithOnlinePageIds(Collection<Long> tenantIds) {
LambdaQueryWrapper<SysTenantExt> qw = new LambdaQueryWrapper<>();
qw.select(SysTenantExt::getTenantId, SysTenantExt::getTenantOnlinePageIds);
qw.in(SysTenantExt::getTenantId, tenantIds);
return sysTenantExtMapper.selectList(qw);
}
private Set<Long> filterTenantIdSet(Long tenantRoleId, Set<Long> otherRoleIdList) {
Set<Long> otherRoleTenantIdSet = null;
if (CollUtil.isNotEmpty(otherRoleIdList)) {
// 从上一步返回的租户角色列表中,找出所有属于他们的租户。
// select * from zz_tenant_role_tenant where tenant_role_id in (otherRoleIdList)
LambdaQueryWrapper<SysTenantRoleTenant> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SysTenantRoleTenant::getTenantRoleId, otherRoleIdList);
otherRoleTenantIdSet = sysTenantRoleTenantMapper.selectList(queryWrapper)
.stream().map(SysTenantRoleTenant::getTenantId).collect(Collectors.toSet());
}
// 获取当前租户角色的租户列表。因为在外部已经判断过了,当前租户角色是包含租户的
SysTenantRoleTenant tenantRoleTenant = new SysTenantRoleTenant();
tenantRoleTenant.setTenantRoleId(tenantRoleId);
Set<Long> tenantIdSet = sysTenantRoleTenantMapper.selectList(new QueryWrapper<>(tenantRoleTenant))
.stream().map(SysTenantRoleTenant::getTenantId).collect(Collectors.toSet());
Set<Long> resultTenantIdSet = tenantIdSet;
if (CollUtil.isNotEmpty(otherRoleTenantIdSet)) {
// 遍历当前租户Id列表,所有出现在 otherRoleTenantIdSet 集合中的tenantId,都不能删除他们对该菜单的可见性。
resultTenantIdSet = new HashSet<>();
for (Long tenantId : tenantIdSet) {
if (!CollUtil.contains(otherRoleTenantIdSet, tenantId)) {
resultTenantIdSet.add(tenantId);
}
}
}
return resultTenantIdSet;
}
private Set<Long> filterTenantOnlinePageIdSet(Set<Long> onlinePageIdSet, Set<Long> otherRoleIdSet) {
Set<Long> otherPageIdSet = null;
if (CollUtil.isNotEmpty(otherRoleIdSet)) {
LambdaQueryWrapper<SysTenantRoleOnlinePage> qw = new LambdaQueryWrapper<>();
qw.in(SysTenantRoleOnlinePage::getTenantRoleId, otherRoleIdSet);
otherPageIdSet = sysTenantRoleOnlinePageMapper.selectList(qw)
.stream().map(SysTenantRoleOnlinePage::getPageId).collect(Collectors.toSet());
}
Set<Long> resultPageIdSet = onlinePageIdSet;
if (CollUtil.isNotEmpty(otherPageIdSet)) {
resultPageIdSet = new HashSet<>();
for (Long pageId : onlinePageIdSet) {
if (!CollUtil.contains(otherPageIdSet, pageId)) {
resultPageIdSet.add(pageId);
}
}
}
return resultPageIdSet;
}
private Set<Long> filterTenantReportDatasetIdSet(Set<Long> reportDatasetIdSet, Set<Long> otherRoleIdSet) {
Set<Long> otherDatasetIdSet = null;
if (CollUtil.isNotEmpty(otherRoleIdSet)) {
LambdaQueryWrapper<SysTenantRoleReportDataset> qw = new LambdaQueryWrapper<>();
qw.in(SysTenantRoleReportDataset::getTenantRoleId, otherRoleIdSet);
otherDatasetIdSet = sysTenantRoleReportDatasetMapper.selectList(qw)
.stream().map(SysTenantRoleReportDataset::getDatasetId).collect(Collectors.toSet());
}
Set<Long> resultDatasetIdSet = reportDatasetIdSet;
if (CollUtil.isNotEmpty(otherDatasetIdSet)) {
resultDatasetIdSet = new HashSet<>();
for (Long datasetId : reportDatasetIdSet) {
if (!CollUtil.contains(otherDatasetIdSet, datasetId)) {
resultDatasetIdSet.add(datasetId);
}
}
}
return resultDatasetIdSet;
}
private Set<Long> filterTenantMenuIdSet(Set<Long> menuIdSet, Set<Long> otherRoleIdSet) {
Set<Long> otherMenuIdSet = null;
if (CollUtil.isNotEmpty(otherRoleIdSet)) {
// 获取当前租户所属其他其他租户角色的菜单Id集合。
// select menu_id from zz_tenant_role_menu where tenant_role_id in (otherTenantRoleIdSet)
LambdaQueryWrapper<SysTenantRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(SysTenantRoleMenu::getTenantRoleId, otherRoleIdSet);
otherMenuIdSet = sysTenantRoleMenuMapper.selectList(queryWrapper)
.stream().map(SysTenantRoleMenu::getMenuId).collect(Collectors.toSet());
}
Set<Long> resultMenuIdSet = menuIdSet;
if (CollUtil.isNotEmpty(otherMenuIdSet)) {
resultMenuIdSet = new HashSet<>();
for (Long menuId : menuIdSet) {
if (!CollUtil.contains(otherMenuIdSet, menuId)) {
resultMenuIdSet.add(menuId);
}
}
}
return resultMenuIdSet;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
static class TenantOnlinePageIdMap {
private Long pageId;
private Long tenantPageId;
}
}

245
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/service/impl/SysTenantServiceImpl.java

@ -0,0 +1,245 @@ @@ -0,0 +1,245 @@
package apelet.tenantadmin.tenant.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import apelet.common.core.base.dao.BaseDaoMapper;
import apelet.common.core.base.service.BaseService;
import apelet.common.core.annotation.MyDataSource;
import apelet.common.core.constant.GlobalDeletedFlag;
import apelet.common.core.object.MyRelationParam;
import apelet.common.core.util.MyModelUtil;
import apelet.common.datasync.constant.DataSyncCommandType;
import apelet.common.datasync.producer.DataSyncRocketMqProducer;
import apelet.common.sequence.wrapper.IdGeneratorWrapper;
import apelet.common.tenant.constant.TenantConstant;
import apelet.tenantadmin.config.ApplicationConfig;
import apelet.tenantadmin.tenant.dao.SysTenantExtMapper;
import apelet.tenantadmin.tenant.dao.SysTenantMapper;
import apelet.tenantadmin.tenant.dao.SysTenantRoleTenantMapper;
import apelet.tenantadmin.tenant.model.SysTenant;
import apelet.tenantadmin.tenant.model.SysTenantExt;
import apelet.tenantadmin.tenant.model.SysTenantMenu;
import apelet.tenantadmin.tenant.model.SysTenantRoleTenant;
import apelet.tenantadmin.tenant.service.SysTenantMenuService;
import apelet.tenantadmin.tenant.service.SysTenantService;
import apelet.tenantadmin.config.DataSourceType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
/**
* 租户数据服务类
*
* @author guifc
* @date 2023-08-04
*/
@Slf4j
@MyDataSource(DataSourceType.TENANT_ADMIN)
@Service("sysTenantService")
public class SysTenantServiceImpl extends BaseService<SysTenant, Long> implements SysTenantService {
@Autowired
private SysTenantMapper sysTenantMapper;
@Autowired
private SysTenantExtMapper sysTenantExtMapper;
@Autowired
private SysTenantRoleTenantMapper sysTenantRoleTenantMapper;
@Autowired
private SysTenantMenuService sysTenantMenuService;
@Autowired
private IdGeneratorWrapper idGenerator;
@Autowired
private DataSyncRocketMqProducer dataSyncProducer;
@Autowired
private ApplicationConfig applicationConfig;
/**
* 返回主对象的Mapper对象
*
* @return 主对象的Mapper对象
*/
@Override
protected BaseDaoMapper<SysTenant> mapper() {
return sysTenantMapper;
}
/**
* 填充租户实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地新增操作事务的结果
*
* @param sysTenant 新增的租户实体对象
* @return 新增数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public SysTenant saveNew(SysTenant sysTenant) {
sysTenant.setTenantId(idGenerator.nextLongId());
sysTenant.setAvailable(true);
sysTenant.setDeletedFlag(GlobalDeletedFlag.NORMAL);
MyModelUtil.fillCommonsForInsert(sysTenant);
sysTenantMapper.insert(sysTenant);
SysTenantExt tenantExt = new SysTenantExt();
tenantExt.setTenantId(sysTenant.getTenantId());
sysTenantExtMapper.insert(tenantExt);
List<SysTenantMenu> menuList = sysTenantMenuService.getAllList();
JSONObject messageJsonData = this.makeMessageData(sysTenant);
if (CollUtil.isNotEmpty(menuList)) {
messageJsonData.put("menuList", menuList);
}
dataSyncProducer.sendOrderly(
sysTenant.getTenantId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.INSERT.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return sysTenant;
}
/**
* 填充租户实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地更新操作事务的结果
*
* @param sysTenant 更新的租户对象
* @param originalSysTenant 原有的租户对象
* @return 更新数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean update(SysTenant sysTenant, SysTenant originalSysTenant) {
MyModelUtil.fillCommonsForUpdate(sysTenant, originalSysTenant);
UpdateWrapper<SysTenant> updateWrapper =
this.createUpdateQueryForNullValue(sysTenant, sysTenant.getTenantId());
if (sysTenantMapper.update(sysTenant, updateWrapper) == 0) {
return false;
}
JSONObject messageJsonData = this.makeMessageData(sysTenant);
dataSyncProducer.sendOrderly(
sysTenant.getTenantId(),
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.UPDATE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 填充租户实体对象中的数据并发送消息到RocketMQ同步远程数据
* 同时等待本地删除操作事务的结果
*
* @param sysTenant 租户实体对象
* @return 删除数据操作和同步发送消息的结果
*/
@Transactional(rollbackFor = Exception.class)
@Override
public boolean remove(SysTenant sysTenant) {
Long tenantId = sysTenant.getTenantId();
if (!this.removeById(tenantId)) {
return false;
}
sysTenantExtMapper.deleteById(sysTenant.getTenantId());
SysTenantRoleTenant tenantRoleTenant = new SysTenantRoleTenant();
tenantRoleTenant.setTenantId(tenantId);
sysTenantRoleTenantMapper.delete(new QueryWrapper<>(tenantRoleTenant));
JSONObject messageJsonData = this.makeMessageData(sysTenant);
dataSyncProducer.sendOrderly(
tenantId,
applicationConfig.getTenantSyncTopic(),
modelClass.getSimpleName(),
DataSyncCommandType.DELETE.name(),
messageJsonData.toJSONString(),
TenantConstant.MESSAGE_QUEUE_SELECTOR_KEY);
return true;
}
/**
* 获取租户列表及其关联数据
*
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序参数
* @return 查询结果列表
*/
@Override
public List<SysTenant> getSysTenantList(SysTenant sysTenantFilter, String orderBy) {
List<SysTenant> sysTenantList = sysTenantMapper.getSysTenantList(sysTenantFilter, orderBy);
this.buildRelationForDataList(sysTenantList, MyRelationParam.dictOnly());
return sysTenantList;
}
/**
* 根据租户角色Id获取关联的租户从表中没有和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序字符串order by从句的参数
* @return 与主表没有建立关联的租户数据列表
*/
@Override
public List<SysTenant> getNotInSysTenantListByRoleId(
Long tenantRoleId, SysTenant sysTenantFilter, String orderBy) {
return sysTenantMapper.getNotInSysTenantListByRoleId(tenantRoleId, sysTenantFilter, orderBy);
}
/**
* 根据租户角色Id获取关联的租户从表中和主表建立关联关系的数据列表
*
* @param tenantRoleId 关联租户角色Id
* @param sysTenantFilter 租户过滤对象
* @param orderBy 排序字符串order by从句的参数
* @return 与主表建立关联的租户数据列表
*/
@Override
public List<SysTenant> getSysTenantListByRoleId(
Long tenantRoleId, SysTenant sysTenantFilter, String orderBy) {
return sysTenantMapper.getSysTenantListByRoleId(tenantRoleId, sysTenantFilter, orderBy);
}
/**
* 查询租户的权限资源地址列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param url url过滤条件
* @return 包含从租户到权限资源的完整权限分配路径信息的查询结果列表
*/
@Override
public List<Map<String, Object>> getSysTenantPermListWithDetail(Long tenantId, String url) {
return sysTenantMapper.getSysTenantPermListWithDetail(tenantId, url);
}
/**
* 查询租户的权限字列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param permCode 权限字名称过滤条件
* @return 包含从租户到权限字的权限分配路径信息的查询结果列表
*/
@Override
public List<Map<String, Object>> getSysTenantPermCodeListWithDetail(Long tenantId, String permCode) {
return sysTenantMapper.getSysTenantPermCodeListWithDetail(tenantId, permCode);
}
/**
* 查询租户的菜单列表同时返回详细的分配路径
*
* @param tenantId 租户Id
* @param menuName 菜单名称过滤条件
* @return 包含从租户到菜单的权限分配路径信息的查询结果列表
*/
@Override
public List<Map<String, Object>> getSysTenantMenuListWithDetail(Long tenantId, String menuName) {
return sysTenantMapper.getSysTenantMenuListWithDetail(tenantId, menuName);
}
private JSONObject makeMessageData(SysTenant sysTenant) {
JSONObject messageJsonData = new JSONObject();
messageJsonData.put("sysTenant", sysTenant);
return messageJsonData;
}
}

129
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/test/Tt.java

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
package apelet.tenantadmin.tenant.test;
import javassist.*;
import java.lang.reflect.Method;
public class Tt {
/*
public static void main3(String[] args) throws Exception {
// 创建一个新的类池
ClassPool pool = ClassPool.getDefault();
// 创建一个新的类
CtClass ctClass = pool.makeClass("MyClass");
// 定义方法签名
CtClass stringType = pool.get("java.lang.String");
CtClass listType = pool.get("java.util.List");
CtClass mapType = pool.get("java.util.Map");
CtClass hashMapType = pool.get("java.util.HashMap");
CtClass objectType = pool.get("java.lang.Object");
// 创建方法参数类型数组
CtClass[] parameterTypes = new CtClass[]{pool.get("java.lang.Double"), pool.get("java.lang.Double")};
// 创建方法返回类型
CtClass returnType = mapType;
// 创建方法
CtMethod newMethod = new CtMethod(pool.get("java.lang.Double"), "processList", parameterTypes, ctClass);
// 添加方法体
String body = "{"
+ " Double d = $1 + $2;"
+ "return d;"
+ "}";
newMethod.setBody(body);
// 将方法添加到类中
ctClass.addMethod(newMethod);
// 加载并执行代码
Class<?> clazz = ctClass.toClass();
Object instance = clazz.newInstance();
Method method = clazz.getMethod("processList", Double.class, Double.class);
double keys = 12.0;
double values = 12.0;
Object o = method.invoke(instance, new Object[]{keys, values});
System.out.println("Result: " + o);
}
public static void main2(String[] args) throws Exception {
// 创建一个新的类池
javassist.ClassPool pool = javassist.ClassPool.getDefault();
// 创建一个新的类
javassist.CtClass ctClass = pool.makeClass("MyClass");
// 定义方法签名
javassist.CtClass stringType = pool.get("java.lang.String");
javassist.CtClass listType = pool.get("java.util.List");
javassist.CtClass mapType = pool.get("java.util.Map");
javassist.CtClass hashMapType = pool.get("java.util.HashMap");
javassist.CtClass objectType = pool.get("java.lang.Object");
// 创建方法参数类型数组
javassist.CtClass[] parameterTypes = new javassist.CtClass[]{stringType, listType};
// 创建方法返回类型
javassist.CtClass returnType = mapType;
// 创建方法
javassist.CtMethod newMethod = new javassist.CtMethod(returnType, "processList", parameterTypes, ctClass);
// 添加方法体
newMethod.setBody("{"
+ " java.util.Map resultMap = new java.util.HashMap();"
+ " String[] arr = $1.toString().split(\",\"); "
+ " java.util.List list = new java.util.ArrayList();"
+ " for(int i=0; i<$2.size(); i++){"
+ " resultMap.put(arr[i] , $2.get(i));"
+ " System.out.println(\"Result: \" + resultMap);"
+ " }"
+ " return resultMap;"
+ " }");
// 将方法添加到类中
ctClass.addMethod(newMethod);
// 加载并执行代码
Class<?> clazz = ctClass.toClass();
Object instance = clazz.newInstance();
Class[] classes = {String.class, List.class};
Method method = clazz.getDeclaredMethod("processList", classes);
List<String> inputList = Arrays.asList("item1", "item2", "item3");
Map<String, Object> resultMap = (Map<String, Object>) method.invoke(instance, new Object[]{"key1,key2,key3", inputList});
System.out.println("Result: " + resultMap);
}
*/
public static void main(String[] args) throws Exception {
// 创建一个 ClassPool 对象
ClassPool pool = ClassPool.getDefault();
// 创建一个空的 CtClass 对象,表示要生成的类
CtClass ctClass = pool.makeClass("MyCustomClass");
// 定义方法签名
// CtMethod method = CtNewMethod.make(
// "public double multiply(double a, double b) { return a * b; }",
// ctClass);
CtClass[] parameters = new CtClass[2];
parameters[0] = CtClass.doubleType;
parameters[1] = CtClass.doubleType;
CtMethod method = new CtMethod(
CtClass.doubleType, // 返回值类型
"multiply", // 方法名称
parameters , // 方法参数
ctClass);
method.setBody("{ return $1 * $2; }");
// 将方法添加到类中
ctClass.addMethod(method);
// 将生成的类写入文件
ctClass.writeFile("output/");
// 加载生成的类
Class<?> clazz = ctClass.toClass();
// 实例化类
Object instance = clazz.newInstance();
// 获取方法并执行
Method m = clazz.getMethod("multiply", double.class, double.class);
Object invoke = m.invoke(instance, 3.0, 4.0);
System.out.println("Result: " + invoke); // 输出:Result: 12.0
}
}

21
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/DeployPluginVo.java

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
package apelet.tenantadmin.tenant.vo;
import apelet.tenantadmin.tenant.model.DeployPlugin;
import lombok.Data;
import java.io.Serializable;
/**
* <p>
* 自定义模板
* 热部署插件表
* </p>
*
* @author admin
* @since 2024-06-27 14:58:01
*/
@Data
public class DeployPluginVo extends DeployPlugin implements Serializable {
private static final long serialVersionUID = 1L;
}

72
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantDatasourceVo.java

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
package apelet.tenantadmin.tenant.vo;
import apelet.common.core.base.vo.BaseVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* 租户数据源Vo对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户数据源Vo对象")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysTenantDatasourceVo extends BaseVo {
/**
* 租户数据源Id
*/
@Schema(description = "租户数据源Id")
private Long datasourceId;
/**
* 租户数据源名称
*/
@Schema(description = "租户数据源名称")
private String datasourceName;
/**
* 租户所在数据源的类型值
*/
@Schema(description = "租户所在数据源的类型值")
private Integer datasourceType;
/**
* 主机名
*/
@Schema(description = "主机名")
private String databaseHost;
/**
* 端口号
*/
@Schema(description = "端口号")
private Integer port;
/**
* 用户名
*/
@Schema(description = "用户名")
private String username;
/**
* 密码
*/
@Schema(description = "密码")
private String password;
/**
* 模式名
*/
@Schema(description = "模式名")
private String schemaName;
/**
* 数据库名
*/
@Schema(description = "数据库名")
private String databaseName;
}

93
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantMenuVo.java

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
package apelet.tenantadmin.tenant.vo;
import apelet.common.core.base.vo.BaseVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
import java.util.Map;
/**
* 租户菜单资源VO对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户菜单资源VO对象")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysTenantMenuVo extends BaseVo {
/**
* 租户菜单Id
*/
@Schema(description = "租户菜单Id")
private Long menuId;
/**
* 菜单显示名称
*/
@Schema(description = "菜单显示名称")
private String menuName;
/**
* 菜单类型(0: 目录 1: 菜单 2: 按钮 3: UI片段)
*/
@Schema(description = "菜单类型(0: 目录 1: 菜单 2: 按钮 3: UI片段)")
private Integer menuType;
/**
* 父菜单Id目录菜单的父菜单为null
*/
@Schema(description = "父菜单Id")
private Long parentId;
/**
* 前端表单路由名称仅用于menu_type为1的菜单类型
*/
@Schema(description = "前端表单路由名称")
private String formRouterName;
/**
* 统计页面主键Id仅用于统计页面绑定的菜单
*/
@Schema(description = "统计页面主键Id")
private Long reportPageId;
/**
* 在线表单主键Id仅用于在线表单绑定的菜单
*/
@Schema(description = "在线表单主键Id")
private Long onlineFormId;
/**
* 在线表单菜单的权限控制类型具体值可参考SysOnlineMenuPermType常量对象
*/
@Schema(description = "在线表单菜单的权限控制类型")
private Integer onlineMenuPermType;
/**
* 菜单显示顺序 (值越小排序越靠前)
*/
@Schema(description = "菜单显示顺序")
private Integer showOrder;
/**
* 菜单图标
*/
@Schema(description = "菜单图标")
private String icon;
/**
* 附加信息
*/
@Schema(description = "附加信息")
private String extraData;
/**
* 菜单与权限字关联对象列表
*/
@Schema(description = "菜单与权限字关联对象列表")
private List<Map<String, Object>> sysMenuPermCodeList;
}

63
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantPermCodeVo.java

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
package apelet.tenantadmin.tenant.vo;
import apelet.common.core.base.vo.BaseVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
import java.util.Map;
/**
* 租户权限字VO对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户权限字VO对象")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysTenantPermCodeVo extends BaseVo {
/**
* 租户权限字Id
*/
@Schema(description = "租户权限字Id")
private Long permCodeId;
/**
* 上级权限字Id
*/
@Schema(description = "上级权限字Id")
private Long parentId;
/**
* 租户权限字标识(一般为有含义的英文字符串)
*/
@Schema(description = "租户权限字标识")
private String permCode;
/**
* 租户权限类型(0: 表单 1: UI片段 2: 操作)
*/
@Schema(description = "租户权限类型")
private Integer permCodeType;
/**
* 租户权限字显示顺序(数值越小越靠前)
*/
@Schema(description = "租户权限字显示顺序")
private Integer showOrder;
/**
* 租户权限字显示名称
*/
@Schema(description = "租户权限字显示名称")
private String showName;
/**
* 权限字与权限资源关联对象列表
*/
@Schema(description = "权限字与权限资源关联对象列表")
private List<Map<String, Object>> sysPermCodePermList;
}

57
application-tenant/tenant-admin/src/main/java/apelet/tenantadmin/tenant/vo/SysTenantPermModuleVo.java

@ -0,0 +1,57 @@ @@ -0,0 +1,57 @@
package apelet.tenantadmin.tenant.vo;
import apelet.common.core.base.vo.BaseVo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.List;
import java.util.Map;
/**
* 租户权限模块VO对象
*
* @author guifc
* @date 2023-08-04
*/
@Schema(description = "租户权限模块VO对象")
@Data
@EqualsAndHashCode(callSuper = true)
public class SysTenantPermModuleVo extends BaseVo {
/**
* 租户权限模块Id
*/
@Schema(description = "租户权限模块Id")
private Long moduleId;
/**
* 上级权限模块Id
*/
@Schema(description = "上级权限模块Id")
private Long parentId;
/**
* 租户权限模块名称
*/
@Schema(description = "租户权限模块名称")
private String moduleName;
/**
* 租户权限模块类型(0: 普通模块 1: Controller模块)
*/
@Schema(description = "租户权限模块类型")
private Integer moduleType;
/**
* 权限模块在当前层级下的顺序由小到大
*/
@Schema(description = "权限模块在当前层级下的顺序")
private Integer showOrder;
/**
* 权限资源对象列表
*/
@Schema(description = "权限资源对象列表")
private List<Map<String, Object>> sysPermList;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save