Initial commit all

develop
Hoshi 2024-08-20 17:57:30 +08:00
parent 9ba4f3027d
commit c063b1a0ec
316 changed files with 37410 additions and 0 deletions
bocloud.sms.booter
src/main
java/com/bocloud/sms/booter

228
bocloud.sms.booter/pom.xml Normal file
View File

@ -0,0 +1,228 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>bocloud.sms</artifactId>
<groupId>com.bocloud</groupId>
<version>6.5.0-LTS-SZ</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>bocloud.sms.booter</artifactId>
<version>${bocloud.booter.version}</version>
<dependencies>
<dependency>
<groupId>jakarta.platform</groupId>
<artifactId>jakarta.jakartaee-api</artifactId>
<version>10.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.7</version>
</dependency>
<!-- Spring boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Bocloud相关配置 -->
<dependency>
<groupId>com.bocloud</groupId>
<artifactId>bocloud.sms.service</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.bocloud</groupId>
<artifactId>bocloud.boot.common</artifactId>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.bocloud</groupId>
<artifactId>bocloud.cmp.core</artifactId>
<version>${bocloud.core.version}</version>
</dependency>
<dependency>
<groupId>com.freedom</groupId>
<artifactId>megatron.microservice</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
</dependency>
<dependency>
<groupId>jakarta.websocket</groupId>
<artifactId>jakarta.websocket-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.23.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<parameters>true</parameters>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<archive>
<manifest>
<mainClass>com.bocloud.sms.booter.Application</mainClass>
<addClasspath>true</addClasspath>
<useUniqueVersions>false</useUniqueVersions>
<classpathPrefix>libs/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<type>jar</type>
<includeTypes>jar</includeTypes>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- <plugin>-->
<!-- <groupId>com.gitee.starblues</groupId>-->
<!-- <artifactId>spring-brick-maven-packager</artifactId>-->
<!-- <version>${spring-brick.version}</version>-->
<!-- <configuration>-->
<!-- <mode>dev</mode>-->
<!-- <mainConfig>-->
<!-- <mainClass>com.bocloud.sms.booter.Application</mainClass>-->
<!-- </mainConfig>-->
<!-- </configuration>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <goals>-->
<!-- <goal>repackage</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
</plugins>
</build>
<profiles>
<profile>
<id>bocloud.booter.tomcat</id>
<properties>
<bocloud.booter.version>6.5.0-LTS-SZ</bocloud.booter.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</profile>
<profile>
<id>bocloud.booter.tongweb</id>
<properties>
<bocloud.booter.version>6.5.0-LTS-SZ-TONGWEB</bocloud.booter.version>
</properties>
<dependencies>
<dependency>
<groupId>com.tongweb</groupId>
<artifactId>tongweb-embed</artifactId>
<version>7.0.E.2</version>
</dependency>
<dependency>
<groupId>com.tongweb.springboot</groupId>
<artifactId>tongweb-spring-boot-starter</artifactId>
<version>2.x.0.RELEASE</version>
</dependency>
<dependency>
<groupId>com.tongweb.springboot</groupId>
<artifactId>tongweb-spring-boot-websocket</artifactId>
<version>2.x.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</profile>
</profiles>
</project>

View File

@ -0,0 +1,20 @@
package com.bocloud.sms.booter;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
* @author dmw
*/
@EnableRabbit
@EnableScheduling
@SpringBootApplication
@ComponentScan(value = {"com.bocloud", "com.megatron"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,222 @@
package com.bocloud.sms.booter.config;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import com.bocloud.sms.entity.ApiToken;
import com.bocloud.sms.entity.Role;
import com.bocloud.sms.entity.Tenant;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.entity.UserGroup;
import com.bocloud.sms.repository.ApiTokenRepository;
import com.bocloud.sms.repository.RoleRepository;
import com.bocloud.sms.repository.TenantRepository;
import com.bocloud.sms.repository.UserGroupRepository;
import com.bocloud.sms.repository.UserRepository;
import com.megatron.common.model.RequestContext;
import lombok.extern.slf4j.Slf4j;
/**
* @author tyl
* @since 2020/3/25 14:06
*/
@Component
@Slf4j
public class AccountCache implements InitializingBean {
private final StringRedisTemplate redisTemplate;
private final TenantRepository tenantRepository;
private final UserRepository userRepository;
private final RoleRepository roleRepository;
private final UserGroupRepository userGroupRepository;
private final ApiTokenRepository apiTokenRepository;
private final ThreadPoolTaskExecutor taskExecutor;
public AccountCache(StringRedisTemplate redisTemplate, TenantRepository tenantRepository,
UserRepository userRepository, RoleRepository roleRepository, UserGroupRepository userGroupRepository,
ApiTokenRepository apiTokenRepository, ThreadPoolTaskExecutor taskExecutor) {
this.redisTemplate = redisTemplate;
this.tenantRepository = tenantRepository;
this.userRepository = userRepository;
this.roleRepository = roleRepository;
this.userGroupRepository = userGroupRepository;
this.apiTokenRepository = apiTokenRepository;
this.taskExecutor = taskExecutor;
}
public void putAccountCache(RequestContext.Catalog catalog, Long id, String account) {
String key = catalog.name() + "_" + id;
this.redisTemplate.opsForValue().set(key, account);
}
public void putNameCache(RequestContext.Catalog catalog, Long id, String name) {
String key = catalog.name() + "_Name_" + id;
this.redisTemplate.opsForValue().set(key, name);
}
public void putRoleCache(Long id, String name) {
this.redisTemplate.opsForValue().set("Role_Name_" + id, name);
}
public void putUserGroupCache(Long id, String name) {
this.redisTemplate.opsForValue().set("Group_Name_" + id, name);
}
public void putApiTokenCache(String token, String apis) {
this.redisTemplate.opsForValue().set("Api_Token_" + token, apis);
}
/**
*
*
* @param id
* id
* @return
*/
public String getUserAccount(Long id) {
return redisTemplate.opsForValue().get(RequestContext.Catalog.User.name() + "_" + id);
}
/**
*
*
* @param id
* id
* @return
*/
public String getUserName(Long id) {
return redisTemplate.opsForValue().get(RequestContext.Catalog.User.name() + "_Name_" + id);
}
/**
*
*
* @param id
* id
* @return
*/
public String getTenantAccount(Long id) {
return redisTemplate.opsForValue().get(RequestContext.Catalog.Tenant.name() + "_" + id);
}
/**
*
*
* @param id
* id
* @return
*/
public String getTenantName(Long id) {
return redisTemplate.opsForValue().get(RequestContext.Catalog.Tenant.name() + "_Name_" + id);
}
/**
*
*
* @param id
* id
* @return
*/
public String getRoleName(Long id) {
return redisTemplate.opsForValue().get("Role_Name_" + id);
}
/**
*
*
* @param id
* id
* @return
*/
public String getUserGroupName(Long id) {
return redisTemplate.opsForValue().get("Group_Name_" + id);
}
public String getApiToken(String api) {
return redisTemplate.opsForValue().get("Api_Token_" + api);
}
@Override
public void afterPropertiesSet() {
taskExecutor.execute(this::addTenantCache);
taskExecutor.execute(this::addUserCache);
taskExecutor.execute(this::addRoleCache);
taskExecutor.execute(this::addUserGroupCache);
taskExecutor.execute(this::addApiTokenCache);
}
public void addTenantCache() {
try {
List<Tenant> tenants = tenantRepository.listAll();
// 缓存租户账号和租户名
for (Tenant tenant : tenants) {
if (!tenant.getDeleted()) {
putAccountCache(RequestContext.Catalog.Tenant, tenant.getId(), tenant.getAccount());
}
putNameCache(RequestContext.Catalog.Tenant, tenant.getId(), tenant.getName());
}
} catch (Exception e) {
log.error("put tenant cache error,", e);
}
}
public void addUserCache() {
try {
List<User> users = userRepository.listAll();
// 缓存用户账号和用户名
for (User user : users) {
if (!user.getDeleted()) {
putAccountCache(RequestContext.Catalog.User, user.getId(), user.getAccount());
}
putNameCache(RequestContext.Catalog.User, user.getId(), user.getName());
}
} catch (Exception e) {
log.error("put user cache error,", e);
}
}
public void addRoleCache() {
try {
List<Role> roles = roleRepository.list();
// 缓存角色名
for (Role role : roles) {
putRoleCache(role.getId(), role.getName());
}
} catch (Exception e) {
log.error("put role cache error,", e);
}
}
public void addUserGroupCache() {
try {
List<UserGroup> groups = userGroupRepository.list();
// 缓存角色名
for (UserGroup group : groups) {
putUserGroupCache(group.getId(), group.getName());
}
} catch (Exception e) {
log.error("put user group cache error,", e);
}
}
public void addApiTokenCache() {
try {
List<ApiToken> tokens = apiTokenRepository.listAll();
// 缓存角色名
for (ApiToken token : tokens) {
if (!token.getEnabled()) {
continue;
}
putApiTokenCache(token.getToken(), token.getApis());
}
} catch (Exception e) {
log.error("put api token cache error,", e);
}
}
}

View File

@ -0,0 +1,63 @@
package com.bocloud.sms.booter.config;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.sms.entity.Dictionary;
import com.bocloud.sms.interfaces.DictService;
import lombok.extern.slf4j.Slf4j;
/**
* @author tyl
* @since 2020/3/25 14:06
*/
@Component
@Slf4j
public class DictCache implements InitializingBean {
private final StringRedisTemplate redisTemplate;
private final DictService dictService;
private final ThreadPoolTaskExecutor taskExecutor;
public DictCache(StringRedisTemplate redisTemplate, DictService dictService, ThreadPoolTaskExecutor taskExecutor) {
this.redisTemplate = redisTemplate;
this.dictService = dictService;
this.taskExecutor = taskExecutor;
}
public void putCache(String code, String value) {
String key = Dictionary.class.getSimpleName() + "_" + code;
this.redisTemplate.opsForValue().set(key, value);
}
@Override
public void afterPropertiesSet() {
taskExecutor.execute(this::addOsNamesCache);
taskExecutor.execute(this::addDataCenterCache);
}
public void addOsNamesCache() {
try {
List<String> list = dictService.getAllOsName();
putCache("OS_CATEGORY_TASK", JSONObject.toJSONString(list));
} catch (Exception e) {
log.error("put os name cache error,", e);
}
}
public void addDataCenterCache() {
try {
Map<String,String> map = dictService.getAllDataCenter();
putCache("DATA_CENTER", JSONObject.toJSONString(map));
} catch (Exception e) {
log.error("put data center cache error,", e);
}
}
}

View File

@ -0,0 +1,155 @@
package com.bocloud.sms.booter.config;
import com.bocloud.cmp.boot.model.BoCloudExchange;
import com.bocloud.cmp.core.encrypt.AbstractEncryptHandler;
import com.bocloud.sms.booter.listener.BocloudMessageListener;
import com.megatron.common.utils.IDFactory;
import com.megatron.common.utils.MapTools;
import com.megatron.framework.core.CurrentService;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import java.util.Map;
/**
* rabbitmq
*
* @author wangyu
* @version 1.0
* @since 2018330
*/
@Configuration
public class RabbitMQConfiguration {
private final ConnectionFactory connectionFactory;
private final Map<String, Object> arguments = MapTools.simpleMap("x-ha-policy", "all");
public RabbitMQConfiguration(ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
/**
*
*
* @return
*/
@Bean
public TopicExchange topicExchange() {
return new TopicExchange(BoCloudExchange.Default.TOPIC.getExchange(), true, true);
}
/**
*
*
* @return
*/
@Bean
public DirectExchange defaultExchange() {
return new DirectExchange(BoCloudExchange.Default.DIRECT.getExchange(), true, true);
}
@Bean
public Binding bindingMessageQueue(CurrentService service) {
return BindingBuilder.bind(declareMessageQueue(service)).to(topicExchange()).with("bocloud.message.queue.#");
}
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
@Bean
public Queue declareMessageQueue(CurrentService service) {
return new Queue("bocloud.message.queue.sms." + service.getToken(), true, false, true, arguments);
}
/**
*
*
* @return
*/
@Bean
public Queue declareLogQueue() {
return new Queue("bocloud.log.queue", true, false, false, arguments);
}
/**
*
*
* @return
*/
@Bean
public Queue declareNoticeQueue() {
return new Queue("event.notice.queue", true, false, false, arguments);
}
@Bean
public Binding bindingNoticeQueue() {
return BindingBuilder.bind(declareNoticeQueue()).to(defaultExchange()).withQueueName();
}
@Bean
public Binding bindingLogQueue() {
return BindingBuilder.bind(declareLogQueue()).to(defaultExchange()).withQueueName();
}
@Bean
@ConditionalOnBean(AbstractEncryptHandler.class)
public Queue declareLicenseInstallQueue() {
return new Queue("license.install.queue." + IDFactory.instance().uuid(), true, false, true, arguments);
}
@Bean
@ConditionalOnBean(AbstractEncryptHandler.class)
public Binding bindLicenseInstallQueue() {
return BindingBuilder.bind(declareLicenseInstallQueue()).to(defaultExchange()).with("license.install.queue");
}
@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public RabbitTemplate amqpTemplate() {
RabbitTemplate amqpTemplate = new RabbitTemplate(connectionFactory);
amqpTemplate.setMessageConverter(messageConverter());
return amqpTemplate;
}
@Bean
public RabbitAdmin rabbitAdmin() {
return new RabbitAdmin(amqpTemplate());
}
@Bean
public SimpleMessageListenerContainer autoMessageListener(CurrentService service, BocloudMessageListener bocloudMessageListener) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueues(declareMessageQueue(service));
// 设置确认模式自动确认
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
container.setMessageListener(bocloudMessageListener);
container.setAmqpAdmin(rabbitAdmin());
container.setAutoStartup(true);
return container;
}
@Bean
@ConditionalOnBean(AbstractEncryptHandler.class)
public SimpleMessageListenerContainer licenseInstallListener(AbstractEncryptHandler encryptHandler) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
// 设置确认模式自动确认
container.setQueues(declareLicenseInstallQueue());
container.setAcknowledgeMode(AcknowledgeMode.AUTO);
container.setMessageListener(encryptHandler);
container.setAmqpAdmin(rabbitAdmin());
container.setAutoStartup(true);
return container;
}
}

View File

@ -0,0 +1,45 @@
package com.bocloud.sms.booter.config;
import cn.hutool.core.util.RandomUtil;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
/**
* @author dmw
*/
@Configuration
public class SwaggerConfiguration {
@Bean
public GlobalOpenApiCustomizer orderGlobalOpenApiCustomizer() {
return openApi -> {
if (openApi.getTags() != null) {
openApi.getTags().forEach(tag -> {
Map<String, Object> map = new HashMap<>();
map.put("x-order", RandomUtil.randomInt(0, 100));
tag.setExtensions(map);
});
}
if (openApi.getPaths() != null) {
openApi.addExtension("x-production", "BeyondCMP");
openApi.getPaths().addExtension("x-sign", RandomUtil.randomInt(1, 100));
}
};
}
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info().title("系统管理服务API接口文档")
.version("6.5.0-LTS")
.description("系统管理服务API接口文档")
.termsOfService("https://www.bocloud.com")
.license(new License().name("Apache 2.0").url("https://www.bocloud.com")));
}
}

View File

@ -0,0 +1,108 @@
package com.bocloud.sms.booter.config;
import com.bocloud.cmp.boot.config.PagerArgumentResolver;
import com.bocloud.cmp.boot.interceptor.AccessInterceptor;
import com.bocloud.cmp.boot.interceptor.LogInterceptor;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.megatron.framework.core.InterceptorBridge;
import com.megatron.framework.core.config.InterceptorConfiguration;
import com.megatron.framework.core.domain.InterceptorEntity;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.reflections.scanners.Scanner;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
*
*
* @author wangyu
* @version 1.0
* @since 2018330
*/
@Slf4j
@Component
public class WebInterceptorConfiguration implements InterceptorConfiguration {
private static final String[] ACCESS_EXCLUDES = new String[]{"/*/*.css",
"/*/*.js", "/*/*.png", "/*/*.jpg", "/*/*.jpeg", "/*.html", "/*/*.html", "/swagger-resources/**",
"/favicon.ico", "/webjars/**", "/v2/**", "/swagger-ui.html/**", "/v1/log/**", "/v1/logo", "/v1/configs", "/v1/*/login",
"/v1/logview", "/v1/logzip", "/status/**", "/v1/tokens", "/v1/config/captcha/install", "/v1/status/sid",
"/v1/config/license/install", "/v1/config/status/", "/v1/status/sids", "/status", "/status/db",
"/error", "/v1/*/info", "/v1/*/status", "/v1/config/**", "/v1/status/**", "/v1/config/license",
"/v3/api-docs/**", "/v1/autologin", "/v1/single/login"};
private static final String[] LOG_EXCLUDES = new String[]{"/*/*.css",
"/*/*.js", "/*/*.png", "/*/*.jpg", "/*/*.jpeg", "/*.html", "/*/*.html", "/swagger-resources/**", "/favicon.ico",
"/webjars/**", "/v2/**", "/swagger-ui.html/**", "/error", "/v3/api-docs/**"};
private static final String[] INCLUDES = new String[]{"/**"};
private final LogInterceptor logInterceptor;
private final AccessInterceptor accessInterceptor;
@Autowired
public WebInterceptorConfiguration(AccessInterceptor accessInterceptor, LogInterceptor logInterceptor) {
this.logInterceptor = logInterceptor;
this.accessInterceptor = accessInterceptor;
}
@Override
public InterceptorBridge buildBridge() {
log.info("start to build interceptor bridge ...");
InterceptorEntity accessEntity = InterceptorEntity.builder().interceptor(accessInterceptor).includes(INCLUDES).excludes(ACCESS_EXCLUDES).order(0).build();
InterceptorEntity auditLogEntity = InterceptorEntity.builder().interceptor(logInterceptor).includes(INCLUDES).excludes(LOG_EXCLUDES).order(1).build();
List<InterceptorEntity> interceptors = new ArrayList<>();
interceptors.add(accessEntity);
interceptors.add(auditLogEntity);
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>();
resolvers.add(new PagerArgumentResolver());
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(this.byteConverter());
converters.add(this.jsonConverter());
InterceptorBridge bridge = new InterceptorBridge();
bridge.setInterceptors(interceptors);
bridge.setResolvers(resolvers);
bridge.setMessageConverters(converters);
log.info("build interceptor bridge success!!!");
return bridge;
}
private HttpMessageConverter<?> byteConverter() {
return new ByteArrayHttpMessageConverter();
}
private HttpMessageConverter<?> jsonConverter() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Reflections reflections = new Reflections("com", new Scanner[0]);
Set<Class<?>> classSet = reflections.getTypesAnnotatedWith(JsonTypeName.class);
objectMapper.registerSubtypes(classSet);
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
jackson2HttpMessageConverter.setDefaultCharset(Charset.defaultCharset());
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
jackson2HttpMessageConverter.setPrettyPrint(true);
jackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
return jackson2HttpMessageConverter;
}
}

View File

@ -0,0 +1,71 @@
package com.bocloud.sms.booter.config;
import com.bocloud.sms.booter.websocket.logview.LogViewHandler;
import com.bocloud.sms.booter.websocket.message.MessageHandler;
import com.bocloud.sms.booter.websocket.message.MessageInterceptor;
import com.bocloud.sms.booter.websocket.upload.UploadServiceHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;
/**
*
*
* @author tyl
* @version 1.0
* @since 2021325
*/
@Configuration
@EnableWebSocket
@RequiredArgsConstructor
public class WebSocketConfiguration implements WebSocketConfigurer {
private final MessageInterceptor messageInterceptor;
private final MessageHandler messageHandler;
private final LogViewHandler logViewHandler;
private final UploadServiceHandler uploadServiceHandler;
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
@Bean
public DefaultHandshakeHandler handshakeHandler() {
return new DefaultHandshakeHandler();
}
@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(10240);
container.setMaxBinaryMessageBufferSize(5 * 1024 * 1024);
return container;
}
@Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// 注册普通消息服务
registry.addHandler(messageHandler, "/messageService").addInterceptors(messageInterceptor)
.setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*");
registry.addHandler(messageHandler, "/sockjs/messageService").addInterceptors(messageInterceptor)
.setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*").withSockJS();
// 注册日志查看消息服务
registry.addHandler(logViewHandler, "/logViewService").addInterceptors(messageInterceptor)
.setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*");
registry.addHandler(logViewHandler, "/sockjs/logViewService").addInterceptors(messageInterceptor)
.setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*").withSockJS();
// 普通文件上传消息服务
registry.addHandler(this.uploadServiceHandler, "/uploadService").addInterceptors(messageInterceptor)
.setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*");
registry.addHandler(this.uploadServiceHandler, "/sockjs/uploadService")
.addInterceptors(this.messageInterceptor).setHandshakeHandler(handshakeHandler()).setAllowedOrigins("*")
.withSockJS();
}
}

View File

@ -0,0 +1,39 @@
package com.bocloud.sms.booter.config;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* api
*
* @author tyl
* @since 2021/3/9 18:10
*/
@Component
public class WhiteApiCache implements InitializingBean {
private final StringRedisTemplate redisTemplate;
private final ThreadPoolTaskExecutor taskExecutor;
public WhiteApiCache(StringRedisTemplate redisTemplate, ThreadPoolTaskExecutor taskExecutor) {
this.redisTemplate = redisTemplate;
this.taskExecutor = taskExecutor;
}
@Override
public void afterPropertiesSet() {
taskExecutor.execute(() -> {
//设置白名单
List<String> whiteList = Lists.newArrayList("^GET:/v1/users/permissions$",
"^GET:/v1/login/detail$", "^GET:/v1/messages$", "^GET:/v1/token$",
"^POST:/v1/users/logout$", "^POST:/v1/tenants/logout$", "^GET:/v1/config/license$", "^GET:/v1/roles/ids$");
redisTemplate.opsForValue().set("permission_white", JSONObject.toJSONString(whiteList));
});
}
}

View File

@ -0,0 +1,107 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Admission;
import com.bocloud.sms.interfaces.AdmissionService;
import com.bocloud.sms.model.AdmissionModel;
import com.bocloud.sms.service.utils.AdmissionUtil;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* ip访
*
* @author wangyu
* @version 4.2.1-SNAPSHOT
* @since 2019/11/12
*/
@RestController
@RequestMapping("/v1/admissions")
@Tag(name = "IP限制管理")
public class AdmissionController {
private final AdmissionService admissionService;
private final AdmissionUtil admissionUtil;
public AdmissionController(AdmissionService admissionService, AdmissionUtil admissionUtil) {
this.admissionService = admissionService;
this.admissionUtil = admissionUtil;
}
/**
* IP访
*
* @param pager
* @return
*/
@Operation(summary = "查询IP访问限制列表")
@GetMapping
public GeneralResult<GridBean<Admission>> list(Pager pager) {
return admissionService.list(pager);
}
/**
* IP访
*
* @param admissionModel ip
* @return
*/
@Operation(summary = "创建IP访问限制")
@PostMapping
public Result create(@RequestBody AdmissionModel admissionModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
Assert.notNull(admissionModel, "请求参数不能为空");
Result result = admissionService.create(admissionModel, requestContext);
if (result.isSuccess()) {
admissionUtil.refresh();
}
return result;
}
/**
* IP访
*
* @param id id
* @return
*/
@Operation(summary = "删除IP访问限制")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id) {
Result result = admissionService.remove(id);
if (result.isSuccess()) {
admissionUtil.refresh();
}
return result;
}
/**
* IP访
*
* @param id id
* @return id访
*/
@Operation(summary = "查看IP访问限制")
@GetMapping("/{id}")
public GeneralResult<Admission> detail(@PathVariable(value = Common.ID) Long id) {
return admissionService.detail(id);
}
/**
* IP访
*
* @param ids id
* @return
*/
@Operation(summary = "批量删除IP访问限制")
@DeleteMapping
public Result batchRemove(@RequestBody List<Long> ids) {
return admissionService.batchRemove(ids);
}
}

View File

@ -0,0 +1,85 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.ApiToken;
import com.bocloud.sms.interfaces.ApiTokenService;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.RequestContext;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
* api token访
*/
@RestController
@RequestMapping("/v1/api/tokens")
@Tag(name = "API Token管理")
public class ApiTokenController {
@Autowired
private ApiTokenService apiTokenService;
@GetMapping("/check/{token}")
@Operation(summary = "查看API Token")
public GeneralResult<ApiToken> detail(@PathVariable(value = Common.TOKEN) String token) {
return apiTokenService.get(token);
}
/**
* Token
*
* @param token
* @param context
* @return
*/
@PostMapping
@Operation(summary = "创建 ApiToken")
public GeneralResult<ApiToken> create(@RequestBody ApiToken token, @Value(Common.REQ_CONTEXT) RequestContext context) {
return apiTokenService.create(token, context);
}
/**
* Api token
*
* @param pager
* @param context
* @return
*/
@GetMapping
@Operation(summary = "查看API Token列表")
public GeneralResult<GridBean<ApiToken>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return apiTokenService.list(pager, context);
}
/**
* Api token
*
* @param token
* @param context
* @return
*/
@PutMapping
@Operation(summary = "修改API Token")
public GeneralResult<Void> modify(@RequestBody ApiToken token, @Value(Common.REQ_CONTEXT) RequestContext context) {
return apiTokenService.modify(token, context);
}
/**
* Api Token
*
* @param id
* @param context
* @return
*/
@DeleteMapping("/{id}")
@Operation(summary = "移除Api Token")
public GeneralResult<Void> remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
return apiTokenService.remove(id, context);
}
}

View File

@ -0,0 +1,29 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.interfaces.AutoLoginService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.view.RedirectView;
@RestController
@RequestMapping("/v1/autologin")
@Tag(name = "自动登录")
public class AutoLoginController {
@Autowired
private AutoLoginService autoLoginService;
@GetMapping()
@Operation(summary = "查看API Token")
public RedirectView autoLogin(
@RequestHeader(value = "x-forwarded-host", required = false) String host,
HttpServletRequest request) {
return autoLoginService.autoLogin(host, request);
}
}

View File

@ -0,0 +1,221 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Business;
import com.bocloud.sms.entity.Project;
import com.bocloud.sms.interfaces.BusinessService;
import com.bocloud.sms.model.BusinessModel;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author tyl
* @time 2020/6/3 15:29
*/
@RestController
@RequestMapping("/v1/bizs")
@Tag(name = "业务管理")
@Slf4j
public class BusinessController {
private final BusinessService businessService;
public BusinessController(BusinessService businessService) {
this.businessService = businessService;
}
/**
*
*
* @param pager
* @return
*/
@Operation(summary = "查看业务列表")
@GetMapping
public GeneralResult<GridBean<Business>> list(Pager pager,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return businessService.list(pager, requestContext);
}
/**
*
*
* @param businessModel
* @param requestContext
* @return
*/
@Operation(summary = "添加业务")
@PostMapping
public Result create(@RequestBody BusinessModel businessModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return businessService.create(businessModel, requestContext);
}
/**
*
*
* @param id id
* @param businessModel
* @param requestContext
* @return
*/
@Operation(summary = "修改业务")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id,
@RequestBody BusinessModel businessModel, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return businessService.modify(id, businessModel, requestContext);
}
/**
*
*
* @param id id
* @param requestContext
* @return
*/
@Operation(summary = "删除业务")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return businessService.remove(id, requestContext);
}
/**
*
*
* @param ids id
* @param requestContext
* @return
*/
@Operation(summary = "批量删除业务")
@DeleteMapping
public Result batchRemove(@RequestBody List<Long> ids,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return businessService.batchRemove(ids, requestContext);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查看业务明细")
@GetMapping("/{id}")
public GeneralResult<Business> detail(@PathVariable(value = Common.ID) Long id) {
return businessService.detail(id);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查看业务下项目")
@GetMapping("/{id}/projects")
public GeneralResult<List<Project>> projects(
@PathVariable(value = Common.ID) Long id) {
return businessService.listBusinessProject(id);
}
/**
*
*
* @param id id
* @param projectIds id
* @return
*/
@Operation(summary = "配置业务项目")
@PatchMapping("/{id}")
public Result businessAction(@PathVariable(value = Common.ID) Long id,
@RequestBody List<Long> projectIds) {
return businessService.businessAction(id, projectIds);
}
/**
*
*
* @param pager
* @param requestContext
*/
@Deprecated
@Operation(summary = "导出项目列表")
@RequestMapping(value = "/export", method = {RequestMethod.GET})
public void export(Pager pager,
@Value(Common.REQ_CONTEXT) RequestContext requestContext, HttpServletRequest request,
HttpServletResponse response) {
List<Param> paramList = pager.getParams();
try {
XSSFWorkbook workbook = businessService.export(paramList, requestContext);
// 下载表格到浏览器
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream");
String fileName = "业务统计数据" + System.currentTimeMillis() + ".xlsx";
final String userAgent = request.getHeader("user-agent").toLowerCase();
if (userAgent.contains("trident") || userAgent.contains("edge")) {
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
} else {
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
OutputStream os = response.getOutputStream();
workbook.write(os);
os.flush();
os.close();
} catch (Exception e) {
log.error("export project error,", e);
}
}
/**
*
*
* @param response
*/
@Operation(summary = "下载业务列表模板")
@RequestMapping(value = "/import/template", method = {RequestMethod.GET})
public void importTemp(HttpServletResponse response) {
businessService.importTemp(response);
}
/**
*
*
* @param requestContext
* @param request
* @return
*/
@Operation(summary = "导入业务列表")
@PostMapping(value = "/import")
public Result importData(@Value(Common.REQ_CONTEXT) RequestContext requestContext, HttpServletRequest request) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
List<MultipartFile> fileList = multipartRequest.getFiles("file");
if (fileList.isEmpty()) {
return new Result(false, "文件错误");
}
MultipartFile multipartFile = fileList.get(0);
String originalFilename = multipartFile.getOriginalFilename();
// 判断文件名
if (originalFilename == null || !(originalFilename.endsWith(".xls") || originalFilename.endsWith(".xlsx"))) {
return new Result(false, "文件错误");
}
return businessService.importData(multipartFile, requestContext);
}
}

View File

@ -0,0 +1,167 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.boot.model.BoCloudExchange;
import com.bocloud.sms.model.LicenseMask;
import com.megatron.common.http.HttpClient;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.License;
import com.megatron.common.model.Result;
import com.megatron.common.utils.Common;
import com.megatron.framework.core.CurrentService;
import com.megatron.framework.license.LicenseDaemon;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
*
*
* @author weiwei
*/
@Slf4j
@RestController
@RequestMapping("/v1")
@Tag(name = "服务节点信息管理")
public class ConfigController {
private static final String LICENSE_SUCCESS = "证书激活成功";
private static final String LICENSE_FAILED = "证书激活失败";
private final LicenseDaemon licenseDaemon;
@Value("${service.host:127.0.0.1}")
private String host;
@Value("${server.port:18088}")
private String port;
@Autowired
private AmqpTemplate amqpTemplate;
public ConfigController(CurrentService currentService) {
this.licenseDaemon = LicenseDaemon.instance(currentService);
}
/**
* license
*
* @return license
*/
@Operation(summary = "查询云管license信息")
@GetMapping("/config/license")
public GeneralResult<License> license() {
License license = licenseDaemon.content();
return new GeneralResult<>(true, license, "查询成功");
}
/**
*
*
* @param value url
* @return
*/
@Operation(summary = "系统状态信息")
@GetMapping("/config/status")
public GeneralResult status(@RequestParam(value = Common.VALUE) String value) {
HttpClient client = new HttpClient();
String message = client.get(value).getMessage();
return JSONObject.parseObject(message, GeneralResult.class);
}
/**
*
*
* @param file
* @return
*/
@Operation(summary = "安装证书")
@PostMapping("/config/license/install")
public Result licenseInstall(@RequestParam("file") MultipartFile file) {
if (file.isEmpty()) {
return new Result(false, "证书为空!");
}
Result result;
try {
result = licenseDaemon.verify(file.getBytes());
if (result.isFailed()) {
log.error("证书校验失败");
return new Result(false, LICENSE_FAILED);
}
result = licenseDaemon.install(file.getBytes());
if (result.isSuccess()) {
return new Result(true, LICENSE_SUCCESS);
}
return new Result(false, LICENSE_FAILED);
} catch (IOException e) {
log.error("证书激活异常:", e);
return new Result(false, LICENSE_FAILED);
}
}
/**
* license
*
* @param licenseMask license
* @return
*/
@Operation(summary = "安装license验证码")
@PostMapping("/config/captcha/install")
public Result captchaInstall(@RequestBody LicenseMask licenseMask) {
try {
GeneralResult<byte[]> GeneralResult = licenseDaemon.decode(licenseMask.getLicenseMask());
if (GeneralResult.isFailed()) {
log.error("证书激活码格式有误,激活失败!");
return new Result(false, LICENSE_FAILED);
}
Result result = licenseDaemon.verify(GeneralResult.getData());
if (result.isFailed()) {
log.error("证书格式不正确!");
return new Result(false, LICENSE_FAILED);
}
result = licenseDaemon.install(GeneralResult.getData());
if (result.isFailed()) {
log.error("证书安装失败");
return new Result(false, LICENSE_FAILED);
}
amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(),
"license.install.queue", LICENSE_SUCCESS);
return new Result(true, LICENSE_SUCCESS);
} catch (Exception e) {
log.error("证书激活异常!", e);
return new Result(false, LICENSE_FAILED);
}
}
/**
* sid
*
* @return sid
*/
@Operation(summary = "系统状态信息")
@GetMapping("/status/sid")
public GeneralResult getSid() {
HttpClient client = new HttpClient();
String url = "http://" + host + ":" + port + "/status/sid";
String message = client.get(url).getMessage();
return JSONObject.parseObject(message, GeneralResult.class);
}
/**
* sid
*
* @return sid
*/
@Operation(summary = "系统状态信息")
@GetMapping("/status/sids")
public GeneralResult getSids() {
HttpClient client = new HttpClient();
String url = "http://" + host + ":" + port + "/status/sids";
String message = client.get(url).getMessage();
return JSONObject.parseObject(message, GeneralResult.class);
}
}

