diff --git a/mallinkSysAdmin/pom.xml b/mallinkSysAdmin/pom.xml new file mode 100644 index 000000000..d6ebc3c85 --- /dev/null +++ b/mallinkSysAdmin/pom.xml @@ -0,0 +1,157 @@ + + + 4.0.0 + + + mallink + com.iformall + 1.0 + + + mallinkSysAdmin + + + 3.3.0 + 3.3.0 + + + + + com.iformall + mallinkService + 1.0 + + + commons-fileupload + commons-fileupload + 1.3.3 + + + + com.google.zxing + core + 3.3.3 + + + + com.github.axet + kaptcha + 0.0.9 + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + ZIP + + antlr, + cn.afterturn, + ch.qos.logback, + com.alibaba, + com.amazonaws, + com.mchange, + com.fasterxml.jackson.core, + com.fasterxml.jackson.dataformat, + com.fasterxml.jackson.datatype, + com.fasterxml.jackson.module, + com.github.axet, + com.github.binarywang, + com.github.jsqlparser, + com.github.pagehelper, + com.github.ulisesbocchio, + com.github.virtuald, + com.google.code.gson, + com.google.guava, + com.google.protobuf, + com.google.zxing, + com.jayway.jsonpath, + com.jhlabs, + com.puppycrawl.tools, + com.rabbitmq, + com.squareup.okhttp3, + com.squareup.okio, + com.sun, + com.sun.mail, + com.thoughtworks.xstream, + com.zaxxer, + commons-beanutils, + commons-cli, + commons-codec, + commons-collections, + commons-io, + commons-logging, + io.lettuce, + io.netty, + io.projectreactor, + io.springfox, + io.swagger, + io.undertow, + javax.activation, + javax.mail, + javax.persistence, + javax.xml.bind, + joda-time, + junit, + mysql, + net.bytebuddy, + net.minidev, + net.sf.saxon, + ognl, + org.antlr, + org.apache.commons, + org.apache.httpcomponents, + org.apache.logging.log4j, + org.apache.poi, + org.apache.poi.wso2, + org.apache.rocketmq, + org.apache.shiro, + org.apache.tomcat.embed, + org.apache.xmlbeans, + org.aspectj, + org.assertj, + org.bouncycastle, + org.checkerframework, + org.crazycake, + org.dom4j, + org.flowable, + org.hibernate.validator, + org.jasypt, + org.javassist, + org.jboss.spec.javax.annotation, + org.jboss.xnio, + org.jdom, + org.mockito, + org.mybatis, + org.mybatis.generator, + org.mybatis.spring.boot, + org.ow2.asm, + org.projectlombok, + org.quartz-scheduler, + org.rocketmq.spring.boot, + org.springframework, + org.springframework.amqp, + org.springframework.boot, + org.springframework.data, + org.springframework.retry, + org.springframework.ws, + org.yaml, + redis.clients, + software.amazon.ion, + tk.mybatis, + xmlpull, + xpp3 + + + + + + + \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/SysApplication.java b/mallinkSysAdmin/src/main/java/com/iformall/SysApplication.java new file mode 100644 index 000000000..98252e9b9 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/SysApplication.java @@ -0,0 +1,52 @@ +package com.iformall; + +import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties; +import org.rocketmq.starter.annotation.EnableRocketMQ; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableAsync; +import springfox.documentation.swagger2.annotations.EnableSwagger2; +import tk.mybatis.spring.annotation.MapperScan; + +/** + * @author chenkx + * @date 2017-12-26 + */ +@SpringBootApplication +@MapperScan(basePackages = {"com.iformall.mapper"}) +@EnableSwagger2 +@EnableEncryptableProperties +@EnableAsync +@EnableRocketMQ +public class SysApplication { + + @Value("${fm.exception}") + private boolean fmException; + + @Value("${fm.exception_emails}") + private String fmExceptionEmails; + + @Value("${fm.open}") + private boolean fmOpen; + + @Bean + public boolean isFmException() { + return fmException; + } + + @Bean + public String fmExceptionEmails() { + return fmExceptionEmails; + } + + @Bean + public boolean isFmOpen() { + return fmOpen; + } + + public static void main(String[] args) { + SpringApplication.run(SysApplication.class, args); + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/advice/JsonpAdvice.java b/mallinkSysAdmin/src/main/java/com/iformall/advice/JsonpAdvice.java new file mode 100644 index 000000000..c07e0005c --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/advice/JsonpAdvice.java @@ -0,0 +1,11 @@ +package com.iformall.advice; + +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.AbstractJsonpResponseBodyAdvice; + +@ControllerAdvice +public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { + public JsonpAdvice() { + super("callback"); + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/annotation/SystemControllerLog.java b/mallinkSysAdmin/src/main/java/com/iformall/annotation/SystemControllerLog.java new file mode 100644 index 000000000..61821c134 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/annotation/SystemControllerLog.java @@ -0,0 +1,10 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SystemControllerLog { + String description() default ""; +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/annotation/SystemServiceLog.java b/mallinkSysAdmin/src/main/java/com/iformall/annotation/SystemServiceLog.java new file mode 100644 index 000000000..f2cd84adf --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/annotation/SystemServiceLog.java @@ -0,0 +1,10 @@ +package com.iformall.annotation; + +import java.lang.annotation.*; + +@Target({ElementType.PARAMETER, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface SystemServiceLog { + String description() default ""; +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/AwsProperty.java b/mallinkSysAdmin/src/main/java/com/iformall/config/AwsProperty.java new file mode 100644 index 000000000..0329f1d6d --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/AwsProperty.java @@ -0,0 +1,52 @@ +package com.iformall.config; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author Stormeye + */ +@Component +@ConfigurationProperties(prefix = "aws") +public class AwsProperty { + // AWS ACCESS KEY + private String access; + + private String secret; + + private String clientRegion; + + private String bucketName; + + public String getAccess() { + return access; + } + + public void setAccess(String access) { + this.access = access; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getClientRegion() { + return clientRegion; + } + + public void setClientRegion(String clientRegion) { + this.clientRegion = clientRegion; + } + + public String getBucketName() { + return bucketName; + } + + public void setBucketName(String bucketName) { + this.bucketName = bucketName; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/KaptchaConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/config/KaptchaConfig.java new file mode 100644 index 000000000..8d20c0893 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/KaptchaConfig.java @@ -0,0 +1,32 @@ +package com.iformall.config; + +import com.google.code.kaptcha.impl.DefaultKaptcha; +import com.google.code.kaptcha.util.Config; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Properties; + + +/** + * 生成验证码配置 + * + * @author stormeye.wu + * @email wugq@mippoint.com + * @date 2017-04-20 19:22 + */ +@Configuration +public class KaptchaConfig { + + @Bean + public DefaultKaptcha producer() { + Properties properties = new Properties(); + properties.put("kaptcha.border", "no"); + properties.put("kaptcha.textproducer.font.color", "black"); + properties.put("kaptcha.textproducer.char.space", "5"); + Config config = new Config(properties); + DefaultKaptcha defaultKaptcha = new DefaultKaptcha(); + defaultKaptcha.setConfig(config); + return defaultKaptcha; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/MyExecutorConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/config/MyExecutorConfig.java new file mode 100644 index 000000000..c60425e84 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/MyExecutorConfig.java @@ -0,0 +1,26 @@ +package com.iformall.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.ThreadPoolExecutor; + +@Configuration +public class MyExecutorConfig { + /** + * 自定义异步线程池 + * + * @return + */ + @Bean + public AsyncTaskExecutor taskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setThreadNamePrefix("Anno-Executor"); + executor.setMaxPoolSize(100); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + return executor; + } +} + diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/RedisConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/config/RedisConfig.java new file mode 100644 index 000000000..7da08a3d9 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/RedisConfig.java @@ -0,0 +1,163 @@ +package com.iformall.config; + +import com.iformall.domain.po.PushLimit; +import com.iformall.domain.po.WxCUser; +import com.iformall.domain.po.WxMall; +import com.iformall.domain.po.WxScoreRules; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CachingConfigurerSupport; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +import java.time.Duration; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Created by Stormeye on 2018/10/1. + */ +@Configuration +@EnableCaching +public class RedisConfig extends CachingConfigurerSupport { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + //缓存管理器 + @Bean + public CacheManager cacheManager(RedisConnectionFactory connectionFactory) { + /* + //user信息缓存配置 + RedisCacheConfiguration userCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)).disableCachingNullValues().prefixKeysWith("user"); + Map redisCacheConfigurationMap = new HashMap<>(); + redisCacheConfigurationMap.put("user", userCacheConfiguration); + //初始化一个RedisCacheWriter + RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory); + // 设置CacheManager的值序列化方式为JdkSerializationRedisSerializer,但其实RedisCacheConfiguration默认就是使用StringRedisSerializer序列化key,JdkSerializationRedisSerializer序列化value,所以以下注释代码为默认实现 + // ClassLoader loader = this.getClass().getClassLoader(); + // JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer(loader); + // RedisSerializationContext.SerializationPair pair = RedisSerializationContext.SerializationPair.fromSerializer(jdkSerializer); + // RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair); + RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig(); + //设置默认超过期时间是30秒 + defaultCacheConfig.entryTtl(Duration.ofSeconds(30)); + //初始化RedisCacheManager + RedisCacheManager cacheManager = new RedisCacheManager(redisCacheWriter, defaultCacheConfig, redisCacheConfigurationMap); + return cacheManager; + */ + RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig(); // 生成一个默认配置,通过config对象即可对缓存进行自定义配置 + config = config.entryTtl(Duration.ofMinutes(1)) // 设置缓存的默认过期时间,也是使用Duration设置 + .disableCachingNullValues(); // 不缓存空值 + + // 设置一个初始化的缓存空间set集合 + Set cacheNames = new HashSet<>(); + cacheNames.add("my-redis-cache1"); + cacheNames.add("my-redis-cache2"); + + // 对每个缓存空间应用不同的配置 + Map configMap = new HashMap<>(); + configMap.put("my-redis-cache1", config); + configMap.put("my-redis-cache2", config.entryTtl(Duration.ofSeconds(120))); + + RedisCacheManager cacheManager = RedisCacheManager.builder(connectionFactory) // 使用自定义的缓存配置初始化一个cacheManager + .initialCacheNames(cacheNames) // 注意这两句的调用顺序,一定要先调用该方法设置初始化的缓存名,再初始化相关的配置 + .withInitialCacheConfigurations(configMap) + .build(); + return cacheManager; + } + + @Bean("pushLimitRedisTemplate") + public RedisTemplate getPushLimitRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(PushLimit.class); + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("scoreRuleRedisTemplate") + public RedisTemplate getScoreRuleRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxScoreRules.class); + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("openRedisTemplate") + public RedisTemplate getWeChatOpen(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + // value值的序列化 + template.setValueSerializer(new StringRedisSerializer()); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("cuserTokenRedisTemplate") + public RedisTemplate getCUserTokenRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxCUser.class); + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + + @Bean("mallRedisTemplate") + public RedisTemplate getMallRedisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate(); + + Jackson2JsonRedisSerializer j = new Jackson2JsonRedisSerializer(WxMall.class); + // value值的序列化 + template.setValueSerializer(j); + template.setHashKeySerializer(j); + + // key的序列化 + template.setKeySerializer(new StringRedisSerializer()); + template.setHashKeySerializer(new StringRedisSerializer()); + + template.setConnectionFactory(connectionFactory); + return template; + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/RestFilter.java b/mallinkSysAdmin/src/main/java/com/iformall/config/RestFilter.java new file mode 100644 index 000000000..4f9298433 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/RestFilter.java @@ -0,0 +1,58 @@ +package com.iformall.config; + +import java.io.IOException; +import java.util.Optional; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * 前后端分离RESTful接口过滤器 + * + * @author xuguoqin + * + */ +public class RestFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + HttpServletRequest req = null; + if (request instanceof HttpServletRequest) { + req = (HttpServletRequest) request; + } + HttpServletResponse res = null; + if (response instanceof HttpServletResponse) { + res = (HttpServletResponse) response; + } + if (req != null && res != null) { + //设置允许传递的参数 + res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization"); + //设置允许带上cookie + res.setHeader("Access-Control-Allow-Credentials", "true"); + String origin = Optional.ofNullable(req.getHeader("Origin")).orElse(req.getHeader("Referer")); + //设置允许的请求来源 + res.setHeader("Access-Control-Allow-Origin", origin); + //设置允许的请求方法 + res.setHeader("Access-Control-Allow-Methods", "GET, POST, PATCH, PUT, DELETE, OPTIONS"); + } + chain.doFilter(request, response); + } + + @Override + public void destroy() { + + } + +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/RestTemplateConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/config/RestTemplateConfig.java new file mode 100644 index 000000000..560a77cb5 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/RestTemplateConfig.java @@ -0,0 +1,24 @@ +package com.iformall.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Bean + public RestTemplate restTemplate(ClientHttpRequestFactory factory) { + return new RestTemplate(factory); + } + + @Bean + public ClientHttpRequestFactory simpleClientHttpRequestFactory() { + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + factory.setReadTimeout(5000);//ms + factory.setConnectTimeout(10000);//ms + return factory; + } +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/ShiroConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/config/ShiroConfig.java new file mode 100644 index 000000000..112d749b2 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/ShiroConfig.java @@ -0,0 +1,317 @@ +package com.iformall.config; + +import com.iformall.service.MallPermissionService; +import com.iformall.shiro.MyRetryLimitCredentialsMatcher; +import com.iformall.shiro.MyShiroRealm; +import org.apache.shiro.mgt.SecurityManager; +import org.apache.shiro.spring.LifecycleBeanPostProcessor; +import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.apache.shiro.web.servlet.SimpleCookie; +import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; +import org.crazycake.shiro.RedisCacheManager; +import org.crazycake.shiro.RedisManager; +import org.crazycake.shiro.RedisSessionDAO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.Filter; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import java.util.LinkedHashMap; +import java.util.Map; + + +/** + * Created by yangqj on 2017/4/23. + */ +@Configuration +public class ShiroConfig { + + @Value("${spring.redis.host}") + private String host; + + @Value("${spring.redis.port}") + private int port; + + @Value("${spring.redis.timeout}") + private int timeout; + + @Value("${spring.redis.expire}") + private int expire; + + @Value("${spring.redis.password}") + private String password; + + @Bean + public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { + return new LifecycleBeanPostProcessor(); + } + + /** + * ShiroDialect,为了在thymeleaf里使用shiro的标签的bean + * @return + */ +// @Bean +// public ShiroDialect shiroDialect() { +// return new ShiroDialect(); +// } + + /** + * ShiroFilterFactoryBean 处理拦截资源文件问题。 + * 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在 + * 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager + *

+ * Filter Chain定义说明 + * 1、一个URL可以配置多个Filter,使用逗号分隔 + * 2、当设置多个过滤器时,全部验证通过,才视为通过 + * 3、部分过滤器可指定参数,如perms,roles + */ + @Bean + public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { + System.out.println("ShiroConfiguration.shirFilter()"); + ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); + // 必须设置 SecurityManager + shiroFilterFactoryBean.setSecurityManager(securityManager); + Map filters = new LinkedHashMap(); + filters.put("token", new ShiroLoginFilter()); + filters.put("corsFilter", new RestFilter()); + //filters.put("authc", new MyFormAuthenticationFilter()); + shiroFilterFactoryBean.setFilters(filters); + // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面 + shiroFilterFactoryBean.setLoginUrl("/#/"); + // 登录成功后要跳转的链接 + + shiroFilterFactoryBean.setSuccessUrl("/usersPage"); + //未授权界面; + shiroFilterFactoryBean.setUnauthorizedUrl("/403"); + //拦截器. + Map filterChainDefinitionMap = new LinkedHashMap(); + + //filterChainDefinitionMap.put("/ue/**", "anon"); + //filterChainDefinitionMap.put("/config.json", "anon"); + // login + filterChainDefinitionMap.put("/doLogin/**", "anon"); + filterChainDefinitionMap.put("/bHidLogin/**", "anon"); + filterChainDefinitionMap.put("/sendLoginPhoneCode/**", "anon"); + filterChainDefinitionMap.put("/doLoginByPhone/**", "anon"); + filterChainDefinitionMap.put("/wechat/login", "anon"); // 微信第三方登录callback + filterChainDefinitionMap.put("/wechat/callback", "anon"); // 微信网页登录回调 + filterChainDefinitionMap.put("/wechat/weChatUserLogin", "anon"); // 微信第三方登录 + // 验证码 + filterChainDefinitionMap.put("/captcha.jpg", "anon"); + // 官网 + filterChainDefinitionMap.put("/wxMallApply/add", "anon"); + // callback + filterChainDefinitionMap.put("/wxPay/notify/**", "anon"); // 支付回调 + filterChainDefinitionMap.put("/wxPayBill/notify/**", "anon"); + filterChainDefinitionMap.put("/wxMsgCallback/**", "anon"); + filterChainDefinitionMap.put("/user/sendvalidationcode", "anon"); + filterChainDefinitionMap.put("/user/updatepwd", "anon"); + filterChainDefinitionMap.put("/carCallback/**", "anon"); + filterChainDefinitionMap.put("/wxMallApply/sendvalidationcode", "anon"); + + // static files + filterChainDefinitionMap.put("/css/**", "anon"); + filterChainDefinitionMap.put("/js/**", "anon"); + filterChainDefinitionMap.put("/img/**", "anon"); + filterChainDefinitionMap.put("/font-awesome/**", "anon"); + + //:这是一个坑呢,一不小心代码就不好使了; + // + //自定义加载权限资源关系 +// Map map = new HashMap<>(); +// List resourcesList = resourcesService.list(map); +// for(SysPermission resources:resourcesList){ +// +// if (StringUtil.isNotEmpty(resources.getUrl())) { +// String permission = "perms[" + resources.getUrl()+ "]"; +// filterChainDefinitionMap.put(resources.getUrl(),permission); +// } +// } + // swagger-ui + filterChainDefinitionMap.put("/swagger-ui.html", "anon"); + filterChainDefinitionMap.put("/v2/**", "anon"); + filterChainDefinitionMap.put("/swagger-resources/**", "anon"); + filterChainDefinitionMap.put("/webjars/**", "anon"); + + filterChainDefinitionMap.put("/version", "anon"); + filterChainDefinitionMap.put("/wxDeviceScreenAd/**", "anon"); +// filterChainDefinitionMap.put("/role/**", "corsFilter,token"); + + + //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 + filterChainDefinitionMap.put("/logout", "authc"); + + filterChainDefinitionMap.put("/**", "corsFilter,token,authc"); +// filterChainDefinitionMap.put("/**", "anon"); + + + shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return shiroFilterFactoryBean; + } + + + public static boolean isAjax(ServletRequest request) { + String header = ((HttpServletRequest) request).getHeader("X-Requested-With"); + if ("XMLHttpRequest".equalsIgnoreCase(header)) { + System.out.println("当前请求为Ajax请求"); + return Boolean.TRUE; + } + System.out.println("当前请求非Ajax请求"); + return Boolean.FALSE; + } + + @Bean + public SecurityManager securityManager(@Qualifier("myRetryLimitCredentialsMatcher") MyRetryLimitCredentialsMatcher matcher) { + DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); + //设置realm. + securityManager.setRealm(myShiroRealm(matcher)); + // 自定义缓存实现 使用redis + //securityManager.setCacheManager(cacheManager()); + // 自定义session管理 使用redis + securityManager.setSessionManager(sessionManager()); + return securityManager; + } + + @Bean + public MyShiroRealm myShiroRealm(MyRetryLimitCredentialsMatcher matcher) { + MyShiroRealm myShiroRealm = new MyShiroRealm(); + myShiroRealm.setCredentialsMatcher(matcher); + return myShiroRealm; + } + + + /** + * 密码匹配凭证管理器 凭证匹配器 + * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了 + * 所以我们需要修改下doGetAuthenticationInfo中的代码; + * ) + * + * @return + */ + @Bean(name = "myRetryLimitCredentialsMatcher") + public MyRetryLimitCredentialsMatcher hashedCredentialsMatcher() { + MyRetryLimitCredentialsMatcher hashedCredentialsMatcher = new MyRetryLimitCredentialsMatcher(); + + hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法; + hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5("")); + + return hashedCredentialsMatcher; + } + + + /** + * 开启shiro aop注解支持. + * 使用代理方式;所以需要开启代码支持; + * + * @param securityManager + * @return + */ + @Bean + public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { + AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); + authorizationAttributeSourceAdvisor.setSecurityManager(securityManager); + return authorizationAttributeSourceAdvisor; + } + + /** + * 配置shiro redisManager + * 使用的是shiro-redis开源插件 + * + * @return + */ + public RedisManager redisManager() { + RedisManager redisManager = new RedisManager(); + redisManager.setHost(host); + redisManager.setPort(port); + //redisManager.setExpire(expire);// 配置缓存过期时间 + redisManager.setTimeout(timeout); + redisManager.setPassword(password); + return redisManager; + } + + /** + * cacheManager 缓存 redis实现 + * 使用的是shiro-redis开源插件 + * + * @return + */ + public RedisCacheManager cacheManager() { + RedisCacheManager redisCacheManager = new RedisCacheManager(); + redisCacheManager.setRedisManager(redisManager()); + return redisCacheManager; + } + + + /** + * RedisSessionDAO shiro sessionDao层的实现 通过redis + * 使用的是shiro-redis开源插件 + */ + @Bean + public RedisSessionDAO redisSessionDAO() { + RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); + redisSessionDAO.setRedisManager(redisManager()); + return redisSessionDAO; + } + + /** + * shiro session的管理 + */ + @Bean + public DefaultWebSessionManager sessionManager() { + DefaultWebSessionManager sessionManager = new DefaultWebSessionManager(); + //设置session过期时间为1小时(单位:毫秒),默认为30分钟 + sessionManager.setGlobalSessionTimeout(60 * 60 * 1000); + sessionManager.setSessionValidationSchedulerEnabled(true); + sessionManager.setSessionIdUrlRewritingEnabled(false); + + sessionManager.setSessionDAO(redisSessionDAO()); + sessionManager.setSessionIdCookie(simpleCookie()); + return sessionManager; + } + + @Bean + public SimpleCookie simpleCookie() { + SimpleCookie simpleCookie = new SimpleCookie("SSIDS"); + simpleCookie.setDomain(""); + return simpleCookie; + } + +// @Bean +// public SimpleCookie rememberMeCookie(){ +// //System.out.println("ShiroConfiguration.rememberMeCookie()"); +// //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe +// SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); +// // +// simpleCookie.setMaxAge(60*30); +// return simpleCookie; +// } + +// @Bean +// public CookieRememberMeManager rememberMeManager(){ +// //System.out.println("ShiroConfiguration.rememberMeManager()"); +// CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); +// cookieRememberMeManager.setCookie(rememberMeCookie()); +// //rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位) +// cookieRememberMeManager.setCipherKey(Base64.decodeBytes("2AvVhdsgUs0FSA3SDFAdag==")); +// return cookieRememberMeManager; +// } + +// @Bean(name = "securityManager") +// public DefaultWebSecurityManager defaultWebSecurityManager(MyShiroRealm realm){ +// DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); +// //设置realm +// securityManager.setRealm(realm); +// //用户授权/认证信息Cache, 采用EhCache缓存 +// securityManager.setCacheManager(cacheManager()); +// //注入记住我管理器 +// securityManager.setRememberMeManager(rememberMeManager()); +// return securityManager; +// } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/ShiroLoginFilter.java b/mallinkSysAdmin/src/main/java/com/iformall/config/ShiroLoginFilter.java new file mode 100644 index 000000000..67c07385e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/ShiroLoginFilter.java @@ -0,0 +1,31 @@ +package com.iformall.config; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; + +import org.apache.shiro.web.filter.authc.FormAuthenticationFilter; + +import com.alibaba.fastjson.JSON; +import com.iformall.common.ResultData; +public class ShiroLoginFilter extends FormAuthenticationFilter { + + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + ResultData resultData = new ResultData(ResultData.UNLOGIN,"用户未登录"); + response.getWriter().write(JSON.toJSONString(resultData)); + return false; + } + + /** + * 判断ajax请求 + * @param request + * @return + */ + boolean isAjax(HttpServletRequest request){ + return (request.getHeader("X-Requested-With") != null && "XMLHttpRequest".equals( request.getHeader("X-Requested-With").toString()) ) ; + } + +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/WebConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/config/WebConfig.java new file mode 100644 index 000000000..d08ea21f5 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/WebConfig.java @@ -0,0 +1,151 @@ +package com.iformall.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationConfig; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import com.iformall.interceptor.HttpServletRequestWrapperFilter; +import com.iformall.interceptor.RequestInterceptor; +import com.iformall.ueditor.ActionEnter; +import com.iformall.ueditor.ConfigManager; +import com.iformall.ueditor.UEditorConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CharacterEncodingFilter; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.*; + +import javax.servlet.Filter; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.List; + +@Configuration +@EnableWebMvc +@EnableConfigurationProperties({UEditorConfig.class, AwsProperty.class}) +public class WebConfig implements WebMvcConfigurer { + @Autowired + private UEditorConfig uEditorConfig; + + @Autowired + private AwsProperty awsProperty; + + @Autowired + private RequestInterceptor requestInterceptor; + + @Bean + @ConditionalOnMissingBean(ActionEnter.class) + public ActionEnter actionEnter() { + ActionEnter actionEnter = new ActionEnter(ConfigManager.getInstance(uEditorConfig, awsProperty)); + return actionEnter; + } + + @Bean + public CorsFilter corsFilter() { + final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource(); + final CorsConfiguration corsConfiguration = new CorsConfiguration(); + // 允许cookies跨域 + corsConfiguration.setAllowCredentials(true); + // 允许向该服务器提交请求的URI, *表示全部允许 + corsConfiguration.addAllowedOrigin("*"); + // 允许访问的头信息,*表示全部 + corsConfiguration.addAllowedHeader("*"); + // 允许提交请求的方法, *表示全部允许 + corsConfiguration.addAllowedMethod("*"); + urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration); + return new CorsFilter(urlBasedCorsConfigurationSource); + } + + /** + * 用于处理编码问题 + * + * @return + */ + @Bean + public Filter characterEncodingFilter() { + CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); + characterEncodingFilter.setEncoding("UTF-8"); + characterEncodingFilter.setForceEncoding(true); + return characterEncodingFilter; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(requestInterceptor).addPathPatterns("/**"); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("swagger-ui.html") + .addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + // ueditor + registry.addResourceHandler("/upload/**") + .addResourceLocations("file:" + uEditorConfig.getUploadPath()); + registry.addResourceHandler("/config.json").addResourceLocations("classpath:/config.json"); + + } + + @Override + public void addCorsMappings(CorsRegistry registry) { + registry.addMapping("/**") + .allowedOrigins("*") + .allowCredentials(true) + .allowedMethods("GET", "POST", "DELETE", "PUT") + .maxAge(3600); + } + + @Override + public void configureMessageConverters(List> converters) { + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); + //ObjectMapper 是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然 + ObjectMapper objectMapper = new ObjectMapper(); + SimpleModule simpleModule = new SimpleModule(); + + //不显示为null的字段 + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + + DeserializationConfig dc = objectMapper.getDeserializationConfig(); + // 设置反序列化日期格式、忽略不存在get、set的属性 + objectMapper.setConfig( + dc.with(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")) + .without(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + ); + + //序列化将Long转String类型 + simpleModule.addSerializer(Long.class, ToStringSerializer.instance); + simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance); + SimpleModule bigIntegerModule = new SimpleModule(); + //序列化将BigInteger转String类型 + bigIntegerModule.addSerializer(BigInteger.class, ToStringSerializer.instance); + SimpleModule bigDecimalModule = new SimpleModule(); + //序列化将BigDecimal转String类型 + bigDecimalModule.addSerializer(BigDecimal.class, ToStringSerializer.instance); + objectMapper.registerModule(simpleModule); + objectMapper.registerModule(bigDecimalModule); + objectMapper.registerModule(bigIntegerModule); + jackson2HttpMessageConverter.setObjectMapper(objectMapper); + converters.add(jackson2HttpMessageConverter); + } + + @Bean + public FilterRegistrationBean Filters() { + FilterRegistrationBean registrationBean = new FilterRegistrationBean(); + registrationBean.setFilter(new HttpServletRequestWrapperFilter()); + registrationBean.addUrlPatterns("/*"); + registrationBean.setName("koalaSignFilter"); + return registrationBean; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/WechatMpConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/config/WechatMpConfig.java new file mode 100644 index 000000000..4dff6c762 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/WechatMpConfig.java @@ -0,0 +1,33 @@ +package com.iformall.config; + +import me.chanjar.weixin.mp.api.WxMpConfigStorage; +import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; + +@Component +public class WechatMpConfig { + + @Autowired + private WechatWebProperties wechatWebProperties; + + @Bean + public WxMpService wxMpService() { + //创建WxMpService实例并设置appid和sectret + WxMpService wxMpService = new WxMpServiceImpl(); + //这里的设置方式是跟着这个sdk的文档写的 + wxMpService.setWxMpConfigStorage(wxConfigProvider()); + return wxMpService; + } + + @Bean + public WxMpConfigStorage wxConfigProvider(){ + WxMpInMemoryConfigStorage wxConfigProvider = new WxMpInMemoryConfigStorage(); + wxConfigProvider.setAppId(wechatWebProperties.getAppId()); + wxConfigProvider.setSecret(wechatWebProperties.getSecret()); + return wxConfigProvider; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/config/WechatWebProperties.java b/mallinkSysAdmin/src/main/java/com/iformall/config/WechatWebProperties.java new file mode 100644 index 000000000..0b9047399 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/config/WechatWebProperties.java @@ -0,0 +1,59 @@ +package com.iformall.config; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * Stormeye + */ +@Component +@ConfigurationProperties(prefix = "wechat.web") +public class WechatWebProperties { + /** + * 设置微信第三方平台-微信登录的web应用appid + */ + private String appId; + + /** + * 设置微信第三方平台-微信登录的web应用app secret + */ + private String secret; + + /** + * 网页URL + * @return + */ + private String url; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, + ToStringStyle.MULTI_LINE_STYLE); + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/app/WxAppinfoController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/app/WxAppinfoController.java new file mode 100644 index 000000000..133f7ea0e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/app/WxAppinfoController.java @@ -0,0 +1,245 @@ +package com.iformall.controller.app; + +import cn.binarywang.wx.miniapp.api.WxMaService; +import cn.binarywang.wx.miniapp.bean.WxMaCodeLineColor; +import com.github.pagehelper.PageInfo; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxAppinfo; +import com.iformall.exception.MallinkException; +import com.iformall.service.WxAppinfoService; +import com.iformall.service.wechat.FmOpenService; +import com.iformall.utils.Constant; +import com.iformall.utils.MaUtil; +import com.iformall.utils.QRCodeUtils; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import me.chanjar.weixin.common.error.WxErrorException; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; + +@RestController +@RequestMapping("wxAppinfo") +public class WxAppinfoController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private boolean isFmOpen; + + @Autowired + private WxAppinfoService wxAppinfoService; + + @Autowired + private FmOpenService openService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + public ResultData list(@ModelAttribute WxAppinfo wxAppinfo, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxAppinfoController::list"); + if (null == wxAppinfo) wxAppinfo = new WxAppinfo(); + final PageInfo page = wxAppinfoService.listAsPage(wxAppinfo, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + public ResultData add(@RequestBody WxAppinfo wxAppinfo) { + logger.debug("[" + getIpAddr() + "] WxAppinfoController::add"); + //Assert.notNull(wxAppinfo.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxAppinfoService.saveOrUpdate(wxAppinfo); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + public ResultData update(@RequestBody WxAppinfo wxAppinfo) { + logger.debug("[" + getIpAddr() + "] WxAppinfoController::update"); + wxAppinfoService.saveOrUpdate(wxAppinfo); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxAppinfoController::delete"); + wxAppinfoService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxAppinfoController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxAppinfoService.getById(id)); + } + + @ApiOperation(value = "下载二维码", produces="application/json;charset=UTF-8", notes = "参数{\"name\":\"String\",\"pageUrl\":\"String\", \"sceneParam\":\"二维码参数\", \"type\":0:有限二维码,1:无限二维码,\"withText\":int(0:不带字, 1:加一行字,2:加两行字),\"text1\":\"String\",\"text2\":\"String\"}") + @PostMapping("/downQrCode") + public void downQrCode(HttpServletRequest request, HttpServletResponse response, @RequestBody Map params) throws MallinkException { + logger.debug("[" + getIpAddr() + "] WxAppinfoController::downQrCode"); + String name = (String) params.get("name"); + String pageUrl = (String) params.get("pageUrl"); + String sceneParam = (String) params.get("sceneParam"); + int type = 0; + try { + type = (int) params.get("type"); + } catch (Exception e) { + type = 0; + } + + int withText = 0; + try { + withText = (int) params.get("withText"); + } catch (Exception e) { + withText = 0; + } + String text1 = (String) params.get("text1"); + String text2 = (String) params.get("text2"); + if (StringUtils.isBlank(pageUrl)) { + throw new MallinkException(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "pageUrl不能为空"); + } + try { + exportQrcode(request, response, + getTenantId(), type, pageUrl, sceneParam, + withText, text1, text2, + name); + } catch (Exception e) { + logger.error(e.getMessage()); + throw new MallinkException(Result.ERROR, "下载异常"); + } + } + + private void exportQrcode(HttpServletRequest request, HttpServletResponse response, + String tenantId, int type, String pageUrl, String sceneParam, + int withText, String text1, String text2, + String name) { + // type 0 有限二维码, 1 无限制二维码 + // withText 0 不带字 1. 带下面的字,2 带下面的两行字 + WxAppinfo appinfo = wxAppinfoService.getCAppInfo(tenantId); + boolean autoColor = false; + boolean isHyaline = true; + WxMaCodeLineColor color = new WxMaCodeLineColor("0", "0", "0"); + + WxMaService wxMaService; + if(isFmOpen) { + wxMaService = openService.getWxOpenComponentService().getWxMaServiceByAppid(appinfo.getAppId()); + } else { + wxMaService = MaUtil.getWeappService(appinfo); + } + + String pathStr = ""; + if (StringUtils.isNotBlank(sceneParam)) { + pathStr = pageUrl + "?scene="+sceneParam; + } else { + pathStr = pageUrl; + } + + + String filepath = Constant.fileDirectory; + String fileName = name + ".png"; + String destPath1 = filepath + "1_" + fileName; + String destPath = filepath + fileName; + + File dest = new File(destPath); + File pDest = dest.getParentFile(); + if (!pDest.exists()) { + pDest.mkdirs(); + } + try { + if(type == 0) { + final File codeFile = wxMaService.getQrcodeService().createQrcode(pathStr, QRCodeUtils.QR_WIDTH); + if (withText == 1) { + File dest1 = new File(destPath1); + org.apache.commons.io.FileUtils.copyFile(codeFile, dest1); + QRCodeUtils.graphicsGeneration(dest1, dest, text1); + org.apache.commons.io.FileUtils.forceDelete(dest1); + } else if (withText == 2) { + File dest1 = new File(destPath1); + org.apache.commons.io.FileUtils.copyFile(codeFile, dest1); + QRCodeUtils.graphicsGeneration2(dest1, dest, text1, text2); + org.apache.commons.io.FileUtils.forceDelete(dest1); + } else { + org.apache.commons.io.FileUtils.copyFile(codeFile, dest); + } + org.apache.commons.io.FileUtils.forceDelete(codeFile); + } else { + final File codeFile = wxMaService.getQrcodeService().createWxaCodeUnlimit(sceneParam, pageUrl, QRCodeUtils.QR_WIDTH, autoColor, color, isHyaline); + if (withText == 1) { + File dest1 = new File(destPath1); + org.apache.commons.io.FileUtils.copyFile(codeFile, dest1); + QRCodeUtils.graphicsGeneration(dest1, dest, text1); + org.apache.commons.io.FileUtils.forceDelete(dest1); + } else if (withText == 2) { + File dest1 = new File(destPath1); + org.apache.commons.io.FileUtils.copyFile(codeFile, dest1); + QRCodeUtils.graphicsGeneration2(dest1, dest, text1, text2); + org.apache.commons.io.FileUtils.forceDelete(dest1); + } else { + org.apache.commons.io.FileUtils.copyFile(codeFile, dest); + } + org.apache.commons.io.FileUtils.forceDelete(codeFile); + } + + } catch (WxErrorException e) { + logger.error(e.getMessage()); + } catch (Exception e) { + logger.error(e.getMessage()); + } + + try { + downFile(destPath, fileName, response, request); + org.apache.commons.io.FileUtils.forceDelete(dest); + } catch (Exception e) { + logger.error(e.getMessage()); + } + + } + + private void downFile(String filePath, String filename, HttpServletResponse response, HttpServletRequest req) throws IOException { + try { + response.reset(); + response.setContentType("application/octet-stream"); + String agent = req.getHeader("user-agent"); + if (agent.contains("Firefox")) { + response.setHeader("Content-disposition", + "attachment; filename=" + + new String(filename.getBytes("GB2312"),"ISO-8859-1")); + } else { + response.setHeader("Content-disposition", + "attachment; filename=" + + java.net.URLEncoder.encode(filename,"UTF-8")); + } + // 循环取出流中的数据 + byte[] b = new byte[1024]; + int len; + InputStream inStream = new FileInputStream(filePath); + while ((len = inStream.read(b)) > 0) + response.getOutputStream().write(b, 0, len); + inStream.close(); + } catch (Exception e) { + logger.error(e.getMessage()); + } + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/base/BaseController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/base/BaseController.java new file mode 100644 index 000000000..2767ffb3b --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/base/BaseController.java @@ -0,0 +1,64 @@ +package com.iformall.controller.base; + +import java.beans.PropertyEditorSupport; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.iformall.domain.po.MallUserInfo; +import com.iformall.shiro.UserSession; +import com.iformall.utils.IPUtil; +import org.apache.shiro.SecurityUtils; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.InitBinder; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; + +@RestController +public class BaseController { + + @InitBinder + public void InitBinder(WebDataBinder dataBinder) { + dataBinder.registerCustomEditor(Date.class, new PropertyEditorSupport() { + public void setAsText(String value) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(value)); + } catch(ParseException e) { + try { + setValue(new SimpleDateFormat("yyyy-MM-dd ").parse(value)); + } catch (ParseException e1) { + setValue(null); + } + } + } + + public String getAsText() { + return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((Date) getValue()); + } + + }); + } + public MallUserInfo getUser(){ + MallUserInfo user = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + return user; + } + + public Long getUserId(){ + Long userId = (Long) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userId); + return userId; + } + + public String getTenantId(){ + String tenantId = (String)SecurityUtils.getSubject().getSession().getAttribute(UserSession.tenantId); + return tenantId; + } + + public String getIpAddr() { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + String ipaddress = IPUtil.getIpAddr(request); + return ipaddress; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxBrandController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxBrandController.java new file mode 100644 index 000000000..50ded68c6 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxBrandController.java @@ -0,0 +1,102 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxBrand; +import com.iformall.service.WxBrandService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Map; + +import static com.iformall.domain.po.WxBrand.Field.Id_DESC; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxBrand") +public class WxBrandController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxBrandService wxBrandService; + + + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "品牌-列表") + public ResultData list(@ModelAttribute WxBrand wxBrand, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxBrandController::list"); + if (null == wxBrand) { + wxBrand = new WxBrand(); + } + wxBrand.setSortColumns(Id_DESC); + final PageInfo page = wxBrandService.listAsPage(wxBrand, pageNum, pageSize); + return new ResultData(page); + } + + @PostMapping("add") + @SystemControllerLog(description = "品牌-增加") + public ResultData add(@RequestBody WxBrand wxBrand) { + logger.debug("[" + getIpAddr() + "] WxBrandController::add"); + wxBrand.setTenantId(getTenantId()); + return wxBrandService.save(wxBrand); + } + + @PostMapping("update") + @SystemControllerLog(description = "品牌-更新") + public ResultData update(@RequestBody WxBrand wxBrand) { + logger.debug("[" + getIpAddr() + "] WxBrandController::update"); + wxBrand.setTenantId(getTenantId()); + return wxBrandService.update(wxBrand); + } + + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "品牌-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxBrandController::del"); + wxBrandService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "品牌-查找") + public ResultData findById(Long id) { + return new ResultData(Result.SUCCESS, "查询成功", wxBrandService.getById(id)); + } + + @GetMapping("/queryBrand") + @SystemControllerLog(description = "品牌-租户-全部") + public ResultData queryBrand() { + List> brandList = wxBrandService.queryBrand(getTenantId()); + return new ResultData(brandList); + } + + + @ApiOperation("查询品牌名称是否存在") + @GetMapping("hasBrand") + @ApiImplicitParams({ + @ApiImplicitParam(name = "name", value = "name", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query")}) + @SystemControllerLog(description = "品牌-名称是否存在") + public ResultData hasBrand(String name, Long id) { + logger.debug("[" + getIpAddr() + "] WxBrandController::hasBrand"); + return wxBrandService.hasBrand(getTenantId(), name, id); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxGroupController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxGroupController.java new file mode 100644 index 000000000..c01941f64 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxGroupController.java @@ -0,0 +1,73 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxGroup; +import com.iformall.service.WxGroupService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxGroup") +public class WxGroupController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxGroupService wxGroupService; + + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "集团-列表") + public ResultData list(@ModelAttribute WxGroup wxGroup, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxGroupController::list"); + if (null == wxGroup) wxGroup = new WxGroup(); + final PageInfo page = wxGroupService.listAsPage(wxGroup, pageNum, pageSize); + return new ResultData(page); + } + + @PostMapping("add") + @SystemControllerLog(description = "集团-添加") + public ResultData add(@RequestBody WxGroup wxGroup) { + logger.debug("[" + getIpAddr() + "] WxGroupController::add"); + //Assert.notNull(wxGroup.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxGroupService.saveOrUpdate(wxGroup); + return new ResultData(); + } + + @PostMapping("update") + @SystemControllerLog(description = "集团-更新") + public ResultData update(@RequestBody WxGroup wxGroup) { + logger.debug("[" + getIpAddr() + "] WxGroupController::update"); + wxGroupService.saveOrUpdate(wxGroup); + return new ResultData(); + } + + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "集团-删除") + public ResultData delete(String id) { + logger.debug("[" + getIpAddr() + "] WxGroupController::delete"); + wxGroupService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "集团-查询") + public ResultData findById(String id) { + logger.debug("[" + getIpAddr() + "] WxGroupController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxGroupService.getById(id)); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallBuildingController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallBuildingController.java new file mode 100644 index 000000000..8e4f36042 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallBuildingController.java @@ -0,0 +1,96 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMallBuilding; +import com.iformall.service.WxMallBuildingService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMallBuilding") +public class WxMallBuildingController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMallBuildingService wxMallBuildingService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商城-楼座-列表") + public ResultData list(@ModelAttribute WxMallBuilding wxMallBuilding, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::list"); + if (null == wxMallBuilding) wxMallBuilding = new WxMallBuilding(); + final PageInfo page = wxMallBuildingService.listAsPage(wxMallBuilding, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "商城-楼座-新增") + public ResultData add(@RequestBody WxMallBuilding wxMallBuilding) { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::add"); + //Assert.notNull(wxMallBuilding.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMallBuildingService.saveOrUpdate(wxMallBuilding); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "商城-楼座-更新") + public ResultData update(@RequestBody WxMallBuilding wxMallBuilding) { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::update"); + wxMallBuildingService.saveOrUpdate(wxMallBuilding); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商城-楼座-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::delete"); + wxMallBuildingService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商城-楼座-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMallBuildingService.getById(id)); + } + + + @ApiOperation("获取所有数据") + @GetMapping("getbuildinglist") + @SystemControllerLog(description = "商城-楼座-获取所有数据") + public ResultData getbuildinglist() { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::getbuildinglist"); + return wxMallBuildingService.getbuildinglist(getTenantId()); + } + + @ApiOperation("获取楼层楼座数据") + @GetMapping("getbuildingfloorlist") + @SystemControllerLog(description = "商城-楼座-获取楼层楼座数据") + public ResultData getbuildingfloorlist() { + logger.debug("[" + getIpAddr() + "] WxMallBuildingController::getbuildingfloorlist"); + return wxMallBuildingService.getbuildingfloorlist(getTenantId()); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallController.java new file mode 100644 index 000000000..08e545f22 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallController.java @@ -0,0 +1,95 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMall; +import com.iformall.service.WxMallService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMall") +public class WxMallController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMallService wxMallService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商城") + public ResultData list(@ModelAttribute WxMall wxMall, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMallController::list"); + if (null == wxMall) wxMall = new WxMall(); + final PageInfo page = wxMallService.listAsPage(wxMall, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "商城-新增") + public ResultData add(@RequestBody WxMall wxMall) { + logger.debug("[" + getIpAddr() + "] WxMallController::add"); + //Assert.notNull(wxMall.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMallService.saveOrUpdate(wxMall); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "商城-更新") + public ResultData update(@RequestBody WxMall wxMall) { + logger.debug("[" + getIpAddr() + "] WxMallController::update"); + wxMallService.saveOrUpdate(wxMall); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商城-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMallController::delete"); + wxMallService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商城-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMallController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMallService.getById(id)); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/mallinfoExt") + @SystemControllerLog(description = "商城-查询") + public ResultData mallinfoExt() { + logger.debug("[" + getIpAddr() + "] WxMallController::mallinfoExt"); + return new ResultData(wxMallService.getByTenantIdExt(getTenantId())); + } + + @ApiOperation("查询当前mall的信息") + @GetMapping("/mallinfo") + @SystemControllerLog(description = "商城-当前查询") + public ResultData mallinfo() { + logger.debug("[" + getIpAddr() + "] WxMallController::mallinfo"); + return new ResultData(wxMallService.getByTenantId(getTenantId())); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallFloorController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallFloorController.java new file mode 100644 index 000000000..7825f42eb --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMallFloorController.java @@ -0,0 +1,91 @@ +package com.iformall.controller.basic; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.controller.base.BaseController; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import com.github.pagehelper.PageInfo; +import com.iformall.common.Result; +import com.iformall.common.ResultData; + +import com.iformall.domain.po.WxMallFloor; +import com.iformall.service.WxMallFloorService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; + +@RestController +@RequestMapping("wxMallFloor") +public class WxMallFloorController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMallFloorService wxMallFloorService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商城-楼层-列表") + public ResultData list(@ModelAttribute WxMallFloor wxMallFloor, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMallFloorController::list"); + if (null == wxMallFloor) wxMallFloor = new WxMallFloor(); + final PageInfo page = wxMallFloorService.listAsPage(wxMallFloor, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "商城-楼层-新增") + public ResultData add(@RequestBody WxMallFloor wxMallFloor) { + logger.debug("[" + getIpAddr() + "] WxMallFloorController::add"); + //Assert.notNull(wxMallFloor.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMallFloorService.saveOrUpdate(wxMallFloor); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "商城-楼层-更新") + public ResultData update(@RequestBody WxMallFloor wxMallFloor) { + logger.debug("[" + getIpAddr() + "] WxMallFloorController::update"); + wxMallFloorService.saveOrUpdate(wxMallFloor); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商城-楼层-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMallFloorController::delete"); + wxMallFloorService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商城-楼层-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMallFloorController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMallFloorService.getById(id)); + } + + @ApiOperation("获取所有数据") + @GetMapping("getfloorlist") + @ApiImplicitParams({ + @ApiImplicitParam(name = "buildingId", value = "楼座ID", dataType = "Long", paramType = "query", required = true)}) + @SystemControllerLog(description = "商城-楼座-楼层") + public ResultData getfloorlist(Long buildingId) { + logger.debug("[" + getIpAddr() + "] WxMallFloorController::getfloorlist"); + return wxMallFloorService.getfloorlist(getTenantId(), buildingId); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMerchantController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMerchantController.java new file mode 100644 index 000000000..0d4c8426d --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/basic/WxMerchantController.java @@ -0,0 +1,190 @@ +package com.iformall.controller.basic; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMerchant; +import com.iformall.domain.vo.WxMerchantVo; +import com.iformall.service.WxMerchantService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.List; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxMerchant") +public class WxMerchantController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMerchantService wxMerchantService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "商户-列表") + public ResultData list(@ModelAttribute WxMerchant wxMerchant, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::list"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.setTenantId(getTenantId()); + wxMerchant.setSortColumns(WxMerchant.Field.TopTime_DESC); + final PageInfo page = wxMerchantService.listAsPage(wxMerchant, pageNum, pageSize); + return new ResultData(page); + } + + + @ApiOperation("ETCP商户列表") + @GetMapping("etcplist") + @SystemControllerLog(description = "商户-ETCP商户列表") + public ResultData etcpList(@ModelAttribute WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::etcpList"); + if (null == wxMerchant) wxMerchant = new WxMerchant(); + wxMerchant.setTenantId(getTenantId()); + final List merchantList = wxMerchantService.etcpList(wxMerchant); + return new ResultData(merchantList); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::delete"); + wxMerchantService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::findById"); + WxMerchant wxMerchant = wxMerchantService.getById(id); + + return new ResultData(wxMerchant); + } + + @ApiOperation("停用") + @GetMapping("disable") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-停用") + public ResultData disable(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::disable"); + wxMerchantService.disable(id); + return new ResultData(Result.SUCCESS, "停用成功"); + } + + @ApiOperation("新增商户接口") + @PostMapping("addMerchant") + @SystemControllerLog(description = "商户-新增") + public ResultData addMerchant(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::addMerchant"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.addMerchant(wxMerchant, getUserId()); + } + + @ApiOperation("更新商户接口") + @PostMapping("updateMerchant") + @SystemControllerLog(description = "商户-更新") + public ResultData updateMerchant(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchant"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.updateMerchant(wxMerchant); + } + + @ApiOperation("更新账户接口") + @PostMapping("updateMerchantAccount") + @SystemControllerLog(description = "商户-更新账户") + public ResultData updateMerchantAccount(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantAccount"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.updateMerchantAccount(wxMerchant); + } + + @ApiOperation("更新管理员接口") + @PostMapping("updateMerchantAdmin") + @SystemControllerLog(description = "商户-更新管理员") + public ResultData updateMerchantAdmin(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantAdmin"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.updateMerchantAdmin(wxMerchant); + } + + @ApiOperation("更新法人接口") + @PostMapping("updateMerchantCorp") + @SystemControllerLog(description = "商户-更新法人") + public ResultData updateMerchantCopr(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantCorp"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.updateMerchantCorp(wxMerchant); + } + + @ApiOperation("更新税务接口") + @PostMapping("updateMerchantTax") + @SystemControllerLog(description = "商户-更新税务") + public ResultData updateMerchantTax(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantTax"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.updateMerchantTax(wxMerchant); + } + + @ApiOperation("更新会员等级权益接口") + @PostMapping("updateMerchantLevel") + @SystemControllerLog(description = "商户-更新会员等级权益") + public ResultData updateMerchantLevel(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::updateMerchantLevel"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.updateMerchantLevel(wxMerchant); + } + + @ApiOperation("查询当前租户下商户名称列表") + @GetMapping("/name_list") + @SystemControllerLog(description = "查询当前租户下商户名称列表") + public ResultData nameList() { + logger.debug("[" + getIpAddr() + "] WxMerchantController::name_list"); + return new ResultData(wxMerchantService.findList(getTenantId())); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findMerchantById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "商户-查询") + public ResultData findMerchantById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::findMerchantById"); + WxMerchantVo wxMerchant = wxMerchantService.findMerchantById(id); + return new ResultData(wxMerchant); + } + + @ApiOperation("商户数据导出") + @GetMapping("/exportData") + @SystemControllerLog(description = "商户-商户数据导出") + public void exportData(@ModelAttribute WxMerchant wxMerchant, HttpServletRequest request, HttpServletResponse response) { + wxMerchant.setTenantId(getTenantId()); + wxMerchantService.exportData(wxMerchant,request,response); + } + + @ApiOperation("置顶") + @PostMapping("top") + @SystemControllerLog(description = "商户-置顶") + public ResultData top(@RequestBody WxMerchant wxMerchant) { + logger.debug("[" + getIpAddr() + "] WxMerchantController::top"); + wxMerchant.setTenantId(getTenantId()); + return wxMerchantService.top(wxMerchant); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java new file mode 100644 index 000000000..9dfcc6cab --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgCallbackController.java @@ -0,0 +1,82 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgCallback; +import com.iformall.service.WxMsgCallbackService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("msgCallback") +public class WxMsgCallbackController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgCallbackService wxMsgCallbackService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "短信回调结果-列表") + public ResultData list(@ModelAttribute WxMsgCallback wxMsgCallback, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::list"); + if (null == wxMsgCallback) wxMsgCallback = new WxMsgCallback(); + wxMsgCallback.setTenantId(getTenantId()); + wxMsgCallback.setSortColumns(WxMsgCallback.Field.Createtime_DESC); + final PageInfo page = wxMsgCallbackService.listAsPage(wxMsgCallback, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "短信回调结果-新增") + public ResultData add(@RequestBody WxMsgCallback wxMsgCallback) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::add"); + //Assert.notNull(wxMsgCallback.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgCallback.setTenantId(getTenantId()); + wxMsgCallbackService.saveOrUpdate(wxMsgCallback); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "短信回调结果-更新") + public ResultData update(@RequestBody WxMsgCallback wxMsgCallback) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::update"); + wxMsgCallbackService.saveOrUpdate(wxMsgCallback); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信回调结果-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::delete"); + wxMsgCallbackService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信回调结果-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgCallbackController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgCallbackService.getById(id)); + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgConfigController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgConfigController.java new file mode 100644 index 000000000..6b226eb6b --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgConfigController.java @@ -0,0 +1,79 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgConfig; +import com.iformall.service.WxMsgConfigService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgConfig") +public class WxMsgConfigController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgConfigService wxMsgConfigService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "短信-配置-列表") + public ResultData list(@ModelAttribute WxMsgConfig wxMsgConfig, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::list"); + if (null == wxMsgConfig) wxMsgConfig = new WxMsgConfig(); + final PageInfo page = wxMsgConfigService.listAsPage(wxMsgConfig, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "短信-配置-新增") + public ResultData add(@RequestBody WxMsgConfig wxMsgConfig) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::add"); + //Assert.notNull(wxMsgConfig.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgConfigService.saveOrUpdate(wxMsgConfig); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "短信-配置-更新") + public ResultData update(@RequestBody WxMsgConfig wxMsgConfig) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::update"); + wxMsgConfigService.saveOrUpdate(wxMsgConfig); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信-配置-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::delete"); + wxMsgConfigService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信-配置-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgConfigController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgConfigService.getById(id)); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgController.java new file mode 100644 index 000000000..9074089da --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgController.java @@ -0,0 +1,108 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.msg.WxMsg; +import com.iformall.service.WxMsgService; +import com.iformall.utils.Constant; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.*; + +/** + * @author gongbiao + */ +@RestController +@RequestMapping("wxMsg") +public class WxMsgController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + + @Autowired + private WxMsgService wxMsgService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "标签短信-列表") + public ResultData list(@ModelAttribute WxMsg wxMsg, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgController::list"); + if (null == wxMsg) wxMsg = new WxMsg(); + wxMsg.setTenantId(getTenantId()); + //wxMsg.setWay(EnumSendWay.TAG.getCode()); + wxMsg.setSortColumns(WxMsg.Field.Createtime_DESC); + final PageInfo page = wxMsgService.listAsPage(wxMsg, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "标签短信-新增") + public ResultData add(@RequestBody WxMsg wxMsg) { + logger.debug("[" + getIpAddr() + "] WxMsgController::add"); + wxMsg.setTenantId(getTenantId()); + return wxMsgService.add(wxMsg); + } + + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "标签短信-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgController::delete"); + wxMsgService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "标签短信-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgController::findById"); + WxMsg wxMsg = wxMsgService.getById(id); + return new ResultData(wxMsg); + } + + + @RequestMapping("/excleupload") + public ResultData excleupload(@RequestParam("file") MultipartFile file) { + logger.debug("[" + getIpAddr() + "] WxMsgController::excleupload"); + if (file.isEmpty()) { + return new ResultData(Result.SUCCESS, "上传文件不能为空"); + } + + String filename = UUID.randomUUID() + file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".")); + File path = new File(Constant.fileDirectory); + if (!path.exists()) { + path.mkdirs(); + } + String filepath = Constant.fileDirectory + File.separator + filename; + try { + FileOutputStream out = new FileOutputStream(new File(filepath)); + IOUtils.write(file.getBytes(), out); + IOUtils.closeQuietly(out); + } catch (Exception e) { + return new ResultData(Result.ERROR, "上传失败"); + } + + return new ResultData(Result.SUCCESS, "上传成功", filepath); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgModelController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgModelController.java new file mode 100644 index 000000000..f3e80a330 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgModelController.java @@ -0,0 +1,89 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgModel; +import com.iformall.service.WxMsgModelService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgModel") +public class WxMsgModelController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgModelService wxMsgModelService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "短信模板-列表") + public ResultData list(@ModelAttribute WxMsgModel wxMsgModel, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::list"); + if (null == wxMsgModel) wxMsgModel = new WxMsgModel(); + wxMsgModel.setTenantId(getTenantId()); + wxMsgModel.setSortColumns(WxMsgModel.Field.Createtime_DESC); + final PageInfo page = wxMsgModelService.listAsPage(wxMsgModel, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "短信模板-新增") + public ResultData add(@RequestBody WxMsgModel wxMsgModel) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::add"); + //Assert.notNull(wxMsgModel.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgModel.setTenantId(getTenantId()); + return wxMsgModelService.saveOrUpdate(wxMsgModel); + + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "短信模板-更新") + public ResultData update(@RequestBody WxMsgModel wxMsgModel) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::update"); + return wxMsgModelService.saveOrUpdate(wxMsgModel); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信模板-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::delete"); + wxMsgModelService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "短信模板-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgModelService.getById(id)); + } + + @ApiOperation("获取所有数据") + @GetMapping("getmodellist") + @SystemControllerLog(description = "短信模板-获取所有数据") + public ResultData getmodellist() { + logger.debug("[" + getIpAddr() + "] WxMsgModelController::getmodellist"); + return wxMsgModelService.getmodellist(getTenantId()); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgRecordController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgRecordController.java new file mode 100644 index 000000000..860b75a63 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgRecordController.java @@ -0,0 +1,111 @@ +package com.iformall.controller.msg; + +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.msg.MailMsg; +import com.iformall.domain.po.msg.SmartAppMsg; +import com.iformall.domain.po.msg.WxMsg; +import com.iformall.domain.po.msg.WxMsgRecord; +import com.iformall.enums.*; +import com.iformall.mapper.WxMsgMapper; +import com.iformall.mq.MqBaseProducer; +import com.iformall.service.WxMsgRecordService; +import com.iformall.service.msg.impl.SendCallBackSmsServiceImpl; +import com.iformall.utils.JsonUtil; +import io.swagger.annotations.Api; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import java.util.List; + +@RestController +@Api(description = "消息记录") +@RequestMapping(value = "msgrecord") +public class WxMsgRecordController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgRecordService wxMsgRecordService; + @Autowired + private MqBaseProducer mqBaseProducer; + @Autowired + private WxMsgMapper wxMsgMapper; + @Autowired + private SendCallBackSmsServiceImpl msgSendService; + + + @GetMapping(value = "/test") + public ResultData test(Long id) throws Exception{ +// String systemTime = DateUtils.getSystemTime("yyyy-MM-dd HH:00:00"); +// WxMsg wxMsg = new WxMsg(); +// wxMsg.setIsright(0); +// wxMsg.setSendtime(systemTime); +// wxMsg.setId(id); +// List list = wxMsgMapper.findList(wxMsg); +// logger.info("将要发送的短信列表:" + JSONArray.toJSONString(list)); +// for (WxMsg msg : list) { +// //sendmsg(msg); +// msg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode()); +// msg.setReceiver(msg.getPhones()); +// mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(),null); +// } + + String s = "{\"msg\": \"新手妈妈不要怕,金宝贝帮您带孩子,音乐美术还有游戏,孩子玩着玩着就长大了\", \"way\": 2, \"name\": \"亲子活动\", \"uuid\": \"0a4ae632-9522-4a8f-bb0d-b22620ac79c3\", \"label\": \"\", \"domain\": 0, \"phones\": \"18601973448\", \"status\": 1, \"isright\": 1, \"modelId\": 204500584231862272, \"msgType\": 2, \"receiver\": \"18601973448\", \"sendtime\": \"2019-04-17 18:29:08\", \"tenantId\": \"456\", \"signature\": \"富茂科技\", \"errorNumber\": 0, \"wxMsgConfig\": {\"id\": 1, \"bid\": \"465565\", \"appid\": \"wx9ff823abeef23b94\", \"total\": 100000, \"secret\": \"7305150347587283553aa8898e7dbf20\", \"account\": \"15626593768\", \"remains\": 62667, \"recharge\": 0, \"tenantId\": \"456\", \"notifyurl\": \"http://202.165.179.86:9000/wxMsgCallback/receivemsg/456\", \"publickey\": \"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvh8j/zagfxQdnSh5OIic\\r\\nMzN+MuRuWQJPjgu4Gza4+gX3j5Ln2xNDBOTjpwyuLBjh/JcBd1cGO3lAaKCwcaix\\r\\nsmhTq56wVXXUMgDiAChu4ud8FSvRc8G8tdZAirKVAIi3NW+/pYgpWBs/0wnF8hz4\\r\\n8no4pyJHl9Jc1LH3VNIMz8vqzKUPc4ack4pFUXlcNj6C+sBlaurmI4/vwLqNxBGs\\r\\n7/zyM7dv6oy3DSU/Y1qBArM1YPjfL2dNun8rmtPgJvlPwXqA7uoHPwQ2Ym3aUn59\\r\\npkS7QI6IE8uuqNkfSte8BXLd2nIqPLFxLYLDmdll7eoyRblHcHqAYSj8stK6StC7\\r\\nDNryNKEjTEwbgf9trUI0uvF1pfgTy2gpclnY69FtD/m0+FvLyorMq+nmBqYMjka5\\r\\nK0txDQJPOa7gsi//uXd/cJW2SAXY9MSO1AfMi8Xq/YKRQzN9FW5iapskXFHca7uX\\r\\ng5NhH7flr6DW+QInFlpoN6WIEAuDF1aj4O49Ikm3WxwhTqnvEkdSCfivpYQkp9Sh\\r\\n4kQ/SQdxuT7VX+Nz6k+uMx2z4cySk33bHi0KoHbA9QFGg/54Qd0+eU4qZnd4mrgh\\r\\nhH7/QQhL7Z9eF1U5UPrsHq2Vq3rEnN+tYQ26AuKeU8vzTxBrC/SxC6C/SMFt3f/Y\\r\\nnuFh1UnNJZleZwyQt+ZdGO0CAwEAAQ==\", \"modelnotifyurl\": \"http://202.165.179.86:9000/wxMsgCallback/receivemodel/456\", \"reminderstatus\": 0, \"verifynotifyurl\": \"http://202.165.179.86:9000/wxMsgCallback/receiveverifymodel/456\"}, \"couponInject\": {\"id\": 278440211602472960, \"name\": \"END\", \"tags\": \"[{\\\"name\\\":\\\"一天以上+普通会员+男\\\",\\\"tagList\\\":[{\\\"id\\\":1011,\\\"typeId\\\":50},{\\\"id\\\":0,\\\"typeId\\\":51},{\\\"id\\\":1}]},{\\\"name\\\":\\\"一月以上+男\\\",\\\"tagList\\\":[{\\\"id\\\":1009,\\\"typeId\\\":50},{\\\"id\\\":1}]}]\", \"status\": 2, \"mUserId\": 204398756307664896, \"modelId\": 204500584231862272, \"muserId\": 204398756307664896, \"couponId\": 275856462247362560, \"sendTime\": \"2019-04-17 18:28:49\", \"sendType\": 0, \"tenantId\": \"456\", \"couponName\": \"礼品券大礼5\", \"filterList\": [{\"name\": \"一天以上+普通会员+男\", \"tagList\": [{\"id\": 1011, \"typeId\": 50}, {\"id\": 0, \"typeId\": 51}, {\"id\": 1}]}, {\"name\": \"一月以上+男\", \"tagList\": [{\"id\": 1009, \"typeId\": 50}, {\"id\": 1}]}], \"sendAmount\": 40}, \"successNumber\": 0, \"delayTimeLevel\": 0, \"expectSendNumber\": 40}"; + WxMsg wxMsg = (WxMsg) JsonUtil.readValue(s,WxMsg.class); + wxMsg.setMsgType(EnumMsgRecordType.SMS_CALLBACK.getCode()); + wxMsg.setReceiver("18601973448"); + wxMsg.setTenantId("456"); + msgSendService.send(wxMsg); + return new ResultData(); + } + + /** + * 重新发送失败的消息 + * @param x + * @return + */ + @GetMapping(value = "/resendMsg") + public ResultData resendMsg(String x) { + if("xll1dxx1314".equals(x)){ + WxMsgRecord msgRecord = new WxMsgRecord(); + msgRecord.setMsgStatus(EnumMsgRecordStatus.CONSUME_FAIL.getCode()); + List recordList = wxMsgRecordService.findList(msgRecord); + for (WxMsgRecord wxMsgRecord:recordList) { + if(EnumMsgRecordType.SMS.getCode().equals(wxMsgRecord.getMsgType())){ + //短信 + mqBaseProducer.sendMessage(wxMsgRecord, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + }else if(EnumMsgRecordType.SMS_CALLBACK.getCode().equals(wxMsgRecord.getMsgType())){ + //业务短信 + WxMsg wxMsg = (WxMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),WxMsg.class); + wxMsg.setMsgType(wxMsgRecord.getMsgType()); + wxMsg.setReceiver(wxMsgRecord.getReceiver()); + wxMsg.setTenantId(wxMsgRecord.getTenantId()); + mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + }else if(EnumMsgRecordType.EMAIL.getCode().equals(wxMsgRecord.getMsgType())){ + //邮件 + MailMsg wxMsg = (MailMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),MailMsg.class); + wxMsg.setMsgType(wxMsgRecord.getMsgType()); + wxMsg.setReceiver(wxMsgRecord.getReceiver()); + wxMsg.setTenantId(wxMsgRecord.getTenantId()); + mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + }else if(EnumMsgRecordType.SMART_APP.getCode().equals(wxMsgRecord.getMsgType())){ + //微信小程序 + SmartAppMsg wxMsg = (SmartAppMsg) JsonUtil.readValue(wxMsgRecord.getMsgJson(),SmartAppMsg.class); + wxMsg.setMsgType(wxMsgRecord.getMsgType()); + wxMsg.setReceiver(wxMsgRecord.getReceiver()); + wxMsg.setTenantId(wxMsgRecord.getTenantId()); + mqBaseProducer.sendMessage(wxMsg, EnumMsgMqTopic.DEFAULT.getCode(), EnumMsgMqTag.DEFAULT.getCode(), EnumMsgMqKey.DEFAULT.getCode()); + } + } + return new ResultData(); + }else{ + return new ResultData("fail"); + } + } + + + + + +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgSignatureController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgSignatureController.java new file mode 100644 index 000000000..fbede329c --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgSignatureController.java @@ -0,0 +1,90 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgSignature; +import com.iformall.service.WxMsgSignatureService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgSignature") +public class WxMsgSignatureController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgSignatureService wxMsgSignatureService; + + @ApiOperation("分页列表接口") + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "消息签名-列表") + public ResultData list(@ModelAttribute WxMsgSignature wxMsgSignature, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::list"); + if (null == wxMsgSignature) wxMsgSignature = new WxMsgSignature(); + wxMsgSignature.setTenantId(getTenantId()); + wxMsgSignature.setSortColumns(WxMsgSignature.Field.Createtime_DESC); + final PageInfo page = wxMsgSignatureService.listAsPage(wxMsgSignature, pageNum, pageSize); + return new ResultData(page); + } + + @ApiOperation("新增接口") + @PostMapping("add") + @SystemControllerLog(description = "消息签名-新增") + public ResultData add(@RequestBody WxMsgSignature wxMsgSignature) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::add"); + //Assert.notNull(wxMsgSignature.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgSignature.setTenantId(getTenantId()); + wxMsgSignatureService.saveOrUpdate(wxMsgSignature); + return new ResultData(); + } + + @ApiOperation("根据id更新接口") + @PostMapping("update") + @SystemControllerLog(description = "消息签名-更新") + public ResultData update(@RequestBody WxMsgSignature wxMsgSignature) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::update"); + wxMsgSignatureService.saveOrUpdate(wxMsgSignature); + return new ResultData(); + } + + @ApiOperation("根据id删除接口") + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息签名-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::delete"); + wxMsgSignatureService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @ApiOperation("根据id查询接口") + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息签名-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgSignatureService.getById(id)); + } + + @ApiOperation("获取所有数据") + @GetMapping("getsignaturelist") + @SystemControllerLog(description = "消息签名-获取所有") + public ResultData getmodellist() { + logger.debug("[" + getIpAddr() + "] WxMsgSignatureController::getmodellist"); + return wxMsgSignatureService.getsignaturelist(getTenantId()); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeController.java new file mode 100644 index 000000000..4ecdcb5c7 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeController.java @@ -0,0 +1,108 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgValidationcode; +import com.iformall.service.WxMsgValidationcodeService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgValidationcode") +public class WxMsgValidationcodeController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgValidationcodeService wxMsgValidationcodeService; + + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "消息验证码-列表") + public ResultData list(@ModelAttribute WxMsgValidationcode wxMsgValidationcode, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::list"); + if (null == wxMsgValidationcode) wxMsgValidationcode = new WxMsgValidationcode(); + final PageInfo page = wxMsgValidationcodeService.listAsPage(wxMsgValidationcode, pageNum, pageSize); + return new ResultData(page); + } + + @PostMapping("add") + @SystemControllerLog(description = "消息验证码-添加") + public ResultData add(@RequestBody WxMsgValidationcode wxMsgValidationcode) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::add"); + //Assert.notNull(wxMsgValidationcode.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgValidationcodeService.saveOrUpdate(wxMsgValidationcode); + return new ResultData(); + } + + @PostMapping("update") + @SystemControllerLog(description = "消息验证码-更新") + public ResultData update(@RequestBody WxMsgValidationcode wxMsgValidationcode) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::update"); + wxMsgValidationcodeService.saveOrUpdate(wxMsgValidationcode); + return new ResultData(); + } + + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证码-删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::update"); + wxMsgValidationcodeService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "Long", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证码-查询") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgValidationcodeService.getById(id)); + } + + + @GetMapping("sendvalidationcode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "tenantId", value = "租户ID", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "type", value = "场景", dataType = "Integer", paramType = "query", required = true), + @ApiImplicitParam(name = "appid", value = "appid", dataType = "String", paramType = "query", required = true)}) + public ResultData sendvalidationcode(String tenantId, String phone, Integer type, String appid) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::sendvalidationcode"); + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.setTenantId(tenantId); + wxMsgValidationcode.setPhone(phone); + wxMsgValidationcode.setType(type); + wxMsgValidationcode.setAppid(appid); + return wxMsgValidationcodeService.sendvalidationcode(wxMsgValidationcode); + } + + @GetMapping("hasvalidationcode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "tenantId", value = "租户ID", dataType = "String", paramType = "query"), + @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "type", value = "场景", dataType = "Integer", paramType = "query", required = true), + @ApiImplicitParam(name = "code", value = "验证码", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "appid", value = "appid", dataType = "String", paramType = "query", required = true)}) + public ResultData hasvalidationcode(String tenantId, String phone, Integer type, String code, String appid) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeController::hasvalidationcode"); + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.setTenantId(tenantId); + wxMsgValidationcode.setPhone(phone); + wxMsgValidationcode.setType(type); + wxMsgValidationcode.setCode(code); + wxMsgValidationcode.setAppid(appid); + return wxMsgValidationcodeService.hasvalidationcode(wxMsgValidationcode); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeModelController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeModelController.java new file mode 100644 index 000000000..a67e4a93c --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/msg/WxMsgValidationcodeModelController.java @@ -0,0 +1,74 @@ +package com.iformall.controller.msg; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxMsgValidationcodeModel; +import com.iformall.service.WxMsgValidationcodeModelService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxMsgValidationcodeModel") +public class WxMsgValidationcodeModelController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxMsgValidationcodeModelService wxMsgValidationcodeModelService; + + @GetMapping("list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "消息验证模板-列表") + public ResultData list(@ModelAttribute WxMsgValidationcodeModel wxMsgValidationcodeModel, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::list"); + if (null == wxMsgValidationcodeModel) wxMsgValidationcodeModel = new WxMsgValidationcodeModel(); + wxMsgValidationcodeModel.setTenantId(getTenantId()); + final PageInfo page = wxMsgValidationcodeModelService.listAsPage(wxMsgValidationcodeModel, pageNum, pageSize); + return new ResultData(page); + } + + @PostMapping("add") + @SystemControllerLog(description = "消息验证模板-添加") + public ResultData add(@RequestBody WxMsgValidationcodeModel wxMsgValidationcodeModel) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::add"); + //Assert.notNull(wxMsgValidationcodeModel.getName(), "角色名不能为空"); + //Assert.isTrue(!checkUnique(sysRole.getName(), null), "重复的角色名"); + wxMsgValidationcodeModel.setTenantId(getTenantId()); + return wxMsgValidationcodeModelService.saveOrUpdate(wxMsgValidationcodeModel); + } + + @PostMapping("update") + @SystemControllerLog(description = "消息验证模板-更新") + public ResultData update(@RequestBody WxMsgValidationcodeModel wxMsgValidationcodeModel) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::update"); + wxMsgValidationcodeModelService.saveOrUpdate(wxMsgValidationcodeModel); + return new ResultData(); + } + + @GetMapping("/del") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证模板-删除") + public ResultData delete(String id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::delete"); + wxMsgValidationcodeModelService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + @GetMapping("/findById") + @ApiImplicitParam(name = "id", value = "id", dataType = "String", paramType = "query", required = true) + @SystemControllerLog(description = "消息验证模板-查询") + public ResultData findById(String id) { + logger.debug("[" + getIpAddr() + "] WxMsgValidationcodeModelController::findById"); + return new ResultData(Result.SUCCESS, "查询成功", wxMsgValidationcodeModelService.getById(id)); + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/HomeController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/HomeController.java new file mode 100644 index 000000000..47e3799e8 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/HomeController.java @@ -0,0 +1,394 @@ +package com.iformall.controller.sys; + +import com.google.code.kaptcha.Constants; +import com.google.code.kaptcha.Producer; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.domain.vo.MallUserInfoVo; +import com.iformall.enums.*; +import com.iformall.exception.MallinkException; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.service.*; +import com.iformall.shiro.UserSession; +import com.iformall.shiro.UseriFormallToken; +import com.iformall.utils.ShiroUtils; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.subject.Subject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.*; + +import javax.imageio.ImageIO; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +@RestController +@Api(description = "登录相关接口") +public class HomeController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Value("${version}") + private String version; + + @Autowired + private Producer producer; + + @Autowired + private MallUserInfoService mallUserInfoService; + + @Autowired + private MallUserRoleService mallUserRoleService; + + @Autowired + private WxAppinfoService appinfoService; + + @Autowired + private WxMsgValidationcodeService wxMsgValidationcodeService; + + @Autowired + private MallUserActionService mallUserActionService; + + @Autowired + private WxMallService mallService; + + @ApiOperation("验证码") + @GetMapping("/captcha.jpg") + public void captcha(HttpServletResponse response)throws ServletException, IOException { + logger.debug("[" + getIpAddr() + "] HomeController::captcha"); + response.setHeader("Cache-Control", "no-store, no-cache"); + response.setContentType("image/jpeg"); + + //生成文字验证码 + String text = producer.createText(); + //生成图片验证码 + BufferedImage image = producer.createImage(text); + //保存到shiro session + ShiroUtils.setSessionAttribute(Constants.KAPTCHA_SESSION_KEY, text); + + ServletOutputStream out = response.getOutputStream(); + ImageIO.write(image, "jpg", out); + IOUtils.closeQuietly(out); + } + + @ApiOperation("登录") + @PostMapping("/doLogin") + public ResultData login(@RequestBody MallUserInfo user, HttpServletResponse response) { + String ipaddress = getIpAddr(); + logger.debug("[" + ipaddress + "] HomeController::doLogin"); + try { + String kaptcha = ShiroUtils.getKaptcha(Constants.KAPTCHA_SESSION_KEY); + if(!user.getCaptcha().equalsIgnoreCase(kaptcha)){ + return new ResultData(ErrorCode.KAPCHA_NOT_EQUAL); + } + } catch (MallinkException e) { + logger.error("验证码" + e.getMessage()); + return new ResultData(ErrorCode.KAPCHA_NOT_VALID.getCode(), e.getMessage()); + } + + + ResultData data = new ResultData(); + if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) { +// throw new SystemException(ErrorCode.LOGIN_USER_OR_PWD_ERROR); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + // check user + MallUserInfo userCheck = mallUserInfoService.getByUsername(user.getUsername()); + if(userCheck == null) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if(userCheck.getStatus().equals(EnumMallUserStatus.NOT_VALID.getCode())) { + logger.error(ErrorCode.USER_IS_LOCKED.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword()); + subject.login(token); + isLogin = true; + } catch (UnknownAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } catch (DisabledAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + + if(isLogin) { + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + mallUserActionService.saveActionInfo(info.getTenantId(), EnumMallUserAction.CONTROLLER.getCode(), ipaddress, info.getId(), "用户登录"); + + WxMall mall = mallService.getByTenantId(info.getTenantId()); + if(mall == null) { + logger.error("未配置相应的mall"); + return new ResultData(Result.ERROR, "未配置相应的mall"); + } + if(!mall.isValid()) { + logger.error("mall未启用"); + return new ResultData(Result.ERROR, "mall未启用"); + } + + try { + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + Map map = new HashMap(); + map.put("username", info.getUsername()); + map.put("withWechat", info.getWithWechat()); + data.data = map; + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(Result.ERROR, e.getMessage()); + } + } + return data; + } + + private boolean isInMobileAdmin(MallUserInfo user) { + // 检查用户是否有 移动端数据塔台 权限 + boolean isInMobile = false; + isInMobile = mallUserRoleService.checkIsMobileAdmin(user); + return isInMobile; + } + + @ApiOperation("B端登录") + @PostMapping("/bHidLogin") + public ResultData bLogin(@RequestBody MallUserInfo user, HttpServletResponse response) { + String ipaddress = getIpAddr(); + logger.debug("[" + ipaddress + "] HomeController::bHidLogin"); + ResultData data = new ResultData(); + // tenantId is appId + if (StringUtils.isBlank(user.getTenantId())) { + logger.error("appid信息未提供"); + return new ResultData(ErrorCode.MALL_INFO_NOT_FOUND); + } + WxAppinfo appinfo = appinfoService.getByAppId(user.getTenantId()); + if (appinfo == null) { + logger.error("appid未找到"); + return new ResultData(ErrorCode.MALL_INFO_NOT_FOUND); + } + if (StringUtils.isNotBlank(user.getPhone())) { + // 领导登录 + user = mallUserInfoService.getByPhone(user.getPhone(), appinfo.getTenantId()); + if (user == null || !isInMobileAdmin(user)) { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + } else if (StringUtils.isNotBlank(user.getBopenId())) { + // 领导登录 + user = mallUserInfoService.getByBOpenId(user.getBopenId(), appinfo.getTenantId()); + if (user == null || !isInMobileAdmin(user)) { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + } else { + if (StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword())) { +// throw new SystemException(ErrorCode.LOGIN_USER_OR_PWD_ERROR); + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + } + + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(user.getUsername()); + subject.login(token); + isLogin = true; + } catch (UnknownAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } catch (DisabledAccountException e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } catch (Exception e) { + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + + if (isLogin) { + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + + mallUserActionService.saveActionInfo(info.getTenantId(), EnumMallUserAction.CONTROLLER.getCode(), ipaddress, info.getId(), "用户登录"); + + WxMall mall = mallService.getByTenantId(info.getTenantId()); + if (mall == null) { + logger.error("未配置相应的mall"); + return new ResultData(Result.ERROR, "未配置相应的mall"); + } + if (!mall.isValid()) { + logger.error("mall未启用"); + return new ResultData(Result.ERROR, "mall未启用"); + } + try { + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + Map map = new HashMap(); + map.put("username", info.getUsername()); + map.put("withWechat", info.getWithWechat()); + data.data = map; + + } catch(Exception e){ + logger.error(e.getMessage()); + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + } + return data; + } + + @ApiOperation("发送手机验证码") + @GetMapping("sendLoginPhoneCode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "query", required = true)}) + public ResultData sendLoginPhoneCode(String phone) { + logger.debug("[" + getIpAddr() + "] HomeController::sendlogincode"); + // 1. 检查手机号是否在用户列表里, 是否只有一个 + // 2. 发送手机验证码, 直接发 + List users = mallUserInfoService.getUserByPhone(phone); + if(users.size() <= 0) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if(users.size() > 1) { + logger.error(ErrorCode.USER_IS_MULTI.getMessage()); + return new ResultData(ErrorCode.USER_IS_MULTI); + } + MallUserInfoVo user = users.get(0); + if (user==null) { + logger.error("用户不存在, userName: " + user.getUsername()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + if(user.getStatus() == EnumMallUserStatus.NOT_VALID.getCode()){ + logger.error("用户已停用, userName: " + user.getUsername()); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.setPhone(phone); + wxMsgValidationcode.setTenantId(user.getTenantId()); + wxMsgValidationcode.setType(EnumMsgModel.VALIDATION_CODE.getCode()); + return wxMsgValidationcodeService.sendvalidationcode(wxMsgValidationcode); + } + + @ApiOperation(value = "手机验证码登录", notes = "{\"phone\",\"string\",\"code\",\"string\"}") + @PostMapping("/doLoginByPhone") + public ResultData doLoginByPhone(@RequestBody Map params, HttpServletResponse response) { + String ipaddress = getIpAddr(); + logger.debug("[" + ipaddress + "] HomeController::doLoginByPhone"); + // String phone,String code,String pwd + String phone = params.get("phone"); + String code = params.get("code"); + + if (StringUtils.isBlank(phone)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "userName不能为空"); + } + if (StringUtils.isBlank(code)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "验证码不能为空"); + } + + // 获取用户信息列表 + List userList = mallUserInfoService.getUserByPhone(phone); + if(userList.size() == 1) { + MallUserInfoVo user = userList.get(0); + // check 验证码正确 + boolean isValidCode = false; + try { + isValidCode = mallUserInfoService.checkCodeValid(user, code); + } catch (Exception e) { + return new ResultData(Result.ERROR, e.getMessage()); + } + if(isValidCode) { + // 验证码正确,直接登录 + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(user.getUsername()); + subject.login(token); + + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + mallUserActionService.saveActionInfo(info.getTenantId(), EnumMallUserAction.CONTROLLER.getCode(), ipaddress, info.getId(), "用户手机号登录"); + + WxMall mall = mallService.getByTenantId(info.getTenantId()); + if (mall == null) { + logger.error("未配置相应的mall"); + return new ResultData(Result.ERROR, "未配置相应的mall"); + } + if (!mall.isValid()) { + logger.error("mall未启用"); + return new ResultData(Result.ERROR, "mall未启用"); + } + + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + Map map = new HashMap(); + map.put("username", info.getUsername()); + map.put("withWechat", info.getWithWechat()); + + return new ResultData(map); + } catch (MallinkException e) { + return new ResultData(e.getErrorCode(), e.getMessage()); + } catch (Exception e) { + return new ResultData(ErrorCode.USER_PASSWD_ERR); + } + } else { + return new ResultData(ErrorCode.MSG_VERIFY_CODE_NOT_FOUND); + } + } else { + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + } + + @ApiOperation("登出") + @GetMapping("/logout") + @SystemControllerLog(description = "用户登出") + public ResultData logout() { + logger.debug("[" + getIpAddr() + "] HomeController::logout"); + ResultData data = new ResultData(); + SecurityUtils.getSubject().logout(); + return data; + } + + @ApiOperation("获取后端版本号") + @GetMapping("/version") + public ResultData version() { + logger.debug("[" + getIpAddr() + "] HomeController::version"); + return new ResultData(version); + } +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/MallRoleController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/MallRoleController.java new file mode 100644 index 000000000..3a432cc4e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/MallRoleController.java @@ -0,0 +1,169 @@ +package com.iformall.controller.sys; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallRole; +import com.iformall.domain.po.MallRolePermission; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.po.MallUserRole; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.MallRolePermissionService; +import com.iformall.service.MallRoleService; +import com.iformall.service.MallUserRoleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; + + +@RestController +@RequestMapping("role") +@Api(description = "角色相关接口") +public class MallRoleController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private MallRoleService sysRoleService; + + @Autowired + private MallRolePermissionService sysRolePermissionService; + + @Autowired + private MallUserRoleService mallUserRoleService; + + @ApiOperation("角色列表") + @GetMapping("list") + //@RequiresPermissions("sys:role:list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "用户管理-rule列表") + public ResultData list(MallRole sysRole, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] MallRoleController::list"); + String tenantId = getTenantId(); + sysRole.setTenantId(tenantId); + final PageInfo page = sysRoleService.listAsPage(sysRole, pageNum, pageSize); + for (MallRole r : page.getList()) { + MallRolePermission p = new MallRolePermission(); + p.setRoleId(r.getId()); + p.setTenantId(tenantId); + PageInfo pers = sysRolePermissionService.listAsPage(p, 1, 1000); + String menus = ""; + for (MallRolePermission rp : pers.getList()) { + menus += rp.getPermissionId() + ","; + } + if (menus.length() > 1) { + menus = menus.substring(0, menus.length() - 1); + } + r.setMenus(menus); + } + return new ResultData(page); + } + + + @ApiOperation("角色保存") + @PostMapping("saveOrUpdate") + //@RequiresPermissions("sys:role:save") + @SystemControllerLog(description = "用户管理-rule保存") + public ResultData saveOrUpdate(@RequestBody MallRole sysRole) { + logger.debug("[" + getIpAddr() + "] MallRoleController::saveOrUpdate"); + MallUserInfo currentUser = getUser(); + if(currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有超级管理员才能保存角色"); + } + String tenantId = currentUser.getTenantId(); + int count = checkUnique(sysRole.getName(), tenantId); + if (sysRole.getId() == null && count > 0) { + return new ResultData(ResultData.ERROR, "角色名已存在"); + } + sysRole.setTenantId(tenantId); + sysRoleService.saveOrUpdate(sysRole); +// SysRolePermissionService.deleteById(id); + if (StringUtils.isNoneBlank(sysRole.getMenus())) { + List mIds = new ArrayList<>(); + for (String mId : sysRole.getMenus().split(",")) { + mIds.add(Long.valueOf(mId)); + } + sysRolePermissionService.savePermissions(tenantId, sysRole.getId(), mIds.toArray(new Long[]{})); + } + return new ResultData(); + } + + @ApiOperation("角色增加") + @PostMapping("add") + //@RequiresPermissions("sys:role:add") + @SystemControllerLog(description = "用户管理-rule添加") + public ResultData add(MallRole sysRole) { + logger.debug("[" + getIpAddr() + "] MallRoleController::add"); + MallUserInfo currentUser = getUser(); + if(currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有超级管理员才能添加角色"); + } + Assert.notNull(sysRole.getName(), "角色名不能为空"); + Assert.isTrue(checkUnique(sysRole.getName(), currentUser.getTenantId())>0, "重复的角色名"); + sysRoleService.saveOrUpdate(sysRole); + return new ResultData(); + } + + @ApiOperation("角色更新") + @PostMapping("update") + //@RequiresPermissions("sys:role:update") + @SystemControllerLog(description = "用户管理-rule更新") + public ResultData update(MallRole sysRole) { + logger.debug("[" + getIpAddr() + "] MallRoleController::update"); + MallUserInfo currentUser = getUser(); + if(currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有超级管理员才能更新角色"); + } + if (sysRole.getName() != null) { + Assert.isTrue(checkUnique(sysRole.getName(), currentUser.getTenantId())>1, "角色名已存在"); + } + sysRoleService.saveOrUpdate(sysRole); +// Assert.notNull(sysRole.getName(), "角色名不能为空"); + return new ResultData(); + } + + @ApiOperation("角色删除") + @PostMapping("/del") + //@RequiresPermissions("sys:role:del") + @SystemControllerLog(description = "用户管理-rule删除") + public ResultData delete(@RequestBody MallRole sysRole) { + logger.debug("[" + getIpAddr() + "] MallRoleController::delete"); + MallUserInfo currentUser = getUser(); + if(currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有超级管理员才能删除角色"); + } + MallUserRole record = new MallUserRole(); + record.setRoleId(sysRole.getId()); + int count = mallUserRoleService.cntUserList(record); + if (count > 0) { + return new ResultData(ErrorCode.USER_USE_ROLE.getCode(), "有用户使用此角色,请先删除相应的用户!!"); + } + sysRoleService.deleteById(sysRole.getId()); + sysRolePermissionService.deleteByRoleId(sysRole.getId()); + return new ResultData(Result.SUCCESS, "删除成功", null); + } + + private int checkUnique(String name, String tenantId) { + MallRole role = new MallRole(); + role.setName(name); + role.setTenantId(tenantId); + return sysRoleService.countList(role); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/MallUserInfoController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/MallUserInfoController.java new file mode 100644 index 000000000..b67fa5f53 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/MallUserInfoController.java @@ -0,0 +1,407 @@ +package com.iformall.controller.sys; + +import com.github.pagehelper.PageInfo; +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.*; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.enums.EnumFlowPermissionType; +import com.iformall.service.*; +import com.iformall.shiro.PasswordHelper; +import com.iformall.shiro.UserSession; +import com.iformall.utils.Constant; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.collections.map.HashedMap; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.Assert; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author chenkx + * @date 2018-01-05. + */ +@Api(value = "API - UserInfoController", description = "用户接口") +@RestController +@RequestMapping("user") +public class MallUserInfoController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + MallUserInfoService userInfoService; + + @Autowired + MallUserRoleService userRoleService; + + @Autowired + MallRoleService mallRoleService; + + @Autowired + MallUserRoleService mallUserRoleService; + + @Autowired + MallPermissionService mallPermissionService; + + @Autowired + MallRolePermissionService mallRolePermissionService; + + @Autowired + WxMsgValidationcodeService wxMsgValidationcodeService; + + @ApiOperation(value = "用户分页接口", response = String.class) + @GetMapping("lists") + //@RequiresPermissions("sys:user:list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "pageNum", value = "页数", dataType = "int", paramType = "query", required = true), + @ApiImplicitParam(name = "pageSize", value = "每页条数", dataType = "int", paramType = "query", required = true)}) + @SystemControllerLog(description = "用户管理-列表") + public ResultData listAsPage(MallUserInfo userInfo, Integer pageNum, Integer pageSize) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::listAsPage"); + userInfo.setTenantId(getTenantId()); + userInfo.setSortColumns(MallUserInfo.Field.Id_DESC); + final PageInfo page = userInfoService.listAsPage(userInfo, pageNum, pageSize); + for (MallUserInfo u : page.getList()) { + MallUserRole r = new MallUserRole(); + r.setUid(u.getId()); + PageInfo ur = userRoleService.listAsPage(r, 1, 1); + if (ur.getSize() > 0) { + MallRole role = mallRoleService.getById(ur.getList().get(0).getRoleId()); + if (role != null) { + u.setRoleName(role.getName()); + u.setRoleId(role.getId()); + } + } + // 保密 + u.setPassword(null); + u.setBopenId(null); + if(StringUtils.isNotBlank(u.getWebOpenId())) { + u.setWebOpenId("保密"); + } + } + return new ResultData(page); + } + + @ApiOperation(value = "用户详情接口", response = String.class) + @GetMapping("detail") + //@RequiresPermissions("sys:user:info") + @SystemControllerLog(description = "用户管理-用户详情") + public ResultData detail(Long id) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::detail"); + final MallUserInfo user = userInfoService.getById(id); + user.setPassword(null); + user.setBopenId(null); + if(StringUtils.isNotBlank(user.getWebOpenId())) { + user.setWebOpenId("保密"); + } + + return new ResultData(user); + } + + @ApiOperation(value = "创建用户接口", response = String.class) + @PostMapping("add") + //@RequiresPermissions("sys:user:add") + @SystemControllerLog(description = "用户管理-创建用户") + public ResultData createUser(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::createUser"); + MallUserInfo currentUser = getUser(); + if(currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有超级管理员才能添加用户"); + } + + if(checkUniqueName(userInfo.getUsername()) > 0){ + return new ResultData(ErrorCode.USER_NAME_IS_FOUND.getCode(),"用户名已存在"); + } + if(checkUniquePhone(userInfo.getPhone()) > 0){ + return new ResultData(ErrorCode.USER_PHONE_IS_FOUND.getCode(),"手机号已存在"); + } + Assert.notNull(userInfo.getPassword(), "密码不能为空"); + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(userInfo); + userInfo.setTenantId(getTenantId()); + // 无法创建超管 + userInfo.setIsAdmin(EnumUserAdmin.Normal.getCode()); + userInfoService.saveOrUpdate(userInfo); + if (userInfo.getRoleId() != null) { + MallUserRole r = new MallUserRole(); + r.setRoleId(userInfo.getRoleId()); + r.setUid(userInfo.getId()); + userRoleService.saveOrUpdate(r); + } + return new ResultData(userInfo); + } + + @ApiOperation(value = "修改用户接口", response = String.class) + @PostMapping("update") + //@RequiresPermissions("sys:user:update") + @SystemControllerLog(description = "用户管理-修改用户") + public ResultData updateUser(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::updateUser"); + boolean bChangedPhone = false; + MallUserInfo currentUser = getUser(); + // 只有超管和自己能更新信息 + if (!(currentUser.getId().equals(userInfo.getId()) || + currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode()))) { + return new ResultData(ErrorCode.USER_NO_PERMISSION.getCode(), "超级管理员和自己才能修改信息"); + } + MallUserInfo oldUser = userInfoService.getById(userInfo.getId()); + if (!oldUser.getUsername().equals(userInfo.getUsername())) { + if(checkUniqueName(userInfo.getUsername()) > 0){ + return new ResultData(ErrorCode.USER_NAME_IS_FOUND.getCode(),"用户名已存在"); + } + } + if (!oldUser.getPhone().equals(userInfo.getPhone())) { + if(checkUniquePhone(userInfo.getPhone()) > 0){ + return new ResultData(ErrorCode.USER_PHONE_IS_FOUND.getCode(),"手机号已存在"); + } + bChangedPhone = true; + } + + userInfo.setTenantId(getTenantId()); + if (StringUtils.isNotBlank(userInfo.getPassword()) && userInfo.getPassword().length() > 0) { + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(userInfo); + } + // 系统内人员不能设置超级管理员 + userInfo.setIsAdmin(null); + /* + if (!currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + // 只有超级管理员才能设置超级管理员 + userInfo.setIsAdmin(null); + } + */ + + if (currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode()) && + currentUser.getId().equals(userInfo.getId())) { + // 超管 + MallUserInfo adminUser = new MallUserInfo(); + adminUser.setFlowPermission(userInfo.getFlowPermission()); + adminUser.setEmail(userInfo.getEmail()); + adminUser.setId(userInfo.getId()); + if (StringUtils.isNotBlank(userInfo.getPassword()) && userInfo.getPassword().length() > 0) { + adminUser.setPassword(userInfo.getPassword()); + } + if (StringUtils.isNotBlank(userInfo.getNickName())) { + adminUser.setNickName(userInfo.getNickName()); + } + if (StringUtils.isNotBlank(userInfo.getPhone())) { + adminUser.setPhone(userInfo.getPhone()); + } + userInfoService.saveOrUpdate(adminUser); + } else { + userInfoService.saveOrUpdate(userInfo); + if (userInfo.getRoleId() != null) { + userRoleService.deleteByUserId(userInfo.getId()); + MallUserRole r = new MallUserRole(); + r.setRoleId(userInfo.getRoleId()); + r.setUid(userInfo.getId()); + userRoleService.saveOrUpdate(r); + } + } + if(bChangedPhone) { + // 手机号修改,清除bopen_id, 清除web_open_id + userInfoService.cleanAllOpenId(userInfo); + } + + return new ResultData(); + } + + @ApiOperation(value = "删除用户接口", response = String.class) + @PostMapping("/del") + //@RequiresPermissions("sys:user:del") + @SystemControllerLog(description = "用户管理-删除用户") + public ResultData deleteUser(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::deleteUser"); + MallUserInfo currentUser = getUser(); + if (currentUser.getIsAdmin().equals(EnumUserAdmin.Normal.getCode())) { + return new ResultData(ErrorCode.USER_NOT_ADMIN.getCode(), "只有超级管理员才能删除用户"); + } + if (currentUser.getId().equals(userInfo.getId())) { + return new ResultData(ErrorCode.USER_NO_PERMISSION.getCode(), "用户不能删除自己"); + } + userInfoService.deleteById(userInfo.getId()); + userRoleService.deleteByUserId(userInfo.getId()); + return new ResultData(); + } + + @ApiOperation(value = "起停用户接口") + @PostMapping("updateStatus") + //@RequiresPermissions("sys:user:update") + @SystemControllerLog(description = "用户管理-起停用户") + public ResultData modifyStatus(@RequestBody MallUserInfo userInfo) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::modifyStatus"); + MallUserInfo currentUser = getUser(); + if (currentUser.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + MallUserInfo userInfo1 = userInfoService.getById(userInfo.getId()); + if(userInfo1 == null) { + logger.error(ErrorCode.USER_IS_EMPTY.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + MallUserInfo updateUserInfo = new MallUserInfo(); + updateUserInfo.setId(userInfo.getId()); + updateUserInfo.setTenantId(getTenantId()); + updateUserInfo.setStatus(userInfo.getStatus()); + userInfoService.saveOrUpdate(userInfo); + return new ResultData(); + } else { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + } + + private int checkUniqueName(String userName) { + return userInfoService.cntByUserName(userName); + } + + private int checkUniquePhone(String phone) { + return userInfoService.cntByUserPhone(phone); + } + + + @ApiOperation(value = "用户权限检查") + @GetMapping("hasButtonPermission") + @SystemControllerLog(description = "用户管理-用户权限检查") + public ResultData hasButtonPermission(String permissions) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::hasButtonPermission"); + MallUserInfo info = getUser(); + info.setPassword("保密"); + Map map = new HashMap<>(); + for (String name : permissions.split(",")) { + Long userId = (Long)SecurityUtils.getSubject().getSession().getAttribute(UserSession.userId); + boolean has = userInfoService.hasButtonPermission(userId, name); + map.put(name, has); + } + return new ResultData(map); + } + + @ApiOperation(value = "用户权限检查") + @GetMapping("getUser") + //@RequiresPermissions("sys:user:info") + @SystemControllerLog(description = "用户管理-用户信息") + public ResultData getUserInfo() { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::getUserInfo"); + MallUserInfo info = getUser(); + info.protectInfos(); + + // TODO 请用 /menu/nav 获取菜单及权限 + List menuList = mallPermissionService.queryAdminMenuList(info); + StringBuilder sb = new StringBuilder(); + boolean bFirst = true; + for(Long id: menuList) { + if(bFirst) { + sb.append(id); + bFirst = false; + } else { + sb.append(',').append(id); + } + } + info.setMenus(sb.toString()); + return new ResultData(info); + } + + @ApiOperation(value = "用户密码发送验证码") + @GetMapping("sendvalidationcode") + @ApiImplicitParams({ + @ApiImplicitParam(name = "userName", value = "手机号", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "type", value = "场景(1:登录)", dataType = "Integer", paramType = "query", required = true)}) + public ResultData sendvalidationcode(String userName, Integer type) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::sendvalidationcode"); + MallUserInfo userQ = new MallUserInfo(); + userQ.setUsername(userName); + + MallUserInfo user = userInfoService.getByUsername(userName); + if (user==null) { + logger.error("用户不存在, userName: " + userName); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + + if(user.getStatus() == EnumMallUserStatus.NOT_VALID.getCode()){ + logger.error("用户已停用, userName: " + userName); + return new ResultData(ErrorCode.USER_IS_LOCKED); + } + + if (StringUtils.isBlank(user.getPhone())) { + logger.error("用户手机号为空, userName: " + userName); + return new ResultData(ErrorCode.USER_PHONE_IS_NOT_FOUND); + } + + WxMsgValidationcode wxMsgValidationcode = new WxMsgValidationcode(); + wxMsgValidationcode.setTenantId(user.getTenantId()); + wxMsgValidationcode.setPhone(user.getPhone()); + wxMsgValidationcode.setType(type); + return wxMsgValidationcodeService.sendvalidationcode(wxMsgValidationcode); + } + + @ApiOperation(value = "修改密码", notes = "{\"userName\",\"string\",\"code\",\"string\",\"pwd\",\"string\"}") + @PostMapping("/updatepwd") + public ResultData updatepwd(@RequestBody Map params) { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::updatepwd"); + // String phone,String code,String pwd + String userName = params.get("userName"); + String code = params.get("code"); + String pwd = params.get("pwd"); + + if (StringUtils.isBlank(userName)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "userName不能为空"); + } + if (StringUtils.isBlank(code)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "验证码不能为空"); + } + if (StringUtils.isBlank(pwd)) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL.getCode(), "密码不能为空"); + } + + MallUserInfo userQ = new MallUserInfo(); + userQ.setUsername(userName); + MallUserInfo user = userInfoService.getByUsername(userName); + if (user==null) { + logger.error("用户不存在, userName: " + userName); + return new ResultData(ErrorCode.USER_IS_EMPTY); + } + + user.setPassword(pwd); + + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(user); + + + try { + return userInfoService.updatepwd(user, code); + } catch (Exception e) { + return new ResultData(Result.ERROR, e.getMessage()); + } + } + + @ApiOperation(value = "审批权限用户列表", response = String.class) + @GetMapping("getFlowPermissionList") + //@RequiresPermissions("sys:user:flowlist") + @SystemControllerLog(description = "用户管理-审批权限用户列表") + public ResultData getFlowPermissionList() { + logger.debug("[" + getIpAddr() + "] MallUserInfoController::getFlowPermissionList"); + MallUserInfo mallUserInfo = new MallUserInfo(); + mallUserInfo.setFlowPermission(EnumFlowPermissionType.CONTRACT.getCode()+""); + List contractUserList = userInfoService.findList(mallUserInfo); + + mallUserInfo.setFlowPermission(EnumFlowPermissionType.BILL.getCode()+""); + List billUserList = userInfoService.findList(mallUserInfo); + Map resultMap = new HashedMap(); + resultMap.put("contractUserList",contractUserList); + resultMap.put("billUserList",billUserList); + return new ResultData(resultMap); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/SysMenuController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/SysMenuController.java new file mode 100644 index 000000000..b5c7dfbbe --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/SysMenuController.java @@ -0,0 +1,269 @@ +package com.iformall.controller.sys; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallPermission; +import com.iformall.domain.po.MallRole; +import com.iformall.domain.po.MallRolePermission; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.enums.EnumMenuType; +import com.iformall.enums.EnumPermissionType; +import com.iformall.exception.MallinkException; +import com.iformall.service.MallPermissionService; +import com.iformall.service.MallRolePermissionService; +import com.iformall.service.MallRoleService; +import com.iformall.service.MallUserInfoService; +import com.iformall.utils.Constant; +import io.swagger.annotations.ApiOperation; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.apache.shiro.util.Assert; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author Stormeye Wu + * @date 2019-04-20. + */ +@RestController +@RequestMapping("menu") +public class SysMenuController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private MallPermissionService mallPermissionService; + + @Autowired + private MallUserInfoService mallUserInfoService; + + @Autowired + private MallRoleService mallRoleService; + + @Autowired + private MallRolePermissionService mallRolePermissionService; + + @ApiOperation("导航菜单") + @GetMapping("/nav") + public ResultData nav(){ + logger.debug("[" + getIpAddr() + "] MallPermissionController::nav"); + MallUserInfo user = getUser(); + List menuList = mallPermissionService.getUserMenuList(user); + Set permissions = mallUserInfoService.getUserPermissions(user); + Map map = new HashMap<>(); + map.put("menuList", menuList); + map.put("permissions", permissions); + return new ResultData(map); + } + + @ApiOperation("所有菜单列表") + @GetMapping("list") + //@RequiresPermissions("sys:menu:list") + @SystemControllerLog(description = "用户管理-权限") + public ResultData getList() { + logger.debug("[" + getIpAddr() + "] MallPermissionController::list"); + MallUserInfo user = getUser(); + List menuList = mallUserInfoService.getAllPermissions(user); + return new ResultData(Result.SUCCESS, "查询成功", menuList); + } + + @ApiOperation("添加菜单/权限") + @PostMapping("add") + //@RequiresPermissions("sys:menu:save") + @SystemControllerLog(description = "用户管理-权限添加") + public ResultData createPermission(MallPermission mallPermission) { + logger.debug("[" + getIpAddr() + "] MallPermissionController::createPermission"); + Assert.notNull(mallPermission.getName(), "用户名不能为空"); + // 数据校验 + verifyForm(mallPermission); + + mallPermissionService.saveOrUpdate(mallPermission); + return new ResultData(mallPermission.getId()); + } + + @ApiOperation("更新菜单/权限") + @PostMapping("update") + //@RequiresPermissions("sys:menu:update") + @SystemControllerLog(description = "用户管理-权限更新") + public ResultData updatePermission(MallPermission sysPermission) { + logger.debug("[" + getIpAddr() + "] MallPermissionController::updatePermission"); + // 数据校验 + verifyForm(sysPermission); + + mallPermissionService.saveOrUpdate(sysPermission); + return new ResultData(); + } + + @ApiOperation("删除菜单/权限") + @GetMapping("/del") + //@RequiresPermissions("sys:menu:delete") + @SystemControllerLog(description = "用户管理-权限删除") + public ResultData delete(Long id) { + logger.debug("[" + getIpAddr() + "] MallPermissionController::delete"); + if(id <= Constant.SYS_MENU_MAX) { + logger.error(ErrorCode.MENU_SYS_NOT_DEL.getMessage()); + return new ResultData(ErrorCode.MENU_SYS_NOT_DEL); + } + //判断是否有子菜单或按钮 + List menuList = mallPermissionService.getByParentId(id); + if(menuList.size() > 0){ + logger.error(ErrorCode.MENU_CHILD_NOT_DEL.getMessage()); + return new ResultData(ErrorCode.MENU_CHILD_NOT_DEL); + } + mallPermissionService.deleteById(id); + return new ResultData(Result.SUCCESS, "删除成功"); + } + + @ApiOperation("菜单信息") + @GetMapping("/findById") + //@RequiresPermissions("sys:menu:info") + @SystemControllerLog(description = "用户管理-权限查找") + public ResultData findById(Long id) { + logger.debug("[" + getIpAddr() + "] MallPermissionController::findById"); + return new ResultData(Result.SUCCESS, "成功", mallPermissionService.getById(id)); + } + + @ApiOperation("用户菜单权限升级") + @GetMapping("/upgradeMenus") + //@RequiresPermissions("sys:menu:info") + @SystemControllerLog(description = "用户管理-权限升级") + public ResultData upgradeMenus() { + logger.debug("[" + getIpAddr() + "] MallPermissionController::upgradeMenus"); + MallUserInfo userInfo = getUser(); + if(userInfo.isFmSuperAdmin()) { + // 已有Role + MallRole q = new MallRole(); + List mallRoleList = mallRoleService.getList(q); + for(MallRole mallRole: mallRoleList) { + MallRolePermission qRP = new MallRolePermission(); + qRP.setRoleId(mallRole.getId()); + List mallRolePermissionList = mallRolePermissionService.getList(qRP); + boolean isOld = mallRolePermissionList.stream().allMatch( + (rolePermission-> + (rolePermission.getPermissionId().longValue() <= (long)EnumMenuType.HARDWARE.getCode()) + ) + ); + if(isOld){ + // 添加子权限给此role + for(MallRolePermission mRP: mallRolePermissionList) { + List pList = new ArrayList<>(); + // 二级菜单 + List subList1 = mallPermissionService.getByParentId(mRP.getPermissionId()); + for(MallPermission mp: subList1) { + pList.add(mp.getId()); + // 三级菜单 + List subList2 = mallPermissionService.getByParentId(mRP.getPermissionId()); + if(subList2.size() > 0) { + subList2.stream().forEach(smp->{ + pList.add(smp.getId()); + }); + } + } + List dpList = pList.stream().distinct().collect(Collectors.toList()); + Long[] idArray = new Long[dpList.size()]; + dpList.toArray(idArray); + mallRolePermissionService.savePermissions(mRP.getTenantId(), mRP.getRoleId(), idArray); + } + } + } + return new ResultData(); + } + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + + @Autowired + private RequestMappingHandlerMapping requestMappingHandlerMapping; + + @ApiOperation("导出菜单") + @GetMapping("/export") + //@RequiresPermissions("sys:menu:import") + @SystemControllerLog(description = "用户管理-导出权限") + public ResultData export() { + logger.debug("[" + getIpAddr() + "] MallPermissionController::export"); + List resourceList = new ArrayList(); + //获取所有Controller的方法 + Map map = requestMappingHandlerMapping.getHandlerMethods(); + for (Map.Entry m : map.entrySet()) { + RequestMappingInfo info = m.getKey(); + HandlerMethod method = m.getValue(); + PatternsRequestCondition p = info.getPatternsCondition(); + //扫描Shiro的权限资源标签 + RequiresPermissions requiresPermissions = method.getMethod().getAnnotation(RequiresPermissions.class); + if (requiresPermissions != null) { + Map newSource = new HashMap(); + String[] strArr = requiresPermissions.value(); + newSource.put("permission", strArr[0]); + //扫描Swagger注解 + ApiOperation apiOperation = method.getMethod().getAnnotation(ApiOperation.class); + if (apiOperation != null) { + newSource.put("name", apiOperation.value()); + Set urls = p.getPatterns(); + newSource.put("url", urls.toArray()[0]); + } + resourceList.add(newSource); + } + } + + return new ResultData(resourceList); + } + + /** + * 验证参数是否正确 + */ + private void verifyForm(MallPermission menu){ + if(StringUtils.isBlank(menu.getName())){ + throw new MallinkException(ErrorCode.MENU_NAME_EMPTY); + } + + if(menu.getParentId() == null){ + throw new MallinkException(ErrorCode.MENU_PARENT_EMPTY); + } + + //菜单 + if(menu.getResourceType().equals(EnumPermissionType.MENU.getCode())){ + if(StringUtils.isBlank(menu.getUrl())){ + throw new MallinkException(ErrorCode.MENU_URL_EMPTY); + } + } + + //上级菜单类型 + int parentType = EnumPermissionType.CATALOG.getCode(); + if(menu.getParentId() != 0){ + MallPermission parentMenu = mallPermissionService.getById(menu.getParentId()); + parentType = parentMenu.getResourceType(); + } + + //目录、菜单 + if(menu.getResourceType().equals(EnumPermissionType.CATALOG.getCode()) || + menu.getResourceType().equals(EnumPermissionType.MENU.getCode())){ + if(parentType != EnumPermissionType.CATALOG.getCode()){ + throw new MallinkException(ErrorCode.MENU_PARENT_NOT_CATEGORY); + } + return ; + } + + //按钮 + if(menu.getResourceType().equals(EnumPermissionType.BUTTON.getCode())){ + if(parentType != EnumPermissionType.MENU.getCode()){ + throw new MallinkException(ErrorCode.MENU_PARENT_NOT_MENU); + } + return ; + } + } + + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/UploadController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/UploadController.java new file mode 100644 index 000000000..9d493d174 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/UploadController.java @@ -0,0 +1,212 @@ +package com.iformall.controller.sys; + + +import com.amazonaws.AmazonClientException; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.iformall.common.ResultData; +import com.iformall.config.AwsProperty; +import com.iformall.controller.base.BaseController; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.BufferedInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.*; + +@RestController +@RequestMapping(value = "upload") +@Api(description = "文件上传接口") +public class UploadController extends BaseController { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private AwsProperty awsProperty; + + private AmazonS3 s3 = null; + + private ResultData awsUpload(MultipartFile multiReq, ObjectMetadata metadata, String fileName) { + ResultData data = new ResultData(); + try { + if(s3 == null) { + s3 = AmazonS3ClientBuilder.standard() + .withRegion(awsProperty.getClientRegion()) + .withCredentials(new AWSCredentialsProvider() { + @Override + public AWSCredentials getCredentials() { + return new BasicAWSCredentials(awsProperty.getAccess(), awsProperty.getSecret()); + } + + @Override + public void refresh() { + + } + }) + .build(); + } + + s3.putObject( + new PutObjectRequest(awsProperty.getBucketName(), fileName, multiReq.getInputStream(), metadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + URL url = s3.getUrl(awsProperty.getBucketName(), fileName); + logger.info(url.toString()); + + data.code = ResultData.SUCCESS; + Map map = new HashMap<>(); + map.put("url", url.toString()); + data.data = map; + } catch (AmazonServiceException ase) { + data.code = ResultData.ERROR; + logger.warn("Caught an AmazonServiceException, which " + + "means your request made it " + + "to Amazon S3, but was rejected with an error response" + + " for some reason."); + logger.warn(ase.getMessage()); + data.code = ResultData.ERROR; + data.message = "上传失败"; + } catch (AmazonClientException ace) { + data.code = ResultData.ERROR; + logger.warn("Caught an AmazonClientException, which " + + "means the client encountered " + + "an internal error while trying to " + + "communicate with S3, " + + "such as not being able to access the network."); + logger.warn("Error Message: " + ace.getMessage()); + data.code = ResultData.ERROR; + data.message = "上传失败"; + } catch (IOException ioe) { + data.code = ResultData.ERROR; + logger.warn("Caught an IOException: " + ioe.getMessage()); + data.code = ResultData.ERROR; + data.message = "上传失败"; + } + return data; + } + + /** + * 上传文件 + * + * @param multiReq + * @return + * @throws Exception + */ + @PostMapping(value = "/awsFileUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("上传文件") + public ResultData awsfileUpload(@RequestParam("file") MultipartFile multiReq) { + logger.info("[" + getIpAddr() + "] UploadController::awsfileUpload"); + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(multiReq.getContentType()); + metadata.setContentLength(multiReq.getSize()); + + FileOutputStream fos = null; + BufferedInputStream fs = null; + + String fileName = UUID.randomUUID().toString(); + int dot = multiReq.getOriginalFilename().lastIndexOf('.'); + if (dot >= 0) { + fileName = getTenantId() + "/" + fileName + multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length()); + } else { + fileName = getTenantId() + "/" + fileName; + } + + ResultData data = awsUpload(multiReq, metadata, fileName); + return data; + } + + /** + * 多文件上传 + * + * @param files + * @return + * @throws Exception + */ + @PostMapping(value = "/awsFilesUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("多文件上传") + public ResultData awsFilesUpload(@RequestParam("files") MultipartFile[] files) { + logger.info("[" + getIpAddr() + "] UploadController::awsFilesUpload"); + + if(files.length > 0){ + ResultData data = new ResultData(); + List> dataList = new ArrayList>(); + for(MultipartFile multipartFile: files) { + Map map = new HashMap<>(); + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(multipartFile.getContentType()); + metadata.setContentLength(multipartFile.getSize()); + + FileOutputStream fos = null; + BufferedInputStream fs = null; + + map.put("key", multipartFile.getOriginalFilename()); + + String fileName = UUID.randomUUID().toString(); + int dot = multipartFile.getOriginalFilename().lastIndexOf('.'); + if (dot >= 0) { + fileName = getTenantId() + "/" + fileName + multipartFile.getOriginalFilename().substring(dot, multipartFile.getOriginalFilename().length()); + } else { + fileName = getTenantId() + "/" + fileName; + } + + ResultData data1 = awsUpload(multipartFile, metadata, fileName); + if(data1.code == ResultData.SUCCESS) { + Map _data = (Map)data1.data; + map.put("url", (String) _data.get("url")); + dataList.add(map); + } else { + // 部分成功 + data.code = ResultData.SUCCESS; + data.data = dataList; + return data; + } + } + data.code = ResultData.SUCCESS; + data.data = dataList; + return data; + + } + return new ResultData(); + } + + /** + * C端上传图片文件 + * + * @param multiReq + * @return + * @throws Exception + */ + @PostMapping(value = "/cimgUpload", consumes = "multipart/*", headers = "content-type=multipart/form-data") + @ApiOperation("C端上传图片文件") + public ResultData cimgUpload(@RequestParam("file") MultipartFile multiReq) { + logger.info("[" + getIpAddr() + "] UploadController::cimgUpload"); + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(multiReq.getContentType()); + metadata.setContentLength(multiReq.getSize()); + + String fileName = multiReq.getOriginalFilename(); + fileName = "cimg/" + fileName; + ResultData data = awsUpload(multiReq, metadata, fileName); + return data; + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WechatLoginController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WechatLoginController.java new file mode 100644 index 000000000..08a48846a --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WechatLoginController.java @@ -0,0 +1,393 @@ +package com.iformall.controller.sys; + +import com.alibaba.fastjson.JSON; +import com.iformall.common.ErrorCode; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.MallUserAction; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.domain.vo.MallUserInfoVo; +import com.iformall.enums.EnumMallUserAction; +import com.iformall.enums.EnumUserAdmin; +import com.iformall.service.MallUserActionService; +import com.iformall.service.MallUserInfoService; +import com.iformall.service.MallUserRoleService; +import com.iformall.shiro.UserSession; +import com.iformall.shiro.UseriFormallToken; +import com.iformall.utils.TOTP; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.mp.api.WxMpService; +import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; +import me.chanjar.weixin.mp.bean.result.WxMpUser; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.subject.Subject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; +import redis.clients.jedis.Protocol; +import redis.clients.util.SafeEncoder; + +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.*; + + +@Controller +@RequestMapping("/wechat") +@Slf4j +public class WechatLoginController extends BaseController { + private String WECHAT_PREV = "LOGIN:OPEN:"; + + @Autowired + private WxMpService wxMpService; + + @Autowired + private MallUserInfoService mallUserInfoService; + + @Autowired + private MallUserRoleService mallUserRoleService; + + @Autowired + private MallUserActionService mallUserActionService; + + @Autowired + @Qualifier("openRedisTemplate") + RedisTemplate openRedisTemplate; + + @Data + private class DisplayUserInfo { + String mallName; + String userName; + String userRole; + } + + @ApiOperation(value = "微信登录") + @GetMapping("login") + public void login(HttpServletRequest request, HttpServletResponse response) { + log.debug("[" + getIpAddr() + "] MallUserInfoController::login"); + String host = request.getHeader("host"); + log.debug("Host: " + host); + String wechatUrl = wxMpService.buildQrConnectUrl("https://"+host+"/api/wechat/callback", "snsapi_login", "111"); + try { + response.sendRedirect(wechatUrl); + } catch (IOException e) { + log.error(e.getMessage()); + } + } + + @ApiOperation(value = "微信网页登录回调", notes = "请配置此callback到网页redirect_uri") + @GetMapping("callback") + public void getAccessToken(String code, String state, HttpServletRequest request, HttpServletResponse response) { + String ipaddress = getIpAddr(); + log.debug("[" + ipaddress + "] WechatLoginController::getAccessToken"); + String host = request.getHeader("host"); + log.debug("host: " + host); + log.debug("code: " + code); + try { + WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); + log.info("accessToken: " + accessToken.getAccessToken() + ", openId: " + accessToken.getOpenId() + ", unionId: " + accessToken.getUnionId()); + + accessToken = wxMpService.oauth2refreshAccessToken(accessToken.getRefreshToken()); + log.info("accessToken: " + accessToken.getAccessToken() + ", openId: " + accessToken.getOpenId() + ", unionId: " + accessToken.getUnionId()); + + // 获取 用户信息 + WxMpUser mpUser = wxMpService.oauth2getUserInfo(accessToken, null); + if(mpUser != null) { + log.info(mpUser.toString()); + } + + // check user openid 是否是已授权用户 + List userList = mallUserInfoService.getUsersByWebOpenId(accessToken.getOpenId()); + log.info("login user list count " + userList.size()); + if(userList.size() > 0) { + if(userList.size() == 1) { + Map ret = new HashMap<>(); + // 唯一用户 + MallUserInfo user = userList.get(0); + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(user.getUsername()); + subject.login(token); + isLogin = true; + } catch (UnknownAccountException e) { + log.error(e.getMessage()); + ret.put("code", ErrorCode.USER_IS_EMPTY.getCode()); + ret.put("message", e.getMessage()); + } catch (DisabledAccountException e) { + log.error(e.getMessage()); + ret.put("code", ErrorCode.USER_IS_LOCKED.getCode()); + ret.put("message", e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage()); + ret.put("code", Result.ERROR); + ret.put("message", e.getMessage()); + } + if(isLogin) { + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + String menus = mallUserRoleService.getPermissionsByUser(info); + if(menus != null) { + info.setMenus(menus); + } + try { + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + MallUserAction action = new MallUserAction(); + action.setTenantId(info.getTenantId()); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setUserId(info.getId()); + action.setActionDesc("用户微信登录"); + action.setActionTime(new Date()); + mallUserActionService.saveOrUpdate(action); + } catch (Exception e) { + log.error(e.getMessage()); + ret.put("code", Result.ERROR); + ret.put("message", e.getMessage()); + } + Object codeObj = ret.get("code"); + if(codeObj == null) { + log.info("用户登录成功,切换主页"); + try { + response.sendRedirect("https://"+host+"/#/layout"); + } catch (Exception e) { + log.error(e.getMessage()); + } + } else { + log.info("用户登录失败-3,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode=" + errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } else { + log.info("用户登录失败-2,返回登录"); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode="+errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } else { + // 跳转登录选择页面 + String openId = accessToken.getOpenId(); + String key = TOTP.generateWechatOpen(openId); + String openKey = WECHAT_PREV + key; + Boolean isAbsent = openRedisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + RedisSerializer valueSerializer = openRedisTemplate.getValueSerializer(); + RedisSerializer keySerializer = openRedisTemplate.getKeySerializer(); + Object obj = connection.execute("set", keySerializer.serialize(openKey), + valueSerializer.serialize(openId), + SafeEncoder.encode("NX"), + SafeEncoder.encode("EX"), + Protocol.toByteArray(60)); // 60s 过期时间 + return obj != null; + } + }); + List users = new ArrayList(); + for(MallUserInfoVo user: userList) { + DisplayUserInfo disUser = new DisplayUserInfo(); + disUser.setMallName(user.getMallName()); + disUser.setUserName(user.getUsername()); + disUser.setUserRole(user.getRoleName()); + users.add(disUser); + } + String usersStr = JSON.toJSONString(users); + log.info(usersStr); + try { + usersStr = URLEncoder.encode(usersStr, "utf-8"); + response.sendRedirect("https://" + host + "/#/loginselect?key=" + key + "&list=" + usersStr); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } else { + log.info("用户登录失败-1,返回登录"); + // 跳转登录页面 + Map ret = new HashMap<>(); + ret.put("code", ErrorCode.WECHAT_LOGIN_NOT_BIND.getCode()); + ret.put("message", ErrorCode.WECHAT_LOGIN_NOT_BIND.getMessage()); + try { + String errCode = URLEncoder.encode(JSON.toJSONString(ret), "utf-8"); + response.sendRedirect("https://" + host + "/#/login?errcode="+errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } catch (WxErrorException e) { + log.error(e.getMessage()); + } + } + + @ApiOperation(value = "微信用户登录") + @GetMapping("weChatUserLogin") + @ApiImplicitParams({ + @ApiImplicitParam(name = "key", value = "key", dataType = "String", paramType = "query", required = true), + @ApiImplicitParam(name = "userName", value = "userName", dataType = "String", paramType = "query", required = true)}) + public ResultData weChatUserLogin(String key, String userName, HttpServletRequest request, HttpServletResponse response) { + String ipaddress = getIpAddr(); + log.debug("[" + ipaddress + "] MallUserInfoController::weChatUserLogin"); + String host = request.getHeader("host"); + log.debug("Host: " + host); + if(StringUtils.isBlank(userName)) { + log.error("请选择要登录的用户"); + return new ResultData(ErrorCode.WECHAT_LOGIN_USER_SELECT); + } + + String openKey = WECHAT_PREV + key; + // 限时时间内查找到此用户openId + if (openRedisTemplate.hasKey(openKey)){ + log.info(openKey + " - 找不到"); + String openId = openRedisTemplate.opsForValue().get(openKey); + openRedisTemplate.delete(openKey); + log.info("KEY: " + openKey + " deleted"); + + MallUserInfo userInfo = mallUserInfoService.getByUsername(userName); + if(userInfo.getWebOpenId().equals(openId)) { + boolean isLogin = false; + try { + Subject subject = SecurityUtils.getSubject(); + UseriFormallToken token = new UseriFormallToken(userInfo.getUsername()); + subject.login(token); + MallUserInfo info = (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + info.protectInfos(); + String menus = mallUserRoleService.getPermissionsByUser(info); + if(menus != null) { + info.setMenus(menus); + } + // 登录cookie + String cookieName = URLEncoder.encode(info.getUsername(), "utf-8"); + Cookie unameCookie = new Cookie("uname", cookieName); + unameCookie.setPath("/"); + unameCookie.setMaxAge(3600); + response.addCookie(unameCookie); + + MallUserAction action = new MallUserAction(); + action.setTenantId(info.getTenantId()); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setUserId(info.getId()); + action.setActionDesc("用户微信登录"); + action.setActionTime(new Date()); + mallUserActionService.saveOrUpdate(action); + + return new ResultData(); + } catch (UnknownAccountException e) { + log.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_EMPTY.getCode(), e.getMessage()); + } catch (DisabledAccountException e) { + log.error(e.getMessage()); + return new ResultData(ErrorCode.USER_IS_LOCKED.getCode(), e.getMessage()); + } catch (Exception e) { + log.error(e.getMessage()); + return new ResultData(Result.ERROR, e.getMessage()); + } + } else { + // 登录失败 + log.error("微信登录失败,用户微信未绑定:" + openId); + return new ResultData(ErrorCode.WECHAT_LOGIN_NOT_BIND); + } + } + log.error("微信登录失败,KEY已过期: "+ key); + return new ResultData(ErrorCode.WECHAT_LOGIN_KEY_OVERTIME); + } + + @ApiOperation(value = "微信第三方登录绑定", notes = "请配置此callback到网页redirect_uri") + @GetMapping("bindWebOpenId") + public void userBindWebOpenId(String code, String state, HttpServletRequest request, HttpServletResponse response) { + log.debug("[" + getIpAddr() + "] WechatLoginController::bindWebOpenId"); + String host = request.getHeader("host"); + String errCode = null; + try { + WxMpOAuth2AccessToken accessToken = wxMpService.oauth2getAccessToken(code); + log.debug("accessToken: " + accessToken.getAccessToken() + ", openId: " + accessToken.getOpenId() + ", unionId: " + accessToken.getUnionId()); + + // 获取 用户信息 + WxMpUser mpUser = wxMpService.oauth2getUserInfo(accessToken, null); + if(mpUser != null) { + log.debug(mpUser.toString()); + } + + String uname = state; + MallUserInfo user = mallUserInfoService.getByUsername(uname); + if(user != null) { + user.setWebOpenId(accessToken.getOpenId()); + mallUserInfoService.updateWebOpenId(user); + log.debug("https://" + host + "/#/layout"); + response.sendRedirect("https://" + host + "/#/layout"); + } else { + log.debug("https://" + host + "/#/layout?errcode=绑定失败"); + errCode = URLEncoder.encode("绑定失败", "utf-8"); + response.sendRedirect("https://" + host + "/#/layout?errcode="+errCode); + } + } catch (WxErrorException e) { + log.error(e.getMessage()); + errCode = e.getMessage(); + } catch (IOException e) { + log.error(e.getMessage()); + errCode = e.getMessage(); + } + + if(StringUtils.isNotBlank(errCode)) { + try { + errCode = URLEncoder.encode(errCode, "utf-8"); + response.sendRedirect("https://" + host + "/#/layout?errcode="+errCode); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + } + + @ApiOperation(value = "微信第三方登录解绑", notes = "请配置此callback到网页redirect_uri") + @GetMapping("cleanWebOpenId") + public ResultData cleanWebOpenId(@ModelAttribute MallUserInfo userInfo) { + log.debug("[" + getIpAddr() + "] WechatLoginController::cleanWebOpenId"); + MallUserInfo user = getUser(); + if(userInfo == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + if(StringUtils.isBlank(userInfo.getTenantId())) { + userInfo.setTenantId(user.getTenantId()); + } + if(userInfo.getId() == null && userInfo.getUsername() == null) { + return new ResultData(ErrorCode.SYS_PARAMETER_NOT_NULL); + } + // 只有本人及超级管理员可以解绑微信 + if(userInfo.getId().equals(user.getId()) + || user.getIsAdmin().equals(EnumUserAdmin.ADMIN.getCode())) { + mallUserInfoService.cleanWebOpenId(userInfo); + return new ResultData(); + } else { + return new ResultData(ErrorCode.USER_NO_PERMISSION); + } + + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WxAdminLogController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WxAdminLogController.java new file mode 100644 index 000000000..34528e993 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WxAdminLogController.java @@ -0,0 +1,35 @@ +package com.iformall.controller.sys; + +import com.github.pagehelper.PageInfo; +import com.iformall.common.Result; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxAdminLog; +import com.iformall.service.WxAdminLogService; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("wxAdminLog") +public class WxAdminLogController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxAdminLogService wxAdminLogService; + + @ApiOperation("PV计数") + @PostMapping("pvlog") + public ResultData pvLog(@RequestBody WxAdminLog wxAdminLog) { + logger.debug("[" + getIpAddr() + "] WxAdminLogController::pvLog"); + String tenantId = getTenantId(); + wxAdminLog.setTenantId(tenantId); + wxAdminLogService.saveLogCount(wxAdminLog); + return new ResultData(); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WxBusinessController.java b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WxBusinessController.java new file mode 100644 index 000000000..21de83030 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/controller/sys/WxBusinessController.java @@ -0,0 +1,49 @@ +package com.iformall.controller.sys; + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.common.ResultData; +import com.iformall.controller.base.BaseController; +import com.iformall.domain.po.WxBusiness; +import com.iformall.domain.po.WxSubBusiness; +import com.iformall.service.WxBusinessService; +import com.iformall.service.WxSubBusinessService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("wxBusiness") +@Api(description = "业态接口") +public class WxBusinessController extends BaseController { + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Autowired + private WxBusinessService wxBusinessService; + + @Autowired + private WxSubBusinessService wxSubBusinessService; + + @ApiOperation("业态全列表接口") + @GetMapping("listAll") + @SystemControllerLog(description = "业态-全列表") + public ResultData listAll() { + logger.debug("[" + getIpAddr() + "] WxBusinessController::getList"); + final List busList = wxBusinessService.findListAll(); + return new ResultData(busList); + } + + @ApiOperation("子业态表接口") + @GetMapping("listSub") + @SystemControllerLog(description = "子业态") + public ResultData listSub(@ModelAttribute WxSubBusiness wxSubBusiness) { + logger.debug("[" + getIpAddr() + "] WxBusinessController::getList"); + final List busList = wxSubBusinessService.findList(wxSubBusiness); + return new ResultData(busList); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/enums/EnumLoginType.java b/mallinkSysAdmin/src/main/java/com/iformall/enums/EnumLoginType.java new file mode 100644 index 000000000..d25d5f607 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/enums/EnumLoginType.java @@ -0,0 +1,38 @@ +package com.iformall.enums; + +/** + * Created by Stormeye on 2018/11/16. + */ +public enum EnumLoginType { + + // 0-password, 1-nopassword + + PASSWORD(0, "PASSWORD"), + NOPASSWD(1, "NOPASSWORD") + ; + + public static EnumLoginType getEnum(Integer code) { + for (EnumLoginType value : values()) { + if (value.getCode().equals(code)) { + return value; + } + } + return null; + } + + private Integer code; + private String message; + + EnumLoginType(Integer code, String message) { + this.code = code; + this.message = message; + } + + public Integer getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/flowable/ContractTaskFinishHandler.java b/mallinkSysAdmin/src/main/java/com/iformall/flowable/ContractTaskFinishHandler.java new file mode 100644 index 000000000..39982396e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/flowable/ContractTaskFinishHandler.java @@ -0,0 +1,44 @@ +package com.iformall.flowable; + +import com.iformall.enums.EnumRentContractAppStatus; +import com.iformall.service.WxFlowService; +import com.iformall.service.WxPropertyContractService; +import com.iformall.service.impl.WxFlowServiceImpl; +import org.apache.commons.lang3.StringUtils; +import org.flowable.engine.delegate.TaskListener; +import org.flowable.task.service.delegate.DelegateTask; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import java.util.List; +import java.util.Map; + +/** + * 合同审批完成,修改状态 + * + */ +@Component(value="contractTaskFinishListener") +public class ContractTaskFinishHandler implements TaskListener { + @Autowired + private WxFlowService wxFlowService; + @Autowired + private WxPropertyContractService wxPropertyContractService; + + @Override + public void notify(DelegateTask delegateTask) { +// Long businessId = (Long)delegateTask.getVariable("businessId"); +// List> variables = (List)delegateTask.getVariable("variables"); +// Integer flowType = (Integer)delegateTask.getVariable("flowType"); +// +// Integer contractType = 0; +// String str = WxFlowServiceImpl.getVariableByKey(variables,"contractType"); +// if(StringUtils.isNotBlank(str)){ +// contractType = Integer.parseInt(str); +// +// if(3==contractType){ +// wxPropertyContractService.updatePropertyContractStatus(businessId); +// } +// } +// wxFlowService.updateBusinessStatus(businessId,flowType,contractType,EnumRentContractAppStatus.FINISH.getCode()); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/flowable/FlowableConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/flowable/FlowableConfig.java new file mode 100644 index 000000000..0c71fc1d7 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/flowable/FlowableConfig.java @@ -0,0 +1,22 @@ +package com.iformall.flowable; + +import org.flowable.spring.SpringProcessEngineConfiguration; +import org.flowable.spring.boot.EngineConfigurationConfigurer; +import org.springframework.context.annotation.Configuration; + +/** + * @author haiyangp + * date: 2018/4/7 + * desc: flowable配置----为放置生成的流程图中中文乱码 + */ +@Configuration +public class FlowableConfig implements EngineConfigurationConfigurer { + + + @Override + public void configure(SpringProcessEngineConfiguration engineConfiguration) { + engineConfiguration.setActivityFontName("宋体"); + engineConfiguration.setLabelFontName("宋体"); + engineConfiguration.setAnnotationFontName("宋体"); + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java new file mode 100644 index 000000000..7be788b6e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/BodyReaderHttpServletRequestWrapper.java @@ -0,0 +1,76 @@ +package com.iformall.interceptor; + +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.*; + +public class BodyReaderHttpServletRequestWrapper extends XssHttpServletRequestWrapper { + private final String body; + + public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException { + super(request); + StringBuffer stringBuilder = new StringBuffer(); + BufferedReader bufferedReader = null; + try { + InputStream inputStream = request.getInputStream(); + if (inputStream != null) { + bufferedReader = new BufferedReader(new InputStreamReader(inputStream,"utf-8")); + char[] charBuffer = new char[1024]; + int bytesRead = -1; + while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { + stringBuilder.append(charBuffer, 0, bytesRead); + } + } else { + stringBuilder.append(""); + } + } catch (IOException ex) { + throw ex; + } finally { + if (bufferedReader != null) { + try { + bufferedReader.close(); + } catch (IOException ex) { + throw ex; + } + } + } + body = stringBuilder.toString(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + final ByteArrayInputStream byteArrayInputStream = + new ByteArrayInputStream(body.getBytes("utf-8")); + return new ServletInputStream() { + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + + @Override + public int read() throws IOException { + return byteArrayInputStream.read(); + } + }; + } + + @Override + public BufferedReader getReader() throws IOException { + return new BufferedReader(new InputStreamReader(this.getInputStream())); + } + + public String getBody() { + return this.body; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java new file mode 100644 index 000000000..aebf7d874 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/HttpServletRequestWrapperFilter.java @@ -0,0 +1,72 @@ +package com.iformall.interceptor; + +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; + +public class HttpServletRequestWrapperFilter implements Filter { + private static final Logger logger = LoggerFactory.getLogger(HttpServletRequestWrapperFilter.class); + // 多个跨域域名设置 + // public static final String[] ALLOW_DOMAIN = {"https://admin.malls.iformall.com"}; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + ServletRequest requestWrapper = null; + /* // 跨域访问 + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + String originHeader = req.getHeader("Origin"); + + if (Arrays.asList(ALLOW_DOMAIN).contains(originHeader)) { + //通过在响应 header 中设置 ‘*’ 来允许来自所有域的跨域请求访问。 + res.setHeader("Access-Control-Allow-Origin", originHeader); + //通过对 Credentials 参数的设置,就可以保持跨域 Ajax 时的 Cookie + //设置了Allow-Credentials,Allow-Origin就不能为*,需要指明具体的url域 + res.setHeader("Access-Control-Allow-Credentials", "true"); + //请求方式 + res.setHeader("Access-Control-Allow-Methods", "*"); + //(预检请求)的返回结果(即 Access-Control-Allow-Methods 和Access-Control-Allow-Headers 提供的信息) 可以被缓存多久 + res.setHeader("Access-Control-Max-Age", "86400"); + //首部字段用于预检请求的响应。其指明了实际请求中允许携带的首部字段 + //res.setHeader("Access-Control-Allow-Headers", "*"); + res.setHeader("Access-Control-Allow-Headers", + "Timestamp,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token,Access-Control-Allow-Headers"); + } + */ + + //sql,xss过滤 + XssHttpServletRequestWrapper xssHttpServletRequestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest)request); + + if (request instanceof HttpServletRequest) { + String url = ((HttpServletRequest) request).getRequestURI(); + if (!UrlCheck.checkUrl(url)) { + requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request); + } + } + if (null == requestWrapper) { + chain.doFilter(xssHttpServletRequestWrapper, response); + } else { + chain.doFilter(requestWrapper, response); + } + + } + + + @Override + public void destroy() { + + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/interceptor/RequestInterceptor.java b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/RequestInterceptor.java new file mode 100644 index 000000000..d01a11de5 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/RequestInterceptor.java @@ -0,0 +1,117 @@ +package com.iformall.interceptor; + +import com.iformall.common.ErrorCode; +import com.iformall.exception.MallinkException; +import com.iformall.utils.HashUtil; +import com.iformall.utils.IPUtil; +import com.iformall.utils.UrlCheck; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.dao.DataAccessException; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.core.RedisCallback; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.RedisSerializer; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import redis.clients.jedis.Protocol; +import redis.clients.util.SafeEncoder; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Enumeration; +import java.util.concurrent.TimeUnit; + +/** + * 幂等检查 + * @author stormeye.wu + * @email wuguoqiang@iformall.com + * @date 2017-03-23 15:38 + */ +@Component +public class RequestInterceptor extends HandlerInterceptorAdapter { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @Resource + private RedisTemplate redisTemplate; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if ("GET".equalsIgnoreCase(request.getMethod())) { + // 获取不检查幂等 + return true; + } + + String ipaddress = IPUtil.getIpAddr(request); + String url = request.getRequestURL().toString(); + if (UrlCheck.checkUrl(url)) { + // pvlog不检查幂等 + // awsFileUpload不检查幂等 + // ueditor 不检查幂等 + return true; + } + StringBuilder sb = new StringBuilder(); + sb.append(url); + sb.append("method=").append(request.getMethod()).append("&"); + sb.append("ip=").append(ipaddress).append("&"); + + final Enumeration parameterNames = request.getParameterNames(); + while (parameterNames.hasMoreElements()) { + String key = (String) parameterNames.nextElement(); + if(key.equalsIgnoreCase("ran")) // 跳过ran + continue; + String parameter = request.getParameter(key); + sb.append(key).append("=").append(parameter).append("&"); + } + + InputStream inStream = request.getInputStream(); + ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len = 0; + while ((len = inStream.read(buffer)) != -1) { + outSteam.write(buffer, 0, len); + } + String resultBody = new String(outSteam.toByteArray(), Charset.forName("UTF-8")); + inStream.close(); + outSteam.close(); + + sb.append(resultBody); + + String key = "request:A:" + HashUtil.md5(sb.toString()); + Boolean isAbsent = redisTemplate.execute(new RedisCallback() { + @Override + public Boolean doInRedis(RedisConnection connection) throws DataAccessException { + RedisSerializer valueSerializer = redisTemplate.getValueSerializer(); + RedisSerializer keySerializer = redisTemplate.getKeySerializer(); + Object obj = connection.execute("set", keySerializer.serialize(key), + valueSerializer.serialize(key), + SafeEncoder.encode("NX"), + SafeEncoder.encode("EX"), + Protocol.toByteArray(3)); // 3s + return obj != null; + } + }); + if (isAbsent) { + logger.info(key + ": 第一次提交"); + return true; + } + logger.info(key + ": 第二次提交"); + throw new MallinkException(ErrorCode.SYS_REPEAT_SUBMIT_EXCEPTION); + } + + @Override + public void postHandle(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { + + } + + @Override + public void afterCompletion(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, Object handler, Exception ex) throws Exception { + + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java new file mode 100644 index 000000000..1d954d163 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/interceptor/XssHttpServletRequestWrapper.java @@ -0,0 +1,125 @@ +package com.iformall.interceptor; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * 防止sql注入,xss攻击 + * 前端可以对输入信息做预处理,后端也可以做处理。 + */ +public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { + private final Logger log = LoggerFactory.getLogger(getClass()); + private static String key = "and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+"; + private static Set notAllowedKeyWords = new HashSet(0); + private static String replacedString="INVALID"; + static { + String keyStr[] = key.split("\\|"); + for (String str : keyStr) { + notAllowedKeyWords.add(str); + } + } + + private String currentUrl; + + public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) { + super(servletRequest); + currentUrl = servletRequest.getRequestURI(); + } + + + /**覆盖getParameter方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取 + * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 + */ + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + if (value == null) { + return null; + } + return cleanXSS(value); + } + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = cleanXSS(values[i]); + } + return encodedValues; + } + @Override + public Map getParameterMap(){ + Map values=super.getParameterMap(); + if (values == null) { + return null; + } + Map result=new HashMap<>(); + for(String key:values.keySet()){ + String encodedKey=cleanXSS(key); + int count=values.get(key).length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++){ + encodedValues[i]=cleanXSS(values.get(key)[i]); + } + result.put(encodedKey,encodedValues); + } + return result; + } + /** + * 覆盖getHeader方法,将参数名和参数值都做xss过滤。 + * 如果需要获得原始的值,则通过super.getHeaders(name)来获取 + * getHeaderNames 也可能需要覆盖 + */ + @Override + public String getHeader(String name) { + if(name.equalsIgnoreCase("user-agent")) { + return super.getHeader(name); + } + String value = super.getHeader(name); + if (value == null) { + return null; + } + return cleanXSS(value); + } + + private String cleanXSS(String valueP) { + // You'll need to remove the spaces from the html entities below + String value = valueP.replaceAll("<", "<").replaceAll(">", ">"); + value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); + value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); + value = value.replaceAll("'", "& #39;"); + value = value.replaceAll("eval\\((.*)\\)", ""); + value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); + value = value.replaceAll("script", ""); + value = cleanSqlKeyWords(value); + return value; + } + + private String cleanSqlKeyWords(String value) { + String paramValue = value; + for (String keyword : notAllowedKeyWords) { + if (paramValue.length() > keyword.length() + 4 + && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) { + paramValue = StringUtils.replace(paramValue, keyword, replacedString); + log.error(this.currentUrl + "已被过滤,因为参数中包含不允许sql的关键词(" + keyword + + ")"+";参数:"+value+";过滤后的参数:"+paramValue); + } + } + return paramValue; + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/log/SystemLogAspect.java b/mallinkSysAdmin/src/main/java/com/iformall/log/SystemLogAspect.java new file mode 100644 index 000000000..02bbae52a --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/log/SystemLogAspect.java @@ -0,0 +1,171 @@ +package com.iformall.log; + + +import com.iformall.annotation.SystemControllerLog; +import com.iformall.annotation.SystemServiceLog; +import com.iformall.domain.po.MallUserAction; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.enums.EnumMallUserAction; +import com.iformall.service.MallUserActionService; +import com.iformall.shiro.UserSession; +import com.iformall.utils.IPUtil; +import org.apache.shiro.SecurityUtils; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.lang.reflect.Method; +import java.util.Date; + +@Aspect +@Component +public class SystemLogAspect { + private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class); + + @Autowired + private MallUserActionService mallUserActionService; + + @Pointcut("@annotation(com.iformall.annotation.SystemControllerLog)") + public void controllerAspect(){ + } + + @Pointcut("@annotation(com.iformall.annotation.SystemServiceLog)") + public void serviceAspect(){ + } + + @Before("controllerAspect()") + public void doBefore(JoinPoint joinPoint) { + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + MallUserInfo user = (MallUserInfo) request.getSession().getAttribute(UserSession.userInfo); + if(user == null) { + logger.error("session 获取 user 失败"); + return; + } + String ipaddress = IPUtil.getIpAddr(request); + + try { + logger.info("===前置通知开始=== [" + + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName()) + "]" + + getControllerMethodDescription(joinPoint) + " " + user.getUsername() + + " ip:" + ipaddress); + + MallUserAction action = new MallUserAction(); + action.setTenantId(user.getTenantId()); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setUserId(user.getId()); + action.setActionDesc(getControllerMethodDescription(joinPoint)); + action.setActionTime(new Date()); + + mallUserActionService.saveOrUpdate(action); + } catch (Exception e) { + logger.error("===前置通知异常信息:{}",e.getMessage()); + } + } + + /** + * @Description 异常通知 用于拦截service层记录异常日志 + * @date 2019年3月29日 + */ + @AfterThrowing(pointcut = "serviceAspect()",throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint,Throwable e){ + /* + HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + HttpSession session = request.getSession(); + MallUserInfo user = (MallUserInfo) request.getSession().getAttribute(UserSession.userInfo); + //获取请求ip + String ipaddress = IPUtil.getIpAddr(request); + //获取用户请求方法的参数并序列化为JSON格式字符串 + String params = ""; + if (joinPoint.getArgs()!=null&&joinPoint.getArgs().length>0){ + for (int i = 0; i < joinPoint.getArgs().length; i++) { + params+= JsonUtils.objectToJson(joinPoint.getArgs()[i])+";"; + } + } + try{ + // ========控制台输出========= + System.out.println("=====异常通知开始====="); + System.out.println("异常代码:" + e.getClass().getName()); + System.out.println("异常信息:" + e.getMessage()); + System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); + System.out.println("方法描述:" + getServiceMethodDescription(joinPoint)); + System.out.println("请求人:" + user.getUsername()); + System.out.println("请求IP:" + ipaddress); + System.out.println("请求参数:" + params); + + + MallUserAction action = new MallUserAction(); + action.setTenantId(user.getTenantId()); + action.setUserId(user.getId()); + action.setType(EnumMallUserAction.CONTROLLER.getCode()); + action.setIp(ipaddress); + action.setDesc(getControllerMethodDescription(joinPoint)); + action.setActionTime(new Date()); + + mallUserActionService.saveOrUpdate(action); + }catch (Exception ex){ + //记录本地异常日志 + logger.error("==异常通知异常=="); + logger.error("异常信息:{}", ex.getMessage()); + } + */ + } + + /** + * @author Stormeye + * @Description 获取注解中对方法的描述信息 用于Controller层注解 + * @date 2019年3月29日 + */ + public static String getControllerMethodDescription(JoinPoint joinPoint) throws Exception { + String targetName = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName();//目标方法名 + Object[] arguments = joinPoint.getArgs(); + Class targetClass = Class.forName(targetName); + Method[] methods = targetClass.getMethods(); + String description = ""; + for (Method method:methods) { + if (method.getName().equals(methodName)){ + Class[] clazzs = method.getParameterTypes(); + if (clazzs.length==arguments.length){ + description = method.getAnnotation(SystemControllerLog.class).description(); + break; + } + } + } + return description; + } + + /** + * @Description 获取注解中对方法的描述信息 用于service层注解 + * @date 2018年9月3日 下午5:05 + */ + public static String getServiceMethodDescription(JoinPoint joinPoint)throws Exception{ + String targetName = joinPoint.getTarget().getClass().getName(); + String methodName = joinPoint.getSignature().getName(); + Object[] arguments = joinPoint.getArgs(); + Class targetClass = Class.forName(targetName); + Method[] methods = targetClass.getMethods(); + String description = ""; + for (Method method:methods) { + if (method.getName().equals(methodName)){ + Class[] clazzs = method.getParameterTypes(); + if (clazzs.length==arguments.length){ + description = method.getAnnotation(SystemServiceLog.class).description(); + break; + } + } + } + return description; + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java b/mallinkSysAdmin/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java new file mode 100644 index 000000000..e71e52c61 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/shiro/MyRetryLimitCredentialsMatcher.java @@ -0,0 +1,45 @@ +package com.iformall.shiro; + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.enums.EnumLoginType; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.service.MallUserInfoService; +import org.apache.shiro.authc.AuthenticationInfo; +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.DisabledAccountException; +import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.credential.HashedCredentialsMatcher; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.Resource; + +@Configuration +public class MyRetryLimitCredentialsMatcher extends HashedCredentialsMatcher { + @Resource + private MallUserInfoService userService; + + @Override + public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) { + if(authcToken instanceof UseriFormallToken) { + UseriFormallToken tk = (UseriFormallToken) authcToken; + if(tk.getType().equals(EnumLoginType.NOPASSWD)){ + // 获取用户的输入的账号. + String username = (String)tk.getPrincipal(); + MallUserInfo user = userService.getByUsername(username); + if(user == null) { + throw new UnknownAccountException(ErrorCode.USER_IS_EMPTY.getMessage()); + } + // 用户被禁用 + if(user.getStatus()==null ||!EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) { + throw new DisabledAccountException(ErrorCode.USER_IS_LOCKED.getMessage()); + } + return true; + } + boolean matches = super.doCredentialsMatch(authcToken, info); + return matches; + } + boolean matches =super.doCredentialsMatch(authcToken, info); + return matches; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/shiro/MyShiroRealm.java b/mallinkSysAdmin/src/main/java/com/iformall/shiro/MyShiroRealm.java new file mode 100644 index 000000000..f3c80982c --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/shiro/MyShiroRealm.java @@ -0,0 +1,82 @@ +package com.iformall.shiro; + +import javax.annotation.Resource; + +import com.iformall.common.ErrorCode; +import com.iformall.enums.EnumMallUserStatus; +import com.iformall.service.MallUserInfoService; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.authc.*; +import org.apache.shiro.authz.AuthorizationInfo; +import org.apache.shiro.authz.SimpleAuthorizationInfo; +import org.apache.shiro.realm.AuthorizingRealm; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.util.ByteSource; + +import com.iformall.domain.po.MallUserInfo; + +import java.util.Set; + +/** + * Created by yangqj on 2017/4/21. + */ +public class MyShiroRealm extends AuthorizingRealm { + + @Resource + private MallUserInfoService userService; + + //授权 + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { + MallUserInfo user= (MallUserInfo) SecurityUtils.getSubject().getPrincipal(); + Set permissionSet = userService.getUserPermissions(user); + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + info.setStringPermissions(permissionSet); + return info; + } + + //认证 + @Override + protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { + //获取用户的输入的账号. + String username = (String)token.getPrincipal(); + MallUserInfo user = userService.getByUsername(username); + if(user == null) { + throw new UnknownAccountException(ErrorCode.USER_IS_EMPTY.getMessage()); + } + // 租户1为预留系统管理端 + if(!user.getTenantId().equals("1")) { + // 只支持租户为1的用户 + throw new UnknownAccountException("租户不支持"); + } + if(user.getStatus()==null || + !EnumMallUserStatus.VALID.getCode().equals(user.getStatus())) {//用户被禁用 + throw new DisabledAccountException(ErrorCode.USER_IS_LOCKED.getMessage()); + } + SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo( + user, //用户 + user.getPassword(), //密码 + ByteSource.Util.bytes(username), + getName() //realm name + ); + // 当验证都通过后,把用户信息放在session里 + Session session = SecurityUtils.getSubject().getSession(); + session.setAttribute(UserSession.userInfo, user); + session.setAttribute(UserSession.userId, user.getId()); + session.setAttribute(UserSession.tenantId, user.getTenantId()); + return authenticationInfo; + } + + + /** + * 指定principalCollection 清除 + */ + /* public void clearCachedAuthorizationInfo(PrincipalCollection principalCollection) { + + SimplePrincipalCollection principals = new SimplePrincipalCollection( + principalCollection, getName()); + super.clearCachedAuthorizationInfo(principals); + } +*/ +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/shiro/PasswordHelper.java b/mallinkSysAdmin/src/main/java/com/iformall/shiro/PasswordHelper.java new file mode 100644 index 000000000..155fca778 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/shiro/PasswordHelper.java @@ -0,0 +1,33 @@ +package com.iformall.shiro; + + +import com.iformall.domain.po.MallUserInfo; +import org.apache.shiro.crypto.hash.SimpleHash; +import org.apache.shiro.util.ByteSource; + + + +public class PasswordHelper { + //private RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator(); + private String algorithmName = "md5"; + private int hashIterations = 2; + + public void encryptPassword(MallUserInfo user) { + //String salt=randomNumberGenerator.nextBytes().toHex(); + String newPassword = new SimpleHash(algorithmName, user.getPassword(), ByteSource.Util.bytes(user.getUsername()), hashIterations).toHex(); + //String newPassword = new SimpleHash(algorithmName, user.getPassword()).toHex(); + user.setPassword(newPassword); + + } + + public static void main(String[] args) { + MallUserInfo user = new MallUserInfo(); + user.setUsername("fmkjadmin"); + user.setPassword("fmkjadmin790"); + PasswordHelper passwordHelper = new PasswordHelper(); + passwordHelper.encryptPassword(user); + System.out.println(user); + System.out.println(user.getPassword()); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/shiro/ShiroService.java b/mallinkSysAdmin/src/main/java/com/iformall/shiro/ShiroService.java new file mode 100644 index 000000000..5c311ac54 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/shiro/ShiroService.java @@ -0,0 +1,127 @@ +package com.iformall.shiro; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.shiro.spring.web.ShiroFilterFactoryBean; +import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager; +import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver; +import org.apache.shiro.web.servlet.AbstractShiroFilter; +import org.crazycake.shiro.RedisSessionDAO; +import org.springframework.beans.factory.annotation.Autowired; + +import com.iformall.service.MallPermissionService; + +/** + * Created by yangqj on 2017/4/30. + */ +//@Service +public class ShiroService { + @Autowired + private ShiroFilterFactoryBean shiroFilterFactoryBean; + @Autowired + private MallPermissionService resourcesService; + @Autowired + private RedisSessionDAO redisSessionDAO; + /** + * 初始化权限 + */ + public Map loadFilterChainDefinitions() { + // 权限控制map.从数据库获取 + Map filterChainDefinitionMap = new LinkedHashMap(); + filterChainDefinitionMap.put("/logout", "logout"); + filterChainDefinitionMap.put("/css/**","anon"); + filterChainDefinitionMap.put("/js/**","anon"); + filterChainDefinitionMap.put("/img/**","anon"); + filterChainDefinitionMap.put("/user/**","anon"); + filterChainDefinitionMap.put("/font-awesome/**","anon"); +// Map map = new HashMap<>(); +// List resourcesList = resourcesService.list(map); +// for(SysPermission resources:resourcesList){ +// +// if (StringUtil.isNotEmpty(resources.getUrl())) { +// String permission = "perms[" + resources.getUrl()+ "]"; +// filterChainDefinitionMap.put(resources.getUrl(),permission); +// } +// } + filterChainDefinitionMap.put("/**", "authc"); + return filterChainDefinitionMap; + } + + /** + * 重新加载权限 + */ + public void updatePermission() { + + synchronized (shiroFilterFactoryBean) { + + AbstractShiroFilter shiroFilter = null; + try { + shiroFilter = (AbstractShiroFilter) shiroFilterFactoryBean + .getObject(); + } catch (Exception e) { + throw new RuntimeException( + "get ShiroFilter from shiroFilterFactoryBean error!"); + } + + PathMatchingFilterChainResolver filterChainResolver = (PathMatchingFilterChainResolver) shiroFilter + .getFilterChainResolver(); + DefaultFilterChainManager manager = (DefaultFilterChainManager) filterChainResolver + .getFilterChainManager(); + + // 清空老的权限控制 + manager.getFilterChains().clear(); + + shiroFilterFactoryBean.getFilterChainDefinitionMap().clear(); + shiroFilterFactoryBean + .setFilterChainDefinitionMap(loadFilterChainDefinitions()); + // 重新构建生成 + Map chains = shiroFilterFactoryBean + .getFilterChainDefinitionMap(); + for (Map.Entry entry : chains.entrySet()) { + String url = entry.getKey(); + String chainDefinition = entry.getValue().trim() + .replace(" ", ""); + manager.createChain(url, chainDefinition); + } + + System.out.println("更新权限成功!!"); + } + } + + /** + * 根据userId 清除当前session存在的用户的权限缓存 + * @param userIds 已经修改了权限的userId + */ + /* public void clearUserAuthByUserId(List userIds){ + if(null == userIds || userIds.size() == 0) return ; + //获取所有session + Collection sessions = redisSessionDAO.getActiveSessions(); + //定义返回 + List list = new ArrayList(); + for (Session session:sessions){ + //获取session登录信息。 + Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); + if(null != obj && obj instanceof SimplePrincipalCollection){ + //强转 + SimplePrincipalCollection spc = (SimplePrincipalCollection)obj; + //判断用户,匹配用户ID。 + obj = spc.getPrimaryPrincipal(); + if(null != obj && obj instanceof User){ + User user = (User) obj; + System.out.println("user:"+user); + //比较用户ID,符合即加入集合 + if(null != user && userIds.contains(user.getId())){ + list.add(spc); + } + } + } + } + RealmSecurityManager securityManager = + (RealmSecurityManager) SecurityUtils.getSecurityManager(); + MyShiroRealm realm = (MyShiroRealm)securityManager.getRealms().iterator().next(); + for (SimplePrincipalCollection simplePrincipalCollection : list) { + realm.clearCachedAuthorizationInfo(simplePrincipalCollection); + } + }*/ +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/shiro/UserSession.java b/mallinkSysAdmin/src/main/java/com/iformall/shiro/UserSession.java new file mode 100644 index 000000000..02a7aca87 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/shiro/UserSession.java @@ -0,0 +1,11 @@ +package com.iformall.shiro; + +public class UserSession { + + public static String userInfo="userSession"; + + public static String userId ="userSessionId"; + + public static String tenantId ="TENANT_ID"; + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/shiro/UseriFormallToken.java b/mallinkSysAdmin/src/main/java/com/iformall/shiro/UseriFormallToken.java new file mode 100644 index 000000000..04f525a73 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/shiro/UseriFormallToken.java @@ -0,0 +1,39 @@ +package com.iformall.shiro; + +import com.iformall.enums.EnumLoginType; +import org.apache.shiro.authc.UsernamePasswordToken; + +public class UseriFormallToken extends UsernamePasswordToken { + private static final long serialVersionUID = -2564928913725078138L; + + private EnumLoginType type; + + public UseriFormallToken() { + super(); + } + + public UseriFormallToken(String username, String password, EnumLoginType type, boolean rememberMe, String host) { + super(username, password, rememberMe, host); + this.type = type; + } + + /** 免密登录 */ + public UseriFormallToken(String username) { + super(username, "", false, null); + this.type = EnumLoginType.NOPASSWD; + } + /** 账号密码登录 */ + public UseriFormallToken(String username, String pwd) { + super(username, pwd, false, null); + this.type = EnumLoginType.PASSWORD; + } + + public EnumLoginType getType() { + return type; + } + + + public void setType(EnumLoginType type) { + this.type = type; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java new file mode 100644 index 000000000..be78d3668 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/ActionEnter.java @@ -0,0 +1,119 @@ +package com.iformall.ueditor; + +import com.iformall.ueditor.define.ActionMap; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import com.iformall.ueditor.hunter.FileManager; +import com.iformall.ueditor.hunter.ImageHunter; +import com.iformall.ueditor.upload.Uploader; + +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +public class ActionEnter { + + private HttpServletRequest request = null; + + private String actionType = null; + + private ConfigManager configManager = null; + + public ActionEnter(ConfigManager configManager) { + this.configManager = configManager; + } + + public Object exec(HttpServletRequest request) { + this.request = request; + this.actionType = request.getParameter("action"); + String callbackName = this.request.getParameter("callback"); + + if (callbackName != null) { + + if (!validCallbackName(callbackName)) { + return new BaseState(false, AppInfo.ILLEGAL).toJSONString(); + } + + //return callbackName + "(" + this.invoke() + ");"; + return this.invoke(); + + } else { + return this.invoke(); + } + + } + + public Object invoke() { + + if (actionType == null || !ActionMap.mapping.containsKey(actionType)) { + return new BaseState(false, AppInfo.INVALID_ACTION).toJSONString(); + } + + if (this.configManager == null || !this.configManager.valid()) { + return new BaseState(false, AppInfo.CONFIG_ERROR).toJSONString(); + } + + State state = null; + + int actionCode = ActionMap.getType(this.actionType); + + Map conf = null; + + switch (actionCode) { + + case ActionMap.CONFIG: + return this.configManager.getAllConfig(); + + case ActionMap.UPLOAD_IMAGE: + case ActionMap.UPLOAD_SCRAWL: + case ActionMap.UPLOAD_VIDEO: + case ActionMap.UPLOAD_FILE: + conf = this.configManager.getConfig(actionCode); + state = new Uploader(request, conf).doExec(); + break; + + case ActionMap.CATCH_IMAGE: + conf = configManager.getConfig(actionCode); + String[] list = this.request.getParameterValues((String) conf.get("fieldName")); + state = new ImageHunter(conf).capture(list); + break; + + case ActionMap.LIST_IMAGE: + case ActionMap.LIST_FILE: + conf = configManager.getConfig(actionCode); + int start = this.getStartIndex(); + state = new FileManager(conf).listFile(start); + break; + + } + + return state.toJSONString(); + + } + + public int getStartIndex() { + + String start = this.request.getParameter("start"); + + try { + return Integer.parseInt(start); + } catch (Exception e) { + return 0; + } + + } + + /** + * callback参数验证 + */ + public boolean validCallbackName(String name) { + + if (name.matches("^[a-zA-Z_]+[\\w0-9_]*$")) { + return true; + } + + return false; + + } + +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java new file mode 100644 index 000000000..036c95c77 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/ConfigManager.java @@ -0,0 +1,223 @@ +package com.iformall.ueditor; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.iformall.config.AwsProperty; +import com.iformall.ueditor.define.ActionMap; + +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +/** + * 配置管理器 + * + * @author hancong03@baidu.com + */ +public final class ConfigManager { + + private static final String configFileName = "config.json"; + private JSONObject jsonConfig = null; + // 涂鸦上传filename定义 + private final static String SCRAWL_FILE_NAME = "scrawl"; + // 远程图片抓取filename定义 + private final static String REMOTE_FILE_NAME = "remote"; + //配置信息 + private UEditorConfig uEditorConfig; + private AwsProperty awsProperty; + + /* + * 通过一个给定的路径构建一个配置管理器, 该管理器要求地址路径所在目录下必须存在config.properties文件 + */ + private ConfigManager(UEditorConfig uEditorConfig, AwsProperty awsProperty) throws IOException { + this.uEditorConfig = uEditorConfig; + this.awsProperty = awsProperty; + String configPath = uEditorConfig.getConfig(); + configPath = configPath == null || configPath.isEmpty() ? configFileName : configPath; + this.initEnv(configPath); + } + + /** + * 配置管理器构造工厂 + * + * @param uEditorConfig 配置文件 + * @return 配置管理器实例或者null + */ + public static ConfigManager getInstance(UEditorConfig uEditorConfig, AwsProperty awsProperty) { + + try { + return new ConfigManager(uEditorConfig, awsProperty); + } catch (Exception e) { + System.err.println("UEditor ConfigManager load error~"); + return null; + } + + } + + // 验证配置文件加载是否正确 + public boolean valid() { + return this.jsonConfig != null; + } + + public JSONObject getAllConfig() { + + return this.jsonConfig; + + } + + public Map getConfig(int type) { + + Map conf = new HashMap(); + String savePath = null; + + try { + switch (type) { + + case ActionMap.UPLOAD_FILE: + conf.put("isBase64", "false"); + conf.put("maxSize", this.jsonConfig.getLong("fileMaxSize")); + conf.put("allowFiles", this.getArray("fileAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("fileFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("filePathFormat"); + break; + + case ActionMap.UPLOAD_IMAGE: + conf.put("isBase64", "false"); + conf.put("maxSize", this.jsonConfig.getLong("imageMaxSize")); + conf.put("allowFiles", this.getArray("imageAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("imageFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("imagePathFormat"); + break; + + case ActionMap.UPLOAD_VIDEO: + conf.put("maxSize", this.jsonConfig.getLong("videoMaxSize")); + conf.put("allowFiles", this.getArray("videoAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("videoFieldName")); + conf.put("clientRegion", this.awsProperty.getClientRegion()); + conf.put("bucketName", this.awsProperty.getBucketName()); + conf.put("access", this.awsProperty.getAccess()); + conf.put("secret", this.awsProperty.getSecret()); + savePath = this.jsonConfig.getString("videoPathFormat"); + break; + + case ActionMap.UPLOAD_SCRAWL: + conf.put("filename", ConfigManager.SCRAWL_FILE_NAME); + conf.put("maxSize", this.jsonConfig.getLong("scrawlMaxSize")); + conf.put("fieldName", this.jsonConfig.getString("scrawlFieldName")); + conf.put("isBase64", "true"); + savePath = this.jsonConfig.getString("scrawlPathFormat"); + break; + + case ActionMap.CATCH_IMAGE: + conf.put("filename", ConfigManager.REMOTE_FILE_NAME); + conf.put("filter", this.getArray("catcherLocalDomain")); + conf.put("maxSize", this.jsonConfig.getLong("catcherMaxSize")); + conf.put("allowFiles", this.getArray("catcherAllowFiles")); + conf.put("fieldName", this.jsonConfig.getString("catcherFieldName") + "[]"); + savePath = this.jsonConfig.getString("catcherPathFormat"); + break; + + case ActionMap.LIST_IMAGE: + conf.put("allowFiles", this.getArray("imageManagerAllowFiles")); + conf.put("dir", this.jsonConfig.getString("imageManagerListPath")); + conf.put("count", this.jsonConfig.getIntValue("imageManagerListSize")); + break; + + case ActionMap.LIST_FILE: + conf.put("allowFiles", this.getArray("fileManagerAllowFiles")); + conf.put("dir", this.jsonConfig.getString("fileManagerListPath")); + conf.put("count", this.jsonConfig.getIntValue("fileManagerListSize")); + break; + + } + } catch (JSONException e) { + e.printStackTrace(); + } + + conf.put("savePath", savePath); + conf.put("rootPath", uEditorConfig.getUploadPath()); + conf.put("urlPrefix", uEditorConfig.getUrlPrefix()); + return conf; + + } + + private void initEnv(String configPath) throws IOException { + + String configContent = this.readFile(configPath); + + try { + JSONObject jsonConfig = JSON.parseObject(configContent); + //统一url访问前缀 + if (uEditorConfig.getUnified()) { + Set> entrySet = jsonConfig.entrySet(); + for (Map.Entry entry : entrySet) { + String key = entry.getKey(); + if(key.contains("UrlPrefix")) { + jsonConfig.put(key, uEditorConfig.getUrlPrefix()); + } + } + } + this.jsonConfig = jsonConfig; + } catch (Exception e) { + this.jsonConfig = null; + } + + } + + private String[] getArray(String key) throws JSONException { + + JSONArray jsonArray = this.jsonConfig.getJSONArray(key); + String[] result = new String[jsonArray.size()]; + + for (int i = 0, len = jsonArray.size(); i < len; i++) { + result[i] = jsonArray.getString(i); + } + + return result; + + } + + private String readFile(String path) throws IOException { + + StringBuilder builder = new StringBuilder(); + + try { + InputStream inputStream = getClass().getClassLoader().getResourceAsStream(path); + InputStreamReader reader = new InputStreamReader(inputStream, "UTF-8"); + BufferedReader bfReader = new BufferedReader(reader); + + String tmpContent = null; + + while ((tmpContent = bfReader.readLine()) != null) { + builder.append(tmpContent); + } + + bfReader.close(); + + } catch (UnsupportedEncodingException e) { + // 忽略 + } + + return this.filter(builder.toString()); + + } + + // 过滤输入字符串, 剔除多行注释以及替换掉反斜杠 + private String filter(String input) { + + return input.replaceAll("/\\*[\\s\\S]*?\\*/", ""); + + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/Encoder.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/Encoder.java new file mode 100644 index 000000000..7ce810b43 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/Encoder.java @@ -0,0 +1,24 @@ +package com.iformall.ueditor; + +public class Encoder { + + public static String toUnicode ( String input ) { + + StringBuilder builder = new StringBuilder(); + char[] chars = input.toCharArray(); + + for ( char ch : chars ) { + + if ( ch < 256 ) { + builder.append( ch ); + } else { + builder.append( "\\u" + Integer.toHexString( ch& 0xffff ) ); + } + + } + + return builder.toString(); + + } + +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/PathFormat.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/PathFormat.java new file mode 100644 index 000000000..b388a2f2e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/PathFormat.java @@ -0,0 +1,157 @@ +package com.iformall.ueditor; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class PathFormat { + + private static final String TIME = "time"; + private static final String FULL_YEAR = "yyyy"; + private static final String YEAR = "yy"; + private static final String MONTH = "mm"; + private static final String DAY = "dd"; + private static final String HOUR = "hh"; + private static final String MINUTE = "ii"; + private static final String SECOND = "ss"; + private static final String RAND = "rand"; + + private static Date currentDate = null; + + public static String parse ( String input ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matcher.appendReplacement(sb, PathFormat.getString( matcher.group( 1 ) ) ); + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + /** + * 格式化路径, 把windows路径替换成标准路径 + * @param input 待格式化的路径 + * @return 格式化后的路径 + */ + public static String format ( String input ) { + + return input.replace( "\\", "/" ); + + } + + public static String parse ( String input, String filename ) { + + Pattern pattern = Pattern.compile( "\\{([^\\}]+)\\}", Pattern.CASE_INSENSITIVE ); + Matcher matcher = pattern.matcher(input); + String matchStr = null; + + PathFormat.currentDate = new Date(); + + StringBuffer sb = new StringBuffer(); + + while ( matcher.find() ) { + + matchStr = matcher.group( 1 ); + if ( matchStr.indexOf( "filename" ) != -1 ) { + filename = filename.replace( "$", "\\$" ).replaceAll( "[\\/:*?\"<>|]", "" ); + matcher.appendReplacement(sb, filename ); + } else { + matcher.appendReplacement(sb, PathFormat.getString( matchStr ) ); + } + + } + + matcher.appendTail(sb); + + return sb.toString(); + } + + private static String getString ( String pattern ) { + + pattern = pattern.toLowerCase(); + + // time 处理 + if ( pattern.indexOf( PathFormat.TIME ) != -1 ) { + return PathFormat.getTimestamp(); + } else if ( pattern.indexOf( PathFormat.FULL_YEAR ) != -1 ) { + return PathFormat.getFullYear(); + } else if ( pattern.indexOf( PathFormat.YEAR ) != -1 ) { + return PathFormat.getYear(); + } else if ( pattern.indexOf( PathFormat.MONTH ) != -1 ) { + return PathFormat.getMonth(); + } else if ( pattern.indexOf( PathFormat.DAY ) != -1 ) { + return PathFormat.getDay(); + } else if ( pattern.indexOf( PathFormat.HOUR ) != -1 ) { + return PathFormat.getHour(); + } else if ( pattern.indexOf( PathFormat.MINUTE ) != -1 ) { + return PathFormat.getMinute(); + } else if ( pattern.indexOf( PathFormat.SECOND ) != -1 ) { + return PathFormat.getSecond(); + } else if ( pattern.indexOf( PathFormat.RAND ) != -1 ) { + return PathFormat.getRandom( pattern ); + } + + return pattern; + + } + + private static String getTimestamp () { + return System.currentTimeMillis() + ""; + } + + private static String getFullYear () { + return new SimpleDateFormat( "yyyy" ).format( PathFormat.currentDate ); + } + + private static String getYear () { + return new SimpleDateFormat( "yy" ).format( PathFormat.currentDate ); + } + + private static String getMonth () { + return new SimpleDateFormat( "MM" ).format( PathFormat.currentDate ); + } + + private static String getDay () { + return new SimpleDateFormat( "dd" ).format( PathFormat.currentDate ); + } + + private static String getHour () { + return new SimpleDateFormat( "HH" ).format( PathFormat.currentDate ); + } + + private static String getMinute () { + return new SimpleDateFormat( "mm" ).format( PathFormat.currentDate ); + } + + private static String getSecond () { + return new SimpleDateFormat( "ss" ).format( PathFormat.currentDate ); + } + + private static String getRandom ( String pattern ) { + + int length = 0; + pattern = pattern.split( ":" )[ 1 ].trim(); + + length = Integer.parseInt( pattern ); + + return ( Math.random() + "" ).replace( ".", "" ).substring( 0, length ); + + } + + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java new file mode 100644 index 000000000..8dcedbc4e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/UEditorConfig.java @@ -0,0 +1,59 @@ +package com.iformall.ueditor; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Created by pangxiaofeng on 2017/9/27. + */ +@ConfigurationProperties(prefix = "ueditor") +public class UEditorConfig { + + /** + * config.json的文件存放地址 + */ + private String config; + /** + * 是否同统一上传地址:图片上传地址,视频上传地址... + */ + private boolean unified; + /** + * 文件上传路径 + */ + private String uploadPath; + /** + * 文件url前缀 + */ + private String urlPrefix; + + public String getConfig() { + return config; + } + + public void setConfig(String config) { + this.config = config; + } + + public String getUploadPath() { + return uploadPath; + } + + public void setUploadPath(String uploadPath) { + this.uploadPath = uploadPath; + } + + public String getUrlPrefix() { + return urlPrefix; + } + + public void setUrlPrefix(String urlPrefix) { + this.urlPrefix = urlPrefix; + } + + public boolean getUnified() { + return unified; + } + + public void setUnified(boolean unified) { + this.unified = unified; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java new file mode 100644 index 000000000..265425939 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/ActionMap.java @@ -0,0 +1,42 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +/** + * 定义请求action类型 + * @author hancong03@baidu.com + * + */ +@SuppressWarnings("serial") +public final class ActionMap { + + public static final Map mapping; + // 获取配置请求 + public static final int CONFIG = 0; + public static final int UPLOAD_IMAGE = 1; + public static final int UPLOAD_SCRAWL = 2; + public static final int UPLOAD_VIDEO = 3; + public static final int UPLOAD_FILE = 4; + public static final int CATCH_IMAGE = 5; + public static final int LIST_FILE = 6; + public static final int LIST_IMAGE = 7; + + static { + mapping = new HashMap(){{ + put( "config", ActionMap.CONFIG ); + put( "uploadimage", ActionMap.UPLOAD_IMAGE ); + put( "uploadscrawl", ActionMap.UPLOAD_SCRAWL ); + put( "uploadvideo", ActionMap.UPLOAD_VIDEO ); + put( "uploadfile", ActionMap.UPLOAD_FILE ); + put( "catchimage", ActionMap.CATCH_IMAGE ); + put( "listfile", ActionMap.LIST_FILE ); + put( "listimage", ActionMap.LIST_IMAGE ); + }}; + } + + public static int getType ( String key ) { + return ActionMap.mapping.get( key ); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java new file mode 100644 index 000000000..bfbcf3d97 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/ActionState.java @@ -0,0 +1,5 @@ +package com.iformall.ueditor.define; + +public enum ActionState { + UNKNOW_ERROR +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java new file mode 100644 index 000000000..a31425d6f --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/AppInfo.java @@ -0,0 +1,77 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public final class AppInfo { + + public static final int SUCCESS = 0; + public static final int MAX_SIZE = 1; + public static final int PERMISSION_DENIED = 2; + public static final int FAILED_CREATE_FILE = 3; + public static final int IO_ERROR = 4; + public static final int NOT_MULTIPART_CONTENT = 5; + public static final int PARSE_REQUEST_ERROR = 6; + public static final int NOTFOUND_UPLOAD_DATA = 7; + public static final int NOT_ALLOW_FILE_TYPE = 8; + + public static final int INVALID_ACTION = 101; + public static final int CONFIG_ERROR = 102; + + public static final int PREVENT_HOST = 201; + public static final int CONNECTION_ERROR = 202; + public static final int REMOTE_FAIL = 203; + + public static final int NOT_DIRECTORY = 301; + public static final int NOT_EXIST = 302; + + public static final int ILLEGAL = 401; + + public static Map info = new HashMap(){{ + + put( AppInfo.SUCCESS, "SUCCESS" ); + + // 无效的Action + put( AppInfo.INVALID_ACTION, "\u65E0\u6548\u7684Action" ); + // 配置文件初始化失败 + put( AppInfo.CONFIG_ERROR, "\u914D\u7F6E\u6587\u4EF6\u521D\u59CB\u5316\u5931\u8D25" ); + // 抓取远程图片失败 + put( AppInfo.REMOTE_FAIL, "\u6293\u53D6\u8FDC\u7A0B\u56FE\u7247\u5931\u8D25" ); + + // 被阻止的远程主机 + put( AppInfo.PREVENT_HOST, "\u88AB\u963B\u6B62\u7684\u8FDC\u7A0B\u4E3B\u673A" ); + // 远程连接出错 + put( AppInfo.CONNECTION_ERROR, "\u8FDC\u7A0B\u8FDE\u63A5\u51FA\u9519" ); + + // "文件大小超出限制" + put( AppInfo.MAX_SIZE, "\u6587\u4ef6\u5927\u5c0f\u8d85\u51fa\u9650\u5236" ); + // 权限不足, 多指写权限 + put( AppInfo.PERMISSION_DENIED, "\u6743\u9650\u4E0D\u8DB3" ); + // 创建文件失败 + put( AppInfo.FAILED_CREATE_FILE, "\u521B\u5EFA\u6587\u4EF6\u5931\u8D25" ); + // IO错误 + put( AppInfo.IO_ERROR, "IO\u9519\u8BEF" ); + // 上传表单不是multipart/form-data类型 + put( AppInfo.NOT_MULTIPART_CONTENT, "\u4E0A\u4F20\u8868\u5355\u4E0D\u662Fmultipart/form-data\u7C7B\u578B" ); + // 解析上传表单错误 + put( AppInfo.PARSE_REQUEST_ERROR, "\u89E3\u6790\u4E0A\u4F20\u8868\u5355\u9519\u8BEF" ); + // 未找到上传数据 + put( AppInfo.NOTFOUND_UPLOAD_DATA, "\u672A\u627E\u5230\u4E0A\u4F20\u6570\u636E" ); + // 不允许的文件类型 + put( AppInfo.NOT_ALLOW_FILE_TYPE, "\u4E0D\u5141\u8BB8\u7684\u6587\u4EF6\u7C7B\u578B" ); + + // 指定路径不是目录 + put( AppInfo.NOT_DIRECTORY, "\u6307\u5B9A\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55" ); + // 指定路径并不存在 + put( AppInfo.NOT_EXIST, "\u6307\u5B9A\u8DEF\u5F84\u5E76\u4E0D\u5B58\u5728" ); + + // callback参数名不合法 + put( AppInfo.ILLEGAL, "Callback\u53C2\u6570\u540D\u4E0D\u5408\u6CD5" ); + + }}; + + public static String getStateInfo ( int key ) { + return AppInfo.info.get( key ); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java new file mode 100644 index 000000000..db66dd2cc --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/BaseState.java @@ -0,0 +1,90 @@ +package com.iformall.ueditor.define; + +import com.iformall.ueditor.Encoder; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class BaseState implements State { + + private boolean state = false; + private String info = null; + + private Map infoMap = new HashMap(); + + public BaseState () { + this.state = true; + } + + public BaseState ( boolean state ) { + this.setState( state ); + } + + public BaseState ( boolean state, String info ) { + this.setState( state ); + this.info = info; + } + + public BaseState ( boolean state, int infoCode ) { + this.setState( state ); + this.info = AppInfo.getStateInfo( infoCode ); + } + + public boolean isSuccess () { + return this.state; + } + + public void setState ( boolean state ) { + this.state = state; + } + + public void setInfo ( String info ) { + this.info = info; + } + + public void setInfo ( int infoCode ) { + this.info = AppInfo.getStateInfo( infoCode ); + } + + @Override + public String toJSONString() { + return this.toString(); + } + + public String toString () { + + String key = null; + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + Iterator iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + key = iterator.next(); + + builder.append( ",\"" + key + "\": \"" + this.infoMap.get(key) + "\"" ); + + } + + builder.append( "}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public void putInfo(String name, long val) { + this.putInfo(name, val+""); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/FileType.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/FileType.java new file mode 100644 index 000000000..ebc432554 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/FileType.java @@ -0,0 +1,31 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class FileType { + + public static final String JPG = "JPG"; + + private static final Map types = new HashMap(){{ + + put( FileType.JPG, ".jpg" ); + + }}; + + public static String getSuffix ( String key ) { + return FileType.types.get( key ); + } + + /** + * 根据给定的文件名,获取其后缀信息 + * @param filename + * @return + */ + public static String getSuffixByFilename ( String filename ) { + + return filename.substring( filename.lastIndexOf( "." ) ).toLowerCase(); + + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java new file mode 100644 index 000000000..d76bb621c --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/MIMEType.java @@ -0,0 +1,20 @@ +package com.iformall.ueditor.define; + +import java.util.HashMap; +import java.util.Map; + +public class MIMEType { + + public static final Map types = new HashMap(){{ + put( "image/gif", ".gif" ); + put( "image/jpeg", ".jpg" ); + put( "image/jpg", ".jpg" ); + put( "image/png", ".png" ); + put( "image/bmp", ".bmp" ); + }}; + + public static String getSuffix ( String mime ) { + return MIMEType.types.get( mime ); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java new file mode 100644 index 000000000..a1799cb2a --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/MultiState.java @@ -0,0 +1,108 @@ +package com.iformall.ueditor.define; + +import com.iformall.ueditor.Encoder; + +import java.util.*; + +/** + * 多状态集合状态 + * 其包含了多个状态的集合, 其本身自己也是一个状态 + * @author hancong03@baidu.com + * + */ +public class MultiState implements State { + + private boolean state = false; + private String info = null; + private Map intMap = new HashMap(); + private Map infoMap = new HashMap(); + private List stateList = new ArrayList(); + + public MultiState ( boolean state ) { + this.state = state; + } + + public MultiState ( boolean state, String info ) { + this.state = state; + this.info = info; + } + + public MultiState ( boolean state, int infoKey ) { + this.state = state; + this.info = AppInfo.getStateInfo( infoKey ); + } + + @Override + public boolean isSuccess() { + return this.state; + } + + public void addState ( State state ) { + stateList.add( state.toJSONString() ); + } + + /** + * 该方法调用无效果 + */ + @Override + public void putInfo(String name, String val) { + this.infoMap.put(name, val); + } + + @Override + public String toJSONString() { + + String stateVal = this.isSuccess() ? AppInfo.getStateInfo( AppInfo.SUCCESS ) : this.info; + + StringBuilder builder = new StringBuilder(); + + builder.append( "{\"state\": \"" + stateVal + "\"" ); + + // 数字转换 + Iterator iterator = this.intMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": " + this.intMap.get( stateVal ) ); + + } + + iterator = this.infoMap.keySet().iterator(); + + while ( iterator.hasNext() ) { + + stateVal = iterator.next(); + + builder.append( ",\""+ stateVal +"\": \"" + this.infoMap.get( stateVal ) + "\"" ); + + } + + builder.append( ", list: [" ); + + + iterator = this.stateList.iterator(); + + while ( iterator.hasNext() ) { + + builder.append( iterator.next() + "," ); + + } + + if ( this.stateList.size() > 0 ) { + builder.deleteCharAt( builder.length() - 1 ); + } + + builder.append( " ]}" ); + + return Encoder.toUnicode( builder.toString() ); + + } + + @Override + public void putInfo(String name, long val) { + this.intMap.put( name, val ); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/State.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/State.java new file mode 100644 index 000000000..1a8ca2d94 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/define/State.java @@ -0,0 +1,18 @@ +package com.iformall.ueditor.define; + +/** + * 处理状态接口 + * @author hancong03@baidu.com + * + */ +public interface State { + + public boolean isSuccess(); + + public void putInfo(String name, String val); + + public void putInfo(String name, long val); + + public String toJSONString(); + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java new file mode 100644 index 000000000..a21590d60 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/hunter/FileManager.java @@ -0,0 +1,111 @@ +package com.iformall.ueditor.hunter; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.MultiState; +import com.iformall.ueditor.define.State; +import org.apache.commons.io.FileUtils; + +import java.io.File; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +public class FileManager { + + private String dir = null; + private String rootPath = null; + private String[] allowFiles = null; + private int count = 0; + + public FileManager(Map conf) { + + this.rootPath = (String) conf.get("rootPath"); + this.dir = this.rootPath + (String) conf.get("dir"); + this.allowFiles = this.getAllowFiles(conf.get("allowFiles")); + this.count = (Integer) conf.get("count"); + + } + + public State listFile(int index) { + + File dir = new File(this.dir); + State state = null; + + if (!dir.exists()) { + return new BaseState(false, AppInfo.NOT_EXIST); + } + + if (!dir.isDirectory()) { + return new BaseState(false, AppInfo.NOT_DIRECTORY); + } + + Collection list = FileUtils.listFiles(dir, this.allowFiles, true); + + if (index < 0 || index > list.size()) { + state = new MultiState(true); + } else { + Object[] fileList = Arrays.copyOfRange(list.toArray(), index, index + this.count); + state = this.getState(fileList); + } + + state.putInfo("start", index); + state.putInfo("total", list.size()); + + return state; + + } + + private State getState(Object[] files) { + + MultiState state = new MultiState(true); + BaseState fileState = null; + + File file = null; + + for (Object obj : files) { + if (obj == null) { + break; + } + file = (File) obj; + fileState = new BaseState(true); + fileState.putInfo("url", PathFormat.format(this.getPath(file))); + state.addState(fileState); + } + + return state; + + } + + private String getPath(File file) { + + String path = file.getAbsolutePath(); + path = PathFormat.format(path); + return path.replace(this.rootPath, "/"); + + } + + private String[] getAllowFiles(Object fileExt) { + + String[] exts = null; + String ext = null; + + if (fileExt == null) { + return new String[0]; + } + + exts = (String[]) fileExt; + + for (int i = 0, len = exts.length; i < len; i++) { + + ext = exts[i]; + exts[i] = ext.replace(".", ""); + + } + + return exts; + + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java new file mode 100644 index 000000000..1cd68ee62 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/hunter/ImageHunter.java @@ -0,0 +1,140 @@ +package com.iformall.ueditor.hunter; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.*; +import com.iformall.ueditor.upload.StorageManager; + +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.URL; +import java.net.UnknownHostException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * 图片抓取器 + * @author hancong03@baidu.com + * + */ +public class ImageHunter { + + private String filename = null; + private String savePath = null; + private String rootPath = null; + private List allowTypes = null; + private long maxSize = -1; + + private List filters = null; + + public ImageHunter ( Map conf ) { + + this.filename = (String)conf.get( "filename" ); + this.savePath = (String)conf.get( "savePath" ); + this.rootPath = (String)conf.get( "rootPath" ); + this.maxSize = (Long)conf.get( "maxSize" ); + this.allowTypes = Arrays.asList( (String[])conf.get( "allowFiles" ) ); + this.filters = Arrays.asList( (String[])conf.get( "filter" ) ); + + } + + public State capture (String[] list ) { + + MultiState state = new MultiState( true ); + + for ( String source : list ) { + state.addState( captureRemoteData( source ) ); + } + + return state; + + } + + public State captureRemoteData ( String urlStr ) { + + HttpURLConnection connection = null; + URL url = null; + String suffix = null; + + try { + url = new URL( urlStr ); + + if ( !validHost( url.getHost() ) ) { + return new BaseState( false, AppInfo.PREVENT_HOST ); + } + + connection = (HttpURLConnection) url.openConnection(); + + connection.setInstanceFollowRedirects( true ); + connection.setUseCaches( true ); + + if ( !validContentState( connection.getResponseCode() ) ) { + return new BaseState( false, AppInfo.CONNECTION_ERROR ); + } + + suffix = MIMEType.getSuffix( connection.getContentType() ); + + if ( !validFileType( suffix ) ) { + return new BaseState( false, AppInfo.NOT_ALLOW_FILE_TYPE ); + } + + if ( !validFileSize( connection.getContentLength() ) ) { + return new BaseState( false, AppInfo.MAX_SIZE ); + } + + String savePath = this.getPath( this.savePath, this.filename, suffix ); + String physicalPath = this.rootPath + savePath; + + State state = StorageManager.saveFileByInputStream( connection.getInputStream(), physicalPath ); + + if ( state.isSuccess() ) { + state.putInfo( "url", PathFormat.format( savePath ) ); + state.putInfo( "source", urlStr ); + } + + return state; + + } catch ( Exception e ) { + return new BaseState( false, AppInfo.REMOTE_FAIL ); + } + + } + + private String getPath ( String savePath, String filename, String suffix ) { + + return PathFormat.parse( savePath + suffix, filename ); + + } + + private boolean validHost ( String hostname ) { + try { + InetAddress ip = InetAddress.getByName(hostname); + + if (ip.isSiteLocalAddress()) { + return false; + } + } catch (UnknownHostException e) { + return false; + } + + return !filters.contains( hostname ); + + } + + private boolean validContentState ( int code ) { + + return HttpURLConnection.HTTP_OK == code; + + } + + private boolean validFileType ( String type ) { + + return this.allowTypes.contains( type ); + + } + + private boolean validFileSize ( int size ) { + return size < this.maxSize; + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java new file mode 100644 index 000000000..27b48b406 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/Base64Uploader.java @@ -0,0 +1,51 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.FileType; +import com.iformall.ueditor.define.State; +import org.apache.commons.codec.binary.Base64; + +import java.util.Map; + +public final class Base64Uploader { + + public static State save(String content, Map conf) { + + byte[] data = decode(content); + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validSize(data, maxSize)) { + return new BaseState(false, AppInfo.MAX_SIZE); + } + + String suffix = FileType.getSuffix("JPG"); + + String savePath = PathFormat.parse((String) conf.get("savePath"), + (String) conf.get("filename")); + + savePath = savePath + suffix; + String physicalPath = (String) conf.get("rootPath") + savePath; + + State storageState = StorageManager.saveBinaryFile(data, physicalPath); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("type", suffix); + storageState.putInfo("original", ""); + } + + return storageState; + } + + private static byte[] decode(String content) { + return Base64.decodeBase64(content); + } + + private static boolean validSize(byte[] data, long length) { + return data.length <= length; + } + +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java new file mode 100644 index 000000000..54e02de8e --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/BinaryUploader.java @@ -0,0 +1,70 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.PathFormat; +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.FileType; +import com.iformall.ueditor.define.State; +import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class BinaryUploader { + + public static final State save(HttpServletRequest request, Map conf) { + if (!ServletFileUpload.isMultipartContent(request)) { + return new BaseState(false, AppInfo.NOT_MULTIPART_CONTENT); + } + + MultipartFile file = ((MultipartHttpServletRequest) request).getFile("upfile"); + try { + if (file == null) { + return new BaseState(false, AppInfo.NOTFOUND_UPLOAD_DATA); + } + + String savePath = (String) conf.get("savePath"); + String originFileName = file.getOriginalFilename(); + String suffix = FileType.getSuffixByFilename(file.getOriginalFilename()); + + originFileName = originFileName.substring(0, + originFileName.length() - suffix.length()); + savePath = savePath + suffix; + + long maxSize = ((Long) conf.get("maxSize")).longValue(); + + if (!validType(suffix, (String[]) conf.get("allowFiles"))) { + return new BaseState(false, AppInfo.NOT_ALLOW_FILE_TYPE); + } + + savePath = PathFormat.parse(savePath, originFileName); + String physicalPath = (String) conf.get("rootPath") + savePath; + + InputStream is = file.getInputStream(); + State storageState = StorageManager.saveFileByInputStream(is, physicalPath, maxSize); + is.close(); + + if (storageState.isSuccess()) { + storageState.putInfo("url", PathFormat.format(savePath)); + storageState.putInfo("local", physicalPath); + storageState.putInfo("type", suffix); + storageState.putInfo("original", originFileName + suffix); + } + return storageState; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static boolean validType(String type, String[] allowTypes) { + List list = Arrays.asList(allowTypes); + + return list.contains(type); + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java new file mode 100644 index 000000000..ca0cdc65b --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/StorageManager.java @@ -0,0 +1,148 @@ +package com.iformall.ueditor.upload; + +import com.iformall.ueditor.define.AppInfo; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import org.apache.commons.io.FileUtils; + +import java.io.*; + +public class StorageManager { + public static final int BUFFER_SIZE = 8192; + + public StorageManager() { + } + + public static State saveBinaryFile(byte[] data, String path) { + File file = new File(path); + + State state = valid(file); + + if (!state.isSuccess()) { + return state; + } + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(file)); + bos.write(data); + bos.flush(); + bos.close(); + } catch (IOException ioe) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true, file.getAbsolutePath()); + state.putInfo("size", data.length); + state.putInfo("title", file.getName()); + return state; + } + + public static State saveFileByInputStream(InputStream is, String path, long maxSize) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[2048]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + if (tmpFile.length() > maxSize) { + tmpFile.delete(); + return new BaseState(false, AppInfo.MAX_SIZE); + } + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + public static State saveFileByInputStream(InputStream is, String path) { + State state = null; + + File tmpFile = getTmpFile(); + + byte[] dataBuf = new byte[2048]; + BufferedInputStream bis = new BufferedInputStream(is, StorageManager.BUFFER_SIZE); + + try { + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(tmpFile), StorageManager.BUFFER_SIZE); + + int count = 0; + while ((count = bis.read(dataBuf)) != -1) { + bos.write(dataBuf, 0, count); + } + bos.flush(); + bos.close(); + + state = saveTmpFile(tmpFile, path); + + if (!state.isSuccess()) { + tmpFile.delete(); + } + + return state; + } catch (IOException e) { + } + return new BaseState(false, AppInfo.IO_ERROR); + } + + private static File getTmpFile() { + File tmpDir = FileUtils.getTempDirectory(); + String tmpFileName = (Math.random() * 10000 + "").replace(".", ""); + return new File(tmpDir, tmpFileName); + } + + private static State saveTmpFile(File tmpFile, String path) { + State state = null; + File targetFile = new File(path); + + if (targetFile.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + try { + FileUtils.moveFile(tmpFile, targetFile); + } catch (IOException e) { + return new BaseState(false, AppInfo.IO_ERROR); + } + + state = new BaseState(true); + state.putInfo("size", targetFile.length()); + state.putInfo("title", targetFile.getName()); + + return state; + } + + private static State valid(File file) { + File parentPath = file.getParentFile(); + + if ((!parentPath.exists()) && (!parentPath.mkdirs())) { + return new BaseState(false, AppInfo.FAILED_CREATE_FILE); + } + + if (!parentPath.canWrite()) { + return new BaseState(false, AppInfo.PERMISSION_DENIED); + } + + return new BaseState(true); + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java new file mode 100644 index 000000000..1e6e33caf --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/ueditor/upload/Uploader.java @@ -0,0 +1,120 @@ +package com.iformall.ueditor.upload; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.amazonaws.AmazonClientException; +import com.amazonaws.AmazonServiceException; +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.iformall.shiro.UserSession; +import com.iformall.ueditor.define.BaseState; +import com.iformall.ueditor.define.State; +import org.apache.shiro.SecurityUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartHttpServletRequest; + +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.net.URL; +import java.util.Map; +import java.util.UUID; + +public class Uploader { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private HttpServletRequest request = null; + private Map conf = null; + private AmazonS3 s3 = null; + + public Uploader(HttpServletRequest request, Map conf) { + this.request = request; + this.conf = conf; + this.s3 = AmazonS3ClientBuilder.standard() + .withRegion(conf.get("clientRegion").toString()) + .withCredentials(new AWSCredentialsProvider() { + @Override + public AWSCredentials getCredentials() { + return new BasicAWSCredentials(conf.get("access").toString(), conf.get("secret").toString()); + } + + @Override + public void refresh() { + + } + }) + .build(); + } + + public final State doExec() { + String filedName = (String) this.conf.get("fieldName"); + State state = null; + + if ("true".equals(this.conf.get("isBase64"))) { + state = Base64Uploader.save(this.request.getParameter(filedName), + this.conf); + } else { + MultipartFile multiReq= ((MultipartHttpServletRequest) this.request).getFile("upfile"); + String tenantId = (String)SecurityUtils.getSubject().getSession().getAttribute(UserSession.tenantId); + + String fileName = UUID.randomUUID().toString(); + int dot = multiReq.getOriginalFilename().lastIndexOf('.'); + if (dot >= 0) { + fileName = tenantId + "/" + fileName + multiReq.getOriginalFilename().substring(dot, multiReq.getOriginalFilename().length()); + } else { + fileName = tenantId + "/" + fileName; + } + + state = state = new BaseState(true); + state.putInfo("size", multiReq.getSize()); + state.putInfo("title", filedName); + + JSONObject stateJson = JSON.parseObject(state.toJSONString()); + + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(multiReq.getContentType()); + metadata.setContentLength(multiReq.getSize()); + + try { + s3.putObject( + new PutObjectRequest(conf.get("bucketName").toString(), fileName, multiReq.getInputStream(), metadata) + .withCannedAcl(CannedAccessControlList.PublicRead)); + URL url = s3.getUrl(conf.get("bucketName").toString(), fileName); + //logger.info(url.toString()); + state.putInfo("url", url.toString()); + } catch (AmazonServiceException ase) { + /* + logger.warn("Caught an AmazonServiceException, which " + + "means your request made it " + + "to Amazon S3, but was rejected with an error response" + + " for some reason."); + logger.warn(ase.getMessage()); + */ + ase.printStackTrace(); + } catch (AmazonClientException ace) { + /* + logger.warn("Caught an AmazonClientException, which " + + "means the client encountered " + + "an internal error while trying to " + + "communicate with S3, " + + "such as not being able to access the network."); + logger.warn("Error Message: " + ace.getMessage()); + */ + ace.printStackTrace(); + } catch (IOException ioe) { + //logger.warn("Caught an IOException: " + ioe.getMessage()); + ioe.printStackTrace(); + } + } + + return state; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/utils/PayUtil.java b/mallinkSysAdmin/src/main/java/com/iformall/utils/PayUtil.java new file mode 100644 index 000000000..9776aad04 --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/utils/PayUtil.java @@ -0,0 +1,37 @@ +package com.iformall.utils; + +import com.google.zxing.BarcodeFormat; +import com.google.zxing.EncodeHintType; +import com.google.zxing.MultiFormatWriter; +import com.google.zxing.WriterException; +import com.google.zxing.common.BitMatrix; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; + +import java.awt.image.BufferedImage; +import java.util.Hashtable; +import java.util.Map; + +public class PayUtil { + /** + * 根据url生成二位图片对象 + * + * @param codeUrl + * @return + * @throws WriterException + */ + public static BufferedImage getQRCodeImge(String codeUrl) throws WriterException { + Map hints = new Hashtable(); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); + hints.put(EncodeHintType.CHARACTER_SET, "UTF8"); + int width = 256; + BitMatrix bitMatrix = (new MultiFormatWriter()).encode(codeUrl, BarcodeFormat.QR_CODE, width, width, hints); + BufferedImage image = new BufferedImage(width, width, 1); + for(int x = 0; x < width; ++x) { + for(int y = 0; y < width; ++y) { + image.setRGB(x, y, bitMatrix.get(x, y) ? -16777216 : -1); + } + } + + return image; + } +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/utils/ShiroUtils.java b/mallinkSysAdmin/src/main/java/com/iformall/utils/ShiroUtils.java new file mode 100644 index 000000000..02b66fc2d --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/utils/ShiroUtils.java @@ -0,0 +1,61 @@ +package com.iformall.utils; + +import com.iformall.common.ErrorCode; +import com.iformall.domain.po.MallUserInfo; +import com.iformall.exception.MallinkException; +import com.iformall.shiro.UserSession; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.Subject; + +/** + * Shiro工具类 + * + * @author stormeye.wu + * @email wugq@mippoint.com + * @date 2016年11月12日 上午9:49:19 + */ +public class ShiroUtils { + + public static Session getSession() { + return SecurityUtils.getSubject().getSession(); + } + + public static Subject getSubject() { + return SecurityUtils.getSubject(); + } + + public static MallUserInfo getUserInfo() { + return (MallUserInfo) SecurityUtils.getSubject().getSession().getAttribute(UserSession.userInfo); + } + + public static Long getUserId() { + return getUserInfo().getId(); + } + + public static void setSessionAttribute(Object key, Object value) { + getSession().setAttribute(key, value); + } + + public static Object getSessionAttribute(Object key) { + return getSession().getAttribute(key); + } + + public static boolean isLogin() { + return SecurityUtils.getSubject().getPrincipal() != null; + } + + public static void logout() { + SecurityUtils.getSubject().logout(); + } + + public static String getKaptcha(String key) { + Object kaptcha = getSessionAttribute(key); + if (kaptcha == null) { + throw new MallinkException(ErrorCode.KAPCHA_NOT_VALID); + } + getSession().removeAttribute(key); + return kaptcha.toString(); + } + +} diff --git a/mallinkSysAdmin/src/main/java/com/iformall/utils/UrlCheck.java b/mallinkSysAdmin/src/main/java/com/iformall/utils/UrlCheck.java new file mode 100644 index 000000000..2a4dcf90a --- /dev/null +++ b/mallinkSysAdmin/src/main/java/com/iformall/utils/UrlCheck.java @@ -0,0 +1,22 @@ +package com.iformall.utils; + +/** + * @author gongbiao + */ +public class UrlCheck { + + public static boolean checkUrl(String url) { + return url.contains("awsFileUpload") + || url.contains("awsFilesUpload") + || url.contains("downQrCode") + || url.contains("cimgUpload") + || url.contains("ueditor/exec") + || url.contains("/wxCUserBasicInfo/importTemplate") + || url.contains("/wxCUserBasicInfo/countByFilter") + || url.contains("/wxCUserBasicInfo/listByFilter") + || url.contains("wxMsgCallback") + || url.contains("notify") + || url.contains("pvlog"); + } + +} diff --git a/mallinkSysAdmin/src/main/resources/application-dev.yml b/mallinkSysAdmin/src/main/resources/application-dev.yml new file mode 100644 index 000000000..7ddbee3c6 --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/application-dev.yml @@ -0,0 +1,128 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://localhost:3306/mallinkDev?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useUnicode=true&useSSL=false&useAffectedRows=true + username: userone + password: wgq2WYJ2018Mb@#$ + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" + #jackson: + #date-format: yyyy-MM-dd HH:mm:ss + # REDIS + redis: + host: 202.165.179.86 + port: 6379 + password: ENC(aYJ3Wr2UWtkORRQjjrWWpz2ZeTISsHOA) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 500 + max-wait: -1 + min-idle: 10 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(lknBjZsA24AaQEXuy0fFw3acd4v4Xsf3CsgDcRZgjlYnNAL9R07d/w==) + password: ENC(gIkVPuYMmJ/EDxry8QIfGumIAk4plAwolGrfg1fiM3U=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # ROCKETMQ + rocketmq: + nameServer: 127.0.0.1:9876 + producer: + retry-times-when-send-async-failed: 0 + send-msg-timeout: 300000 + compress-msg-body-over-howmuch: 4096 + max-message-size: 4194304 + retry-another-broker-when-not-store-ok: false + retry-times-when-send-failed: 2 + # RABBITMQ + rabbitmq: + host: 202.165.179.86 + port: 5672 + username: fumao + password: f8l89&*%%u7f1t22 + publisher-confirms: true + virtual-host: / + flyway: + enabled: true + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(3gx5ghDFBqGrEhO3Wf8aYmXsnwHO7Cj3HNKJGOeUj0o=) + secret: ENC(HVKIJwCJKVXLlUpGlQPwNqJOlnpxn4xYuy91SH0seTSm2uAttIQHvA49fXWWax90v5wloIk0QuU=) + +wechat: + web: + appId: "wxe31beafbfd8295ba" + secret: "c689fabf3c4c9f5b6424ff2a36a26727" + url: "https://mall.youlane.cn" + open: + componentAppId: "wx897e4673286c915d" + componentSecret: "cdfdfda65c45689beb6766c4c427eed2" + componentToken: "formall2018" + componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" + redis: + host: 202.165.179.86 + port: 6379 + password: ENC(aYJ3Wr2UWtkORRQjjrWWpz2ZeTISsHOA) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 500 + max-wait: -1 + min-idle: 10 + +jasypt: + encryptor: + password: oRqdnDbK5pj3eMmB + +fm: + exception: false + exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com,hanxueda@iformall.com + deploy: 1 + open: true + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + tk.mybatis: debug + com.iformall: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/resources/application-prod.yml b/mallinkSysAdmin/src/main/resources/application-prod.yml new file mode 100644 index 000000000..ad957ad0b --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/application-prod.yml @@ -0,0 +1,112 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallink?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true + username: ENC(NUzgQOdJnCbVLKT6BaX0aw==) + password: ENC(mvuoDRiu0jqYaKNRwwTuXZ6U7aoIaqsjdiPqTLgi/nY=) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" + # REDIS + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(8gYU47Fu93NUJPhwPCiPbAT+6VFA1YDx1egK4Z0Nl6w=) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(IiL/PHP9wCkpibWHRH/Mts8K9fh4izYqaiaF66bDrqtEHP+KUcJRRg==) + password: ENC(m7L57m8mk6tApVoa4XIDQnXF0VxnYjKe4LVdzcgb+xY=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: localhost + port: 5672 + username: ENC(lRmLd6EzgeY1RT5ktcHv9g==) + password: ENC(gBI8mCjr3OC0v57jcnSb660Ux7mW03K2oePgvohhg7w=) + publisher-confirms: true + virtual-host: / + flyway: + enabled: true + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(a6SN1sZ1enNL49ypiOXkg/pPPAnZD8H4buQFTTKN08s=) + secret: ENC(5P5ff4bTMJUbXVR4ZsM03UHzOKZ4+Zg5Iutcdkyp/Quny/oXg+A4KpfwEyGarlLu3vQMJahGP5M=) + +wechat: + web: + appId: "wx9cc4ca09eb20fe03" + secret: "af1d7f7a1268022a73cb4ce0b9cf0985" + url: "https://admin.malls.iformall.com" + open: + componentAppId: ENC(b3JG0MUZgQfz5Zj+DC2ZM1zDeLOiGTmmeokfe2O8kaM=) + componentSecret: ENC(QVyc4BPGdnSjXGs2ivgpDBE1v8wPWHLLRMYI7Vv8uYwC0SiZHQz0QpyyQV/b48Pb) + componentToken: ENC(rkxj0733WxFFDLgA9x01m2s5Fi2L+0PC) + componentAesKey: ENC(EIbJUBpbYOrLb4YQ/HXLQmxlxgAqIp2ZmpnGICC8pu5xiTz3Cqfkbwd2S8raCcK/IvYcX2GmedI=) + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(8gYU47Fu93NUJPhwPCiPbAT+6VFA1YDx1egK4Z0Nl6w=) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com,hanxueda@iformall.com + deploy: 3 + open: true + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + tk.mybatis: debug + com.iformall.mapper: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/resources/application-test.yml b/mallinkSysAdmin/src/main/resources/application-test.yml new file mode 100644 index 000000000..574e7844f --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/application-test.yml @@ -0,0 +1,112 @@ +spring: + profiles: + include: rabbitMQ + # JDBC + datasource: + url: jdbc:mysql://formalldb.cfqyqflkdlit.rds.cn-northwest-1.amazonaws.com.cn:3306/mallinkTest?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false&useAffectedRows=true + username: ENC(Uc0AjgkytxHHCwZrmDASWg==) + password: ENC(nV4Mi3bEbBx0Fj7uUyYH55eTaqsFMjKvmNzagicH4pc=) + type: com.alibaba.druid.pool.DruidDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + filters: stat + maxActive: 20 + initialSize: 1 + maxWait: 60000 + minIdle: 1 + timeBetweenEvictionRunsMillis: 28000 + minEvictableIdleTimeMillis: 28000 + validationQuery: select 'x' + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + poolPreparedStatements: true + maxOpenPreparedStatements: 20 + connectionProperties: "druid.stat.mergeSql=true;druid.stat.slowSqlMillis=6000" + # REDIS + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 1 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 20 + max-wait: -1 + min-idle: 0 + # EMAIL + mail: + host: smtp.exmail.qq.com + username: ENC(TtJQE2C4cWo8CpVGMMl5hiy5eykepd96J5XjsW3Kj5fgP+6+5ctDNQ==) + password: ENC(Zh6A6kRtA2ABtH6nzdvsqQSO1/8p3mparJr8neI2BLU=) # 授权密码 + properties: + mail: + smtp: + auth: true + starttls: + enable: true + socketFactory: + port: 465 + class: javax.net.ssl.SSLSocketFactory + # RABBITMQ + rabbitmq: + host: 127.0.0.1 + port: 5672 + username: ENC(aSRr6mnSryEqzHHz1hJf1g==) + password: ENC(GnjF/mdqKdvmDYC0tIIso7+20/jBALPw39tiWCYJ4iw=) + publisher-confirms: true + virtual-host: / + flyway: + enabled: true + +aws: + clientRegion: cn-northwest-1 + bucketName: iformall-net + access: ENC(NCLcmjwKpAWdn/abD17OKIY7yKepVLWzEpqRYUlURCw=) + secret: ENC(TRcZqql0Rq5PExlMeH/4WiZ/i02b8FXKmLTBChJmbluTa1uoLS9LrHyNEMrqe1DK+QgOAdvqGBo=) + +wechat: + web: + appId: "wx091907dd0bfd3f6b" + secret: "2a2ca10738998b9ef92c1fe8a4d366a6" + url: "https://admintest.malls.iformall.com" + open: + componentAppId: ENC(hnH31XdNzArfMfikKgBFpqQuJUl6rVOPFFcAVyb595o=) + componentSecret: ENC(t/GUVX5L+U7LCwSvZ5WmxAnmTMrc/Uy1nljsrokuzzsBL2j6BEVnrS/n7DCdGc/G) + componentToken: ENC(gUF1m0YgCCI2IY54fX6sGLZVlCswA8tG) + componentAesKey: ENC(TYHcrIkICtfrCfGq4HW6s1b/pHf7OD2uyPN11SzJNB0acqJ/4JVX1nuljo/cAtgMG4O05TImLQc=) + redis: + host: 127.0.0.1 + port: 6379 + password: ENC(QFwqv3NshvvGhFPiP8rwhvbnxk+rFSqhJi8Pw6TogSg=) + timeout: 3600 + expire: 1800 #30分钟 + database: 2 + defaultExpiration: 2592000 # 默认生命周期30天 + jedis: + pool: + max-active: 100 + max-idle: 100 + max-wait: -1 + min-idle: 10 + +fm: + exception: true + exception_emails: hupeng@iformall.com,wuguoqiang@iformall.com,gongbiao@iformall.com,luozukai@iformall.com,hanxueda@iformall.com + deploy: 2 + open: true + +ueditor: + config: config.json + unified: true + upload-path: ./upload/ + url-prefix: "" + +logging: + level: + tk.mybatis: debug + com.iformall: debug + path: ./logs/admin \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/resources/application.yml b/mallinkSysAdmin/src/main/resources/application.yml new file mode 100644 index 000000000..f9c2f4778 --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/application.yml @@ -0,0 +1,80 @@ +server: + port: 9900 + servlet: + context-path: / + +spring: + application: + name: mallink + profiles: + active: dev + jackson: + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + default-property-inclusion: non_null + servlet: + multipart: + max-file-size: 2MB + max-request-size: 2MB + cache: + type: REDIS + cache-names: redis_cache #缓存的名字(可以不指定) + redis: + time-to-live: 60000ms #很重要,缓存的有效时间,以便缓存的过期(单位为毫秒) + rocketmq: + nameServer: 202.165.179.86:9876 + producer: + retry-times-when-send-async-failed: 0 + send-msg-timeout: 300000 + compress-msg-body-over-howmuch: 4096 + max-message-size: 4194304 + retry-another-broker-when-not-store-ok: false + retry-times-when-send-failed: 2 + rabbitmq: + host: 202.165.179.86 + port: 5672 + username: guest + password: guest + publisher-confirms: true + virtual-host: / + # FLOWABLE + flowable: + async-executor-activate: false + aop: + proxy-target-class: true + auto: true + flyway: + locations: classpath:/db/migration + baseline-on-migrate: true + baseline-version: 1 + + +# @{link} https://github.com/abel533 +#Mybatis +mybatis: + type-aliases-package: com.iformall.domain.po + mapper-locations: classpath:mapper/*Mapper.xml + configuration: + map-underscore-to-camel-case: true + cache-enabled: true + lazy-loading-enabled: true + use-generated-keys: true + default-fetch-size: 100 + default-statement-timeout: 10 + + +#PageHelper +pagehelper: + helperDialect: mysql + reasonable: false + supportMethodsArguments: true + params: count=countSql + offset-as-page-num: true + page-size-zero: true + row-bounds-with-count: true + +mapper: + mappers: + - com.iformall.common.CommonMapper + +version: @project.version@ diff --git a/mallinkSysAdmin/src/main/resources/config.json b/mallinkSysAdmin/src/main/resources/config.json new file mode 100644 index 000000000..f8062cf66 --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/config.json @@ -0,0 +1,94 @@ +/* 前后端通信相关的配置,注释只允许使用多行方式 */ +{ + /* 上传图片配置项 */ + "imageActionName": "uploadimage", /* 执行上传图片的action名称 */ + "imageFieldName": "upfile", /* 提交的图片表单名称 */ + "imageMaxSize": 2048000, /* 上传大小限制,单位B */ + "imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */ + "imageCompressEnable": true, /* 是否压缩图片,默认是true */ + "imageCompressBorder": 1600, /* 图片压缩最长边限制 */ + "imageInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageUrlPrefix": "", /* 图片访问路径前缀 */ + "imagePathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */ + /* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */ + /* {time} 会替换成时间戳 */ + /* {yyyy} 会替换成四位年份 */ + /* {yy} 会替换成两位年份 */ + /* {mm} 会替换成两位月份 */ + /* {dd} 会替换成两位日期 */ + /* {hh} 会替换成两位小时 */ + /* {ii} 会替换成两位分钟 */ + /* {ss} 会替换成两位秒 */ + /* 非法字符 \ : * ? " < > | */ + /* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */ + + /* 涂鸦图片上传配置项 */ + "scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */ + "scrawlFieldName": "upfile", /* 提交的图片表单名称 */ + "scrawlPathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "scrawlMaxSize": 2048000, /* 上传大小限制,单位B */ + "scrawlUrlPrefix": "", /* 图片访问路径前缀 */ + "scrawlInsertAlign": "none", + + /* 截图工具上传 */ + "snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */ + "snapscreenPathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "snapscreenUrlPrefix": "", /* 图片访问路径前缀 */ + "snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */ + + /* 抓取远程图片配置 */ + "catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"], + "catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */ + "catcherFieldName": "source", /* 提交的图片列表表单名称 */ + "catcherPathFormat": "/ueditor/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "catcherUrlPrefix": "", /* 图片访问路径前缀 */ + "catcherMaxSize": 2048000, /* 上传大小限制,单位B */ + "catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */ + + /* 上传视频配置 */ + "videoActionName": "uploadvideo", /* 执行上传视频的action名称 */ + "videoFieldName": "upfile", /* 提交的视频表单名称 */ + "videoPathFormat": "/ueditor/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "videoUrlPrefix": "", /* 视频访问路径前缀 */ + "videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */ + "videoAllowFiles": [ + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */ + + /* 上传文件配置 */ + "fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */ + "fileFieldName": "upfile", /* 提交的文件表单名称 */ + "filePathFormat": "/ueditor/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */ + "fileUrlPrefix": "", /* 文件访问路径前缀 */ + "fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */ + "fileAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ], /* 上传文件格式显示 */ + + /* 列出指定目录下的图片 */ + "imageManagerActionName": "listimage", /* 执行图片管理的action名称 */ + "imageManagerListPath": "/ueditor/image/", /* 指定要列出图片的目录 */ + "imageManagerListSize": 20, /* 每次列出文件数量 */ + "imageManagerUrlPrefix": "", /* 图片访问路径前缀 */ + "imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */ + "imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */ + + /* 列出指定目录下的文件 */ + "fileManagerActionName": "listfile", /* 执行文件管理的action名称 */ + "fileManagerListPath": "/ueditor/file/", /* 指定要列出文件的目录 */ + "fileManagerUrlPrefix": "", /* 文件访问路径前缀 */ + "fileManagerListSize": 20, /* 每次列出文件数量 */ + "fileManagerAllowFiles": [ + ".png", ".jpg", ".jpeg", ".gif", ".bmp", + ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg", + ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid", + ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso", + ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml" + ] /* 列出的文件类型 */ + +} \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/resources/logback-spring.xml b/mallinkSysAdmin/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..2525413f1 --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/logback-spring.xml @@ -0,0 +1,100 @@ + + + + + + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] --%mdc{client}%msg%n + + + + + ${logPath}/trace.log + + ${logPath}/daily/trace.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + + + ${logPath}/info.log + + ${logPath}/daily/info.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + INFO + ACCEPT + DENY + + + + + ${logPath}/debug.log + + ${logPath}/daily/debug.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + DEBUG + ACCEPT + DENY + + + + + + ${logPath}/warn.log + + ${logPath}/daily/warn.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + WARN + ACCEPT + DENY + + + + + + + ${logPath}/error.log + + ${logPath}/daily/error.%d{yyyy-MM-dd}.log + 180 + + + [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] [%logger:%line]--%mdc{client} %msg%n + + + ERROR + ACCEPT + DENY + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/resources/processes/contractflow.bpmn20.xml b/mallinkSysAdmin/src/main/resources/processes/contractflow.bpmn20.xml new file mode 100644 index 000000000..fb90dd9d6 --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/processes/contractflow.bpmn20.xml @@ -0,0 +1,50 @@ + + + + 合同审批流程 + + + 初审 + + + + + + + 复审 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/resources/processes/endBillflow.bpmn20.xml b/mallinkSysAdmin/src/main/resources/processes/endBillflow.bpmn20.xml new file mode 100644 index 000000000..e44520472 --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/processes/endBillflow.bpmn20.xml @@ -0,0 +1,45 @@ + + + + 账单审批流程 + + + 初审 + + + + + + + 复审 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mallinkSysAdmin/src/main/resources/processes/endContractflow.bpmn20.xml b/mallinkSysAdmin/src/main/resources/processes/endContractflow.bpmn20.xml new file mode 100644 index 000000000..9fe8beae0 --- /dev/null +++ b/mallinkSysAdmin/src/main/resources/processes/endContractflow.bpmn20.xml @@ -0,0 +1,45 @@ + + + + 终止合同审批流程 + + + 初审 + + + + + + + 复审 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1b82c52bc..c499ddd45 100644 --- a/pom.xml +++ b/pom.xml @@ -15,6 +15,7 @@ mallinkService mallinkCallback mallinkAdmin + mallinkSysAdmin mallinkCApi mallinkBApi mallinkSchedule