commit
a817943dde
305 changed files with 27779 additions and 0 deletions
@ -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> |
||||
@ -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> |
||||
@ -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); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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() { |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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/**"); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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()); |
||||
} |
||||
|
||||
} |
||||
@ -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(); |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -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)); |
||||
} |
||||
} |
||||
@ -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)); |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
} |
||||
@ -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)); |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
} |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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); |
||||
|
||||
} |
||||
@ -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> { |
||||
} |
||||
@ -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> { |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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> { |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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> { |
||||
} |
||||
@ -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(); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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 >= #{sysTenantFilter.createTimeStart} |
||||
</if> |
||||
<if test="sysTenantFilter.createTimeEnd != null and sysTenantFilter.createTimeEnd != ''"> |
||||
AND xy_sys_tenant.create_time <= #{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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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> |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
} |
||||
@ -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(""); |
||||
} |
||||
} |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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); |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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; |
||||
} |
||||
} |
||||
@ -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
|
||||
} |
||||
|
||||
} |
||||
@ -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; |
||||
|
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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; |
||||
} |
||||
@ -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…
Reference in new issue