View File

@ -0,0 +1,117 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Department;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.interfaces.DepartmentService;
import com.bocloud.sms.model.DepartmentModel;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
*
* @author tyl
* @since 2021/03/25
*/
@RestController
@RequestMapping("/v1/departments")
@Tag(name = "组织管理")
public class DepartmentController {
private final DepartmentService departmentService;
public DepartmentController(DepartmentService departmentService) {
this.departmentService = departmentService;
}
/**
*
*
* @param parentId id
* @param requestContext
* @return
*/
@GetMapping
@Operation(summary = "组织机构列表显示")
public GeneralResult<List<Department>> list(@RequestParam(value = Common.PARENTID) Long parentId, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return departmentService.list(parentId, requestContext);
}
/**
*
*
* @param id id
* @param requestContext
* @return
*/
@GetMapping("/{id}/managers")
@Operation(summary = "查询组织机构下的管理员")
public GeneralResult<List<User>> listDeptManager(@PathVariable(value = Common.ID) Long id, RequestContext requestContext) {
return departmentService.listDeptManager(id, requestContext);
}
/**
*
*
* @param department
* @param requestContext
* @return
*/
@Operation(summary = "创建组织机构")
@PostMapping
public Result create(@RequestBody DepartmentModel department,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return departmentService.create(department, requestContext);
}
/**
*
*
* @param id id
* @param department
* @param requestContext
* @return
*/
@Operation(summary = "修改组织机构")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id,
@RequestBody DepartmentModel department,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return departmentService.modify(id, department, requestContext);
}
/**
*
*
* @param id id
* @param requestContext
* @return
*/
@Operation(summary = "删除组织机构")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return departmentService.remove(id, requestContext);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "组织机构详情")
@GetMapping("/{id}")
public GeneralResult<Department> detail(@PathVariable(value = Common.ID) Long id) {
return departmentService.detail(id);
}
}

View File

@ -0,0 +1,106 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Dictionary;
import com.bocloud.sms.interfaces.DictService;
import com.bocloud.sms.model.DictionaryBean;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.Result;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
*
* @author dmw
*/
@RestController
@RequestMapping("/v1/dictionaries")
@Tag(name = "字典信息管理")
public class DictController {
private final DictService dictService;
public DictController(DictService dictService) {
this.dictService = dictService;
}
@Operation(summary = "查询字典树列表")
@GetMapping
public GeneralResult<List<Dictionary>> list(@RequestParam(value = "pid", required = false) Long pid) {
return dictService.list(pid);
}
@Operation(summary = "根据id查询字典")
@GetMapping("/{id}")
public GeneralResult<Dictionary> detail(@PathVariable(value = "id") Long id) {
return dictService.detail(id);
}
/**
*
*
* @param value
* @return
*/
@Operation(summary = "查询系统字典子信息")
@GetMapping("/children")
public GeneralResult<List<Dictionary>> children(@RequestParam(value = Common.VALUE, required = false) String value,
@RequestParam(value = "pid", required = false) Long pid) {
return dictService.listChild(value, pid);
}
/**
*
*
* @param value
* @return
*/
@Operation(summary = "查询字典树")
@GetMapping("/children/tree")
public GeneralResult<List<Dictionary>> childTree(@RequestParam(value = Common.VALUE, required = false) String value) {
return dictService.childTree(value);
}
/**
*
*
* @param dictionary
* @return
*/
@Operation(summary = "新增字典")
@PostMapping
public GeneralResult<Dictionary> create(@RequestBody Dictionary dictionary) {
return dictService.create(dictionary);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "删除字典")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id) {
return dictService.remove(id);
}
/**
*
*
* @param id id
* @param bean
* @return
*/
@Operation(summary = "修改字典")
@PutMapping("/{id}")
public GeneralResult<Dictionary> modify(@PathVariable(value = Common.ID) Long id,
@RequestBody DictionaryBean bean) {
bean.setId(id);
return dictService.modify(bean);
}
}

View File

@ -0,0 +1,96 @@
package com.bocloud.sms.booter.controller;
import com.auth0.jwt.interfaces.Claim;
import com.bocloud.sms.entity.SystemConfig;
import com.bocloud.sms.repository.SystemConfigRepository;
import com.megatron.common.utils.Common;
import com.megatron.common.utils.Tokens;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import java.util.Objects;
import java.util.Optional;
/**
* @author tyl
* {@code @time} 2020/4/24 20:02
*/
@Slf4j
@Controller
@RequestMapping
@Tag(name = "跳转控制")
public class DispatchController {
private final SystemConfigRepository configRepository;
private final StringRedisTemplate redisTemplate;
public DispatchController(SystemConfigRepository systemConfigService, StringRedisTemplate redisTemplate) {
this.configRepository = systemConfigService;
this.redisTemplate = redisTemplate;
}
/**
*
*
* @param request
* @param response
* @throws Exception
*/
@RequestMapping("/v1/redirect")
@Operation(summary = "单点登录跳转")
public void redirect(HttpServletRequest request, HttpServletResponse response) throws Exception {
//获取登录地址
String target = request.getParameter("target");
String redirectParameter = request.getParameter("redirect");
SystemConfig config;
if (target == null || "Manager".equals(target)) {
config = configRepository.queryByCode("ManagerAddress");
} else {
config = configRepository.queryByCode("TenantAddress");
}
String loginAddress = config.getValue();
log.info("#######debuge########the request url is {}", request.getRequestURL() + "?" + request.getQueryString());
log.info("#######debuge########the redirect url is {}", redirectParameter);
String redirect = Optional.ofNullable(redirectParameter).orElse(loginAddress + "/#/");
String token = request.getParameter("token");
log.info("#######debuge########the redirect token is {}", token);
Claim claim = Tokens.parse(token);
if (!Objects.isNull(claim)) {
String catalog = claim.asMap().get("catalog").toString();
long uuid = Long.parseLong(claim.asMap().get(Common.UUID).toString());
String tokenKey = Common.TOKEN + "_" + catalog + "_" + uuid;
boolean checkResult = check(token, tokenKey);
if (checkResult) {
HttpSession session = request.getSession();
session.setAttribute("redirect", redirect);
session.setAttribute(Common.TOKEN, token);
response.sendRedirect(loginAddress + "/#/sso");
} else {
String replace = redirect.replace("#", "%23");
response.sendRedirect(loginAddress + "/#/login?redirect=" + replace);
}
} else {
String replace = redirect.replace("#", "%23");
response.sendRedirect(loginAddress + "/#/login?redirect=" + replace);
}
}
private boolean check(String token, String tokenKey) {
String newTokenCache = (String) this.redisTemplate.opsForHash().get(tokenKey + "_n", Common.TOKEN);
String oldTokenCache = this.redisTemplate.opsForValue().get(tokenKey + "_o");
if (token.equals(newTokenCache)) {
return true;
} else {
return token.equals(oldTokenCache);
}
}
}

View File

@ -0,0 +1,99 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Environment;
import com.bocloud.sms.interfaces.EnvironmentService;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.RequestContext;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
* Controller
*
* @author wangshuai
* @version 4.1.0-SNAPSHOT
* @since 2018/12/24
*/
@RestController
@RequestMapping("/v1/environments")
@Tag(name = "所属环境")
public class EnvironmentController {
private final EnvironmentService environmentService;
public EnvironmentController(EnvironmentService environmentService) {
this.environmentService = environmentService;
}
/**
*
*
* @param pager
* @return
*/
@Operation(summary = "获取所属环境列表")
@GetMapping
public GeneralResult<GridBean<Environment>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return environmentService.list(pager, context);
}
/**
*
*
* @param environment
* @param context
* @return
*/
@Operation(summary = "添加所属环境")
@PostMapping
public GeneralResult<Environment> create(@RequestBody Environment environment,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return environmentService.create(environment, context);
}
/**
*
*
* @param id id
* @param environment
* @param context
* @return
*/
@Operation(summary = "修改所属环境")
@PutMapping("/{id}")
public GeneralResult<Environment> modify(@PathVariable(value = Common.ID) Long id, @RequestBody Environment environment,
@Value(Common.REQ_CONTEXT) RequestContext context) {
environment.setId(id);
return environmentService.modify(environment, context);
}
/**
*
*
* @param id id
* @param context
* @return
*/
@Operation(summary = "删除所属环境")
@DeleteMapping("/{id}")
public GeneralResult remove(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return environmentService.remove(id, context);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查看所属环境详情")
@GetMapping("/{id}")
public GeneralResult<Environment> detail(@PathVariable(value = Common.ID) Long id) {
return environmentService.detail(id);
}
}

View File

@ -0,0 +1,66 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.GlobalManConfig;
import com.bocloud.sms.interfaces.GlobalManConfigService;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
* @author wpj
* @since 2022/9/8
*/
@RestController
@RequestMapping("/v1/global/config")
@Slf4j
@Tag(name = "全局运维配置")
public class GlobalManConfigController {
private final GlobalManConfigService globalManConfigService;
public GlobalManConfigController(GlobalManConfigService globalManConfigService) {
this.globalManConfigService = globalManConfigService;
}
@Operation(summary = "查询周期时间列表")
@GetMapping
public GeneralResult<GridBean<GlobalManConfig>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return globalManConfigService.list(pager, context);
}
@Operation(summary = "创建禁止周期时间")
@PostMapping
public Result create(@RequestBody GlobalManConfig globalManConfig,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return globalManConfigService.create(globalManConfig, requestContext);
}
@Operation(summary = "修改禁止周期时间")
@PutMapping("/{id}")
public Result modify(@RequestBody GlobalManConfig globalManConfig,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return globalManConfigService.modify(globalManConfig, requestContext);
}
@Operation(summary = "删除禁止周期时间")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return globalManConfigService.remove(id, requestContext);
}
@Operation(summary = "查询当前全局配置是否被禁止")
@GetMapping("/isAllow")
public Result isAllow(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return globalManConfigService.allow(requestContext);
}
}

View File

@ -0,0 +1,66 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Icon;
import com.bocloud.sms.interfaces.IconService;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.RequestContext;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
/**
* controller
*
* @author
* @Version 1.0
* @since 202047
*/
@RestController
@RequestMapping("/v1/icon")
@Tag(name = "图标管理")
public class IconController {
@Autowired
private IconService iconService;
/**
*
*
* @return
*/
@GetMapping
@Operation(summary = "图标列表查询")
public GeneralResult<GridBean<Icon>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return iconService.list(pager, context);
}
/**
*
*
* @param files
* @param context
* @return
*/
@PostMapping()
@Operation(summary = "上传图标")
public GeneralResult<Void> upload(MultipartFile[] files, String category, @Value(Common.REQ_CONTEXT) RequestContext context) {
return iconService.create(files, category, context);
}
/**
*
*
* @param id id
* @return
*/
@DeleteMapping(value = "/{id}")
@Operation(summary = "删除图标")
public GeneralResult<Void> remove(@PathVariable(value = Common.ID) Long id) {
return iconService.remove(id);
}
}

View File

@ -0,0 +1,88 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Label;
import com.bocloud.sms.interfaces.LabelService;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
* @author zhangdi
* @since 2018/7/2
*/
@RestController
@RequestMapping("/v1/tags")
@Tag(name = "标签管理")
public class LabelController {
private final LabelService labelService;
public LabelController(LabelService labelService) {
this.labelService = labelService;
}
/**
*
*
* @param pager
* @return
*/
@Operation(summary = "获取命名规则列表")
@GetMapping
public GeneralResult<GridBean<Label>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return labelService.list(pager, context);
}
/**
*
*
* @param label
* @return
*/
@Operation(summary = "添加标签")
@PostMapping
public GeneralResult<Label> create(@RequestBody Label label, @Value(Common.REQ_CONTEXT) RequestContext context) {
return labelService.create(label, context);
}
/**
*
*
* @param id id
* @param label
* @return
*/
@Operation(summary = "修改标签")
@PutMapping("/{id}")
public GeneralResult<Label> modify(@PathVariable(value = Common.ID) Long id, @RequestBody Label label) {
label.setId(id);
return labelService.modify(label);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "删除标签")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id) {
return labelService.remove(id);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查看标签详情")
@GetMapping("/{id}")
public GeneralResult<Label> detail(@PathVariable(value = Common.ID) Long id) {
return labelService.detail(id);
}
}

View File

@ -0,0 +1,44 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.LogArchiveRecord;
import com.bocloud.sms.interfaces.LogArchiveRecordService;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
*
* @author zhangdi
* @since Nov 6,2019
*/
@RestController
@RequestMapping("/v1/archives")
@Tag(name = "日志归档管理")
public class LogArchiveRecordController {
private final LogArchiveRecordService logArchiveRecordService;
public LogArchiveRecordController(LogArchiveRecordService logArchiveRecordService) {
this.logArchiveRecordService = logArchiveRecordService;
}
/**
*
*
* @param pager
* @return
*/
@GetMapping
@Operation(summary = "审计日志归档记录")
public GeneralResult<GridBean<LogArchiveRecord>> list(Pager pager) {
return logArchiveRecordService.list(pager);
}
}

View File

@ -0,0 +1,76 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.AccessLog;
import com.bocloud.sms.interfaces.LogService;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
*
* @author dmw
*/
@RestController
@RequestMapping("/v1/logs")
@Tag(name = "审计日志管理")
public class LogController {
private final LogService logService;
public LogController(LogService logService) {
this.logService = logService;
}
/**
*
*
* @param pager
* @return
*/
@GetMapping
@Operation(summary = "获取审计日志列表")
public GeneralResult<GridBean<AccessLog>> list(Pager pager) {
return this.logService.list(pager);
}
/**
*
*
* @param logs
* @return
*/
@Operation(summary = "批量保存审计日志")
@PostMapping
public Result batchSave(@RequestBody List<AccessLog> logs) {
return this.logService.batch(logs);
}
/**
*
*
* @param startTime
* @param endTime
* @param deleted
* @param context
* @return
*/
@GetMapping(value = "/archive")
@Operation(summary = "审计日志归档")
public GeneralResult<StringBuilder> archive(@RequestParam(value = "startTime", required = false) String startTime,
@RequestParam(value = "endTime", required = false) String endTime,
@RequestParam(value = "deleted", required = false) Boolean deleted,
@Value(Common.REQ_CONTEXT) RequestContext context, HttpServletRequest request,
HttpServletResponse response) {
return logService.archive(startTime, endTime, deleted, context, request, response);
}
}

View File

@ -0,0 +1,332 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.sms.booter.websocket.model.LogViewMessage;
import com.google.common.collect.Maps;
import com.megatron.common.enums.PostDataFormat;
import com.megatron.common.http.HttpClient;
import com.megatron.common.model.Result;
import com.megatron.common.utils.MapTools;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
*
*
* @author zhangdi
* @since 2018.7.23
*/
@Slf4j
@RestController
@RequestMapping("/v1/logs")
@Tag(name = "日志下载管理")
public class LogDownloadController {
@Value("${logging.dir:/log/services}")
private String loggingDir;
/**
*
*
* @param token token
* @param server
* @param host host
* @param request
* @param response
*/
@Operation(summary = "当日日志下载")
@RequestMapping(value = "/download", method = {RequestMethod.GET})
public void download(@RequestParam(value = "token") String token,
@RequestParam(value = "server") String server,
@RequestParam(value = "host") String host,
HttpServletRequest request, HttpServletResponse response) {
Long position = 0L;
Long presize = Long.MAX_VALUE;
String fileName = server + ".log";
String filepath = loggingDir + File.separator + fileName;
LogViewMessage logViewMessage;
switch (server) {
case "worker": {
String workPath = "/var/log/bocloud/bocloud_worker.log";
String url = "http://" + host + "/api/" + server + "/v1/logview";
logViewMessage = getRemoteLog(url, workPath, position, presize, host.substring(0, host.indexOf(':')));
break;
}
case "pontus": {
String workPath = "/var/log/pontus/pontus.log";
String url = "http://" + host + "/api/" + server + "/v1/logview";
logViewMessage = getRemoteLog(url, workPath, position, presize, null);
break;
}
default: {
String url = "http://" + host + "/v1/logview";
log.info("token:{}", token);
logViewMessage = getRemoteLog(token, url, filepath, position, presize);
break;
}
}
String content;
try {
content = JSONObject.toJSONString(logViewMessage.getContent());
// 获取当前时间并拼成yyyy-MM-dd格式 HH:mm
Date date = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String beginIndex = dateFormat.format(date).substring(0, 11) + "00:00";
String endIndex = dateFormat.format(date);
// 将开始结束时间放入日历类 操作日历截取日志
Calendar beginTime = Calendar.getInstance();
Calendar endTime = Calendar.getInstance();
beginTime.setTime(dateFormat.parse(beginIndex));
// beginTime.add(Calendar.MINUTE, -1);
endTime.setTime(dateFormat.parse(endIndex));
// 根据开始时间和结束时间进行索引
int begin = content.indexOf(beginIndex);
int end = content.indexOf(endIndex);
// 判断开始时间是否存在,不存在则向后推一分钟
int i = 0;
while (begin == -1) {
beginTime.add(Calendar.MINUTE, 1);
SimpleDateFormat beginFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String newBeginIndex = beginFormat.format(beginTime.getTime());
begin = content.indexOf(newBeginIndex);
i++;
if (i > 1440) {
break;
}
}
// 判断结束时间是否存在,不存在则向前推一分钟
int j = 0;
while (end == -1) {
endTime.add(Calendar.MINUTE, -1);
SimpleDateFormat endFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
String newEndIndex = endFormat.format(endTime.getTime());
// 索引最后一次出现的结束时间
end = content.lastIndexOf(newEndIndex);
j++;
if (j > 1440) {
break;
}
}
// 判断此时间段内是否有日志
String total;
if (begin > end || begin == -1) {
total = "此时间段内无日志";
} else {
String substring = content.substring(begin, end);
// 补上最后时刻的一条数据
String character = "\\n";
// 从end的索引开始向后拿到到“\n”为址的第一条数据
int endAdd = content.indexOf(character, end);
String add = content.substring(end, endAdd);
total = substring + add;
// 将捕获日志时拿到的“\n”、“\\”及着色符替换掉
total = total.replace("\\\\", "").replace("\\n", "\r\n").replace("\\u001B[36m", "")
.replace("\\u001B[34m", "").replace("\\u001B[31m", "").replace("\\u001B[1;31m", "")
.replace("\\u001B[0;39m", "").replace("\\tat", " ").replace("\\t...", "...");
}
response.setContentType("text/plain");
String filename = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
final String userAgent = request.getHeader("USER-AGENT");
if (userAgent.contains("Mozilla")) {
filename = new String(fileName.getBytes(), "ISO8859-1");
}
response.setHeader("Content-Disposition", "attachment;fileName=" + filename);
// 定义输出流
OutputStream outputStream = response.getOutputStream();
byte[] decode = total.getBytes();
outputStream.write(decode);
outputStream.close();
} catch (Exception e) {
log.error("Daily log download failed!");
}
}
/**
*
*
* @param server
* @param host host
* @param begin
* @param end
* @param request
* @param response
*/
@Operation(summary = "历史日志下载")
@RequestMapping(value = "/zip", method = {RequestMethod.GET})
public void zip(@RequestParam(value = "token") String token,
@RequestParam(value = "server") String server,
@RequestParam(value = "host") String host,
@RequestParam(value = "begin") String begin,
@RequestParam(value = "end") String end,
HttpServletRequest request, HttpServletResponse response) {
try {
String filepath = loggingDir + File.separator + "history";
// 定义导出文件名称
String fileName = server + ".zip";
String url = "http://" + host + "/v1/logzip";
Map<String, byte[]> map = getRemoteZip(token, url, filepath, begin, end, server);
response.setContentType("application/x-zip-compressed");
String filename = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
final String userAgent = request.getHeader("USER-AGENT");
if (userAgent.contains("Mozilla")) {
filename = new String(fileName.getBytes(), "ISO8859-1");
}
response.setHeader("Content-Disposition", "attachment;fileName=" + filename);
// 创建一个临时文件
File file = new File(System.getProperty("user.home") + File.separator + fileName);
OutputStream outputStream = response.getOutputStream();
try (ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(file))) {
byte[] buffer = new byte[1024];
// 遍历拿到的每个文件的数据
for (Map.Entry<String, byte[]> entry : map.entrySet()) {
InputStream inputStream = new ByteArrayInputStream(entry.getValue());
// 文件命名
zipOutputStream.putNextEntry(new ZipEntry(entry.getKey()));
int len;
// 读入需要下载的文件的内容
while ((len = inputStream.read(buffer)) > 0) {
zipOutputStream.write(buffer, 0, len);
}
zipOutputStream.closeEntry();
}
} catch (IOException e) {
log.error("Get error message", e);
}
try (FileInputStream fileInputStream = new FileInputStream(file)) {
IOUtils.copy(fileInputStream, outputStream);
outputStream.close();
} catch (IOException e) {
log.error("Get error message", e);
}
// 删除临时文件
boolean flag = file.delete();
log.info("临时文件删除状态:{}", flag);
} catch (Exception e) {
log.error("Get error message", e);
}
}
/**
*
*
* @param url
* @param filepath
* @param position
* @param presize
* @return
*/
private LogViewMessage getRemoteLog(String token, String url, String filepath, Long position, Long presize) {
LogViewMessage message;
HttpClient client = new HttpClient();
client.setDataFormat(PostDataFormat.RAW);
Map<String, Object> param = MapTools.simpleMap("filepath", filepath);
param.put("position", position);
param.put("presize", presize);
Result result = client.get(MapTools.simpleMap("token", token), param, url);
if (result.isFailed()) {
message = new LogViewMessage("", position);
} else {
JSONObject jsonObject = JSONObject.parseObject(result.getMessage());
if (null != jsonObject) {
jsonObject = JSONObject.parseObject(jsonObject.getString("message"));
} else {
jsonObject = new JSONObject();
}
message = new LogViewMessage(jsonObject.getString("content"), jsonObject.getLong("position"));
}
return message;
}
/**
* worker
*
* @param url
* @param filepath
* @param position
* @param presize
* @param target workerIP
* @return
*/
private LogViewMessage getRemoteLog(String url, String filepath, Long position, Long presize, String target) {
LogViewMessage message;
HttpClient client = new HttpClient();
client.setDataFormat(PostDataFormat.RAW);
Map<String, Object> param = MapTools.simpleMap("filepath", filepath);
param.put("position", position);
param.put("presize", presize);
if (StringUtils.isNotEmpty(target)) {
param.put("target", target);
}
Result result = client.post(null, param, url);
if (result.isFailed()) {
message = new LogViewMessage("", position);
} else {
JSONObject jsonObject = JSONObject.parseObject(result.getMessage());
message = new LogViewMessage(jsonObject.getString("message"), jsonObject.getLong("filesize"));
}
return message;
}
/**
*
*
* @param url
* @param filepath
* @param begin
* @param end
* @param server
* @return byte
*/
private Map<String, byte[]> getRemoteZip(String token, String url, String filepath, String begin, String end,
String server) {
HttpClient client = new HttpClient();
client.setDataFormat(PostDataFormat.RAW);
Map<String, Object> param = MapTools.simpleMap("filepath", filepath);
param.put("begin", begin);
param.put("end", end);
param.put("server", server);
Result result = client.get(MapTools.simpleMap("token", token), param, url);
Map<String, byte[]> dataMap = Maps.newHashMap();
if (result.isSuccess() && StringUtils.isNotEmpty(result.getMessage())) {
JSONObject object = JSONObject.parseObject(result.getMessage(), JSONObject.class);
log.info("获取到日志结果为 {} ", JSONObject.toJSONString(object));
for (String key : object.keySet()) {
try {
dataMap.put(key, object.getBytes(key));
} catch (Exception e) {
log.error("获取日志异常 {} , ->>>>>{}", JSONObject.toJSONString(key), object.get(key));
}
}
}
return dataMap;
}
}

View File

@ -0,0 +1,266 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.AccountSecurity;
import com.bocloud.sms.entity.SystemConfig;
import com.bocloud.sms.entity.TenantAccount;
import com.bocloud.sms.interfaces.TenantService;
import com.bocloud.sms.interfaces.UserService;
import com.bocloud.sms.model.LoginModel;
import com.bocloud.sms.repository.SystemConfigRepository;
import com.bocloud.sms.service.internel.CosInternelService;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import com.megatron.common.utils.Common;
import com.megatron.common.utils.MapTools;
import com.megatron.framework.lock.LockFactory;
import com.megatron.framework.utils.IpTool;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
/**
*
*
* @author dmw
*/
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/v1")
@Tag(name = "登录管理")
public class LoginController {
private final UserService userService;
private final TenantService tenantService;
private final CosInternelService cosInternelService;
private final SystemConfigRepository systemConfigRepository;
private final StringRedisTemplate redisTemplate;
private final LockFactory lockFactory;
/**
*
*
* @param loginModel
* @param request
* @return
*/
@Operation(summary = "用户登录")
@PostMapping("/users/login")
public GeneralResult<Map<String, Object>> userLogin(@RequestBody LoginModel loginModel,
HttpServletRequest request) {
log.info("开始执行登录请求");
long start;
String account = loginModel.getAccount();
String password = loginModel.getPassword();
log.info("开始调用UserService");
GeneralResult<Map<String, Object>> loginResult = userService
.login(account, password, request.getSession().getId(), IpTool.getIP(request), loginModel.getIsManager());
log.info("结束调用UserService");
if (loginResult.isFailed()) {
if (null == loginResult.getData()) {
String path = "Login_" + account;
try (com.megatron.framework.lock.AutoCloseLock lock = lockFactory.getACLock(path)) {
Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
start = System.currentTimeMillis();
String value = redisTemplate.opsForValue().get(RequestContext.Catalog.User.name() + account);
log.info("查询Redis耗时{}ms", System.currentTimeMillis() - start);
SystemConfig errorNumber = systemConfigRepository.queryByCode("pwdErrorNumber");
int error = Integer.parseInt(errorNumber.getValue());
if (!StringUtils.hasText(value)) {
//密码操作失败
start = System.currentTimeMillis();
redisTemplate.opsForValue()
.set(RequestContext.Catalog.User.name() + account, String.valueOf(1), 60, TimeUnit.SECONDS);
log.info("写入Redis耗时{}ms", System.currentTimeMillis() - start);
loginResult = new GeneralResult<>(false, loginResult.getMessage() + "已操作【1】次");
} else if (Integer.parseInt(value) >= error) {
Result lockResult = userService.lockByAccount(account);
boolean success = lockResult.isSuccess();
start = System.currentTimeMillis();
redisTemplate.delete(RequestContext.Catalog.User.name() + account);
log.info("删除Redis耗时{}ms", System.currentTimeMillis() - start);
if (success) {
loginResult = new GeneralResult<>(false, "账号或者密码错误已达【" + error + "】次,若用户存在将被冻结,请联系管理员解冻");
} else {
loginResult = new GeneralResult<>(false, "认证服务账号缓存存在问题");
}
} else {
start = System.currentTimeMillis();
redisTemplate.boundValueOps(RequestContext.Catalog.User.name() + account).increment(1L);
log.info("写入Redis耗时{}ms", System.currentTimeMillis() - start);
String num = redisTemplate.opsForValue().get(RequestContext.Catalog.User.name() + account);
loginResult = new GeneralResult<>(false, loginResult.getMessage() + ",已操作【" + num + "】次");
}
log.info("登录请求处理完成");
return loginResult;
} catch (Exception e) {
log.error("Get login error message", e);
log.info("登录请求处理完成");
return loginResult;
}
}
}
start = System.currentTimeMillis();
redisTemplate.delete(RequestContext.Catalog.User.name() + account);
log.info("删除Redis耗时{}ms", System.currentTimeMillis() - start);
log.info("登录请求处理完成");
return loginResult;
}
/**
*
*
* @param requestContext
* @return
*/
@Operation(summary = "用户退出系统")
@PostMapping("/users/logout")
public Result userLogout(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.logout(requestContext.getTarget());
}
/**
*
*
* @param loginModel
* @param request
* @return token
*/
@Operation(summary = "租户登录")
@PostMapping("/tenants/login")
public GeneralResult<Map<String, Object>> tenantLogin(
@RequestBody LoginModel loginModel, HttpServletRequest request) {
String account = loginModel.getAccount();
String password = loginModel.getPassword();
GeneralResult<Map<String, Object>> loginResult =
tenantService.login(account, password, request.getSession().getId(), IpTool.getIP(request));
if (loginResult.isFailed()) {
if (null == loginResult.getData()) {
String path = "Login_" + account;
try (com.megatron.framework.lock.AutoCloseLock lock = lockFactory.getACLock(path)) {
Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
String value = redisTemplate.opsForValue().get(RequestContext.Catalog.Tenant.name() + account);
SystemConfig errorNumber = systemConfigRepository.queryByCode("pwdErrorNumber");
int error = Integer.parseInt(errorNumber.getValue());
if (!StringUtils.hasText(value)) {
//密码操作失败
redisTemplate.opsForValue()
.set(RequestContext.Catalog.Tenant.name() + account, String.valueOf(1), 60,
TimeUnit.SECONDS);
loginResult = new GeneralResult<>(false, loginResult.getMessage() + ",已操作【1】次");
} else if (Integer.parseInt(value) >= error) {
Result lockResult = tenantService.lockByAccount(account);
boolean success = lockResult.isSuccess();
redisTemplate.delete(RequestContext.Catalog.Tenant.name() + account);
if (success) {
loginResult = new GeneralResult<>(false, "账号或者密码错误已达【" + error + "】次,若租户存在将被冻结,请联系管理员解冻");
} else {
loginResult = new GeneralResult<>(false, "认证服务存在问题");
}
} else {
redisTemplate.boundValueOps(RequestContext.Catalog.Tenant.name() + account).increment(1L);
String num = redisTemplate.opsForValue().get(RequestContext.Catalog.Tenant.name() + account);
loginResult = new GeneralResult<>(false, loginResult.getMessage() + ",已操作【" + num + "】次");
}
return loginResult;
} catch (Exception e) {
log.error("Get error message", e);
return loginResult;
}
}
}
redisTemplate.delete(RequestContext.Catalog.Tenant.name() + account);
return loginResult;
}
/**
*
*
* @param requestContext
* @return
*/
@Operation(summary = "租户登出")
@PostMapping("/tenants/logout")
public Result tenantLogout(
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.logout(requestContext.getTarget());
}
/**
*
*
* @param requestContext
* @param password
* @return
*/
@Operation(summary = "校验用户密码")
@GetMapping("/check/password")
public GeneralResult checkPassword(@Value(Common.REQ_CONTEXT) RequestContext requestContext,
@RequestParam String password
) {
switch (requestContext.getCatalog()) {
case Tenant:
return tenantService.checkPassword(requestContext, password);
case Manager:
case User:
return userService.checkPassword(requestContext, password);
default:
}
return new GeneralResult(false, "校验用户密码异常");
}
/**
* key
*
* @param apiKey
* @return key
*/
@Operation(summary = "获取key")
@GetMapping("/key")
public GeneralResult<AccountSecurity> key(@RequestParam(value = "apiKey") String apiKey) {
return tenantService.apiKey(apiKey);
}
/**
*
*
* @param requestContext
* @return
*/
@Operation(summary = "获取登录账号信息详情")
@GetMapping("/login/detail")
public GeneralResult<Map<String, Object>> loginDetail(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
Map<String, Object> resultMap = MapTools.simpleMap("accountCategory", requestContext.getCatalog());
if (Objects.requireNonNull(requestContext.getCatalog()) == RequestContext.Catalog.Tenant) {
resultMap.put(requestContext.getCatalog().name(),
tenantService.detail(requestContext.getTarget()).getData());
GeneralResult<TenantAccount> accountDetail =
cosInternelService.tenantAccountDetail(requestContext.getTarget(), requestContext.getApiKey());
resultMap.put("tenantAccount", accountDetail.isSuccess() ? accountDetail.getData() : null);
} else {
resultMap
.put(requestContext.getCatalog().name(), userService.detail(requestContext.getTarget()).getData());
}
Long projectId = Long.parseLong(
Optional.ofNullable(redisTemplate.opsForValue().get("current_project_" + requestContext.getApiKey()))
.orElse("0"));
resultMap.put("projectId", projectId);
return new GeneralResult<>(true, resultMap, "获取登录账号信息成功");
}
}

