upload UI source code
This commit is contained in:
103
UI source code/dns-dev-2.0/dns-system/pom.xml
Normal file
103
UI source code/dns-dev-2.0/dns-system/pom.xml
Normal file
@@ -0,0 +1,103 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>dns</artifactId>
|
||||
<groupId>com.example</groupId>
|
||||
<version>2.6</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>dns-system</artifactId>
|
||||
<name>dns-system</name>
|
||||
|
||||
<properties>
|
||||
<jjwt.version>0.11.1</jjwt.version>
|
||||
<!-- oshi监控需要指定jna版本, 问题详见 https://github.com/oshi/oshi/issues/1040 -->
|
||||
<jna.version>5.8.0</jna.version>
|
||||
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- tools 模块包含了 common 和 logging 模块 -->
|
||||
<dependency>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>dns-common</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>dns-logging</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring boot websocket -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- jwt -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>${jjwt.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- quartz -->
|
||||
<dependency>
|
||||
<groupId>org.quartz-scheduler</groupId>
|
||||
<artifactId>quartz</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- linux的管理 -->
|
||||
<dependency>
|
||||
<groupId>ch.ethz.ganymed</groupId>
|
||||
<artifactId>ganymed-ssh2</artifactId>
|
||||
<version>build210</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jcraft</groupId>
|
||||
<artifactId>jsch</artifactId>
|
||||
<version>0.1.55</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 获取系统信息 -->
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>5.7.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<!-- 打包 -->
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<!-- 跳过单元测试 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<skipTests>true</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example;
|
||||
|
||||
import com.example.utils.SpringContextHolder;
|
||||
import io.swagger.annotations.Api;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.ApplicationPidFileWriter;
|
||||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 开启审计功能 -> @EnableJpaAuditing
|
||||
*
|
||||
* 2018/11/15 9:20:19
|
||||
*/
|
||||
@EnableAsync
|
||||
@RestController
|
||||
@Api(hidden = true)
|
||||
@SpringBootApplication
|
||||
@EnableTransactionManagement
|
||||
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
|
||||
public class AppRun {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication springApplication = new SpringApplication(AppRun.class);
|
||||
// 监控应用的PID,启动时可指定PID路径:--spring.pid.file=/home/dns/app.pid
|
||||
// 或者在 application.yml 添加文件路径,方便 kill,kill `cat /home/dns/app.pid`
|
||||
springApplication.addListeners(new ApplicationPidFileWriter());
|
||||
springApplication.run(args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SpringContextHolder springContextHolder() {
|
||||
return new SpringContextHolder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletWebServerFactory webServerFactory() {
|
||||
TomcatServletWebServerFactory fa = new TomcatServletWebServerFactory();
|
||||
fa.addConnectorCustomizers(connector -> connector.setProperty("relaxedQueryChars", "[]{}"));
|
||||
return fa;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.config;
|
||||
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.fastjson.support.config.FastJsonConfig;
|
||||
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* WebMvcConfigurer
|
||||
*
|
||||
*
|
||||
* 2018-11-30
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class ConfigurerAdapter implements WebMvcConfigurer {
|
||||
|
||||
/** 文件配置 */
|
||||
private final FileProperties properties;
|
||||
|
||||
public ConfigurerAdapter(FileProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
config.setAllowCredentials(true);
|
||||
config.addAllowedOrigin("*");
|
||||
config.addAllowedHeader("*");
|
||||
config.addAllowedMethod("*");
|
||||
source.registerCorsConfiguration("/**", config);
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
FileProperties.ElPath path = properties.getPath();
|
||||
String avatarUtl = "file:" + path.getAvatar().replace("\\","/");
|
||||
String pathUtl = "file:" + path.getPath().replace("\\","/");
|
||||
registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0);
|
||||
registry.addResourceHandler("/file/**").addResourceLocations(pathUtl).setCachePeriod(0);
|
||||
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/").setCachePeriod(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
// 使用 fastjson 序列化,会导致 @JsonIgnore 失效,可以使用 @JSONField(serialize = false) 替换
|
||||
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
|
||||
List<MediaType> supportMediaTypeList = new ArrayList<>();
|
||||
supportMediaTypeList.add(MediaType.APPLICATION_JSON);
|
||||
FastJsonConfig config = new FastJsonConfig();
|
||||
config.setDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
|
||||
converter.setFastJsonConfig(config);
|
||||
converter.setSupportedMediaTypes(supportMediaTypeList);
|
||||
converter.setDefaultCharset(StandardCharsets.UTF_8);
|
||||
converters.add(converter);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
package com.example.config;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
|
||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
|
||||
import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
|
||||
import com.baomidou.mybatisplus.core.MybatisConfiguration;
|
||||
import com.baomidou.mybatisplus.core.config.GlobalConfig;
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
|
||||
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
|
||||
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.mapping.DatabaseIdProvider;
|
||||
import org.apache.ibatis.plugin.Interceptor;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.mybatis.spring.mapper.ClassPathMapperScanner;
|
||||
import org.mybatis.spring.mapper.MapperFactoryBean;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* mybatis-plus 初始化配置
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(MybatisPlusProperties.class)
|
||||
public class MybatisPlusConfig {
|
||||
|
||||
public MybatisPlusConfig(MybatisPlusProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider,
|
||||
ResourceLoader resourceLoader, ObjectProvider<DatabaseIdProvider> databaseIdProvider,
|
||||
ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider,
|
||||
ApplicationContext applicationContext) {
|
||||
this.properties = properties;
|
||||
this.interceptors = interceptorsProvider.getIfAvailable();
|
||||
this.resourceLoader = resourceLoader;
|
||||
this.databaseIdProvider = databaseIdProvider.getIfAvailable();
|
||||
this.configurationCustomizers = configurationCustomizersProvider.getIfAvailable();
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
private static final Log logger = Log.get();
|
||||
|
||||
private final MybatisPlusProperties properties;
|
||||
|
||||
private final Interceptor[] interceptors;
|
||||
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
private final DatabaseIdProvider databaseIdProvider;
|
||||
|
||||
private final List<ConfigurationCustomizer> configurationCustomizers;
|
||||
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
@PostConstruct
|
||||
public void checkConfigFileExists() {
|
||||
if (this.properties.isCheckConfigLocation() && StringUtils.hasText(this.properties.getConfigLocation())) {
|
||||
Resource resource = this.resourceLoader.getResource(this.properties.getConfigLocation());
|
||||
Assert.state(resource.exists(), "Cannot find config location: " + resource
|
||||
+ " (please add config file or check your Mybatis configuration)");
|
||||
}
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
|
||||
MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
|
||||
factory.setDataSource(dataSource);
|
||||
factory.setVfs(SpringBootVFS.class);
|
||||
if (StringUtils.hasText(this.properties.getConfigLocation())) {
|
||||
factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
|
||||
}
|
||||
applyConfiguration(factory);
|
||||
if (this.properties.getConfigurationProperties() != null) {
|
||||
factory.setConfigurationProperties(this.properties.getConfigurationProperties());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(this.interceptors)) {
|
||||
factory.setPlugins(this.interceptors);
|
||||
}
|
||||
if (this.databaseIdProvider != null) {
|
||||
factory.setDatabaseIdProvider(this.databaseIdProvider);
|
||||
}
|
||||
if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
|
||||
factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
|
||||
}
|
||||
// TODO 自定义枚举包
|
||||
if (StringUtils.hasLength(this.properties.getTypeEnumsPackage())) {
|
||||
factory.setTypeEnumsPackage(this.properties.getTypeEnumsPackage());
|
||||
}
|
||||
if (this.properties.getTypeAliasesSuperType() != null) {
|
||||
factory.setTypeAliasesSuperType(this.properties.getTypeAliasesSuperType());
|
||||
}
|
||||
if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
|
||||
factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
|
||||
factory.setMapperLocations(this.properties.resolveMapperLocations());
|
||||
}
|
||||
// TODO 此处必为非 NULL
|
||||
GlobalConfig globalConfig = this.properties.getGlobalConfig();
|
||||
// 注入填充器
|
||||
if (this.applicationContext.getBeanNamesForType(MetaObjectHandler.class, false, false).length > 0) {
|
||||
MetaObjectHandler metaObjectHandler = this.applicationContext.getBean(MetaObjectHandler.class);
|
||||
globalConfig.setMetaObjectHandler(metaObjectHandler);
|
||||
}
|
||||
// 注入主键生成器
|
||||
if (this.applicationContext.getBeanNamesForType(IKeyGenerator.class, false, false).length > 0) {
|
||||
IKeyGenerator keyGenerator = this.applicationContext.getBean(IKeyGenerator.class);
|
||||
globalConfig.getDbConfig().setKeyGenerator(keyGenerator);
|
||||
}
|
||||
// 注入sql注入器
|
||||
if (this.applicationContext.getBeanNamesForType(ISqlInjector.class, false, false).length > 0) {
|
||||
ISqlInjector iSqlInjector = this.applicationContext.getBean(ISqlInjector.class);
|
||||
globalConfig.setSqlInjector(iSqlInjector);
|
||||
}
|
||||
factory.setGlobalConfig(globalConfig);
|
||||
return factory.getObject();
|
||||
}
|
||||
|
||||
private void applyConfiguration(MybatisSqlSessionFactoryBean factory) {
|
||||
MybatisConfiguration configuration = this.properties.getConfiguration();
|
||||
if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
|
||||
configuration = new MybatisConfiguration();
|
||||
}
|
||||
if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
|
||||
for (ConfigurationCustomizer customizer : this.configurationCustomizers) {
|
||||
customizer.customize(configuration);
|
||||
}
|
||||
}
|
||||
factory.setConfiguration(configuration);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
|
||||
ExecutorType executorType = this.properties.getExecutorType();
|
||||
if (executorType != null) {
|
||||
return new SqlSessionTemplate(sqlSessionFactory, executorType);
|
||||
} else {
|
||||
return new SqlSessionTemplate(sqlSessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This will just scan the same base package as Spring Boot does. If you want
|
||||
* more power, you can explicitly use
|
||||
* {@link org.mybatis.spring.annotation.MapperScan} but this will get typed
|
||||
* mappers working correctly, out-of-the-box, similar to using Spring Data JPA
|
||||
* repositories.
|
||||
*/
|
||||
public static class AutoConfiguredMapperScannerRegistrar
|
||||
implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
private ResourceLoader resourceLoader;
|
||||
|
||||
@Override
|
||||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
|
||||
BeanDefinitionRegistry registry) {
|
||||
|
||||
logger.debug("Searching for mappers annotated with @Mapper");
|
||||
|
||||
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
|
||||
|
||||
try {
|
||||
if (this.resourceLoader != null) {
|
||||
scanner.setResourceLoader(this.resourceLoader);
|
||||
}
|
||||
|
||||
List<String> packages = AutoConfigurationPackages.get(this.beanFactory);
|
||||
if (logger.isDebugEnabled()) {
|
||||
packages.forEach(pkg -> logger.debug("Using auto-configuration base package '{}'", pkg));
|
||||
}
|
||||
|
||||
scanner.setAnnotationClass(Mapper.class);
|
||||
scanner.registerFilters();
|
||||
scanner.doScan(StringUtils.toStringArray(packages));
|
||||
} catch (IllegalStateException ex) {
|
||||
logger.debug("Could not determine auto-configuration package, automatic mapper scanning disabled.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourceLoader(ResourceLoader resourceLoader) {
|
||||
this.resourceLoader = resourceLoader;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link org.mybatis.spring.annotation.MapperScan} ultimately ends up creating
|
||||
* instances of {@link MapperFactoryBean}. If
|
||||
* {@link org.mybatis.spring.annotation.MapperScan} is used then this
|
||||
* auto-configuration is not needed. If it is _not_ used, however, then this
|
||||
* will bring in a bean registrar and automatically register components based on
|
||||
* the same component-scanning path as Spring Boot itself.
|
||||
*/
|
||||
@Configuration
|
||||
@Import({ AutoConfiguredMapperScannerRegistrar.class })
|
||||
@ConditionalOnMissingBean(MapperFactoryBean.class)
|
||||
public static class MapperScannerRegistrarNotFoundConfiguration {
|
||||
|
||||
@PostConstruct
|
||||
public void afterPropertiesSet() {
|
||||
logger.debug("No {} found.", MapperFactoryBean.class.getName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.example.config;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
|
||||
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
|
||||
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
|
||||
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
* mybatis-plus 插件配置
|
||||
*/
|
||||
@Configuration
|
||||
public class MybatisPlusPluginsConfig {
|
||||
|
||||
private static final Log logger = Log.get();
|
||||
|
||||
/**
|
||||
* 分页插件
|
||||
*/
|
||||
@Bean
|
||||
public PaginationInterceptor paginationInterceptor() {
|
||||
return new PaginationInterceptor();
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public ISqlInjector sqlInjector() {
|
||||
return new LogicSqlInjector();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
/**
|
||||
* @author ZhangHouYing
|
||||
* 2019-08-24 15:44
|
||||
*/
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.config.thread;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 异步任务线程池装配类
|
||||
* @author https://juejin.im/entry/5abb8f6951882555677e9da2
|
||||
* 2019年10月31日15:06:18
|
||||
*/
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class AsyncTaskExecutePool implements AsyncConfigurer {
|
||||
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
//核心线程池大小
|
||||
executor.setCorePoolSize(AsyncTaskProperties.corePoolSize);
|
||||
//最大线程数
|
||||
executor.setMaxPoolSize(AsyncTaskProperties.maxPoolSize);
|
||||
//队列容量
|
||||
executor.setQueueCapacity(AsyncTaskProperties.queueCapacity);
|
||||
//活跃时间
|
||||
executor.setKeepAliveSeconds(AsyncTaskProperties.keepAliveSeconds);
|
||||
//线程名字前缀
|
||||
executor.setThreadNamePrefix("el-async-");
|
||||
// setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务
|
||||
// CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return (throwable, method, objects) -> {
|
||||
log.error("===="+throwable.getMessage()+"====", throwable);
|
||||
log.error("exception method:"+method.getName());
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.config.thread;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 线程池配置属性类
|
||||
* @author https://juejin.im/entry/5abb8f6951882555677e9da2
|
||||
* 2019年10月31日14:58:18
|
||||
*/
|
||||
@Data
|
||||
@Component
|
||||
public class AsyncTaskProperties {
|
||||
|
||||
public static int corePoolSize;
|
||||
|
||||
public static int maxPoolSize;
|
||||
|
||||
public static int keepAliveSeconds;
|
||||
|
||||
public static int queueCapacity;
|
||||
|
||||
@Value("${task.pool.core-pool-size}")
|
||||
public void setCorePoolSize(int corePoolSize) {
|
||||
AsyncTaskProperties.corePoolSize = corePoolSize;
|
||||
}
|
||||
|
||||
@Value("${task.pool.max-pool-size}")
|
||||
public void setMaxPoolSize(int maxPoolSize) {
|
||||
AsyncTaskProperties.maxPoolSize = maxPoolSize;
|
||||
}
|
||||
|
||||
@Value("${task.pool.keep-alive-seconds}")
|
||||
public void setKeepAliveSeconds(int keepAliveSeconds) {
|
||||
AsyncTaskProperties.keepAliveSeconds = keepAliveSeconds;
|
||||
}
|
||||
|
||||
@Value("${task.pool.queue-capacity}")
|
||||
public void setQueueCapacity(int queueCapacity) {
|
||||
AsyncTaskProperties.queueCapacity = queueCapacity;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.config.thread;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 自定义线程名称
|
||||
*
|
||||
* 2019年10月31日17:49:55
|
||||
*/
|
||||
@Component
|
||||
public class TheadFactoryName implements ThreadFactory {
|
||||
|
||||
private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
|
||||
private final ThreadGroup group;
|
||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
private final String namePrefix;
|
||||
|
||||
public TheadFactoryName() {
|
||||
this("el-pool");
|
||||
}
|
||||
|
||||
private TheadFactoryName(String name){
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
group = (s != null) ? s.getThreadGroup() :
|
||||
Thread.currentThread().getThreadGroup();
|
||||
//此时namePrefix就是 name + 第几个用这个工厂创建线程池的
|
||||
this.namePrefix = name +
|
||||
POOL_NUMBER.getAndIncrement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
//此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程
|
||||
Thread t = new Thread(group, r,
|
||||
namePrefix + "-thread-"+threadNumber.getAndIncrement(),
|
||||
0);
|
||||
if (t.isDaemon()) {
|
||||
t.setDaemon(false);
|
||||
}
|
||||
if (t.getPriority() != Thread.NORM_PRIORITY) {
|
||||
t.setPriority(Thread.NORM_PRIORITY);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.config.thread;
|
||||
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 用于获取自定义线程池
|
||||
*
|
||||
* 2019年10月31日18:16:47
|
||||
*/
|
||||
public class ThreadPoolExecutorUtil {
|
||||
|
||||
public static ThreadPoolExecutor getPoll(){
|
||||
return new ThreadPoolExecutor(
|
||||
AsyncTaskProperties.corePoolSize,
|
||||
AsyncTaskProperties.maxPoolSize,
|
||||
AsyncTaskProperties.keepAliveSeconds,
|
||||
TimeUnit.SECONDS,
|
||||
new ArrayBlockingQueue<>(AsyncTaskProperties.queueCapacity),
|
||||
new TheadFactoryName()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.example.modules.dns.controller;
|
||||
|
||||
import com.example.modules.dns.service.DnsService;
|
||||
import com.example.utils.page.PageUtils;
|
||||
import com.example.utils.page.R;
|
||||
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;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/dns")
|
||||
public class DnsController {
|
||||
@Autowired
|
||||
private DnsService dnsService;
|
||||
|
||||
@GetMapping
|
||||
public R queryPage(@RequestParam Map<String, Object> params) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
PageUtils page =dnsService.queryPage(params);
|
||||
long endTime = System.currentTimeMillis();
|
||||
DecimalFormat df = new DecimalFormat("0.000");
|
||||
String totalTime = df.format((float) (endTime - startTime) / 1000);
|
||||
page.setTotalTime(Double.parseDouble(totalTime));
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
|
||||
//区域数据统计
|
||||
@GetMapping("/dataCount")
|
||||
public R dataCount(@RequestParam Map<String, Object> params) {
|
||||
return R.ok(dnsService.dataCount(params));
|
||||
}
|
||||
|
||||
//区域数据统计
|
||||
@GetMapping("/mapData")
|
||||
public R mapData() {
|
||||
return R.ok(dnsService.mapData());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@Data
|
||||
@TableName("dns_type")
|
||||
public class DnsType implements Serializable {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String ip;
|
||||
|
||||
private String type;
|
||||
|
||||
private int epoch;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@TableName("doh_attribute")
|
||||
public class DohAttribute implements Serializable {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
private String ip;
|
||||
private Integer port;
|
||||
private String host;
|
||||
private String path;
|
||||
private String method;
|
||||
private Integer connectType;
|
||||
private Integer statusCode;
|
||||
private String repHeader;
|
||||
private String repBody;
|
||||
private Date timestamp;
|
||||
|
||||
private String component;
|
||||
|
||||
private int rounds;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<String> pathList;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<String> componentList;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<IpCert> ipCert;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<IpInformation> ipInformation;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<List<Vulnerability>> vulnerability;
|
||||
@TableField(exist = false)
|
||||
private List<String> tags;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
@Data
|
||||
@TableName("forward_dns")
|
||||
public class ForwardDns implements Serializable {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String forwarder;
|
||||
|
||||
private String upstream;
|
||||
|
||||
private int epoch;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.example.modules.system.domain.Dept;
|
||||
import com.example.modules.system.domain.Job;
|
||||
import com.example.modules.system.domain.Role;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 2018-11-22
|
||||
*/
|
||||
@Data
|
||||
@TableName("ip_cert")
|
||||
public class IpCert implements Serializable {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String ip;
|
||||
|
||||
private String port;
|
||||
|
||||
private String certificate;
|
||||
|
||||
private String ca;
|
||||
|
||||
private Date timestamp;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-11-22
|
||||
*/
|
||||
@Data
|
||||
@TableName("ip_information")
|
||||
public class IpInformation implements Serializable {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String ip;
|
||||
|
||||
private String country;
|
||||
|
||||
private String province;
|
||||
|
||||
private String city;
|
||||
private String district;
|
||||
private String provider;
|
||||
private String isp;
|
||||
private Integer asnumber;
|
||||
private Date timestamp;
|
||||
private String zipcode;
|
||||
private String timezone;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<IpCert> ipCert;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<NonstandardDns> nonstandardDns;
|
||||
|
||||
|
||||
@TableField(exist = false)
|
||||
private DnsType dnsType;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<DohAttribute> dohAttribute;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<ForwardDns> forwardDns;
|
||||
|
||||
@TableField(exist = false)
|
||||
private ScanResult scanResult;
|
||||
|
||||
@TableField(exist = false)
|
||||
private Integer dnsTypeValue;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 直接响DNS表
|
||||
*/
|
||||
@Data
|
||||
@TableName("nonstandard_dns")
|
||||
public class NonstandardDns implements Serializable {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String ip;
|
||||
|
||||
private String record;
|
||||
|
||||
private int epoch;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class Result implements Serializable {
|
||||
|
||||
private Long id;
|
||||
private String ip;
|
||||
|
||||
private String protocolType;
|
||||
private String ipType;
|
||||
|
||||
private Integer port;
|
||||
private String host;
|
||||
private String path;
|
||||
private String method;
|
||||
private Integer connectType;
|
||||
private Integer statusCode;
|
||||
private String repHeader;
|
||||
private String repBody;
|
||||
private Date timestamp;
|
||||
private String component;
|
||||
|
||||
|
||||
private Integer flags;
|
||||
private Integer opcode;
|
||||
private Integer qr;
|
||||
//权威标志位
|
||||
private Integer aa;
|
||||
//递归标志位
|
||||
private Integer ra;
|
||||
private Integer rcode;
|
||||
private String queryName;
|
||||
private String queryResponse;
|
||||
|
||||
//(预留)ipv4,ipv6,dnssec,tcp,udp等
|
||||
private Integer scanType;
|
||||
|
||||
private Date time;
|
||||
|
||||
private Integer epoch;
|
||||
|
||||
private Integer rounds;
|
||||
|
||||
|
||||
private Integer dnsType;
|
||||
|
||||
private String uuid;
|
||||
|
||||
private List<String> pathList;
|
||||
|
||||
private List<String> componentList;
|
||||
|
||||
private List<IpCert> ipCert;
|
||||
|
||||
private List<Vulnerability> vulnerability;
|
||||
|
||||
private List<String> tags;
|
||||
|
||||
private IpInformation ipInformation;
|
||||
|
||||
private List<? extends Object> banner;
|
||||
|
||||
private List<? extends Object> httpContent;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 2018-11-22
|
||||
*/
|
||||
@Data
|
||||
@TableName("scan_result")
|
||||
public class ScanResult implements Serializable {
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String ip;
|
||||
|
||||
private Integer flags;
|
||||
|
||||
private Integer opcode;
|
||||
|
||||
private Integer qr;
|
||||
//权威标志位
|
||||
private Integer aa;
|
||||
//递归标志位
|
||||
private Integer ra;
|
||||
|
||||
private Integer rcode;
|
||||
|
||||
private String queryName;
|
||||
|
||||
private String queryResponse;
|
||||
|
||||
private String component;
|
||||
|
||||
private int epoch;
|
||||
|
||||
private List<String> componentList;
|
||||
//(预留)ipv4,ipv6,dnssec,tcp,udp等
|
||||
private Integer scanType;
|
||||
|
||||
private Date time;
|
||||
@TableField(exist = false)
|
||||
private IpInformation IpInformation;
|
||||
@TableField(exist = false)
|
||||
private List<IpInformation> forwarderBanner;
|
||||
@TableField(exist = false)
|
||||
private Integer dnsType;
|
||||
@TableField(exist = false)
|
||||
private List<NonstandardDns> nonstandardBanner;
|
||||
|
||||
@TableField(exist = false)
|
||||
private List<String> tags;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.example.modules.dns.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName("vulnerability")
|
||||
public class Vulnerability implements Serializable {
|
||||
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String component;
|
||||
|
||||
private String vulnerability;
|
||||
|
||||
private Date timestamp;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.example.modules.dns.domain.Result;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface DnsDo53Dao extends BaseMapper<ScanResult> {
|
||||
|
||||
List<Result> queryDo53Page(IPage page, @Param("params") Map<String, Object> params);
|
||||
|
||||
int do53IpCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> do53ServiceCategoryCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> do53ProvinceCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> do53ProviderCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> do53ComponentCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> do53VulnerabilityCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> do53CountryCount();
|
||||
|
||||
List<Map<String, Object>> do53CountryMapCount();
|
||||
|
||||
|
||||
List<Map<String, Object>> do53WorldMapCount();
|
||||
|
||||
List<Map<String, Object>> do53ChinaMapCount();
|
||||
|
||||
int pageCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Result> queryOpenRdns(@Param("params")Map<String, Object> params);
|
||||
|
||||
int getCountByDnsType(@Param("dnsType")Integer dnsType,@Param("params") Map<String, Object> params);
|
||||
|
||||
int getIndependentIpNum(@Param("dnsType")Integer dnsType, @Param("params")Map<String, Object> params);
|
||||
|
||||
List<Result> selectScanResultByUnion(IPage page, @Param("params") Map<String, Object> params);
|
||||
|
||||
Integer selectScanResultCountByUnion(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> getDohAndDo53SrvCategoryCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 根据dnsType和其他参数统计ip省份分布
|
||||
* @param dnsType
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> getDo53ProvinceCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 根据dnsType和其他参数统计ip运营商分布
|
||||
* @param dnsType
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> getDo53ProviderCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> getDo53ComponentCountByDnsType(@Param("dnsType") Integer dnsType, Map<String, Object> params);
|
||||
|
||||
Integer getDo53SrvCategoryCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> getDo53VulnerabCountByDnsType(@Param("dnsType") Integer dnsType, @Param("params") Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.example.modules.dns.domain.DohAttribute;
|
||||
import com.example.modules.dns.domain.IpInformation;
|
||||
import com.example.modules.dns.domain.Result;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface DnsDohDao extends BaseMapper<DohAttribute> {
|
||||
|
||||
List<Result> queryDohPage(IPage page, @Param("params") Map<String, Object> params);
|
||||
|
||||
//省份数据统计
|
||||
List<Map<String, Object>> dohProvinceCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
int dohIpCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohPortCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohAndDo53ProvinceCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohProviderCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohAndDo53ProviderCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohComponentCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohAndDo53ComponentCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
Map<String, Object> dohServiceCategoryCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
int dohResultTotalCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohVulnerabilityCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohAndDo53VulnerabilityCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> dohCountryCount();
|
||||
|
||||
List<Map<String, Object>> dohChinaMapCount();
|
||||
|
||||
List<Result> getDohRepBody(String ip, Integer port, String host, Integer rounds);
|
||||
|
||||
List<Result> selectDohInfoByUnion(@Param("params") Map<String, Object> params);
|
||||
|
||||
Integer selectDohCountByUnion(@Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 查询 doh 和 do53 交集下的port ip数量
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> countDohPortUnion(@Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 统计 doh和do53公共ip的省份分布
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> getDohAndDo53ProvinceCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 统计 doh和do53公共ip的运营商分布
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> getDohAndDo53ProviderCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 统计 doh和do53公共ip的组件分布
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
List<Map<String, Object>> getDohAndDo53ComponentCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 统计 doh 和 do53公共ip 服务类别统计
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
Map<String, Object> getDohServiceCategoryCount(@Param("params") Map<String, Object> params);
|
||||
|
||||
List<Map<String, Object>> getDohAndDo53VulnerabilityCount(@Param("params") Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.example.modules.dns.domain.DnsType;
|
||||
import com.example.modules.dns.domain.DohAttribute;
|
||||
import com.example.modules.dns.domain.IpCert;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface DnsTypeDao extends BaseMapper<DnsType> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.example.modules.dns.domain.ForwardDns;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface ForwardDnsDao extends BaseMapper<ForwardDns> {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.example.modules.dns.domain.DohAttribute;
|
||||
import com.example.modules.dns.domain.IpCert;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface IpCertDao extends BaseMapper<IpCert> {
|
||||
|
||||
List<DohAttribute> queryDohPage(IPage page, @Param("params") Map<String, Object> params);
|
||||
|
||||
// 国家数据统计
|
||||
List<Map<String, Object>> countryCount();
|
||||
|
||||
//省份数据统计
|
||||
List<Map<String, Object>> provinceCount();
|
||||
|
||||
// 城市数据统计
|
||||
List<Map<String, Object>> cityCount();
|
||||
|
||||
|
||||
List<ScanResult> queryDo53Page(IPage page, @Param("params") Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.example.modules.dns.domain.IpInformation;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface IpInformationDao extends BaseMapper<IpInformation> {
|
||||
|
||||
|
||||
List<IpInformation> queryIpPage(IPage page, @Param("params") Map<String, Object> params);
|
||||
|
||||
/**
|
||||
* 根据 forward_dns中的 forwarder查询ip信息
|
||||
* @param ip
|
||||
* @return
|
||||
*/
|
||||
List<IpInformation> getIpInfoByFwd(@Param("ip")String ip,@Param("epoch")Integer epoch);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.example.modules.dns.domain.ForwardDns;
|
||||
import com.example.modules.dns.domain.NonstandardDns;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface NonstandardDnsDao extends BaseMapper<NonstandardDns> {
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.example.modules.dns.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.example.modules.dns.domain.DohAttribute;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
import com.example.modules.dns.domain.Vulnerability;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
@Repository
|
||||
public interface VulnerabilityDao extends BaseMapper<Vulnerability> {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.example.modules.dns.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.example.modules.dns.domain.DohAttribute;
|
||||
import com.example.modules.dns.domain.IpInformation;
|
||||
import com.example.utils.page.PageUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface DnsService extends IService<DohAttribute> {
|
||||
|
||||
|
||||
PageUtils queryPage(Map<String, Object> params);
|
||||
|
||||
Map<String, Object> dataCount(Map<String, Object> params);
|
||||
|
||||
Map<String, List<Map<String, Object>>> mapData();
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.example.modules.dns.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.example.modules.dns.domain.DnsType;
|
||||
import com.example.modules.dns.domain.DohAttribute;
|
||||
import com.example.utils.page.PageUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface DnsTypeService extends IService<DnsType> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.example.modules.dns.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface ScanResultService extends IService<ScanResult> {
|
||||
|
||||
|
||||
Map<String, Object> queryDo53DataCountByDnsType(Map<String,Object> params,Integer dnsType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.example.modules.dns.service.impl;
|
||||
|
||||
import com.example.utils.Constant;
|
||||
import com.example.utils.ElAdminConstant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Lihe
|
||||
* @version 1
|
||||
* @description 查询分类
|
||||
* @date 2022/6/22
|
||||
*/
|
||||
public enum DnsQueryEnum {
|
||||
|
||||
OPEN_RDNS(Constant.OPENRDNSTAG, ElAdminConstant.openRdnsLabels, "openRdns", 1),
|
||||
|
||||
FORWARDER(Constant.FORWARDERTAG, ElAdminConstant.forwarderLabels, "forwarder", 2),
|
||||
|
||||
FWD_RDNS(Constant.FWDRDNSTAG, ElAdminConstant.fwdRdnsLabels, "fwdRdns", 3),
|
||||
|
||||
EGRESS_DNS(Constant.EGRESSRDNSTAG, ElAdminConstant.egressDnsLabels, "egressDns", 4),
|
||||
|
||||
NON_STANDARD(Constant.NONSTANDARDTAG, ElAdminConstant.nonstandardLabels, "nonstandard", 5),
|
||||
|
||||
DNS(Constant.DNSTAG, ElAdminConstant.dnsLabels, "queryDnsInfo", 0),
|
||||
|
||||
DOH(Constant.DOH, ElAdminConstant.dohLabels, "queryDohInfo", 0),
|
||||
|
||||
DO53(Constant.DO53, ElAdminConstant.do53Labels, "queryDo53Info", 0),
|
||||
|
||||
DOH_AND_DO53("dohAndDo53", null, "queryDohAndDo53Info", 0),
|
||||
|
||||
IP(Constant.IP, null, "queryPageByIp", 0),
|
||||
;
|
||||
|
||||
private final String service;
|
||||
|
||||
private final List<String> labels;
|
||||
|
||||
private final String methodName;
|
||||
|
||||
private final Integer dnsType;
|
||||
|
||||
public static DnsQueryEnum getQueryInfo(String serviceName) {
|
||||
for (DnsQueryEnum value : DnsQueryEnum.values()) {
|
||||
if (value.getService().equals(serviceName)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
public String getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
public List<String> getLabels() {
|
||||
return labels;
|
||||
}
|
||||
|
||||
public Integer getDnsType() {
|
||||
return dnsType;
|
||||
}
|
||||
|
||||
DnsQueryEnum(String service, List<String> labels, String methodName, Integer dnsType) {
|
||||
this.service = service;
|
||||
this.labels = labels;
|
||||
this.methodName = methodName;
|
||||
this.dnsType = dnsType;
|
||||
}
|
||||
|
||||
public static List<String> getLabels(String key) {
|
||||
for (DnsQueryEnum value : DnsQueryEnum.values()) {
|
||||
if (value.getService().equals(key)) {
|
||||
return value.getLabels();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Integer getDnsType(String key) {
|
||||
for (DnsQueryEnum value : DnsQueryEnum.values()) {
|
||||
if (value.getService().equals(key)) {
|
||||
return value.getDnsType();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String getDnsType(Integer type) {
|
||||
for (DnsQueryEnum value : DnsQueryEnum.values()) {
|
||||
if (value.getDnsType().equals(type)) {
|
||||
return value.getService();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,631 @@
|
||||
package com.example.modules.dns.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.example.modules.dns.domain.*;
|
||||
import com.example.modules.dns.mapper.*;
|
||||
import com.example.modules.dns.service.DnsService;
|
||||
import com.example.modules.dns.service.ScanResultService;
|
||||
import com.example.utils.Constant;
|
||||
import com.example.utils.page.PageUtils;
|
||||
import com.example.utils.page.Query;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class DnsServiceImpl extends ServiceImpl<DnsDohDao, DohAttribute> implements DnsService {
|
||||
@Autowired
|
||||
private DnsDohDao dnsDohDao;
|
||||
|
||||
@Autowired
|
||||
private DnsDo53Dao dnsDo53Dao;
|
||||
|
||||
@Autowired
|
||||
private IpCertDao ipCertDao;
|
||||
|
||||
@Autowired
|
||||
private IpInformationDao ipInformationDao;
|
||||
|
||||
@Autowired
|
||||
private NonstandardDnsDao nonstandardDnsDao;
|
||||
|
||||
@Autowired
|
||||
private ScanResultService scanResultService;
|
||||
|
||||
|
||||
/**
|
||||
* 添加新service查询逻辑时:
|
||||
* 1. 在本类中实现该service的查询逻辑
|
||||
* 2. DnsQueryEnum 添加该查询逻辑的枚举,包括serviceName,方法名,标签和dnsType可根据需要设置
|
||||
* and 查询逻辑需要单独实现
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public PageUtils queryPage(Map<String, Object> params) {
|
||||
String service = (String) params.get(Constant.SERVICE);
|
||||
String port = (String) params.get(Constant.PORT);
|
||||
String ip = (String) params.get(Constant.IP);
|
||||
IPage page = new Query(IpInformation.class).getPage(params);
|
||||
params.put("n", (page.getCurrent() - 1) * page.getSize()); //用作doh查询的分页
|
||||
params.put("m", page.getSize()); //用作doh查询的分页
|
||||
if(StringUtils.isBlank(service) && StringUtils.isBlank(ip) && StringUtils.isBlank(port)){
|
||||
return new PageUtils(page);
|
||||
}
|
||||
if(StringUtils.isNotBlank(port)){
|
||||
if(Constant.PORT53.equals(port)){
|
||||
service = Constant.DO53;
|
||||
}else if(Constant.PORT443.equals(port) || Constant.PORT8443.equals(port)){
|
||||
service = Constant.DOH;
|
||||
}
|
||||
}
|
||||
if(StringUtils.isBlank(port) && StringUtils.isBlank(service) && StringUtils.isNotBlank(ip)){
|
||||
service = Constant.IP;
|
||||
}
|
||||
if(StringUtils.isNotBlank(service)) {
|
||||
if(service.toLowerCase().contains("and")){
|
||||
return queryDohAndDo53Info(page,params);
|
||||
}else {
|
||||
// DnsQueryEnum 枚举类获取service对应的方法名,并通过反射调用
|
||||
DnsQueryEnum serviceEnum = DnsQueryEnum.getQueryInfo(service.toLowerCase());
|
||||
Class<? extends DnsServiceImpl> aClass = this.getClass();
|
||||
try {
|
||||
Method method = aClass.getDeclaredMethod(serviceEnum.getMethodName(), IPage.class, Map.class);
|
||||
return (PageUtils) method.invoke(this, page, params);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PageUtils(page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> dataCount(Map<String, Object> params) {
|
||||
String service = (String) params.get(Constant.SERVICE);
|
||||
String port = (String) params.get(Constant.PORT);
|
||||
String ip = (String) params.get(Constant.IP);
|
||||
Map<String, Object> resultMap = new HashMap(8);
|
||||
if(StringUtils.isBlank(service) && StringUtils.isBlank(ip) && StringUtils.isBlank(port)){
|
||||
return resultMap;
|
||||
}
|
||||
List<Map<String, Object>> portList = new ArrayList<>();
|
||||
List<Map<String, Object>> regionList ;
|
||||
List<Map<String, Object>> providerList ;
|
||||
List<Map<String, Object>> componentList ;
|
||||
List<Map<String, Object>> serviceCategoryList = new ArrayList<>();
|
||||
List<Map<String, Object>> do53serviceCategoryList ;
|
||||
List<Map<String, Object>> vulnerabilityCountList ;
|
||||
if (Constant.DOH.equals(service) || Constant.PORT8443.equals(port) || Constant.PORT443.equals(port)) {
|
||||
//端口
|
||||
portList = dnsDohDao.dohPortCount(params);
|
||||
//地域
|
||||
regionList = dnsDohDao.dohProvinceCount(params);
|
||||
//运营商
|
||||
providerList = dnsDohDao.dohProviderCount(params);
|
||||
//服务组件
|
||||
componentList = dnsDohDao.dohComponentCount(params);
|
||||
//服务类别
|
||||
Map<String, Object> map = dnsDohDao.dohServiceCategoryCount(params);
|
||||
map.put("key", Constant.DOHTAG);
|
||||
serviceCategoryList.add(map);
|
||||
//漏洞威胁
|
||||
vulnerabilityCountList = dnsDohDao.dohVulnerabilityCount(params);
|
||||
|
||||
} else if (Constant.DO53.equals(service) || Constant.PORT53.equals(port)) {
|
||||
//端口
|
||||
Map<String, Object> portMap = new HashMap<>();
|
||||
int do53PortCount = dnsDo53Dao.do53IpCount(params);
|
||||
portMap.put("port", Constant.PORT53);
|
||||
portMap.put("count", do53PortCount);
|
||||
portList.add(portMap);
|
||||
//地域
|
||||
regionList = dnsDo53Dao.do53ProvinceCount(params);
|
||||
//运营商
|
||||
providerList = dnsDo53Dao.do53ProviderCount(params);
|
||||
//服务组件
|
||||
componentList = dnsDo53Dao.do53ComponentCount(params);
|
||||
//服务类别
|
||||
do53serviceCategoryList = dnsDo53Dao.do53ServiceCategoryCount(params);
|
||||
serviceCategoryList = transformDo53serviceCategory(do53serviceCategoryList);
|
||||
//漏洞威胁
|
||||
vulnerabilityCountList = dnsDo53Dao.do53VulnerabilityCount(params);
|
||||
|
||||
}else if ("dns".equalsIgnoreCase(service) || StringUtils.isNotBlank(ip)) {
|
||||
//端口
|
||||
portList = dnsDohDao.dohPortCount(params);
|
||||
Map<String, Object> portMap = new HashMap<>();
|
||||
Integer do53PortCount = dnsDo53Dao.do53IpCount(params);
|
||||
portMap.put("port", Constant.PORT53);
|
||||
portMap.put("count", do53PortCount);
|
||||
portList.add(portMap);
|
||||
//地域
|
||||
regionList = dnsDohDao.dohAndDo53ProvinceCount(params);
|
||||
//运营商
|
||||
providerList = dnsDohDao.dohAndDo53ProviderCount(params);
|
||||
//服务组件
|
||||
componentList = dnsDohDao.dohAndDo53ComponentCount(params);
|
||||
//服务类别
|
||||
do53serviceCategoryList = dnsDo53Dao.do53ServiceCategoryCount(params);
|
||||
serviceCategoryList = transformDo53serviceCategory(do53serviceCategoryList);
|
||||
Map<String, Object> map = dnsDohDao.dohServiceCategoryCount(params);
|
||||
map.put("key", Constant.DOHTAG);
|
||||
serviceCategoryList.add(map);
|
||||
//漏洞威胁
|
||||
vulnerabilityCountList = dnsDohDao.dohAndDo53VulnerabilityCount(params);
|
||||
}else if(service.toLowerCase().contains("and")){
|
||||
// 目前只有 doh AND do53其余条件未实现
|
||||
//端口
|
||||
portList = dnsDohDao.countDohPortUnion(params);
|
||||
|
||||
//地域
|
||||
regionList = dnsDohDao.getDohAndDo53ProvinceCount(params);
|
||||
//运营商
|
||||
providerList = dnsDohDao.getDohAndDo53ProviderCount(params);
|
||||
//服务组件
|
||||
componentList = dnsDohDao.getDohAndDo53ComponentCount(params);
|
||||
//服务类别
|
||||
do53serviceCategoryList = dnsDo53Dao.getDohAndDo53SrvCategoryCount(params);
|
||||
serviceCategoryList = transformDo53serviceCategory(do53serviceCategoryList);
|
||||
Map<String, Object> map = dnsDohDao.getDohServiceCategoryCount(params);
|
||||
map.put("key", Constant.DOHTAG);
|
||||
map.put("count", dnsDo53Dao.selectScanResultCountByUnion(params));
|
||||
serviceCategoryList.add(map);
|
||||
//漏洞威胁
|
||||
vulnerabilityCountList = dnsDohDao.getDohAndDo53VulnerabilityCount(params);
|
||||
}else{
|
||||
// dn53下5种 dns_type 统计
|
||||
return scanResultService.queryDo53DataCountByDnsType(params,DnsQueryEnum.getDnsType(service));
|
||||
}
|
||||
resultMap.put("portList", portList);
|
||||
resultMap.put("regionList", regionList);
|
||||
resultMap.put("providerList", providerList);
|
||||
resultMap.put("componentList", componentList);
|
||||
resultMap.put("serviceCategoryList", serviceCategoryList);
|
||||
resultMap.put("vulnerabilityCountList", vulnerabilityCountList);
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, List<Map<String, Object>>> mapData() {
|
||||
Map<String, List<Map<String, Object>>> resultMap = new HashMap<>();
|
||||
List<Map<String, Object>> dohChinaMapList ;
|
||||
List<Map<String, Object>> dohWorldMapDataList ;
|
||||
List<Map<String, Object>> do53CountryMapCountList ;
|
||||
List<Map<String, Object>> do53OpenRdnsList = new ArrayList<>();
|
||||
List<Map<String, Object>> do53ForwarderList = new ArrayList<>();
|
||||
List<Map<String, Object>> do53FwdRdnsList = new ArrayList<>();
|
||||
List<Map<String, Object>> do53EgressDnsList = new ArrayList<>();
|
||||
List<Map<String, Object>> do53NonstandardList = new ArrayList<>();
|
||||
List<Map<String, Object>> do53WorldMapList ;
|
||||
List<Map<String, Object>> do53ChinaMapList ;
|
||||
dohChinaMapList = dnsDohDao.dohChinaMapCount();
|
||||
dohWorldMapDataList = dnsDohDao.dohCountryCount();
|
||||
do53WorldMapList = dnsDo53Dao.do53WorldMapCount();
|
||||
do53ChinaMapList = dnsDo53Dao.do53ChinaMapCount();
|
||||
do53CountryMapCountList = dnsDo53Dao.do53CountryMapCount();
|
||||
for (Map<String, Object> map : do53CountryMapCountList) {
|
||||
if (Constant.OPENRDNS == map.get("type")) {
|
||||
do53OpenRdnsList.add(map);
|
||||
} else if (Constant.FORWARDER == map.get("type")) {
|
||||
do53ForwarderList.add(map);
|
||||
} else if (Constant.FWDRDNS == map.get("type")) {
|
||||
do53FwdRdnsList.add(map);
|
||||
} else if (Constant.EGRESSRDNS == map.get("type")) {
|
||||
do53EgressDnsList.add(map);
|
||||
} else if (Constant.NONSTANDARD == map.get("type")) {
|
||||
do53NonstandardList.add(map);
|
||||
}
|
||||
}
|
||||
resultMap.put("dohChinaMapList", dohChinaMapList);
|
||||
resultMap.put("dohWorldMapDataList", dohWorldMapDataList);
|
||||
resultMap.put("do53WorldMapDataList", do53WorldMapList);
|
||||
resultMap.put("do53ChinaMapList", do53ChinaMapList);
|
||||
resultMap.put("do53OpenRdnsList", do53OpenRdnsList);
|
||||
resultMap.put("do53ForwarderList", do53ForwarderList);
|
||||
resultMap.put("do53FwdRdnsList", do53FwdRdnsList);
|
||||
resultMap.put("do53EgressDnsList", do53EgressDnsList);
|
||||
resultMap.put("do53NonstandardList", do53NonstandardList);
|
||||
return resultMap;
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> transformDo53serviceCategory(List<Map<String, Object>> do53serviceCategoryList) {
|
||||
List<Map<String, Object>> serviceCategoryList = new ArrayList<>();
|
||||
long do53Count = 0;
|
||||
for (Map<String, Object> map : do53serviceCategoryList) {
|
||||
Map<String, Object> do53ServiceMap = new HashMap<>();
|
||||
long count = (long) map.get("count");
|
||||
int dnsType = (int) map.get("type");
|
||||
if (Constant.FORWARDER == dnsType) { //2
|
||||
do53ServiceMap.put("key", Constant.FORWARDERTAG);
|
||||
do53ServiceMap.put("count", count);
|
||||
} else if (Constant.FWDRDNS == dnsType) {//3
|
||||
do53ServiceMap.put("key", Constant.FWDRDNSTAG);
|
||||
do53ServiceMap.put("count", count);
|
||||
} else if (Constant.EGRESSRDNS == dnsType) { //4
|
||||
do53ServiceMap.put("key", Constant.EGRESSRDNSTAG);
|
||||
do53ServiceMap.put("count", count);
|
||||
} else if (Constant.NONSTANDARD == dnsType) { //5
|
||||
do53ServiceMap.put("key", Constant.NONSTANDARDTAG);
|
||||
do53ServiceMap.put("count", count);
|
||||
} else if (Constant.OPENRDNS == dnsType) { //1
|
||||
do53ServiceMap.put("key", Constant.OPENRDNSTAG);
|
||||
do53ServiceMap.put("count", count);
|
||||
}
|
||||
do53Count += count;
|
||||
serviceCategoryList.add(do53ServiceMap);
|
||||
}
|
||||
HashMap<String, Object> do53Map = new HashMap<>();
|
||||
do53Map.put("key", Constant.DO53TAG);
|
||||
do53Map.put("count", do53Count);
|
||||
serviceCategoryList.add(do53Map);
|
||||
return serviceCategoryList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置doh属性
|
||||
* @param dohAttributes
|
||||
*/
|
||||
public void setDohData(List<Result> dohAttributes) {
|
||||
for (Result dohAttribute : dohAttributes) {
|
||||
String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
|
||||
dohAttribute.setUuid(uuid);
|
||||
String dohIp = dohAttribute.getIp();
|
||||
Integer port = dohAttribute.getPort();
|
||||
String component = dohAttribute.getComponent();
|
||||
String path = dohAttribute.getPath();
|
||||
dohAttribute.setProtocolType(Constant.PROTOC_TCP);
|
||||
dohAttribute.setIpType(getIpType(dohIp));
|
||||
if (component != null)
|
||||
dohAttribute.setComponentList(new ArrayList<>(Arrays.stream(component.split(",")).collect(Collectors.toSet())));
|
||||
if (path != null)
|
||||
dohAttribute.setPathList(new ArrayList<>(Arrays.stream(path.split(",")).collect(Collectors.toSet())));
|
||||
ArrayList<String> tagList = new ArrayList<>(); //添加服务类别标签
|
||||
tagList.add(Constant.DOHTAG);
|
||||
List<Object> banner = new ArrayList<>();
|
||||
List<Object> httpHeader = new ArrayList<>();
|
||||
// 根据ip,port,host,rounds查询doh_attribute rep_body repHeader信息
|
||||
List<Result> repList = this.baseMapper.getDohRepBody(dohIp, port, dohAttribute.getHost(), dohAttribute.getRounds());
|
||||
for (int i = 0; i < repList.size(); i++) {
|
||||
Result result = repList.get(i);
|
||||
if (StringUtils.isNotBlank(result.getRepBody())) {
|
||||
banner.add(result.getRepBody());
|
||||
}
|
||||
if (StringUtils.isNotBlank(result.getRepHeader())) {
|
||||
httpHeader.add(result.getRepHeader());
|
||||
}
|
||||
}
|
||||
dohAttribute.setBanner(banner);
|
||||
dohAttribute.setHttpContent(httpHeader);
|
||||
//根据ip和端口查询证书库,获取证书数据
|
||||
List<IpCert> ipCertList = ipCertDao.selectList(new LambdaQueryWrapper<IpCert>().eq(IpCert::getIp, dohIp).eq(IpCert::getPort, port));
|
||||
dohAttribute.setIpCert(ipCertList);
|
||||
dohAttribute.setTags(tagList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置do53标签,根据dnsType设置banner
|
||||
* type = 1 banner list.get(0)为rep
|
||||
* type = 2,3 banner中的 list.get(0)为 query_rep,列表其余数据为ip信息
|
||||
* type = 5 banner list.get(0)为rep,其余为NonstandardDns列表
|
||||
* @param scanResultList
|
||||
*/
|
||||
public void setdo53Data(List<Result> scanResultList) {
|
||||
for (Result scanResult : scanResultList) {
|
||||
String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
|
||||
scanResult.setUuid(uuid);
|
||||
String do53Ip = scanResult.getIp();
|
||||
Integer epoch = scanResult.getEpoch();
|
||||
Integer dnsType = scanResult.getDnsType();
|
||||
ArrayList<String> tagList = new ArrayList<>(); //添加服务类别标签
|
||||
tagList.add(Constant.DO53TAG);
|
||||
scanResult.setIpType(getIpType(do53Ip));
|
||||
scanResult.setProtocolType(getProtocolType(scanResult.getScanType()));
|
||||
List<Object> bannerList = new ArrayList<>();
|
||||
if (Constant.FORWARDER.equals(dnsType) || Constant.FWDRDNS.equals(dnsType)) { //2、3
|
||||
if (Constant.FWDRDNS.equals(dnsType)) { //3
|
||||
tagList.add(Constant.FORWARDERTAG);
|
||||
} else {
|
||||
tagList.add(Constant.FWDRDNSTAG);
|
||||
}
|
||||
bannerList.add(scanResult.getQueryResponse());
|
||||
List<IpInformation> forwardDnsList = ipInformationDao.getIpInfoByFwd(do53Ip, epoch);
|
||||
bannerList.addAll(forwardDnsList);
|
||||
} else if (Constant.EGRESSRDNS.equals(dnsType)) { //4
|
||||
tagList.add(Constant.EGRESSRDNSTAG);
|
||||
|
||||
} else if (Constant.NONSTANDARD.equals(dnsType)) { //5
|
||||
bannerList.add(scanResult.getQueryResponse());
|
||||
tagList.add(Constant.NONSTANDARDTAG);
|
||||
List<NonstandardDns> nonstandardDnsList = nonstandardDnsDao.selectList(new LambdaQueryWrapper<NonstandardDns>().eq(NonstandardDns::getIp, do53Ip).eq(NonstandardDns::getEpoch, epoch));
|
||||
bannerList.addAll((List<JSONObject>) JSONObject.toJSON(nonstandardDnsList));
|
||||
} else if (Constant.OPENRDNS.equals(dnsType)) { //1
|
||||
tagList.add(Constant.OPENRDNSTAG);
|
||||
if(StringUtils.isNotBlank(scanResult.getQueryResponse())){
|
||||
bannerList.add(scanResult.getQueryResponse());
|
||||
}
|
||||
}
|
||||
scanResult.setBanner(bannerList);
|
||||
scanResult.setTags(tagList);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dataList 目标list
|
||||
* @param pageSize 当前页大小
|
||||
* @param currentPage 当前页
|
||||
* @return 返回当前页的数据集
|
||||
* @deprecated 对list进行分页
|
||||
*/
|
||||
public List<Result> getPage(List<Result> dataList, int pageSize, int currentPage) {
|
||||
List<Result> currentPageList = new ArrayList<>();
|
||||
if (!dataList.isEmpty()) {
|
||||
int currIdx = (currentPage > 1 ? (currentPage - 1) * pageSize : 0);
|
||||
for (int i = 0; i < pageSize && i < dataList.size() - currIdx; i++) {
|
||||
Result data = dataList.get(currIdx + i);
|
||||
currentPageList.add(data);
|
||||
}
|
||||
}
|
||||
return currentPageList;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询dns信息,dnh和do53(scan_result)结果并集
|
||||
*
|
||||
* @param page
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
private PageUtils queryDnsInfo(IPage page, Map<String, Object> params) {
|
||||
Map<String, Object> indepentIpMap = new HashMap<>(4);
|
||||
int resultTotal = 0;
|
||||
long pageSize = page.getSize();
|
||||
params.put("n", 0); //用作doh查询的分页偏移量
|
||||
params.put("m", page.getCurrent() * page.getSize()); //用作查询的分页大小
|
||||
// 查询doh信息
|
||||
//同一轮次,相同ip合并path和component,漏洞信息
|
||||
List<Result> dohAttributes = dnsDohDao.queryDohPage(null, params);
|
||||
setDohData(dohAttributes);
|
||||
int dohResultTotal = dnsDohDao.dohResultTotalCount(params);
|
||||
indepentIpMap.put("dns-doh", dnsDohDao.dohIpCount(params));
|
||||
// 查询do53信息
|
||||
List<Result> scanResultList = dnsDo53Dao.queryDo53Page(null, params);
|
||||
setdo53Data(scanResultList);
|
||||
indepentIpMap.put("dns-do53", dnsDo53Dao.do53IpCount(params));
|
||||
int do53ResultTotal = dnsDo53Dao.pageCount(params);
|
||||
|
||||
List<Result> resultList = new ArrayList<>();
|
||||
resultList.addAll(dohAttributes);
|
||||
resultList.addAll(scanResultList);
|
||||
List<Result> collect = resultList.stream().sorted(Comparator.comparing(Result::getTimestamp).reversed()).collect(Collectors.toList());
|
||||
|
||||
page.setTotal(do53ResultTotal + dohResultTotal);
|
||||
page.setRecords(getPage(collect, (int) pageSize, (int) page.getCurrent()));
|
||||
|
||||
return buildResult(page,indepentIpMap,(do53ResultTotal + dohResultTotal));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 do53信息
|
||||
* @param page
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
private PageUtils queryDo53Info(IPage page, Map<String, Object> params){
|
||||
// 根据 service=dns-do53, port为53查询 scan_result表 参数:ip,port
|
||||
List<Result> scanResultList = dnsDo53Dao.queryDo53Page(null, params);
|
||||
setdo53Data(scanResultList);
|
||||
|
||||
int independentIpNum = dnsDo53Dao.do53IpCount(params);
|
||||
int resultTotal = dnsDo53Dao.pageCount(params);
|
||||
page.setRecords(scanResultList);
|
||||
return buildResult(page,independentIpNum,resultTotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询doh信息
|
||||
* @param page
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
private PageUtils queryDohInfo(IPage page, Map<String, Object> params){
|
||||
// 根据 service=dns-do53, port为53查询 scan_result表 参数:ip,port
|
||||
List<Result> scanResultList = dnsDohDao.queryDohPage(null, params);
|
||||
setDohData(scanResultList);
|
||||
|
||||
int independentIpNum = dnsDohDao.dohIpCount(params);
|
||||
int resultTotal = dnsDohDao.dohResultTotalCount(params);
|
||||
page.setRecords(scanResultList);
|
||||
return buildResult(page,independentIpNum,resultTotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 只根据ip查询
|
||||
* @param page
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
private PageUtils queryPageByIp(IPage page, Map<String, Object> params){
|
||||
// 只根据ip查询
|
||||
int independentIpNum = 0;
|
||||
params.put("n", 0); //用作doh查询的分页
|
||||
params.put("m", page.getCurrent() * page.getSize()); //用作doh查询的分页
|
||||
long pageSize = page.getSize();
|
||||
List<Result> dohAttributesList = dnsDohDao.queryDohPage(null, params);
|
||||
setDohData(dohAttributesList);
|
||||
List<Result> scanResultList = dnsDo53Dao.queryDo53Page(null, params);
|
||||
setdo53Data(scanResultList);
|
||||
List<Result> resultList = new ArrayList<>();
|
||||
resultList.addAll(dohAttributesList);
|
||||
resultList.addAll(scanResultList);
|
||||
int resultTotal = resultList.size();
|
||||
List<Result> collect = resultList.stream().sorted(Comparator.comparing(Result::getTimestamp).reversed()).collect(Collectors.toList());
|
||||
if (!collect.isEmpty()) {
|
||||
independentIpNum = 1;
|
||||
}
|
||||
page.setTotal(collect.size());
|
||||
page.setRecords(getPage(collect, (int) pageSize, (int) page.getCurrent()));
|
||||
return buildResult(page,independentIpNum,resultTotal);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 dnh和do53(scan_result)结果交集 service = dns-doh AND dns-do53
|
||||
*
|
||||
* @param page
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
private PageUtils queryDohAndDo53Info(IPage page, Map<String, Object> params) {
|
||||
params.put("offset", 0); //用作doh查询的分页偏移量
|
||||
params.put("limit", page.getCurrent() * page.getSize()); //用作查询的分页大小
|
||||
Map<String, Object> indepentIpMap = new HashMap<>(4);
|
||||
|
||||
// 查询doh信息
|
||||
List<Result> dohAttributes = dnsDohDao.selectDohInfoByUnion(params);
|
||||
Integer dohCount = dnsDohDao.selectDohCountByUnion(params);
|
||||
setDohData(dohAttributes);
|
||||
// 查询do53(scan_result)信息
|
||||
List<Result> do53Infos = dnsDo53Dao.selectScanResultByUnion(null,params);
|
||||
Integer do53Count = dnsDo53Dao.selectScanResultCountByUnion(params);
|
||||
setdo53Data(do53Infos);
|
||||
do53Infos.addAll(dohAttributes);
|
||||
|
||||
page.setTotal(dohCount + do53Count);
|
||||
page.setRecords(getPage(do53Infos, (int) page.getSize(), (int) page.getCurrent()));
|
||||
indepentIpMap.put("dns-doh",do53Count);
|
||||
indepentIpMap.put("dns-do53",do53Count);
|
||||
|
||||
return buildResult(page,indepentIpMap,(dohCount + do53Count));
|
||||
|
||||
}
|
||||
|
||||
private String getIpType(String ip){
|
||||
if(ip.contains(Constant.POINT)){
|
||||
return Constant.IP_IPV4;
|
||||
}
|
||||
return Constant.IP_IPV6;
|
||||
}
|
||||
|
||||
private String getProtocolType(Integer scanType){
|
||||
// dnsType 为2为udp,1或者空为tcp
|
||||
if(scanType == null || scanType < 2){
|
||||
return Constant.PROTOC_TCP;
|
||||
}
|
||||
return Constant.PROTOC_UDP;
|
||||
}
|
||||
|
||||
private PageUtils buildResult(IPage page,Object independentIpNum,Integer resultTotal ){
|
||||
PageUtils pageUtils = new PageUtils(page);
|
||||
// 添加独立IP个数
|
||||
pageUtils.setIndependentIpNum(independentIpNum);
|
||||
pageUtils.setResultTotal(resultTotal);
|
||||
return pageUtils;
|
||||
}
|
||||
|
||||
|
||||
private PageUtils openRdns(IPage page, Map<String, Object> params) {
|
||||
List<Result> results = dnsDo53Dao.queryOpenRdns(params);
|
||||
int totalCount = dnsDo53Dao.getCountByDnsType(Constant.OPENRDNS, params);
|
||||
setDo53Label(results, Constant.OPENRDNSTAG);
|
||||
page.setRecords(results);
|
||||
// 添加独立IP个数
|
||||
Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.OPENRDNS, params);
|
||||
|
||||
return buildResult(page,independentIpNum,totalCount);
|
||||
}
|
||||
|
||||
private PageUtils forwarder(IPage page, Map<String, Object> params) {
|
||||
int totalCount = dnsDo53Dao.getCountByDnsType(Constant.FORWARDER, params);
|
||||
List<Result> results = dnsDo53Dao.queryOpenRdns(params);
|
||||
for (Result result : results) {
|
||||
List<IpInformation> ipInfos = ipInformationDao.getIpInfoByFwd(result.getIp(),null);
|
||||
result.setBanner(ipInfos);
|
||||
result.setProtocolType(getProtocolType(result.getScanType()));
|
||||
result.setIpType(getIpType(result.getIp()));
|
||||
addLabels(result, Constant.FORWARDERTAG);
|
||||
}
|
||||
|
||||
page.setRecords(results);
|
||||
// 添加独立IP个数
|
||||
Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.FORWARDER, params);
|
||||
|
||||
return buildResult(page,independentIpNum,totalCount);
|
||||
}
|
||||
|
||||
private PageUtils fwdRdns(IPage page, Map<String, Object> params) {
|
||||
int totalCount = dnsDo53Dao.getCountByDnsType(Constant.FWDRDNS, params);
|
||||
List<Result> results = dnsDo53Dao.queryOpenRdns(params);
|
||||
for (Result result : results) {
|
||||
List<IpInformation> ipInfos = ipInformationDao.getIpInfoByFwd(result.getIp(),null);
|
||||
result.setBanner(ipInfos);
|
||||
result.setProtocolType(getProtocolType(result.getScanType()));
|
||||
result.setIpType(getIpType(result.getIp()));
|
||||
addLabels(result, Constant.FWDRDNSTAG);
|
||||
}
|
||||
page.setRecords(results);
|
||||
// 添加独立IP个数
|
||||
Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.FWDRDNS, params);
|
||||
|
||||
return buildResult(page,independentIpNum,totalCount);
|
||||
}
|
||||
|
||||
private PageUtils egressDns(IPage page, Map<String, Object> params) {
|
||||
int totalCount = dnsDo53Dao.getCountByDnsType(Constant.EGRESSRDNS, params);
|
||||
List<Result> results = dnsDo53Dao.queryOpenRdns(params);
|
||||
setDo53Label(results, Constant.EGRESSRDNSTAG);
|
||||
page.setRecords(results);
|
||||
// 添加独立IP个数
|
||||
Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.EGRESSRDNS, params);
|
||||
|
||||
return buildResult(page,independentIpNum,totalCount);
|
||||
}
|
||||
|
||||
private PageUtils nonstandard(IPage page, Map<String, Object> params) {
|
||||
int totalCount = dnsDo53Dao.getCountByDnsType(Constant.NONSTANDARD, params);
|
||||
List<Result> results = dnsDo53Dao.queryOpenRdns(params);
|
||||
for (Result result : results) {
|
||||
List<IpInformation> ipInfos = ipInformationDao.getIpInfoByFwd(result.getIp(),null);
|
||||
result.setBanner(ipInfos);
|
||||
result.setProtocolType(getProtocolType(result.getScanType()));
|
||||
result.setIpType(getIpType(result.getIp()));
|
||||
addLabels(result, Constant.NONSTANDARDTAG);
|
||||
}
|
||||
|
||||
page.setRecords(results);
|
||||
// 添加独立IP个数
|
||||
Integer independentIpNum = dnsDo53Dao.getIndependentIpNum(Constant.NONSTANDARD, params);
|
||||
|
||||
return buildResult(page,independentIpNum,totalCount);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void setDo53Label(List<Result> results, String serviceType) {
|
||||
List<String> labels = DnsQueryEnum.getLabels(serviceType);
|
||||
for (Result result : results) {
|
||||
// result.setBanner(result.getQueryResponse());
|
||||
result.setProtocolType(getProtocolType(result.getScanType()));
|
||||
result.setIpType(getIpType(result.getIp()));
|
||||
result.setTags(labels);
|
||||
}
|
||||
}
|
||||
|
||||
private void addLabels(Result result, String serviceType) {
|
||||
List<String> labels = DnsQueryEnum.getLabels(serviceType);
|
||||
result.setTags(labels);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.example.modules.dns.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.example.modules.dns.domain.DnsType;
|
||||
import com.example.modules.dns.mapper.DnsTypeDao;
|
||||
import com.example.modules.dns.service.DnsTypeService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class DnsTypeServiceImpl extends ServiceImpl<DnsTypeDao, DnsType> implements DnsTypeService {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.example.modules.dns.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.example.modules.dns.domain.ScanResult;
|
||||
import com.example.modules.dns.mapper.DnsDo53Dao;
|
||||
import com.example.modules.dns.service.ScanResultService;
|
||||
import com.example.utils.Constant;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Lihe
|
||||
* @version 1
|
||||
* @description
|
||||
* @date 2022/6/8
|
||||
*/
|
||||
@Service
|
||||
public class ScanResultServiceImpl extends ServiceImpl<DnsDo53Dao, ScanResult> implements ScanResultService {
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, Object> queryDo53DataCountByDnsType(Map<String, Object> params, Integer dnsType) {
|
||||
|
||||
Map<String, Object> resultMap = new HashMap(8);
|
||||
List<Map<String, Object>> portList = new ArrayList<>();
|
||||
|
||||
List<Map<String, Object>> serviceCategoryList = new ArrayList<>();
|
||||
//端口
|
||||
Map<String, Object> portMap = new HashMap<>();
|
||||
int count = this.baseMapper.getCountByDnsType(dnsType,params);
|
||||
portMap.put("port", Constant.PORT53);
|
||||
portMap.put("count", count);
|
||||
portList.add(portMap);
|
||||
resultMap.put("portList", portList);
|
||||
|
||||
//地域
|
||||
resultMap.put("regionList", this.baseMapper.getDo53ProvinceCountByDnsType(dnsType,params));
|
||||
|
||||
//运营商
|
||||
resultMap.put("providerList", this.baseMapper.getDo53ProviderCountByDnsType(dnsType,params));
|
||||
|
||||
//服务组件
|
||||
resultMap.put("componentList", this.baseMapper.getDo53ComponentCountByDnsType(dnsType,params));
|
||||
|
||||
//服务类别
|
||||
Integer serviceCount = this.baseMapper.getDo53SrvCategoryCountByDnsType(dnsType,params);
|
||||
Map<String,Object> dnsTypeMap = new HashMap<>(2);
|
||||
dnsTypeMap.put("key",DnsQueryEnum.getDnsType(dnsType));
|
||||
dnsTypeMap.put("count",serviceCount);
|
||||
serviceCategoryList.add(dnsTypeMap);
|
||||
Map<String,Object> do53ServiceMap = new HashMap<>(2);
|
||||
do53ServiceMap.put("key",Constant.DO53TAG);
|
||||
do53ServiceMap.put("count",serviceCount);
|
||||
serviceCategoryList.add(do53ServiceMap);
|
||||
resultMap.put("serviceCategoryList", serviceCategoryList);
|
||||
|
||||
//漏洞威胁
|
||||
resultMap.put("vulnerabilityCountList", this.baseMapper.getDo53VulnerabCountByDnsType(dnsType,params));
|
||||
|
||||
return resultMap;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.config;
|
||||
|
||||
import com.example.modules.security.config.bean.LoginProperties;
|
||||
import com.example.modules.security.config.bean.SecurityProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @apiNote 配置文件转换Pojo类的 统一配置 类
|
||||
* @author: liaojinlong
|
||||
* : 2020/6/10 19:04
|
||||
*/
|
||||
@Configuration
|
||||
public class ConfigBeanConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "login")
|
||||
public LoginProperties loginProperties() {
|
||||
return new LoginProperties();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "jwt")
|
||||
public SecurityProperties securityProperties() {
|
||||
return new SecurityProperties();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.config;
|
||||
|
||||
import com.example.modules.security.security.JwtAccessDeniedHandler;
|
||||
import com.example.modules.security.security.JwtAuthenticationEntryPoint;
|
||||
import com.example.modules.security.security.TokenConfigurer;
|
||||
import com.example.modules.security.security.TokenProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.AnonymousAccess;
|
||||
import com.example.modules.security.config.bean.SecurityProperties;
|
||||
import com.example.modules.security.security.*;
|
||||
import com.example.modules.security.service.OnlineUserService;
|
||||
import com.example.modules.security.service.UserCacheClean;
|
||||
import com.example.utils.enums.RequestMethodEnum;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.core.GrantedAuthorityDefaults;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.springframework.web.method.HandlerMethod;
|
||||
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@RequiredArgsConstructor
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final TokenProvider tokenProvider;
|
||||
private final CorsFilter corsFilter;
|
||||
private final JwtAuthenticationEntryPoint authenticationErrorHandler;
|
||||
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
|
||||
private final ApplicationContext applicationContext;
|
||||
private final SecurityProperties properties;
|
||||
private final OnlineUserService onlineUserService;
|
||||
private final UserCacheClean userCacheClean;
|
||||
|
||||
@Bean
|
||||
GrantedAuthorityDefaults grantedAuthorityDefaults() {
|
||||
// 去除 ROLE_ 前缀
|
||||
return new GrantedAuthorityDefaults("");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
// 密码加密方式
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity httpSecurity) throws Exception {
|
||||
// 搜寻匿名标记 url: @AnonymousAccess
|
||||
RequestMappingHandlerMapping requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping");
|
||||
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
|
||||
// 获取匿名标记
|
||||
Map<String, Set<String>> anonymousUrls = getAnonymousUrl(handlerMethodMap);
|
||||
httpSecurity
|
||||
// 禁用 CSRF
|
||||
.csrf().disable()
|
||||
.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
|
||||
// 授权异常
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(authenticationErrorHandler)
|
||||
.accessDeniedHandler(jwtAccessDeniedHandler)
|
||||
// 防止iframe 造成跨域
|
||||
.and()
|
||||
.headers()
|
||||
.frameOptions()
|
||||
.disable()
|
||||
// 不创建会话
|
||||
.and()
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
// 静态资源等等
|
||||
.antMatchers(
|
||||
HttpMethod.GET,
|
||||
"/*.html",
|
||||
"/**/*.html",
|
||||
"/**/*.css",
|
||||
"/**/*.js",
|
||||
"/webSocket/**"
|
||||
).permitAll()
|
||||
// swagger 文档
|
||||
.antMatchers("/swagger-ui.html").permitAll()
|
||||
.antMatchers("/swagger-resources/**").permitAll()
|
||||
.antMatchers("/webjars/**").permitAll()
|
||||
.antMatchers("/*/api-docs").permitAll()
|
||||
// 文件
|
||||
.antMatchers("/avatar/**").permitAll()
|
||||
.antMatchers("/file/**").permitAll()
|
||||
// 阿里巴巴 druid
|
||||
.antMatchers("/druid/**").permitAll()
|
||||
// 放行OPTIONS请求
|
||||
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
// 自定义匿名访问所有url放行:允许匿名和带Token访问,细腻化到每个 Request 类型
|
||||
// GET
|
||||
.antMatchers(HttpMethod.GET, anonymousUrls.get(RequestMethodEnum.GET.getType()).toArray(new String[0])).permitAll()
|
||||
// POST
|
||||
.antMatchers(HttpMethod.POST, anonymousUrls.get(RequestMethodEnum.POST.getType()).toArray(new String[0])).permitAll()
|
||||
// PUT
|
||||
.antMatchers(HttpMethod.PUT, anonymousUrls.get(RequestMethodEnum.PUT.getType()).toArray(new String[0])).permitAll()
|
||||
// PATCH
|
||||
.antMatchers(HttpMethod.PATCH, anonymousUrls.get(RequestMethodEnum.PATCH.getType()).toArray(new String[0])).permitAll()
|
||||
// DELETE
|
||||
.antMatchers(HttpMethod.DELETE, anonymousUrls.get(RequestMethodEnum.DELETE.getType()).toArray(new String[0])).permitAll()
|
||||
// 所有类型的接口都放行
|
||||
.antMatchers(anonymousUrls.get(RequestMethodEnum.ALL.getType()).toArray(new String[0])).permitAll()
|
||||
// 所有请求都需要认证
|
||||
.anyRequest().authenticated()
|
||||
.and().apply(securityConfigurerAdapter());
|
||||
}
|
||||
|
||||
private TokenConfigurer securityConfigurerAdapter() {
|
||||
return new TokenConfigurer(tokenProvider, properties, onlineUserService, userCacheClean);
|
||||
}
|
||||
|
||||
private Map<String, Set<String>> getAnonymousUrl(Map<RequestMappingInfo, HandlerMethod> handlerMethodMap) {
|
||||
Map<String, Set<String>> anonymousUrls = new HashMap<>(8);
|
||||
Set<String> get = new HashSet<>();
|
||||
Set<String> post = new HashSet<>();
|
||||
Set<String> put = new HashSet<>();
|
||||
Set<String> patch = new HashSet<>();
|
||||
Set<String> delete = new HashSet<>();
|
||||
Set<String> all = new HashSet<>();
|
||||
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
|
||||
HandlerMethod handlerMethod = infoEntry.getValue();
|
||||
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
|
||||
if (null != anonymousAccess) {
|
||||
List<RequestMethod> requestMethods = new ArrayList<>(infoEntry.getKey().getMethodsCondition().getMethods());
|
||||
RequestMethodEnum request = RequestMethodEnum.find(requestMethods.size() == 0 ? RequestMethodEnum.ALL.getType() : requestMethods.get(0).name());
|
||||
switch (Objects.requireNonNull(request)) {
|
||||
case GET:
|
||||
get.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||
break;
|
||||
case POST:
|
||||
post.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||
break;
|
||||
case PUT:
|
||||
put.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||
break;
|
||||
case PATCH:
|
||||
patch.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||
break;
|
||||
case DELETE:
|
||||
delete.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||
break;
|
||||
default:
|
||||
all.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
anonymousUrls.put(RequestMethodEnum.GET.getType(), get);
|
||||
anonymousUrls.put(RequestMethodEnum.POST.getType(), post);
|
||||
anonymousUrls.put(RequestMethodEnum.PUT.getType(), put);
|
||||
anonymousUrls.put(RequestMethodEnum.PATCH.getType(), patch);
|
||||
anonymousUrls.put(RequestMethodEnum.DELETE.getType(), delete);
|
||||
anonymousUrls.put(RequestMethodEnum.ALL.getType(), all);
|
||||
return anonymousUrls;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.config.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 登录验证码配置信息
|
||||
*
|
||||
* @author liaojinlong
|
||||
* 2020/6/10 18:53
|
||||
*/
|
||||
@Data
|
||||
public class LoginCode {
|
||||
|
||||
/**
|
||||
* 验证码配置
|
||||
*/
|
||||
private LoginCodeEnum codeType;
|
||||
/**
|
||||
* 验证码有效期 分钟
|
||||
*/
|
||||
private Long expiration = 2L;
|
||||
/**
|
||||
* 验证码内容长度
|
||||
*/
|
||||
private int length = 2;
|
||||
/**
|
||||
* 验证码宽度
|
||||
*/
|
||||
private int width = 111;
|
||||
/**
|
||||
* 验证码高度
|
||||
*/
|
||||
private int height = 36;
|
||||
/**
|
||||
* 验证码字体
|
||||
*/
|
||||
private String fontName;
|
||||
/**
|
||||
* 字体大小
|
||||
*/
|
||||
private int fontSize = 25;
|
||||
|
||||
public LoginCodeEnum getCodeType() {
|
||||
return codeType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.config.bean;
|
||||
|
||||
/**
|
||||
* 验证码配置枚举
|
||||
*
|
||||
* @author: liaojinlong
|
||||
* : 2020/6/10 17:40
|
||||
*/
|
||||
|
||||
public enum LoginCodeEnum {
|
||||
/**
|
||||
* 算数
|
||||
*/
|
||||
ARITHMETIC,
|
||||
/**
|
||||
* 中文
|
||||
*/
|
||||
CHINESE,
|
||||
/**
|
||||
* 中文闪图
|
||||
*/
|
||||
CHINESE_GIF,
|
||||
/**
|
||||
* 闪图
|
||||
*/
|
||||
GIF,
|
||||
SPEC
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version loginCode.length.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-loginCode.length.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.config.bean;
|
||||
|
||||
import com.wf.captcha.*;
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import lombok.Data;
|
||||
import com.example.exception.BadConfigurationException;
|
||||
import com.example.utils.StringUtils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 配置文件读取
|
||||
*
|
||||
* @author liaojinlong
|
||||
* loginCode.length0loginCode.length0/6/10 17:loginCode.length6
|
||||
*/
|
||||
@Data
|
||||
public class LoginProperties {
|
||||
|
||||
/**
|
||||
* 账号单用户 登录
|
||||
*/
|
||||
private boolean singleLogin = false;
|
||||
|
||||
private LoginCode loginCode;
|
||||
|
||||
/**
|
||||
* 用户登录信息缓存
|
||||
*/
|
||||
private boolean cacheEnable;
|
||||
|
||||
public boolean isSingleLogin() {
|
||||
return singleLogin;
|
||||
}
|
||||
|
||||
public boolean isCacheEnable() {
|
||||
return cacheEnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证码生产类
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
public Captcha getCaptcha() {
|
||||
if (Objects.isNull(loginCode)) {
|
||||
loginCode = new LoginCode();
|
||||
if (Objects.isNull(loginCode.getCodeType())) {
|
||||
loginCode.setCodeType(LoginCodeEnum.ARITHMETIC);
|
||||
}
|
||||
}
|
||||
return switchCaptcha(loginCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* 依据配置信息生产验证码
|
||||
*
|
||||
* @param loginCode 验证码配置信息
|
||||
* @return /
|
||||
*/
|
||||
private Captcha switchCaptcha(LoginCode loginCode) {
|
||||
Captcha captcha;
|
||||
synchronized (this) {
|
||||
switch (loginCode.getCodeType()) {
|
||||
case ARITHMETIC:
|
||||
// 算术类型 https://gitee.com/whvse/EasyCaptcha
|
||||
captcha = new FixedArithmeticCaptcha(loginCode.getWidth(), loginCode.getHeight());
|
||||
// 几位数运算,默认是两位
|
||||
captcha.setLen(loginCode.getLength());
|
||||
break;
|
||||
case CHINESE:
|
||||
captcha = new ChineseCaptcha(loginCode.getWidth(), loginCode.getHeight());
|
||||
captcha.setLen(loginCode.getLength());
|
||||
break;
|
||||
case CHINESE_GIF:
|
||||
captcha = new ChineseGifCaptcha(loginCode.getWidth(), loginCode.getHeight());
|
||||
captcha.setLen(loginCode.getLength());
|
||||
break;
|
||||
case GIF:
|
||||
captcha = new GifCaptcha(loginCode.getWidth(), loginCode.getHeight());
|
||||
captcha.setLen(loginCode.getLength());
|
||||
break;
|
||||
case SPEC:
|
||||
captcha = new SpecCaptcha(loginCode.getWidth(), loginCode.getHeight());
|
||||
captcha.setLen(loginCode.getLength());
|
||||
break;
|
||||
default:
|
||||
throw new BadConfigurationException("验证码配置信息错误!正确配置查看 LoginCodeEnum ");
|
||||
}
|
||||
}
|
||||
if(StringUtils.isNotBlank(loginCode.getFontName())){
|
||||
captcha.setFont(new Font(loginCode.getFontName(), Font.PLAIN, loginCode.getFontSize()));
|
||||
}
|
||||
return captcha;
|
||||
}
|
||||
|
||||
static class FixedArithmeticCaptcha extends ArithmeticCaptcha {
|
||||
public FixedArithmeticCaptcha(int width, int height) {
|
||||
super(width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected char[] alphas() {
|
||||
// 生成随机数字和运算符
|
||||
int n1 = num(1, 10), n2 = num(1, 10);
|
||||
int opt = num(3);
|
||||
|
||||
// 计算结果
|
||||
int res = new int[]{n1 + n2, n1 - n2, n1 * n2}[opt];
|
||||
// 转换为字符运算符
|
||||
char optChar = "+-x".charAt(opt);
|
||||
|
||||
this.setArithmeticString(String.format("%s%c%s=?", n1, optChar, n2));
|
||||
this.chars = String.valueOf(res);
|
||||
|
||||
return chars.toCharArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.config.bean;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* Jwt参数配置
|
||||
*
|
||||
*
|
||||
* 2019年11月28日
|
||||
*/
|
||||
@Data
|
||||
public class SecurityProperties {
|
||||
|
||||
/**
|
||||
* Request Headers : Authorization
|
||||
*/
|
||||
private String header;
|
||||
|
||||
/**
|
||||
* 令牌前缀,最后留个空格 Bearer
|
||||
*/
|
||||
private String tokenStartWith;
|
||||
|
||||
/**
|
||||
* 必须使用最少88位的Base64对该令牌进行编码
|
||||
*/
|
||||
private String base64Secret;
|
||||
|
||||
/**
|
||||
* 令牌过期时间 此处单位/毫秒
|
||||
*/
|
||||
private Long tokenValidityInSeconds;
|
||||
|
||||
/**
|
||||
* 在线用户 key,根据 key 查询 redis 中在线用户的数据
|
||||
*/
|
||||
private String onlineKey;
|
||||
|
||||
/**
|
||||
* 验证码 key
|
||||
*/
|
||||
private String codeKey;
|
||||
|
||||
/**
|
||||
* token 续期检查
|
||||
*/
|
||||
private Long detect;
|
||||
|
||||
/**
|
||||
* 续期时间
|
||||
*/
|
||||
private Long renew;
|
||||
|
||||
public String getTokenStartWith() {
|
||||
return tokenStartWith + " ";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.rest;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.wf.captcha.base.Captcha;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.example.annotation.rest.AnonymousDeleteMapping;
|
||||
import com.example.annotation.rest.AnonymousGetMapping;
|
||||
import com.example.annotation.rest.AnonymousPostMapping;
|
||||
import com.example.config.RsaProperties;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.security.config.bean.LoginCodeEnum;
|
||||
import com.example.modules.security.config.bean.LoginProperties;
|
||||
import com.example.modules.security.config.bean.SecurityProperties;
|
||||
import com.example.modules.security.security.TokenProvider;
|
||||
import com.example.modules.security.service.dto.AuthUserDto;
|
||||
import com.example.modules.security.service.dto.JwtUserDto;
|
||||
import com.example.modules.security.service.OnlineUserService;
|
||||
import com.example.utils.RsaUtils;
|
||||
import com.example.utils.RedisUtils;
|
||||
import com.example.utils.SecurityUtils;
|
||||
import com.example.utils.StringUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-11-23
|
||||
* 授权、根据token获取用户详细信息
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/auth")
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统:系统授权接口")
|
||||
public class AuthorizationController {
|
||||
private final SecurityProperties properties;
|
||||
private final RedisUtils redisUtils;
|
||||
private final OnlineUserService onlineUserService;
|
||||
private final TokenProvider tokenProvider;
|
||||
private final AuthenticationManagerBuilder authenticationManagerBuilder;
|
||||
@Resource
|
||||
private LoginProperties loginProperties;
|
||||
|
||||
@ApiOperation("登录授权")
|
||||
@AnonymousPostMapping(value = "/login")
|
||||
public ResponseEntity<Object> login(@Validated @RequestBody AuthUserDto authUser, HttpServletRequest request) throws Exception {
|
||||
// 密码解密
|
||||
String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey, authUser.getPassword());
|
||||
//去除验证码功能
|
||||
/* // 查询验证码
|
||||
String code = (String) redisUtils.get(authUser.getUuid());
|
||||
// 清除验证码
|
||||
redisUtils.del(authUser.getUuid());
|
||||
if (StringUtils.isBlank(code)) {
|
||||
throw new BadRequestException("验证码不存在或已过期");
|
||||
}
|
||||
if (StringUtils.isBlank(authUser.getCode()) || !authUser.getCode().equalsIgnoreCase(code)) {
|
||||
throw new BadRequestException("验证码错误");
|
||||
}*/
|
||||
UsernamePasswordAuthenticationToken authenticationToken =
|
||||
new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);
|
||||
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 生成令牌与第三方系统获取令牌方式
|
||||
// UserDetails userDetails = userDetailsService.loadUserByUsername(userInfo.getUsername());
|
||||
// Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
// SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
String token = tokenProvider.createToken(authentication);
|
||||
final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
|
||||
// 保存在线信息
|
||||
onlineUserService.save(jwtUserDto, token, request);
|
||||
// 返回 token 与 用户信息
|
||||
Map<String, Object> authInfo = new HashMap<String, Object>(2) {{
|
||||
put("token", properties.getTokenStartWith() + token);
|
||||
put("user", jwtUserDto);
|
||||
}};
|
||||
if (loginProperties.isSingleLogin()) {
|
||||
//踢掉之前已经登录的token
|
||||
onlineUserService.checkLoginOnUser(authUser.getUsername(), token);
|
||||
}
|
||||
return ResponseEntity.ok(authInfo);
|
||||
}
|
||||
|
||||
@ApiOperation("获取用户信息")
|
||||
@GetMapping(value = "/info")
|
||||
public ResponseEntity<Object> getUserInfo() {
|
||||
return ResponseEntity.ok(SecurityUtils.getCurrentUser());
|
||||
}
|
||||
|
||||
@ApiOperation("获取验证码")
|
||||
@AnonymousGetMapping(value = "/code")
|
||||
public ResponseEntity<Object> getCode() {
|
||||
// 获取运算的结果
|
||||
Captcha captcha = loginProperties.getCaptcha();
|
||||
String uuid = properties.getCodeKey() + IdUtil.simpleUUID();
|
||||
//当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
|
||||
String captchaValue = captcha.text();
|
||||
if (captcha.getCharType() - 1 == LoginCodeEnum.ARITHMETIC.ordinal() && captchaValue.contains(".")) {
|
||||
captchaValue = captchaValue.split("\\.")[0];
|
||||
}
|
||||
// 保存
|
||||
redisUtils.set(uuid, captchaValue, loginProperties.getLoginCode().getExpiration(), TimeUnit.MINUTES);
|
||||
// 验证码信息
|
||||
Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
|
||||
put("img", captcha.toBase64());
|
||||
put("uuid", uuid);
|
||||
}};
|
||||
return ResponseEntity.ok(imgResult);
|
||||
}
|
||||
|
||||
@ApiOperation("退出登录")
|
||||
@AnonymousDeleteMapping(value = "/logout")
|
||||
public ResponseEntity<Object> logout(HttpServletRequest request) {
|
||||
onlineUserService.logout(tokenProvider.getToken(request));
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.rest;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.modules.security.service.OnlineUserService;
|
||||
import com.example.utils.EncryptUtils;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@RequestMapping("/auth/online")
|
||||
@Api(tags = "系统:在线用户管理")
|
||||
public class OnlineController {
|
||||
|
||||
private final OnlineUserService onlineUserService;
|
||||
|
||||
@ApiOperation("查询在线用户")
|
||||
@GetMapping
|
||||
@PreAuthorize("@el.check()")
|
||||
public ResponseEntity<Object> queryOnlineUser(String filter, Pageable pageable){
|
||||
return new ResponseEntity<>(onlineUserService.getAll(filter, pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("导出数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check()")
|
||||
public void exportOnlineUser(HttpServletResponse response, String filter) throws IOException {
|
||||
onlineUserService.download(onlineUserService.getAll(filter), response);
|
||||
}
|
||||
|
||||
@ApiOperation("踢出用户")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@el.check()")
|
||||
public ResponseEntity<Object> deleteOnlineUser(@RequestBody Set<String> keys) throws Exception {
|
||||
for (String key : keys) {
|
||||
// 解密Key
|
||||
key = EncryptUtils.desDecrypt(key);
|
||||
onlineUserService.kickOut(key);
|
||||
}
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.security;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class JwtAccessDeniedHandler implements AccessDeniedHandler {
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException {
|
||||
//当用户在没有授权的情况下访问受保护的REST资源时,将调用此方法发送403 Forbidden响应
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, accessDeniedException.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.security;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request,
|
||||
HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException {
|
||||
// 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.security;
|
||||
|
||||
import com.example.modules.security.config.bean.SecurityProperties;
|
||||
import com.example.modules.security.service.OnlineUserService;
|
||||
import com.example.modules.security.service.UserCacheClean;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
|
||||
/**
|
||||
* @author /
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class TokenConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
|
||||
|
||||
private final TokenProvider tokenProvider;
|
||||
private final SecurityProperties properties;
|
||||
private final OnlineUserService onlineUserService;
|
||||
private final UserCacheClean userCacheClean;
|
||||
|
||||
@Override
|
||||
public void configure(HttpSecurity http) {
|
||||
TokenFilter customFilter = new TokenFilter(tokenProvider, properties, onlineUserService, userCacheClean);
|
||||
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.security;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.example.modules.security.config.bean.SecurityProperties;
|
||||
import com.example.modules.security.service.OnlineUserService;
|
||||
import com.example.modules.security.service.UserCacheClean;
|
||||
import com.example.modules.security.service.dto.OnlineUserDto;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.filter.GenericFilterBean;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author /
|
||||
*/
|
||||
public class TokenFilter extends GenericFilterBean {
|
||||
private static final Logger log = LoggerFactory.getLogger(TokenFilter.class);
|
||||
|
||||
|
||||
private final TokenProvider tokenProvider;
|
||||
private final SecurityProperties properties;
|
||||
private final OnlineUserService onlineUserService;
|
||||
private final UserCacheClean userCacheClean;
|
||||
|
||||
/**
|
||||
* @param tokenProvider Token
|
||||
* @param properties JWT
|
||||
* @param onlineUserService 用户在线
|
||||
* @param userCacheClean 用户缓存清理工具
|
||||
*/
|
||||
public TokenFilter(TokenProvider tokenProvider, SecurityProperties properties, OnlineUserService onlineUserService, UserCacheClean userCacheClean) {
|
||||
this.properties = properties;
|
||||
this.onlineUserService = onlineUserService;
|
||||
this.tokenProvider = tokenProvider;
|
||||
this.userCacheClean = userCacheClean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
|
||||
String token = resolveToken(httpServletRequest);
|
||||
// 对于 Token 为空的不需要去查 Redis
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
OnlineUserDto onlineUserDto = null;
|
||||
boolean cleanUserCache = false;
|
||||
try {
|
||||
onlineUserDto = onlineUserService.getOne(properties.getOnlineKey() + token);
|
||||
} catch (ExpiredJwtException e) {
|
||||
log.error(e.getMessage());
|
||||
cleanUserCache = true;
|
||||
} finally {
|
||||
if (cleanUserCache || Objects.isNull(onlineUserDto)) {
|
||||
userCacheClean.cleanUserCache(String.valueOf(tokenProvider.getClaims(token).get(TokenProvider.AUTHORITIES_KEY)));
|
||||
}
|
||||
}
|
||||
if (onlineUserDto != null && StringUtils.hasText(token)) {
|
||||
Authentication authentication = tokenProvider.getAuthentication(token);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// Token 续期
|
||||
tokenProvider.checkRenewal(token);
|
||||
}
|
||||
}
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初步检测Token
|
||||
*
|
||||
* @param request /
|
||||
* @return /
|
||||
*/
|
||||
private String resolveToken(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader(properties.getHeader());
|
||||
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(properties.getTokenStartWith())) {
|
||||
// 去掉令牌前缀
|
||||
return bearerToken.replace(properties.getTokenStartWith(), "");
|
||||
} else {
|
||||
log.debug("非法Token:{}", bearerToken);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.security;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.example.modules.security.config.bean.SecurityProperties;
|
||||
import com.example.utils.RedisUtils;
|
||||
import io.jsonwebtoken.*;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.stereotype.Component;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.security.Key;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* @author /
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TokenProvider implements InitializingBean {
|
||||
|
||||
private final SecurityProperties properties;
|
||||
private final RedisUtils redisUtils;
|
||||
public static final String AUTHORITIES_KEY = "user";
|
||||
private JwtParser jwtParser;
|
||||
private JwtBuilder jwtBuilder;
|
||||
|
||||
public TokenProvider(SecurityProperties properties, RedisUtils redisUtils) {
|
||||
this.properties = properties;
|
||||
this.redisUtils = redisUtils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
|
||||
Key key = Keys.hmacShaKeyFor(keyBytes);
|
||||
jwtParser = Jwts.parserBuilder()
|
||||
.setSigningKey(key)
|
||||
.build();
|
||||
jwtBuilder = Jwts.builder()
|
||||
.signWith(key, SignatureAlgorithm.HS512);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建Token 设置永不过期,
|
||||
* Token 的时间有效性转到Redis 维护
|
||||
*
|
||||
* @param authentication /
|
||||
* @return /
|
||||
*/
|
||||
public String createToken(Authentication authentication) {
|
||||
return jwtBuilder
|
||||
// 加入ID确保生成的 Token 都不一致
|
||||
.setId(IdUtil.simpleUUID())
|
||||
.claim(AUTHORITIES_KEY, authentication.getName())
|
||||
.setSubject(authentication.getName())
|
||||
.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* 依据Token 获取鉴权信息
|
||||
*
|
||||
* @param token /
|
||||
* @return /
|
||||
*/
|
||||
Authentication getAuthentication(String token) {
|
||||
Claims claims = getClaims(token);
|
||||
User principal = new User(claims.getSubject(), "******", new ArrayList<>());
|
||||
return new UsernamePasswordAuthenticationToken(principal, token, new ArrayList<>());
|
||||
}
|
||||
|
||||
public Claims getClaims(String token) {
|
||||
return jwtParser
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param token 需要检查的token
|
||||
*/
|
||||
public void checkRenewal(String token) {
|
||||
// 判断是否续期token,计算token的过期时间
|
||||
long time = redisUtils.getExpire(properties.getOnlineKey() + token) * 1000;
|
||||
Date expireDate = DateUtil.offset(new Date(), DateField.MILLISECOND, (int) time);
|
||||
// 判断当前时间与过期时间的时间差
|
||||
long differ = expireDate.getTime() - System.currentTimeMillis();
|
||||
// 如果在续期检查的范围内,则续期
|
||||
if (differ <= properties.getDetect()) {
|
||||
long renew = time + properties.getRenew();
|
||||
redisUtils.expire(properties.getOnlineKey() + token, renew, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
public String getToken(HttpServletRequest request) {
|
||||
final String requestHeader = request.getHeader(properties.getHeader());
|
||||
if (requestHeader != null && requestHeader.startsWith(properties.getTokenStartWith())) {
|
||||
return requestHeader.substring(7);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.service;
|
||||
|
||||
import com.example.modules.security.config.bean.SecurityProperties;
|
||||
import com.example.utils.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.example.modules.security.service.dto.JwtUserDto;
|
||||
import com.example.modules.security.service.dto.OnlineUserDto;
|
||||
import com.example.utils.*;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019年10月26日21:56:27
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class OnlineUserService {
|
||||
|
||||
private final SecurityProperties properties;
|
||||
private final RedisUtils redisUtils;
|
||||
|
||||
public OnlineUserService(SecurityProperties properties, RedisUtils redisUtils) {
|
||||
this.properties = properties;
|
||||
this.redisUtils = redisUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存在线用户信息
|
||||
* @param jwtUserDto /
|
||||
* @param token /
|
||||
* @param request /
|
||||
*/
|
||||
public void save(JwtUserDto jwtUserDto, String token, HttpServletRequest request){
|
||||
String dept = jwtUserDto.getUser().getDept().getName();
|
||||
String ip = StringUtils.getIp(request);
|
||||
String browser = StringUtils.getBrowser(request);
|
||||
String address = StringUtils.getCityInfo(ip);
|
||||
OnlineUserDto onlineUserDto = null;
|
||||
try {
|
||||
onlineUserDto = new OnlineUserDto(jwtUserDto.getUsername(), jwtUserDto.getUser().getNickName(), dept, browser , ip, address, EncryptUtils.desEncrypt(token), new Date());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(),e);
|
||||
}
|
||||
redisUtils.set(properties.getOnlineKey() + token, onlineUserDto, properties.getTokenValidityInSeconds()/1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
* @param filter /
|
||||
* @param pageable /
|
||||
* @return /
|
||||
*/
|
||||
public Map<String,Object> getAll(String filter, Pageable pageable){
|
||||
List<OnlineUserDto> onlineUserDtos = getAll(filter);
|
||||
return PageUtil.toPage(
|
||||
PageUtil.toPage(pageable.getPageNumber(),pageable.getPageSize(), onlineUserDtos),
|
||||
onlineUserDtos.size()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询全部数据,不分页
|
||||
* @param filter /
|
||||
* @return /
|
||||
*/
|
||||
public List<OnlineUserDto> getAll(String filter){
|
||||
List<String> keys = redisUtils.scan(properties.getOnlineKey() + "*");
|
||||
Collections.reverse(keys);
|
||||
List<OnlineUserDto> onlineUserDtos = new ArrayList<>();
|
||||
for (String key : keys) {
|
||||
OnlineUserDto onlineUserDto = (OnlineUserDto) redisUtils.get(key);
|
||||
if(StringUtils.isNotBlank(filter)){
|
||||
if(onlineUserDto.toString().contains(filter)){
|
||||
onlineUserDtos.add(onlineUserDto);
|
||||
}
|
||||
} else {
|
||||
onlineUserDtos.add(onlineUserDto);
|
||||
}
|
||||
}
|
||||
onlineUserDtos.sort((o1, o2) -> o2.getLoginTime().compareTo(o1.getLoginTime()));
|
||||
return onlineUserDtos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 踢出用户
|
||||
* @param key /
|
||||
*/
|
||||
public void kickOut(String key){
|
||||
key = properties.getOnlineKey() + key;
|
||||
redisUtils.del(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
* @param token /
|
||||
*/
|
||||
public void logout(String token) {
|
||||
String key = properties.getOnlineKey() + token;
|
||||
redisUtils.del(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出
|
||||
* @param all /
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
public void download(List<OnlineUserDto> all, HttpServletResponse response) throws IOException {
|
||||
List<Map<String, Object>> list = new ArrayList<>();
|
||||
for (OnlineUserDto user : all) {
|
||||
Map<String,Object> map = new LinkedHashMap<>();
|
||||
map.put("用户名", user.getUserName());
|
||||
map.put("部门", user.getDept());
|
||||
map.put("登录IP", user.getIp());
|
||||
map.put("登录地点", user.getAddress());
|
||||
map.put("浏览器", user.getBrowser());
|
||||
map.put("登录日期", user.getLoginTime());
|
||||
list.add(map);
|
||||
}
|
||||
FileUtil.downloadExcel(list, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户
|
||||
* @param key /
|
||||
* @return /
|
||||
*/
|
||||
public OnlineUserDto getOne(String key) {
|
||||
return (OnlineUserDto)redisUtils.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测用户是否在之前已经登录,已经登录踢下线
|
||||
* @param userName 用户名
|
||||
*/
|
||||
public void checkLoginOnUser(String userName, String igoreToken){
|
||||
List<OnlineUserDto> onlineUserDtos = getAll(userName);
|
||||
if(onlineUserDtos ==null || onlineUserDtos.isEmpty()){
|
||||
return;
|
||||
}
|
||||
for(OnlineUserDto onlineUserDto : onlineUserDtos){
|
||||
if(onlineUserDto.getUserName().equals(userName)){
|
||||
try {
|
||||
String token =EncryptUtils.desDecrypt(onlineUserDto.getKey());
|
||||
if(StringUtils.isNotBlank(igoreToken)&&!igoreToken.equals(token)){
|
||||
this.kickOut(token);
|
||||
}else if(StringUtils.isBlank(igoreToken)){
|
||||
this.kickOut(token);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("checkUser is error",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户名强退用户
|
||||
* @param username /
|
||||
*/
|
||||
@Async
|
||||
public void kickOutForUsername(String username) throws Exception {
|
||||
List<OnlineUserDto> onlineUsers = getAll(username);
|
||||
for (OnlineUserDto onlineUser : onlineUsers) {
|
||||
if (onlineUser.getUserName().equals(username)) {
|
||||
String token =EncryptUtils.desDecrypt(onlineUser.getKey());
|
||||
kickOut(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2019-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.modules.security.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import com.example.utils.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author: liaojinlong
|
||||
* : 2020/6/11 18:01
|
||||
* @apiNote: 用于清理 用户登录信息缓存,为防止Spring循环依赖与安全考虑 ,单独构成工具类
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class UserCacheClean {
|
||||
|
||||
private final UserCacheManager userCacheManager;
|
||||
|
||||
/**
|
||||
* 清理特定用户缓存信息<br>
|
||||
* 用户信息变更时
|
||||
*
|
||||
* @param userName /
|
||||
*/
|
||||
public void cleanUserCache(String userName) {
|
||||
if (StringUtils.isNotEmpty(userName)) {
|
||||
userCacheManager.remove(userName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理所有用户的缓存信息<br>
|
||||
* ,如发生角色授权信息变化,可以简便的全部失效缓存
|
||||
*/
|
||||
public void cleanAll() {
|
||||
userCacheManager.clear();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package com.example.modules.security.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import com.example.modules.security.service.dto.JwtUserDto;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* 用户缓存
|
||||
*
|
||||
* @author TikiWong
|
||||
* 2022/1/27 8:23
|
||||
**/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class UserCacheManager {
|
||||
|
||||
@Value("${user-cache.min-evictable-size}")
|
||||
private int minEvictableSize;
|
||||
@Value("${user-cache.min-evictable-interval}")
|
||||
private long minEvictableInterval;
|
||||
@Value("${user-cache.min-idle-time}")
|
||||
private long minIdleTime;
|
||||
|
||||
private final Map<String, Node> cache = new ConcurrentHashMap<>();
|
||||
private final AtomicBoolean expelLock = new AtomicBoolean(true);
|
||||
private long nextMinEvictableTime = 0;
|
||||
|
||||
public Future<JwtUserDto> putIfAbsent(String username, Future<JwtUserDto> ft) {
|
||||
Node tryNode = new Node(ft);
|
||||
Node node = cache.putIfAbsent(username, tryNode);
|
||||
expel();
|
||||
return nodeToDate(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存回收
|
||||
* 为避免超过边界后回收热点数据设置了最小生存时间
|
||||
* 回收时会保留在最小生存时间内的数据
|
||||
**/
|
||||
public void expel() {
|
||||
long now = System.currentTimeMillis();
|
||||
if (cache.size() < minEvictableSize ||
|
||||
now < nextMinEvictableTime ||
|
||||
!expelLock.compareAndSet(true, false)) {
|
||||
return;
|
||||
}
|
||||
long oldestTime = now;
|
||||
int evictedCount = 0;
|
||||
try {
|
||||
Iterator<Map.Entry<String, Node>> iterator = cache.entrySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Map.Entry<String, Node> entry = iterator.next();
|
||||
long nodeTime = entry.getValue().getTime();
|
||||
if (nodeTime + minIdleTime < now) {
|
||||
iterator.remove();
|
||||
evictedCount++;
|
||||
}
|
||||
oldestTime = Math.min(oldestTime, nodeTime);
|
||||
}
|
||||
} finally {
|
||||
this.nextMinEvictableTime = Math.max(now + minEvictableInterval, oldestTime);
|
||||
expelLock.set(true);
|
||||
log.info("回收掉【{}】条用户缓存, 剩余缓存数为【{}】,下次可回收时间为【{}】秒后",
|
||||
evictedCount,
|
||||
cache.size(),
|
||||
(this.nextMinEvictableTime - now) / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
public Future<JwtUserDto> get(String username) {
|
||||
return nodeToDate(cache.get(username));
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
public void remove(String username) {
|
||||
cache.remove(username);
|
||||
}
|
||||
|
||||
private Future<JwtUserDto> nodeToDate(Node node) {
|
||||
return node == null ? null : node.getData();
|
||||
}
|
||||
|
||||
private static class Node {
|
||||
private final Future<JwtUserDto> data;
|
||||
private final long time;
|
||||
|
||||
public Node(Future<JwtUserDto> data) {
|
||||
this.data = data;
|
||||
this.time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public Future<JwtUserDto> getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.service;
|
||||
|
||||
import com.example.modules.security.config.bean.LoginProperties;
|
||||
import com.example.modules.system.service.DataService;
|
||||
import com.example.modules.system.service.RoleService;
|
||||
import com.example.modules.system.service.UserService;
|
||||
import com.example.modules.system.service.dto.UserDto;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.exception.EntityNotFoundException;
|
||||
import com.example.modules.security.service.dto.JwtUserDto;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-11-22
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Service("userDetailsService")
|
||||
public class UserDetailsServiceImpl implements UserDetailsService {
|
||||
private final UserService userService;
|
||||
private final RoleService roleService;
|
||||
private final DataService dataService;
|
||||
private final LoginProperties loginProperties;
|
||||
|
||||
private final UserCacheManager USER_DTO_CACHE;
|
||||
|
||||
public void setEnableCache(boolean enableCache) {
|
||||
this.loginProperties.setCacheEnable(enableCache);
|
||||
}
|
||||
|
||||
public static ExecutorService executor = newThreadPool();
|
||||
|
||||
@Override
|
||||
public JwtUserDto loadUserByUsername(String username) {
|
||||
JwtUserDto jwtUserDto = null;
|
||||
Future<JwtUserDto> future = USER_DTO_CACHE.get(username);
|
||||
if (!loginProperties.isCacheEnable()) {
|
||||
UserDto user;
|
||||
try {
|
||||
user = userService.findByName(username);
|
||||
} catch (EntityNotFoundException e) {
|
||||
// SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException
|
||||
throw new UsernameNotFoundException(username, e);
|
||||
}
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("");
|
||||
} else {
|
||||
if (!user.getEnabled()) {
|
||||
throw new BadRequestException("账号未激活!");
|
||||
}
|
||||
jwtUserDto = new JwtUserDto(
|
||||
user,
|
||||
dataService.getDeptIds(user),
|
||||
roleService.mapToGrantedAuthorities(user)
|
||||
);
|
||||
}
|
||||
return jwtUserDto;
|
||||
}
|
||||
|
||||
if (future == null) {
|
||||
Callable<JwtUserDto> call = () -> getJwtBySearchDb(username);
|
||||
FutureTask<JwtUserDto> ft = new FutureTask<>(call);
|
||||
future = USER_DTO_CACHE.putIfAbsent(username, ft);
|
||||
if (future == null) {
|
||||
future = ft;
|
||||
executor.submit(ft);
|
||||
}
|
||||
try {
|
||||
return future.get();
|
||||
} catch (CancellationException e) {
|
||||
USER_DTO_CACHE.remove(username);
|
||||
System.out.println("error" + Thread.currentThread().getName());
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
jwtUserDto = future.get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
// 检查dataScope是否修改
|
||||
List<Long> dataScopes = jwtUserDto.getDataScopes();
|
||||
dataScopes.clear();
|
||||
dataScopes.addAll(dataService.getDeptIds(jwtUserDto.getUser()));
|
||||
|
||||
}
|
||||
return jwtUserDto;
|
||||
|
||||
}
|
||||
|
||||
private JwtUserDto getJwtBySearchDb(String username) {
|
||||
UserDto user;
|
||||
try {
|
||||
user = userService.findByName(username);
|
||||
} catch (EntityNotFoundException e) {
|
||||
// SpringSecurity会自动转换UsernameNotFoundException为BadCredentialsException
|
||||
throw new UsernameNotFoundException("", e);
|
||||
}
|
||||
if (user == null) {
|
||||
throw new UsernameNotFoundException("");
|
||||
} else {
|
||||
if (!user.getEnabled()) {
|
||||
throw new BadRequestException("账号未激活!");
|
||||
}
|
||||
return new JwtUserDto(
|
||||
user,
|
||||
dataService.getDeptIds(user),
|
||||
roleService.mapToGrantedAuthorities(user)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static ExecutorService newThreadPool() {
|
||||
ThreadFactory namedThreadFactory = new ThreadFactory() {
|
||||
final AtomicInteger sequence = new AtomicInteger(1);
|
||||
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r);
|
||||
int seq = this.sequence.getAndIncrement();
|
||||
thread.setName("future-task-thread" + (seq > 1 ? "-" + seq : ""));
|
||||
if (!thread.isDaemon()) {
|
||||
thread.setDaemon(true);
|
||||
}
|
||||
|
||||
return thread;
|
||||
}
|
||||
};
|
||||
return new ThreadPoolExecutor(10, 200,
|
||||
0L, TimeUnit.MILLISECONDS,
|
||||
new LinkedBlockingQueue<>(1024),
|
||||
namedThreadFactory,
|
||||
new ThreadPoolExecutor.AbortPolicy());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.service.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-11-30
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class AuthUserDto {
|
||||
|
||||
@NotBlank
|
||||
private String username;
|
||||
|
||||
@NotBlank
|
||||
private String password;
|
||||
|
||||
private String code;
|
||||
|
||||
private String uuid = "";
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.service.dto;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.example.modules.system.service.dto.UserDto;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public class JwtUserDto implements UserDetails {
|
||||
|
||||
private final UserDto user;
|
||||
|
||||
private final List<Long> dataScopes;
|
||||
|
||||
@JSONField(serialize = false)
|
||||
private final List<GrantedAuthority> authorities;
|
||||
|
||||
public Set<String> getRoles() {
|
||||
return authorities.stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
@JSONField(serialize = false)
|
||||
public String getPassword() {
|
||||
return user.getPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
@JSONField(serialize = false)
|
||||
public String getUsername() {
|
||||
return user.getUsername();
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@JSONField(serialize = false)
|
||||
public boolean isEnabled() {
|
||||
return user.getEnabled();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.security.service.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 在线用户
|
||||
*
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class OnlineUserDto {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 岗位
|
||||
*/
|
||||
private String dept;
|
||||
|
||||
/**
|
||||
* 浏览器
|
||||
*/
|
||||
private String browser;
|
||||
|
||||
/**
|
||||
* IP
|
||||
*/
|
||||
private String ip;
|
||||
|
||||
/**
|
||||
* 地址
|
||||
*/
|
||||
private String address;
|
||||
|
||||
/**
|
||||
* token
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 登录时间
|
||||
*/
|
||||
private Date loginTime;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.example.modules.system.domain.Dept;
|
||||
import com.example.modules.system.service.DeptService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.Log;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.system.service.dto.DeptDto;
|
||||
import com.example.modules.system.service.dto.DeptQueryCriteria;
|
||||
import com.example.utils.PageUtil;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-25
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统:部门管理")
|
||||
@RequestMapping("/api/dept")
|
||||
public class DeptController {
|
||||
|
||||
private final DeptService deptService;
|
||||
private static final String ENTITY_NAME = "dept";
|
||||
|
||||
@ApiOperation("导出部门数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('dept:list')")
|
||||
public void exportDept(HttpServletResponse response, DeptQueryCriteria criteria) throws Exception {
|
||||
deptService.download(deptService.queryAll(criteria, false), response);
|
||||
}
|
||||
|
||||
@ApiOperation("查询部门")
|
||||
@GetMapping
|
||||
@PreAuthorize("@el.check('user:list','dept:list')")
|
||||
public ResponseEntity<Object> queryDept(DeptQueryCriteria criteria) throws Exception {
|
||||
List<DeptDto> deptDtos = deptService.queryAll(criteria, true);
|
||||
return new ResponseEntity<>(PageUtil.toPage(deptDtos, deptDtos.size()),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("查询部门:根据ID获取同级与上级数据")
|
||||
@PostMapping("/superior")
|
||||
@PreAuthorize("@el.check('user:list','dept:list')")
|
||||
public ResponseEntity<Object> getDeptSuperior(@RequestBody List<Long> ids) {
|
||||
Set<DeptDto> deptDtos = new LinkedHashSet<>();
|
||||
for (Long id : ids) {
|
||||
DeptDto deptDto = deptService.findById(id);
|
||||
List<DeptDto> depts = deptService.getSuperior(deptDto, new ArrayList<>());
|
||||
deptDtos.addAll(depts);
|
||||
}
|
||||
return new ResponseEntity<>(deptService.buildTree(new ArrayList<>(deptDtos)),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("新增部门")
|
||||
@ApiOperation("新增部门")
|
||||
@PostMapping
|
||||
@PreAuthorize("@el.check('dept:add')")
|
||||
public ResponseEntity<Object> createDept(@Validated @RequestBody Dept resources){
|
||||
if (resources.getId() != null) {
|
||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||
}
|
||||
deptService.create(resources);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("修改部门")
|
||||
@ApiOperation("修改部门")
|
||||
@PutMapping
|
||||
@PreAuthorize("@el.check('dept:edit')")
|
||||
public ResponseEntity<Object> updateDept(@Validated(Dept.Update.class) @RequestBody Dept resources){
|
||||
deptService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除部门")
|
||||
@ApiOperation("删除部门")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@el.check('dept:del')")
|
||||
public ResponseEntity<Object> deleteDept(@RequestBody Set<Long> ids){
|
||||
Set<DeptDto> deptDtos = new HashSet<>();
|
||||
for (Long id : ids) {
|
||||
List<Dept> deptList = deptService.findByPid(id);
|
||||
deptDtos.add(deptService.findById(id));
|
||||
if(CollectionUtil.isNotEmpty(deptList)){
|
||||
deptDtos = deptService.getDeleteDepts(deptList, deptDtos);
|
||||
}
|
||||
}
|
||||
// 验证是否被角色或用户关联
|
||||
deptService.verification(deptDtos);
|
||||
deptService.delete(deptDtos);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import com.example.modules.system.domain.Dict;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.Log;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.system.service.DictService;
|
||||
import com.example.modules.system.service.dto.DictQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统:字典管理")
|
||||
@RequestMapping("/api/dict")
|
||||
public class DictController {
|
||||
|
||||
private final DictService dictService;
|
||||
private static final String ENTITY_NAME = "dict";
|
||||
|
||||
@ApiOperation("导出字典数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('dict:list')")
|
||||
public void exportDict(HttpServletResponse response, DictQueryCriteria criteria) throws IOException {
|
||||
dictService.download(dictService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@ApiOperation("查询字典")
|
||||
@GetMapping(value = "/all")
|
||||
@PreAuthorize("@el.check('dict:list')")
|
||||
public ResponseEntity<Object> queryAllDict(){
|
||||
return new ResponseEntity<>(dictService.queryAll(new DictQueryCriteria()),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("查询字典")
|
||||
@GetMapping
|
||||
@PreAuthorize("@el.check('dict:list')")
|
||||
public ResponseEntity<Object> queryDict(DictQueryCriteria resources, Pageable pageable){
|
||||
return new ResponseEntity<>(dictService.queryAll(resources,pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("新增字典")
|
||||
@ApiOperation("新增字典")
|
||||
@PostMapping
|
||||
@PreAuthorize("@el.check('dict:add')")
|
||||
public ResponseEntity<Object> createDict(@Validated @RequestBody Dict resources){
|
||||
if (resources.getId() != null) {
|
||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||
}
|
||||
dictService.create(resources);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("修改字典")
|
||||
@ApiOperation("修改字典")
|
||||
@PutMapping
|
||||
@PreAuthorize("@el.check('dict:edit')")
|
||||
public ResponseEntity<Object> updateDict(@Validated(Dict.Update.class) @RequestBody Dict resources){
|
||||
dictService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除字典")
|
||||
@ApiOperation("删除字典")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@el.check('dict:del')")
|
||||
public ResponseEntity<Object> deleteDict(@RequestBody Set<Long> ids){
|
||||
dictService.delete(ids);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import com.example.modules.system.domain.DictDetail;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.Log;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.system.service.DictDetailService;
|
||||
import com.example.modules.system.service.dto.DictDetailDto;
|
||||
import com.example.modules.system.service.dto.DictDetailQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统:字典详情管理")
|
||||
@RequestMapping("/api/dictDetail")
|
||||
public class DictDetailController {
|
||||
|
||||
private final DictDetailService dictDetailService;
|
||||
private static final String ENTITY_NAME = "dictDetail";
|
||||
|
||||
@ApiOperation("查询字典详情")
|
||||
@GetMapping
|
||||
public ResponseEntity<Object> queryDictDetail(DictDetailQueryCriteria criteria,
|
||||
@PageableDefault(sort = {"dictSort"}, direction = Sort.Direction.ASC) Pageable pageable){
|
||||
return new ResponseEntity<>(dictDetailService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("查询多个字典详情")
|
||||
@GetMapping(value = "/map")
|
||||
public ResponseEntity<Object> getDictDetailMaps(@RequestParam String dictName){
|
||||
String[] names = dictName.split("[,,]");
|
||||
Map<String, List<DictDetailDto>> dictMap = new HashMap<>(16);
|
||||
for (String name : names) {
|
||||
dictMap.put(name, dictDetailService.getDictByName(name));
|
||||
}
|
||||
return new ResponseEntity<>(dictMap, HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("新增字典详情")
|
||||
@ApiOperation("新增字典详情")
|
||||
@PostMapping
|
||||
@PreAuthorize("@el.check('dict:add')")
|
||||
public ResponseEntity<Object> createDictDetail(@Validated @RequestBody DictDetail resources){
|
||||
if (resources.getId() != null) {
|
||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||
}
|
||||
dictDetailService.create(resources);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("修改字典详情")
|
||||
@ApiOperation("修改字典详情")
|
||||
@PutMapping
|
||||
@PreAuthorize("@el.check('dict:edit')")
|
||||
public ResponseEntity<Object> updateDictDetail(@Validated(DictDetail.Update.class) @RequestBody DictDetail resources){
|
||||
dictDetailService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除字典详情")
|
||||
@ApiOperation("删除字典详情")
|
||||
@DeleteMapping(value = "/{id}")
|
||||
@PreAuthorize("@el.check('dict:del')")
|
||||
public ResponseEntity<Object> deleteDictDetail(@PathVariable Long id){
|
||||
dictDetailService.delete(id);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import com.example.modules.system.domain.Job;
|
||||
import com.example.modules.system.service.JobService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.Log;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.system.service.dto.JobQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-29
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统:岗位管理")
|
||||
@RequestMapping("/api/job")
|
||||
public class JobController {
|
||||
|
||||
private final JobService jobService;
|
||||
private static final String ENTITY_NAME = "job";
|
||||
|
||||
@ApiOperation("导出岗位数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('job:list')")
|
||||
public void exportJob(HttpServletResponse response, JobQueryCriteria criteria) throws IOException {
|
||||
jobService.download(jobService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@ApiOperation("查询岗位")
|
||||
@GetMapping
|
||||
@PreAuthorize("@el.check('job:list','user:list')")
|
||||
public ResponseEntity<Object> queryJob(JobQueryCriteria criteria, Pageable pageable){
|
||||
return new ResponseEntity<>(jobService.queryAll(criteria, pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("新增岗位")
|
||||
@ApiOperation("新增岗位")
|
||||
@PostMapping
|
||||
@PreAuthorize("@el.check('job:add')")
|
||||
public ResponseEntity<Object> createJob(@Validated @RequestBody Job resources){
|
||||
if (resources.getId() != null) {
|
||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||
}
|
||||
jobService.create(resources);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("修改岗位")
|
||||
@ApiOperation("修改岗位")
|
||||
@PutMapping
|
||||
@PreAuthorize("@el.check('job:edit')")
|
||||
public ResponseEntity<Object> updateJob(@Validated(Job.Update.class) @RequestBody Job resources){
|
||||
jobService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除岗位")
|
||||
@ApiOperation("删除岗位")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@el.check('job:del')")
|
||||
public ResponseEntity<Object> deleteJob(@RequestBody Set<Long> ids){
|
||||
// 验证是否被用户关联
|
||||
jobService.verification(ids);
|
||||
jobService.delete(ids);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import com.example.annotation.Limit;
|
||||
import com.example.annotation.rest.AnonymousGetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @author /
|
||||
* 接口限流测试类
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/limit")
|
||||
@Api(tags = "系统:限流测试管理")
|
||||
public class LimitController {
|
||||
|
||||
private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test,
|
||||
*/
|
||||
@AnonymousGetMapping
|
||||
@ApiOperation("测试")
|
||||
@Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit")
|
||||
public int testLimit() {
|
||||
return ATOMIC_INTEGER.incrementAndGet();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.example.modules.system.domain.Menu;
|
||||
import com.example.modules.system.service.MenuService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.Log;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.system.service.dto.MenuDto;
|
||||
import com.example.modules.system.service.dto.MenuQueryCriteria;
|
||||
import com.example.modules.system.service.mapstruct.MenuMapper;
|
||||
import com.example.utils.PageUtil;
|
||||
import com.example.utils.SecurityUtils;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-03
|
||||
*/
|
||||
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统:菜单管理")
|
||||
@RequestMapping("/api/menus")
|
||||
public class MenuController {
|
||||
|
||||
private final MenuService menuService;
|
||||
private final MenuMapper menuMapper;
|
||||
private static final String ENTITY_NAME = "menu";
|
||||
|
||||
@ApiOperation("导出菜单数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('menu:list')")
|
||||
public void exportMenu(HttpServletResponse response, MenuQueryCriteria criteria) throws Exception {
|
||||
menuService.download(menuService.queryAll(criteria, false), response);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/build")
|
||||
@ApiOperation("获取前端所需菜单")
|
||||
public ResponseEntity<Object> buildMenus(){
|
||||
List<MenuDto> menuDtoList = menuService.findByUser(SecurityUtils.getCurrentUserId());
|
||||
List<MenuDto> menuDtos = menuService.buildTree(menuDtoList);
|
||||
return new ResponseEntity<>(menuService.buildMenus(menuDtos),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("返回全部的菜单")
|
||||
@GetMapping(value = "/lazy")
|
||||
@PreAuthorize("@el.check('menu:list','roles:list')")
|
||||
public ResponseEntity<Object> queryAllMenu(@RequestParam Long pid){
|
||||
return new ResponseEntity<>(menuService.getMenus(pid),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("根据菜单ID返回所有子节点ID,包含自身ID")
|
||||
@GetMapping(value = "/child")
|
||||
@PreAuthorize("@el.check('menu:list','roles:list')")
|
||||
public ResponseEntity<Object> childMenu(@RequestParam Long id){
|
||||
Set<Menu> menuSet = new HashSet<>();
|
||||
List<MenuDto> menuList = menuService.getMenus(id);
|
||||
menuSet.add(menuService.findOne(id));
|
||||
menuSet = menuService.getChildMenus(menuMapper.toEntity(menuList), menuSet);
|
||||
Set<Long> ids = menuSet.stream().map(Menu::getId).collect(Collectors.toSet());
|
||||
return new ResponseEntity<>(ids,HttpStatus.OK);
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("查询菜单")
|
||||
@PreAuthorize("@el.check('menu:list')")
|
||||
public ResponseEntity<Object> queryMenu(MenuQueryCriteria criteria) throws Exception {
|
||||
List<MenuDto> menuDtoList = menuService.queryAll(criteria, true);
|
||||
return new ResponseEntity<>(PageUtil.toPage(menuDtoList, menuDtoList.size()),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("查询菜单:根据ID获取同级与上级数据")
|
||||
@PostMapping("/superior")
|
||||
@PreAuthorize("@el.check('menu:list')")
|
||||
public ResponseEntity<Object> getMenuSuperior(@RequestBody List<Long> ids) {
|
||||
Set<MenuDto> menuDtos = new LinkedHashSet<>();
|
||||
if(CollectionUtil.isNotEmpty(ids)){
|
||||
for (Long id : ids) {
|
||||
MenuDto menuDto = menuService.findById(id);
|
||||
menuDtos.addAll(menuService.getSuperior(menuDto, new ArrayList<>()));
|
||||
}
|
||||
return new ResponseEntity<>(menuService.buildTree(new ArrayList<>(menuDtos)),HttpStatus.OK);
|
||||
}
|
||||
return new ResponseEntity<>(menuService.getMenus(null),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("新增菜单")
|
||||
@ApiOperation("新增菜单")
|
||||
@PostMapping
|
||||
@PreAuthorize("@el.check('menu:add')")
|
||||
public ResponseEntity<Object> createMenu(@Validated @RequestBody Menu resources){
|
||||
if (resources.getId() != null) {
|
||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||
}
|
||||
menuService.create(resources);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("修改菜单")
|
||||
@ApiOperation("修改菜单")
|
||||
@PutMapping
|
||||
@PreAuthorize("@el.check('menu:edit')")
|
||||
public ResponseEntity<Object> updateMenu(@Validated(Menu.Update.class) @RequestBody Menu resources){
|
||||
menuService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除菜单")
|
||||
@ApiOperation("删除菜单")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@el.check('menu:del')")
|
||||
public ResponseEntity<Object> deleteMenu(@RequestBody Set<Long> ids){
|
||||
Set<Menu> menuSet = new HashSet<>();
|
||||
for (Long id : ids) {
|
||||
List<MenuDto> menuList = menuService.getMenus(id);
|
||||
menuSet.add(menuService.findOne(id));
|
||||
menuSet = menuService.getChildMenus(menuMapper.toEntity(menuList), menuSet);
|
||||
}
|
||||
menuService.delete(menuSet);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.modules.system.service.MonitorService;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2020-05-02
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统-服务监控管理")
|
||||
@RequestMapping("/api/monitor")
|
||||
public class MonitorController {
|
||||
|
||||
private final MonitorService serverService;
|
||||
|
||||
@GetMapping
|
||||
@ApiOperation("查询服务监控")
|
||||
@PreAuthorize("@el.check('monitor:list')")
|
||||
public ResponseEntity<Object> queryMonitor(){
|
||||
return new ResponseEntity<>(serverService.getServers(),HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import com.example.modules.system.domain.Role;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.Log;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.system.service.RoleService;
|
||||
import com.example.modules.system.service.dto.RoleDto;
|
||||
import com.example.modules.system.service.dto.RoleQueryCriteria;
|
||||
import com.example.modules.system.service.dto.RoleSmallDto;
|
||||
import com.example.utils.SecurityUtils;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-03
|
||||
*/
|
||||
@RestController
|
||||
@RequiredArgsConstructor
|
||||
@Api(tags = "系统:角色管理")
|
||||
@RequestMapping("/api/roles")
|
||||
public class RoleController {
|
||||
|
||||
private final RoleService roleService;
|
||||
|
||||
private static final String ENTITY_NAME = "role";
|
||||
|
||||
@ApiOperation("获取单个role")
|
||||
@GetMapping(value = "/{id}")
|
||||
@PreAuthorize("@el.check('roles:list')")
|
||||
public ResponseEntity<Object> findRoleById(@PathVariable Long id){
|
||||
return new ResponseEntity<>(roleService.findById(id), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("导出角色数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('role:list')")
|
||||
public void exportRole(HttpServletResponse response, RoleQueryCriteria criteria) throws IOException {
|
||||
roleService.download(roleService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@ApiOperation("返回全部的角色")
|
||||
@GetMapping(value = "/all")
|
||||
@PreAuthorize("@el.check('roles:list','user:add','user:edit')")
|
||||
public ResponseEntity<Object> queryAllRole(){
|
||||
return new ResponseEntity<>(roleService.queryAll(),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("查询角色")
|
||||
@GetMapping
|
||||
@PreAuthorize("@el.check('roles:list')")
|
||||
public ResponseEntity<Object> queryRole(RoleQueryCriteria criteria, Pageable pageable){
|
||||
return new ResponseEntity<>(roleService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("获取用户级别")
|
||||
@GetMapping(value = "/level")
|
||||
public ResponseEntity<Object> getRoleLevel(){
|
||||
return new ResponseEntity<>(Dict.create().set("level", getLevels(null)),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("新增角色")
|
||||
@ApiOperation("新增角色")
|
||||
@PostMapping
|
||||
@PreAuthorize("@el.check('roles:add')")
|
||||
public ResponseEntity<Object> createRole(@Validated @RequestBody Role resources){
|
||||
if (resources.getId() != null) {
|
||||
throw new BadRequestException("A new "+ ENTITY_NAME +" cannot already have an ID");
|
||||
}
|
||||
getLevels(resources.getLevel());
|
||||
roleService.create(resources);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("修改角色")
|
||||
@ApiOperation("修改角色")
|
||||
@PutMapping
|
||||
@PreAuthorize("@el.check('roles:edit')")
|
||||
public ResponseEntity<Object> updateRole(@Validated(Role.Update.class) @RequestBody Role resources){
|
||||
getLevels(resources.getLevel());
|
||||
roleService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("修改角色菜单")
|
||||
@ApiOperation("修改角色菜单")
|
||||
@PutMapping(value = "/menu")
|
||||
@PreAuthorize("@el.check('roles:edit')")
|
||||
public ResponseEntity<Object> updateRoleMenu(@RequestBody Role resources){
|
||||
RoleDto role = roleService.findById(resources.getId());
|
||||
getLevels(role.getLevel());
|
||||
roleService.updateMenu(resources,role);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除角色")
|
||||
@ApiOperation("删除角色")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@el.check('roles:del')")
|
||||
public ResponseEntity<Object> deleteRole(@RequestBody Set<Long> ids){
|
||||
for (Long id : ids) {
|
||||
RoleDto role = roleService.findById(id);
|
||||
getLevels(role.getLevel());
|
||||
}
|
||||
// 验证是否被用户关联
|
||||
roleService.verification(ids);
|
||||
roleService.delete(ids);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的角色级别
|
||||
* @return /
|
||||
*/
|
||||
private int getLevels(Integer level){
|
||||
List<Integer> levels = roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList());
|
||||
int min = Collections.min(levels);
|
||||
if(level != null){
|
||||
if(level < min){
|
||||
throw new BadRequestException("权限不足,你的角色级别:" + min + ",低于操作的角色级别:" + level);
|
||||
}
|
||||
}
|
||||
return min;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.controller;
|
||||
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.example.modules.system.domain.Dept;
|
||||
import com.example.modules.system.domain.vo.UserPassVo;
|
||||
import com.example.modules.system.service.DataService;
|
||||
import com.example.modules.system.service.DeptService;
|
||||
import com.example.modules.system.service.UserService;
|
||||
import com.example.utils.PageUtil;
|
||||
import com.example.utils.RsaUtils;
|
||||
import com.example.utils.SecurityUtils;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import com.example.annotation.Log;
|
||||
import com.example.config.RsaProperties;
|
||||
import com.example.modules.system.domain.User;
|
||||
import com.example.exception.BadRequestException;
|
||||
import com.example.modules.system.service.RoleService;
|
||||
import com.example.modules.system.service.dto.RoleSmallDto;
|
||||
import com.example.modules.system.service.dto.UserDto;
|
||||
import com.example.modules.system.service.dto.UserQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Api(tags = "系统:用户管理")
|
||||
@RestController
|
||||
@RequestMapping("/api/users")
|
||||
@RequiredArgsConstructor
|
||||
public class UserController {
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
private final UserService userService;
|
||||
private final DataService dataService;
|
||||
private final DeptService deptService;
|
||||
private final RoleService roleService;
|
||||
|
||||
@ApiOperation("导出用户数据")
|
||||
@GetMapping(value = "/download")
|
||||
@PreAuthorize("@el.check('user:list')")
|
||||
public void exportUser(HttpServletResponse response, UserQueryCriteria criteria) throws IOException {
|
||||
userService.download(userService.queryAll(criteria), response);
|
||||
}
|
||||
|
||||
@ApiOperation("查询用户")
|
||||
@GetMapping
|
||||
@PreAuthorize("@el.check('user:list')")
|
||||
public ResponseEntity<Object> queryUser(UserQueryCriteria criteria, Pageable pageable){
|
||||
if (!ObjectUtils.isEmpty(criteria.getDeptId())) {
|
||||
criteria.getDeptIds().add(criteria.getDeptId());
|
||||
// 先查找是否存在子节点
|
||||
List<Dept> data = deptService.findByPid(criteria.getDeptId());
|
||||
// 然后把子节点的ID都加入到集合中
|
||||
criteria.getDeptIds().addAll(deptService.getDeptChildren(data));
|
||||
}
|
||||
// 数据权限
|
||||
List<Long> dataScopes = dataService.getDeptIds(userService.findByName(SecurityUtils.getCurrentUsername()));
|
||||
// criteria.getDeptIds() 不为空并且数据权限不为空则取交集
|
||||
if (!CollectionUtils.isEmpty(criteria.getDeptIds()) && !CollectionUtils.isEmpty(dataScopes)){
|
||||
// 取交集
|
||||
criteria.getDeptIds().retainAll(dataScopes);
|
||||
if(!CollectionUtil.isEmpty(criteria.getDeptIds())){
|
||||
return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
} else {
|
||||
// 否则取并集
|
||||
criteria.getDeptIds().addAll(dataScopes);
|
||||
return new ResponseEntity<>(userService.queryAll(criteria,pageable),HttpStatus.OK);
|
||||
}
|
||||
return new ResponseEntity<>(PageUtil.toPage(null,0),HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("新增用户")
|
||||
@ApiOperation("新增用户")
|
||||
@PostMapping
|
||||
@PreAuthorize("@el.check('user:add')")
|
||||
public ResponseEntity<Object> createUser(@Validated @RequestBody User resources){
|
||||
// checkLevel(resources);
|
||||
// 默认密码 123456
|
||||
resources.setPassword(passwordEncoder.encode("123456"));
|
||||
userService.create(resources);
|
||||
return new ResponseEntity<>(HttpStatus.CREATED);
|
||||
}
|
||||
|
||||
@Log("修改用户")
|
||||
@ApiOperation("修改用户")
|
||||
@PutMapping
|
||||
@PreAuthorize("@el.check('user:edit')")
|
||||
public ResponseEntity<Object> updateUser(@Validated(User.Update.class) @RequestBody User resources) throws Exception {
|
||||
checkLevel(resources);
|
||||
userService.update(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("修改用户:个人中心")
|
||||
@ApiOperation("修改用户:个人中心")
|
||||
@PutMapping(value = "center")
|
||||
public ResponseEntity<Object> centerUser(@Validated(User.Update.class) @RequestBody User resources){
|
||||
if(!resources.getId().equals(SecurityUtils.getCurrentUserId())){
|
||||
throw new BadRequestException("不能修改他人资料");
|
||||
}
|
||||
userService.updateCenter(resources);
|
||||
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
|
||||
}
|
||||
|
||||
@Log("删除用户")
|
||||
@ApiOperation("删除用户")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("@el.check('user:del')")
|
||||
public ResponseEntity<Object> deleteUser(@RequestBody Set<Long> ids){
|
||||
for (Long id : ids) {
|
||||
Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
|
||||
Integer optLevel = Collections.min(roleService.findByUsersId(id).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
|
||||
if (currentLevel > optLevel) {
|
||||
throw new BadRequestException("角色权限不足,不能删除:" + userService.findById(id).getUsername());
|
||||
}
|
||||
}
|
||||
userService.delete(ids);
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("修改密码")
|
||||
@PostMapping(value = "/updatePass")
|
||||
public ResponseEntity<Object> updateUserPass(@RequestBody UserPassVo passVo) throws Exception {
|
||||
String oldPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getOldPass());
|
||||
String newPass = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,passVo.getNewPass());
|
||||
UserDto user = userService.findByName(SecurityUtils.getCurrentUsername());
|
||||
if(!passwordEncoder.matches(oldPass, user.getPassword())){
|
||||
throw new BadRequestException("修改失败,旧密码错误");
|
||||
}
|
||||
if(passwordEncoder.matches(newPass, user.getPassword())){
|
||||
throw new BadRequestException("新密码不能与旧密码相同");
|
||||
}
|
||||
userService.updatePass(user.getUsername(),passwordEncoder.encode(newPass));
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@ApiOperation("修改头像")
|
||||
@PostMapping(value = "/updateAvatar")
|
||||
public ResponseEntity<Object> updateUserAvatar(@RequestParam MultipartFile avatar){
|
||||
return new ResponseEntity<>(userService.updateAvatar(avatar), HttpStatus.OK);
|
||||
}
|
||||
|
||||
@Log("修改邮箱")
|
||||
@ApiOperation("修改邮箱")
|
||||
@PostMapping(value = "/updateEmail/{code}")
|
||||
public ResponseEntity<Object> updateUserEmail(@PathVariable String code,@RequestBody User user) throws Exception {
|
||||
String password = RsaUtils.decryptByPrivateKey(RsaProperties.privateKey,user.getPassword());
|
||||
UserDto userDto = userService.findByName(SecurityUtils.getCurrentUsername());
|
||||
if(!passwordEncoder.matches(password, userDto.getPassword())){
|
||||
throw new BadRequestException("密码错误");
|
||||
}
|
||||
userService.updateEmail(userDto.getUsername(),user.getEmail());
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果当前用户的角色级别低于创建用户的角色级别,则抛出权限不足的错误
|
||||
* @param resources /
|
||||
*/
|
||||
private void checkLevel(User resources) {
|
||||
Integer currentLevel = Collections.min(roleService.findByUsersId(SecurityUtils.getCurrentUserId()).stream().map(RoleSmallDto::getLevel).collect(Collectors.toList()));
|
||||
Integer optLevel = roleService.findByRoles(resources.getRoles());
|
||||
if (currentLevel > optLevel) {
|
||||
throw new BadRequestException("角色权限不足");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseEntity;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-25
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name="sys_dept")
|
||||
public class Dept extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "dept_id")
|
||||
@NotNull(groups = Update.class)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@ManyToMany(mappedBy = "depts")
|
||||
@ApiModelProperty(value = "角色")
|
||||
private Set<Role> roles;
|
||||
|
||||
@ApiModelProperty(value = "排序")
|
||||
private Integer deptSort;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "部门名称")
|
||||
private String name;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "是否启用")
|
||||
private Boolean enabled;
|
||||
|
||||
@ApiModelProperty(value = "上级部门")
|
||||
private Long pid;
|
||||
|
||||
@ApiModelProperty(value = "子节点数目", hidden = true)
|
||||
private Integer subCount = 0;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Dept dept = (Dept) o;
|
||||
return Objects.equals(id, dept.id) &&
|
||||
Objects.equals(name, dept.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseEntity;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name="sys_dict")
|
||||
public class Dict extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "dict_id")
|
||||
@NotNull(groups = Update.class)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@OneToMany(mappedBy = "dict",cascade={CascadeType.PERSIST,CascadeType.REMOVE})
|
||||
private List<DictDetail> dictDetails;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "名称")
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "描述")
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseEntity;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name="sys_dict_detail")
|
||||
public class DictDetail extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "detail_id")
|
||||
@NotNull(groups = Update.class)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@JoinColumn(name = "dict_id")
|
||||
@ManyToOne(fetch=FetchType.LAZY)
|
||||
@ApiModelProperty(value = "字典", hidden = true)
|
||||
private Dict dict;
|
||||
|
||||
@ApiModelProperty(value = "字典标签")
|
||||
private String label;
|
||||
|
||||
@ApiModelProperty(value = "字典值")
|
||||
private String value;
|
||||
|
||||
@ApiModelProperty(value = "排序")
|
||||
private Integer dictSort = 999;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseEntity;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-29
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name="sys_job")
|
||||
public class Job extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "job_id")
|
||||
@NotNull(groups = Update.class)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "岗位名称")
|
||||
private String name;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "岗位排序")
|
||||
private Long jobSort;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "是否启用")
|
||||
private Boolean enabled;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Job job = (Job) o;
|
||||
return Objects.equals(id, job.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-17
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "sys_menu")
|
||||
public class Menu extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "menu_id")
|
||||
@NotNull(groups = {Update.class})
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@ManyToMany(mappedBy = "menus")
|
||||
@ApiModelProperty(value = "菜单角色")
|
||||
private Set<Role> roles;
|
||||
|
||||
@ApiModelProperty(value = "菜单标题")
|
||||
private String title;
|
||||
|
||||
@Column(name = "name")
|
||||
@ApiModelProperty(value = "菜单组件名称")
|
||||
private String componentName;
|
||||
|
||||
@ApiModelProperty(value = "排序")
|
||||
private Integer menuSort = 999;
|
||||
|
||||
@ApiModelProperty(value = "组件路径")
|
||||
private String component;
|
||||
|
||||
@ApiModelProperty(value = "路由地址")
|
||||
private String path;
|
||||
|
||||
@ApiModelProperty(value = "菜单类型,目录、菜单、按钮")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty(value = "权限标识")
|
||||
private String permission;
|
||||
|
||||
@ApiModelProperty(value = "菜单图标")
|
||||
private String icon;
|
||||
|
||||
@Column(columnDefinition = "bit(1) default 0")
|
||||
@ApiModelProperty(value = "缓存")
|
||||
private Boolean cache;
|
||||
|
||||
@Column(columnDefinition = "bit(1) default 0")
|
||||
@ApiModelProperty(value = "是否隐藏")
|
||||
private Boolean hidden;
|
||||
|
||||
@ApiModelProperty(value = "上级菜单")
|
||||
private Long pid;
|
||||
|
||||
@ApiModelProperty(value = "子节点数目", hidden = true)
|
||||
private Integer subCount = 0;
|
||||
|
||||
@ApiModelProperty(value = "外链菜单")
|
||||
private Boolean iFrame;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Menu menu = (Menu) o;
|
||||
return Objects.equals(id, menu.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseEntity;
|
||||
import com.example.utils.enums.DataScopeEnum;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* 角色
|
||||
*
|
||||
* 2018-11-22
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@Entity
|
||||
@Table(name = "sys_role")
|
||||
public class Role extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "role_id")
|
||||
@NotNull(groups = {Update.class})
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
private Long id;
|
||||
|
||||
@JSONField(serialize = false)
|
||||
@ManyToMany(mappedBy = "roles")
|
||||
@ApiModelProperty(value = "用户", hidden = true)
|
||||
private Set<User> users;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "sys_roles_menus",
|
||||
joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "menu_id",referencedColumnName = "menu_id")})
|
||||
@ApiModelProperty(value = "菜单", hidden = true)
|
||||
private Set<Menu> menus;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(name = "sys_roles_depts",
|
||||
joinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "dept_id",referencedColumnName = "dept_id")})
|
||||
@ApiModelProperty(value = "部门", hidden = true)
|
||||
private Set<Dept> depts;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "名称", hidden = true)
|
||||
private String name;
|
||||
|
||||
@ApiModelProperty(value = "数据权限,全部 、 本级 、 自定义")
|
||||
private String dataScope = DataScopeEnum.THIS_LEVEL.getValue();
|
||||
|
||||
@Column(name = "level")
|
||||
@ApiModelProperty(value = "级别,数值越小,级别越大")
|
||||
private Integer level = 3;
|
||||
|
||||
@ApiModelProperty(value = "描述")
|
||||
private String description;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Role role = (Role) o;
|
||||
return Objects.equals(id, role.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseEntity;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-11-22
|
||||
*/
|
||||
@Entity
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name="sys_user")
|
||||
public class User extends BaseEntity implements Serializable {
|
||||
|
||||
@Id
|
||||
@Column(name = "user_id")
|
||||
@NotNull(groups = Update.class)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@ApiModelProperty(value = "ID", hidden = true)
|
||||
private Long id;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@ApiModelProperty(value = "用户角色")
|
||||
@JoinTable(name = "sys_users_roles",
|
||||
joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "role_id",referencedColumnName = "role_id")})
|
||||
private Set<Role> roles;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@ApiModelProperty(value = "用户岗位")
|
||||
@JoinTable(name = "sys_users_jobs",
|
||||
joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "user_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "job_id",referencedColumnName = "job_id")})
|
||||
private Set<Job> jobs;
|
||||
|
||||
@OneToOne
|
||||
@JoinColumn(name = "dept_id")
|
||||
@ApiModelProperty(value = "用户部门")
|
||||
private Dept dept;
|
||||
|
||||
@NotBlank
|
||||
@Column(unique = true)
|
||||
@ApiModelProperty(value = "用户名称")
|
||||
private String username;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "用户昵称")
|
||||
private String nickName;
|
||||
|
||||
@Email
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "邮箱")
|
||||
private String email;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty(value = "电话号码")
|
||||
private String phone;
|
||||
|
||||
@ApiModelProperty(value = "用户性别")
|
||||
private String gender;
|
||||
|
||||
@ApiModelProperty(value = "头像真实名称",hidden = true)
|
||||
private String avatarName;
|
||||
|
||||
@ApiModelProperty(value = "头像存储的路径", hidden = true)
|
||||
private String avatarPath;
|
||||
|
||||
@ApiModelProperty(value = "密码")
|
||||
private String password;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty(value = "是否启用")
|
||||
private Boolean enabled;
|
||||
|
||||
@ApiModelProperty(value = "是否为admin账号", hidden = true)
|
||||
private Boolean isAdmin = false;
|
||||
|
||||
@Column(name = "pwd_reset_time")
|
||||
@ApiModelProperty(value = "最后修改密码的时间", hidden = true)
|
||||
private Date pwdResetTime;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
User user = (User) o;
|
||||
return Objects.equals(id, user.id) &&
|
||||
Objects.equals(username, user.username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, username);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain.vo;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-20
|
||||
*/
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class MenuMetaVo implements Serializable {
|
||||
|
||||
private String title;
|
||||
|
||||
private String icon;
|
||||
|
||||
private Boolean noCache;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain.vo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 构建前端路由时用到
|
||||
*
|
||||
* 2018-12-20
|
||||
*/
|
||||
@Data
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
public class MenuVo implements Serializable {
|
||||
|
||||
private String name;
|
||||
|
||||
private String path;
|
||||
|
||||
private Boolean hidden;
|
||||
|
||||
private String redirect;
|
||||
|
||||
private String component;
|
||||
|
||||
private Boolean alwaysShow;
|
||||
|
||||
private MenuMetaVo meta;
|
||||
|
||||
private List<MenuVo> children;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 修改密码的 Vo 类
|
||||
*
|
||||
* 2019年7月11日13:59:49
|
||||
*/
|
||||
@Data
|
||||
public class UserPassVo {
|
||||
|
||||
private String oldPass;
|
||||
|
||||
private String newPass;
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.repository;
|
||||
|
||||
import com.example.modules.system.domain.Dept;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-25
|
||||
*/
|
||||
public interface DeptRepository extends JpaRepository<Dept, Long>, JpaSpecificationExecutor<Dept> {
|
||||
|
||||
/**
|
||||
* 根据 PID 查询
|
||||
* @param id pid
|
||||
* @return /
|
||||
*/
|
||||
List<Dept> findByPid(Long id);
|
||||
|
||||
/**
|
||||
* 获取顶级部门
|
||||
* @return /
|
||||
*/
|
||||
List<Dept> findByPidIsNull();
|
||||
|
||||
/**
|
||||
* 根据角色ID 查询
|
||||
* @param roleId 角色ID
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "select d.* from sys_dept d, sys_roles_depts r where " +
|
||||
"d.dept_id = r.dept_id and r.role_id = ?1", nativeQuery = true)
|
||||
Set<Dept> findByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 判断是否存在子节点
|
||||
* @param pid /
|
||||
* @return /
|
||||
*/
|
||||
int countByPid(Long pid);
|
||||
|
||||
/**
|
||||
* 根据ID更新sub_count
|
||||
* @param count /
|
||||
* @param id /
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = " update sys_dept set sub_count = ?1 where dept_id = ?2 ",nativeQuery = true)
|
||||
void updateSubCntById(Integer count, Long id);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.repository;
|
||||
|
||||
import com.example.modules.system.domain.DictDetail;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
public interface DictDetailRepository extends JpaRepository<DictDetail, Long>, JpaSpecificationExecutor<DictDetail> {
|
||||
|
||||
/**
|
||||
* 根据字典名称查询
|
||||
* @param name /
|
||||
* @return /
|
||||
*/
|
||||
List<DictDetail> findByDictName(String name);
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.repository;
|
||||
|
||||
import com.example.modules.system.domain.Dict;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
public interface DictRepository extends JpaRepository<Dict, Long>, JpaSpecificationExecutor<Dict> {
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param ids /
|
||||
*/
|
||||
void deleteByIdIn(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 查询
|
||||
* @param ids /
|
||||
* @return /
|
||||
*/
|
||||
List<Dict> findByIdIn(Set<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.repository;
|
||||
|
||||
import com.example.modules.system.domain.Job;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-29
|
||||
*/
|
||||
public interface JobRepository extends JpaRepository<Job, Long>, JpaSpecificationExecutor<Job> {
|
||||
|
||||
/**
|
||||
* 根据名称查询
|
||||
* @param name 名称
|
||||
* @return /
|
||||
*/
|
||||
Job findByName(String name);
|
||||
|
||||
/**
|
||||
* 根据Id删除
|
||||
* @param ids /
|
||||
*/
|
||||
void deleteAllByIdIn(Set<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.repository;
|
||||
|
||||
import com.example.modules.system.domain.Menu;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-17
|
||||
*/
|
||||
public interface MenuRepository extends JpaRepository<Menu, Long>, JpaSpecificationExecutor<Menu> {
|
||||
|
||||
/**
|
||||
* 根据菜单标题查询
|
||||
* @param title 菜单标题
|
||||
* @return /
|
||||
*/
|
||||
Menu findByTitle(String title);
|
||||
|
||||
/**
|
||||
* 根据组件名称查询
|
||||
* @param name 组件名称
|
||||
* @return /
|
||||
*/
|
||||
Menu findByComponentName(String name);
|
||||
|
||||
/**
|
||||
* 根据菜单的 PID 查询
|
||||
* @param pid /
|
||||
* @return /
|
||||
*/
|
||||
List<Menu> findByPid(long pid);
|
||||
|
||||
/**
|
||||
* 查询顶级菜单
|
||||
* @return /
|
||||
*/
|
||||
List<Menu> findByPidIsNull();
|
||||
|
||||
/**
|
||||
* 根据角色ID与菜单类型查询菜单
|
||||
* @param roleIds roleIDs
|
||||
* @param type 类型
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT m.* FROM sys_menu m, sys_roles_menus r WHERE " +
|
||||
"m.menu_id = r.menu_id AND r.role_id IN ?1 AND type != ?2 order by m.menu_sort asc",nativeQuery = true)
|
||||
LinkedHashSet<Menu> findByRoleIdsAndTypeNot(Set<Long> roleIds, int type);
|
||||
|
||||
/**
|
||||
* 获取节点数量
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
int countByPid(Long id);
|
||||
|
||||
/**
|
||||
* 更新节点数目
|
||||
* @param count /
|
||||
* @param menuId /
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = " update sys_menu set sub_count = ?1 where menu_id = ?2 ",nativeQuery = true)
|
||||
void updateSubCntById(int count, Long menuId);
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.repository;
|
||||
|
||||
import com.example.modules.system.domain.Role;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-03
|
||||
*/
|
||||
public interface RoleRepository extends JpaRepository<Role, Long>, JpaSpecificationExecutor<Role> {
|
||||
|
||||
/**
|
||||
* 根据名称查询
|
||||
* @param name /
|
||||
* @return /
|
||||
*/
|
||||
Role findByName(String name);
|
||||
|
||||
/**
|
||||
* 删除多个角色
|
||||
* @param ids /
|
||||
*/
|
||||
void deleteAllByIdIn(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询
|
||||
* @param id 用户ID
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT r.* FROM sys_role r, sys_users_roles u WHERE " +
|
||||
"r.role_id = u.role_id AND u.user_id = ?1",nativeQuery = true)
|
||||
Set<Role> findByUserId(Long id);
|
||||
|
||||
/**
|
||||
* 解绑角色菜单
|
||||
* @param id 菜单ID
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = "delete from sys_roles_menus where menu_id = ?1",nativeQuery = true)
|
||||
void untiedMenu(Long id);
|
||||
|
||||
/**
|
||||
* 根据部门查询
|
||||
* @param deptIds /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "select count(1) from sys_role r, sys_roles_depts d where " +
|
||||
"r.role_id = d.role_id and d.dept_id in ?1",nativeQuery = true)
|
||||
int countByDepts(Set<Long> deptIds);
|
||||
|
||||
/**
|
||||
* 根据菜单Id查询
|
||||
* @param menuIds /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT r.* FROM sys_role r, sys_roles_menus m WHERE " +
|
||||
"r.role_id = m.role_id AND m.menu_id in ?1",nativeQuery = true)
|
||||
List<Role> findInMenuId(List<Long> menuIds);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.repository;
|
||||
|
||||
import com.example.modules.system.domain.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-11-22
|
||||
*/
|
||||
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
|
||||
|
||||
/**
|
||||
* 根据用户名查询
|
||||
* @param username 用户名
|
||||
* @return /
|
||||
*/
|
||||
User findByUsername(String username);
|
||||
|
||||
/**
|
||||
* 根据邮箱查询
|
||||
* @param email 邮箱
|
||||
* @return /
|
||||
*/
|
||||
User findByEmail(String email);
|
||||
|
||||
/**
|
||||
* 根据手机号查询
|
||||
* @param phone 手机号
|
||||
* @return /
|
||||
*/
|
||||
User findByPhone(String phone);
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param username 用户名
|
||||
* @param pass 密码
|
||||
* @param lastPasswordResetTime /
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = "update sys_user set password = ?2 , pwd_reset_time = ?3 where username = ?1",nativeQuery = true)
|
||||
void updatePass(String username, String pass, Date lastPasswordResetTime);
|
||||
|
||||
/**
|
||||
* 修改邮箱
|
||||
* @param username 用户名
|
||||
* @param email 邮箱
|
||||
*/
|
||||
@Modifying
|
||||
@Query(value = "update sys_user set email = ?2 where username = ?1",nativeQuery = true)
|
||||
void updateEmail(String username, String email);
|
||||
|
||||
/**
|
||||
* 根据角色查询用户
|
||||
* @param roleId /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT u.* FROM sys_user u, sys_users_roles r WHERE" +
|
||||
" u.user_id = r.user_id AND r.role_id = ?1", nativeQuery = true)
|
||||
List<User> findByRoleId(Long roleId);
|
||||
|
||||
/**
|
||||
* 根据角色中的部门查询
|
||||
* @param deptId /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT u.* FROM sys_user u, sys_users_roles r, sys_roles_depts d WHERE " +
|
||||
"u.user_id = r.user_id AND r.role_id = d.role_id AND d.dept_id = ?1 group by u.user_id", nativeQuery = true)
|
||||
List<User> findByRoleDeptId(Long deptId);
|
||||
|
||||
/**
|
||||
* 根据菜单查询
|
||||
* @param id 菜单ID
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT u.* FROM sys_user u, sys_users_roles ur, sys_roles_menus rm WHERE\n" +
|
||||
"u.user_id = ur.user_id AND ur.role_id = rm.role_id AND rm.menu_id = ?1 group by u.user_id", nativeQuery = true)
|
||||
List<User> findByMenuId(Long id);
|
||||
|
||||
/**
|
||||
* 根据Id删除
|
||||
* @param ids /
|
||||
*/
|
||||
void deleteAllByIdIn(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据岗位查询
|
||||
* @param ids /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT count(1) FROM sys_user u, sys_users_jobs j WHERE u.user_id = j.user_id AND j.job_id IN ?1", nativeQuery = true)
|
||||
int countByJobs(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据部门查询
|
||||
* @param deptIds /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT count(1) FROM sys_user u WHERE u.dept_id IN ?1", nativeQuery = true)
|
||||
int countByDepts(Set<Long> deptIds);
|
||||
|
||||
/**
|
||||
* 根据角色查询
|
||||
* @param ids /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT count(1) FROM sys_user u, sys_users_roles r WHERE " +
|
||||
"u.user_id = r.user_id AND r.role_id in ?1", nativeQuery = true)
|
||||
int countByRoles(Set<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.service.dto.UserDto;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 数据权限服务类
|
||||
*
|
||||
* 2020-05-07
|
||||
*/
|
||||
public interface DataService {
|
||||
|
||||
/**
|
||||
* 获取数据权限
|
||||
* @param user /
|
||||
* @return /
|
||||
*/
|
||||
List<Long> getDeptIds(UserDto user);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.domain.Dept;
|
||||
import com.example.modules.system.service.dto.DeptDto;
|
||||
import com.example.modules.system.service.dto.DeptQueryCriteria;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-25
|
||||
*/
|
||||
public interface DeptService {
|
||||
|
||||
/**
|
||||
* 查询所有数据
|
||||
* @param criteria 条件
|
||||
* @param isQuery /
|
||||
* @throws Exception /
|
||||
* @return /
|
||||
*/
|
||||
List<DeptDto> queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception;
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
DeptDto findById(Long id);
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
*/
|
||||
void create(Dept resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(Dept resources);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param deptDtos /
|
||||
*
|
||||
*/
|
||||
void delete(Set<DeptDto> deptDtos);
|
||||
|
||||
/**
|
||||
* 根据PID查询
|
||||
* @param pid /
|
||||
* @return /
|
||||
*/
|
||||
List<Dept> findByPid(long pid);
|
||||
|
||||
/**
|
||||
* 根据角色ID查询
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
Set<Dept> findByRoleId(Long id);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param queryAll 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<DeptDto> queryAll, HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
* 获取待删除的部门
|
||||
* @param deptList /
|
||||
* @param deptDtos /
|
||||
* @return /
|
||||
*/
|
||||
Set<DeptDto> getDeleteDepts(List<Dept> deptList, Set<DeptDto> deptDtos);
|
||||
|
||||
/**
|
||||
* 根据ID获取同级与上级数据
|
||||
* @param deptDto /
|
||||
* @param depts /
|
||||
* @return /
|
||||
*/
|
||||
List<DeptDto> getSuperior(DeptDto deptDto, List<Dept> depts);
|
||||
|
||||
/**
|
||||
* 构建树形数据
|
||||
* @param deptDtos /
|
||||
* @return /
|
||||
*/
|
||||
Object buildTree(List<DeptDto> deptDtos);
|
||||
|
||||
/**
|
||||
* 获取
|
||||
* @param deptList
|
||||
* @return
|
||||
*/
|
||||
List<Long> getDeptChildren(List<Dept> deptList);
|
||||
|
||||
/**
|
||||
* 验证是否被角色或用户关联
|
||||
* @param deptDtos /
|
||||
*/
|
||||
void verification(Set<DeptDto> deptDtos);
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.domain.DictDetail;
|
||||
import com.example.modules.system.service.dto.DictDetailDto;
|
||||
import com.example.modules.system.service.dto.DictDetailQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
public interface DictDetailService {
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
*/
|
||||
void create(DictDetail resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(DictDetail resources);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param id /
|
||||
*/
|
||||
void delete(Long id);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Map<String,Object> queryAll(DictDetailQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 根据字典名称获取字典详情
|
||||
* @param name 字典名称
|
||||
* @return /
|
||||
*/
|
||||
List<DictDetailDto> getDictByName(String name);
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.domain.Dict;
|
||||
import com.example.modules.system.service.dto.DictDto;
|
||||
import com.example.modules.system.service.dto.DictQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
public interface DictService {
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Map<String,Object> queryAll(DictQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
* @param dict /
|
||||
* @return /
|
||||
*/
|
||||
List<DictDto> queryAll(DictQueryCriteria dict);
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
* @return /
|
||||
*/
|
||||
void create(Dict resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(Dict resources);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param ids /
|
||||
*/
|
||||
void delete(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param queryAll 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<DictDto> queryAll, HttpServletResponse response) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.domain.Job;
|
||||
import com.example.modules.system.service.dto.JobDto;
|
||||
import com.example.modules.system.service.dto.JobQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-29
|
||||
*/
|
||||
public interface JobService {
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
JobDto findById(Long id);
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
* @return /
|
||||
*/
|
||||
void create(Job resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(Job resources);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param ids /
|
||||
*/
|
||||
void delete(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
* @param criteria /
|
||||
* @return /
|
||||
*/
|
||||
List<JobDto> queryAll(JobQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param queryAll 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<JobDto> queryAll, HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
* 验证是否被用户关联
|
||||
* @param ids /
|
||||
*/
|
||||
void verification(Set<Long> ids);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.domain.Menu;
|
||||
import com.example.modules.system.service.dto.MenuDto;
|
||||
import com.example.modules.system.service.dto.MenuQueryCriteria;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-17
|
||||
*/
|
||||
public interface MenuService {
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
* @param criteria 条件
|
||||
* @param isQuery /
|
||||
* @throws Exception /
|
||||
* @return /
|
||||
*/
|
||||
List<MenuDto> queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception;
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
MenuDto findById(long id);
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
*/
|
||||
void create(Menu resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(Menu resources);
|
||||
|
||||
/**
|
||||
* 获取所有子节点,包含自身ID
|
||||
* @param menuList /
|
||||
* @param menuSet /
|
||||
* @return /
|
||||
*/
|
||||
Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet);
|
||||
|
||||
/**
|
||||
* 构建菜单树
|
||||
* @param menuDtos 原始数据
|
||||
* @return /
|
||||
*/
|
||||
List<MenuDto> buildTree(List<MenuDto> menuDtos);
|
||||
|
||||
/**
|
||||
* 构建菜单树
|
||||
* @param menuDtos /
|
||||
* @return /
|
||||
*/
|
||||
Object buildMenus(List<MenuDto> menuDtos);
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
Menu findOne(Long id);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param menuSet /
|
||||
*/
|
||||
void delete(Set<Menu> menuSet);
|
||||
|
||||
/**
|
||||
* 导出
|
||||
* @param queryAll 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<MenuDto> queryAll, HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
* 懒加载菜单数据
|
||||
* @param pid /
|
||||
* @return /
|
||||
*/
|
||||
List<MenuDto> getMenus(Long pid);
|
||||
|
||||
/**
|
||||
* 根据ID获取同级与上级数据
|
||||
* @param menuDto /
|
||||
* @param objects /
|
||||
* @return /
|
||||
*/
|
||||
List<MenuDto> getSuperior(MenuDto menuDto, List<Menu> objects);
|
||||
|
||||
/**
|
||||
* 根据当前用户获取菜单
|
||||
* @param currentUserId /
|
||||
* @return /
|
||||
*/
|
||||
List<MenuDto> findByUser(Long currentUserId);
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2020-05-02
|
||||
*/
|
||||
public interface MonitorService {
|
||||
|
||||
/**
|
||||
* 查询数据分页
|
||||
* @return Map<String,Object>
|
||||
*/
|
||||
Map<String,Object> getServers();
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.domain.Role;
|
||||
import com.example.modules.system.service.dto.RoleDto;
|
||||
import com.example.modules.system.service.dto.RoleQueryCriteria;
|
||||
import com.example.modules.system.service.dto.RoleSmallDto;
|
||||
import com.example.modules.system.service.dto.UserDto;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2018-12-03
|
||||
*/
|
||||
public interface RoleService {
|
||||
|
||||
/**
|
||||
* 查询全部数据
|
||||
* @return /
|
||||
*/
|
||||
List<RoleDto> queryAll();
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id /
|
||||
* @return /
|
||||
*/
|
||||
RoleDto findById(long id);
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param resources /
|
||||
*/
|
||||
void create(Role resources);
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param resources /
|
||||
*/
|
||||
void update(Role resources);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param ids /
|
||||
*/
|
||||
void delete(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据用户ID查询
|
||||
* @param id 用户ID
|
||||
* @return /
|
||||
*/
|
||||
List<RoleSmallDto> findByUsersId(Long id);
|
||||
|
||||
/**
|
||||
* 根据角色查询角色级别
|
||||
* @param roles /
|
||||
* @return /
|
||||
*/
|
||||
Integer findByRoles(Set<Role> roles);
|
||||
|
||||
/**
|
||||
* 修改绑定的菜单
|
||||
* @param resources /
|
||||
* @param roleDTO /
|
||||
*/
|
||||
void updateMenu(Role resources, RoleDto roleDTO);
|
||||
|
||||
/**
|
||||
* 解绑菜单
|
||||
* @param id /
|
||||
*/
|
||||
void untiedMenu(Long id);
|
||||
|
||||
/**
|
||||
* 待条件分页查询
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Object queryAll(RoleQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
* @param criteria 条件
|
||||
* @return /
|
||||
*/
|
||||
List<RoleDto> queryAll(RoleQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param queryAll 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<RoleDto> queryAll, HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
* 获取用户权限信息
|
||||
* @param user 用户信息
|
||||
* @return 权限信息
|
||||
*/
|
||||
List<GrantedAuthority> mapToGrantedAuthorities(UserDto user);
|
||||
|
||||
/**
|
||||
* 验证是否被用户关联
|
||||
* @param ids /
|
||||
*/
|
||||
void verification(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据菜单Id查询
|
||||
* @param menuIds /
|
||||
* @return /
|
||||
*/
|
||||
List<Role> findInMenuId(List<Long> menuIds);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service;
|
||||
|
||||
import com.example.modules.system.domain.User;
|
||||
import com.example.modules.system.service.dto.UserDto;
|
||||
import com.example.modules.system.service.dto.UserQueryCriteria;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public interface UserService {
|
||||
|
||||
/**
|
||||
* 根据ID查询
|
||||
* @param id ID
|
||||
* @return /
|
||||
*/
|
||||
UserDto findById(long id);
|
||||
|
||||
/**
|
||||
* 新增用户
|
||||
* @param resources /
|
||||
*/
|
||||
void create(User resources);
|
||||
|
||||
/**
|
||||
* 编辑用户
|
||||
* @param resources /
|
||||
* @throws Exception /
|
||||
*/
|
||||
void update(User resources) throws Exception;
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
* @param ids /
|
||||
*/
|
||||
void delete(Set<Long> ids);
|
||||
|
||||
/**
|
||||
* 根据用户名查询
|
||||
* @param userName /
|
||||
* @return /
|
||||
*/
|
||||
UserDto findByName(String userName);
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
* @param username 用户名
|
||||
* @param encryptPassword 密码
|
||||
*/
|
||||
void updatePass(String username, String encryptPassword);
|
||||
|
||||
/**
|
||||
* 修改头像
|
||||
* @param file 文件
|
||||
* @return /
|
||||
*/
|
||||
Map<String, String> updateAvatar(MultipartFile file);
|
||||
|
||||
/**
|
||||
* 修改邮箱
|
||||
* @param username 用户名
|
||||
* @param email 邮箱
|
||||
*/
|
||||
void updateEmail(String username, String email);
|
||||
|
||||
/**
|
||||
* 查询全部
|
||||
* @param criteria 条件
|
||||
* @param pageable 分页参数
|
||||
* @return /
|
||||
*/
|
||||
Object queryAll(UserQueryCriteria criteria, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 查询全部不分页
|
||||
* @param criteria 条件
|
||||
* @return /
|
||||
*/
|
||||
List<UserDto> queryAll(UserQueryCriteria criteria);
|
||||
|
||||
/**
|
||||
* 导出数据
|
||||
* @param queryAll 待导出的数据
|
||||
* @param response /
|
||||
* @throws IOException /
|
||||
*/
|
||||
void download(List<UserDto> queryAll, HttpServletResponse response) throws IOException;
|
||||
|
||||
/**
|
||||
* 用户自助修改资料
|
||||
* @param resources /
|
||||
*/
|
||||
void updateCenter(User resources);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseDTO;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-25
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class DeptDto extends BaseDTO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean enabled;
|
||||
|
||||
private Integer deptSort;
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
||||
private List<DeptDto> children;
|
||||
|
||||
private Long pid;
|
||||
|
||||
private Integer subCount;
|
||||
|
||||
public Boolean getHasChildren() {
|
||||
return subCount > 0;
|
||||
}
|
||||
|
||||
public Boolean getLeaf() {
|
||||
return subCount <= 0;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
DeptDto deptDto = (DeptDto) o;
|
||||
return Objects.equals(id, deptDto.id) &&
|
||||
Objects.equals(name, deptDto.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import com.example.annotation.DataPermission;
|
||||
import com.example.annotation.Query;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-25
|
||||
*/
|
||||
@Data
|
||||
@DataPermission(fieldName = "id")
|
||||
public class DeptQueryCriteria{
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String name;
|
||||
|
||||
@Query
|
||||
private Boolean enabled;
|
||||
|
||||
@Query
|
||||
private Long pid;
|
||||
|
||||
@Query(type = Query.Type.IS_NULL, propName = "pid")
|
||||
private Boolean pidIsNull;
|
||||
|
||||
@Query(type = Query.Type.BETWEEN)
|
||||
private List<Timestamp> createTime;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-6-10 16:32:18
|
||||
*/
|
||||
@Data
|
||||
public class DeptSmallDto implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseDTO;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class DictDetailDto extends BaseDTO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private DictSmallDto dict;
|
||||
|
||||
private String label;
|
||||
|
||||
private String value;
|
||||
|
||||
private Integer dictSort;
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import com.example.annotation.Query;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@Data
|
||||
public class DictDetailQueryCriteria {
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String label;
|
||||
|
||||
@Query(propName = "name",joinName = "dict")
|
||||
private String dictName;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseDTO;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class DictDto extends BaseDTO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private List<DictDetailDto> dictDetails;
|
||||
|
||||
private String name;
|
||||
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import com.example.annotation.Query;
|
||||
|
||||
/**
|
||||
*
|
||||
* 公共查询类
|
||||
*/
|
||||
@Data
|
||||
public class DictQueryCriteria {
|
||||
|
||||
@Query(blurry = "name,description")
|
||||
private String blurry;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-04-10
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class DictSmallDto implements Serializable {
|
||||
|
||||
private Long id;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import com.example.base.BaseDTO;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-03-29
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class JobDto extends BaseDTO implements Serializable {
|
||||
|
||||
private Long id;
|
||||
|
||||
private Integer jobSort;
|
||||
|
||||
private String name;
|
||||
|
||||
private Boolean enabled;
|
||||
|
||||
public JobDto(String name, Boolean enabled) {
|
||||
this.name = name;
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2019-2020 Zheng Jie
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.modules.system.service.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import com.example.annotation.Query;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* 2019-6-4 14:49:34
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class JobQueryCriteria {
|
||||
|
||||
@Query(type = Query.Type.INNER_LIKE)
|
||||
private String name;
|
||||
|
||||
@Query
|
||||
private Boolean enabled;
|
||||
|
||||
@Query(type = Query.Type.BETWEEN)
|
||||
private List<Timestamp> createTime;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user