diff options
Diffstat (limited to 'UI source code/dns-dev-2.0/dns-system/src/main')
137 files changed, 11509 insertions, 0 deletions
diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/AppRun.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/AppRun.java new file mode 100644 index 0000000..521f939 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/AppRun.java @@ -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; + } + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/ConfigurerAdapter.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/ConfigurerAdapter.java new file mode 100644 index 0000000..b2bcf86 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/ConfigurerAdapter.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusConfig.java new file mode 100644 index 0000000..87e8cbf --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusConfig.java @@ -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()); + } + } + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusPluginsConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusPluginsConfig.java new file mode 100644 index 0000000..cc9739c --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/MybatisPlusPluginsConfig.java @@ -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(); + } + + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/WebSocketConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/WebSocketConfig.java new file mode 100644 index 0000000..906021c --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/WebSocketConfig.java @@ -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(); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskExecutePool.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskExecutePool.java new file mode 100644 index 0000000..44abd3d --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskExecutePool.java @@ -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()); + }; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskProperties.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskProperties.java new file mode 100644 index 0000000..012a127 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/AsyncTaskProperties.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/TheadFactoryName.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/TheadFactoryName.java new file mode 100644 index 0000000..b06a723 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/TheadFactoryName.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/ThreadPoolExecutorUtil.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/ThreadPoolExecutorUtil.java new file mode 100644 index 0000000..db542cf --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/config/thread/ThreadPoolExecutorUtil.java @@ -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() + ); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/controller/DnsController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/controller/DnsController.java new file mode 100644 index 0000000..581a46b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/controller/DnsController.java @@ -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()); + } + + + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DnsType.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DnsType.java new file mode 100644 index 0000000..983c2ee --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DnsType.java @@ -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; + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DohAttribute.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DohAttribute.java new file mode 100644 index 0000000..5a772e2 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/DohAttribute.java @@ -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; + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ForwardDns.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ForwardDns.java new file mode 100644 index 0000000..5823a34 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ForwardDns.java @@ -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; + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpCert.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpCert.java new file mode 100644 index 0000000..a7f88af --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpCert.java @@ -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; + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpInformation.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpInformation.java new file mode 100644 index 0000000..1c61eb5 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/IpInformation.java @@ -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; + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/NonstandardDns.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/NonstandardDns.java new file mode 100644 index 0000000..11badef --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/NonstandardDns.java @@ -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; + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Result.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Result.java new file mode 100644 index 0000000..6047df6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Result.java @@ -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; + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ScanResult.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ScanResult.java new file mode 100644 index 0000000..8d479dc --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/ScanResult.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Vulnerability.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Vulnerability.java new file mode 100644 index 0000000..b31ba3e --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/domain/Vulnerability.java @@ -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; + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDo53Dao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDo53Dao.java new file mode 100644 index 0000000..0d1eee5 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDo53Dao.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDohDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDohDao.java new file mode 100644 index 0000000..29018e6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsDohDao.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsTypeDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsTypeDao.java new file mode 100644 index 0000000..e5193e6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/DnsTypeDao.java @@ -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> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/ForwardDnsDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/ForwardDnsDao.java new file mode 100644 index 0000000..2986981 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/ForwardDnsDao.java @@ -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> { + + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpCertDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpCertDao.java new file mode 100644 index 0000000..01939f6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpCertDao.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpInformationDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpInformationDao.java new file mode 100644 index 0000000..2ed80e3 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/IpInformationDao.java @@ -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); + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/NonstandardDnsDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/NonstandardDnsDao.java new file mode 100644 index 0000000..7c050ef --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/NonstandardDnsDao.java @@ -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> { + + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/VulnerabilityDao.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/VulnerabilityDao.java new file mode 100644 index 0000000..5d1c06f --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/mapper/VulnerabilityDao.java @@ -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> { + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsService.java new file mode 100644 index 0000000..3aad1ca --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsService.java @@ -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(); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsTypeService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsTypeService.java new file mode 100644 index 0000000..f9cb1c6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/DnsTypeService.java @@ -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> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/ScanResultService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/ScanResultService.java new file mode 100644 index 0000000..3dcd9dd --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/ScanResultService.java @@ -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); + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsQueryEnum.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsQueryEnum.java new file mode 100644 index 0000000..089a514 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsQueryEnum.java @@ -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; + } + +} + + + diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsServiceImpl.java new file mode 100644 index 0000000..09cab1a --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsServiceImpl.java @@ -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); + } + +} + + + diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsTypeServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsTypeServiceImpl.java new file mode 100644 index 0000000..8bd6d89 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/DnsTypeServiceImpl.java @@ -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 { + +} + + + diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/ScanResultServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/ScanResultServiceImpl.java new file mode 100644 index 0000000..5b832c9 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/dns/service/impl/ScanResultServiceImpl.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/ConfigBeanConfiguration.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/ConfigBeanConfiguration.java new file mode 100644 index 0000000..1c01c10 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/ConfigBeanConfiguration.java @@ -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(); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/SpringSecurityConfig.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/SpringSecurityConfig.java new file mode 100644 index 0000000..aa9fddf --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/SpringSecurityConfig.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCode.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCode.java new file mode 100644 index 0000000..02fbc23 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCode.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCodeEnum.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCodeEnum.java new file mode 100644 index 0000000..d9fe369 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginCodeEnum.java @@ -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 +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginProperties.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginProperties.java new file mode 100644 index 0000000..f4b6754 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/LoginProperties.java @@ -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(); + } + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/SecurityProperties.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/SecurityProperties.java new file mode 100644 index 0000000..f341003 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/config/bean/SecurityProperties.java @@ -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 + " "; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/AuthorizationController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/AuthorizationController.java new file mode 100644 index 0000000..7e2148b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/AuthorizationController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/OnlineController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/OnlineController.java new file mode 100644 index 0000000..c4962a3 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/rest/OnlineController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAccessDeniedHandler.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAccessDeniedHandler.java new file mode 100644 index 0000000..c0b6f86 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAccessDeniedHandler.java @@ -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()); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAuthenticationEntryPoint.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAuthenticationEntryPoint.java new file mode 100644 index 0000000..9fa256e --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/JwtAuthenticationEntryPoint.java @@ -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()); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenConfigurer.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenConfigurer.java new file mode 100644 index 0000000..2a1ad1c --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenConfigurer.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenFilter.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenFilter.java new file mode 100644 index 0000000..dc1369e --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenFilter.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenProvider.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenProvider.java new file mode 100644 index 0000000..dfe2134 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/security/TokenProvider.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/OnlineUserService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/OnlineUserService.java new file mode 100644 index 0000000..9cfda04 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/OnlineUserService.java @@ -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); + } + } + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheClean.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheClean.java new file mode 100644 index 0000000..aa1ef9c --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheClean.java @@ -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(); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheManager.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheManager.java new file mode 100644 index 0000000..9c1f60b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserCacheManager.java @@ -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; + } + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserDetailsServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserDetailsServiceImpl.java new file mode 100644 index 0000000..8d368f2 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/UserDetailsServiceImpl.java @@ -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()); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/AuthUserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/AuthUserDto.java new file mode 100644 index 0000000..983d690 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/AuthUserDto.java @@ -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 = ""; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/JwtUserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/JwtUserDto.java new file mode 100644 index 0000000..20e1bc6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/JwtUserDto.java @@ -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(); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/OnlineUserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/OnlineUserDto.java new file mode 100644 index 0000000..77ba3bc --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/security/service/dto/OnlineUserDto.java @@ -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; + + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DeptController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DeptController.java new file mode 100644 index 0000000..0bef112 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DeptController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictController.java new file mode 100644 index 0000000..8f4dec7 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictDetailController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictDetailController.java new file mode 100644 index 0000000..e3c5891 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/DictDetailController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/JobController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/JobController.java new file mode 100644 index 0000000..6106f0d --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/JobController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/LimitController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/LimitController.java new file mode 100644 index 0000000..636ec91 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/LimitController.java @@ -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(); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MenuController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MenuController.java new file mode 100644 index 0000000..26a2f1a --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MenuController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MonitorController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MonitorController.java new file mode 100644 index 0000000..bb7bf02 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/MonitorController.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/RoleController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/RoleController.java new file mode 100644 index 0000000..8f4fae8 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/RoleController.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/UserController.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/UserController.java new file mode 100644 index 0000000..393a878 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/controller/UserController.java @@ -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("角色权限不足"); + } + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dept.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dept.java new file mode 100644 index 0000000..4ef6ac1 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dept.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dict.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dict.java new file mode 100644 index 0000000..de65392 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Dict.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/DictDetail.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/DictDetail.java new file mode 100644 index 0000000..538743e --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/DictDetail.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Job.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Job.java new file mode 100644 index 0000000..f3f47b3 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Job.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Menu.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Menu.java new file mode 100644 index 0000000..0989055 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Menu.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Role.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Role.java new file mode 100644 index 0000000..b600f46 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/Role.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/User.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/User.java new file mode 100644 index 0000000..fcbba83 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/User.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuMetaVo.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuMetaVo.java new file mode 100644 index 0000000..68944cc --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuMetaVo.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuVo.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuVo.java new file mode 100644 index 0000000..71c6161 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/MenuVo.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/UserPassVo.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/UserPassVo.java new file mode 100644 index 0000000..66869b2 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/domain/vo/UserPassVo.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DeptRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DeptRepository.java new file mode 100644 index 0000000..5952659 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DeptRepository.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictDetailRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictDetailRepository.java new file mode 100644 index 0000000..315be98 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictDetailRepository.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictRepository.java new file mode 100644 index 0000000..c2d1a49 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/DictRepository.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/JobRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/JobRepository.java new file mode 100644 index 0000000..d804309 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/JobRepository.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/MenuRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/MenuRepository.java new file mode 100644 index 0000000..ac1e524 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/MenuRepository.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/RoleRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/RoleRepository.java new file mode 100644 index 0000000..dd6e48b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/RoleRepository.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/UserRepository.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/UserRepository.java new file mode 100644 index 0000000..620b247 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/repository/UserRepository.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DataService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DataService.java new file mode 100644 index 0000000..de01bd9 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DataService.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DeptService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DeptService.java new file mode 100644 index 0000000..24f6138 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DeptService.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictDetailService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictDetailService.java new file mode 100644 index 0000000..57e5a7f --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictDetailService.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictService.java new file mode 100644 index 0000000..8cf7e9c --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/DictService.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/JobService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/JobService.java new file mode 100644 index 0000000..2fc99b6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/JobService.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MenuService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MenuService.java new file mode 100644 index 0000000..4706705 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MenuService.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MonitorService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MonitorService.java new file mode 100644 index 0000000..d9f87f9 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/MonitorService.java @@ -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(); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/RoleService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/RoleService.java new file mode 100644 index 0000000..5fa13ca --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/RoleService.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/UserService.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/UserService.java new file mode 100644 index 0000000..10fba88 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/UserService.java @@ -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); +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptDto.java new file mode 100644 index 0000000..02ec1ea --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptDto.java @@ -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); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptQueryCriteria.java new file mode 100644 index 0000000..8f8c56b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptQueryCriteria.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptSmallDto.java new file mode 100644 index 0000000..503762b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DeptSmallDto.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailDto.java new file mode 100644 index 0000000..58e826b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailDto.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailQueryCriteria.java new file mode 100644 index 0000000..2f12c80 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDetailQueryCriteria.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDto.java new file mode 100644 index 0000000..72f704e --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictDto.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictQueryCriteria.java new file mode 100644 index 0000000..3a5da52 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictQueryCriteria.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictSmallDto.java new file mode 100644 index 0000000..a0ed61f --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/DictSmallDto.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobDto.java new file mode 100644 index 0000000..502176b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobDto.java @@ -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; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobQueryCriteria.java new file mode 100644 index 0000000..215d721 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobQueryCriteria.java @@ -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; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobSmallDto.java new file mode 100644 index 0000000..af9f8a6 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/JobSmallDto.java @@ -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 lombok.NoArgsConstructor; +import java.io.Serializable; + +/** +* +* 2019-6-10 16:32:18 +*/ +@Data +@NoArgsConstructor +public class JobSmallDto implements Serializable { + + private Long id; + + private String name; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuDto.java new file mode 100644 index 0000000..8500654 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuDto.java @@ -0,0 +1,91 @@ +/* + * 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; +import java.util.Objects; + +/** + * + * 2018-12-17 + */ +@Getter +@Setter +public class MenuDto extends BaseDTO implements Serializable { + + private Long id; + + private List<MenuDto> children; + + private Integer type; + + private String permission; + + private String title; + + private Integer menuSort; + + private String path; + + private String component; + + private Long pid; + + private Integer subCount; + + private Boolean iFrame; + + private Boolean cache; + + private Boolean hidden; + + private String componentName; + + private String icon; + + public Boolean getHasChildren() { + return subCount > 0; + } + + public Boolean getLeaf() { + return subCount <= 0; + } + + public String getLabel() { + return title; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MenuDto menuDto = (MenuDto) o; + return Objects.equals(id, menuDto.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuQueryCriteria.java new file mode 100644 index 0000000..1d03860 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/MenuQueryCriteria.java @@ -0,0 +1,41 @@ +/* + * 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; +import java.sql.Timestamp; +import java.util.List; + +/** + * + * 公共查询类 + */ +@Data +public class MenuQueryCriteria { + + @Query(blurry = "title,component,permission") + private String blurry; + + @Query(type = Query.Type.BETWEEN) + private List<Timestamp> createTime; + + @Query(type = Query.Type.IS_NULL, propName = "pid") + private Boolean pidIsNull; + + @Query + private Long pid; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleDto.java new file mode 100644 index 0000000..1373b7f --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleDto.java @@ -0,0 +1,60 @@ +/* + * 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.Objects; +import java.util.Set; + + +@Getter +@Setter +public class RoleDto extends BaseDTO implements Serializable { + + private Long id; + + private Set<MenuDto> menus; + + private Set<DeptDto> depts; + + private String name; + + private String dataScope; + + private Integer level; + + private String description; + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + RoleDto roleDto = (RoleDto) o; + return Objects.equals(id, roleDto.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleQueryCriteria.java new file mode 100644 index 0000000..afe3a4e --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleQueryCriteria.java @@ -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.service.dto; + +import lombok.Data; +import com.example.annotation.Query; + +import java.sql.Timestamp; +import java.util.List; + +/** + * + * 公共查询类 + */ +@Data +public class RoleQueryCriteria { + + @Query(blurry = "name,description") + private String blurry; + + @Query(type = Query.Type.BETWEEN) + private List<Timestamp> createTime; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleSmallDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleSmallDto.java new file mode 100644 index 0000000..5c7f184 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/RoleSmallDto.java @@ -0,0 +1,32 @@ +/* + * 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; + + +@Data +public class RoleSmallDto implements Serializable { + + private Long id; + + private String name; + + private Integer level; + + private String dataScope; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserDto.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserDto.java new file mode 100644 index 0000000..a1ecd96 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserDto.java @@ -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.modules.system.service.dto; + +import com.alibaba.fastjson.annotation.JSONField; +import lombok.Getter; +import lombok.Setter; +import com.example.base.BaseDTO; +import java.io.Serializable; +import java.util.Date; +import java.util.Set; + + +@Getter +@Setter +public class UserDto extends BaseDTO implements Serializable { + + private Long id; + + private Set<RoleSmallDto> roles; + + private Set<JobSmallDto> jobs; + + private DeptSmallDto dept; + + private Long deptId; + + private String username; + + private String nickName; + + private String email; + + private String phone; + + private String gender; + + private String avatarName; + + private String avatarPath; + + @JSONField(serialize = false) + private String password; + + private Boolean enabled; + + @JSONField(serialize = false) + private Boolean isAdmin = false; + + private Date pwdResetTime; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserQueryCriteria.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserQueryCriteria.java new file mode 100644 index 0000000..1f862cf --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/dto/UserQueryCriteria.java @@ -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.Query; +import java.io.Serializable; +import java.sql.Timestamp; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + + +@Data +public class UserQueryCriteria implements Serializable { + + @Query + private Long id; + + @Query(propName = "id", type = Query.Type.IN, joinName = "dept") + private Set<Long> deptIds = new HashSet<>(); + + @Query(blurry = "email,username,nickName") + private String blurry; + + @Query + private Boolean enabled; + + private Long deptId; + + @Query(type = Query.Type.BETWEEN) + private List<Timestamp> createTime; +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DataServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DataServiceImpl.java new file mode 100644 index 0000000..e31f26b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DataServiceImpl.java @@ -0,0 +1,91 @@ +/* + * 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.impl; + +import com.example.modules.system.domain.Dept; +import com.example.modules.system.service.DataService; +import com.example.modules.system.service.DeptService; +import lombok.RequiredArgsConstructor; +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.utils.enums.DataScopeEnum; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import java.util.*; + +/** + * + * @website https://el-admin.vip + * @description 数据权限服务实现 + * 2020-05-07 + **/ +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "data") +public class DataServiceImpl implements DataService { + + private final RoleService roleService; + private final DeptService deptService; + + /** + * 用户角色改变时需清理缓存 + * @param user / + * @return / + */ + @Override + @Cacheable(key = "'user:' + #p0.id") + public List<Long> getDeptIds(UserDto user) { + // 用于存储部门id + Set<Long> deptIds = new HashSet<>(); + // 查询用户角色 + List<RoleSmallDto> roleSet = roleService.findByUsersId(user.getId()); + // 获取对应的部门ID + for (RoleSmallDto role : roleSet) { + DataScopeEnum dataScopeEnum = DataScopeEnum.find(role.getDataScope()); + switch (Objects.requireNonNull(dataScopeEnum)) { + case THIS_LEVEL: + deptIds.add(user.getDept().getId()); + break; + case CUSTOMIZE: + deptIds.addAll(getCustomize(deptIds, role)); + break; + default: + return new ArrayList<>(deptIds); + } + } + return new ArrayList<>(deptIds); + } + + /** + * 获取自定义的数据权限 + * @param deptIds 部门ID + * @param role 角色 + * @return 数据权限ID + */ + public Set<Long> getCustomize(Set<Long> deptIds, RoleSmallDto role){ + Set<Dept> depts = deptService.findByRoleId(role.getId()); + for (Dept dept : depts) { + deptIds.add(dept.getId()); + List<Dept> deptChildren = deptService.findByPid(dept.getId()); + if (deptChildren != null && deptChildren.size() != 0) { + deptIds.addAll(deptService.getDeptChildren(deptChildren)); + } + } + return deptIds; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DeptServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DeptServiceImpl.java new file mode 100644 index 0000000..e777319 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DeptServiceImpl.java @@ -0,0 +1,284 @@ +/* + * 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.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import com.example.modules.system.domain.Dept; +import com.example.modules.system.domain.User; +import com.example.modules.system.repository.DeptRepository; +import com.example.modules.system.repository.RoleRepository; +import com.example.modules.system.service.DeptService; +import com.example.modules.system.service.dto.DeptDto; +import com.example.modules.system.service.dto.DeptQueryCriteria; +import com.example.utils.*; +import lombok.RequiredArgsConstructor; +import com.example.exception.BadRequestException; +import com.example.modules.system.repository.UserRepository; +import com.example.utils.*; +import com.example.modules.system.service.mapstruct.DeptMapper; +import com.example.utils.enums.DataScopeEnum; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; + +/** +* +* 2019-03-25 +*/ +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "dept") +public class DeptServiceImpl implements DeptService { + + private final DeptRepository deptRepository; + private final DeptMapper deptMapper; + private final UserRepository userRepository; + private final RedisUtils redisUtils; + private final RoleRepository roleRepository; + + @Override + public List<DeptDto> queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception { + Sort sort = Sort.by(Sort.Direction.ASC, "deptSort"); + String dataScopeType = SecurityUtils.getDataScopeType(); + if (isQuery) { + if(dataScopeType.equals(DataScopeEnum.ALL.getValue())){ + criteria.setPidIsNull(true); + } + List<Field> fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>()); + List<String> fieldNames = new ArrayList<String>(){{ add("pidIsNull");add("enabled");}}; + for (Field field : fields) { + //设置对象的访问权限,保证对private的属性的访问 + field.setAccessible(true); + Object val = field.get(criteria); + if(fieldNames.contains(field.getName())){ + continue; + } + if (ObjectUtil.isNotNull(val)) { + criteria.setPidIsNull(null); + break; + } + } + } + List<DeptDto> list = deptMapper.toDto(deptRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort)); + // 如果为空,就代表为自定义权限或者本级权限,就需要去重,不理解可以注释掉,看查询结果 + if(StringUtils.isBlank(dataScopeType)){ + return deduplication(list); + } + return list; + } + + @Override + @Cacheable(key = "'id:' + #p0") + public DeptDto findById(Long id) { + Dept dept = deptRepository.findById(id).orElseGet(Dept::new); + ValidationUtil.isNull(dept.getId(),"Dept","id",id); + return deptMapper.toDto(dept); + } + + @Override + public List<Dept> findByPid(long pid) { + return deptRepository.findByPid(pid); + } + + @Override + public Set<Dept> findByRoleId(Long id) { + return deptRepository.findByRoleId(id); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(Dept resources) { + deptRepository.save(resources); + // 计算子节点数目 + resources.setSubCount(0); + // 清理缓存 + updateSubCnt(resources.getPid()); + // 清理自定义角色权限的datascope缓存 + delCaches(resources.getPid()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Dept resources) { + // 旧的部门 + Long oldPid = findById(resources.getId()).getPid(); + Long newPid = resources.getPid(); + if(resources.getPid() != null && resources.getId().equals(resources.getPid())) { + throw new BadRequestException("上级不能为自己"); + } + Dept dept = deptRepository.findById(resources.getId()).orElseGet(Dept::new); + ValidationUtil.isNull( dept.getId(),"Dept","id",resources.getId()); + resources.setId(dept.getId()); + deptRepository.save(resources); + // 更新父节点中子节点数目 + updateSubCnt(oldPid); + updateSubCnt(newPid); + // 清理缓存 + delCaches(resources.getId()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set<DeptDto> deptDtos) { + for (DeptDto deptDto : deptDtos) { + // 清理缓存 + delCaches(deptDto.getId()); + deptRepository.deleteById(deptDto.getId()); + updateSubCnt(deptDto.getPid()); + } + } + + @Override + public void download(List<DeptDto> deptDtos, HttpServletResponse response) throws IOException { + List<Map<String, Object>> list = new ArrayList<>(); + for (DeptDto deptDTO : deptDtos) { + Map<String,Object> map = new LinkedHashMap<>(); + map.put("部门名称", deptDTO.getName()); + map.put("部门状态", deptDTO.getEnabled() ? "启用" : "停用"); + map.put("创建日期", deptDTO.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + @Override + public Set<DeptDto> getDeleteDepts(List<Dept> menuList, Set<DeptDto> deptDtos) { + for (Dept dept : menuList) { + deptDtos.add(deptMapper.toDto(dept)); + List<Dept> depts = deptRepository.findByPid(dept.getId()); + if(depts!=null && depts.size()!=0){ + getDeleteDepts(depts, deptDtos); + } + } + return deptDtos; + } + + @Override + public List<Long> getDeptChildren(List<Dept> deptList) { + List<Long> list = new ArrayList<>(); + deptList.forEach(dept -> { + if (dept!=null && dept.getEnabled()) { + List<Dept> depts = deptRepository.findByPid(dept.getId()); + if (depts.size() != 0) { + list.addAll(getDeptChildren(depts)); + } + list.add(dept.getId()); + } + } + ); + return list; + } + + @Override + public List<DeptDto> getSuperior(DeptDto deptDto, List<Dept> depts) { + if(deptDto.getPid() == null){ + depts.addAll(deptRepository.findByPidIsNull()); + return deptMapper.toDto(depts); + } + depts.addAll(deptRepository.findByPid(deptDto.getPid())); + return getSuperior(findById(deptDto.getPid()), depts); + } + + @Override + public Object buildTree(List<DeptDto> deptDtos) { + Set<DeptDto> trees = new LinkedHashSet<>(); + Set<DeptDto> depts= new LinkedHashSet<>(); + List<String> deptNames = deptDtos.stream().map(DeptDto::getName).collect(Collectors.toList()); + boolean isChild; + for (DeptDto deptDTO : deptDtos) { + isChild = false; + if (deptDTO.getPid() == null) { + trees.add(deptDTO); + } + for (DeptDto it : deptDtos) { + if (it.getPid() != null && deptDTO.getId().equals(it.getPid())) { + isChild = true; + if (deptDTO.getChildren() == null) { + deptDTO.setChildren(new ArrayList<>()); + } + deptDTO.getChildren().add(it); + } + } + if(isChild) { + depts.add(deptDTO); + } else if(deptDTO.getPid() != null && !deptNames.contains(findById(deptDTO.getPid()).getName())) { + depts.add(deptDTO); + } + } + + if (CollectionUtil.isEmpty(trees)) { + trees = depts; + } + Map<String,Object> map = new HashMap<>(2); + map.put("totalElements",deptDtos.size()); + map.put("content",CollectionUtil.isEmpty(trees)? deptDtos :trees); + return map; + } + + @Override + public void verification(Set<DeptDto> deptDtos) { + Set<Long> deptIds = deptDtos.stream().map(DeptDto::getId).collect(Collectors.toSet()); + if(userRepository.countByDepts(deptIds) > 0){ + throw new BadRequestException("所选部门存在用户关联,请解除后再试!"); + } + if(roleRepository.countByDepts(deptIds) > 0){ + throw new BadRequestException("所选部门存在角色关联,请解除后再试!"); + } + } + + private void updateSubCnt(Long deptId){ + if(deptId != null){ + int count = deptRepository.countByPid(deptId); + deptRepository.updateSubCntById(count, deptId); + } + } + + private List<DeptDto> deduplication(List<DeptDto> list) { + List<DeptDto> deptDtos = new ArrayList<>(); + for (DeptDto deptDto : list) { + boolean flag = true; + for (DeptDto dto : list) { + if (dto.getId().equals(deptDto.getPid())) { + flag = false; + break; + } + } + if (flag){ + deptDtos.add(deptDto); + } + } + return deptDtos; + } + + /** + * 清理缓存 + * @param id / + */ + public void delCaches(Long id){ + List<User> users = userRepository.findByRoleDeptId(id); + // 删除数据权限 + redisUtils.delByKeys(CacheKey.DATA_USER, users.stream().map(User::getId).collect(Collectors.toSet())); + redisUtils.del(CacheKey.DEPT_ID + id); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictDetailServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictDetailServiceImpl.java new file mode 100644 index 0000000..672a31a --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictDetailServiceImpl.java @@ -0,0 +1,96 @@ +/* + * 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.impl; + +import com.example.modules.system.domain.Dict; +import com.example.modules.system.domain.DictDetail; +import com.example.utils.*; +import lombok.RequiredArgsConstructor; +import com.example.modules.system.repository.DictRepository; +import com.example.modules.system.service.dto.DictDetailQueryCriteria; +import com.example.utils.*; +import com.example.modules.system.repository.DictDetailRepository; +import com.example.modules.system.service.DictDetailService; +import com.example.modules.system.service.dto.DictDetailDto; +import com.example.modules.system.service.mapstruct.DictDetailMapper; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.Map; + +/** +* +* 2019-04-10 +*/ +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "dict") +public class DictDetailServiceImpl implements DictDetailService { + + private final DictRepository dictRepository; + private final DictDetailRepository dictDetailRepository; + private final DictDetailMapper dictDetailMapper; + private final RedisUtils redisUtils; + + @Override + public Map<String,Object> queryAll(DictDetailQueryCriteria criteria, Pageable pageable) { + Page<DictDetail> page = dictDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); + return PageUtil.toPage(page.map(dictDetailMapper::toDto)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(DictDetail resources) { + dictDetailRepository.save(resources); + // 清理缓存 + delCaches(resources); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(DictDetail resources) { + DictDetail dictDetail = dictDetailRepository.findById(resources.getId()).orElseGet(DictDetail::new); + ValidationUtil.isNull( dictDetail.getId(),"DictDetail","id",resources.getId()); + resources.setId(dictDetail.getId()); + dictDetailRepository.save(resources); + // 清理缓存 + delCaches(resources); + } + + @Override + @Cacheable(key = "'name:' + #p0") + public List<DictDetailDto> getDictByName(String name) { + return dictDetailMapper.toDto(dictDetailRepository.findByDictName(name)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Long id) { + DictDetail dictDetail = dictDetailRepository.findById(id).orElseGet(DictDetail::new); + // 清理缓存 + delCaches(dictDetail); + dictDetailRepository.deleteById(id); + } + + public void delCaches(DictDetail dictDetail){ + Dict dict = dictRepository.findById(dictDetail.getDict().getId()).orElseGet(Dict::new); + redisUtils.del(CacheKey.DICT_NAME + dict.getName()); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictServiceImpl.java new file mode 100644 index 0000000..79cd9e3 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/DictServiceImpl.java @@ -0,0 +1,122 @@ +/* + * 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.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.example.modules.system.domain.Dict; +import com.example.modules.system.service.dto.DictDto; +import com.example.utils.*; +import lombok.RequiredArgsConstructor; +import com.example.modules.system.service.dto.DictDetailDto; +import com.example.modules.system.service.dto.DictQueryCriteria; +import com.example.utils.*; +import com.example.modules.system.repository.DictRepository; +import com.example.modules.system.service.DictService; +import com.example.modules.system.service.mapstruct.DictMapper; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.*; + +/** +* +* 2019-04-10 +*/ +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "dict") +public class DictServiceImpl implements DictService { + + private final DictRepository dictRepository; + private final DictMapper dictMapper; + private final RedisUtils redisUtils; + + @Override + public Map<String, Object> queryAll(DictQueryCriteria dict, Pageable pageable){ + Page<Dict> page = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb), pageable); + return PageUtil.toPage(page.map(dictMapper::toDto)); + } + + @Override + public List<DictDto> queryAll(DictQueryCriteria dict) { + List<Dict> list = dictRepository.findAll((root, query, cb) -> QueryHelp.getPredicate(root, dict, cb)); + return dictMapper.toDto(list); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(Dict resources) { + dictRepository.save(resources); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Dict resources) { + // 清理缓存 + delCaches(resources); + Dict dict = dictRepository.findById(resources.getId()).orElseGet(Dict::new); + ValidationUtil.isNull( dict.getId(),"Dict","id",resources.getId()); + dict.setName(resources.getName()); + dict.setDescription(resources.getDescription()); + dictRepository.save(dict); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set<Long> ids) { + // 清理缓存 + List<Dict> dicts = dictRepository.findByIdIn(ids); + for (Dict dict : dicts) { + delCaches(dict); + } + dictRepository.deleteByIdIn(ids); + } + + @Override + public void download(List<DictDto> dictDtos, HttpServletResponse response) throws IOException { + List<Map<String, Object>> list = new ArrayList<>(); + for (DictDto dictDTO : dictDtos) { + if(CollectionUtil.isNotEmpty(dictDTO.getDictDetails())){ + for (DictDetailDto dictDetail : dictDTO.getDictDetails()) { + Map<String,Object> map = new LinkedHashMap<>(); + map.put("字典名称", dictDTO.getName()); + map.put("字典描述", dictDTO.getDescription()); + map.put("字典标签", dictDetail.getLabel()); + map.put("字典值", dictDetail.getValue()); + map.put("创建日期", dictDetail.getCreateTime()); + list.add(map); + } + } else { + Map<String,Object> map = new LinkedHashMap<>(); + map.put("字典名称", dictDTO.getName()); + map.put("字典描述", dictDTO.getDescription()); + map.put("字典标签", null); + map.put("字典值", null); + map.put("创建日期", dictDTO.getCreateTime()); + list.add(map); + } + } + FileUtil.downloadExcel(list, response); + } + + public void delCaches(Dict dict){ + redisUtils.del(CacheKey.DICT_NAME + dict.getName()); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/JobServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/JobServiceImpl.java new file mode 100644 index 0000000..73c93c5 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/JobServiceImpl.java @@ -0,0 +1,126 @@ +/* + * 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.impl; + +import com.example.modules.system.domain.Job; +import com.example.modules.system.service.JobService; +import com.example.modules.system.service.dto.JobDto; +import com.example.utils.*; +import lombok.RequiredArgsConstructor; +import com.example.exception.BadRequestException; +import com.example.exception.EntityExistException; +import com.example.modules.system.repository.UserRepository; +import com.example.modules.system.service.dto.JobQueryCriteria; +import com.example.utils.*; +import com.example.modules.system.repository.JobRepository; +import com.example.modules.system.service.mapstruct.JobMapper; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.*; + +/** +* +* 2019-03-29 +*/ +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "job") +public class JobServiceImpl implements JobService { + + private final JobRepository jobRepository; + private final JobMapper jobMapper; + private final RedisUtils redisUtils; + private final UserRepository userRepository; + + @Override + public Map<String,Object> queryAll(JobQueryCriteria criteria, Pageable pageable) { + Page<Job> page = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); + return PageUtil.toPage(page.map(jobMapper::toDto).getContent(),page.getTotalElements()); + } + + @Override + public List<JobDto> queryAll(JobQueryCriteria criteria) { + List<Job> list = jobRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)); + return jobMapper.toDto(list); + } + + @Override + @Cacheable(key = "'id:' + #p0") + public JobDto findById(Long id) { + Job job = jobRepository.findById(id).orElseGet(Job::new); + ValidationUtil.isNull(job.getId(),"Job","id",id); + return jobMapper.toDto(job); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(Job resources) { + Job job = jobRepository.findByName(resources.getName()); + if(job != null){ + throw new EntityExistException(Job.class,"name",resources.getName()); + } + jobRepository.save(resources); + } + + @Override + @CacheEvict(key = "'id:' + #p0.id") + @Transactional(rollbackFor = Exception.class) + public void update(Job resources) { + Job job = jobRepository.findById(resources.getId()).orElseGet(Job::new); + Job old = jobRepository.findByName(resources.getName()); + if(old != null && !old.getId().equals(resources.getId())){ + throw new EntityExistException(Job.class,"name",resources.getName()); + } + ValidationUtil.isNull( job.getId(),"Job","id",resources.getId()); + resources.setId(job.getId()); + jobRepository.save(resources); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set<Long> ids) { + jobRepository.deleteAllByIdIn(ids); + // 删除缓存 + redisUtils.delByKeys(CacheKey.JOB_ID, ids); + } + + @Override + public void download(List<JobDto> jobDtos, HttpServletResponse response) throws IOException { + List<Map<String, Object>> list = new ArrayList<>(); + for (JobDto jobDTO : jobDtos) { + Map<String,Object> map = new LinkedHashMap<>(); + map.put("岗位名称", jobDTO.getName()); + map.put("岗位状态", jobDTO.getEnabled() ? "启用" : "停用"); + map.put("创建日期", jobDTO.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + @Override + public void verification(Set<Long> ids) { + if(userRepository.countByJobs(ids) > 0){ + throw new BadRequestException("所选的岗位中存在用户关联,请解除关联再试!"); + } + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MenuServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MenuServiceImpl.java new file mode 100644 index 0000000..ceacddb --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MenuServiceImpl.java @@ -0,0 +1,356 @@ +/* + * 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.impl; + +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; +import com.example.modules.system.domain.Menu; +import com.example.modules.system.domain.Role; +import com.example.modules.system.domain.User; +import com.example.modules.system.domain.vo.MenuMetaVo; +import com.example.modules.system.domain.vo.MenuVo; +import com.example.modules.system.repository.MenuRepository; +import com.example.modules.system.service.MenuService; +import com.example.modules.system.service.RoleService; +import com.example.modules.system.service.dto.MenuDto; +import com.example.modules.system.service.dto.MenuQueryCriteria; +import com.example.modules.system.service.dto.RoleSmallDto; +import com.example.utils.*; +import lombok.RequiredArgsConstructor; +import com.example.exception.BadRequestException; +import com.example.exception.EntityExistException; +import com.example.modules.system.repository.UserRepository; +import com.example.modules.system.service.mapstruct.MenuMapper; +import com.example.utils.*; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; + +/** + * + */ +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "menu") +public class MenuServiceImpl implements MenuService { + + private final MenuRepository menuRepository; + private final UserRepository userRepository; + private final MenuMapper menuMapper; + private final RoleService roleService; + private final RedisUtils redisUtils; + + @Override + public List<MenuDto> queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception { + Sort sort = Sort.by(Sort.Direction.ASC, "menuSort"); + if(Boolean.TRUE.equals(isQuery)){ + criteria.setPidIsNull(true); + List<Field> fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>()); + for (Field field : fields) { + //设置对象的访问权限,保证对private的属性的访问 + field.setAccessible(true); + Object val = field.get(criteria); + if("pidIsNull".equals(field.getName())){ + continue; + } + if (ObjectUtil.isNotNull(val)) { + criteria.setPidIsNull(null); + break; + } + } + } + return menuMapper.toDto(menuRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),sort)); + } + + @Override + @Cacheable(key = "'id:' + #p0") + public MenuDto findById(long id) { + Menu menu = menuRepository.findById(id).orElseGet(Menu::new); + ValidationUtil.isNull(menu.getId(),"Menu","id",id); + return menuMapper.toDto(menu); + } + + /** + * 用户角色改变时需清理缓存 + * @param currentUserId / + * @return / + */ + @Override + @Cacheable(key = "'user:' + #p0") + public List<MenuDto> findByUser(Long currentUserId) { + List<RoleSmallDto> roles = roleService.findByUsersId(currentUserId); + Set<Long> roleIds = roles.stream().map(RoleSmallDto::getId).collect(Collectors.toSet()); + LinkedHashSet<Menu> menus = menuRepository.findByRoleIdsAndTypeNot(roleIds, 2); + return menus.stream().map(menuMapper::toDto).collect(Collectors.toList()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(Menu resources) { + if(menuRepository.findByTitle(resources.getTitle()) != null){ + throw new EntityExistException(Menu.class,"title",resources.getTitle()); + } + if(StringUtils.isNotBlank(resources.getComponentName())){ + if(menuRepository.findByComponentName(resources.getComponentName()) != null){ + throw new EntityExistException(Menu.class,"componentName",resources.getComponentName()); + } + } + if(resources.getPid().equals(0L)){ + resources.setPid(null); + } + if(resources.getIFrame()){ + String http = "http://", https = "https://"; + if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) { + throw new BadRequestException("外链必须以http://或者https://开头"); + } + } + menuRepository.save(resources); + // 计算子节点数目 + resources.setSubCount(0); + // 更新父节点菜单数目 + updateSubCnt(resources.getPid()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Menu resources) { + if(resources.getId().equals(resources.getPid())) { + throw new BadRequestException("上级不能为自己"); + } + Menu menu = menuRepository.findById(resources.getId()).orElseGet(Menu::new); + ValidationUtil.isNull(menu.getId(),"Permission","id",resources.getId()); + + if(resources.getIFrame()){ + String http = "http://", https = "https://"; + if (!(resources.getPath().toLowerCase().startsWith(http)||resources.getPath().toLowerCase().startsWith(https))) { + throw new BadRequestException("外链必须以http://或者https://开头"); + } + } + Menu menu1 = menuRepository.findByTitle(resources.getTitle()); + + if(menu1 != null && !menu1.getId().equals(menu.getId())){ + throw new EntityExistException(Menu.class,"title",resources.getTitle()); + } + + if(resources.getPid().equals(0L)){ + resources.setPid(null); + } + + // 记录的父节点ID + Long oldPid = menu.getPid(); + Long newPid = resources.getPid(); + + if(StringUtils.isNotBlank(resources.getComponentName())){ + menu1 = menuRepository.findByComponentName(resources.getComponentName()); + if(menu1 != null && !menu1.getId().equals(menu.getId())){ + throw new EntityExistException(Menu.class,"componentName",resources.getComponentName()); + } + } + menu.setTitle(resources.getTitle()); + menu.setComponent(resources.getComponent()); + menu.setPath(resources.getPath()); + menu.setIcon(resources.getIcon()); + menu.setIFrame(resources.getIFrame()); + menu.setPid(resources.getPid()); + menu.setMenuSort(resources.getMenuSort()); + menu.setCache(resources.getCache()); + menu.setHidden(resources.getHidden()); + menu.setComponentName(resources.getComponentName()); + menu.setPermission(resources.getPermission()); + menu.setType(resources.getType()); + menuRepository.save(menu); + // 计算父级菜单节点数目 + updateSubCnt(oldPid); + updateSubCnt(newPid); + // 清理缓存 + delCaches(resources.getId()); + } + + @Override + public Set<Menu> getChildMenus(List<Menu> menuList, Set<Menu> menuSet) { + for (Menu menu : menuList) { + menuSet.add(menu); + List<Menu> menus = menuRepository.findByPid(menu.getId()); + if(menus!=null && menus.size()!=0){ + getChildMenus(menus, menuSet); + } + } + return menuSet; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set<Menu> menuSet) { + for (Menu menu : menuSet) { + // 清理缓存 + delCaches(menu.getId()); + roleService.untiedMenu(menu.getId()); + menuRepository.deleteById(menu.getId()); + updateSubCnt(menu.getPid()); + } + } + + @Override + public List<MenuDto> getMenus(Long pid) { + List<Menu> menus; + if(pid != null && !pid.equals(0L)){ + menus = menuRepository.findByPid(pid); + } else { + menus = menuRepository.findByPidIsNull(); + } + return menuMapper.toDto(menus); + } + + @Override + public List<MenuDto> getSuperior(MenuDto menuDto, List<Menu> menus) { + if(menuDto.getPid() == null){ + menus.addAll(menuRepository.findByPidIsNull()); + return menuMapper.toDto(menus); + } + menus.addAll(menuRepository.findByPid(menuDto.getPid())); + return getSuperior(findById(menuDto.getPid()), menus); + } + + @Override + public List<MenuDto> buildTree(List<MenuDto> menuDtos) { + List<MenuDto> trees = new ArrayList<>(); + Set<Long> ids = new HashSet<>(); + for (MenuDto menuDTO : menuDtos) { + if (menuDTO.getPid() == null) { + trees.add(menuDTO); + } + for (MenuDto it : menuDtos) { + if (menuDTO.getId().equals(it.getPid())) { + if (menuDTO.getChildren() == null) { + menuDTO.setChildren(new ArrayList<>()); + } + menuDTO.getChildren().add(it); + ids.add(it.getId()); + } + } + } + if(trees.size() == 0){ + trees = menuDtos.stream().filter(s -> !ids.contains(s.getId())).collect(Collectors.toList()); + } + return trees; + } + + @Override + public List<MenuVo> buildMenus(List<MenuDto> menuDtos) { + List<MenuVo> list = new LinkedList<>(); + menuDtos.forEach(menuDTO -> { + if (menuDTO!=null){ + List<MenuDto> menuDtoList = menuDTO.getChildren(); + MenuVo menuVo = new MenuVo(); + menuVo.setName(ObjectUtil.isNotEmpty(menuDTO.getComponentName()) ? menuDTO.getComponentName() : menuDTO.getTitle()); + // 一级目录需要加斜杠,不然会报警告 + menuVo.setPath(menuDTO.getPid() == null ? "/" + menuDTO.getPath() :menuDTO.getPath()); + menuVo.setHidden(menuDTO.getHidden()); + // 如果不是外链 + if(!menuDTO.getIFrame()){ + if(menuDTO.getPid() == null){ + menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"Layout":menuDTO.getComponent()); + // 如果不是一级菜单,并且菜单类型为目录,则代表是多级菜单 + }else if(menuDTO.getType() == 0){ + menuVo.setComponent(StringUtils.isEmpty(menuDTO.getComponent())?"ParentView":menuDTO.getComponent()); + }else if(StringUtils.isNoneBlank(menuDTO.getComponent())){ + menuVo.setComponent(menuDTO.getComponent()); + } + } + menuVo.setMeta(new MenuMetaVo(menuDTO.getTitle(),menuDTO.getIcon(),!menuDTO.getCache())); + if(CollectionUtil.isNotEmpty(menuDtoList)){ + menuVo.setAlwaysShow(true); + menuVo.setRedirect("noredirect"); + menuVo.setChildren(buildMenus(menuDtoList)); + // 处理是一级菜单并且没有子菜单的情况 + } else if(menuDTO.getPid() == null){ + MenuVo menuVo1 = new MenuVo(); + menuVo1.setMeta(menuVo.getMeta()); + // 非外链 + if(!menuDTO.getIFrame()){ + menuVo1.setPath("index"); + menuVo1.setName(menuVo.getName()); + menuVo1.setComponent(menuVo.getComponent()); + } else { + menuVo1.setPath(menuDTO.getPath()); + } + menuVo.setName(null); + menuVo.setMeta(null); + menuVo.setComponent("Layout"); + List<MenuVo> list1 = new ArrayList<>(); + list1.add(menuVo1); + menuVo.setChildren(list1); + } + list.add(menuVo); + } + } + ); + return list; + } + + @Override + public Menu findOne(Long id) { + Menu menu = menuRepository.findById(id).orElseGet(Menu::new); + ValidationUtil.isNull(menu.getId(),"Menu","id",id); + return menu; + } + + @Override + public void download(List<MenuDto> menuDtos, HttpServletResponse response) throws IOException { + List<Map<String, Object>> list = new ArrayList<>(); + for (MenuDto menuDTO : menuDtos) { + Map<String,Object> map = new LinkedHashMap<>(); + map.put("菜单标题", menuDTO.getTitle()); + map.put("菜单类型", menuDTO.getType() == null ? "目录" : menuDTO.getType() == 1 ? "菜单" : "按钮"); + map.put("权限标识", menuDTO.getPermission()); + map.put("外链菜单", menuDTO.getIFrame() ? "是" : "否"); + map.put("菜单可见", menuDTO.getHidden() ? "否" : "是"); + map.put("是否缓存", menuDTO.getCache() ? "是" : "否"); + map.put("创建日期", menuDTO.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + private void updateSubCnt(Long menuId){ + if(menuId != null){ + int count = menuRepository.countByPid(menuId); + menuRepository.updateSubCntById(count, menuId); + } + } + + /** + * 清理缓存 + * @param id 菜单ID + */ + public void delCaches(Long id){ + List<User> users = userRepository.findByMenuId(id); + redisUtils.del(CacheKey.MENU_ID + id); + redisUtils.delByKeys(CacheKey.MENU_USER, users.stream().map(User::getId).collect(Collectors.toSet())); + // 清除 Role 缓存 + List<Role> roles = roleService.findInMenuId(new ArrayList<Long>(){{ + add(id); + }}); + redisUtils.delByKeys(CacheKey.ROLE_ID, roles.stream().map(Role::getId).collect(Collectors.toSet())); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MonitorServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MonitorServiceImpl.java new file mode 100644 index 0000000..c279293 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/MonitorServiceImpl.java @@ -0,0 +1,186 @@ +/* + * 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.impl; + +import cn.hutool.core.date.BetweenFormater; +import cn.hutool.core.date.DateUtil; +import com.example.modules.system.service.MonitorService; +import com.example.utils.ElAdminConstant; +import com.example.utils.FileUtil; +import com.example.utils.StringUtils; +import org.springframework.stereotype.Service; +import oshi.SystemInfo; +import oshi.hardware.*; +import oshi.software.os.FileSystem; +import oshi.software.os.OSFileStore; +import oshi.software.os.OperatingSystem; +import oshi.util.FormatUtil; +import oshi.util.Util; +import java.lang.management.ManagementFactory; +import java.text.DecimalFormat; +import java.util.*; + +/** +* +* 2020-05-02 +*/ +@Service +public class MonitorServiceImpl implements MonitorService { + + private final DecimalFormat df = new DecimalFormat("0.00"); + + @Override + public Map<String,Object> getServers(){ + Map<String, Object> resultMap = new LinkedHashMap<>(8); + try { + SystemInfo si = new SystemInfo(); + OperatingSystem os = si.getOperatingSystem(); + HardwareAbstractionLayer hal = si.getHardware(); + // 系统信息 + resultMap.put("sys", getSystemInfo(os)); + // cpu 信息 + resultMap.put("cpu", getCpuInfo(hal.getProcessor())); + // 内存信息 + resultMap.put("memory", getMemoryInfo(hal.getMemory())); + // 交换区信息 + resultMap.put("swap", getSwapInfo(hal.getMemory())); + // 磁盘 + resultMap.put("disk", getDiskInfo(os)); + resultMap.put("time", DateUtil.format(new Date(), "HH:mm:ss")); + } catch (Exception e) { + e.printStackTrace(); + } + return resultMap; + } + + /** + * 获取磁盘信息 + * @return / + */ + private Map<String,Object> getDiskInfo(OperatingSystem os) { + Map<String,Object> diskInfo = new LinkedHashMap<>(); + FileSystem fileSystem = os.getFileSystem(); + List<OSFileStore> fsArray = fileSystem.getFileStores(); + String osName = System.getProperty("os.name"); + long available = 0, total = 0; + for (OSFileStore fs : fsArray){ + // windows 需要将所有磁盘分区累加,linux 和 mac 直接累加会出现磁盘重复的问题,待修复 + if(osName.toLowerCase().startsWith(ElAdminConstant.WIN)) { + available += fs.getUsableSpace(); + total += fs.getTotalSpace(); + } else { + available = fs.getUsableSpace(); + total = fs.getTotalSpace(); + break; + } + } + long used = total - available; + diskInfo.put("total", total > 0 ? FileUtil.getSize(total) : "?"); + diskInfo.put("available", FileUtil.getSize(available)); + diskInfo.put("used", FileUtil.getSize(used)); + if(total != 0){ + diskInfo.put("usageRate", df.format(used/(double)total * 100)); + } else { + diskInfo.put("usageRate", 0); + } + return diskInfo; + } + + /** + * 获取交换区信息 + * @param memory / + * @return / + */ + private Map<String,Object> getSwapInfo(GlobalMemory memory) { + Map<String,Object> swapInfo = new LinkedHashMap<>(); + VirtualMemory virtualMemory = memory.getVirtualMemory(); + long total = virtualMemory.getSwapTotal(); + long used = virtualMemory.getSwapUsed(); + swapInfo.put("total", FormatUtil.formatBytes(total)); + swapInfo.put("used", FormatUtil.formatBytes(used)); + swapInfo.put("available", FormatUtil.formatBytes(total - used)); + if(used == 0){ + swapInfo.put("usageRate", 0); + } else { + swapInfo.put("usageRate", df.format(used/(double)total * 100)); + } + return swapInfo; + } + + /** + * 获取内存信息 + * @param memory / + * @return / + */ + private Map<String,Object> getMemoryInfo(GlobalMemory memory) { + Map<String,Object> memoryInfo = new LinkedHashMap<>(); + memoryInfo.put("total", FormatUtil.formatBytes(memory.getTotal())); + memoryInfo.put("available", FormatUtil.formatBytes(memory.getAvailable())); + memoryInfo.put("used", FormatUtil.formatBytes(memory.getTotal() - memory.getAvailable())); + memoryInfo.put("usageRate", df.format((memory.getTotal() - memory.getAvailable())/(double)memory.getTotal() * 100)); + return memoryInfo; + } + + /** + * 获取Cpu相关信息 + * @param processor / + * @return / + */ + private Map<String,Object> getCpuInfo(CentralProcessor processor) { + Map<String,Object> cpuInfo = new LinkedHashMap<>(); + cpuInfo.put("name", processor.getProcessorIdentifier().getName()); + cpuInfo.put("package", processor.getPhysicalPackageCount() + "个物理CPU"); + cpuInfo.put("core", processor.getPhysicalProcessorCount() + "个物理核心"); + cpuInfo.put("coreNumber", processor.getPhysicalProcessorCount()); + cpuInfo.put("logic", processor.getLogicalProcessorCount() + "个逻辑CPU"); + // CPU信息 + long[] prevTicks = processor.getSystemCpuLoadTicks(); + // 等待1秒... + Util.sleep(1000); + long[] ticks = processor.getSystemCpuLoadTicks(); + long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()]; + long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()]; + long sys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()]; + long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()]; + long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()]; + long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()]; + long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()]; + long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()]; + long totalCpu = user + nice + sys + idle + iowait + irq + softirq + steal; + cpuInfo.put("used", df.format(100d * user / totalCpu + 100d * sys / totalCpu)); + cpuInfo.put("idle", df.format(100d * idle / totalCpu)); + return cpuInfo; + } + + /** + * 获取系统相关信息,系统、运行天数、系统IP + * @param os / + * @return / + */ + private Map<String,Object> getSystemInfo(OperatingSystem os){ + Map<String,Object> systemInfo = new LinkedHashMap<>(); + // jvm 运行时间 + long time = ManagementFactory.getRuntimeMXBean().getStartTime(); + Date date = new Date(time); + // 计算项目运行时间 + String formatBetween = DateUtil.formatBetween(date, new Date(),BetweenFormater.Level.HOUR); + // 系统信息 + systemInfo.put("os", os.toString()); + systemInfo.put("day", formatBetween); + systemInfo.put("ip", StringUtils.getLocalIp()); + return systemInfo; + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/RoleServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..4a54a8c --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/RoleServiceImpl.java @@ -0,0 +1,227 @@ +/* + * 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.impl; + +import cn.hutool.core.collection.CollectionUtil; +import com.example.modules.system.domain.Menu; +import com.example.modules.system.domain.Role; +import com.example.modules.system.domain.User; +import com.example.modules.system.service.dto.RoleDto; +import com.example.modules.system.service.dto.RoleQueryCriteria; +import com.example.utils.*; +import lombok.RequiredArgsConstructor; +import com.example.exception.BadRequestException; +import com.example.modules.security.service.UserCacheClean; +import com.example.exception.EntityExistException; +import com.example.modules.system.repository.RoleRepository; +import com.example.modules.system.repository.UserRepository; +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.mapstruct.RoleMapper; +import com.example.modules.system.service.mapstruct.RoleSmallMapper; +import com.example.utils.*; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + +/** + * + * 2018-12-03 + */ +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "role") +public class RoleServiceImpl implements RoleService { + + private final RoleRepository roleRepository; + private final RoleMapper roleMapper; + private final RoleSmallMapper roleSmallMapper; + private final RedisUtils redisUtils; + private final UserRepository userRepository; + private final UserCacheClean userCacheClean; + + @Override + public List<RoleDto> queryAll() { + Sort sort = Sort.by(Sort.Direction.ASC, "level"); + return roleMapper.toDto(roleRepository.findAll(sort)); + } + + @Override + public List<RoleDto> queryAll(RoleQueryCriteria criteria) { + return roleMapper.toDto(roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder))); + } + + @Override + public Object queryAll(RoleQueryCriteria criteria, Pageable pageable) { + Page<Role> page = roleRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable); + return PageUtil.toPage(page.map(roleMapper::toDto)); + } + + @Override + @Cacheable(key = "'id:' + #p0") + @Transactional(rollbackFor = Exception.class) + public RoleDto findById(long id) { + Role role = roleRepository.findById(id).orElseGet(Role::new); + ValidationUtil.isNull(role.getId(), "Role", "id", id); + return roleMapper.toDto(role); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(Role resources) { + if (roleRepository.findByName(resources.getName()) != null) { + throw new EntityExistException(Role.class, "username", resources.getName()); + } + roleRepository.save(resources); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(Role resources) { + Role role = roleRepository.findById(resources.getId()).orElseGet(Role::new); + ValidationUtil.isNull(role.getId(), "Role", "id", resources.getId()); + + Role role1 = roleRepository.findByName(resources.getName()); + + if (role1 != null && !role1.getId().equals(role.getId())) { + throw new EntityExistException(Role.class, "username", resources.getName()); + } + role.setName(resources.getName()); + role.setDescription(resources.getDescription()); + role.setDataScope(resources.getDataScope()); + role.setDepts(resources.getDepts()); + role.setLevel(resources.getLevel()); + roleRepository.save(role); + // 更新相关缓存 + delCaches(role.getId(), null); + } + + @Override + public void updateMenu(Role resources, RoleDto roleDTO) { + Role role = roleMapper.toEntity(roleDTO); + List<User> users = userRepository.findByRoleId(role.getId()); + // 更新菜单 + role.setMenus(resources.getMenus()); + delCaches(resources.getId(), users); + roleRepository.save(role); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void untiedMenu(Long menuId) { + // 更新菜单 + roleRepository.untiedMenu(menuId); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set<Long> ids) { + for (Long id : ids) { + // 更新相关缓存 + delCaches(id, null); + } + roleRepository.deleteAllByIdIn(ids); + } + + @Override + public List<RoleSmallDto> findByUsersId(Long id) { + return roleSmallMapper.toDto(new ArrayList<>(roleRepository.findByUserId(id))); + } + + @Override + public Integer findByRoles(Set<Role> roles) { + if (roles.size() == 0) { + return Integer.MAX_VALUE; + } + Set<RoleDto> roleDtos = new HashSet<>(); + for (Role role : roles) { + roleDtos.add(findById(role.getId())); + } + return Collections.min(roleDtos.stream().map(RoleDto::getLevel).collect(Collectors.toList())); + } + + @Override + @Cacheable(key = "'auth:' + #p0.id") + public List<GrantedAuthority> mapToGrantedAuthorities(UserDto user) { + Set<String> permissions = new HashSet<>(); + // 如果是管理员直接返回 + if (user.getIsAdmin()) { + permissions.add("admin"); + return permissions.stream().map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + } + Set<Role> roles = roleRepository.findByUserId(user.getId()); + permissions = roles.stream().flatMap(role -> role.getMenus().stream()) + .filter(menu -> StringUtils.isNotBlank(menu.getPermission())) + .map(Menu::getPermission).collect(Collectors.toSet()); + return permissions.stream().map(SimpleGrantedAuthority::new) + .collect(Collectors.toList()); + } + + @Override + public void download(List<RoleDto> roles, HttpServletResponse response) throws IOException { + List<Map<String, Object>> list = new ArrayList<>(); + for (RoleDto role : roles) { + Map<String, Object> map = new LinkedHashMap<>(); + map.put("角色名称", role.getName()); + map.put("角色级别", role.getLevel()); + map.put("描述", role.getDescription()); + map.put("创建日期", role.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + @Override + public void verification(Set<Long> ids) { + if (userRepository.countByRoles(ids) > 0) { + throw new BadRequestException("所选角色存在用户关联,请解除关联再试!"); + } + } + + @Override + public List<Role> findInMenuId(List<Long> menuIds) { + return roleRepository.findInMenuId(menuIds); + } + + /** + * 清理缓存 + * @param id / + */ + public void delCaches(Long id, List<User> users) { + users = CollectionUtil.isEmpty(users) ? userRepository.findByRoleId(id) : users; + if (CollectionUtil.isNotEmpty(users)) { + users.forEach(item -> userCacheClean.cleanUserCache(item.getUsername())); + Set<Long> userIds = users.stream().map(User::getId).collect(Collectors.toSet()); + redisUtils.delByKeys(CacheKey.DATA_USER, userIds); + redisUtils.delByKeys(CacheKey.MENU_USER, userIds); + redisUtils.delByKeys(CacheKey.ROLE_AUTH, userIds); + } + redisUtils.del(CacheKey.ROLE_ID + id); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/UserServiceImpl.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..6b86b77 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/impl/UserServiceImpl.java @@ -0,0 +1,255 @@ +/* + * 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.impl; + +import com.example.modules.system.domain.User; +import com.example.modules.system.service.UserService; +import com.example.modules.system.service.dto.JobSmallDto; +import com.example.modules.system.service.dto.UserQueryCriteria; +import com.example.utils.*; +import lombok.RequiredArgsConstructor; +import com.example.config.FileProperties; +import com.example.exception.BadRequestException; +import com.example.modules.security.service.OnlineUserService; +import com.example.modules.security.service.UserCacheClean; +import com.example.exception.EntityExistException; +import com.example.exception.EntityNotFoundException; +import com.example.modules.system.repository.UserRepository; +import com.example.modules.system.service.dto.RoleSmallDto; +import com.example.modules.system.service.dto.UserDto; +import com.example.modules.system.service.mapstruct.UserMapper; +import com.example.utils.*; +import org.springframework.cache.annotation.CacheConfig; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotBlank; +import java.io.File; +import java.io.IOException; +import java.util.*; +import java.util.stream.Collectors; + + +@Service +@RequiredArgsConstructor +@CacheConfig(cacheNames = "user") +public class UserServiceImpl implements UserService { + + private final UserRepository userRepository; + private final UserMapper userMapper; + private final FileProperties properties; + private final RedisUtils redisUtils; + private final UserCacheClean userCacheClean; + private final OnlineUserService onlineUserService; + + @Override + public Object queryAll(UserQueryCriteria criteria, Pageable pageable) { + Page<User> page = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable); + return PageUtil.toPage(page.map(userMapper::toDto)); + } + + @Override + public List<UserDto> queryAll(UserQueryCriteria criteria) { + List<User> users = userRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)); + return userMapper.toDto(users); + } + + @Override + @Cacheable(key = "'id:' + #p0") + @Transactional(rollbackFor = Exception.class) + public UserDto findById(long id) { + User user = userRepository.findById(id).orElseGet(User::new); + ValidationUtil.isNull(user.getId(), "User", "id", id); + return userMapper.toDto(user); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void create(User resources) { + if (userRepository.findByUsername(resources.getUsername()) != null) { + throw new EntityExistException(User.class, "username", resources.getUsername()); + } + if (userRepository.findByEmail(resources.getEmail()) != null) { + throw new EntityExistException(User.class, "email", resources.getEmail()); + } + if (userRepository.findByPhone(resources.getPhone()) != null) { + throw new EntityExistException(User.class, "phone", resources.getPhone()); + } + userRepository.save(resources); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(User resources) throws Exception { + User user = userRepository.findById(resources.getId()).orElseGet(User::new); + ValidationUtil.isNull(user.getId(), "User", "id", resources.getId()); + User user1 = userRepository.findByUsername(resources.getUsername()); + User user2 = userRepository.findByEmail(resources.getEmail()); + User user3 = userRepository.findByPhone(resources.getPhone()); + if (user1 != null && !user.getId().equals(user1.getId())) { + throw new EntityExistException(User.class, "username", resources.getUsername()); + } + if (user2 != null && !user.getId().equals(user2.getId())) { + throw new EntityExistException(User.class, "email", resources.getEmail()); + } + if (user3 != null && !user.getId().equals(user3.getId())) { + throw new EntityExistException(User.class, "phone", resources.getPhone()); + } + // 如果用户的角色改变 + if (!resources.getRoles().equals(user.getRoles())) { + redisUtils.del(CacheKey.DATA_USER + resources.getId()); + redisUtils.del(CacheKey.MENU_USER + resources.getId()); + redisUtils.del(CacheKey.ROLE_AUTH + resources.getId()); + } + // 如果用户被禁用,则清除用户登录信息 + if(!resources.getEnabled()){ + onlineUserService.kickOutForUsername(resources.getUsername()); + } + user.setUsername(resources.getUsername()); + user.setEmail(resources.getEmail()); + user.setEnabled(resources.getEnabled()); + user.setRoles(resources.getRoles()); + user.setDept(resources.getDept()); + user.setJobs(resources.getJobs()); + user.setPhone(resources.getPhone()); + user.setNickName(resources.getNickName()); + user.setGender(resources.getGender()); + userRepository.save(user); + // 清除缓存 + delCaches(user.getId(), user.getUsername()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateCenter(User resources) { + User user = userRepository.findById(resources.getId()).orElseGet(User::new); + User user1 = userRepository.findByPhone(resources.getPhone()); + if (user1 != null && !user.getId().equals(user1.getId())) { + throw new EntityExistException(User.class, "phone", resources.getPhone()); + } + user.setNickName(resources.getNickName()); + user.setPhone(resources.getPhone()); + user.setGender(resources.getGender()); + userRepository.save(user); + // 清理缓存 + delCaches(user.getId(), user.getUsername()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void delete(Set<Long> ids) { + for (Long id : ids) { + // 清理缓存 + UserDto user = findById(id); + delCaches(user.getId(), user.getUsername()); + } + userRepository.deleteAllByIdIn(ids); + } + + @Override + public UserDto findByName(String userName) { + User user = userRepository.findByUsername(userName); + if (user == null) { + throw new EntityNotFoundException(User.class, "name", userName); + } else { + return userMapper.toDto(user); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePass(String username, String pass) { + userRepository.updatePass(username, pass, new Date()); + flushCache(username); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Map<String, String> updateAvatar(MultipartFile multipartFile) { + // 文件大小验证 + FileUtil.checkSize(properties.getAvatarMaxSize(), multipartFile.getSize()); + // 验证文件上传的格式 + String image = "gif jpg png jpeg"; + String fileType = FileUtil.getExtensionName(multipartFile.getOriginalFilename()); + if(fileType != null && !image.contains(fileType)){ + throw new BadRequestException("文件格式错误!, 仅支持 " + image +" 格式"); + } + User user = userRepository.findByUsername(SecurityUtils.getCurrentUsername()); + String oldPath = user.getAvatarPath(); + File file = FileUtil.upload(multipartFile, properties.getPath().getAvatar()); + user.setAvatarPath(Objects.requireNonNull(file).getPath()); + user.setAvatarName(file.getName()); + userRepository.save(user); + if (StringUtils.isNotBlank(oldPath)) { + FileUtil.del(oldPath); + } + @NotBlank String username = user.getUsername(); + flushCache(username); + return new HashMap<String, String>(1) {{ + put("avatar", file.getName()); + }}; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateEmail(String username, String email) { + userRepository.updateEmail(username, email); + flushCache(username); + } + + @Override + public void download(List<UserDto> queryAll, HttpServletResponse response) throws IOException { + List<Map<String, Object>> list = new ArrayList<>(); + for (UserDto userDTO : queryAll) { + List<String> roles = userDTO.getRoles().stream().map(RoleSmallDto::getName).collect(Collectors.toList()); + Map<String, Object> map = new LinkedHashMap<>(); + map.put("用户名", userDTO.getUsername()); + map.put("角色", roles); + map.put("部门", userDTO.getDept().getName()); + map.put("岗位", userDTO.getJobs().stream().map(JobSmallDto::getName).collect(Collectors.toList())); + map.put("邮箱", userDTO.getEmail()); + map.put("状态", userDTO.getEnabled() ? "启用" : "禁用"); + map.put("手机号码", userDTO.getPhone()); + map.put("修改密码的时间", userDTO.getPwdResetTime()); + map.put("创建日期", userDTO.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + /** + * 清理缓存 + * + * @param id / + */ + public void delCaches(Long id, String username) { + redisUtils.del(CacheKey.USER_ID + id); + flushCache(username); + } + + /** + * 清理 登陆时 用户缓存信息 + * + * @param username / + */ + private void flushCache(String username) { + userCacheClean.cleanUserCache(username); + } +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptMapper.java new file mode 100644 index 0000000..25de23f --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Dept; +import com.example.modules.system.service.dto.DeptDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* +* 2019-03-25 +*/ +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DeptMapper extends BaseMapper<DeptDto, Dept> { +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptSmallMapper.java new file mode 100644 index 0000000..01b7c65 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DeptSmallMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Dept; +import com.example.modules.system.service.dto.DeptSmallDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* +* 2019-03-25 +*/ +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DeptSmallMapper extends BaseMapper<DeptSmallDto, Dept> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictDetailMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictDetailMapper.java new file mode 100644 index 0000000..42ad48c --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictDetailMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.DictDetail; +import com.example.modules.system.service.dto.DictDetailDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* +* 2019-04-10 +*/ +@Mapper(componentModel = "spring", uses = {DictSmallMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DictDetailMapper extends BaseMapper<DictDetailDto, DictDetail> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictMapper.java new file mode 100644 index 0000000..24b763e --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Dict; +import com.example.modules.system.service.dto.DictDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* +* 2019-04-10 +*/ +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DictMapper extends BaseMapper<DictDto, Dict> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictSmallMapper.java new file mode 100644 index 0000000..8f05535 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/DictSmallMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Dict; +import com.example.modules.system.service.dto.DictSmallDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* +* 2019-04-10 +*/ +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface DictSmallMapper extends BaseMapper<DictSmallDto, Dict> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobMapper.java new file mode 100644 index 0000000..90be895 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Job; +import com.example.modules.system.service.dto.JobDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* +* 2019-03-29 +*/ +@Mapper(componentModel = "spring",uses = {DeptMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface JobMapper extends BaseMapper<JobDto, Job> { +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobSmallMapper.java new file mode 100644 index 0000000..9a36c91 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/JobSmallMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Job; +import com.example.modules.system.service.dto.JobSmallDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* +* 2019-03-29 +*/ +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface JobSmallMapper extends BaseMapper<JobSmallDto, Job> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/MenuMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/MenuMapper.java new file mode 100644 index 0000000..867cbf2 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/MenuMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Menu; +import com.example.modules.system.service.dto.MenuDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** + * + * 2018-12-17 + */ +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface MenuMapper extends BaseMapper<MenuDto, Menu> { +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleMapper.java new file mode 100644 index 0000000..929b14b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleMapper.java @@ -0,0 +1,28 @@ +/* + * 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.mapstruct; + +import com.example.modules.system.domain.Role; +import com.example.modules.system.service.dto.RoleDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + + +@Mapper(componentModel = "spring", uses = {MenuMapper.class, DeptMapper.class}, unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface RoleMapper extends BaseMapper<RoleDto, Role> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleSmallMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleSmallMapper.java new file mode 100644 index 0000000..4d4ecff --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/RoleSmallMapper.java @@ -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.mapstruct; + +import com.example.modules.system.domain.Role; +import com.example.modules.system.service.dto.RoleSmallDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** + * + * 2019-5-23 + */ +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface RoleSmallMapper extends BaseMapper<RoleSmallDto, Role> { + +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/UserMapper.java b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/UserMapper.java new file mode 100644 index 0000000..68a45dd --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/java/com/example/modules/system/service/mapstruct/UserMapper.java @@ -0,0 +1,27 @@ +/* + * 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.mapstruct; + +import com.example.modules.system.domain.User; +import com.example.modules.system.service.dto.UserDto; +import com.example.base.BaseMapper; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + + +@Mapper(componentModel = "spring",uses = {RoleMapper.class, DeptMapper.class, JobMapper.class},unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface UserMapper extends BaseMapper<UserDto, User> { +} diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/banner.txt b/UI source code/dns-dev-2.0/dns-system/src/main/resources/banner.txt new file mode 100644 index 0000000..d0f401a --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/banner.txt @@ -0,0 +1,8 @@ + _ _ _ + | | | | (_) + ___| |______ __ _ __| |_ __ ___ _ _ __ + / _ | |______/ _` |/ _` | '_ ` _ \| | '_ \ + | __| | | (_| | (_| | | | | | | | | | | + \___|_| \__,_|\__,_|_| |_| |_|_|_| |_| + + :: Spring Boot :: (v2.1.0.RELEASE)
\ No newline at end of file diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-dev.yml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-dev.yml new file mode 100644 index 0000000..983bf6d --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-dev.yml @@ -0,0 +1,118 @@ +#配置数据源 +spring: + datasource: + druid: + db-type: com.alibaba.druid.pool.DruidDataSource + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + url: jdbc:log4jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:eladmin}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false + username: ${DB_USER:root} + password: ${DB_PWD:root} + # 初始连接数 + initial-size: 5 + # 最小连接数 + min-idle: 15 + # 最大连接数 + max-active: 30 + # 超时时间(以秒数为单位) + remove-abandoned-timeout: 180 + # 获取连接超时时间 + max-wait: 3000 + # 连接有效性检测时间 + time-between-eviction-runs-millis: 60000 + # 连接在池中最小生存的时间 + min-evictable-idle-time-millis: 300000 + # 连接在池中最大生存的时间 + max-evictable-idle-time-millis: 900000 + # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 + test-while-idle: true + # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 + test-on-borrow: true + # 是否在归还到池中前进行检验 + test-on-return: false + # 检测连接是否有效 + validation-query: select 1 + # 配置监控统计 + webStatFilter: + enabled: true + stat-view-servlet: + enabled: true + url-pattern: /druid/* + reset-enable: false + filter: + stat: + enabled: true + # 记录慢SQL + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + +# 登录相关配置 +login: + # 登录缓存 + cache-enable: true + # 是否限制单用户登录 + single-login: false + # 验证码 + login-code: + # 验证码类型配置 查看 LoginProperties 类 + code-type: arithmetic + # 登录图形验证码有效时间/分钟 + expiration: 2 + # 验证码高度 + width: 111 + # 验证码宽度 + height: 36 + # 内容长度 + length: 2 + # 字体名称,为空则使用默认字体 + font-name: + # 字体大小 + font-size: 25 + +#jwt +jwt: + header: Authorization + # 令牌前缀 + token-start-with: Bearer + # 必须使用最少88位的Base64对该令牌进行编码 + base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= + # 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html + token-validity-in-seconds: 14400000 + # 在线用户key + online-key: online-token- + # 验证码 + code-key: code-key- + # token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期 + detect: 1800000 + # 续期时间范围,默认1小时,单位毫秒 + renew: 3600000 + +#是否允许生成代码,生产环境设置为false +generator: + enabled: true + +#是否开启 swagger-ui +swagger: + enabled: true + +# IP 本地解析 +ip: + local-parsing: true + +# 文件存储路径 +file: + mac: + path: ~/file/ + avatar: ~/avatar/ + linux: + path: /home/dns/file/ + avatar: /home/dns/avatar/ + windows: + path: C:\dns\file\ + avatar: C:\dns\avatar\ + # 文件大小 /M + maxSize: 100 + avatarMaxSize: 5 diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-prod.yml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-prod.yml new file mode 100644 index 0000000..8e1993f --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application-prod.yml @@ -0,0 +1,126 @@ +#配置数据源 +spring: + datasource: + druid: + db-type: com.alibaba.druid.pool.DruidDataSource + driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy + url: jdbc:log4jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/${DB_NAME:eladmin}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false + username: ${DB_USER:root} + password: ${DB_PWD:123456} + # 初始连接数 + initial-size: 5 + # 最小连接数 + min-idle: 15 + # 最大连接数 + max-active: 30 + # 获取连接超时时间 + max-wait: 5000 + # 连接有效性检测时间 + time-between-eviction-runs-millis: 60000 + # 连接在池中最小生存的时间 + min-evictable-idle-time-millis: 300000 + # 连接在池中最大生存的时间 + max-evictable-idle-time-millis: 900000 + # 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除 + test-while-idle: true + # 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个 + test-on-borrow: true + # 是否在归还到池中前进行检验 + test-on-return: false + # 检测连接是否有效 + validation-query: select 1 + # 配置监控统计 + webStatFilter: + enabled: true + stat-view-servlet: + enabled: true + # 控制台管理用户名和密码 + url-pattern: /druid/* + reset-enable: false + login-username: admin + login-password: 123456 + filter: + stat: + enabled: true + # 记录慢SQL + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + +# 登录相关配置 +login: + # 登录缓存 + cache-enable: true + # 是否限制单用户登录 + single-login: false + # 验证码 + login-code: + # 验证码类型配置 查看 LoginProperties 类 + code-type: arithmetic + # 登录图形验证码有效时间/分钟 + expiration: 2 + # 验证码高度 + width: 111 + # 验证码宽度 + height: 36 + # 内容长度 + length: 2 + # 字体名称,为空则使用默认字体,如遇到线上乱码,设置其他字体即可 + font-name: + # 字体大小 + font-size: 25 + +#jwt +jwt: + header: Authorization + # 令牌前缀 + token-start-with: Bearer + # 必须使用最少88位的Base64对该令牌进行编码 + base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= + # 令牌过期时间 此处单位/毫秒 ,默认2小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html + token-validity-in-seconds: 7200000 + # 在线用户key + online-key: online-token- + # 验证码 + code-key: code-key- + # token 续期检查时间范围(默认30分钟,单位默认毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期 + detect: 1800000 + # 续期时间范围,默认 1小时,这里单位毫秒 + renew: 3600000 + +# IP 本地解析 +ip: + local-parsing: false + +#是否允许生成代码,生产环境设置为false +generator: + enabled: false + +#如果生产环境要开启swagger,需要配置请求地址 +#springfox: +# documentation: +# swagger: +# v2: +# host: # 接口域名或外网ip + +#是否开启 swagger-ui +swagger: + enabled: false + +# 文件存储路径 +file: + mac: + path: ~/file/ + avatar: ~/avatar/ + linux: + path: /home/dns/file/ + avatar: /home/dns/avatar/ + windows: + path: C:\dns\file\ + avatar: C:\dns\avatar\ + # 文件大小 /M + maxSize: 100 + avatarMaxSize: 5 diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application.yml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application.yml new file mode 100644 index 0000000..a43407b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/config/application.yml @@ -0,0 +1,97 @@ +server: + port: 8888 + +spring: + freemarker: + check-template-location: false + profiles: + active: dev + jackson: + time-zone: GMT+8 + data: + redis: + repositories: + enabled: false +# pid: +# file: /自行指定位置/dns.pid + + #配置 Jpa + jpa: + hibernate: + ddl-auto: none + open-in-view: true + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL5InnoDBDialect + + redis: + #数据库索引 + database: ${REDIS_DB:0} + host: ${REDIS_HOST:127.0.0.1} + port: ${REDIS_PORT:6379} + password: ${REDIS_PWD:} + #连接超时时间 + timeout: 5000 + +task: + pool: + # 核心线程池大小 + core-pool-size: 10 + # 最大线程数 + max-pool-size: 30 + # 活跃时间 + keep-alive-seconds: 60 + # 队列容量 + queue-capacity: 50 + +#七牛云 +qiniu: + # 文件大小 /M + max-size: 15 + +#邮箱验证码有效时间/秒 +code: + expiration: 300 + +#密码加密传输,前端公钥加密,后端私钥解密 +rsa: + private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A== + +# 内存用户缓存配置 +user-cache: + # 最小回收数(当缓存数量达到此值时进行回收) + min-evictable-size: 512 + # 最小回收间隔 + min-evictable-interval: 1800000 + # 最小存活时间 (ms) + min-idle-time: 3600000 + + +#mybatis +mybatis-plus: + mapper-locations: classpath*:/mapper/**/*.xml + #实体扫描,多个package用逗号或者分号分隔 + typeAliasesPackage: com.example.modules.*.domain + global-config: + #数据库相关配置 + db-config: + #主键类型 AUTO:"数据库ID自增", INPUT:"用户输入ID", ID_WORKER:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID"; + id-type: AUTO + #字段策略 IGNORED:"忽略判断",NOT_NULL:"非 NULL 判断"),NOT_EMPTY:"非空判断" + field-strategy: NOT_NULL + #驼峰下划线转换 + column-underline: true + logic-delete-value: 1 + logic-not-delete-value: 0 + banner: false + #原生配置 + configuration: + map-underscore-to-camel-case: true + cache-enabled: false + call-setters-on-nulls: true + jdbc-type-for-null: 'null' + +#showSql +logging: + level: + com.example.modules.system.mapper: debug diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/generator.properties b/UI source code/dns-dev-2.0/dns-system/src/main/resources/generator.properties new file mode 100644 index 0000000..2ed9370 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/generator.properties @@ -0,0 +1,27 @@ +#数据库类型转Java类型 +tinyint=Integer +smallint=Integer +mediumint=Integer +int=Integer +integer=Integer + +bigint=Long + +float=Float + +double=Double + +decimal=BigDecimal + +bit=Boolean + +char=String +varchar=String +tinytext=String +text=String +mediumtext=String +longtext=String + +date=Timestamp +datetime=Timestamp +timestamp=Timestamp
\ No newline at end of file diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/log4jdbc.log4j2.properties b/UI source code/dns-dev-2.0/dns-system/src/main/resources/log4jdbc.log4j2.properties new file mode 100644 index 0000000..302525f --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/log4jdbc.log4j2.properties @@ -0,0 +1,4 @@ +# If you use SLF4J. First, you need to tell log4jdbc-log4j2 that you want to use the SLF4J logger +log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator +log4jdbc.auto.load.popular.drivers=false +log4jdbc.drivers=com.mysql.cj.jdbc.Driver
\ No newline at end of file diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/logback.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/logback.xml new file mode 100644 index 0000000..8a399c4 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/logback.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration scan="true" scanPeriod="30 seconds" debug="false"> + <contextName>DiamondV</contextName> + <property name="log.charset" value="utf-8" /> + <property name="log.pattern" value="%contextName- %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %msg%n" /> + + <!--输出到控制台--> + <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> + <encoder> + <pattern>${log.pattern}</pattern> + <charset>${log.charset}</charset> + </encoder> + </appender> + + <!--普通日志输出到控制台--> + <root level="info"> + <appender-ref ref="console" /> + </root> + + <!--监控sql日志输出,如需监控 Sql 打印,请设置为 INFO --> + <logger name="jdbc.sqlonly" level="INFO" additivity="false"> + <appender-ref ref="console" /> + </logger> + + <logger name="jdbc.resultset" level="ERROR" additivity="false"> + <appender-ref ref="console" /> + </logger> + + <!-- 如想看到表格数据,将OFF改为INFO --> + <logger name="jdbc.resultsettable" level="OFF" additivity="false"> + <appender-ref ref="console" /> + </logger> + + <logger name="jdbc.connection" level="OFF" additivity="false"> + <appender-ref ref="console" /> + </logger> + + <logger name="jdbc.sqltiming" level="OFF" additivity="false"> + <appender-ref ref="console" /> + </logger> + + <logger name="jdbc.audit" level="OFF" additivity="false"> + <appender-ref ref="console" /> + </logger> +</configuration> diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDao.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDao.xml new file mode 100644 index 0000000..37d8a3b --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDao.xml @@ -0,0 +1,577 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="com.example.modules.dns.mapper.DnsDohDao"> + + <resultMap id="dohMap" type="com.example.modules.dns.domain.Result"> + <id property="id" column="id"/> + <id property="ip" column="ip"/> + <id property="host" column="host"/> + <id property="port" column="port"/> + <result property="path" column="path"/> + <result property="method" column="method"/> + <result property="connectType" column="connect_type"/> + <result property="statusCode" column="status_code"/> + <result property="repHeader" column="rep_header"/> + <result property="repBody" column="rep_body"/> + <result property="timestamp" column="timestamp"/> + <result property="component" column="component"/> + <result property="rounds" column="rounds"/> + <association property="ipInformation" columnPrefix="ii_" + javaType="com.example.modules.dns.domain.IpInformation"> + <result property="id" column="id"/> + <result property="ip" column="ip"/> + <result property="country" column="country"/> + <result property="province" column="province"/> + <result property="city" column="city"/> + <result property="district" column="district"/> + <result property="provider" column="provider"/> + <result property="isp" column="isp"/> + <result property="asnumber" column="asnumber"/> + <result property="timestamp" column="timestamp"/> + <result property="zipcode" column="zipcode"/> + <result property="timezone" column="timezone"/> + </association> + + <collection property="pathList" columnPrefix="da2_" ofType="String"> + <result property="pathList" column="path"/> + </collection> + + <collection property="componentList" columnPrefix="da2_" ofType="String"> + <result property="component" column="component"/> + </collection> + <collection property="ipCert" columnPrefix="ic_" ofType="com.example.modules.dns.domain.IpCert"> + <id property="id" column="id"/> + <result property="ip" column="ip"/> + <result property="port" column="port"/> + <result property="certificate" column="certificate"/> + <result property="ca" column="ca"/> + <result property="timestamp" column="timestamp"/> + </collection> + + <collection property="vulnerability" columnPrefix="v_" ofType="com.example.modules.dns.domain.Vulnerability"> + <id property="id" column="id"/> + <result property="component" column="component"/> + <result property="vulnerability" column="vulnerability"/> + <result property="timestamp" column="timestamp"/> + </collection> + + </resultMap> + + <select id="queryDohPage" resultMap="dohMap"> + SELECT da.id,da.ip,da.`host`,da.`port`,da.rounds,da.`timestamp` + ,GROUP_CONCAT(concat(da.method,'',da.path)) path + ,GROUP_CONCAT(distinct da.component) component + ,ii.country ii_country,ii.provider ii_provider,ii.city ii_city ,ii.asnumber ii_asnumber,ii.isp ii_isp, + ii.province ii_province,ii.zipcode ii_zipcode,ii.district ii_district, + v.`vulnerability` v_vulnerability + FROM (SELECT da.* FROM doh_attribute da + <where> + <if test="params.ip != null and params.ip != ''"> + da.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + AND da.`port` = #{params.port} + </if> + </where> + ) da + LEFT JOIN ip_information ii ON da.ip=ii.ip + LEFT JOIN `vulnerability` v ON v.`component` = da.`component` + + GROUP BY da.ip,da.port,da.host,da.rounds + order by da.`timestamp` desc + LIMIT #{params.n},#{params.m} + </select> + + <select id="dohProvinceCount" resultType="map"> + SELECT + COUNT(distinct da.ip) count,ii.`province` + FROM (SELECT DISTINCT ip from doh_attribute + <where> + <if test="params.ip != null and params.ip != ''"> + ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and port = #{params.port} + </if> + </where> + ) da + JOIN `ip_information` ii + ON da.ip = ii.ip AND ii.province IS NOT NULL AND ii.province !='' + GROUP BY ii.province + </select> + + <select id="dohChinaMapCount" resultType="map"> + SELECT ii.`province`, + COUNT(distinct da.ip) count + FROM `doh_attribute` da + JOIN `ip_information` ii + ON da.ip = ii.ip + where ii.country = '中国' + and da.`rounds` = (select MAX(rounds) FROM doh_attribute) + and ii.province IS NOT NULL + AND ii.province != '' + GROUP BY ii.province + + order by count desc + </select> + + <select id="dohCountryCount" resultType="map"> + SELECT ii.`country`, + COUNT(distinct da.ip) count + FROM `doh_attribute` da + JOIN `ip_information` ii + ON da.ip = ii.ip + where da.`rounds` = (SELECT DISTINCT MAX(rounds) FROM doh_attribute) + GROUP BY ii.country + order by count desc + </select> + + <select id="dohAndDo53ProvinceCount" resultType="map"> + SELECT province,SUM(count) count FROM ( + SELECT + ii.`province`,COUNT(distinct da.ip) count,da.ip + FROM `doh_attribute` da + JOIN `ip_information` ii + ON da.ip = ii.ip + where ii.province IS NOT NULL AND ii.province !='' + <if test="params.ip != null and params.ip != ''"> + and da.ip = #{params.ip} + </if> + GROUP BY ii.province + + UNION ALL + + SELECT + ii.`province`,COUNT(distinct s.ip) COUNT, s.ip + FROM `scan_result` s + JOIN `ip_information` ii + ON s.ip = ii.ip + where ii.province IS NOT NULL AND ii.province !='' + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + GROUP BY ii.province + ) a1 + + GROUP BY a1.province + </select> + + <select id="dohProviderCount" resultType="map"> + SELECT + COUNT(ip_attr.ip) count,ii.`provider` + from + (SELECT DISTINCT ip from doh_attribute + <where> + <if test="params.ip != null and params.ip != ''"> + ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and port = #{params.port} + </if> + </where> + ) ip_attr + JOIN `ip_information` ii on ip_attr.ip = ii.ip AND ii.provider IS NOT NULL AND ii.provider !='' + + GROUP BY ii.provider + </select> + + <select id="dohAndDo53ProviderCount" resultType="map"> + + SELECT provider,SUM(COUNT) count FROM( + SELECT + ii.`provider`,COUNT(da.ip) COUNT,da.ip + FROM (SELECT id, ip from doh_attribute + <where> + <if test="params.ip != null and params.ip != ''"> + ip = #{params.ip} + </if> + </where> + ) da + JOIN `ip_information` ii ON da.ip = ii.ip + GROUP BY ii.provider + + UNION ALL + SELECT + ii.`provider`,COUNT(distinct s.ip) COUNT,s.ip + FROM `scan_result` s + JOIN `ip_information` ii ON s.ip = ii.ip + GROUP BY ii.provider + ) a1 + <where> + <if test="params.ip != null and params.ip != ''"> + a1.ip = #{params.ip} + </if> + </where> + GROUP BY a1.provider + HAVING provider IS NOT NULL AND provider !='' + </select> + + <select id="dohComponentCount" resultType="map"> + SELECT + da.component,COUNT(distinct da.ip) count + FROM (SELECT DISTINCT ip,component from doh_attribute + where + component IS NOT NULL AND component !='' + <if test="params.ip != null and params.ip != ''"> + and ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and port = #{params.port} + </if> + ) da + GROUP BY da.component + + </select> + + <select id="dohAndDo53ComponentCount" resultType="map"> + SELECT component,SUM(COUNT) count FROM ( + SELECT + da.component,COUNT(distinct da.ip) COUNT,da.ip + FROM `doh_attribute` da + <where> + + <if test="params.ip != null and params.ip != ''"> + da.ip = #{params.ip} + </if> + + </where> + GROUP BY da.component,da.ip + + UNION ALL + + SELECT + s.component,COUNT(distinct s.ip) COUNT ,s.ip + FROM `scan_result` s + GROUP BY s.component,s.ip) a1 + where component IS NOT NULL AND component !='' + <if test="params.ip != null and params.ip != ''"> + and a1.ip = #{params.ip} + </if> + + GROUP BY a1.component + + </select> + + <select id="dohServiceCategoryCount" resultType="map"> + <!--SELECT IFNULL(SUM(count),0) count FROM ( + SELECT da.ip,COUNT(distinct da.ip) count FROM `doh_attribute` da + <where> + <if test="params.ip != null and params.ip != ''"> + and da.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and da.port = #{params.port} + </if> + </where> + GROUP BY ip) a1--> + SELECT count(1) count from ( + SELECT distinct da.ip from `doh_attribute` da + <where> + <if test="params.ip != null and params.ip != ''"> + da.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and da.port = #{params.port} + </if> + </where> + ) a + + </select> + + <select id="dohResultTotalCount" resultType="int"> + SELECT COUNT(1) count FROM ( + SELECT ip,PORT,HOST,rounds + FROM `doh_attribute` da + <where> + <if test="params.ip != null and params.ip != ''"> + da.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and da.port = #{params.port} + </if> + </where> + GROUP BY ip,PORT,HOST,rounds + ) a1 + </select> + + <select id="dohVulnerabilityCount" resultType="map"> + SELECT vulnerability,COUNT(distinct ip) count FROM ( + SELECT da.ip,da.port,da.host,da.`component` + ,v.`vulnerability` + FROM `doh_attribute` da + JOIN `vulnerability` v ON v.`component` = da.`component` AND vulnerability IS NOT NULL AND vulnerability != '' + <where> + <if test="params.ip != null and params.ip != ''"> + da.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and da.port = #{params.port} + </if> + </where> + ) a1 + + GROUP BY a1.vulnerability + </select> + + <select id="dohAndDo53VulnerabilityCount" resultType="map"> + SELECT vulnerability,COUNT(distinct ip) count FROM ( + SELECT da.ip + ,v.`vulnerability` + FROM `doh_attribute` da + JOIN `vulnerability` v ON v.`component` = da.`component` + where vulnerability IS NOT NULL AND vulnerability !='' + <if test="params.ip != null and params.ip != ''"> + and ip = #{params.ip} + </if> + + UNION ALL + + SELECT s.ip + ,v.`vulnerability` + FROM `scan_result` s + JOIN `vulnerability` v ON v.`component` = s.`component` + where vulnerability IS NOT NULL AND vulnerability !='' + <if test="params.ip != null and params.ip != ''"> + and ip = #{params.ip} + </if> + ) a1 + + GROUP BY a1.vulnerability + </select> + + + <select id="dohPortCount" resultType="map"> + SELECT COUNT(ip) count,`port` FROM + (SELECT DISTINCT ip,port from doh_attribute + where `port` is not null AND `port` != '' + <if test="params.ip != null and params.ip != ''"> + and ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and port = #{params.port} + </if> + ) da + GROUP BY port + </select> + + + <select id="dohIpCount" resultType="int"> + SELECT COUNT(distinct da.ip) FROM doh_attribute da + <where> + <if test="params.ip != null and params.ip != ''"> + da.ip = #{params.ip} + </if> + </where> + </select> + <select id="getDohRepBody" resultMap="dohMap"> + select da.rep_body, da.rep_header + from doh_attribute da + where da.ip = #{ip} + AND da.port = #{port} + AND da.host = #{host} + AND da.rounds = #{rounds} + </select> + + <select id="selectDohInfoByUnion" resultMap="dohMap"> + SELECT da.*, + GROUP_CONCAT(concat(da.method, '', da.path)) path, + ii.country ii_country, + ii.provider ii_provider, + ii.city ii_city, + ii.asnumber ii_asnumber, + ii.isp ii_isp, + ii.province ii_province, + ii.zipcode ii_zipcode, + ii.district ii_district, + v.`vulnerability` v_vulnerability + from (select da.ip + from (select count(1), d.ip from doh_attribute d + <where> + <if test="params.ip != null and params.ip != ''"> + d.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and d.`port` = #{params.port} + </if> + </where> + group by d.ip) da + JOIN scan_result s on da.ip = s.ip) dip + join doh_attribute da on da.ip = dip.ip + left join ip_information ii on ii.ip = dip.ip + left join vulnerability v on v.component = da.component + + group by da.ip, da.host, da.`port`, da.rounds + order by da.`timestamp` desc + LIMIT #{params.offset},#{params.limit} + </select> + + <select id="selectDohCountByUnion" resultType="integer"> + select count(1) + from (SELECT da.id, da.ip, da.host, da.`port`, da.rounds + from (select da.ip + from (select count(1), d.ip from doh_attribute d + <where> + <if test="params.ip != null and params.ip != ''"> + d.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and d.`port` = #{params.port} + </if> + </where> + group by d.ip) da + JOIN scan_result s on da.ip = s.ip + ) dip + join doh_attribute da on da.ip = dip.ip + group by da.ip, da.host, da.`port`, da.rounds) total + + </select> + + <select id="countDohPortUnion" resultType="java.util.Map"> + + select count(distinct dh.ip) count ,dh.`port` + from (select distinct ip,`port` from doh_attribute + <where> + <if test="params.ip != null and params.ip != ''"> + ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and port = #{params.port} + </if> + </where> + ) dh + join scan_result sc on sc.ip = dh.ip + group by dh.`port` + having dh.`port` is not null AND dh.`port` != '' + + UNION ALL + + select count(distinct sc.ip) count,'53' as `port` + from (select distinct ip,`port` from doh_attribute da + <where> + <if test="params.ip != null and params.ip != ''"> + da.ip = #{params.ip} + </if> + </where> + ) dh + join scan_result sc on sc.ip = dh.ip + + </select> + + <select id="getDohAndDo53ProvinceCount" resultType="java.util.Map"> + SELECT + ii.`province`,COUNT(distinct s.ip) COUNT + FROM ( select sc.id,sc.ip from `scan_result` sc + <where> + <if test="params.ip != null and params.ip != ''"> + sc.ip = #{ip} + </if> + </where> + )s + join `doh_attribute` da on da.ip = s.ip + JOIN `ip_information` ii + ON s.ip = ii.ip + <where> + <if test="params.port != null and params.port != ''"> + da.`port` = #{params.port} + </if> + </where> + GROUP BY ii.province + having ii.province IS NOT NULL AND ii.province !='' + </select> + + <select id="getDohAndDo53ProviderCount" resultType="java.util.Map"> + SELECT + ii.`provider`,COUNT(distinct s.ip) COUNT + FROM ( select sc.id,sc.ip from `scan_result` sc + <where> + <if test="params.ip != null and params.ip != ''"> + sc.ip = #{ip} + </if> + </where> + )s + join `doh_attribute` da on da.ip = s.ip + JOIN `ip_information` ii + ON s.ip = ii.ip + <where> + <if test="params.port != null and params.port != ''"> + da.`port` = #{params.port} + </if> + </where> + GROUP BY ii.provider + having ii.provider IS NOT NULL AND ii.provider !='' + </select> + + <select id="getDohAndDo53ComponentCount" resultType="java.util.Map"> + SELECT + da.component component,count(distinct da.ip) count + FROM ( select count(1),d.ip,d.component from doh_attribute d + where d.component IS NOT NULL AND d.component !='' + <if test="params.ip != null and params.ip != ''"> + AND d.ip = #{ip} + </if> + ) da + JOIN scan_result s on da.ip = s.ip + <where> + <if test="params.port != null and params.port != ''"> + da.`port` = #{params.port} + </if> + </where> + GROUP BY da.component + having da.component IS NOT NULL AND da.component !='' + </select> + + <select id="getDohServiceCategoryCount" resultType="java.util.Map"> + SELECT count(DISTINCT da.ip) + from (select count(1),d.ip from doh_attribute d + <where> + <if test="params.ip != null and params.ip != ''"> + d.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and d.`port` = #{params.port} + </if> + </where> + group by d.ip) da + join scan_result sc on da.ip = sc.ip + </select> + <select id="getDohAndDo53VulnerabilityCount" resultType="java.util.Map"> + SELECT vulnerability, COUNT(distinct ip) count + FROM ( + select da.ip, dv.vulnerability + from (select count(1), d.ip, d.component + from doh_attribute d + where d.component is not null and d.component != '' + <if test="params.ip != null and params.ip != ''"> + and d.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and d.`port` = #{params.port} + </if> + group by d.ip, d.component) da + join scan_result sc on da.ip = sc.ip + join (select distinct v.vulnerability, d.component, d.ip from doh_attribute d + JOIN `vulnerability` v ON v.`component` = d.`component`) dv + on da.ip = dv.ip + where dv.vulnerability is not null and dv.vulnerability != '' + + union all + + select s.ip, dv.vulnerability + from (select count(1), d.ip from doh_attribute d + group by d.ip + ) da + join scan_result s on da.ip = s.ip + join (select distinct v.vulnerability, sc.component, sc.ip + from scan_result sc + JOIN `vulnerability` v ON v.`component` = sc.`component`) dv + on s.ip = dv.ip + where dv.vulnerability is not null and dv.vulnerability != '' + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + ) a1 + GROUP BY a1.vulnerability + </select> + +</mapper> diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDo53Dao.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDo53Dao.xml new file mode 100644 index 0000000..849fc64 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/DnsDo53Dao.xml @@ -0,0 +1,400 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="com.example.modules.dns.mapper.DnsDo53Dao"> + + <resultMap id="do53Map" type="com.example.modules.dns.domain.Result"> + <id property="id" column="id"/> + <result property="ip" column="ip"/> + <result property="flags" column="flags"/> + <result property="opcode" column="opcode"/> + <result property="qr" column="qr"/> + <result property="aa" column="aa"/> + <result property="ra" column="ra"/> + <result property="rcode" column="rcode"/> + <result property="queryName" column="queryName"/> + <result property="queryResponse" column="query_response"/> + <result property="component" column="component"/> + <result property="scanType" column="scanType"/> + <result property="timestamp" column="time"/> + <result property="dnsType" column="dnsType"/> + <result property="epoch" column="epoch"/> + + <association property="ipInformation" columnPrefix="ii_" + javaType="com.example.modules.dns.domain.IpInformation"> + <result property="id" column="id"/> + <result property="ip" column="ip"/> + <result property="country" column="country"/> + <result property="province" column="province"/> + <result property="city" column="city"/> + <result property="district" column="district"/> + <result property="provider" column="provider"/> + <result property="isp" column="isp"/> + <result property="asnumber" column="asnumber"/> + <result property="timestamp" column="timestamp"/> + <result property="zipcode" column="zipcode"/> + <result property="timezone" column="timezone"/> + </association> + <collection property="componentList" ofType="String"> + <result property="component" column="component"/> + </collection> + + <collection property="vulnerability" columnPrefix="v_" ofType="com.example.modules.dns.domain.Vulnerability"> + <id property="id" column="id"/> + <result property="component" column="component"/> + <result property="vulnerability" column="vulnerability"/> + <result property="timestamp" column="timestamp"/> + </collection> + + + </resultMap> + + <select id="queryDo53Page" resultMap="do53Map"> + SELECT s.*, + ii.country ii_country,ii.provider ii_provider, + ii.city ii_city ,ii.asnumber ii_asnumber,ii.isp ii_isp, + ii.province ii_province,ii.zipcode ii_zipcode,ii.district ii_district, + dt.type dnsType,v.`vulnerability` v_vulnerability + FROM (select s.* from scan_result s + <where> + <if test="params.ip != null and params.ip != ''"> + s.ip = #{params.ip} + </if> + </where> + order by s.time desc + LIMIT #{params.n},#{params.m} + ) s + LEFT JOIN ip_information ii ON ii.ip = s.ip + LEFT JOIN dns_type dt ON dt.ip = s.ip AND dt.`epoch` = s.`epoch` + LEFT JOIN `vulnerability` v ON v.`component` = s.`component` + + + </select> + + <select id="do53IpCount" resultType="int"> + SELECT COUNT(distinct ip) FROM `scan_result` + <where> + <if test="params.ip != null and params.ip != ''"> + ip = #{params.ip} + </if> + </where> + + </select> + + <select id="do53ServiceCategoryCount" resultType="map"> + SELECT TYPE,COUNT(distinct ip) count FROM ( + SELECT s.ip,dt.type FROM `scan_result` s + JOIN `dns_type` dt ON s.ip=dt.ip + where type IS NOT NULL AND type !='' + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + <if test="params.dnsType != null and params.dnsType != ''"> + and dt.type = #{params.dnsType} + </if> + ) a1 + GROUP BY a1.type + </select> + + <select id="do53ProvinceCount" resultType="map"> + SELECT + ii.`province`,COUNT(distinct s.ip) count + FROM `scan_result` s + JOIN `ip_information` ii + ON s.ip = ii.ip AND ii.province IS NOT NULL AND ii.province !='' + <where> + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + </where> + GROUP BY ii.province + </select> + + <select id="do53CountryCount" resultType="map"> + SELECT ii.`country`, + COUNT(s.ip) count + FROM `scan_result` s + JOIN `ip_information` ii + ON s.ip = ii.ip + GROUP BY ii.country + </select> + + <select id="do53CountryMapCount" resultType="map"> + SELECT ii.`country`, + COUNT(ii.`country`) count, + dt.type + FROM `dns_type` dt + JOIN `ip_information` ii ON dt.ip = ii.ip + WHERE dt.epoch = (SELECT MAX(epoch) FROM `dns_type`) + GROUP BY ii.`country`, dt.`type` + order by count desc + </select> + + <select id="do53WorldMapCount" resultType="map"> + SELECT ii.`country`, + COUNT(ii.`country`) count + FROM `dns_type` dt + JOIN `ip_information` ii ON dt.ip = ii.ip + WHERE dt.epoch = (SELECT MAX(epoch) FROM `dns_type`) + GROUP BY ii.`country` + order by count desc + </select> + + <select id="do53ChinaMapCount" resultType="map"> + SELECT ii.`province`, + COUNT(ii.`province`) count + FROM `dns_type` dt + JOIN `ip_information` ii ON dt.ip = ii.ip + WHERE ii.country = '中国' + and dt.epoch = (SELECT MAX(epoch) FROM `dns_type`) + GROUP BY ii.`province` + order by count desc + </select> + + <select id="do53ProviderCount" resultType="map"> + SELECT + ii.`provider`,COUNT(s.ip) count + FROM `scan_result` s + JOIN `ip_information` ii + ON s.ip = ii.ip AND provider IS NOT NULL AND provider !='' + <where> + <if test="params.ip != null and params.ip != ''"> + s.ip = #{params.ip} + </if> + </where> + GROUP BY ii.provider + </select> + + + <select id="do53ComponentCount" resultType="map"> + SELECT + s.component,COUNT(distinct s.ip) count + FROM `scan_result` s + where + component IS NOT NULL AND component !='' + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + GROUP BY s.component + </select> + + <select id="do53VulnerabilityCount" resultType="map"> + + SELECT vulnerability,COUNT(ip) count FROM ( + SELECT s.ip + ,v.`vulnerability` + FROM `scan_result` s + JOIN `vulnerability` v ON v.`component` = s.`component` + where vulnerability IS NOT NULL AND vulnerability !='' + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + ) a1 + GROUP BY a1.vulnerability + </select> + + <select id="pageCount" resultType="java.lang.Integer"> + select count(1) from scan_result s + <where> + <if test="params.ip != null and params.ip != ''"> + s.ip = #{params.ip} + </if> + </where> + </select> + + <select id="queryOpenRdns" resultType="result"> + select sc.*, + dt.type dnsType, + ii.country ii_country,ii.provider ii_provider,ii.city ii_city ,ii.asnumber ii_asnumber,ii.isp ii_isp, + ii.province ii_province,ii.zipcode ii_zipcode,ii.district ii_district, + v.`vulnerability` v_vulnerability + from + ( + select sc.* from + scan_result sc join (select ip,epoch from dns_type where type = 1) dt on dt.ip = sc.ip and dt.epoch = sc.epoch + <where> + <if test="params.ip != null and params.ip != ''"> + sc.ip = #{params.ip} + </if> + </where> + order by sc.epoch desc,sc.`time` desc LIMIT #{params.offset},#{params.limit} + ) sc + + left join ip_information ii on sc.ip = ii.ip + left join vulnerability v on sc.component = v.component + </select> + + <select id="getCountByDnsType" resultType="java.lang.Integer"> + select count(1) from + (select id,ip,epoch from scan_result sr + <where> + <if test="params.ip != null and params.ip != ''"> + sr.ip = #{params.ip} + </if> + </where> + ) sc + join ( select d.id,d.ip,d.epoch from dns_type d where d.type = #{dnsType}) dt + on dt.ip = sc.ip AND dt.epoch = sc.epoch + + + </select> + + <select id="getIndependentIpNum" resultType="java.lang.Integer"> + select count(distinct sc.ip) + from ( select id,ip,epoch from scan_result sr + <where> + <if test="params.ip != null and params.ip != ''"> + ip = #{params.ip} + </if> + </where> + ) sc + join (select ip, epoch from dns_type d where d.type = #{dnsType}) + dt on dt.ip = sc.ip and dt.epoch = sc.epoch + + </select> + + <select id="selectScanResultCountByUnion" resultType="java.lang.Integer"> + select count(1) count + from ( + select da.ip + from (select count(1), d.ip from doh_attribute d + <where> + <if test="params.ip != null and params.ip != ''"> + d.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and d.`port` = #{params.port} + </if> + </where> + group by d.ip) da + JOIN scan_result s on da.ip = s.ip + ) dip + join scan_result sc on sc.ip = dip.ip + </select> + + <select id="selectScanResultByUnion" resultMap="do53Map"> + SELECT sc.*, + ii.country ii_country, ii.provider ii_provider, + ii.city ii_city, ii.asnumber ii_asnumber, ii.isp ii_isp, + ii.province ii_province,ii.zipcode ii_zipcode, + ii.district ii_district, + dt.type dnsType, v.`vulnerability` v_vulnerability + from ( + select da.ip + from (select count(1), d.ip from doh_attribute d + <where> + <if test="params.ip != null and params.ip != ''"> + d.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and d.`port` = #{params.port} + </if> + </where> + group by d.ip) da + JOIN scan_result s on da.ip = s.ip + ) dip + + join scan_result sc on sc.ip = dip.ip + left join ip_information ii on ii.ip = dip.ip + left join vulnerability v on v.component = sc.component + left join dns_type dt ON dt.ip = sc.ip AND dt.`epoch` = sc.`epoch` + order by sc.`time` desc + LIMIT #{params.offset},#{params.limit} + </select> + + <select id="getDohAndDo53SrvCategoryCount" resultType="java.util.Map"> + SELECT dt.type, COUNT(distinct da.ip) count + FROM (select count(1),d.ip from doh_attribute d + <where> + <if test="params.ip != null and params.ip != ''"> + d.ip = #{params.ip} + </if> + <if test="params.port != null and params.port != ''"> + and d.`port` = #{params.port} + </if> + </where> + group by d.ip + ) da + JOIN scan_result s on da.ip = s.ip + JOIN `dns_type` dt ON da.ip = dt.ip and dt.type > 0 + + GROUP BY dt.type + </select> + + <select id="getDo53ProvinceCountByDnsType" resultType="java.util.Map"> + select s.`province`,COUNT(distinct s.ip) count from + (SELECT s.ip,ii.province FROM `scan_result` s + JOIN `ip_information` ii ON s.ip = ii.ip + where ii.province IS NOT NULL AND ii.province !='' + <if test="params.ip != null and params.ip != ''"> + AND s.ip = #{params.ip} + </if> + ) s + join dns_type dt on s.ip = dt.ip + where dt.type = #{dnsType} + GROUP BY s.province + </select> + + <select id="getDo53ProviderCountByDnsType" resultType="java.util.Map"> + SELECT + s.`provider`,COUNT(distinct s.ip) count + FROM ( SELECT ii.`provider`,s.ip + FROM `scan_result` s + JOIN `ip_information` ii + ON s.ip = ii.ip AND provider IS NOT NULL AND provider !='' + <where> + <if test="params.ip != null and params.ip != ''"> + s.ip = #{params.ip} + </if> + </where> + ) s + JOIN dns_type dt on dt.ip = s.ip + <if test="dnsType != null and dnsType != ''"> + AND dt.type = #{dnsType} + </if> + GROUP BY s.provider + </select> + + <select id="getDo53ComponentCountByDnsType" resultType="java.util.Map"> + select s.component,COUNT(distinct s.ip) count + from ( + SELECT s.component, s.ip FROM `scan_result` s + where + component IS NOT NULL AND component !='' + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + ) s + JOIN (SELECT ip from dns_type where type = #{dnsType}) dt on s.ip = dt.ip + GROUP BY s.component + </select> + + <select id="getDo53SrvCategoryCountByDnsType" resultType="java.lang.Integer"> + SELECT COUNT(a1.ip) count FROM ( + SELECT s.ip,dt.type FROM `scan_result` s + JOIN `dns_type` dt ON s.ip=dt.ip + where dt.type = #{dnsType} + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + ) a1 + GROUP BY a1.type + </select> + + <select id="getDo53VulnerabCountByDnsType" resultType="java.util.Map"> + SELECT vulnerability,COUNT(a1.ip) count FROM ( + SELECT s.ip + ,v.`vulnerability` + FROM `scan_result` s + JOIN `vulnerability` v ON v.`component` = s.`component` + where vulnerability IS NOT NULL AND vulnerability !='' + <if test="params.ip != null and params.ip != ''"> + and s.ip = #{params.ip} + </if> + ) a1 + JOIN dns_type dt on a1.ip = dt.ip and dt.type = #{dnsType} + GROUP BY a1.vulnerability + </select> + + +</mapper> diff --git a/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/IpInformationDao.xml b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/IpInformationDao.xml new file mode 100644 index 0000000..f4a0047 --- /dev/null +++ b/UI source code/dns-dev-2.0/dns-system/src/main/resources/mapper/dns/IpInformationDao.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + +<mapper namespace="com.example.modules.dns.mapper.IpInformationDao"> + + <resultMap id="ipMap" type="com.example.modules.dns.domain.IpInformation"> + <id property="id" column="id"/> + <id property="ip" column="ip"/> + <result property="country" column="country"/> + <result property="province" column="province"/> + <result property="city" column="city"/> + <result property="district" column="district"/> + <result property="provider" column="provider"/> + <result property="isp" column="isp"/> + <result property="asnumber" column="asnumber"/> + <result property="timestamp" column="timestamp"/> + <result property="zipcode" column="zipcode"/> + <result property="timezone" column="timezone"/> + + <association property="dnsType" columnPrefix="dt_" javaType="com.example.modules.dns.domain.DnsType"> + <id property="id" column="id"/> + <id property="ip" column="ip"/> + <result property="type" column="type"/> + </association> + + <collection property="ipCert" columnPrefix="ic_" ofType="com.example.modules.dns.domain.IpCert"> + <id property="id" column="id"/> + <id property="ip" column="ip"/> + <result property="port" column="port"/> + <result property="certificate" column="certificate"/> + <result property="ca" column="ca"/> + <result property="timestamp" column="timestamp"/> + </collection> + + <collection property="dohAttribute" columnPrefix="da_" ofType="com.example.modules.dns.domain.DohAttribute"> + <id property="ip" column="ip"/> + <result property="host" column="host"/> + <result property="port" column="port"/> + <result property="path" column="path"/> + <result property="method" column="method"/> + <result property="connectType" column="connect_type"/> + <result property="statusCode" column="status_code"/> + <result property="repHeader" column="rep_header"/> + <result property="repBody" column="rep_body"/> + <result property="timestamp" column="timestamp"/> + <result property="component" column="component"/> + </collection> + + </resultMap> + + + + <select id="queryIpPage" resultMap="ipMap"> + SELECT ii.* +-- ,ic.certificate ic_certificate ,ic.ca ic_ca + ,da.host da_host , da.rep_body da_rep_body , da.status_code da_status_code ,da.component da_component,da.path da_path + FROM `ip_information` ii +-- LEFT JOIN `ip_cert` ic ON ii.ip = ic.ip + left join doh_attribute da on ii.ip = da.ip + + <where> + <if test="params.ip != null and params.ip != ''"> + and ii.ip = #{params.ip} + </if> + </where> + + </select> + <select id="getIpInfoByFwd" resultType="ipInformation"> + select ii.* from ip_information ii + join (SELECT fd.upstream from forward_dns fd where fd.forwarder = #{ip} + <if test="epoch != '' and epoch != null "> + and fd.epoch = #{epoch} + </if> + ) fw + on fw.upstream = ii.ip + </select> + +</mapper> |