View File

@ -0,0 +1,90 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Message;
import com.bocloud.sms.interfaces.MessageService;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
* @author tyl
*/
@RestController
@RequestMapping("/v1/messages")
@Tag(name = "消息管理")
public class MessageController {
private final MessageService messageService;
public MessageController(MessageService messageService) {
this.messageService = messageService;
}
/**
*
*
* @param pager
* @param context
* @return
*/
@GetMapping
@Operation(summary = "获取消息列表")
public GeneralResult<GridBean<Message>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return messageService.list(pager, context);
}
/**
*
*
* @param id id
* @param context
* @return
*/
@DeleteMapping("/{id}")
@Operation(summary = "删除消息")
public Result remove(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return messageService.remove(id, context.getTarget());
}
/**
*
*
* @param id id
* @param context
* @return
*/
@GetMapping("/{id}")
@Operation(summary = "获取消息详情")
public GeneralResult<Message> detail(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return messageService.detail(id, context);
}
/**
*
*
* @param context
* @return
*/
@PatchMapping
@Operation(summary = "更改消息状态")
public Result readAll(@Value(Common.REQ_CONTEXT) RequestContext context) {
return messageService.messageRead(context);
}
/**
*
*
* @param context
* @return
*/
@GetMapping(value = "/stats")
@Operation(summary = "统计消息数量")
public GeneralResult<Message> statistics(@Value(Common.REQ_CONTEXT) RequestContext context) {
return messageService.statistics(context);
}
}

View File

@ -0,0 +1,114 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.NameRule;
import com.bocloud.sms.interfaces.NameRuleService;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
*
*
* @author wangyu
* @version 3.0.0-SNAPSHOT
* @since 2018/7/2
*/
@RestController
@RequestMapping("/v1/namings")
@Tag(name = "命名规则")
public class NameRuleController {
private final NameRuleService nameRuleService;
public NameRuleController(NameRuleService nameRuleService) {
this.nameRuleService = nameRuleService;
}
/**
*
*
* @param pager
* @return
*/
@Operation(summary = "获取命名规则列表")
@GetMapping
public GeneralResult<GridBean<NameRule>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return nameRuleService.list(pager, context);
}
/**
*
*
* @param nameRule
* @param context
* @return
*/
@Operation(summary = "添加命名规则")
@PostMapping
public GeneralResult<NameRule> create(@RequestBody NameRule nameRule,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return nameRuleService.create(nameRule, context);
}
/**
*
*
* @param id id
* @param nameRule
* @param context
* @return
*/
@Operation(summary = "修改命名规则")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id,
@RequestBody NameRule nameRule, @Value(Common.REQ_CONTEXT) RequestContext context) {
nameRule.setId(id);
return nameRuleService.modify(nameRule, context);
}
/**
*
*
* @param id id
* @param tenantId id
* @param userId id
* @param projectId id
* @return
*/
@Operation(summary = "根据命名规则生成云主机名称")
@PatchMapping("/{id}")
public GeneralResult<String> patch(@PathVariable(value = Common.ID) Long id,
@RequestParam(value = "tenantId") Long tenantId,
@RequestParam(value = "userId") Long userId,
@RequestParam(value = "projectId") Long projectId, RequestContext context) {
return nameRuleService.generate(id, tenantId, userId, projectId, context);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "删除命名规则")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id) {
return nameRuleService.remove(id);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查看命名规则详情")
@GetMapping("/{id}")
public GeneralResult<NameRule> detail(@PathVariable(value = Common.ID) Long id) {
return nameRuleService.detail(id);
}
}

View File

@ -0,0 +1,196 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONArray;
import com.bocloud.sms.entity.Permission;
import com.bocloud.sms.interfaces.PermissionService;
import com.bocloud.sms.model.*;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
*
* @author tyl
*/
@RestController
@Tag(name = "权限管理")
@RequestMapping("/v1/permissions")
public class PermissionController {
private final PermissionService permissionService;
public PermissionController(PermissionService permissionService) {
this.permissionService = permissionService;
}
/**
*
*
* @param parentId id
* @param tenant
* @return
*/
@Operation(summary = "查询权限列表")
@GetMapping("/tree")
public GeneralResult<List<PermissionBean>> list(@RequestParam(value = Common.PARENTID, required = false) Long parentId, @RequestParam(value = "category", required = false) String category, @RequestParam(value = "tenant", required = false) Boolean tenant) {
return permissionService.list(parentId, category, tenant);
}
/**
*
*
* @return
*/
@Operation(summary = "查询图标")
@GetMapping("/icons")
public GeneralResult<List<PermissionIcon>> listIcon(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return permissionService.listIcon(requestContext);
}
/**
*
*
* @return
*/
@Operation(summary = "查询父节点")
@GetMapping("/parents")
public GeneralResult<List<PermissionParentsBean>> listParents(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return permissionService.listParents(requestContext);
}
/**
*
*
* @param permissionModel
* @param requestContext
* @return
*/
@Operation(summary = "添加权限")
@PostMapping
public Result create(@RequestBody PermissionModel permissionModel, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return permissionService.create(permissionModel, requestContext);
}
/**
*
*
* @param id id
* @param permissionModel
* @param requestContext
* @return
*/
@Operation(summary = "权限修改")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id, @RequestBody PermissionModel permissionModel, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return permissionService.modify(id, permissionModel, requestContext);
}
/**
*
*
* @param id id
* @param requestContext
* @return
*/
@Operation(summary = "删除权限")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return permissionService.remove(id, requestContext);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查询权限详细信息")
@GetMapping("/{id}")
public GeneralResult<Permission> detail(@PathVariable(value = Common.ID) Long id) {
return permissionService.detail(id);
}
/**
*
*
* @param parentId id
* @param tenant
*/
@Operation(summary = "查询权限列表")
@GetMapping
public GeneralResult<List<PermissionBean>> listPermissions(@RequestParam(value = Common.PARENTID, required = false) Long parentId, @RequestParam(value = "category", required = false) String category, @RequestParam(value = "tenant", required = false) Boolean tenant) {
return permissionService.list(parentId, category, tenant);
}
/**
*
*
* @param condition
*/
@Operation(summary = "字典查询权限列表")
@GetMapping("/condition")
public GeneralResult<List<Permission>> listPermissionsByCondition(@RequestParam(value = Common.CONDITION, required = false) String condition) {
return permissionService.listPermissionsByCondition(condition);
}
/**
* ServiceId
*
* @param serviceId id
* @return
*/
@Operation(summary = "查询服务菜单权限")
@GetMapping("/info")
public GeneralResult<Permission> getServicePermissions(@RequestParam(value = "serviceId", required = false) Long serviceId) {
return permissionService.getServicePermission(serviceId);
}
/**
* api
*
* @return
*/
@Operation(summary = "查询服务模块API权限列表")
@GetMapping("/modules")
public GeneralResult<JSONArray> getApiList() {
return permissionService.getApiList();
}
/**
* codeAPI
*
* @param serviceCodes
* @return
*/
@Operation(summary = "根据服务code查询服务模块API权限列表")
@GetMapping("/modules/services")
public GeneralResult<JSONArray> getApiList(@RequestParam(value = "serviceCodes") String serviceCodes) {
List<String> codes = JSONArray.parseArray(serviceCodes).toJavaList(String.class);
if (!codes.isEmpty()) {
return permissionService.getApiList(codes);
}
return new GeneralResult<>(false, "参数格式错误");
}
/**
*
*
* @param permissionPlugins
* @param requestContext
* @return
*/
@Operation(summary = "插件绑定权限")
@PutMapping("/binding/plugins")
public Result bindingPlugins(@RequestBody PermissionPlugins permissionPlugins, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return permissionService.bindingPlugins(permissionPlugins.getPermissionIdList(), permissionPlugins.getPluginsCode(), permissionPlugins.getTenant(), requestContext);
}
}

View File

@ -0,0 +1,274 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Dictionary;
import com.bocloud.sms.entity.Plugin;
import com.bocloud.sms.interfaces.PluginService;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import com.megatron.common.utils.MapTools;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
*
*
* @author zhangyf
* @since 2022-05-20
*/
@Slf4j
@RestController
@RequestMapping("/v2/plugins")
@Tag(name = "插件管理")
public class PluginController {
private final PluginService pluginService;
@Value("${spring.upload.path:/home/cmp}")
private String path;
@Value("${plugin.repository.path:/home/cmp/plugins/repository/}")
private String pluginRepoPath;
public PluginController(PluginService pluginService) {
this.pluginService = pluginService;
}
/*-------------------------------------------- 不可见插件列表接口 --------------------------------------------*/
/**
* Plugin
*
* @param name
* @param vendorType
* @param service
* @param filepath
* @return
*/
@PostMapping
@Operation(summary = "新增插件")
public Result create(@RequestParam(value = "name") String name,
@RequestParam(value = "vendorType", required = false) String vendorType,
@RequestParam(value = "service", required = false) String service,
@RequestParam(value = "filepath", required = false) String filepath) throws IOException {
File tmpFile = new File(path + File.separator + filepath);
File destFile = new File(pluginRepoPath + File.separator + service, tmpFile.getName());
try {
if (!destFile.getParentFile().exists()) {
if (!destFile.getParentFile().mkdirs()) {
log.error("mkdir {} failed}", destFile.getParentFile());
}
}
FileUtils.copyFile(tmpFile, destFile);
FileUtils.delete(tmpFile);
if (FileUtils.isEmptyDirectory(tmpFile.getParentFile())) {
FileUtils.deleteDirectory(tmpFile.getParentFile());
}
Plugin plugin = new Plugin();
plugin.setService(service);
plugin.setName(name);
plugin.setService(service);
plugin.setVendorType(vendorType);
plugin.setSize(FileUtils.sizeOf(destFile));
plugin.setPath(destFile.getName());
return pluginService.create(plugin);
} catch (RuntimeException | IOException e) {
if (destFile.exists() && !destFile.delete()) {
log.warn("临时文件删除失败:{}", destFile.getPath());
}
throw e;
}
}
/**
* Plugin
*
* @param id ID
* @param name
* @param vendorType
* @param service
* @param filepath
* @return
*/
@PutMapping("/{id}")
@Operation(summary = "修改插件")
public Result modify(@PathVariable(value = Common.ID) Long id, @RequestParam(value = "name") String name,
@RequestParam(value = "vendorType", required = false) String vendorType,
@RequestParam(value = "service", required = false) String service,
@RequestParam(value = "filepath", required = false) String filepath) throws IOException {
boolean hasPackage = filepath != null;
File tmpFile = filepath != null ? new File(path + File.separator + filepath) : null;
File destFile = null;
if (hasPackage) {
destFile = new File(pluginRepoPath + File.separator + service, tmpFile.getName());
}
try {
if (hasPackage) {
if (!destFile.getParentFile().exists()) {
if (!destFile.getParentFile().mkdirs()) {
log.error("mkdir {} failed}", destFile.getParentFile());
}
}
FileUtils.copyFile(tmpFile, destFile);
FileUtils.delete(tmpFile);
if (FileUtils.isEmptyDirectory(tmpFile.getParentFile())) {
FileUtils.deleteDirectory(tmpFile.getParentFile());
}
}
Plugin plugin = new Plugin();
plugin.setService(service);
plugin.setName(name);
plugin.setVendorType(vendorType);
plugin.setSize(hasPackage ? FileUtils.sizeOf(destFile) : null);
plugin.setPath(hasPackage ? destFile.getName() : null);
return pluginService.modify(id, plugin, hasPackage);
} catch (RuntimeException | IOException e) {
if (hasPackage) {
if (destFile.exists() && !destFile.delete()) {
log.warn("临时文件删除失败:{}", destFile.getPath());
}
}
throw e;
}
}
/**
* Plugin
*
* @param id id
* @return
*/
@DeleteMapping("/{id}")
@Operation(summary = "删除插件")
public Result remove(@PathVariable(value = Common.ID) Long id) {
return pluginService.remove(id);
}
/**
* Plugin
*
* @param idList id
* @return /
*/
@DeleteMapping("/batch")
@Operation(summary = "批量删除插件")
public Result batchRemove(@RequestBody List<Long> idList) {
return pluginService.batchRemove(idList);
}
@GetMapping("/{service}/installed")
@Operation(summary = "已安装插件列表")
public GeneralResult<Map<String, List<Plugin>>> listInstalled(@PathVariable(value = "service") String service) {
Map<String, List<Plugin>> pluginList = pluginService.listInstalled(service);
return new GeneralResult<>(true, pluginList, "查询成功");
}
/**
*
*
* @param service name
* @return
*/
@GetMapping("/{service}/update")
@Operation(summary = "可更新插件列表")
public GeneralResult<Map<String, List<Plugin>>> listUpdate(@PathVariable(value = "service") String service) {
Map<String, List<Plugin>> pluginList = pluginService.listUpdate(service);
return new GeneralResult<>(true, pluginList, "查询成功");
}
/**
*
*
* @param service
* @return
*/
@GetMapping("/{service}/install")
@Operation(summary = "已安装插件列表")
public GeneralResult<Map<String, List<Plugin>>> listCanInstall(@PathVariable(value = "service") String service) {
Map<String, List<Plugin>> pluginList = pluginService.listCanInstall(service);
return new GeneralResult<>(true, pluginList, "查询成功");
}
/**
*
*
* @param pager
* @return
*/
@GetMapping
@Operation(summary = "插件列表")
public GeneralResult<GridBean<Plugin>> list(Pager pager) {
return pluginService.list(pager);
}
/**
*
*
* @param code
* @return
*/
@GetMapping("/{code}/upgrade")
@Operation(summary = "插件列表")
public GeneralResult<GridBean<Plugin>> upgradeList(@PathVariable(value = "code") String code, Pager pager) {
pager.getParams().add(new Param(MapTools.simpleMap("code", code), Sign.EQ));
return pluginService.list(pager);
}
/**
*
*
* @param code
* @return
*/
@GetMapping("/{code}/degradation")
@Operation(summary = "插件列表")
public GeneralResult<GridBean<Plugin>> degradationList(@PathVariable(value = "code") String code, Pager pager) {
pager.getParams().add(new Param(MapTools.simpleMap("code", code), Sign.EQ));
return pluginService.list(pager);
}
/**
*
*
* @param id id
* @return
*/
@GetMapping("/{id}")
@Operation(summary = "插件详情")
public GeneralResult<Plugin> detail(@PathVariable(value = Common.ID) Long id) {
return new GeneralResult<>(true, pluginService.detail(id), "查询成功");
}
/**
*
*
* @param pager
* @return
*/
@GetMapping("/vendors")
@Operation(summary = "插件支持的云平台列表")
public GeneralResult<List<Dictionary>> getVendorList(Pager pager) {
return pluginService.getVendorList(pager);
}
/**
* license
*
* @param pager
* @return license
*/
@GetMapping("/license")
@Operation(summary = "获取Plugin插件列表")
public GeneralResult<List<Plugin>> licenseList(Pager pager) {
List<Plugin> plugins = pluginService.listLicense(pager);
return new GeneralResult<>(true, plugins, "查询成功");
}
}

View File

@ -0,0 +1,81 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.service.internel.PluginInsideService;
import com.megatron.common.model.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/v1/plugins")
@Tag(name = "插件")
@Slf4j
public class PluginInsideController {
private final PluginInsideService pluginInsideService;
private final ThreadPoolTaskExecutor taskExecutor;
public PluginInsideController(PluginInsideService pluginInsideService, ThreadPoolTaskExecutor taskExecutor) {
this.pluginInsideService = pluginInsideService;
this.taskExecutor = taskExecutor;
}
@PutMapping("/{pluginId}/start")
@Operation(summary = "启动插件")
public Result start(@PathVariable(value = "pluginId") String pluginId,
@RequestParam(value = "service") String service,
@RequestParam(value = "instance") String instance) {
taskExecutor.execute(() -> pluginInsideService.start(service, instance, pluginId));
return new Result(true, "启动插件任务已下发");
}
@PutMapping("/{pluginId}/stop")
@Operation(summary = "停止插件")
public Result stop(@PathVariable(value = "pluginId") String pluginId,
@RequestParam(value = "service") String service,
@RequestParam(value = "instance") String instance) {
taskExecutor.execute(() -> pluginInsideService.stop(service, instance, pluginId));
return new Result(true, "停止插件任务已下发");
}
@PutMapping("/install")
@Operation(summary = "安装插件")
public Result install(@RequestParam(value = "service") String service,
@RequestParam(value = "instance") String instance,
@RequestParam(value = "pluginPath") String pluginPath) {
taskExecutor.execute(() -> pluginInsideService.install(service, instance, pluginPath));
return new Result(true, "安装插件任务已下发");
}
@PutMapping("/{pluginId}/uninstall")
@Operation(summary = "卸载插件")
public Result uninstall(@PathVariable(value = "pluginId") String pluginId,
@RequestParam(value = "service") String service,
@RequestParam(value = "instance") String instance) {
taskExecutor.execute(() -> pluginInsideService.uninstall(service, instance, pluginId));
return new Result(true, "卸载插件任务已下发");
}
@PutMapping("/{pluginId}/upgrade")
@Operation(summary = "升级插件")
public Result upgrade(@PathVariable(value = "pluginId") String pluginId,
@RequestParam(value = "service") String service,
@RequestParam(value = "instance") String instance,
@RequestParam(value = "pluginPath") String pluginPath) {
taskExecutor.execute(() -> pluginInsideService.upgrade(service, instance, pluginId, pluginPath));
return new Result(true, "升级插件任务已下发");
}
@PutMapping("/{pluginId}/demote")
@Operation(summary = "降级插件")
public Result demote(@PathVariable(value = "pluginId") String pluginId,
@RequestParam(value = "service") String service,
@RequestParam(value = "instance") String instance,
@RequestParam(value = "pluginPath") String pluginPath) {
taskExecutor.execute(() -> pluginInsideService.upgrade(service, instance, pluginId, pluginPath));
return new Result(true, "降级插件任务已下发");
}
}

View File

@ -0,0 +1,42 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.interfaces.PortalElementConfigService;
import com.megatron.common.model.GeneralResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* controller
*
* @author lyy
* @version 2.0
* @time 20171227
*/
@RestController
@RequestMapping("/v1/portal/elements")
@Tag(name = "组件配置管理")
public class PortalElementConfigController {
@Autowired
private PortalElementConfigService portalElementConfigService;
/**
*
*
* @param poolId id
* @return
*/
@Operation(summary = "组件配置元素列表展示")
@GetMapping
public GeneralResult list(@RequestParam(value = "poolId") Long poolId) {
if (null != poolId) {
return portalElementConfigService.list(poolId);
} else {
return new GeneralResult(false, "参数格式不正确");
}
}
}

View File

@ -0,0 +1,39 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.interfaces.PortalElementPoolService;
import com.megatron.common.model.GeneralResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* controller
*
* @author lyy
* @version 2.0
* @time 20171227
*/
@RestController
@RequestMapping("/v1/portal/elementpools")
@Tag(name = "组件池管理")
public class PortalElementPoolController {
@Autowired
private PortalElementPoolService portalElementPoolService;
/**
*
*
* @param module
* @return
*/
@Operation(summary = "组件池列表展示")
@GetMapping
public GeneralResult list(@RequestParam(value = "module", required = false) String module) {
return portalElementPoolService.list(module);
}
}

View File

@ -0,0 +1,81 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.sms.entity.PortalPanel;
import com.bocloud.sms.interfaces.PortalPanelService;
import com.bocloud.sms.model.PortalPanelBean;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* controller
*
* @author lyy
* @version 2.0
* @time 20171227
*/
@RestController
@RequestMapping("/v1/portal/panels")
@Tag(name = "主页配置管理")
public class PortalPanelController {
@Autowired
private PortalPanelService portalPanelService;
/**
*
*
* @param context
* @return
*/
@Operation(summary = "主页配置列表展示")
@GetMapping
public GeneralResult list(@RequestParam(value = "module", required = false) String module,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return portalPanelService.list(module, context);
}
/**
*
*
* @param portalPanelBean
* @param context
* @return
*/
@Operation(summary = "保存主页配置")
@PatchMapping
public GeneralResult save(@RequestBody PortalPanelBean portalPanelBean,
@Value(Common.REQ_CONTEXT) RequestContext context) {
if (null != portalPanelBean) {
if (portalPanelBean.getConfig() == null) {
return new GeneralResult(false, "参数格式不正确");
}
List<PortalPanel> portalPanels = JSONObject.parseArray(portalPanelBean.getConfig(), PortalPanel.class);
return portalPanelService.save(portalPanels, context.getTarget(), context.getTenant(), null, portalPanelBean.getModule());
} else {
return new GeneralResult(false, "参数格式不正确");
}
}
/**
*
*
* @param context
* @return
*/
@Operation(summary = "恢复默认设置")
@PutMapping("/{module}/reset")
public GeneralResult reset(@PathVariable(value = "module") String module, @Value(Common.REQ_CONTEXT) RequestContext context) {
return portalPanelService.reset(module, context);
}
}

View File

@ -0,0 +1,330 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.Business;
import com.bocloud.sms.entity.Project;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.interfaces.ProjectService;
import com.bocloud.sms.interfaces.UserService;
import com.bocloud.sms.model.ProjectModel;
import com.bocloud.sms.model.ProjectUserBean;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import com.megatron.common.utils.MapTools;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
/**
* @author tyl
*/
@RestController
@RequestMapping("/v1/projects")
@Tag(name = "项目关联")
@Slf4j
public class ProjectController {
private final ProjectService projectService;
private final UserService userService;
private final StringRedisTemplate redisTemplate;
public ProjectController(ProjectService projectService, UserService userService, StringRedisTemplate redisTemplate) {
this.projectService = projectService;
this.userService = userService;
this.redisTemplate = redisTemplate;
}
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Operation(summary = "获取项目列表")
@GetMapping
public GeneralResult<GridBean<Project>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext requestContext,
@RequestParam(value = "tenantId", required = false, defaultValue = "false") Boolean tenantId) {
return projectService.list(pager, requestContext, tenantId);
}
/**
*
*
* @param condition
* @return
*/
@Operation(summary = "字典查询项目信息")
@GetMapping("/condition")
public GeneralResult condition(@RequestParam(value = Common.CONDITION, required = false) String condition, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return projectService.condition(condition, requestContext);
}
/**
*
*
* @param projectModel
* @param requestContext
* @return
*/
@Operation(summary = "创建项目")
@PostMapping
public Result create(@RequestBody ProjectModel projectModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return projectService.create(projectModel, requestContext);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "切换项目")
@PatchMapping("/{id}")
public Result switchProject(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
String apiKey = requestContext.getApiKey();
Assert.isTrue(StringUtils.isNotEmpty(apiKey), "当前会话存在异常");
try {
redisTemplate.opsForValue().set("current_project_" + apiKey, String.valueOf(id));
return new Result(true, "项目切换成功");
} catch (Exception e) {
return new Result(false, "项目切换失败");
}
}
/**
*
*
* @param id id
* @param projectModel
* @param requestContext
* @return
*/
@Operation(summary = "修改项目信息")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id, @RequestBody ProjectModel projectModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return projectService.modify(id, projectModel, requestContext);
}
/**
*
*
* @param id id
* @param requestContext
* @return
*/
@Operation(summary = "删除项目")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return projectService.remove(id, requestContext);
}
/**
*
*
* @param ids id
* @param requestContext
* @return
*/
@Operation(summary = "批量删除项目")
@DeleteMapping
public Result batchRemove(@RequestBody List<Long> ids, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return projectService.batchRemove(ids, requestContext);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查看项目详情")
@GetMapping("/{id}")
public GeneralResult<Project> detail(@PathVariable(value = Common.ID) Long id) {
return projectService.detail(id);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "查看项目所在业务信息")
@GetMapping("/{id}/business")
public GeneralResult<Business> business(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return projectService.getBusinessDetail(id, requestContext);
}
/**
*
*
* @param id id
* @param projectUserBean
* @return
*/
@Operation(summary = "项目配追用户")
@PostMapping("/{id}/users")
public Result configUser(@PathVariable(value = Common.ID) Long id, @RequestBody ProjectUserBean projectUserBean) {
return projectService.configUser(id, projectUserBean);
}
/**
*
*
* @param id id
* @param userId id
* @return
*/
@Operation(summary = "项目用户设置为项目经理")
@PatchMapping("/{id}/users/{userId}")
public Result configUser(@PathVariable(value = Common.ID) Long id, @PathVariable(value = "userId") Long userId) {
return projectService.configProjectManager(id, userId);
}
/**
* ID
*
* @param id id
* @return
*/
@Operation(summary = "查询项目下关联用户")
@GetMapping("/{id}/users")
public GeneralResult<List<User>> listByProject(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.listProjectUser(id, requestContext);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "查询项目经理")
@GetMapping("/{id}/managers")
public GeneralResult<List<User>> listProjectManager(@PathVariable(value = Common.ID) Long id) {
return userService.listProjectManager(id);
}
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Deprecated
@Operation(summary = "导出项目列表")
@RequestMapping(value = "/export", method = {RequestMethod.GET})
public void export(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext requestContext,
HttpServletRequest request, HttpServletResponse response) {
List<Param> paramList = pager.getParams();
if (paramList.size() == 0) {
paramList.add(new Param(MapTools.simpleMap("tenantId", 0), Sign.UEQ));
}
try {
XSSFWorkbook workbook = projectService.export(paramList, requestContext);
// 下载表格到浏览器
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream");
String fileName = "项目统计数据" + System.currentTimeMillis() + ".xlsx";
final String userAgent = request.getHeader("user-agent").toLowerCase();
if (userAgent.contains("trident") || userAgent.contains("edge")) {
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
} else {
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}
response.setHeader("Content-Disposition", "attachment;fileName=" + fileName);
OutputStream os = response.getOutputStream();
workbook.write(os);
os.flush();
os.close();
} catch (Exception e) {
log.error("export project error,", e);
}
}
/**
*
*
* @param request
* @param response
* @param requestContext
*/
@Operation(summary = "下载项目列表模板")
@RequestMapping(value = "/import/template", method = {RequestMethod.GET})
public void importTemp(HttpServletRequest request, HttpServletResponse response,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
projectService.importTemp(response);
}
/**
*
*
* @param requestContext
* @param request
* @return
*/
@Operation(summary = "导入项目列表")
@PostMapping(value = "/import")
public Result importData(@Value(Common.REQ_CONTEXT) RequestContext requestContext, HttpServletRequest request) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
List<MultipartFile> fileList = multipartRequest.getFiles("file");
if (fileList.isEmpty()) {
return new Result(false, "文件错误");
}
MultipartFile multipartFile = fileList.get(0);
String originalFilename = multipartFile.getOriginalFilename();
// 判断文件名
if (originalFilename == null || !(originalFilename.endsWith(".xls") || originalFilename.endsWith(".xlsx"))) {
return new Result(false, "文件错误");
}
return projectService.importData(multipartFile, requestContext);
}
/**
*
*
* @param requestContext
* @return
*/
@Operation(summary = "根据组织名称查询某组织下所有项目")
@GetMapping("/by/depart")
public GeneralResult<List<Project>> queryByDepart(@Value(Common.REQ_CONTEXT) RequestContext requestContext,
@RequestParam(value = "departName") String departName) {
return projectService.queryByDepart(departName);
}
@Operation(summary = "根据组织ID查询某组织下所有项目")
@GetMapping("/by/depart/ids")
public GeneralResult<List<Project>> queryByDepart(Pager pager, @RequestParam(value = "departIds") List<Long> departIds) {
return projectService.queryByDepartIds(pager, departIds);
}
@Operation(summary = "根据项目名称获取项目")
@GetMapping("/by/name")
public GeneralResult<Project> getByProjectName(@RequestParam(value = "projectName") String projectName) {
return projectService.getByProjectName(projectName);
}
}

View File

@ -0,0 +1,179 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONArray;
import com.bocloud.sms.entity.Role;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.interfaces.RoleService;
import com.bocloud.sms.model.ApiInfo;
import com.bocloud.sms.model.CloudServiceBean;
import com.bocloud.sms.model.RoleModel;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author tyl
*/
@RestController
@RequestMapping("/v1/roles")
@Tag(name = "角色管理")
public class RoleController {
private final RoleService roleService;
public RoleController(RoleService roleService) {
this.roleService = roleService;
}
/**
*
*
* @param roleModel
* @param requestContext
* @return
*/
@Operation(summary = "创建角色")
@PostMapping
public Result create(@RequestBody RoleModel roleModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return roleService.create(roleModel, requestContext);
}
/**
*
*
* @param roleModel
* @param requestContext
* @return
*/
@Operation(summary = "角色修改")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id,
@RequestBody RoleModel roleModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return roleService.modify(id, roleModel, requestContext);
}
/**
*
*
* @param id id
* @param requestContext
* @return
*/
@Operation(summary = "角色删除")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return roleService.remove(id, requestContext);
}
/**
*
*
* @param id id
* @return
*/
@Operation(summary = "角色详情")
@GetMapping("/{id}")
public GeneralResult<Role> detail(@PathVariable(value = Common.ID) Long id) {
return roleService.detail(id);
}
/**
*
*
* @param id id
* @param ids id
* @param requestContext
* @return
*/
@Operation(summary = "角色授权")
@PatchMapping("/{id}")
public Result accredit(@PathVariable(value = Common.ID) Long id, @RequestBody List<Long> ids,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return roleService.accredit(id, ids, requestContext);
}
/**
*
*
* @param id id
* @param requestContext
* @return
*/
@Operation(summary = "获取权限列表")
@GetMapping("/{id}/permissions")
public GeneralResult<List<CloudServiceBean>> permissions(@PathVariable(value = Common.ID) Long id, @RequestParam(value = "menu", required = false) boolean menu,
@RequestParam(value = "tenant", required = false) boolean tenant, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return roleService.listPermissions(id, menu, tenant, requestContext);
}
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Operation(summary = "获取角色列表")
@GetMapping
public GeneralResult<GridBean<Role>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return roleService.list(pager, requestContext);
}
/**
* boot comment Api
*
* @param requestContext
* @return
*/
@GetMapping("/ids")
public GeneralResult<List<Long>> roleIds(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return roleService.roleIds(requestContext);
}
/**
* API
*
* @param id id
* @param apis apiid
* @return
*/
@Operation(summary = "API授权")
@PatchMapping("/{id}/apis")
public Result accreditRole(@PathVariable(value = Common.ID) Long id, @RequestBody List<ApiInfo> apis) {
return roleService.accreditRole(id, apis);
}
/**
* API
*
* @param id id
* @param tags
* @return
*/
@Operation(summary = "查询API权限列表")
@GetMapping("/{id}/apis")
public GeneralResult<JSONArray> getModuleList(@PathVariable(value = Common.ID) Long id, @RequestParam(value = "tags", required = false) String tags) {
return roleService.getApiPermission(id, tags);
}
/**
*
*
* @param pager
* @param id id
* @return
*/
@Operation(summary = "查询指定角色下的用户")
@GetMapping("/{id}/users")
public GeneralResult<GridBean<User>> listUsersByRoleId(Pager pager, @PathVariable(value = Common.ID) Long id) {
return roleService.listUsersByRoleId(pager, id);
}
}

View File

@ -0,0 +1,27 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.interfaces.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.view.RedirectView;
@RequiredArgsConstructor
@RestController
@RequestMapping("/v1/single/login")
@Tag(name = "单点登录")
public class SingleLoginController {
@Autowired
private SingleLoginService service;
@GetMapping()
@Operation(summary = "单点登录")
public RedirectView doLoginCallback(@RequestParam String token, HttpServletRequest request) throws Exception {
return service.singleLogin(token, request);
}
}

View File

@ -0,0 +1,35 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.interfaces.SysDateViewService;
import com.megatron.common.model.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName: SysDateViewController
* @Description:
* @Author lxy
* @Date 2021/9/29 10:09
*/
@RestController
@RequestMapping("/v1/system")
@Tag(name = "系统数据统计概览")
public class SysDateViewController {
@Autowired
private SysDateViewService sysDateViewService;
/**
* 访
*
* @return 访
*/
@Operation(summary = "用户访问控制数据统计")
@GetMapping("/count")
public Result systemCount() {
return sysDateViewService.systemCount();
}
}

View File

@ -0,0 +1,104 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONArray;
import com.bocloud.sms.interfaces.SystemConfigService;
import com.bocloud.sms.model.ConfigModel;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author lyy
* @Version 1.0
* @since 2017818
*/
@RestController
@RequestMapping("/v1")
@Tag(name = "系统配置管理")
public class SystemConfigController {
private final SystemConfigService systemConfigService;
public SystemConfigController(SystemConfigService systemConfigService) {
this.systemConfigService = systemConfigService;
}
/**
*
*
* @param requestContext
* @param request
* @return
*/
@Operation(summary = "更新系统配置")
@PutMapping("/system-configs")
public Result modify(@Value(Common.REQ_CONTEXT) RequestContext requestContext, HttpServletRequest request) {
List<ConfigModel> configs = JSONArray.parseArray(request.getParameter("configs"), ConfigModel.class);
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
return systemConfigService.batchUpdate(configs, fileMap, requestContext);
}
/**
* Ldap
*
* @return
*/
@Operation(summary = "同步Ldap")
@PostMapping("/configs/syncLdap")
public Result syncLdap() {
return systemConfigService.syncLdap();
}
/**
*
*
* @param category
* @param codes
* @return
*/
@Operation(summary = "批量查询系统配置")
@GetMapping("/configs")
public GeneralResult<Map<String, String>> getByCodes(@RequestParam(value = "category", required = false) String category, @RequestParam(value = "codes", required = false) ArrayList<String> codes) {
return systemConfigService.listConfigs(category, codes);
}
/**
*
*
* @param category
* @return
*/
@Operation(summary = "查询系统配置类型树")
@GetMapping("/configs/tree")
public GeneralResult<JSONArray> listCategoryTree(@RequestParam(value = "category") String category) {
return systemConfigService.listCategoryTree(category);
}
/**
*
*
* @param category
* @return
*/
@Operation(summary = "系统配置连接测试")
@GetMapping("/configs/test")
public Result configTest(@RequestParam(value = "category") String category) {
return systemConfigService.configTest(category);
}
}

View File

@ -0,0 +1,949 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.boot.model.BoCloudExchange;
import com.bocloud.cmp.boot.model.BoCloudService;
import com.bocloud.sms.interfaces.PrometheusService;
import com.bocloud.sms.interfaces.QueryService;
import com.bocloud.sms.monitor.*;
import com.bocloud.sms.service.monitor.*;
import com.google.common.collect.Lists;
import com.megatron.common.http.HttpClient;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.License;
import com.megatron.common.model.Result;
import com.megatron.common.utils.Common;
import com.megatron.common.utils.IDFactory;
import com.megatron.common.utils.ListTool;
import com.megatron.framework.core.CurrentService;
import com.megatron.framework.core.RegistryService;
import com.megatron.framework.core.Service;
import com.megatron.framework.license.LicenseDaemon;
import com.megatron.framework.registry.ZooKeeperClient;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.*;
import org.springframework.data.redis.connection.jedis.JedisClusterConnection;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisSentinelConnection;
import org.springframework.data.redis.connection.lettuce.LettuceClusterConnection;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceSentinelConnection;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
@Tag(name = "系统监控")
@RestController
@RequestMapping("/v1/system/monitor")
@Slf4j
public class SystemController {
private static final String NODE_EXPORTER = "node_exporter";
private static final String TELEGRAF = "telegraf";
private static final String BLACK_BOX = "blackbox";
private static final String MASTER = "master";
private static final String ERROR = "error";
private static final String WARNING = "warning";
private static final String RUNNING = "running";
/**
*
*/
private static final Long TIME_OUT = (long) (1000 * 10);
private final LicenseDaemon licenseDaemon;
@Autowired
private RegistryService registry;
@Autowired
private RabbitAdmin rabbitAdmin;
@Autowired
private ZooKeeperClient client;
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private Environment env;
@Autowired
private PrometheusMonitor prometheusMonitor;
@Autowired
private PrometheusConfig prometheusConfig;
@Autowired
private PrometheusService prometheusService;
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RegistryService registryService;
@Autowired
private MySqlConfiguration mySqlConfiguration;
@Autowired
private QueryService queryService;
public SystemController(CurrentService currentService) {
this.licenseDaemon = LicenseDaemon.instance(currentService);
}
/**
*
*
* @param start
* @param end
* @param ip
* @param step
* @return
*/
@GetMapping("/charts")
@Operation(summary = "查询主机状态统计信息")
public GeneralResult<?> getChars(String start, String end, String ip, String step) {
String cpuParam = "round((1 - avg(irate(node_cpu_seconds_total{instance=\"" + ip
+ "\",mode=\"idle\"}[5m])) by (instance))*100,0.01)";
String memParam = "round(100 - ((node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes)/node_memory_MemTotal_bytes{instance=\"" + ip
+ "\"}) * 100,0.01)";
String diskParam = "round(100 - sum(node_filesystem_free_bytes{ instance=\"" + ip
+ "\",fstype!~\"rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*\"}) "
+ "/ sum(node_filesystem_size_bytes{ instance=\"" + ip
+ "\",fstype!~\"rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*\"}) * 100,0.01)";
String networkParam1 = "sum(round(1/1024*irate(node_network_receive_bytes_total{instance=\"" + ip
+ "\",device=~\"en.*|em.*|eth.*|ten.*|one.*\"}[5m])))";
String networkParam2 = "sum(round(1/1024*irate(node_network_transmit_bytes_total{instance=\"" + ip
+ "\",device=~\"en.*|em.*|eth.*|ten.*|one.*\"}[5m])))";
Map<String, Object> charsMap = new HashMap<>(16, 0.75F);
charsMap.put("cpu", queryService.chart(Collections.singletonList(cpuParam), Collections.singletonList("cpu使用率"), start, end, "20", "%"));
charsMap.put("mem", queryService.chart(Collections.singletonList(memParam), Collections.singletonList("内存使用率"), start, end, "20", "%"));
charsMap.put("disk", queryService.chart(Collections.singletonList(diskParam), Collections.singletonList("磁盘使用率"), start, end, "20", "%"));
charsMap.put("network", queryService.chart(Arrays.asList(networkParam1, networkParam2), Arrays.asList("网络流入速率", "网络流出速率"), start, end, "20", "kb/s"));
return new GeneralResult<>(true, charsMap, "success");
}
/**
*
*
* @param host host
* @return
*/
@Operation(summary = "服务状态信息")
@GetMapping("/status")
public GeneralResult<?> status(@RequestParam(value = Common.VALUE) String host) {
HttpClient client = new HttpClient();
String value = "http://" + host + "/status";
Result result = client.get(value);
return result.isSuccess() ? JSONObject.parseObject(result.getMessage(), GeneralResult.class)
: new GeneralResult<>(false, result.getMessage());
}
/**
*
*
* @return
*/
@Operation(summary = "查询系统状态信息")
@GetMapping("/servers")
public GeneralResult<?> servers() {
Set<String> instances = prometheusService.filter("up{tag='cmp'}", "instance");
List<Map<String, Object>> servers = Lists.newArrayList();
Optional.ofNullable(instances).orElse(new HashSet<>()).forEach(host -> {
// 先判断主机是否启动
Double value = prometheusService.simpleQuery("up{tag='cmp'}", Collections.singletonMap("instance", host));
Map<String, Object> data = new HashMap<>(16, 0.75F);
Double cpuUsed = prometheusService.simpleQuery("round((1 - avg(irate(node_cpu_seconds_total{mode='idle'}[5m])) by (instance))*100,0.01)", Collections.singletonMap("instance", host));
Double memUsed = prometheusService.simpleQuery("round(100 - ((node_memory_MemFree_bytes+node_memory_Cached_bytes+node_memory_Buffers_bytes)/node_memory_MemTotal_bytes{}) * 100,0.01)", Collections.singletonMap("instance", host));
Double diskUsed = prometheusService.simpleQuery("round(100 - sum(node_filesystem_free_bytes{ instance='" + host
+ "',fstype!~'rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*'})"
+ "/ sum(node_filesystem_size_bytes{instance='" + host
+ "',fstype!~'rootfs|selinuxfs|autofs|rpc_pipefs|tmpfs|udev|none|devpts|sysfs|debugfs|fuse.*'}) * 100,0.01)");
data.put("host", host);
data.put("cpuUsed", cpuUsed);
data.put("memUsed", memUsed);
data.put("diskUsed", diskUsed);
data.put("status", (1D == value) ? RUNNING : ERROR);
servers.add(data);
});
return new GeneralResult<>(true, servers, "查询成功");
}
/**
*
*
* @return
*/
@Operation(summary = "查询服务状态信息")
@GetMapping("/services")
public GeneralResult<?> service() {
ServicesModel servicesModel = new ServicesModel();
License catalog = licenseDaemon.content();
List<String> services = catalog.getService();
Integer hosts = catalog.getCatalog().getHosts();
Integer instances = catalog.getCatalog().getInstances();
// 从Licenses里面获取AIO/STD
servicesModel.setHosts(hosts);
servicesModel.setInstances(instances);
List<ServicesModel.Service> serviceList = Lists.newArrayList();
License content = licenseDaemon.content();
if (services != null) {
if (services.contains(BoCloudService.CMP.getName())) {
serviceList.add(buildServiceModel(BoCloudService.CMP, "纳管服务", content));
}
if (services.contains(BoCloudService.SMS.getName())) {
serviceList.add(buildServiceModel(BoCloudService.SMS, "系统管理服务", content));
}
if (services.contains(BoCloudService.CMS.getName())) {
serviceList.add(buildServiceModel(BoCloudService.CMS, "监控服务", content));
}
if (services.contains(BoCloudService.COP.getName())) {
serviceList.add(buildServiceModel(BoCloudService.COP, "运维服务", content));
}
if (services.contains(BoCloudService.TSE.getName())) {
serviceList.add(buildServiceModel(BoCloudService.TSE, "任务引擎服务", content));
}
if (services.contains(BoCloudService.ROS.getName())) {
serviceList.add(buildServiceModel(BoCloudService.ROS, "编排服务", content));
}
if (services.contains(BoCloudService.COS.getName())) {
serviceList.add(buildServiceModel(BoCloudService.COS, "运营服务", content));
}
if (services.contains(BoCloudService.AMS.getName())) {
serviceList.add(buildServiceModel(BoCloudService.AMS, "资产服务", content));
}
if (services.contains(BoCloudService.BMS.getName())) {
serviceList.add(buildServiceModel(BoCloudService.BMS, "裸金属服务", content));
}
}
servicesModel.setService(serviceList);
return new GeneralResult<>(true, servicesModel, "查询成功");
}
/**
*
*
* @return
*/
@Operation(summary = "查询插件状态信息")
@GetMapping("/plugins")
public GeneralResult<?> plugins() {
List<PluginsModel> pluginsModel = Lists.newArrayList();
License catalog = licenseDaemon.content();
List<String> services = catalog.getService();
if (services != null) {
if (services.contains(BoCloudService.GAIA.getName())) {
pluginsModel.add(buildPluginsModel(BoCloudService.GAIA, "作业代理"));
}
if (services.contains(BoCloudService.PONTUS.getName())) {
pluginsModel.add(buildPluginsModel(BoCloudService.PONTUS, "存储代理"));
}
}
return new GeneralResult<>(true, pluginsModel, "查询成功");
}
/**
*
*
* @return
*/
@Operation(summary = "查询组件状态信息")
@GetMapping("/components")
public GeneralResult<?> components() {
List<ComponentModel> componentModels = Lists.newArrayList();
String druidUrl = env.getProperty("spring.datasource.druid.url");
assert druidUrl != null;
if (druidUrl.contains("mysql")) {
componentModels.add(buildComponentMysql());
}
componentModels.add(buildComponentPrometheus());
componentModels.add(buildComponentZookeeper());
componentModels.add(buildComponentRabbitmq());
componentModels.add(buildComponentAlertManager());
componentModels.add(buildComponentRedis());
return new GeneralResult<>(true, componentModels, "查询成功");
}
/**
*
*
* @return
*/
@Operation(summary = "查询网关状态信息")
@GetMapping("/gateway")
public GeneralResult<?> gateWayComponents() {
List<ComponentModel> componentModels = Lists.newArrayList();
componentModels.add(buildComponentGateway());
return new GeneralResult<>(true, componentModels, "查询成功");
}
/**
*
*
* @param service
* @return
*/
private List<String> getServices(BoCloudService service) {
try {
List<String> serviceInstances = registry.getServices(Service.create(service.getName()));
return ListTool.isEmpty(serviceInstances) ? new ArrayList<>() : serviceInstances;
} catch (RuntimeException e) {
log.error("get services error:" + e.getMessage());
return new ArrayList<>();
}
}
/**
*
*
* @param service
* @param alias
* @return
*/
private ServicesModel.Service buildServiceModel(@NonNull BoCloudService service, @NonNull String alias, License content) {
List<ServicesModel.Service.Instance> data = Lists.newArrayList();
try {
String status = RUNNING;
// 获取license里面规定的实例个数(从mac地址中获取)
int instances = content.getAddress().size();
List<String> servers = getServices(service);
log.info(service + " 获取到服务列表:" + servers);
int errorNum = 0;
for (String server : servers) {
server = server.replaceAll("http://", "").replaceAll("https://", "");
String state = this.registryService.getServiceState(service.getName(), server);
SystemBean systemBean;
ServicesModel.Service.Instance serviceInstance = new ServicesModel.Service.Instance();
try {
systemBean = JSONObject.parseObject(state).toJavaObject(SystemBean.class);
} catch (Exception e) {
log.error(service + "获取服务信息失败!" + e);
errorNum++;
serviceInstance.setHost(server);
serviceInstance.setStatus(ERROR);
data.add(serviceInstance);
continue;
}
serviceInstance.setHost(systemBean.getServiceInstance());
serviceInstance.setStatus(RUNNING);
serviceInstance.setCpuUsed(this.round(BigDecimal.valueOf(systemBean.getJvmCpuUsage()).doubleValue() * 100d));
serviceInstance.setMemUsed(this.round(BigDecimal.valueOf(txfloat(systemBean.getJvmMemoryUsed(), systemBean.getJvmMemoryMax())).doubleValue() * 100d));
serviceInstance.setLogger(service.getName() + ".server");
serviceInstance.setIsLeader(systemBean.getIsLeader());
data.add(serviceInstance);
}
if (0 < errorNum || data.size() < instances) {
if (data.size() <= instances) {
int difference = instances - data.size();
for (int i = 0; i < difference; i++) {
ServicesModel.Service.Instance errorInstance = new ServicesModel.Service.Instance();
errorInstance.setStatus(ERROR);
data.add(errorInstance);
}
}
status = WARNING;
}
if (errorNum >= data.size() || data.size() <= 0) {
status = ERROR;
}
return new ServicesModel.Service(alias, status, data);
} catch (Exception e) {
log.error("系统监控服务查询失败!" + service);
return new ServicesModel.Service(alias, ERROR, data);
}
}
/**
* Prometheus oCloudService
* servicegetServicesIP
*
* @param name
* @return
*/
private PluginsModel buildPluginsModel(String name) {
String pluginsName = switch (name) {
case "采集组件" -> TELEGRAF;
case "通断监控" -> BLACK_BOX;
default -> NODE_EXPORTER;
};
PluginsModel pluginsModel = new PluginsModel();
try {
List<PrometheusResult> results = prometheusService.query("up{job=\"" + pluginsName + "\"}");
List<PluginsModel.Plugin> data = Lists.newArrayList();
boolean status = !ListTool.isEmpty(results);
// 活跃个数应该与服务器个数相同,介于 0 和
int runningNums = Optional.ofNullable(results).orElse(new ArrayList<>()).size();
// size之间为 warning0 为 error
for (PrometheusResult obj : results) {
PluginsModel.Plugin plugin = new PluginsModel.Plugin();
String host = String.valueOf(obj.getMetric().get("instance"));
boolean active = "1".equals(obj.getValue()[1]);
if (!active) {
runningNums--;
// 只要有不存活的服务器status就是false即不可能是running状态
status = false;
}
plugin.setStatus(active ? RUNNING : ERROR);
if (!NODE_EXPORTER.equals(pluginsName)) {
plugin.setHost(host + "(" + name + ")");
} else {
plugin.setHost(host);
}
plugin.setLogger(pluginsName + ".server");
data.add(plugin);
}
pluginsModel.setName(pluginsName + "(" + data.size() + "");
pluginsModel.setStatus(runningNums == 0 ? ERROR : status ? RUNNING : WARNING);
pluginsModel.setInstance(data);
return pluginsModel;
} catch (Exception e) {
log.error(e.getMessage(), e);
pluginsModel.setName(pluginsName + "(0)");
pluginsModel.setStatus(ERROR);
pluginsModel.setInstance(null);
return pluginsModel;
}
}
/**
* Prometheus BoCloudService
* servicegetServicesIP
*
* @param service
* @param alias
* @return
*/
private PluginsModel buildPluginsModel(@NonNull BoCloudService service, @NonNull String alias) {
List<String> servers = getServices(service);
PluginsModel pluginsModel = new PluginsModel();
List<PluginsModel.Plugin> data = Lists.newArrayList();
boolean status = !servers.isEmpty();
// 活跃个数应该与服务器个数相同,介于 0 和 size之间为 warning0 为 error
int runningNums = servers.size();
for (String server : servers) {
PluginsModel.Plugin plugin = new PluginsModel.Plugin();
if (service == BoCloudService.MCS) {
// fixBug:不兼容的类型: com.megatron.framework.core.Service无法转换为java.lang.String
registry.getServices(Service.create(service.getName()));
Map<String, String> serviceStatus = registry.getServiceStatus(service.getName());
plugin.setStatus(serviceStatus.isEmpty() ? ERROR : RUNNING);
} else {
plugin.setStatus(RUNNING);
}
server = server.replaceAll("http://", "").replaceAll("https://", "");
if (service == BoCloudService.MCS) {
plugin.setHost(server + "(" + alias + ")");
} else {
plugin.setHost(server);
}
plugin.setLogger(service.getName() + ".server");
data.add(plugin);
}
// 将telegraf和blackbox放入EXPORTER里面作为一个个体
if (service == BoCloudService.MCS) {
// 为了函数能返回两个值放进一个集合index 0为Booleanindex 1为Integer类型不能打乱顺序已经写死后面根据索引取出
List<Object> list = new ArrayList<>(2);
list.add(status);
list.add(runningNums);
getPluginInstance("通断监控(" + data.size() + ")", list, data);
getPluginInstance("采集组件(" + data.size() + ")", list, data);
status = (boolean) list.get(0);
runningNums = (int) list.get(1);
}
pluginsModel.setName(alias);
String setStatus = runningNums == 0 ? ERROR : status ? RUNNING : WARNING;
pluginsModel.setStatus(setStatus);
pluginsModel.setInstance(data);
return pluginsModel;
}
/**
* telegrafblackboxEXPORTEREXPORTERtelegrafblackbox
*
* @param name
* @param list
* @param data
*/
private void getPluginInstance(String name, List<Object> list, List<PluginsModel.Plugin> data) {
boolean status = (boolean) list.get(0);
int runningNums = (int) list.get(1);
PluginsModel model = buildPluginsModel(name);
if (model.getInstance() != null) {
for (PluginsModel.Plugin plugin : model.getInstance()) {
if (RUNNING.equals(model.getStatus())) {
runningNums++;
} else {
status = false;
}
data.add(plugin);
}
} else {
PluginsModel.Plugin plugin = new PluginsModel.Plugin();
plugin.setStatus(ERROR);
plugin.setHost(name);
status = false;
data.add(plugin);
}
list.set(0, status);
list.set(1, runningNums);
}
/**
* mysql
*
* @return /
*/
private ComponentModel buildComponentMysql() {
try {
GeneralResult<?> result = mySqlConfiguration.dbStatus();
log.info("mySqlExecuteResult: " + result);
List<ComponentModel.Component> components = Lists.newArrayList();
int errorNum = 0;
if (result.isSuccess()) {
JSONObject mysqlInfo = JSONObject.parseObject(result.getData().toString());
if (mysqlInfo.getString("mysqlInfos") != null) {
List<String> masterHosts = JSONArray.parseArray(mysqlInfo.getJSONArray("masterHosts").toJSONString(), String.class);
JSONArray mysqlInfos = mysqlInfo.getJSONArray("mysqlInfos");
// 主节点没有slaveStatus这个属性
for (int i = 0; i < mysqlInfos.size(); i++) {
JSONObject info = mysqlInfos.getJSONObject(i);
String host = info.getString("host");
String status;
if (info.getJSONArray("ThreadsGlobalStatus") != null) {
status = RUNNING;
} else {
status = ERROR;
errorNum++;
}
components.add(new ComponentModel.Component(host, status, null, masterHosts.contains(host), info));
}
}
}
if (errorNum == components.size()) {
return new ComponentModel("数据库", ERROR, components);
} else if (errorNum > 0) {
return new ComponentModel("数据库", WARNING, components);
}
return new ComponentModel("数据库", RUNNING, components);
} catch (Exception e) {
log.error("获取数据库状态失败:" + e.getMessage(), e);
return new ComponentModel("数据库", ERROR, Lists.newArrayList());
}
}
/**
* Prometheus
*
* @return /
*/
private ComponentModel buildComponentPrometheus() {
String addr = null;
List<ComponentModel.Component> servers = Lists.newArrayList();
try {
String[] addresses = Optional.ofNullable(prometheusConfig.getNodeUrls()).orElse("").split(",");
boolean status = addresses.length != 0;
// 活跃个数应该与服务器个数相同,介于 0 和 size之间为 warning0 为 error
int runningNums = addresses.length;
for (String address : addresses) {
addr = address;
try {
boolean conn = prometheusMonitor.isPrometheusConn(address);
if (!conn) {
runningNums--;
// 只要有不存活的服务器status就是false即不可能是running状态
status = false;
}
servers.add(new ComponentModel.Component(address.replaceAll("https?://", ""), conn ? RUNNING : ERROR, null,
true, null));
} catch (Exception e) {
log.error("获取Prometheus组件信息失败 " + address);
servers.add(new ComponentModel.Component(address.replaceAll("https?://", ""), ERROR, null,
false, null));
}
}
ComponentModel componentModel = new ComponentModel();
componentModel.setName("监控中心");
componentModel.setStatus(runningNums == 0 ? ERROR : status ? RUNNING : WARNING);
componentModel.setInstance(servers);
return componentModel;
} catch (Exception e) {
log.error("获取Prometheus组件信息失败 " + addr);
ComponentModel componentModel = new ComponentModel();
componentModel.setName("监控中心");
componentModel.setStatus(ERROR);
componentModel.setInstance(servers);
return componentModel;
}
}
/**
* zookeeper
*
* @return /
*/
private ComponentModel buildComponentZookeeper() {
try {
boolean connected = client.getClient().getZookeeperClient().isConnected();
String[] serverUrls = client.getProperties().getServerUrl().split(",");
ComponentModel componentModel = new ComponentModel();
List<ComponentModel.Component> servers = Lists.newArrayList();
boolean warning = false;
componentModel.setName("注册中心");
for (String serverUrl : serverUrls) {
String host = serverUrl.split(":")[0];
String port = serverUrl.split(":")[1];
ZooKeeper zk = ZooKeeperMonitor.getZooKeeperMonitor(host, Integer.parseInt(port));
// 获取状态
String status = zk.getStatus();
String state = "";
if (zk.getMonitorInfo() != null) {
// 获取角色leaderfollow
state = zk.getMonitorInfo().getString("zk_server_state");
}
// 检测单个节点是否挂掉了
if (ERROR.equals(status)) {
warning = true;
}
servers.add(new ComponentModel.Component(host + ":" + port, status, null,
serverUrls.length == 1 || "leader".equals(state), zk));
}
componentModel.setInstance(servers);
String setStatus = connected ? warning ? WARNING : RUNNING : ERROR;
componentModel.setStatus(setStatus);
return componentModel;
} catch (RuntimeException e) {
log.error("build zookeeper component error:" + e.getMessage(), e);
return new ComponentModel("注册中心", ERROR, null);
}
}
/**
* rabbitMq
*
* @return /
*/
private ComponentModel buildComponentRabbitmq() {
try {
String queue = IDFactory.instance().uuid();
String address = env.getProperty("spring.rabbitmq.addresses");
String mqHost = env.getProperty("spring.rabbitmq.host");
String rabbitmqHost = address != null ? address : mqHost;
int port = rabbitAdmin.getRabbitTemplate().getConnectionFactory().getPort();
String[] hosts = Objects.requireNonNull(rabbitmqHost).split(",");
boolean success = false;
try {
rabbitAdmin.declareQueue(new Queue(queue, false, false, true));
rabbitAdmin.declareBinding(new Binding(queue, Binding.DestinationType.QUEUE,
BoCloudExchange.Default.DIRECT.getExchange(), queue, null));
String testContent = "This message is used for testing.";
rabbitAdmin.getRabbitTemplate().send(queue, new Message(testContent.getBytes(), new MessageProperties()));
//fix Bug Cast one of the operands of this multiplication operation to a "long"
Message message = rabbitAdmin.getRabbitTemplate().receive(queue, TIME_OUT);
if (message != null && message.getBody().length > 0) {
String content = new String(message.getBody());
if (testContent.equals(content)) {
success = true;
}
}
} catch (Exception e) {
log.error("detect RabbitMQ connection exception:" + e.getMessage());
} finally {
this.rabbitAdmin.deleteQueue(queue);
}
List<ComponentModel.Component> servers = Lists.newArrayList();
for (String host : hosts) {
String username = env.getProperty("spring.rabbitmq.username");
String password = env.getProperty("spring.rabbitmq.password");
// RabbitMQ的Http API端口都是 15672 但是配置文件中没有 直接用固定值
assert username != null;
JSONObject overview = RabbitMqMonitor.getOverview(host.split(":")[0], username, password);
if (overview == null) {
if (address != null) {
servers.add(new ComponentModel.Component(host, ERROR, null, false, null));
} else {
servers.add(new ComponentModel.Component(host + ":" + port, ERROR, null, false, null));
}
continue;
}
String clusterName = overview.getString("cluster_name");
String node = overview.getString("node");
JSONObject nodeInfo = RabbitMqMonitor.getNodeMonitor(host.split(":")[0], username, password, node);
JSONObject rabbitmq = new JSONObject();
rabbitmq.put("overview", overview);
rabbitmq.put("nodeInfo", nodeInfo);
if (address != null) {
servers.add(new ComponentModel.Component(host, success ? RUNNING : ERROR, null,
clusterName.equals(node), rabbitmq));
} else {
servers.add(new ComponentModel.Component(host + ":" + port, success ? RUNNING : ERROR, null,
clusterName.equals(node), rabbitmq));
}
}
return new ComponentModel("消息队列", success ? RUNNING : ERROR, servers);
} catch (RuntimeException e) {
log.error("build zookeeper component error:" + e.getMessage(), e);
return new ComponentModel("消息队列", ERROR, null);
}
}
/**
* alertManager
*
* @return /
*/
private ComponentModel buildComponentAlertManager() {
try {
String[] addresses = Optional.ofNullable(prometheusConfig.getAlertmanagerUrl()).orElse("").split(",");
boolean status = addresses.length != 0;
// 活跃个数应该与服务器个数相同,介于 0 和 size之间为 warning0 为 error
int runningNums = addresses.length;
List<ComponentModel.Component> componentList = Lists.newArrayList();
for (String address : addresses) {
try {
boolean conn = prometheusMonitor.isAlertManagerConn(address);
if (!conn) {
runningNums--;
// 只要有不存活的服务器status就是false即不可能是running状态
status = false;
}
componentList.add(new ComponentModel.Component(address.replaceAll("https?://", ""), conn ? RUNNING : ERROR,
null, true, null));
} catch (Exception e) {
log.error("获取AlertManager组件信息失败 " + address);
componentList.add(new ComponentModel.Component(address.replaceAll("https?://", ""), ERROR,
null, false, null));
}
}
ComponentModel componentModel = new ComponentModel();
componentModel.setName("告警中心");
String setStatus = runningNums == 0 ? ERROR : status ? RUNNING : WARNING;
componentModel.setStatus(setStatus);
componentModel.setInstance(componentList);
return componentModel;
} catch (RuntimeException e) {
log.error("build alertManager component error:" + e.getMessage(), e);
return new ComponentModel("告警中心", ERROR, null);
}
}
/**
* Redis
*
* @return /
*/
private ComponentModel buildComponentRedis() {
try {
boolean success = false;
try (RedisConnection redisConnection = redisTemplate.getRequiredConnectionFactory().getConnection()) {
if (!redisConnection.isClosed()) {
String uuidKey = UUID.randomUUID().toString();
redisTemplate.opsForValue().set(uuidKey, uuidKey, 10, TimeUnit.SECONDS);
redisTemplate.delete(uuidKey);
success = true;
}
} catch (RuntimeException e) {
log.error("detect redis connection error:" + e.getMessage());
throw e;
}
List<ComponentModel.Component> servers = Lists.newArrayList();
RedisConnectionFactory factory = this.redisTemplate.getConnectionFactory();
if (factory instanceof JedisConnectionFactory jedisConnectionFactory) {
if (jedisConnectionFactory.isRedisClusterAware()) {
JedisClusterConnection jedisClusterConnection = (JedisClusterConnection) jedisConnectionFactory
.getClusterConnection();
Set<RedisClusterNode> clusterNodes = jedisClusterConnection.clusterGetNodes();
for (RedisClusterNode clusterNode : clusterNodes) {
String role = RedisMonitor.getRole(clusterNode.getHost(), Objects.requireNonNull(clusterNode.getPort()),
jedisConnectionFactory.getPassword());
servers.add(new ComponentModel.Component(clusterNode.getHost() + ":" + clusterNode.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(role), null));
}
} else if (jedisConnectionFactory.isRedisSentinelAware()) {
buildSentinelInfo(servers, success, jedisConnectionFactory);
} else {
String role = RedisMonitor.getRole(jedisConnectionFactory.getHostName(),
jedisConnectionFactory.getPort(), jedisConnectionFactory.getPassword());
servers.add(new ComponentModel.Component(
jedisConnectionFactory.getHostName() + ":" + jedisConnectionFactory.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(role), null));
}
} else if (factory instanceof LettuceConnectionFactory lettuceConnectionFactory) {
if (lettuceConnectionFactory.isClusterAware()) {
try {
LettuceClusterConnection lettuceClusterConnection = (LettuceClusterConnection) lettuceConnectionFactory
.getClusterConnection();
List<RedisClusterNode> clusterNodes = lettuceClusterConnection.clusterGetNodes();
for (RedisClusterNode clusterNode : clusterNodes) {
String role = RedisMonitor.getRole(clusterNode.getHost(), Objects.requireNonNull(clusterNode.getPort()),
lettuceConnectionFactory.getPassword());
servers.add(new ComponentModel.Component(clusterNode.getHost() + ":" + clusterNode.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(role), null));
}
} catch (Exception e) {
return new ComponentModel("集群缓存", ERROR, servers);
}
} else if (lettuceConnectionFactory.isRedisSentinelAware()) {
buildSentinelInfo(servers, success, lettuceConnectionFactory);
} else {
String role = RedisMonitor.getRole(lettuceConnectionFactory.getHostName(),
lettuceConnectionFactory.getPort(), lettuceConnectionFactory.getPassword());
servers.add(new ComponentModel.Component(
lettuceConnectionFactory.getHostName() + ":" + lettuceConnectionFactory.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(role), null));
}
}
return new ComponentModel("缓存", RUNNING, servers);
} catch (RuntimeException e) {
log.error("build redis component error:" + e.getMessage(), e);
return new ComponentModel("缓存", ERROR, null);
}
}
/**
* redis()
*
* @param servers
* @param success /
* @param redisConnectionFactory
*/
private void buildSentinelInfo(List<ComponentModel.Component> servers, boolean success, RedisConnectionFactory redisConnectionFactory) {
try (RedisSentinelConnection sentinelConnection = redisConnectionFactory.getSentinelConnection()) {
// 所有master节点
if (sentinelConnection instanceof LettuceSentinelConnection) {
try {
LettuceSentinelConnection lettuceSentinelConnection = (LettuceSentinelConnection) sentinelConnection;
List<RedisServer> masters = lettuceSentinelConnection.masters();
for (RedisServer master : masters) {
String role = RedisMonitor.getRole(master.getHost(), Objects.requireNonNull(master.getPort()),
env.getProperty("spring.redis.password"));
servers.add(new ComponentModel.Component(master.getHost() + ":" + master.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(role), null));
// 查找所有slave节点
List<RedisServer> slaves = lettuceSentinelConnection.slaves(Objects.requireNonNull(master.getName()));
for (RedisServer slave : slaves) {
String nodeRole = RedisMonitor.getRole(slave.getHost(), Objects.requireNonNull(slave.getPort()),
env.getProperty("spring.redis.password"));
servers.add(new ComponentModel.Component(slave.getHost() + ":" + slave.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(nodeRole), null));
}
}
} catch (Exception e) {
log.error("组装redis哨兵数据失败" + e.getMessage(), e);
servers.add(new ComponentModel.Component(null, ERROR, null, false, null));
}
} else if (sentinelConnection instanceof JedisSentinelConnection) {
try {
JedisSentinelConnection jedisSentinelConnection = (JedisSentinelConnection) sentinelConnection;
List<RedisServer> masters = jedisSentinelConnection.masters();
for (RedisServer master : masters) {
String role = RedisMonitor.getRole(master.getHost(), Objects.requireNonNull(master.getPort()),
env.getProperty("spring.redis.password"));
servers.add(new ComponentModel.Component(master.getHost() + ":" + master.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(role), null));
// 查找所有slave节点
List<RedisServer> slaves = jedisSentinelConnection.replicas(Objects.requireNonNull(master.getName()));
for (RedisServer slave : slaves) {
String nodeRole = RedisMonitor.getRole(slave.getHost(), Objects.requireNonNull(slave.getPort()),
env.getProperty("spring.redis.password"));
servers.add(new ComponentModel.Component(slave.getHost() + ":" + slave.getPort(),
success ? RUNNING : ERROR, null, MASTER.equals(nodeRole), null));
}
}
} catch (Exception e) {
log.error("组装redis哨兵数据失败" + e.getMessage(), e);
servers.add(new ComponentModel.Component(null, ERROR, null, false, null));
}
}
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
/**
*
*
* @return /
*/
private ComponentModel buildComponentGateway() {
try {
ComponentModel componentModel = new ComponentModel();
componentModel.setName("服务网关");
List<ComponentModel.Component> servers = Lists.newArrayList();
List<String> services = discoveryClient.getServices();
List<ServiceInstance> gateways = new ArrayList<>();
for (String service : services) {
if ("gateway".equalsIgnoreCase(service)) {
gateways = discoveryClient.getInstances(service);
}
}
Optional.ofNullable(gateways).orElse(new ArrayList<>()).forEach(serviceInstance -> {
boolean status = false;
Map<String, String> metadata = serviceInstance.getMetadata();
if (metadata.get("instance_status") != null) {
status = "UP".equals(metadata.get("instance_status"));
}
servers.add(new ComponentModel.Component(serviceInstance.getHost() + ":" + serviceInstance.getPort(),
Boolean.toString(status), null, false, serviceInstance));
componentModel.setInstance(servers);
componentModel.setStatus(Boolean.toString(status));
});
return componentModel;
} catch (RuntimeException e) {
log.error("build gateway component error:" + e.getMessage(), e);
return new ComponentModel("服务网关", ERROR, null);
}
}
/**
*
*
* @param a
* @param b
* @return
* @author fzx
*/
private Double txfloat(int a, int b) {
try {
if (a == 0 || b == 0) {
return 0.0;
}
//设置保留位数
DecimalFormat df = new DecimalFormat("0.00");
String result = df.format((double) a / b);
return Double.parseDouble(result);
} catch (Exception e) {
log.error("错误除法运算!" + e);
return 0.0;
}
}
/**
*
*
* @param sourceNum
* @author sxp
* @since 2018-04-26
*/
private double round(double sourceNum) {
String num = Double.toString(sourceNum);
BigDecimal sourceBd = new BigDecimal(num);
BigDecimal one = new BigDecimal("1");
// ROUND_HALF_UP
// 向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则舍入远离零的方向(数轴上方向上)。
// 注意,这是我们大多数人在小学时就学过的舍入模式,即四舍五入。
return sourceBd.divide(one, 2, RoundingMode.HALF_UP).doubleValue();
}
}

View File

@ -0,0 +1,29 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.interfaces.SystemHomeService;
import com.megatron.common.model.GeneralResult;
import io.swagger.v3.oas.annotations.Operation;
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.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Tag(name = "系统主页")
@RestController
@RequestMapping("/v1/system/home")
@Slf4j
public class SystemHomeController {
@Autowired
private SystemHomeService systemHomeService;
@Operation(summary = "获取云宏token")
@GetMapping("/winhong/token")
public GeneralResult<?> getToken() {
return systemHomeService.getToken();
}
}

View File

@ -0,0 +1,105 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.SystemNotice;
import com.bocloud.sms.interfaces.SystemNoticeService;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
*
*/
@RestController
@RequestMapping("/v1/system/notice")
@Tag(name = "系统公告管理")
public class SystemNoticeController {
private final SystemNoticeService service;
public SystemNoticeController(SystemNoticeService systemNoticeService) {
this.service = systemNoticeService;
}
/**
*
*
* @param entity
* @param requestContext
* @return
*/
@Operation(summary = "创建")
@PostMapping
public Result create(@RequestBody SystemNotice entity, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return service.create(entity, requestContext);
}
/**
*
*
* @param id
* @param requestContext
* @return
*/
@Operation(summary = "删除")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return service.remove(id, requestContext);
}
/**
*
*
* @param id
* @param entity
* @param requestContext
* @return
*/
@Operation(summary = "修改")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id, @RequestBody SystemNotice entity,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return service.modify(entity, requestContext);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "发布")
@PostMapping("/send/{id}")
public Result send(@PathVariable(value = Common.ID) Long id) {
return service.sendMsg(id);
}
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Operation(summary = "列表")
@GetMapping
public GeneralResult<GridBean<SystemNotice>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return service.list(pager, requestContext);
}
/**
*
*
* @param id
* @param requestContext
* @return
*/
@Operation(summary = "详情")
@GetMapping("/{id}")
public GeneralResult<SystemNotice> detail(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return service.detail(id);
}
}

View File

@ -0,0 +1,426 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.fastjson.JSONArray;
import com.bocloud.sms.entity.*;
import com.bocloud.sms.interfaces.TenantService;
import com.bocloud.sms.model.*;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.util.List;
import java.util.Map;
/**
* @author admin
*/
@RestController
@RequestMapping("/v1/tenants")
@Tag(name = "租户管理")
@Slf4j
public class TenantController {
private final TenantService tenantService;
public TenantController(TenantService tenantService) {
this.tenantService = tenantService;
}
/**
*
*
* @param tenant
* @param requestContext
* @return
*/
@Operation(summary = "创建租户")
@PostMapping
public Result create(@RequestBody TenantModel tenant,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.create(tenant, requestContext);
}
/**
*
*
* @param id
* @param tenant
* @param requestContext
* @return
*/
@Operation(summary = "修改租户")
@PutMapping("/{id}")
public Result modify(@PathVariable(value = Common.ID) Long id,
@RequestBody TenantModel tenant,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.modify(id, tenant, requestContext);
}
/**
*
*
* @param id
* @param requestContext
* @return
*/
@Operation(summary = "删除租户")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.remove(id, requestContext);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "查询租户详情")
@GetMapping("/{id}")
public GeneralResult<Tenant> detail(@PathVariable(value = Common.ID) Long id) {
return tenantService.detail(id);
}
/**
*
*
* @param account
* @return
*/
@Operation(summary = "锁定租户")
@PutMapping()
public Result tenantLock(@RequestParam(value = Common.ACCOUNT) String account) {
return tenantService.lockByAccount(account);
}
/**
*
*
* @param account
* @return
*/
@Operation(summary = "获取租户信息")
@PostMapping("/info")
public GeneralResult<Map<String, Object>> tenantAccountInfo(@RequestParam(value = Common.ACCOUNT) String account) {
return tenantService.tokenLogin(account);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "获取项目列表")
@GetMapping("/{id}/projects")
public GeneralResult<List<Project>> projects(@PathVariable(value = Common.ID) Long id) {
return tenantService.projects(id);
}
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Operation(summary = "分页获取租户列表")
@GetMapping
public GeneralResult<GridBean<Tenant>> list(Pager pager, @Value(value = Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.list(pager, requestContext);
}
/**
*
*
* @param id
* @param action
* @param requestContext
* @return
*/
@Operation(summary = "租户操作")
@PatchMapping("/{id}")
public Result updateStatus(@PathVariable(value = Common.ID) Long id,
@RequestBody ActionModel action,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.updateStatus(id, action.getAction(), requestContext);
}
/**
*
*
* @param id id
* @param passwordModel
* @param requestContext
* @return
*/
@Operation(summary = "修改租户密码")
@PatchMapping("/{id}/pwd")
public Result changePwd(@PathVariable(value = Common.ID) Long id,
@RequestBody PasswordModel passwordModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.changePwd(id, passwordModel.getOldPassword(), passwordModel.getPassword(), requestContext);
}
/**
*
*
* @param id id
* @param passwordModel
* @param requestContext
* @return
*/
@Operation(summary = "重置租户密码")
@PatchMapping("/{id}/reset")
public Result resetPwd(@PathVariable(value = Common.ID) Long id,
@RequestBody PasswordModel passwordModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.resetPwd(id, passwordModel.getPassword(), requestContext);
}
/**
*
*
* @param id
* @param request
* @return
*/
@Operation(summary = "检查租户是否登录")
@GetMapping("/{id}/status")
public Result checkTenant(@PathVariable(value = Common.ID) Long id,
HttpServletRequest request) {
return tenantService.checkTenant(id, request.getHeader(Common.TOKEN));
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "查询租户的角色列表")
@GetMapping("/{id}/roles")
public GeneralResult<List<Role>> roles(@PathVariable(value = Common.ID) Long id) {
return tenantService.listRoles(id);
}
/**
*
*
* @param apiKey
* @return
*/
@Operation(summary = "获取租户安全对象")
@GetMapping("/security")
public GeneralResult<AccountSecurity> security(@RequestParam(value = "apiKey") String apiKey) {
return tenantService.getByApiKey(apiKey);
}
/**
*
*
* @param batchAction
* @return
*/
@Operation(summary = "批量操作租户")
@PatchMapping
public Result batchLock(@RequestBody BatchActionModel batchAction, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
switch (batchAction.getAction()) {
case lock:
return tenantService.batchLock(batchAction.getIds(), requestContext);
case active:
return tenantService.batchActive(batchAction.getIds(), requestContext);
case remove:
return tenantService.batchRemove(batchAction.getIds(), requestContext);
default:
return new Result(false, "不支持这种操作");
}
}
/**
*
*
* @param poolId
* @return
*/
@Operation(summary = "删除租户资源池关联")
@DeleteMapping("/pools")
public Result poolDelete(@RequestParam(value = "poolId") Long poolId) {
return tenantService.deleteByPoolId(poolId);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "查询租户资源池关联")
@GetMapping("/{id}/pools")
public GeneralResult<List<TenantPool>> businessPools(@PathVariable(value = Common.ID) Long id) {
return tenantService.listTenantPool(id);
}
/**
*
*
* @param id
* @param poolIds
* @return
*/
@Operation(summary = "租户配置资源池")
@PostMapping("/{id}/pools")
public Result configPool(@PathVariable(value = Common.ID) Long id, @RequestBody List<Long> poolIds, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.configPool(id, null, poolIds, requestContext);
}
/**
*
*
* @param id
* @param businessIds
* @return
*/
@Operation(summary = "租户配置业务")
@PostMapping("/{id}/businesses")
public Result configBusiness(@PathVariable(value = Common.ID) Long id, @RequestParam(value = "businessIds") String businessIds) {
List<Long> businesses = JSONArray.parseArray(businessIds, Long.class);
return tenantService.configBusiness(id, businesses);
}
/**
*
*
* @param pager
* @return
*/
@Operation(summary = "登录记录查询")
@GetMapping("/track")
public GeneralResult<GridBean<LoginRecord>> records(Pager pager) {
return this.tenantService.list(pager);
}
@Operation(summary = "添加收藏")
@PostMapping("/favorites/{id}")
public Result addFavorite(@PathVariable("id") Long serviceId, @RequestParam("tenantId") Long tenantId) {
return tenantService.addFavorite(serviceId, tenantId);
}
@Operation(summary = "批量添加收藏")
@PostMapping("/favorites")
public Result addFavorites(@RequestBody List<Favorite> favorites) {
return tenantService.addFavorites(favorites);
}
@Operation(summary = "删除收藏")
@DeleteMapping("/favorites")
public Result cancelTenantFavorite(@RequestParam(value = "serviceId", required = false) Long serviceId, @RequestParam(value = "tenantId", required = false) Long tenantId, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.cancelFavorite(serviceId, tenantId, requestContext);
}
@Operation(summary = "获取收藏夹")
@GetMapping("/favorites")
public GeneralResult<List<CloudServiceBean>> listFavorite(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.listFavorite(requestContext);
}
@Operation(summary = "获取服务目录")
@GetMapping("/services")
public GeneralResult<List<ServiceMenuBean>> listServiceMenu(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.listServiceMenu(requestContext);
}
@Operation(summary = "修改收藏夹排序")
@PostMapping("/favorites/order")
public Result changePriority(@RequestBody List<PriorityModel> priorityModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return tenantService.changePriority(priorityModel, requestContext);
}
@Operation(summary = "查询租户下用户")
@GetMapping("/{id}/users")
public GeneralResult<List<User>> getTenantUsers(@PathVariable(value = Common.ID) Long id) {
return tenantService.getTenantUsers(id);
}
@Operation(summary = "租户配置用户")
@PostMapping("/{id}/users")
public Result configUsers(@PathVariable(value = Common.ID) Long id, @RequestBody List<Long> userIds) {
return tenantService.configUsers(id, userIds);
}
@Operation(summary = "查询租户账号是否存在")
@GetMapping("/{account}/exist")
public Result exist(@PathVariable(value = Common.ACCOUNT) String account) {
return tenantService.exist(account);
}
@Operation(summary = "根据省市编码查询租户")
@GetMapping("/{city}/list")
public GeneralResult<List<Tenant>> listTenantByCity(@PathVariable(value = "city") String city) {
return tenantService.listTenantByCity(city);
}
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Deprecated
@Operation(summary = "导出租户列表")
@RequestMapping(value = "/export", method = {RequestMethod.GET})
public void export(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext requestContext,
HttpServletRequest request, HttpServletResponse response) {
List<Param> paramList = pager.getParams();
Result result = tenantService.export(paramList, requestContext, response);
Assert.isTrue(result.isSuccess(), "导出租户列表异常");
}
@Operation(summary = "下载租户列表模板")
@RequestMapping(value = "/import/template", method = {RequestMethod.GET})
public void importTemp(HttpServletRequest request, HttpServletResponse response,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
Result result = tenantService.importTemp("租户列表模板", requestContext, response);
Assert.isTrue(result.isSuccess(), result.getMessage());
}
@Operation(summary = "导入租户列表")
@PostMapping(value = "/import")
public Result importData(@Value(Common.REQ_CONTEXT) RequestContext requestContext, HttpServletRequest request) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
List<MultipartFile> fileList = multipartRequest.getFiles("file");
if (fileList.isEmpty()) {
return new Result(false, "文件错误");
}
MultipartFile multipartFile = fileList.get(0);
String originalFilename = multipartFile.getOriginalFilename();
// 判断文件名
if (originalFilename == null || !(originalFilename.endsWith(".xls") || originalFilename.endsWith(".xlsx"))) {
return new Result(false, "文件错误");
}
return tenantService.importData(multipartFile, requestContext);
}
@Operation(summary = "查询租户账号是否存在")
@GetMapping("/condition")
public GeneralResult condition(@RequestParam(value = Common.CONDITION, required = false) String condition) {
return tenantService.condition(condition);
}
}

View File

@ -0,0 +1,109 @@
package com.bocloud.sms.booter.controller;
import com.auth0.jwt.interfaces.Claim;
import com.bocloud.sms.interfaces.TenantService;
import com.bocloud.sms.interfaces.UserService;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.utils.Common;
import com.megatron.common.utils.Tokens;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
/**
* @author tyl
* @since 2020/7/24 11:38
*/
@RestController
@Tag(name = "token管理")
public class TokenController {
private final StringRedisTemplate redisTemplate;
private final TenantService tenantService;
private final UserService userService;
public TokenController(StringRedisTemplate redisTemplate, TenantService tenantService, UserService userService) {
this.redisTemplate = redisTemplate;
this.tenantService = tenantService;
this.userService = userService;
}
/**
* token
*
* @param request
* @return token
*/
@GetMapping("/v1/token")
@Operation(summary = "单点登录验证token")
public GeneralResult<String> checkToken(HttpServletRequest request) {
String token = request.getHeader(Common.TOKEN);
if (!StringUtils.hasText(token)) {
token = request.getParameter(Common.TOKEN);
}
String tokenKey = "";
if (StringUtils.hasText(token)) {
Claim claim = Tokens.parse(token);
if (claim == null) {
return new GeneralResult<>(false, "token校验失败");
}
String catalog = claim.asMap().get("catalog").toString();
long uuid = Long.parseLong(claim.asMap().get(Common.UUID).toString());
tokenKey = Common.TOKEN + "_" + catalog + "_" + uuid;
}
//校验token
boolean checkResult = check(token, tokenKey);
if (checkResult) {
String newTokenCache = (String) this.redisTemplate.opsForHash().get(tokenKey + "_n", Common.TOKEN);
return new GeneralResult<>(true, newTokenCache, "校验token成功");
} else {
return new GeneralResult<>(false, "token校验失败");
}
}
private boolean check(String token, String tokenKey) {
String newTokenCache = (String) this.redisTemplate.opsForHash().get(tokenKey + "_n", Common.TOKEN);
if (token.equals(newTokenCache)) {
return true;
} else {
String oldTokenCache = this.redisTemplate.opsForValue().get(tokenKey + "_o");
return token.equals(oldTokenCache);
}
}
@PostMapping("/v1/sso/token/info")
@Operation(summary = "token解析获取信息")
public GeneralResult<Map<String, Object>> getTokenInfo(HttpServletRequest request) {
String token = request.getHeader(Common.TOKEN);
HttpSession session = request.getSession();
if (!StringUtils.hasText(token)) {
return new GeneralResult<>(false, "token不存在");
}
Claim claim = Tokens.parse(token);
if (claim == null) {
return new GeneralResult<>(false, "token信息异常重新登录");
}
String catalog = claim.asMap().get("catalog").toString();
String account = claim.asMap().get(Common.ACCOUNT).toString();
GeneralResult<Map<String, Object>> result;
if (catalog.equals(RequestContext.Catalog.Tenant.name())) {
result = tenantService.tokenLogin(account);
} else {
result = userService.tokenLogin(account);
}
Map<String, Object> object = result.getData();
object.put(Common.TOKEN, token);
object.put("redirect", session.getAttribute("redirect"));
result.setData(object);
return result;
}
}

View File

@ -0,0 +1,149 @@
package com.bocloud.sms.booter.controller;
import com.alibaba.druid.filter.config.ConfigTools;
import com.bocloud.cmp.boot.config.DataSourceConfiguration;
import com.bocloud.sms.entity.UpgradeHistory;
import com.bocloud.sms.entity.UpgradeTask;
import com.bocloud.sms.interfaces.UpgradeService;
import com.megatron.common.encrypt.AESEncryptor;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.RequestContext;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* @author luyanchao
* @date 2021-06-09
*/
@RestController
@RequestMapping("/v1/upgrade")
@Tag(name = "系统升级")
@Slf4j
public class UpgradeController {
@Autowired
private UpgradeService upgradeService;
@Autowired
private DataSourceConfiguration dataSourceConfiguration;
/**
*
*
* @return url, user, pass
*/
@Operation(summary = "获取当前数据源")
@GetMapping("/datasource")
public GeneralResult<Map<String, String>> getDatasource() {
Map<String, String> result = new HashMap<>();
result.put("url", dataSourceConfiguration.getUrl());
result.put("user", dataSourceConfiguration.getUsername());
PublicKey publicKey = ConfigTools.getPublicKey(dataSourceConfiguration.getPublicKey());
try {
String passPlainText = ConfigTools.decrypt(publicKey, dataSourceConfiguration.getPassword());
result.put("pass", new AESEncryptor().encrypt(passPlainText, null));
} catch (Exception e) {
log.warn("MySQL密码解密失败{}", e.getMessage());
return new GeneralResult<>(true, result, "执行成功");
}
return new GeneralResult<>(true, result, "执行成功");
}
/**
*
*
* @param param
*/
@Operation(summary = "执行数据迁移")
@PostMapping("/datasource")
public GeneralResult<Boolean> newMigration(@RequestBody Param param, @Value(Common.REQ_CONTEXT) RequestContext context) {
return upgradeService.newMigration(param.getUrl(), param.getUser(), param.getPass(), context);
}
/**
*
*
* @param id id
*/
@Operation(summary = "重试数据迁移")
@PostMapping("/datasource/{id}")
public GeneralResult<Boolean> retryMigration(@PathVariable(value = "id") Long id,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return upgradeService.retryMigration(id, context);
}
/**
*
*
* @param pager
*/
@Operation(summary = "查询数据迁移列表")
@GetMapping("/records")
public GeneralResult<GridBean<UpgradeHistory>> listUpgradeHistory(Pager pager) {
return upgradeService.listUpgradeHistory(pager);
}
/**
*
*
* @param id id
*/
@Operation(summary = "查询数据迁移详情")
@GetMapping("/records/{id}")
public GeneralResult<UpgradeHistory> getUpgradeHistory(@PathVariable(value = "id") Long id) {
return upgradeService.getUpgradeHistory(id);
}
/**
*
*
* @param id id
* @param pager
*/
@Operation(summary = "查询数据迁移子任务列表")
@GetMapping("/records/{id}/tasks")
public GeneralResult<GridBean<UpgradeTask>> listUpgradeTask(Pager pager, @PathVariable(value = "id") Long id) {
return upgradeService.listUpgradeTask(id, pager);
}
/**
*
*
* @param recordId id
* @param taskId id
*/
@Operation(summary = "重试数据迁移子任务")
@PostMapping("/records/{recordId}/tasks/{taskId}")
public GeneralResult<Boolean> retryUpgradeTask(@PathVariable(value = "recordId") Long recordId,
@PathVariable(value = "taskId") Long taskId,
@Value(Common.REQ_CONTEXT) RequestContext context) {
return upgradeService.retryUpgradeTask(taskId, context);
}
@Data
@NoArgsConstructor
public static class Param {
private String url;
private String user;
private String pass;
}
}

View File

@ -0,0 +1,417 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.*;
import com.bocloud.sms.interfaces.ManagerService;
import com.bocloud.sms.interfaces.TenantService;
import com.bocloud.sms.interfaces.UserPermissionService;
import com.bocloud.sms.interfaces.UserService;
import com.bocloud.sms.model.*;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.util.List;
import java.util.Map;
/**
* @author tyl
*/
@RequiredArgsConstructor
@RestController
@RequestMapping("/v1/users")
@Tag(name = "用户管理")
public class UserController {
private final UserService userService;
private final UserPermissionService userPermissionService;
private final TenantService tenantService;
private final ManagerService managerService;
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Operation(summary = "查询用户列表")
@GetMapping
public GeneralResult<GridBean<User>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.list(pager, requestContext);
}
/**
*
*
* @param userBean
* @param requestContext
* @return
*/
@Operation(summary = "创建用户")
@PostMapping
public Result create(@RequestBody UserBean userBean, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.create(userBean, requestContext);
}
/**
*
*
* @param userBean
* @param requestContext
* @return
*/
@Operation(summary = "用户修改")
@PutMapping("/{id}")
public Result modify(@RequestBody UserBean userBean, @Value(Common.REQ_CONTEXT) RequestContext requestContext,
@PathVariable(value = Common.ID) Long id) {
return userService.modify(id, userBean, requestContext);
}
/**
*
*
* @param id
* @param requestContext
* @return
*/
@Operation(summary = "删除用户")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.remove(id, requestContext);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "用户详情")
@GetMapping("/{id}")
public GeneralResult<User> detail(@PathVariable(value = Common.ID) Long id) {
return userService.detail(id);
}
/**
*
*
* @param account
* @return
*/
@Operation(summary = "查询用户账号是否存在")
@GetMapping("/{account}/exist")
public Result exist(@PathVariable(value = Common.ACCOUNT) String account) {
return userService.exist(account);
}
/**
*
*
* @param requestContext
* @return
*/
@Operation(summary = "用户详情")
@GetMapping("/detail")
public GeneralResult<User> detail(@Value(value = Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.detail(requestContext.getTarget());
}
/**
*
*
* @param id
* @param action
* @param requestContext
* @return
*/
@Operation(summary = "修改用户状态")
@PatchMapping("/{id}")
public Result updateStatus(@PathVariable(value = Common.ID) Long id,
@RequestBody ActionModel action,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.updateStatus(id, action.getAction(), requestContext);
}
/**
*
*
* @param id id
* @param passwordModel
* @param requestContext
* @return
*/
@Operation(summary = "修改用户密码")
@PatchMapping("/{id}/pwd")
public Result changePwd(@PathVariable(value = Common.ID) Long id,
@RequestBody PasswordModel passwordModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.changePwd(id, passwordModel.getOldPassword(), passwordModel.getPassword(), requestContext);
}
/**
*
*
* @param id id
* @param passwordModel
* @param requestContext
* @return
*/
@Operation(summary = "重置用户密码")
@PatchMapping("/{id}/reset")
public Result resetPwd(@PathVariable(value = Common.ID) Long id,
@RequestBody PasswordModel passwordModel,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.resetPwd(id, passwordModel.getPassword(), requestContext);
}
/**
*
*
* @param id id
* @param roleIds id
* @param requestContext
* @return
*/
@Operation(summary = "用户授权角色")
@PatchMapping("/{id}/accredit")
public Result accredit(@PathVariable(value = Common.ID) Long id,
@RequestBody List<Long> roleIds,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.accredit(id, roleIds, requestContext);
}
/**
*
*
* @param id
* @param request
* @return
*/
@Operation(summary = "检查用户是否登录")
@GetMapping("/{id}/status")
public Result checkUser(@PathVariable(value = Common.ID) Long id, HttpServletRequest request) {
return userService.checkUser(id, request.getHeader(Common.TOKEN));
}
/**
*
*
* @param id
* @param requestContext
* @return
*/
@Operation(summary = "获取角色列表")
@GetMapping("/{id}/roles")
public GeneralResult<List<Role>> roles(@PathVariable(value = Common.ID) Long id,
@RequestParam(value = Common.CONDITION, required = false) String condition,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.listRoles(id, condition, requestContext);
}
/**
* key
*
* @param apiKey
* @return
*/
@Operation(summary = "获取key")
@GetMapping("/security")
public GeneralResult<AccountSecurity> secKey(@RequestParam(value = "apiKey") String apiKey) {
return userService.getAccountSecurity(apiKey);
}
/**
*
*
* @param batchAction
* @return
*/
@Operation(summary = "批量操作用户")
@PatchMapping
public Result batchLock(@RequestBody BatchActionModel batchAction, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
switch (batchAction.getAction()) {
case lock:
return userService.batchLock(batchAction.getIds(), requestContext);
case active:
return userService.batchActive(batchAction.getIds(), requestContext);
case remove:
return userService.batchRemove(batchAction.getIds(), requestContext);
default:
return new Result(false, "不支持这种操作");
}
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "用户移除所属租户")
@PatchMapping("/{id}/tenants")
public Result unBindTenants(@PathVariable Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.unBindTenants(id, requestContext);
}
/**
*
*
* @param pager
* @return
*/
@Operation(summary = "登录记录查询")
@GetMapping("/track")
public GeneralResult<GridBean<LoginRecord>> records(Pager pager) {
return this.userService.list(pager);
}
@Operation(summary = "添加收藏")
@PostMapping("/favorites/{id}")
public Result addFavorite(@PathVariable("id") Long id, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.addFavorite(id, requestContext);
}
@Operation(summary = "删除收藏")
@DeleteMapping("/favorites/{id}")
public Result cancelFavorite(@PathVariable("id") Long serviceId, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.cancelFavorite(serviceId, requestContext);
}
@Operation(summary = "获取收藏夹")
@GetMapping("/favorites")
public GeneralResult<List<CloudServiceBean>> listFavorite(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.listFavorite(requestContext);
}
@Operation(summary = "获取服务目录")
@GetMapping("/services")
public GeneralResult<List<ServiceMenuBean>> listServiceMenu(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.listServiceMenu(requestContext);
}
@Operation(summary = "修改收藏夹排序")
@PostMapping("/favorites/order")
public Result changePriority(@RequestBody List<PriorityModel> priorityModels, @Value(Common.REQ_CONTEXT) RequestContext requestContext) {
return userService.changePriority(priorityModels, requestContext);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "获取项目列表")
@GetMapping("/{id}/projects")
public GeneralResult<List<Project>> projects(@PathVariable(value = Common.ID) Long id) {
return userService.projects(id);
}
/**
*
*
* @param pager
* @param requestContext
* @return
*/
@Deprecated
@Operation(summary = "导出项目列表")
@RequestMapping(value = "/export", method = {RequestMethod.GET})
public void export(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext requestContext,
HttpServletRequest request, HttpServletResponse response) {
List<Param> paramList = pager.getParams();
Result export = userService.export(paramList, requestContext, response);
Assert.isTrue(export.isSuccess(), "用户列表导出失败");
}
@Operation(summary = "下载用户列表模板")
@RequestMapping(value = "/import/template", method = {RequestMethod.GET})
public void importTemp(HttpServletRequest request, HttpServletResponse response,
@RequestParam(value = "tenantId", required = false) Long tenantId,
@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
Result result = userService.importTemp("用户列表", response);
Assert.isTrue(result.isSuccess(), "用户模板下载失败");
}
@Operation(summary = "导入用户列表")
@PostMapping(value = "/import")
public Result importData(@Value(Common.REQ_CONTEXT) RequestContext requestContext,
@RequestParam(value = "tenantId", required = false) Long tenantId, HttpServletRequest request) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
List<MultipartFile> fileList = multipartRequest.getFiles("file");
if (fileList.isEmpty()) {
return new Result(false, "文件错误");
}
MultipartFile multipartFile = fileList.get(0);
String originalFilename = multipartFile.getOriginalFilename();
// 判断文件名
if (originalFilename == null || !(originalFilename.endsWith(".xls") || originalFilename.endsWith(".xlsx"))) {
return new Result(false, "文件错误");
}
return userService.importData(multipartFile, tenantId, requestContext);
}
/**
*
*
* @param account
* @return
*/
@Operation(summary = "锁定用户")
@PutMapping
@Deprecated
public Result userLock(@RequestParam(value = Common.ACCOUNT) String account) {
return userService.lockByAccount(account);
}
/**
*
*
* @param account
* @return
*/
@PostMapping("/info")
@Operation(summary = "获取用户信息")
public GeneralResult<Map<String, Object>> userAccountInfo(@RequestParam(value = Common.ACCOUNT) String account) {
return userService.tokenLogin(account);
}
/**
*
*
* @param requestContext
* @return
*/
@Operation(summary = "获取登录用户权限")
@GetMapping("/permissions")
public GeneralResult loginPermission(@Value(Common.REQ_CONTEXT) RequestContext requestContext) {
switch (requestContext.getCatalog()) {
case Tenant:
return tenantService.listPermissions(requestContext);
case Manager:
return managerService.listPermissions(requestContext);
case User:
return userPermissionService.listPermissions(requestContext);
default:
}
return new GeneralResult(false, "获取用户信息异常");
}
@Operation(summary = "获取登录用户按钮权限")
@GetMapping("/button/permissions")
public GeneralResult<List<Permission>> buttonPermissions(@Value(Common.REQ_CONTEXT) RequestContext context) {
List<Permission> list = userPermissionService.listButtonPermissions(context);
return new GeneralResult<>(true, list, "获取登录用户按钮权限成功");
}
}

View File

@ -0,0 +1,135 @@
package com.bocloud.sms.booter.controller;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.entity.UserGroup;
import com.bocloud.sms.interfaces.UserGroupService;
import com.bocloud.sms.model.UserGroupBean;
import com.megatron.common.model.*;
import com.megatron.common.utils.Common;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
/**
* @author hongqingyu
*/
@RestController
@RequestMapping("/v1/users/groups")
@Tag(name = "用户管理")
public class UserGroupController {
@Autowired
private UserGroupService userGroupService;
/**
*
*
* @param pager
* @param context
* @return
*/
@Operation(summary = "查询用户组列表")
@GetMapping
public GeneralResult<GridBean<User>> list(Pager pager, @Value(Common.REQ_CONTEXT) RequestContext context) {
return userGroupService.list(pager);
}
/**
*
*
* @param context
* @return
*/
@Operation(summary = "创建用户组")
@PostMapping
public Result create(@RequestBody UserGroup group, @Value(Common.REQ_CONTEXT) RequestContext context) {
return userGroupService.create(group, context);
}
/**
*
*
* @param context
* @return
*/
@Operation(summary = "用户组修改")
@PutMapping("/{id}")
public Result modify(@RequestBody UserGroupBean bean, @Value(Common.REQ_CONTEXT) RequestContext context,
@PathVariable(value = Common.ID) Long id) {
bean.setId(id);
return userGroupService.modify(bean, context);
}
/**
*
*
* @param id
* @param context
* @return
*/
@Operation(summary = "删除用户组")
@DeleteMapping("/{id}")
public Result remove(@PathVariable(value = Common.ID) Long id, @Value(Common.REQ_CONTEXT) RequestContext context) {
return userGroupService.remove(id, context);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "用户组详情")
@GetMapping("/{id}")
public GeneralResult<UserGroup> detail(@PathVariable(value = Common.ID) Long id) {
return userGroupService.detail(id);
}
/**
*
*
* @return
*/
@PostMapping("/relation")
@Operation(summary = "关联账号")
public Result relation(@RequestBody UserGroupBean bean) {
return userGroupService.configUser(bean.getUserIds(), bean.getId());
}
/**
* userId
*
* @param id id
* @return
*/
@GetMapping("/relation/users/{id}")
@Operation(summary = "根据用户id查询用户组")
public Result listGroupIdByUserId(@PathVariable Long id) {
return userGroupService.listGroupIdByUserId(id);
}
/**
*
*
* @param id
* @return
*/
@Operation(summary = "用户组用户详情")
@GetMapping("/{id}/users")
public GeneralResult<UserGroup> users(Pager pager, @PathVariable(value = Common.ID) Long id) {
return userGroupService.listUserByGroupId(pager, id);
}
/**
*
*
* @return
*/
@Operation(summary = "获取全量用户组")
@GetMapping("/all")
public GeneralResult<GridBean<User>> listAll() {
return userGroupService.listAll();
}
}

View File

@ -0,0 +1,54 @@
package com.bocloud.sms.booter.listener;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.sms.booter.websocket.message.MessageHandler;
import com.bocloud.sms.booter.websocket.model.CommonMessage;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.OperateResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.utils.JSONTools;
import io.jsonwebtoken.lang.Assert;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.stereotype.Component;
/**
*
*
* @author wangyu
* @version 1.0
* @since 2017810
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class BocloudMessageListener implements MessageListener {
private final MessageHandler messageHandler;
@Override
public void onMessage(Message message) {
try {
String content = new String(message.getBody());
if (log.isDebugEnabled()) {
log.debug("get bocloud message:{}", content);
}
Assert.notNull(content, "消息内容为空");
GeneralResult<JSONObject> result = JSONTools.isJSON(content);
Assert.isTrue(result.isSuccess(), result.getMessage());
OperateResult operate = JSONObject.parseObject(content, OperateResult.class);
Assert.notNull(content, "消息格式不正确");
RequestContext context = operate.getContext();
if (null != context && null != context.getTarget() && 0 != context.getTarget()) {
// 发送消息给指定ID的用户前端
messageHandler.sendMessageToUser(context.getCatalog(), context.getTarget(), new CommonMessage(content));
} else {// 发送给所有的用户前端
messageHandler.sendMessageToUsers(new CommonMessage(content));
}
} catch (Exception e) {
log.error("send websocket message failed: {}", e.getMessage(), e);
}
}
}

View File

@ -0,0 +1,120 @@
package com.bocloud.sms.booter.listener;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.sms.entity.Tenant;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.interfaces.MessageService;
import com.bocloud.sms.model.NotifyMessage;
import com.bocloud.sms.repository.TenantRepository;
import com.bocloud.sms.repository.UserRepository;
import com.bocloud.sms.service.utils.DingTalkSender;
import com.bocloud.sms.service.utils.EmailSender;
import com.bocloud.sms.service.utils.WeChatWorkSender;
import com.megatron.common.model.RequestContext;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
/**
*
*
* @author weiwei
* @since 2017726
*/
@RequiredArgsConstructor
@Component("eventListener")
@Slf4j
public class EventListener {
private final MessageService messageService;
private final EmailSender emailSender;
private final UserRepository userRepository;
private final TenantRepository tenantRepository;
private final DingTalkSender dingTalkSender;
private final WeChatWorkSender weChatWorkSender;
@RabbitListener(queues = "event.notice.queue", admin = "rabbitAdmin", autoStartup = "true")
public void onMessage(NotifyMessage message) {
log.debug("接收到时间通知消息:{}", JSONObject.toJSON(message));
try {
// 主题
String subject = message.getSubject();
// 站内信内容
String msgContent = message.getContent();
// 邮件内容
String emailContent = StringUtils.hasText(message.getEmailContent()) ? message.getEmailContent() : message.getContent();
// 企业微信内容
String weChatContent = StringUtils.hasText(message.getWeChatContent()) ? message.getWeChatContent() : message.getContent();
// 钉钉内容
String dingTalkContent = StringUtils.hasText(message.getDingTalkContent()) ? message.getDingTalkContent() : message.getContent();
RequestContext context = message.getContext();
List<RequestContext> contexts = Optional.ofNullable(message.getContexts()).orElse(new ArrayList<>());
if (context != null) {
contexts.add(context);
}
//收件邮箱
String[] emails = null;
//接收者钉钉唯一标识
String dingTalkUserId = null;
//企业微信唯一标识
String weChatUserId = null;
for (RequestContext requestContext : contexts) {
if (RequestContext.Catalog.Tenant == requestContext.getCatalog()) {
Tenant tenant = tenantRepository.query(requestContext.getTarget());
if (tenant != null) {
if (StringUtils.hasText(tenant.getEmail())) {
emails = new String[]{tenant.getEmail()};
}
if (StringUtils.hasText(tenant.getDingTalkNumber())) {
dingTalkUserId = tenant.getDingTalkNumber();
}
if (StringUtils.hasText(tenant.getWeChatWorkNumber())) {
weChatUserId = tenant.getWeChatWorkNumber();
}
}
} else {
User user = userRepository.query(requestContext.getTarget());
if (user != null) {
if (StringUtils.hasText(user.getEmail())) {
emails = new String[]{user.getEmail()};
}
if (StringUtils.hasText(user.getDingtalk())) {
dingTalkUserId = user.getDingtalk();
}
if (StringUtils.hasText(user.getWechat())) {
weChatUserId = user.getWechat();
}
}
}
// 发送站内信
if (message.isSendMsg()) {
messageService.create(requestContext, subject, msgContent);
}
// 发送邮件
if (message.isSendEmail() && null != emails) {
if (emailContent == null) {
emailSender.send(subject, emails, msgContent, null);
} else {
emailSender.send(subject, emails, emailContent, null);
}
}
if (message.isSendDingTalk() && StringUtils.hasText(dingTalkUserId)) {
//发送钉钉消息
dingTalkSender.sendMessage(dingTalkContent, dingTalkUserId, null, false);
}
if (message.isSendWeChat() && StringUtils.hasText(weChatUserId)) {
//发送企业微信消息
weChatWorkSender.pushMessage(weChatUserId, weChatContent);
}
}
} catch (Exception e) {
log.error("Send message or email error:", e);
}
}
}

View File

@ -0,0 +1,91 @@
package com.bocloud.sms.booter.listener;
import com.bocloud.sms.entity.AccessLog;
import com.bocloud.sms.interfaces.LogService;
import com.megatron.common.utils.IDFactory;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* rabbitmq
*
* @author dmw
*/
@Component("logListener")
@Slf4j
public class LogListener implements InitializingBean {
private BlockingQueue<AccessLog> accessLogQueue = new LinkedBlockingQueue<>();
private volatile boolean runnable = true;
@Autowired
private LogService logService;
/**
* 访
*
* @param log
*/
@RabbitListener(queues = "bocloud.log.queue", admin = "rabbitAdmin", autoStartup = "true")
public void processAccessLogMessage(AccessLog log) {
log.setId(IDFactory.instance().uuid());
if ("系统配置".equals(log.getTarget()) && "更新操作".equals(log.getAction())) {
if (log.getDetail().length() > 65535) {
log.setDetail(log.getDetail().substring(0, 65534).replace("/", ""));
}
}
accessLogQueue.add(log);
}
class BatchSaver implements Runnable {
long start = System.currentTimeMillis();
/**
*
*
* @return
*/
private List<AccessLog> fetchLog() {
List<AccessLog> logList = new ArrayList<>();
try {
while ((System.currentTimeMillis() - start) < 1000 && logList.size() < 512) {
logList.add(accessLogQueue.take());
}
} catch (Exception e) {
log.error("Fetch log Error", e);
}
return logList;
}
@Override
public void run() {
while (runnable) {
List<AccessLog> logs = fetchLog();
if (logs.isEmpty()) {
continue;
}
logService.batch(logs);
start = System.currentTimeMillis();
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
new Thread(new BatchSaver()).start();
}
@PreDestroy
public void destory() {
this.runnable = false;
}
}

View File

@ -0,0 +1,121 @@
package com.bocloud.sms.booter.scheduler;
import com.bocloud.cmp.boot.model.BoCloudExchange;
import com.bocloud.cmp.boot.model.BocloudStatus;
import com.bocloud.sms.entity.Tenant;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.model.NotifyMessage;
import com.bocloud.sms.repository.TenantRepository;
import com.bocloud.sms.repository.UserRepository;
import com.megatron.common.model.RequestContext;
import com.megatron.framework.core.CurrentService;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
*
*
* @author tyl
* @time 2020/7/22 9:55
*/
@Component
@Slf4j
public class AccountStatusMonitor implements InitializingBean {
private final CurrentService service;
private final UserRepository userRepository;
private final TenantRepository tenantRepository;
private final AmqpTemplate amqpTemplate;
// 一天毫秒数
private static final Long ONE_DAY = 24 * 60 * 60 * 1000L;
public AccountStatusMonitor(CurrentService service, UserRepository userRepository, TenantRepository tenantRepository, AmqpTemplate amqpTemplate) {
this.service = service;
this.userRepository = userRepository;
this.tenantRepository = tenantRepository;
this.amqpTemplate = amqpTemplate;
}
@Scheduled(cron = "0 0 0 * * ?")
private void accountStatusMonitor() throws Exception {
log.info("用户有效期监控开启");
log.info("当前服务是否是leader{}", service.isLeader());
if (!service.isLeader()) {
return;
}
long threeDaysAgo = System.currentTimeMillis() - 3 * ONE_DAY;
Date date = new Date(threeDaysAgo);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
String format = simpleDateFormat.format(date);
//管理员
List<User> users = userRepository.listManagerHasExpiredDate(format);
for (User user : users) {
// 获取管理员的有效期时间
Date expireDate = user.getExpiredDate();
Long useTime = expireDate.getTime() - System.currentTimeMillis();
// 剩余时间小于3天
if (useTime <= 3 * ONE_DAY) {
String content = null;
if (useTime <= 0L) {
content = "用户账号已过期,请联系管理员进行重置!";
user.setStatus(BocloudStatus.Basic.EXPIRED.name());
user.setGmtModify(new Date());
user.setMenderId(1L);
userRepository.update(user);
} else if (useTime % ONE_DAY == 0L) {
content = "用户账号还有【" + useTime / ONE_DAY + "天】将过期,请尽快修改或重置!";
} else if (useTime % ONE_DAY > 0L) {
content = "用户账号还有【" + useTime / ONE_DAY + "天" + useTime % ONE_DAY / (60 * 60 * 1000L)
+ "小时】将过期,请尽快修改或重置!";
}
NotifyMessage message = new NotifyMessage(new RequestContext(RequestContext.Catalog.Manager, user.getId(), 0L, null, null),
"用户账号使用时间到期预警", content, true, false);
amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
message);
log.info("账号到期预警信息发送完毕!管理员{}", user.getName());
}
}
//租户
List<Tenant> tenants = tenantRepository.listManagerHasExpiredDate();
for (Tenant tenant : tenants) {
Date expireDate = tenant.getExpiredDate();
// 账号剩余使用时间
Long useTime = expireDate.getTime() - System.currentTimeMillis();
if (useTime <= 3 * ONE_DAY) {
String content = null;
if (useTime <= 0L) {
content = "租户账号已过期,请联系管理员进行重置!";
tenant.setStatus(BocloudStatus.Basic.EXPIRED.name());
tenant.setGmtModify(new Date());
tenant.setMenderId(1L);
tenantRepository.update(tenant);
} else if (useTime % ONE_DAY == 0L) {
content = "租户账号还有【" + useTime / ONE_DAY + "天】将过期,请尽快修改或重置!";
} else if (useTime % ONE_DAY > 0L) {
content = "租户账号还有【" + useTime / ONE_DAY + "天" + useTime % ONE_DAY / (60 * 60 * 1000L)
+ "小时】将过期,请尽快修改或重置!";
}
NotifyMessage message = new NotifyMessage(new RequestContext(RequestContext.Catalog.Tenant, tenant.getId(), 0L, null, null),
"租户账号使用时间到期预警", content, true, false);
amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
message);
log.info("账号到期预警信息发送完毕!租户{}", tenant.getName());
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
this.accountStatusMonitor();
}
}

View File

@ -0,0 +1,66 @@
package com.bocloud.sms.booter.scheduler;
import com.bocloud.sms.entity.SystemNotice;
import com.bocloud.sms.interfaces.SystemNoticeService;
import com.bocloud.sms.repository.SystemNoticeRepository;
import com.bocloud.sms.service.SystemNoticeServiceImpl;
import com.google.common.collect.Lists;
import com.megatron.common.model.Param;
import com.megatron.common.model.Sign;
import com.megatron.common.utils.MapTools;
import com.megatron.framework.core.CurrentService;
import com.megatron.framework.lock.AutoCloseLock;
import com.megatron.framework.lock.LockFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
@Slf4j
@RequiredArgsConstructor
public class SystemNoticeScheduler implements InitializingBean {
private final CurrentService service;
private final SystemNoticeService systemNoticeService;
private final SystemNoticeRepository systemNoticeRepository;
private final LockFactory lockFactory;
@Scheduled(cron = "0 */2 * * * ?")
protected void sendNotice() {
log.debug("[执行]定时发送系统公告");
log.debug("当前服务是否是leader{}", service.isLeader());
if (!service.isLeader()) {
return;
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String path = SystemNoticeScheduler.class.getSimpleName() + "_sendNotice";
try (AutoCloseLock lock = lockFactory.getACLock(path)) {
Assert.isTrue(lock.acquire(10, TimeUnit.SECONDS), "请求超时");
// 获取未发送且已经到发送时间的系统公告进行发送
List<Param> params = Lists.newArrayList();
params.add(new Param(MapTools.simpleMap("status", SystemNoticeServiceImpl.StatusEnum.NOTSEND), Sign.EQ));
params.add(new Param(MapTools.simpleMap("sendTime", sdf.format(new Date())), Sign.LET));
List<SystemNotice> notices = systemNoticeRepository.list(params);
Assert.notNull(notices, "没有数据");
for (SystemNotice notice : notices) {
systemNoticeService.sendMsg(notice.getId());
}
} catch (Exception e) {
log.error("SystemNoticeScheduler sendNotice error:", e);
}
}
@Override
public void afterPropertiesSet() {
this.sendNotice();
}
}

View File

@ -0,0 +1,142 @@
package com.bocloud.sms.booter.scheduler;
import com.alibaba.druid.util.StringUtils;
import com.bocloud.cmp.boot.model.BoCloudExchange;
import com.bocloud.sms.entity.SystemConfig;
import com.bocloud.sms.entity.Tenant;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.model.NotifyMessage;
import com.bocloud.sms.repository.SystemConfigRepository;
import com.bocloud.sms.repository.TenantRepository;
import com.bocloud.sms.repository.UserRepository;
import com.megatron.common.model.RequestContext;
import com.megatron.framework.core.CurrentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* 使
*
* @author wangyu
* @version 4.2.1-SNAPSHOT
* @since 2019/11/11
*/
@RequiredArgsConstructor
@Component
@Slf4j
public class UserPasswordMonitor implements InitializingBean {
private final CurrentService service;
private final TenantRepository tenantRepository;
private final UserRepository userRepository;
private final SystemConfigRepository systemConfigRepository;
private final AmqpTemplate amqpTemplate;
// 一天毫秒数
private static final Long ONE_DAY = 24 * 60 * 60 * 1000L;
/**
*
*
* @throws Exception
*/
@Scheduled(cron = "0 0 0 * * ?")
protected void monitor() throws Exception {
log.info("当前服务是否是leader{}", service.isLeader());
if (!service.isLeader()) {
return;
}
// 密码最大使用时长,若用户最后一次密码至今时长超过该值,则用户被冻结
Long pwdMaxUsage = 90 * ONE_DAY;
SystemConfig config = systemConfigRepository.queryByCode("pwdExpireDay");
if (null != config) {
String value = config.getValue();
if (!StringUtils.isEmpty(value)) {
pwdMaxUsage = Long.parseLong(value) * ONE_DAY;
// 需对密码最大使用时间判断,如果为-1表示过期时间为无期限
if ("-1".equals(value)) {
return;
}
}
}
// 租户
List<Tenant> tenants = tenantRepository.list(1, Integer.MAX_VALUE, new ArrayList<>(), null);
for (Tenant tenant : tenants) {
Date lastPwdModifyDate = tenant.getLastPwdModifyDate();
if (null == lastPwdModifyDate) {
tenant.setLastPwdModifyDate(new Date());
tenant.setGmtModify(new Date());
tenantRepository.update(tenant);
continue;
}
// 密码已使用时间
Long useTime = System.currentTimeMillis() - lastPwdModifyDate.getTime();
// 密码剩余使用时间
Long residueTime = pwdMaxUsage - useTime;
if (residueTime <= 3 * ONE_DAY) {
String content = null;
if (residueTime < 0L) {
content = "登录密码已过期,租户账号将被冻结,请联系管理员进行重置密码!";
tenantRepository.lock(tenant.getId(), 1L);
} else if (residueTime % ONE_DAY == 0L) {
content = "登录密码还有【" + residueTime / ONE_DAY + "天】将过期,请尽快修改或重置密码!";
} else if (residueTime % ONE_DAY > 0L) {
content = "登录密码还有【" + residueTime / ONE_DAY + "天" + residueTime % ONE_DAY / (60 * 60 * 1000L)
+ "小时】将过期,请尽快修改或重置密码!";
}
NotifyMessage message = new NotifyMessage(new RequestContext(RequestContext.Catalog.Tenant, tenant.getId(),
tenant.getId(), null, null), "租户账号密码使用时间到期预警", content, true, false);
amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue",
message);
log.info("密码到期预警信息发送完毕!租户{}", tenant.getName());
}
}
// 用户
List<User> users = userRepository.list(1, Integer.MAX_VALUE, new ArrayList<>(), null, null);
for (User user : users) {
if (1L == user.getId()) {
// admin账户忽略密码永不过期
continue;
}
Date lastPwdModifyDate = user.getLastPwdModifyDate();
if (null == lastPwdModifyDate) {
user.setLastPwdModifyDate(new Date());
user.setGmtModify(new Date());
userRepository.update(user);
continue;
}
// 密码已使用时间
Long useTime = System.currentTimeMillis() - lastPwdModifyDate.getTime();
// 密码剩余使用时间
Long residueTime = pwdMaxUsage - useTime;
if (residueTime <= 3 * ONE_DAY) {
String content = null;
if (residueTime < 0L) {
content = "登录密码已过期,用户将被冻结,请联系管理员进行重置密码!";
userRepository.lock(user.getId(), 1L);
} else if (residueTime % ONE_DAY == 0L) {
content = "登录密码还有【" + residueTime / ONE_DAY + "天】将过期,请尽快修改或重置密码!";
} else if (residueTime % ONE_DAY > 0L) {
content = "登录密码还有【" + residueTime / ONE_DAY + "天" + residueTime % ONE_DAY / (60 * 60 * 1000L)
+ "小时】将过期,请尽快修改或重置密码!";
}
NotifyMessage userMessage = new NotifyMessage(new RequestContext(RequestContext.Catalog.User, user.getId(),
user.getTenantId(), null, null), "用户密码使用时间到期预警", content, true, false);
amqpTemplate.convertAndSend(BoCloudExchange.Default.DIRECT.getExchange(), "event.notice.queue", userMessage);
log.info("密码到期预警信息发送完毕!用户{}", user.getName());
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
this.monitor();
}
}

View File

@ -0,0 +1,98 @@
package com.bocloud.sms.booter.scheduler;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.sms.entity.Message;
import com.bocloud.sms.repository.MessageRepository;
import com.megatron.common.enums.PostDataFormat;
import com.megatron.common.http.HttpClient;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.*;
/**
*
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class YunKongMessageSchedule {
@Value("${message.enable:false}")
private Boolean enable;
@Value("${message.host:http://127.0.0.1}")
private String host;
@Value("${message.reqUserId:0}")
private String reqUserId;
@Value("${message.systemId:0}")
private String systemId;
@Value("${message.userId:0}")
private String userId;
private final MessageRepository messageRepository;
@Scheduled(cron = "${message.schedule:0 0/1 * * * ?}")
protected void schedule() {
if (!enable) return;
Map<String, Object> params = new HashMap<>();
params.put("page", 1);
params.put("limit", 1000);
params.put("approve_status", 1);
params.put("userId", userId);
params.put("taskStatus", "");
params.put("taskName", "");
Map<String, Object> request = new HashMap<>();
request.put("reqUserId", reqUserId);
request.put("systemId", systemId);
request.put("method", "/activiti/rwMainTask/getTaskList");
request.put("params", params);
String url = host + "/system/common/queryYKInterface";
HttpClient httpClient = new HttpClient(PostDataFormat.RAW);
log.info("curl -k -X POST -H 'Content-Type: application/json' -d '{}' '{}'", JSON.toJSONString(request), url);
Result result = httpClient.post(new HashMap<>(), request, url);
Assert.isTrue(result.isSuccess(), result.getMessage());
JSONArray array = JSON.parseObject(result.getMessage()).getJSONObject("data").getJSONArray("data");
List<Message> oldMessages = messageRepository.list(Message.class, "select * from message where external_id is not null");
List<Message> existsMessages = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
JSONObject item = array.getJSONObject(i);
String externalId = item.getString("record_id");
Message message = oldMessages.stream()
.filter(m -> externalId.equals(m.getExternalId()))
.findFirst().orElse(new Message());
message.setCatalog(RequestContext.Catalog.User);
message.setStatus("UNREAD");
message.setGmtCreate(new Date());
message.setCreatorId(1L);
message.setOwnerId(1L);
message.setSender(1L);
message.setExternalId(externalId);
message.setName(item.getString("task_name"));
message.setContent(item.getString("task_content"));
if (message.getId() == null) {
messageRepository.save(message);
} else {
messageRepository.update(message);
existsMessages.add(message);
}
}
oldMessages.removeAll(existsMessages);
for (Message m : oldMessages) {
messageRepository.remove(m.getId(), 1L);
}
}
}

View File

@ -0,0 +1,15 @@
package com.bocloud.sms.booter.syslog;
import ch.qos.logback.classic.net.SyslogAppender;
import ch.qos.logback.core.net.SyslogOutputStream;
import java.net.SocketException;
import java.net.UnknownHostException;
public class SysLogAppenderTcpAndUdp extends SyslogAppender {
@Override
public SyslogOutputStream createOutputStream() throws SocketException, UnknownHostException {
return new SyslogOutputStreamTcpAndUdp(getSyslogHost(), getPort());
}
}

View File

@ -0,0 +1,22 @@
package com.bocloud.sms.booter.syslog;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.pattern.CompositeConverter;
import java.util.HashMap;
import java.util.Map;
public class SysLogLevelConvertor extends CompositeConverter<ILoggingEvent> {
private static final Map<String, String> MAP = new HashMap<>() {{
this.put("DEBUG", "7");
this.put("INFO", "6");
this.put("WARN", "4");
this.put("ERROR", "3");
}};
@Override
protected String transform(ILoggingEvent iLoggingEvent, String s) {
return MAP.getOrDefault(iLoggingEvent.getLevel().toString(), iLoggingEvent.getLevel().toString());
}
}

View File

@ -0,0 +1,70 @@
package com.bocloud.sms.booter.syslog;
import ch.qos.logback.core.net.SyslogOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
public class SyslogOutputStreamTcpAndUdp extends SyslogOutputStream {
private static final int MAX_LEN_TCP = 1024;
private InetAddress addressTcp;
private Socket socketTcp;
private ByteArrayOutputStream baosTcp = new ByteArrayOutputStream();
final private int portTcp;
public SyslogOutputStreamTcpAndUdp(String syslogHost, int port) throws SocketException, UnknownHostException {
super(syslogHost, port);
this.addressTcp = InetAddress.getByName(syslogHost);
this.portTcp = port;
try {
this.socketTcp = new Socket(addressTcp, portTcp);
} catch (IOException e) {
throw new SocketException(e);
}
}
@Override
public void write(byte[] byteArray, int offset, int len) throws IOException {
super.write(byteArray, offset, len);
baosTcp.write(byteArray, offset, len);
}
@Override
public void flush() throws IOException {
super.flush();
byte[] bytes = baosTcp.toByteArray();
// clean up for next round
if (baosTcp.size() > MAX_LEN_TCP) {
baosTcp = new ByteArrayOutputStream();
} else {
baosTcp.reset();
}
// after a failure, it can happen that bytes.length is zero
// in that case, there is no point in sending out an empty message/
if (bytes.length == 0) {
return;
}
if (this.socketTcp != null) {
socketTcp.getOutputStream().write(bytes);
}
}
@Override
public void close() {
super.close();
addressTcp = null;
try {
socketTcp.close();
} catch (IOException ignored) {
}
}
}

View File

@ -0,0 +1,265 @@
package com.bocloud.sms.booter.websocket.logview;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.boot.model.BoCloudService;
import com.bocloud.sms.booter.websocket.model.LogViewMessage;
import com.google.common.collect.Lists;
import com.megatron.common.enums.PostDataFormat;
import com.megatron.common.http.HttpClient;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.LogBean;
import com.megatron.common.model.Result;
import com.megatron.common.utils.JSONTools;
import com.megatron.common.utils.ListTool;
import com.megatron.common.utils.LogCrawler;
import com.megatron.common.utils.MapTools;
import com.megatron.framework.core.RegistryService;
import com.megatron.framework.core.Service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.*;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* @ Description @ Author @ Date Created in 11:21 2018/11/5 @ Modified By
*/
@Slf4j
@Component
public class LogViewHandler implements WebSocketHandler {
private static final String FETCH_SERVICE = "/logview";
private static final String[] EXCLUDE_SERVERS =
{"tds.server", "ams.server", "cms.server", "mcs.server", "cop.server", "tse.server", "gaia.server",
"cos.server", "sms.server", "gms.server", "ros.server", "ams.server", "bms.server", "cmp.server"};
private final RegistryService registryService;
@Value("${logging.dir:/log/services}")
private String loggingDir;
public LogViewHandler(RegistryService registryService) {
this.registryService = registryService;
}
private String buildUrl(String host, String value) {
return "http://" + host + (!StringUtils.hasText(value) ? "" : value) + FETCH_SERVICE;
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
if (message instanceof TextMessage textMessage) {
String path = new File(loggingDir).getPath() + File.separator;
JSONObject messageJson = JSONTools.isJSONObj(textMessage.getPayload());
if (null == messageJson) {
return;
}
String log = messageJson.getString("logger");
String host = messageJson.getString("host");
Long position = messageJson.getLong("position");
Long presize = messageJson.getLong("logsize");
if (null == position || position <= 0) {
position = 0L;
}
if (null == presize) {
presize = 0L;
}
LogViewMessage logViewMessage = null;
if (Arrays.asList(EXCLUDE_SERVERS).contains(log)) {
path += log.split("\\.")[0] + ".log";
String url = buildUrl(host, "/v1");
logViewMessage = getRemoteLog(url, path, position, presize);
} else if ("gaia.server".equals(log)) {
String url = buildUrl(host, "/api/" + log.split("\\.")[0] + "/v1");
logViewMessage = getRemoteLog(url, "", position, presize, host.split(":")[0]);
} else if ("pontus.server".equals(log)) {
String url = buildUrl(host, "/api/" + log.split("\\.")[0] + "/v1");
logViewMessage = getRemoteLog(url, "", position, presize, null);
} else if (StringUtils.hasText(log) && log.contains("service.log")) {
String user = messageJson.getString("user");
String password = messageJson.getString("password");
String target = messageJson.getString("target");
path = messageJson.getString("filepath");
String category = messageJson.getString("category");
Integer port = messageJson.getInteger("port");
logViewMessage = getRemoteLog(path, position, presize, user, password, port, target, category);
}
session.sendMessage(new TextMessage(JSONObject.toJSONString(logViewMessage)));
} else {
log.error("Unexpected WebSocket message type: " + message);
throw new IllegalStateException("Unexpected WebSocket message type: " + message);
}
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
}
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
}
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
*
*
* @param url
* @param filepath
* @param position
* @param presize
* @return
*/
private LogViewMessage getRemoteLog(String url, String filepath, Long position, Long presize) {
LogViewMessage message = null;
HttpClient client = new HttpClient();
client.setDataFormat(PostDataFormat.RAW);
Map<String, Object> param = MapTools.simpleMap("filepath", filepath);
param.put("position", position);
param.put("presize", presize);
Result result = client.get(null, param, url);
if (result.isFailed()) {
message = new LogViewMessage("", position);
} else {
JSONObject jsonObject = JSONObject.parseObject(result.getMessage());
jsonObject = JSONObject.parseObject(jsonObject.getString("message"));
String originalMessage = jsonObject.getString("content");
String msg = originalMessage.replaceAll("\\[(.{2,4})[m]", "");
message = new LogViewMessage(msg, jsonObject.getLong("position"));
}
return message;
}
/**
*
*
* @param filepath
* @param position
* @param presize
* @param user
* @param password
* @param port
* @return
*/
private LogViewMessage getRemoteLog(String filepath, Long position, Long presize, String user, String password,
Integer port, String host, String category) {
String address = registryService.getService(Service.create(BoCloudService.GAIA.getName()));
if (!StringUtils.hasText(address)) {
return new LogViewMessage("远端日志获取异常");
}
String url = address + "/api/gaia/v1/job/submit";
log.info("服务地址:" + url);
LogViewMessage viewMessage;
HttpClient client = new HttpClient();
client.setDataFormat(PostDataFormat.RAW);
// 同步请求
Map<String, Object> param = MapTools.simpleMap("response", "sync");
// module设置
Map<String, Object> module = MapTools.simpleMap("name", "logview");
Map<String, Object> logview = MapTools.simpleMap("position", position);
logview.put("presize", presize);
logview.put("log_file", filepath);
Map<String, Object> args = MapTools.simpleMap("gaia_logview", logview);
module.put("args", args);
param.put("module", module);
Map<String, Object> target = MapTools.simpleMap("host", host);
target.put("pasd", password);
target.put("user", user);
if (!StringUtils.hasText(category) || !"windows".equalsIgnoreCase(category)) {
category = "Linux";
}
target.put("category", category);
if (null == port) {
port = "windows".equalsIgnoreCase(category) ? 5985 : 22;
}
target.put("port", port);
List<Object> targets = Lists.newArrayList();
targets.add(target);
param.put("targets", targets);
Result result = client.post(null, param, url);
log.info("请求结果内容:" + JSONObject.toJSONString(result));
if (result.isFailed()) {
viewMessage = new LogViewMessage(false, "文件可能不存在或文件为空", position);
} else {
JSONObject object = JSONObject.parseObject(result.getMessage());
List<JSONObject> datas = JSONObject.parseArray(object.getString("data"), JSONObject.class);
if (!ListTool.isEmpty(datas)) {
JSONObject data = datas.get(0);
JSONObject message = data.getJSONObject("message");
if (null != object.getBoolean("success") && object.getBoolean("success")) {
String content = null;
if (null != message) {
content = message.getString("content");
}
viewMessage = new LogViewMessage(true, content, object.getLong("curr_position"));
} else {
viewMessage = new LogViewMessage(false, "文件不存在或存在的文件无法打开", position);
}
} else {
viewMessage = new LogViewMessage(false, "文件可能不存在或文件为空", position);
}
}
return viewMessage;
}
/**
* worker
*
* @param url
* @param filepath
* @param position
* @param presize
* @param target workerIP
* @return
*/
private LogViewMessage getRemoteLog(String url, String filepath, Long position, Long presize, String target) {
LogViewMessage message;
HttpClient client = new HttpClient();
client.setDataFormat(PostDataFormat.RAW);
Map<String, Object> param = MapTools.simpleMap("filepath", filepath);
param.put("position", position);
param.put("presize", presize);
if (StringUtils.hasText(target)) {
param.put("target", target);
}
Result result = client.post(null, param, url);
if (result.isFailed()) {
message = new LogViewMessage("", position);
} else {
JSONObject jsonObject = JSONObject.parseObject(result.getMessage());
String originalMessage = jsonObject.getString("message");
String msg = originalMessage.replaceAll("\\[(.{2,4})[m]", "");
message = new LogViewMessage(msg, jsonObject.getLong("filesize"));
}
return message;
}
private LogViewMessage getLocalLog(String filepath, Long position, Long presize) {
LogViewMessage message = null;
GeneralResult<LogBean> crawlResult = LogCrawler.crawl(filepath, position, presize);
if (crawlResult.isFailed()) {
message = new LogViewMessage("", position);
} else {
LogBean logBean = crawlResult.getData();
String originalMessage = logBean.getContent();
String msg = originalMessage.replaceAll("\\[(.{2,4})[m]", "");
message = new LogViewMessage(msg, logBean.getPosition());
}
return message;
}
}

View File

@ -0,0 +1,171 @@
package com.bocloud.sms.booter.websocket.message;
import com.alibaba.fastjson.JSON;
import com.bocloud.sms.booter.websocket.model.CommonMessage;
import com.megatron.common.model.OperateResult;
import com.megatron.common.model.RequestContext.Catalog;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import java.io.IOException;
import java.util.Vector;
/**
* WebSocket
*
* @author dmw
*/
@Slf4j
@Component
public class MessageHandler implements WebSocketHandler, InitializingBean {
private Vector<WebSocketSession> webSocketSessions;
/*
* (non-Javadoc) WebSocket
*
* @see org.springframework.web.socket.WebSocketHandler#
* afterConnectionEstablished(org.springframework.web.socket. WebSocketSession)
*/
@Override
public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
if (null == webSocketSession.getAttributes().get("catalog")
|| null == webSocketSession.getAttributes().get("id")) {
log.error("Target Information Is Null !!");
throw new Exception("Target Information Is Null !!");
}
this.webSocketSessions.addElement(webSocketSession);
}
/*
* (non-Javadoc)
*
* @see org.springframework.web.socket.WebSocketHandler#handleMessage(org.
* springframework.web.socket.WebSocketSession,
* org.springframework.web.socket.WebSocketMessage)
*/
@Override
public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> message) throws Exception {
if (webSocketSession.isOpen() && "HeartBeat".equals(message.getPayload().toString())) {
OperateResult result = new OperateResult();
result.setData("{}");
result.setSuccess(true);
result.setOperate(message.getPayload().toString());
CommonMessage content = new CommonMessage(JSON.toJSONString(result));
webSocketSession.sendMessage(new TextMessage(content.toString()));
}
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.socket.WebSocketHandler#handleTransportError(org.
* springframework.web.socket.WebSocketSession, java.lang.Throwable)
*/
@Override
public void handleTransportError(WebSocketSession webSocketSession, Throwable exception) throws Exception {
if (webSocketSession.isOpen()) {
webSocketSession.close();
}
this.webSocketSessions.remove(webSocketSession);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.socket.WebSocketHandler#afterConnectionClosed(org
* .springframework.web.socket.WebSocketSession,
* org.springframework.web.socket.CloseStatus)
*/
@Override
public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
this.webSocketSessions.remove(webSocketSession);
}
/*
* (non-Javadoc)
*
* @see
* org.springframework.web.socket.WebSocketHandler#supportsPartialMessages()
*/
@Override
public boolean supportsPartialMessages() {
return false;
}
/**
* websocketsession
*
* @param targetId
*/
public void closeUserSession(Long targetId, String targetCatalog) {
for (int i = this.webSocketSessions.size() - 1; i >= 0; i--) {
WebSocketSession webSocketSession = webSocketSessions.get(i);
String catalog = (String) webSocketSession.getAttributes().get("catalog");
Long id = (Long) webSocketSession.getAttributes().get("id");
if (null == catalog || null == id) {
continue;
}
if (id.equals(targetId) && catalog.equalsIgnoreCase(targetCatalog)) {
if (webSocketSession.isOpen()) {
try {
webSocketSession.close();
webSocketSessions.remove(webSocketSession);
log.info("websocket session closed");
} catch (IOException e) {
log.error("close websocket session exception:", e);
}
}
}
}
}
public void sendMessageToUsers(CommonMessage message) {
for (WebSocketSession webSocketSession : this.webSocketSessions) {
try {
if (webSocketSession.isOpen()) {
webSocketSession.sendMessage(new TextMessage(message.toString()));
}
} catch (IOException e) {
log.error("Send WebSocket Message To All Users Exception {}", e.getMessage());
}
}
}
/**
* websocketID
*
* @param userId ID
* @param message
*/
public void sendMessageToUser(Catalog targetCatalog, Long userId, CommonMessage message) {
for (WebSocketSession webSocketSession : webSocketSessions) {
String catalog = (String) webSocketSession.getAttributes().get("catalog");
Long id = (Long) webSocketSession.getAttributes().get("id");
if (id.equals(userId) && (Catalog.Tenant != targetCatalog || Catalog.Tenant.name().equalsIgnoreCase(catalog))) {
try {
if (webSocketSession.isOpen()) {
webSocketSession.sendMessage(new TextMessage(message.toString()));
log.info("Send WebSocket Message to [{} {}] Success ", catalog, userId);
} else {
log.warn("Send WebSocket Message to [{} {}] Exception for session is closed ", catalog,
userId);
}
} catch (IOException e) {
log.error("Send WebSocket Message to [{} {}] Exception:{}", catalog, userId, e.getMessage());
}
}
}
}
@Override
public void afterPropertiesSet() throws Exception {
this.webSocketSessions = new Vector<>();
}
}

View File

@ -0,0 +1,67 @@
/**
* @author hty
* @time 9:39:37
* @date 2014125
*/
package com.bocloud.sms.booter.websocket.message;
import com.auth0.jwt.interfaces.Claim;
import com.megatron.common.utils.Common;
import com.megatron.common.utils.Tokens;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import java.util.Map;
@Component
@Slf4j
public class MessageInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(@NonNull ServerHttpRequest request, @NonNull ServerHttpResponse response, @NonNull WebSocketHandler wsHandler,
@NonNull Map<String, Object> attributes) throws Exception {
if (request instanceof ServletServerHttpRequest) {
HttpServletRequest httpRequest = ((ServletServerHttpRequest) request).getServletRequest();
String token = httpRequest.getHeader("Sec-WebSocket-Protocol");
if (!StringUtils.hasText(token)) {
return false;
}
Claim claim = Tokens.parse(token);
if (null == claim) {
return false;
}
String catalog = claim.asMap().get("catalog").toString();
if (!StringUtils.hasText(catalog)) {
return false;
}
Long id = Long.valueOf(claim.asMap().get(Common.UUID).toString());
attributes.put("catalog", catalog);
attributes.put("id", id);
return true;
}
return false;
}
@Override
public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
Exception exception) {
if (request instanceof ServletServerHttpRequest) {
HttpServletRequest servletRequest = ((ServletServerHttpRequest) request).getServletRequest();
HttpServletResponse servletResponse = ((ServletServerHttpResponse) response).getServletResponse();
String SEC_WEBSOCKET_PROTOCOL = "Sec-WebSocket-Protocol";
if (StringUtils.hasText(servletRequest.getHeader(SEC_WEBSOCKET_PROTOCOL))) {
servletResponse.addHeader("Sec-WebSocket-Protocol", servletRequest.getHeader("Sec-WebSocket-Protocol"));
}
}
}
}

View File

@ -0,0 +1,63 @@
package com.bocloud.sms.booter.websocket.model;
import com.alibaba.fastjson.JSONObject;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
/**
*
*
* @author dmw
*/
public class CommonMessage implements Message<Object> {
private MessageCategory category;
private String content;
/**
* @return the category
*/
public MessageCategory getCategory() {
return category;
}
/**
* @param category the category to set
*/
public void setCategory(MessageCategory category) {
this.category = category;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public MessageHeaders getHeaders() {
return null;
}
@Override
public Object getPayload() {
return null;
}
public CommonMessage(String content) {
this.setCategory(MessageCategory.TEXT);
this.setContent(content);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return JSONObject.toJSONString(this);
}
}

View File

@ -0,0 +1,88 @@
package com.bocloud.sms.booter.websocket.model;
public class LogViewMessage {
private boolean success;
private MessageCategory category;
private String content;
private Long position;
/**
* @return the success
*/
public boolean isSuccess() {
return success;
}
/**
* @param success the success to set
*/
public void setSuccess(boolean success) {
this.success = success;
}
/**
* @return the category
*/
public MessageCategory getCategory() {
return category;
}
/**
* @param category the category to set
*/
public void setCategory(MessageCategory category) {
this.category = category;
}
/**
* @return the content
*/
public String getContent() {
return content;
}
/**
* @param content the content to set
*/
public void setContent(String content) {
this.content = content;
}
/**
* @return the position
*/
public Long getPosition() {
return position;
}
/**
* @param position the position to set
*/
public void setPosition(Long position) {
this.position = position;
}
public LogViewMessage() {
super();
}
public LogViewMessage(String content) {
this.category = MessageCategory.VIEW_LOG;
this.content = content;
}
public LogViewMessage(String content, Long position) {
this.category = MessageCategory.VIEW_LOG;
this.content = content;
this.position = position;
}
public LogViewMessage(Boolean success, String content, Long position) {
this.success = success;
this.category = MessageCategory.VIEW_LOG;
this.content = content;
this.position = position;
}
}

View File

@ -0,0 +1,32 @@
package com.bocloud.sms.booter.websocket.model;
public enum MessageCategory {
/**
*
*/
TEXT,
/**
*
*/
UPLOAD,
/**
*
*/
UPLOAD_ACK,
/**
*
*/
UPLOAD_CANCEL,
/**
*
*/
TASK,
/**
*
*/
CALLBACK,
/**
*
*/
VIEW_LOG
}

View File

@ -0,0 +1,53 @@
package com.bocloud.sms.booter.websocket.model;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
/**
*
*
* @author zero
*
*/
public class UploadACK implements Message<Object> {
private MessageCategory category;
private String content;
/**
* @return the category
*/
public MessageCategory getCategory() {
return category;
}
/**
* @param category the category to set
*/
public void setCategory(MessageCategory category) {
this.category = category;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public MessageHeaders getHeaders() {
return null;
}
@Override
public Object getPayload() {
return null;
}
public UploadACK(String content) {
this.setCategory(MessageCategory.UPLOAD_ACK);
this.setContent(content);
}
}

View File

@ -0,0 +1,15 @@
package com.bocloud.sms.booter.websocket.model;
import lombok.Data;
@Data
public class UploadBean {
private Long timestamp;
private String filename;
private String path;
private String source;
private String target;
private boolean sendover;
}

View File

@ -0,0 +1,53 @@
package com.bocloud.sms.booter.websocket.model;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
/**
*
*
* @author zero
*
*/
public class UploadCancel implements Message<Object> {
private MessageCategory category;
private String content;
/**
* @return the category
*/
public MessageCategory getCategory() {
return category;
}
/**
* @param category the category to set
*/
public void setCategory(MessageCategory category) {
this.category = category;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public MessageHeaders getHeaders() {
return null;
}
@Override
public Object getPayload() {
return null;
}
public UploadCancel(String content) {
this.setCategory(MessageCategory.UPLOAD_CANCEL);
this.setContent(content);
}
}

View File

@ -0,0 +1,51 @@
package com.bocloud.sms.booter.websocket.model;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
/**
*
*
* @author zero
*/
public class UploadMessage implements Message<Object> {
private MessageCategory category;
private String content;
/**
* @return the category
*/
public MessageCategory getCategory() {
return category;
}
/**
* @param category the category to set
*/
public void setCategory(MessageCategory category) {
this.category = category;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public MessageHeaders getHeaders() {
return null;
}
@Override
public Object getPayload() {
return null;
}
public UploadMessage(String content) {
this.setCategory(MessageCategory.UPLOAD);
this.setContent(content);
}
}

View File

@ -0,0 +1,214 @@
package com.bocloud.sms.booter.websocket.upload;
import com.alibaba.fastjson.JSONObject;
import com.bocloud.sms.booter.websocket.model.UploadACK;
import com.bocloud.sms.booter.websocket.model.UploadBean;
import com.bocloud.sms.booter.websocket.model.UploadCancel;
import com.bocloud.sms.booter.websocket.model.UploadMessage;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;
@Component
@Slf4j
public class UploadServiceHandler implements WebSocketHandler {
private static final String SAVE_SUCCESS = "SAVE_SUCCESS";
private static final String SAVE_FAILURE = "SAVE_FAILURE";
private static final String CANCEL_SUCCESS = "CANCEL_SUCCESS";
private static final String CANCEL_FAILURE = "CANCEL_FAILURE";
private static final String UPLOAD_CANCEL = "UPLOAD_CANCEL";
private static List<WebSocketSession> currentUsers;
static {
UploadServiceHandler.setCurrentUsers(new ArrayList<>());
}
@Value("${spring.upload.path:/home/cmp}")
private String path;
/**
* @return the currentUsers
*/
public static List<WebSocketSession> getCurrentUsers() {
return currentUsers;
}
/**
* @param currentUsers the currentUsers to set
*/
public static void setCurrentUsers(List<WebSocketSession> currentUsers) {
UploadServiceHandler.currentUsers = currentUsers;
}
/**
* byte[]
*
* @param byteBuffer byte[]
* @param outputFile
* @return : true : false
*/
private static boolean saveFile(ByteBuffer byteBuffer, String outputFile) {
FileOutputStream fstream = null;
File file = null;
try {
file = new File(outputFile);
if (!file.exists() && !file.createNewFile()) {
log.error("create new file error,path:{}", file.getPath());
return false;
}
fstream = new FileOutputStream(file, true);
fstream.write(byteBuffer.array());
} catch (Exception e) {
log.error("saveFile Exception:", e);
return false;
} finally {
if (fstream != null) {
try {
fstream.close();
} catch (IOException e1) {
log.error("close fileimput Exception:", e1);
}
}
}
return true;
}
private String getPath() {
if (this.path.endsWith(String.valueOf(File.separatorChar))) {
return this.path.substring(0, this.path.length() - 1);
}
return path;
}
@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
UploadServiceHandler.getCurrentUsers().add(session);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
if (message instanceof TextMessage) {
handleText(session, (TextMessage) message);
} else if (message instanceof BinaryMessage) {
handleBinary(session, (BinaryMessage) message);
} else {
log.error("Unexpected WebSocket message type: " + message);
throw new IllegalStateException("Unexpected WebSocket message type: " + message);
}
}
/**
*
*
* @param session
* @param message
*/
private void handleText(WebSocketSession session, TextMessage message) {
UploadBean uploadBean = null;
try {
if (message.getPayload().contains("upload")) {
uploadBean = JSONObject.parseObject(message.getPayload(), UploadBean.class);
String date = DateFormatUtils.format(Calendar.getInstance(), "yyyyMMdd");
String uuid = UUID.randomUUID().toString().replace("-", "");
String path = File.separatorChar + "tmp" + File.separatorChar + date + File.separatorChar + uuid;
File dir = new File(this.getPath(), path);
if (!dir.exists()) {
boolean flag = dir.mkdirs();
if (!flag) {
log.error("mkdir failed, path: " + dir.getPath());
return;
}
}
path = path + File.separatorChar + uploadBean.getFilename();
uploadBean.setTarget(this.getPath() + path);
session.getAttributes().put("uploadBean", uploadBean);
session.sendMessage(new TextMessage(JSONObject.toJSONString(new UploadACK(path))));
} else if (message.getPayload().contains("sendover")) {
session.sendMessage(new TextMessage(JSONObject.toJSONString(new UploadMessage("TRUE"))));
} else if (message.getPayload().contains(UPLOAD_CANCEL)) {
log.warn("用户取消文件上传");
uploadBean = (UploadBean) session.getAttributes().get("uploadBean");
File file = new File(uploadBean.getTarget());
this.deleteTmpFile(file);
session.sendMessage(new TextMessage(JSONObject.toJSONString(new UploadCancel(CANCEL_SUCCESS))));
}
} catch (IOException e) {
log.error("上传文件异常:", e);
if (null == uploadBean) {
return;
}
File file = new File(uploadBean.getTarget());
this.deleteTmpFile(file);
}
}
@SuppressWarnings("static-access")
private void handleBinary(WebSocketSession session, BinaryMessage message) throws IOException {
UploadBean uploadBean = (UploadBean) session.getAttributes().get("uploadBean");
if (null == uploadBean) {
return;
}
try {
if (saveFile(message.getPayload(), uploadBean.getTarget())) {
session.sendMessage(new TextMessage(JSONObject.toJSONString(new UploadMessage(SAVE_SUCCESS))));
} else {
session.sendMessage(new TextMessage(JSONObject.toJSONString(new UploadMessage(SAVE_FAILURE))));
this.deleteTmpFile(new File(uploadBean.getTarget()));
}
} catch (IOException e) {
log.error("上传文件异常:", e);
session.sendMessage(new TextMessage(JSONObject.toJSONString(new UploadMessage(SAVE_FAILURE))));
this.deleteTmpFile(new File(uploadBean.getTarget()));
}
}
/**
*
*
* @param file
*/
private void deleteTmpFile(File file) {
if (file.exists()) {
if (!file.delete()) {
log.error("file delete failed, path:{} " + file.getPath());
return;
}
File dirFile = file.getParentFile();
if (!dirFile.exists()) {
return;
}
if (Objects.requireNonNull(dirFile.list()).length == 0) {
if (!dirFile.delete()) {
log.error("file delete failed, path:{} " + file.getPath());
}
}
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
UploadServiceHandler.getCurrentUsers().remove(session);
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
if (session.isOpen()) {
session.close();
}
UploadServiceHandler.getCurrentUsers().remove(session);
}
@Override
public boolean supportsPartialMessages() {
return false;
}
}

View File

@ -0,0 +1,133 @@
server:
port: '18087'
spring:
application:
name: sms
thread:
core:
pool:
size: 1000
max:
pool:
size: 1000
queue:
capacity: 2000
upload:
path: /home/cmp
cloud:
zookeeper:
connect-string: 10.20.12.65:2181
home: /bocloud/cmp/product
auth:
username: bocloud
password: AES@CoU6oY/zuAoBbu6cdgOKlA==
config:
enabled: false
discovery:
register: true
enable: true
instance-host: 10.20.12.65
instance-port: ${server.port}
root: ${spring.cloud.zookeeper.home}/services
conn:
timeout: '50000'
session:
timeout: '50000'
datasource:
druid:
dialect: mysql
url: jdbc:mysql://10.20.12.65:3306/cmp?characterEncoding=utf8&useSSL=false
username: cmp
password: Gy2VghUgWHszx8gLFT4etT9ZVOukJi73KoG1q3Oz/DAz5h2mFVVunjcyaaKT9tMPsBgoWBFRmrYbhgqJqT/Q8A==
initialSize: '2'
maxActive: '30'
minIdle: '2'
maxWait: '60000'
poolPreparedStatements: 'true'
maxOpenPreparedStatements: '20'
maxPoolPreparedStatementPerConnectionSize: '20'
validationQuery: select 1
validationQueryTimeout: '1'
testOnBorrow: 'true'
testOnReturn: 'true'
testWhileIdle: 'true'
remove-abandoned: 'true'
remove-abandoned-timeout: '60'
log-abandoned: 'true'
timeBetweenEvictionRunsMillis: '10000'
minEvictableIdleTimeMillis: '30001'
asyncCloseConnectionEnable: 'true'
filters: config,stat,wall,log4j
publicKey: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJfVJOpXYGy8aBCk3zEoKKQDTVCCvJwhhithfY/I5PUvzFBAYygunmuCtUhzPUZ+1RJQds0Q4fu07m5mr5kv5ocCAwEAAQ==
connectionProperties: config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJfVJOpXYGy8aBCk3zEoKKQDTVCCvJwhhithfY/I5PUvzFBAYygunmuCtUhzPUZ+1RJQds0Q4fu07m5mr5kv5ocCAwEAAQ==;druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
use-global-data-source-stat: 'true'
rabbitmq:
host: 10.20.12.65
port: 5672
username: admin
password: AES@CoU6oY/zuAoBbu6cdgOKlA==
virtual-host: cmp
dynamic: 'true'
banner:
charset: UTF-8
freemarker:
checkTemplateLocation: 'false'
data:
redis:
host: 10.20.12.65
port: 6379
password: AES@CoU6oY/zuAoBbu6cdgOKlA==
timeout: 5000
lettuce:
pool:
enabled: false
# 连接池最大连接数(使用负值表示没有限制)
max-active: 5
# 连接池中的最大空闲连接
max-idle: 5
# 连接池中的最小空闲连接
min-idle: 1
# 连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: 5000
time-between-eviction-runs: 1000
servlet:
multipart:
max-file-size: 2MB
max-request-size: 20MB
main:
allow-circular-references: true
logging:
config: classpath:logback-spring.xml
dir: ${user.dir}/log/services
level:
root: info
com:
bocloud: info
file:
max-size: 100MB
max-history: '30'
total-size-cap: 2GB
syslog:
host: mai-miao.cn
port: 8340
facility: LOCAL1
level: error
prometheus:
timeout: 60000
url: http://10.20.12.65:9091
node:
url: http://10.20.12.65:9091
alertmanager:
url: http://10.20.12.65:9093
ipmi:
exporter:
url: http://10.20.12.65:9290
plugin:
mainPackage: com.bocloud
runMode: prod
repository:
path: ${user.dir}/plugins/
deploy:
env: physical
count: 1

View File

@ -0,0 +1,11 @@
/$$$$$$$ /$$ /$$$$$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$ /$$ /$$$$$$
| $$__ $$ | $$ /$$__ $$| $$$ /$$$| $$__ $$ /$$__ $$| $$$ /$$$ /$$__ $$
| $$ \ $$ /$$$$$$ /$$ /$$ /$$$$$$ /$$$$$$$ /$$$$$$$| $$ \__/| $$$$ /$$$$| $$ \ $$ | $$ \__/| $$$$ /$$$$| $$ \__/
| $$$$$$$ /$$__ $$| $$ | $$ /$$__ $$| $$__ $$ /$$__ $$| $$ | $$ $$/$$ $$| $$$$$$$/ | $$$$$$ | $$ $$/$$ $$| $$$$$$
| $$__ $$| $$$$$$$$| $$ | $$| $$ \ $$| $$ \ $$| $$ | $$| $$ | $$ $$$| $$| $$____/ \____ $$| $$ $$$| $$ \____ $$
| $$ \ $$| $$_____/| $$ | $$| $$ | $$| $$ | $$| $$ | $$| $$ $$| $$\ $ | $$| $$ /$$ \ $$| $$\ $ | $$ /$$ \ $$
| $$$$$$$/| $$$$$$$| $$$$$$$| $$$$$$/| $$ | $$| $$$$$$$| $$$$$$/| $$ \/ | $$| $$ | $$$$$$/| $$ \/ | $$| $$$$$$/
|_______/ \_______/ \____ $$ \______/ |__/ |__/ \_______/ \______/ |__/ |__/|__/ \______/ |__/ |__/ \______/
/$$ | $$
| $$$$$$/
\______/

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 读取application.properties中的配置 -->
<springProperty scope="context" name="service.name" source="spring.application.name"/>
<springProperty scope="context" name="logging.dir" source="logging.dir"/>
<springProperty scope="context" name="logging.file.total-size-cap" source="logging.file.total-size-cap"/>
<springProperty scope="context" name="logging.file.max-size" source="logging.file.max-size"/>
<springProperty scope="context" name="logging.file.max-history" source="logging.file.max-history"/>
<springProperty scope="context" name="logging.level.com.bocloud" source="logging.level.com.bocloud"/>
<springProperty scope="context" name="logging.level.root" source="logging.level.root"/>
<springProperty scope="context" name="logging.syslog.host" source="logging.syslog.host"/>
<springProperty scope="context" name="logging.syslog.port" source="logging.syslog.port"/>
<springProperty scope="context" name="logging.syslog.facility" source="logging.syslog.facility"/>
<springProperty scope="context" name="logging.syslog.level" source="logging.syslog.level"/>
<conversionRule conversionWord="ilevel" converterClass="com.bocloud.sms.booter.syslog.SysLogLevelConvertor"/>
<property name="local_log_pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %highlight(%-5level) [%thread] [%X{REQUEST_ID}] %cyan(%logger{32}):%L - %msg%n"/>
<property name="sys_log_pattern" value="{&quot;level&quot;:&quot;%ilevel{%level}&quot;,&quot;log_level&quot;:&quot;%level&quot;,&quot;time&quot;:&quot;%d{yyyy-MM-dd HH:mm:ss.SSS}&quot;,&quot;thread&quot;:&quot;%thread&quot;,&quot;class&quot;:&quot;%logger{36}.%M:%line&quot;,&quot;message&quot;:&quot;%msg&quot;}%n"/>
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<!-- 默认的控制台日志输出,一般生产环境都是后台启动,这个没太大作用 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${local_log_pattern}</pattern>
</layout>
</appender>
<!-- 配置文件轮转 -->
<appender name="LOG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<File>${logging.dir}/${service.name}.log</File>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>${logging.dir}/history/${service.name}.%d{yyyy-MM-dd}.%i.log.gz
</FileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>${logging.file.max-size}</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<MaxHistory>${logging.file.max-history}</MaxHistory>
<totalSizeCap>${logging.file.total-size-cap}</totalSizeCap>
</rollingPolicy>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>${local_log_pattern}</pattern>
</layout>
</appender>
<!--syslog -->
<appender name="SYSLOG" class="com.bocloud.sms.booter.syslog.SysLogAppenderTcpAndUdp">
<syslogHost>${logging.syslog.host}</syslogHost> <!-- Syslog 服务器的地址 -->
<port>${logging.syslog.port}</port> <!-- Syslog 服务器的端口号 -->
<facility>${logging.syslog.facility}</facility> <!-- Syslog 设备标识 -->
<suffixPattern>${sys_log_pattern}</suffixPattern>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>${logging.syslog.level}</level>
</filter>
</appender>
<root level="${logging.level.root}">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOG_FILE"/>
<appender-ref ref="SYSLOG"/>
</root>
<logger name="com.bocloud" level="${logging.level.com.bocloud}" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOG_FILE"/>
<appender-ref ref="SYSLOG"/>
</logger>
<logger name="com.alibaba.druid.pool.DruidAbstractDataSource" level="error" additivity="false">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="LOG_FILE"/>
<appender-ref ref="SYSLOG"/>
</logger>
</configuration>

View File

@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.bocloud</groupId>
<artifactId>bocloud.sms</artifactId>
<version>6.5.0-LTS-SZ</version>
</parent>
<artifactId>bocloud.sms.service</artifactId>
<dependencies>
<dependency>
<groupId>com.freedom</groupId>
<artifactId>megatron.framework</artifactId>
</dependency>
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
</dependency>
<dependency>
<groupId>com.bocloud</groupId>
<artifactId>bocloud.sms.storage</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
<!--导出Excel依赖-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<dependency>
<groupId>com.gitee.starblues</groupId>
<artifactId>spring-brick</artifactId>
<version>${spring-brick.version}</version>
</dependency>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.2</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>4.4.3</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,62 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Admission;
import com.bocloud.sms.model.AdmissionModel;
import com.megatron.common.exception.InternalServerException;
import com.megatron.common.model.*;
import java.util.List;
/**
* ip访
*
* @author wangyu
* @version 4.2.1-SNAPSHOT
* @since 2019/11/12
*/
public interface AdmissionService {
/**
* IP访
*
* @param pager
* @return
*/
GeneralResult<GridBean<Admission>> list(Pager pager);
/**
* IP访
*
* @param id
* @return
*/
GeneralResult<Admission> detail(Long id);
/**
* IP访
*
* @param admission
* @param requestContext
* @return
* @throws InternalServerException
*/
Result create(AdmissionModel admission, RequestContext requestContext) throws InternalServerException;
/**
* IP访
*
* @param id
* @return
* @throws InternalServerException
*/
Result remove(Long id) throws InternalServerException;
/**
* IP访
*
* @param ids
* @return
* @throws InternalServerException
*/
Result batchRemove(List<Long> ids) throws InternalServerException;
}

View File

@ -0,0 +1,23 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.ApiToken;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.RequestContext;
/**
* api token访
*/
public interface ApiTokenService {
GeneralResult<ApiToken> get(String token);
GeneralResult<ApiToken> create(ApiToken param, RequestContext context);
GeneralResult<GridBean<ApiToken>> list(Pager pager, RequestContext context);
GeneralResult<Void> modify(ApiToken param, RequestContext context);
GeneralResult<Void> remove(Long id, RequestContext context);
}

View File

@ -0,0 +1,10 @@
package com.bocloud.sms.interfaces;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.view.RedirectView;
public interface AutoLoginService {
RedirectView autoLogin(String host, HttpServletRequest request);
}

View File

@ -0,0 +1,126 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Business;
import com.bocloud.sms.entity.Project;
import com.bocloud.sms.model.BusinessModel;
import com.megatron.common.model.*;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @author tyl
* @time 2020/6/2 15:57
*/
public interface BusinessService {
/**
*
*
* @param pager
* @param requestContext
* @return
*/
GeneralResult<GridBean<Business>> list(Pager pager, RequestContext requestContext);
/**
*
*
* @param params
* @param user
* @return
*/
Result create(BusinessModel params, RequestContext user);
/**
*
*
* @param id
* @param params
* @param user
* @return
*/
Result modify(Long id, BusinessModel params, RequestContext user);
/**
*
*
* @param id
* @return
*/
GeneralResult<Business> detail(Long id);
/**
*
*
* @param id
* @param user
* @return
*/
Result remove(Long id, RequestContext user);
/**
*
*
* @param ids
* @param requestContext
* @return
*/
Result batchRemove(List<Long> ids, RequestContext requestContext);
/**
*
*
* @param id
* @return
*/
GeneralResult<List<Project>> listBusinessProject(Long id);
/**
*
*
* @param id
* @param projectIds
* @return
*/
Result businessAction(Long id, List<Long> projectIds);
/**
*
*
* @param title
* @param requestContext
* @return
*/
XSSFWorkbook importTemp2(String title, RequestContext requestContext);
/**
*
*
* @param response
* @return
*/
Result importTemp(HttpServletResponse response);
/**
*
*
* @param multipartFile
* @param requestContext
* @return
*/
Result importData(MultipartFile multipartFile, RequestContext requestContext);
/**
*
*
* @param paramList
* @param requestContext
* @return
*/
XSSFWorkbook export(List<Param> paramList, RequestContext requestContext);
}

View File

@ -0,0 +1,85 @@
package com.bocloud.sms.interfaces;
import com.megatron.common.exception.InternalServerException;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import com.bocloud.sms.entity.Department;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.model.DepartmentModel;
import java.util.List;
/**
* Service
*
* @author tyl
*/
public interface DepartmentService {
/**
*
*
* @param params
* @param requestContext
* @return
* @throws InternalServerException
*/
Result create(DepartmentModel params, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @param params
* @param requestContext
* @return
* @throws InternalServerException
*/
Result modify(Long id, DepartmentModel params, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @param requestContext
* @return
* @throws InternalServerException
*/
Result remove(Long id, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @return
*/
GeneralResult<Department> detail(Long id);
/**
*
*
* @param parentId
* @param requestContext
* @return
*/
GeneralResult<List<Department>> list(Long parentId, RequestContext requestContext);
/**
*
*
* @param name
* @param tenantId
* @return
*/
GeneralResult<Department> exists(String name, Long tenantId);
/**
*
*
* @param id
* @param requestContext
* @return
*/
GeneralResult<List<User>> listDeptManager(Long id, RequestContext requestContext);
}

View File

@ -0,0 +1,88 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Dictionary;
import com.bocloud.sms.model.DictionaryBean;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.Result;
import java.util.List;
import java.util.Map;
/**
*
*
* @author dmw
*/
public interface DictService {
/**
*
*
* @param dictionary
* @return
*/
GeneralResult<Dictionary> create(Dictionary dictionary);
/**
*
*
* @param id
* @return
*/
Result remove(Long id);
/**
*
*
* @param bean
* @return
*/
GeneralResult<Dictionary> modify(DictionaryBean bean);
/**
*
*
* @param pid
* @return
*/
GeneralResult<List<Dictionary>> list(Long pid);
/**
*
*
* @param id
* @return
*/
GeneralResult<List<Dictionary>> listChild(String value, Long id);
/**
*
*
* @param pid
* @return
*/
GeneralResult<List<Dictionary>> childTree(String pid);
/**
* osName
*
* @return
*/
List<String> getAllOsName();
/**
*
*
* @return
*/
Map<String, String> getAllDataCenter();
/**
* id
*
* @param id id
* @return {@link GeneralResult}<{@link Dictionary}>
*/
GeneralResult<Dictionary> detail(Long id);
}

View File

@ -0,0 +1,56 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Environment;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.RequestContext;
/**
* Service
*
* @author wangshuai
* @version 4.1.0-SNAPSHOT
* @since 2018/12/24
*/
public interface EnvironmentService {
GeneralResult<GridBean<Environment>> list(Pager pager, RequestContext context);
/**
*
*
* @param id
* @param context
* @return
*/
GeneralResult remove(Long id, RequestContext context);
/**
*
*
* @param id
* @return
*/
GeneralResult<Environment> detail(Long id);
/**
*
*
* @param environment
* @param context
* @return
*/
GeneralResult<Environment> create(Environment environment, RequestContext context);
/**
*
*
* @param bean
* @param context
* @return
*/
GeneralResult<Environment> modify(Environment bean, RequestContext context);
}

View File

@ -0,0 +1,23 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.GlobalManConfig;
import com.megatron.common.model.*;
/**
* @author wpj
* @since 2022/9/8
*/
public interface GlobalManConfigService {
GeneralResult<GridBean<GlobalManConfig>> list(Pager pager, RequestContext context);
Result create(GlobalManConfig globalManConfig, RequestContext context);
Result modify(GlobalManConfig globalManConfig, RequestContext context);
Result remove(Long id, RequestContext context);
Result allow(RequestContext context);
}

View File

@ -0,0 +1,24 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Icon;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.RequestContext;
import org.springframework.web.multipart.MultipartFile;
/**
* service
*
* @author
* @Version 1.0
* @since 202047
*/
public interface IconService {
GeneralResult<GridBean<Icon>> list(Pager pager, RequestContext context);
GeneralResult<Void> create(MultipartFile[] files, String category, RequestContext requestContext);
GeneralResult<Void> remove(Long id);
}

View File

@ -0,0 +1,53 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Label;
import com.megatron.common.model.*;
/**
* @author tyl
*/
public interface LabelService {
/**
*
*
* @param pager
* @param context
* @return
*/
GeneralResult<GridBean<Label>> list(Pager pager, RequestContext context);
/**
*
*
* @param id
* @return
*/
GeneralResult<Label> detail(Long id);
/**
*
*
* @param label
* @param context
* @return
*/
GeneralResult<Label> create(Label label, RequestContext context);
/**
*
*
* @param label
* @return
*/
GeneralResult<Label> modify(Label label);
/**
*
*
* @param id
* @return
*/
Result remove(Long id);
}

View File

@ -0,0 +1,22 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.LogArchiveRecord;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
/**
* @author tyl
*/
public interface LogArchiveRecordService {
/**
*
*
* @param pager
* @return
*/
GeneralResult<GridBean<LogArchiveRecord>> list(Pager pager);
}

View File

@ -0,0 +1,55 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.AccessLog;
import com.megatron.common.model.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
/**
*
*
* @author dmw
*/
public interface LogService {
/**
*
*
* @param pager
* @return
*/
GeneralResult<GridBean<AccessLog>> list(Pager pager);
/**
*
*
* @param accessLog
* @return
*/
Result create(AccessLog accessLog);
/**
*
*
* @param logs
* @return
*/
Result batch(List<AccessLog> logs);
/**
*
*
* @param startTime
* @param endTime
* @param deleted
* @param request
* @param response
* @param context
* @return
*/
GeneralResult<StringBuilder> archive(String startTime, String endTime, boolean deleted, RequestContext context, HttpServletRequest request,
HttpServletResponse response);
}

View File

@ -0,0 +1,23 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.model.PermissionBean;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import java.util.List;
/**
* @author tyl
* @time 2020/2/4 9:38
*/
public interface ManagerService {
/**
*
*
* @param requestContext
* @return
*/
GeneralResult<List<PermissionBean>> listPermissions(RequestContext requestContext);
}

View File

@ -0,0 +1,78 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Message;
import com.megatron.common.model.*;
import java.util.Map;
/**
*
*
* @author weiwei
* @version 1.0
* @since 2016.10.26
*/
public interface MessageService {
/**
*
*
* @param pager
* @param context
* @return
*/
GeneralResult<GridBean<Message>> list(Pager pager, RequestContext context);
/**
*
*
* @param context
* @param title
* @param content
* @return
*/
Result create(RequestContext context, String title, String content);
/**
*
*
* @param id ID
* @param userId ID
* @return
*/
Result remove(Long id, Long userId);
/**
*
*
* @param id ID
* @param context ID
* @return
*/
GeneralResult<Message> detail(Long id, RequestContext context);
/**
*
*
* @param context
* @return
*/
Result messageRead(RequestContext context);
/**
*
*
* @param context
* @return
*/
GeneralResult<Message> statistics(RequestContext context);
/**
*
*
* @param queueName
* @param message
*/
void sendQueueMessage(String queueName, Map<String, Object> message);
}

View File

@ -0,0 +1,69 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.NameRule;
import com.megatron.common.model.*;
/**
* service
*
* @author wangyu
* @version 3.0.0-SNAPSHOT
* @since 2018/7/2
*/
public interface NameRuleService {
/**
*
*
* @param pager
* @param context
* @return
*/
GeneralResult<GridBean<NameRule>> list(Pager pager, RequestContext context);
/**
*
*
* @param id
* @return
*/
GeneralResult<NameRule> detail(Long id);
/**
*
*
* @param nameRule
* @param context
* @return
*/
GeneralResult<NameRule> create(NameRule nameRule, RequestContext context);
/**
*
*
* @param nameRule
* @param context
* @return
*/
Result modify(NameRule nameRule, RequestContext context);
/**
*
*
* @param id
* @return
*/
Result remove(Long id);
/**
*
*
* @param id
* @param tenantId
* @param userId
* @param projectId
* @return
*/
GeneralResult<String> generate(Long id, Long tenantId, Long userId, Long projectId, RequestContext context);
}

View File

@ -0,0 +1,129 @@
package com.bocloud.sms.interfaces;
import com.alibaba.fastjson.JSONArray;
import com.bocloud.sms.entity.Permission;
import com.bocloud.sms.model.PermissionBean;
import com.bocloud.sms.model.PermissionIcon;
import com.bocloud.sms.model.PermissionModel;
import com.bocloud.sms.model.PermissionParentsBean;
import com.megatron.common.exception.InternalServerException;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import java.util.List;
/**
* @author tyl
* @time 2020/2/4 9:43
*/
public interface PermissionService {
/**
*
*
* @param params
* @param requestContext
* @return
* @throws InternalServerException
*/
Result create(PermissionModel params, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @param params
* @param requestContext
* @return
* @throws InternalServerException
*/
Result modify(Long id, PermissionModel params, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @param requestContext
* @return
* @throws InternalServerException
*/
Result remove(Long id, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @return
*/
GeneralResult<Permission> detail(Long id);
/**
*
*
* @param parentId
* @param category
* @param tenant
* @return
*/
GeneralResult<List<PermissionBean>> list(Long parentId, String category, Boolean tenant);
/**
*
*
* @param requestContext
* @return
*/
GeneralResult<List<PermissionParentsBean>> listParents(RequestContext requestContext);
/**
*
*
* @param requestContext
* @return
*/
GeneralResult<List<PermissionIcon>> listIcon(RequestContext requestContext);
/**
* id
*
* @param serviceId
* @return
*/
GeneralResult<Permission> getServicePermission(Long serviceId);
/**
* id
*
* @param services
* @return
*/
GeneralResult<List<Permission>> getServicePermissions(List<Long> services);
/**
* API
*
* @return
*/
GeneralResult<JSONArray> getApiList();
/**
* codeAPI
*
* @param codes
* @return
*/
GeneralResult<JSONArray> getApiList(List<String> codes);
GeneralResult<List<Permission>> listPermissionsByCondition(String condition);
/**
*
*
* @param permissionIdList id
* @param pluginsCode
* @param tenant
* @param requestContext
* @return
*/
Result bindingPlugins(List<Long> permissionIdList, String pluginsCode, Boolean tenant, RequestContext requestContext);
}

View File

@ -0,0 +1,120 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Dictionary;
import com.bocloud.sms.entity.Plugin;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.GridBean;
import com.megatron.common.model.Pager;
import com.megatron.common.model.Result;
import java.util.List;
import java.util.Map;
/**
*
*
* @author zhangyf
* @since 2022-05-19
*/
public interface PluginService {
/**
*
*
* @param pager
* @return plugin
*/
GeneralResult<GridBean<Plugin>> list(Pager pager);
/**
*
*
* @param service
* @return
*/
Map<String, List<Plugin>> listInstalled(String service);
/**
*
*
* @param service
* @return
*/
Map<String, List<Plugin>> listUpdate(String service);
/**
*
*
* @param service
* @return
*/
Map<String, List<Plugin>> listCanInstall(String service);
/**
*
*
* @param plugin
* @return /
*/
Result create(Plugin plugin);
/**
*
*
* @param id ID
* @param plugin
* @param hasPackage
* @return /
*/
Result modify(Long id, Plugin plugin, boolean hasPackage);
/**
*
*
* @param id
* @return
*/
Result remove(Long id);
/**
*
*
* @param idList
* @return /
*/
Result batchRemove(List<Long> idList);
/**
*
*
* @param id
* @return plugin
*/
Plugin detail(Long id);
/**
*
*
* @param pager
* @return to ims
*/
GeneralResult<List<Dictionary>> getVendorList(Pager pager);
/**
* license
*
* @param pager
* @return license
*/
List<Plugin> listLicense(Pager pager);
/**
*
*
* @param services
* @return
*/
List<Plugin> runningPlugins(String... services);
}

View File

@ -0,0 +1,21 @@
package com.bocloud.sms.interfaces;
import com.megatron.common.model.GeneralResult;
/**
* service
*
* @author lyy
* @version 2.0
* @time 20171227
*/
public interface PortalElementConfigService {
/**
*
*
* @param poolId
* @return
*/
GeneralResult list(Long poolId);
}

View File

@ -0,0 +1,20 @@
package com.bocloud.sms.interfaces;
import com.megatron.common.model.GeneralResult;
/**
* service
*
* @author lyy
* @version 2.0
* @time 20171227
*/
public interface PortalElementPoolService {
/**
*
*
* @return
*/
GeneralResult list(String module);
}

View File

@ -0,0 +1,48 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.PortalPanel;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import java.util.List;
/**
* service
*
* @author lyy
* @version 2.0
* @time 20171227
*/
public interface PortalPanelService {
/**
*
*
* @param context
* @return
*/
GeneralResult list(String module, RequestContext context);
/**
*
*
* @param portalPanels
* @param userId
* @param module
* @param tenantId
* @param projectId
* @return
*/
GeneralResult save(List<PortalPanel> portalPanels, Long userId, Long tenantId, Long projectId, String module);
/**
*
*
* @param module
* @param context
* @return
*/
GeneralResult reset(String module, RequestContext context);
}

View File

@ -0,0 +1,151 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.Business;
import com.bocloud.sms.entity.Project;
import com.bocloud.sms.model.ProjectModel;
import com.bocloud.sms.model.ProjectUserBean;
import com.megatron.common.model.*;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
/**
* @author tyl
* @time 2020/6/2 15:57
*/
public interface ProjectService {
/**
*
*
* @param pager
* @param requestContext
* @return
*/
GeneralResult<GridBean<Project>> list(Pager pager, RequestContext requestContext, Boolean tenantId);
/**
*
*
* @param condition
* @param requestContext
* @return
*/
GeneralResult condition(String condition, RequestContext requestContext);
/**
*
*
* @param params
* @param requestContext
* @return
*/
Result create(ProjectModel params, RequestContext requestContext);
/**
*
*
* @param id
* @param params
* @param requestContext
* @return
*/
Result modify(Long id, ProjectModel params, RequestContext requestContext);
/**
*
*
* @param id
* @param requestContext
* @return
*/
Result remove(Long id, RequestContext requestContext);
/**
*
*
* @param ids
* @param requestContext
* @return
*/
Result batchRemove(List<Long> ids, RequestContext requestContext);
/**
*
*
* @param id
* @return
*/
GeneralResult<Project> detail(Long id);
/**
*
*
* @param projectId
* @param projectUserBean
* @return
*/
Result configUser(Long projectId, ProjectUserBean projectUserBean);
/**
*
*
* @param params
* @param requestContext
* @return
*/
XSSFWorkbook export(List<Param> params, RequestContext requestContext);
/**
*
*
* @param id
* @param requestContext
* @return
*/
GeneralResult<Business> getBusinessDetail(Long id, RequestContext requestContext);
/**
*
*
* @param id
* @param userId
* @return
*/
Result configProjectManager(Long id, Long userId);
/**
*
*
* @param title
* @param requestContext
* @return
*/
XSSFWorkbook importTemp2(String title, RequestContext requestContext);
/**
*
*
* @param response
* @return
*/
Result importTemp(HttpServletResponse response);
/**
*
*
* @param multipartFile
* @param requestContext
* @return
*/
Result importData(MultipartFile multipartFile, RequestContext requestContext);
GeneralResult<List<Project>> queryByDepart(String departName);
GeneralResult<List<Project>> queryByDepartIds(Pager pager, List<Long> departIds);
GeneralResult<Project> getByProjectName(String departName);
}

View File

@ -0,0 +1,158 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.monitor.LabelParam;
import com.bocloud.sms.monitor.PrometheusResult;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* prometheus
*
* @author zhangyf
* @since 2018-12-27
*/
public interface PrometheusService {
/**
* query
*
* @param expr
* @return
*/
Double simpleQuery(String expr);
/**
* query
*
* @param expr
* @param time
* @return
*/
Double simpleQuery(String expr, String time);
/**
* query
*
* @param expr
* @param params
* @return
*/
Double simpleQuery(String expr, Map<String, String> params);
/**
* query
*
* @param expr
* @param params
* @return
*/
Double simpleQuery(String expr, List<LabelParam> params);
/**
* query
*
* @param expr
* @return
*/
List<PrometheusResult> query(String expr);
/**
* query
*
* @param expr
* @param params
* @return
*/
List<PrometheusResult> query(String expr, Map<String, String> params);
/**
* query
*
* @param expr
* @param params
* @return
*/
List<PrometheusResult> query(String expr, List<LabelParam> params);
/**
* query
*
* @param expr
* @param time
* @return
*/
List<PrometheusResult> query(String expr, String time);
/**
* query
*
* @param expr
* @param time
* @param params
* @return
*/
List<PrometheusResult> query(String expr, Map<String, String> params, String time);
/**
* query
*
* @param expr
* @param time
* @param params
* @return
*/
List<PrometheusResult> query(String expr, List<LabelParam> params, String time);
/**
* query_range
*
* @param start
* @param end
* @param step
* @param expr
* @return
*/
List<PrometheusResult> queryRange(String expr, String start, String end, String step);
/**
* query_range
*
* @param expr
* @param params
* @param start
* @param end
* @param step
* @return
*/
List<PrometheusResult> queryRange(String expr, Map<String, String> params, String start, String end, String step);
/**
* query_range
*
* @param expr
* @param params
* @param start
* @param end
* @param step
* @return
*/
List<PrometheusResult> queryRange(String expr, List<LabelParam> params, String start, String end, String step);
/**
*
*
* @param expr
* @param filter
* @return Label
*/
Set<String> filter(String expr, String filter);
/**
* prometheus
*/
void reload();
}

View File

@ -0,0 +1,30 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.model.LineChartResult;
import com.megatron.common.model.GeneralResult;
import java.util.List;
/**
*
*
* @author zhangyf
* @since 2019-01-08
*/
public interface QueryService {
/**
*
*
* @param exprs
* @param names
* @param start
* @param end
* @param step
* @param unit
* @return
*/
LineChartResult chart(List<String> exprs, List<String> names, String start, String end, String step, String unit);
}

View File

@ -0,0 +1,135 @@
package com.bocloud.sms.interfaces;
import com.alibaba.fastjson.JSONArray;
import com.bocloud.sms.entity.Role;
import com.bocloud.sms.entity.User;
import com.bocloud.sms.model.ApiInfo;
import com.bocloud.sms.model.CloudServiceBean;
import com.bocloud.sms.model.RoleModel;
import com.megatron.common.exception.InternalServerException;
import com.megatron.common.model.*;
import java.util.List;
/**
* Service
*
* @author tyl
*/
public interface RoleService {
/**
*
*
* @param roleModel
* @param requestContext
* @return
* @throws InternalServerException
*/
Result create(RoleModel roleModel, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @param roleModel
* @param requestContext
* @return
* @throws InternalServerException
*/
Result modify(Long id, RoleModel roleModel, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @param requestContext
* @return
* @throws InternalServerException
*/
Result remove(Long id, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param id
* @return
*/
GeneralResult<Role> detail(Long id);
/**
*
*
* @param id
* @param ids
* @param requestContext
* @return
* @throws InternalServerException
*/
Result accredit(Long id, List<Long> ids, RequestContext requestContext) throws InternalServerException;
/**
*
*
* @param pager
* @param requestContext
* @return
*/
GeneralResult<GridBean<Role>> list(Pager pager, RequestContext requestContext);
/**
*
*
* @param id
* @param menu
* @param tenant
* @param requestContext
* @return
*/
GeneralResult<List<CloudServiceBean>> listPermissions(Long id, boolean menu, boolean tenant, RequestContext requestContext);
/**
*
*
* @param name
* @param tenantId
* @return
*/
Result exists(String name, Long tenantId);
/**
*
*
* @param requestContext
* @return
*/
GeneralResult<List<Long>> roleIds(RequestContext requestContext);
/**
* API
*
* @param id
* @param module
* @param apiList
* @return
*/
Result accreditRole(Long id, List<ApiInfo> apiList);
/**
* API
*
* @param id
* @param tags
* @return
*/
GeneralResult<JSONArray> getApiPermission(Long id, String tags);
/**
*
*
* @param pager
* @param id
* @return
*/
GeneralResult<GridBean<User>> listUsersByRoleId(Pager pager, Long id);
}

View File

@ -0,0 +1,10 @@
package com.bocloud.sms.interfaces;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.servlet.view.RedirectView;
public interface SingleLoginService {
public RedirectView singleLogin(String token, HttpServletRequest request) throws Exception;
}

View File

@ -0,0 +1,13 @@
package com.bocloud.sms.interfaces;
import com.megatron.common.model.Result;
/**
* @ClassName: SysDateViewService
* @Description:
* @Author lxy
* @Date 2021/9/29 10:10
*/
public interface SysDateViewService {
Result systemCount();
}

View File

@ -0,0 +1,52 @@
package com.bocloud.sms.interfaces;
import com.alibaba.fastjson.JSONArray;
import com.bocloud.sms.entity.SystemConfig;
import com.bocloud.sms.model.ConfigModel;
import com.megatron.common.exception.InternalServerException;
import com.megatron.common.model.GeneralResult;
import com.megatron.common.model.RequestContext;
import com.megatron.common.model.Result;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* @author lyy
* @Version 1.0
* @since 2017818
*/
public interface SystemConfigService {
/**
*
*
* @param systemConfig
* @return
*/
Result modify(SystemConfig systemConfig) throws InternalServerException;
/**
*
*
* @param list
* @param requestContext
* @return
*/
Result batchUpdate(List<ConfigModel> list, Map<String, MultipartFile> fileMap, RequestContext requestContext);
Result syncLdap();
GeneralResult<Map<String, String>> listConfigs(String category, List<String> codes);
GeneralResult<JSONArray> listCategoryTree(String category);
/**
*
*
* @param category
* @return
*/
Result configTest(String category);
}

View File

@ -0,0 +1,9 @@
package com.bocloud.sms.interfaces;
import com.megatron.common.model.GeneralResult;
public interface SystemHomeService {
GeneralResult<?> getToken();
}

View File

@ -0,0 +1,41 @@
package com.bocloud.sms.interfaces;
import com.bocloud.sms.entity.SystemNotice;
import com.megatron.common.model.*;
/**
*
*/
public interface SystemNoticeService {
/**
*
*/
Result create(SystemNotice entity, RequestContext user);
/**
*
*/
Result remove(Long id, RequestContext user);
/**
*
*/
Result modify(SystemNotice params, RequestContext user);
/**
*
*/
GeneralResult<GridBean<SystemNotice>> list(Pager pager, RequestContext requestContext);
/**
*
*/
GeneralResult<SystemNotice> detail(Long id);
/**
*
*/
GeneralResult<Void> sendMsg(Long id);
}

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