Commit dd8c5a5e by tangyi

多租户

parent 47c7fba0
Version v3.0.0 (2019-6-9)
--------------------------
新功能:
* 支持多租户,增加租户中心->单位管理,表结构增加tenant_code字段
* 增加登录日志
* 增加controller层的参数校验逻辑
* 用户管理增加重置密码功能
改进:
* 调整后台管理的按钮样式
* 调整认证逻辑、token加入租户标识
* 前台、后台的网关地址可通过环境变量配置
* 方法鉴权优化
* 调整系统架构图
* 优化终端管理的授权范围和授权类型
* 统一前后台的eslint,解决启动报的语法错误问题
Bug修复:
* 修复查看错题时错题不标红的bug
* 修复swagger文档显示不了的问题
* 修复开始答题报错问题
* 修复注册失败的bug
...@@ -4,7 +4,11 @@ ...@@ -4,7 +4,11 @@
- 在线体验-后台:[http://www.it99.club:81](http://www.it99.club:81) - 在线体验-后台:[http://www.it99.club:81](http://www.it99.club:81)
交流QQ群:996208878 交流QQ群:
<a target="_blank" href="https://jq.qq.com/?_wv=1027&k=5RKZNF2"><img border="0" src="http://pub.idqqimg.com/wpa/images/group.png" alt="Spring Cloud考试系统学习" title="Spring Cloud考试系统学习"></a>
群号:996208878
如果您觉得有帮助,请点右上角 "Star" 或者项目底部的“捐助”支持一下,谢谢! 如果您觉得有帮助,请点右上角 "Star" 或者项目底部的“捐助”支持一下,谢谢!
...@@ -26,6 +30,8 @@ ...@@ -26,6 +30,8 @@
默认账号: 默认账号:
单位ID:gitee
1. 管理员:admin/123456 1. 管理员:admin/123456
2. 学生:student/123456 2. 学生:student/123456
3. 教师:teacher/123456 3. 教师:teacher/123456
...@@ -59,7 +65,7 @@ ...@@ -59,7 +65,7 @@
## 系统架构 ## 系统架构
![image](doc/产品设计/系统架构图.png) ![image](doc/产品设计/系统架构图v3.0.jpg)
## 功能概述 ## 功能概述
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>common-core</artifactId> <artifactId>common-core</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
...@@ -101,5 +101,17 @@ ...@@ -101,5 +101,17 @@
<artifactId>jasypt-spring-boot-starter</artifactId> <artifactId>jasypt-spring-boot-starter</artifactId>
<version>${jasypt.version}</version> <version>${jasypt.version}</version>
</dependency> </dependency>
<!-- hibernate-validator参数校验 -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<!-- security -->
<dependency>
<groupId>com.github.tangyi</groupId>
<artifactId>common-security</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>
package com.github.tangyi.common.core.cache;
import org.springframework.dao.PessimisticLockingFailureException;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.types.Expiration;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collections;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* 源码:org.springframework.data.redis.cache.DefaultRedisCacheWriter
*
* @author tangyi
* @date 2019/6/9 15:28
*/
public class CustomRedisCacheWriter implements RedisCacheWriter {
private final RedisConnectionFactory connectionFactory;
private final Duration sleepTime;
/**
* @param connectionFactory must not be {@literal null}.
*/
public CustomRedisCacheWriter(RedisConnectionFactory connectionFactory) {
this(connectionFactory, Duration.ZERO);
}
/**
* @param connectionFactory must not be {@literal null}.
* @param sleepTime sleep time between lock request attempts. Must not be {@literal null}. Use {@link Duration#ZERO}
* to disable locking.
*/
public CustomRedisCacheWriter(RedisConnectionFactory connectionFactory, Duration sleepTime) {
Assert.notNull(connectionFactory, "ConnectionFactory must not be null!");
Assert.notNull(sleepTime, "SleepTime must not be null!");
this.connectionFactory = connectionFactory;
this.sleepTime = sleepTime;
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.cache.RedisCacheWriter#put(java.lang.String, byte[], byte[], java.time.Duration)
*/
@Override
public void put(String name, byte[] key, byte[] value, @Nullable Duration ttl) {
Assert.notNull(name, "Name must not be null!");
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
execute(name, connection -> {
if (shouldExpireWithin(ttl)) {
connection.set(key, value, Expiration.from(ttl.toMillis(), TimeUnit.MILLISECONDS), RedisStringCommands.SetOption.upsert());
} else {
connection.set(key, value);
}
return "OK";
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.cache.RedisCacheWriter#get(java.lang.String, byte[])
*/
@Override
public byte[] get(String name, byte[] key) {
Assert.notNull(name, "Name must not be null!");
Assert.notNull(key, "Key must not be null!");
return execute(name, connection -> connection.get(key));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.cache.RedisCacheWriter#putIfAbsent(java.lang.String, byte[], byte[], java.time.Duration)
*/
@Override
public byte[] putIfAbsent(String name, byte[] key, byte[] value, @Nullable Duration ttl) {
Assert.notNull(name, "Name must not be null!");
Assert.notNull(key, "Key must not be null!");
Assert.notNull(value, "Value must not be null!");
return execute(name, connection -> {
if (isLockingCacheWriter()) {
doLock(name, connection);
}
try {
if (connection.setNX(key, value)) {
if (shouldExpireWithin(ttl)) {
connection.pExpire(key, ttl.toMillis());
}
return null;
}
return connection.get(key);
} finally {
if (isLockingCacheWriter()) {
doUnlock(name, connection);
}
}
});
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.cache.RedisCacheWriter#remove(java.lang.String, byte[])
*/
@Override
public void remove(String name, byte[] key) {
Assert.notNull(name, "Name must not be null!");
Assert.notNull(key, "Key must not be null!");
execute(name, connection -> connection.del(key));
}
/*
* (non-Javadoc)
* @see org.springframework.data.redis.cache.RedisCacheWriter#clean(java.lang.String, byte[])
*/
@Override
public void clean(String name, byte[] pattern) {
Assert.notNull(name, "Name must not be null!");
Assert.notNull(pattern, "Pattern must not be null!");
execute(name, connection -> {
boolean wasLocked = false;
try {
if (isLockingCacheWriter()) {
doLock(name, connection);
wasLocked = true;
}
byte[][] keys = Optional.ofNullable(connection.keys(pattern)).orElse(Collections.emptySet())
.toArray(new byte[0][]);
if (keys.length > 0) {
connection.del(keys);
}
} finally {
if (wasLocked && isLockingCacheWriter()) {
doUnlock(name, connection);
}
}
return "OK";
});
}
/**
* Explicitly set a write lock on a cache.
*
* @param name the name of the cache to lock.
*/
void lock(String name) {
execute(name, connection -> doLock(name, connection));
}
/**
* Explicitly remove a write lock from a cache.
*
* @param name the name of the cache to unlock.
*/
void unlock(String name) {
executeLockFree(connection -> doUnlock(name, connection));
}
private Boolean doLock(String name, RedisConnection connection) {
return connection.setNX(createCacheLockKey(name), new byte[0]);
}
private Long doUnlock(String name, RedisConnection connection) {
return connection.del(createCacheLockKey(name));
}
boolean doCheckLock(String name, RedisConnection connection) {
return connection.exists(createCacheLockKey(name));
}
/**
* @return {@literal true} if {@link RedisCacheWriter} uses locks.
*/
private boolean isLockingCacheWriter() {
return !sleepTime.isZero() && !sleepTime.isNegative();
}
private <T> T execute(String name, Function<RedisConnection, T> callback) {
RedisConnection connection = connectionFactory.getConnection();
try {
checkAndPotentiallyWaitUntilUnlocked(name, connection);
return callback.apply(connection);
} finally {
connection.close();
}
}
private void executeLockFree(Consumer<RedisConnection> callback) {
RedisConnection connection = connectionFactory.getConnection();
try {
callback.accept(connection);
} finally {
connection.close();
}
}
private void checkAndPotentiallyWaitUntilUnlocked(String name, RedisConnection connection) {
if (!isLockingCacheWriter()) {
return;
}
try {
while (doCheckLock(name, connection)) {
Thread.sleep(sleepTime.toMillis());
}
} catch (InterruptedException ex) {
// Re-interrupt current thread, to allow other participants to react.
Thread.currentThread().interrupt();
throw new PessimisticLockingFailureException(String.format("Interrupted while waiting to unlock cache %s", name),
ex);
}
}
private static boolean shouldExpireWithin(@Nullable Duration ttl) {
return ttl != null && !ttl.isZero() && !ttl.isNegative();
}
private static byte[] createCacheLockKey(String name) {
return (name + "~lock").getBytes(StandardCharsets.UTF_8);
}
}
package com.github.tangyi.common.core.cache;
import com.github.tangyi.common.core.utils.SysUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import java.util.Map;
/**
* 扩展CacheManager支持多租户
*
* @author tangyi
* @date 2019/6/9 15:12
*/
@Slf4j
public class MultitenantCacheManager extends RedisCacheManager {
public MultitenantCacheManager(RedisCacheWriter cacheWriter, RedisCacheConfiguration defaultCacheConfiguration,
Map<String, RedisCacheConfiguration> initialCacheConfigurations, boolean allowInFlightCacheCreation) {
super(cacheWriter, defaultCacheConfiguration, initialCacheConfigurations, allowInFlightCacheCreation);
}
/**
* 扩展cache name,加上tenantCode作为前缀
*
* @param name name
* @return Cache
*/
@Override
public Cache getCache(String name) {
name = SysUtil.getTenantCode() + ":" + name;
log.info("cache name: {}", name);
return super.getCache(name);
}
}
package com.github.tangyi.common.core.config; package com.github.tangyi.common.core.config;
import com.github.tangyi.common.core.cache.CustomRedisCacheWriter;
import com.github.tangyi.common.core.cache.MultitenantCacheManager;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*; import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.util.LinkedHashMap;
import java.util.Map;
/** /**
* redis配置 * redis配置
* *
...@@ -32,6 +40,19 @@ public class RedisConfig { ...@@ -32,6 +40,19 @@ public class RedisConfig {
return redisTemplate; return redisTemplate;
} }
/**
* 多租户cacheManager
*
* @return RedisCacheManager
*/
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheWriter redisCacheWriter = new CustomRedisCacheWriter(connectionFactory);
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig();
Map<String, RedisCacheConfiguration> initialCacheConfigurations = new LinkedHashMap<>();
return new MultitenantCacheManager(redisCacheWriter, redisCacheConfiguration, initialCacheConfigurations, true);
}
@Bean @Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) { public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash(); return redisTemplate.opsForHash();
......
...@@ -16,7 +16,12 @@ public class CommonConstant { ...@@ -16,7 +16,12 @@ public class CommonConstant {
/** /**
* 默认租户编号 * 默认租户编号
*/ */
public static final String TENANT_CODE = "GITHUB"; public static final String DEFAULT_TENANT_CODE = "gitee";
/**
* 租户编号
*/
public static final String TENANT_CODE = "tenantCode";
/** /**
* JSON 资源 * JSON 资源
...@@ -148,5 +153,10 @@ public class CommonConstant { ...@@ -148,5 +153,10 @@ public class CommonConstant {
*/ */
public static final String AUTHORIZATION_BEARER = "Bearer "; public static final String AUTHORIZATION_BEARER = "Bearer ";
/**
* 密码类型
*/
public static final String GRANT_TYPE_PASSWORD = "password";
} }
package com.github.tangyi.common.core.exceptions;
/**
* token非法异常
*
* @author tangyi
* @date 2019/5/27 17:52
*/
public class InvalidAccessTokenException extends CommonException {
private static final long serialVersionUID = -7285211528095468156L;
public InvalidAccessTokenException() {
}
public InvalidAccessTokenException(String msg) {
super(msg);
}
}
package com.github.tangyi.common.core.exceptions;
/**
* 租户不存在异常
*
* @author tangyi
* @date 2019/5/26 10:14
*/
public class TenantNotFoundException extends CommonException {
private static final long serialVersionUID = -7285211528095468156L;
public TenantNotFoundException() {
}
public TenantNotFoundException(String msg) {
super(msg);
}
}
...@@ -3,6 +3,8 @@ package com.github.tangyi.common.core.model; ...@@ -3,6 +3,8 @@ package com.github.tangyi.common.core.model;
import com.github.tangyi.common.core.persistence.BaseEntity; import com.github.tangyi.common.core.persistence.BaseEntity;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotBlank;
/** /**
* 日志 * 日志
* *
...@@ -15,11 +17,13 @@ public class Log extends BaseEntity<Log> { ...@@ -15,11 +17,13 @@ public class Log extends BaseEntity<Log> {
/** /**
* 日志类型 * 日志类型
*/ */
@NotBlank(message = "日志类型不能为空")
private String type; private String type;
/** /**
* 日志标题 * 日志标题
*/ */
@NotBlank(message = "日志标题不能为空")
private String title; private String title;
/** /**
......
...@@ -3,6 +3,8 @@ package com.github.tangyi.common.core.model; ...@@ -3,6 +3,8 @@ package com.github.tangyi.common.core.model;
import com.github.tangyi.common.core.persistence.BaseEntity; import com.github.tangyi.common.core.persistence.BaseEntity;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotBlank;
/** /**
* 路由信息 * 路由信息
* *
...@@ -15,6 +17,7 @@ public class Route extends BaseEntity<Route> { ...@@ -15,6 +17,7 @@ public class Route extends BaseEntity<Route> {
/** /**
* 路由ID * 路由ID
*/ */
@NotBlank(message = "路由id不能为空")
private String routeId; private String routeId;
/** /**
...@@ -35,6 +38,7 @@ public class Route extends BaseEntity<Route> { ...@@ -35,6 +38,7 @@ public class Route extends BaseEntity<Route> {
/** /**
* URI * URI
*/ */
@NotBlank(message = "路由URI不能为空")
private String uri; private String uri;
/** /**
...@@ -45,5 +49,6 @@ public class Route extends BaseEntity<Route> { ...@@ -45,5 +49,6 @@ public class Route extends BaseEntity<Route> {
/** /**
* 启用禁用 * 启用禁用
*/ */
@NotBlank(message = "路由状态不能为空")
private String status; private String status;
} }
...@@ -3,6 +3,7 @@ package com.github.tangyi.common.core.persistence; ...@@ -3,6 +3,7 @@ package com.github.tangyi.common.core.persistence;
import com.github.tangyi.common.core.constant.CommonConstant; import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.utils.DateUtils; import com.github.tangyi.common.core.utils.DateUtils;
import com.github.tangyi.common.core.utils.IdGen; import com.github.tangyi.common.core.utils.IdGen;
import com.github.tangyi.common.core.utils.SysUtil;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
...@@ -95,7 +96,7 @@ public class BaseEntity<T> implements Serializable { ...@@ -95,7 +96,7 @@ public class BaseEntity<T> implements Serializable {
* @param applicationCode 系统编号 * @param applicationCode 系统编号
*/ */
public void setCommonValue(String userCode, String applicationCode) { public void setCommonValue(String userCode, String applicationCode) {
setCommonValue(userCode, applicationCode, ""); setCommonValue(userCode, applicationCode, SysUtil.getTenantCode());
} }
/** /**
......
package com.github.tangyi.common.core.persistence; package com.github.tangyi.common.core.persistence;
import com.github.tangyi.common.core.persistence.BaseEntity;
import lombok.Data; import lombok.Data;
import java.util.ArrayList; import java.util.ArrayList;
......
package com.github.tangyi.common.core.tenant;
/**
* ThreadLocal保存租户code
*
* @author tangyi
* @date 2019/5/28 20:54
*/
public class TenantContextHolder {
private static final ThreadLocal<String> CONTEXT = new ThreadLocal<>();
public static void setTenantCode(String tenantCode) {
CONTEXT.set(tenantCode);
}
public static String getTenantCode() {
return CONTEXT.get();
}
public static void clear() {
CONTEXT.remove();
}
}
package com.github.tangyi.common.core.utils; package com.github.tangyi.common.core.utils;
import com.github.tangyi.common.core.constant.CommonConstant; import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.security.Principal;
/** /**
* 系统工具类 * 系统工具类
...@@ -8,20 +22,23 @@ import com.github.tangyi.common.core.constant.CommonConstant; ...@@ -8,20 +22,23 @@ import com.github.tangyi.common.core.constant.CommonConstant;
* @author tangyi * @author tangyi
* @date 2018-09-13 20:50 * @date 2018-09-13 20:50
*/ */
@Slf4j
public class SysUtil { public class SysUtil {
private static final String KEY_USER = "user";
private static final String BASIC_ = "Basic ";
/** /**
* 从thread local 获取用户名 * 获取当前登录的用户名
* *
* @return 用户名 * @return String
* @author tangyi
* @date 2019/03/17 11:46
*/ */
public static String getUser() { public static String getUser() {
return null; Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails)
return ((UserDetails) principal).getUsername();
if (principal instanceof Principal)
return ((Principal) principal).getName();
return String.valueOf(principal);
} }
/** /**
...@@ -39,6 +56,41 @@ public class SysUtil { ...@@ -39,6 +56,41 @@ public class SysUtil {
* @return String * @return String
*/ */
public static String getTenantCode() { public static String getTenantCode() {
return CommonConstant.TENANT_CODE; String tenantCode = TenantContextHolder.getTenantCode();
if (StringUtils.isBlank(tenantCode))
tenantCode = getCurrentUserTenantCode();
if (StringUtils.isBlank(tenantCode))
tenantCode = CommonConstant.DEFAULT_TENANT_CODE;
log.debug("租户code:{}", tenantCode);
return tenantCode;
}
/**
* 获取当前登录的租户code
*
* @return String
*/
private static String getCurrentUserTenantCode() {
String tenantCode = "";
try {
ResourceServerTokenServices resourceServerTokenServices = SpringContextHolder.getApplicationContext().getBean(ResourceServerTokenServices.class);
Object details = SecurityContextHolder.getContext().getAuthentication().getDetails();
if (details instanceof OAuth2AuthenticationDetails) {
OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) details;
OAuth2AccessToken oAuth2AccessToken = resourceServerTokenServices.readAccessToken(oAuth2AuthenticationDetails.getTokenValue());
Object tenantObj = oAuth2AccessToken.getAdditionalInformation().get(CommonConstant.TENANT_CODE);
tenantCode = tenantObj == null ? "" : tenantObj.toString();
} else if (details instanceof WebAuthenticationDetails) {
// 未认证
Object requestObj = RequestContextHolder.getRequestAttributes();
if (requestObj != null) {
HttpServletRequest request = ((ServletRequestAttributes) requestObj).getRequest();
tenantCode = request.getParameter(CommonConstant.TENANT_CODE);
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return tenantCode;
} }
} }
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>common-feign</artifactId> <artifactId>common-feign</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>common-log</artifactId> <artifactId>common-log</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<description>日志公共依赖</description> <description>日志公共依赖</description>
......
...@@ -5,7 +5,6 @@ import com.github.tangyi.common.core.utils.SysUtil; ...@@ -5,7 +5,6 @@ import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.log.event.LogEvent; import com.github.tangyi.common.log.event.LogEvent;
import com.github.tangyi.common.log.utils.LogUtil; import com.github.tangyi.common.log.utils.LogUtil;
import com.github.tangyi.common.security.utils.SecurityUtil;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
...@@ -35,7 +34,7 @@ public class LogAspect { ...@@ -35,7 +34,7 @@ public class LogAspect {
Object obj = point.proceed(); Object obj = point.proceed();
Long endTime = System.currentTimeMillis(); Long endTime = System.currentTimeMillis();
logVo.setTime(String.valueOf(endTime - startTime)); logVo.setTime(String.valueOf(endTime - startTime));
logVo.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); logVo.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode());
SpringContextHolder.publishEvent(new LogEvent(logVo)); SpringContextHolder.publishEvent(new LogEvent(logVo));
return obj; return obj;
} }
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>common-security</artifactId> <artifactId>common-security</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<description>security公共依赖</description> <description>security公共依赖</description>
<dependencies> <dependencies>
<!-- 单点登录 --> <!-- 单点登录 -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId> <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
...@@ -12,31 +12,16 @@ public class SecurityConstant { ...@@ -12,31 +12,16 @@ public class SecurityConstant {
public static final String BASE_ROLE = "role_user"; public static final String BASE_ROLE = "role_user";
/** /**
* 管理员角色 * 超级管理员角色
*/ */
public static final String ROLE_ADMIN = "role_admin"; public static final String ROLE_ADMIN = "role_admin";
/** /**
* 老师角色
*/
public static final String ROLE_TEACHER = "role_teacher";
/**
* token
*/
public static final String TOKEN_USER_DETAIL = "token-user-detail";
/**
* 默认生成图形验证码过期时间 * 默认生成图形验证码过期时间
*/ */
public static final int DEFAULT_IMAGE_EXPIRE = 60; public static final int DEFAULT_IMAGE_EXPIRE = 60;
/** /**
* oauth 客户端信息
*/
public static final String CLIENT_DETAILS_KEY = "exam_oauth:client:details";
/**
* 正常状态 * 正常状态
*/ */
public static final String NORMAL = "0"; public static final String NORMAL = "0";
......
package com.github.tangyi.common.security.core; package com.github.tangyi.common.security.core;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
...@@ -12,6 +13,7 @@ import java.util.Set; ...@@ -12,6 +13,7 @@ import java.util.Set;
* @author tangyi * @author tangyi
* @date 2019/3/17 14:37 * @date 2019/3/17 14:37
*/ */
@Data
public class UserDetailsImpl implements UserDetails { public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = -6509897037222767090L; private static final long serialVersionUID = -6509897037222767090L;
...@@ -36,7 +38,13 @@ public class UserDetailsImpl implements UserDetails { ...@@ -36,7 +38,13 @@ public class UserDetailsImpl implements UserDetails {
*/ */
private String status; private String status;
public UserDetailsImpl(String username, String password, String status, Set<GrantedAuthority> authorities) { /**
* 租户标识
*/
private String tenantCode;
public UserDetailsImpl(String tenantCode, String username, String password, String status, Set<GrantedAuthority> authorities) {
this.tenantCode = tenantCode;
this.authorities = authorities; this.authorities = authorities;
this.username = username; this.username = username;
this.password = password; this.password = password;
......
package com.github.tangyi.common.security.utils; package com.github.tangyi.common.security.utils;
import com.github.tangyi.common.security.core.UserDetailsImpl;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
...@@ -15,6 +16,18 @@ import java.security.Principal; ...@@ -15,6 +16,18 @@ import java.security.Principal;
public class SecurityUtil { public class SecurityUtil {
/** /**
* 获取当前用户的租户标识
*
* @return String
* @author tangyi
* @date 2019/05/25 14:19
*/
public static String getCurrentUserTenantCode() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return principal instanceof UserDetails ? ((UserDetailsImpl) principal).getTenantCode() : "";
}
/**
* 获取当前登录的用户名 * 获取当前登录的用户名
* *
* @return String * @return String
...@@ -28,7 +41,6 @@ public class SecurityUtil { ...@@ -28,7 +41,6 @@ public class SecurityUtil {
if (principal instanceof Principal) if (principal instanceof Principal)
return ((Principal) principal).getName(); return ((Principal) principal).getName();
return String.valueOf(principal); return String.valueOf(principal);
} }
/** /**
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId> <artifactId>spring-microservice-exam</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>common</artifactId> <artifactId>common</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
<description>公共依赖</description> <description>公共依赖</description>
<modules> <modules>
<module>common-core</module> <module>common-core</module>
<module>common-security</module> <module>common-security</module>
<module>common-feign</module> <module>common-feign</module>
<module>common-log</module> <module>common-log</module>
</modules> </modules>
</project> </project>
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId> <artifactId>spring-microservice-exam</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>config-service</artifactId> <artifactId>config-service</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
......
...@@ -83,6 +83,7 @@ ignore: ...@@ -83,6 +83,7 @@ ignore:
- /actuator/** - /actuator/**
- /hystrix.sender - /hystrix.sender
- /v1/user/findUserByUsername/** - /v1/user/findUserByUsername/**
- /v1/tenant/findTenantByTenantCode/**
- /v1/user/checkExist/** - /v1/user/checkExist/**
- /v1/menu/findMenuByRole/** - /v1/menu/findMenuByRole/**
- /v1/menu/findAllMenu - /v1/menu/findAllMenu
......
...@@ -48,15 +48,15 @@ security: ...@@ -48,15 +48,15 @@ security:
jwt: jwt:
key-uri: http://${AUTH_SERVICE_HOST:localhost}:${AUTH_SERVICE_PORT:8000}/api/auth/oauth/token_key key-uri: http://${AUTH_SERVICE_HOST:localhost}:${AUTH_SERVICE_PORT:8000}/api/auth/oauth/token_key
key-value: | key-value: |
-----BEGIN PUBLIC KEY----- -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjxSawA+NUNmhB2ctiVnt MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjxSawA+NUNmhB2ctiVnt
YH41WCNoD5STW2iPm5AIsKvm6X67lr6A88qOMRwx9oySdZnUnJ+8L3QJ51fkwuDe YH41WCNoD5STW2iPm5AIsKvm6X67lr6A88qOMRwx9oySdZnUnJ+8L3QJ51fkwuDe
ix5w9yA3f/7LUPWZU8M/7Oi+2nda05JMgU999TUlhTGsp9SPiBqq/iwuqMxU8xKu ix5w9yA3f/7LUPWZU8M/7Oi+2nda05JMgU999TUlhTGsp9SPiBqq/iwuqMxU8xKu
F8bpTJTOpzrxH4e5BM6J/UJcOwDZLY6/3zP5w+tbhTvxjc995G4NtUyS4owE1MHe F8bpTJTOpzrxH4e5BM6J/UJcOwDZLY6/3zP5w+tbhTvxjc995G4NtUyS4owE1MHe
lj8IJepknjePrE6nXD6ecdL401hstMY838UOOFiCnM8NpiBuNI0nY0qCbb9mhQZ+ lj8IJepknjePrE6nXD6ecdL401hstMY838UOOFiCnM8NpiBuNI0nY0qCbb9mhQZ+
7gP3jjM+Ft7R+MFTuEHWQ5UN8qHAPIT9UlLcu9IXdk6YwTsqNavwaTLUcP/ih9HB 7gP3jjM+Ft7R+MFTuEHWQ5UN8qHAPIT9UlLcu9IXdk6YwTsqNavwaTLUcP/ih9HB
6wIDAQAB 6wIDAQAB
-----END PUBLIC KEY----- -----END PUBLIC KEY-----
# mybatis配置 # mybatis配置
mybatis: mybatis:
...@@ -68,10 +68,10 @@ mybatis: ...@@ -68,10 +68,10 @@ mybatis:
lazy-loading-enabled: true lazy-loading-enabled: true
mapper-locations: classpath:mapper/*.xml mapper-locations: classpath:mapper/*.xml
pagehelper: pagehelper:
helperDialect: mysql helperDialect: mysql
reasonable: true reasonable: true
supportMethodsArguments: true supportMethodsArguments: true
params: count=countSql params: count=countSql
feign: feign:
hystrix: hystrix:
...@@ -107,6 +107,7 @@ ignore: ...@@ -107,6 +107,7 @@ ignore:
- /actuator/** - /actuator/**
- /hystrix.sender - /hystrix.sender
- /v1/user/findUserByUsername/** - /v1/user/findUserByUsername/**
- /v1/tenant/findTenantByTenantCode/**
- /v1/menu/findMenuByRole/** - /v1/menu/findMenuByRole/**
- /v1/menu/findAllMenu - /v1/menu/findAllMenu
- /v1/user/checkExist/** - /v1/user/checkExist/**
...@@ -133,4 +134,4 @@ cluster: ...@@ -133,4 +134,4 @@ cluster:
logging: logging:
level: level:
root: info root: info
com.github.tangyi: debug com.github.tangyi: debug
\ No newline at end of file
...@@ -54,15 +54,15 @@ security: ...@@ -54,15 +54,15 @@ security:
jwt: jwt:
key-uri: http://${AUTH_SERVICE_HOST:localhost}:${AUTH_SERVICE_PORT:8000}/api/auth/oauth/token_key key-uri: http://${AUTH_SERVICE_HOST:localhost}:${AUTH_SERVICE_PORT:8000}/api/auth/oauth/token_key
key-value: | key-value: |
-----BEGIN PUBLIC KEY----- -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjxSawA+NUNmhB2ctiVnt MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjxSawA+NUNmhB2ctiVnt
YH41WCNoD5STW2iPm5AIsKvm6X67lr6A88qOMRwx9oySdZnUnJ+8L3QJ51fkwuDe YH41WCNoD5STW2iPm5AIsKvm6X67lr6A88qOMRwx9oySdZnUnJ+8L3QJ51fkwuDe
ix5w9yA3f/7LUPWZU8M/7Oi+2nda05JMgU999TUlhTGsp9SPiBqq/iwuqMxU8xKu ix5w9yA3f/7LUPWZU8M/7Oi+2nda05JMgU999TUlhTGsp9SPiBqq/iwuqMxU8xKu
F8bpTJTOpzrxH4e5BM6J/UJcOwDZLY6/3zP5w+tbhTvxjc995G4NtUyS4owE1MHe F8bpTJTOpzrxH4e5BM6J/UJcOwDZLY6/3zP5w+tbhTvxjc995G4NtUyS4owE1MHe
lj8IJepknjePrE6nXD6ecdL401hstMY838UOOFiCnM8NpiBuNI0nY0qCbb9mhQZ+ lj8IJepknjePrE6nXD6ecdL401hstMY838UOOFiCnM8NpiBuNI0nY0qCbb9mhQZ+
7gP3jjM+Ft7R+MFTuEHWQ5UN8qHAPIT9UlLcu9IXdk6YwTsqNavwaTLUcP/ih9HB 7gP3jjM+Ft7R+MFTuEHWQ5UN8qHAPIT9UlLcu9IXdk6YwTsqNavwaTLUcP/ih9HB
6wIDAQAB 6wIDAQAB
-----END PUBLIC KEY----- -----END PUBLIC KEY-----
# mybatis配置 # mybatis配置
mybatis: mybatis:
...@@ -74,10 +74,10 @@ mybatis: ...@@ -74,10 +74,10 @@ mybatis:
lazy-loading-enabled: true lazy-loading-enabled: true
mapper-locations: classpath:mapper/*.xml mapper-locations: classpath:mapper/*.xml
pagehelper: pagehelper:
helperDialect: mysql helperDialect: mysql
reasonable: true reasonable: true
supportMethodsArguments: true supportMethodsArguments: true
params: count=countSql params: count=countSql
# =================================================================== # ===================================================================
# 分布式文件系统FDFS配置 # 分布式文件系统FDFS配置
...@@ -89,7 +89,7 @@ fdfs: ...@@ -89,7 +89,7 @@ fdfs:
width: 150 width: 150
height: 150 height: 150
tracker-list: #TrackerList参数,支持多个 tracker-list: #TrackerList参数,支持多个
- ${FDFS_HOST:192.168.0.95}:${FDFS_PORT:22122} - ${FDFS_HOST:182.254.233.125}:${FDFS_PORT:22122}
# 系统配置 # 系统配置
sys: sys:
...@@ -131,6 +131,7 @@ ignore: ...@@ -131,6 +131,7 @@ ignore:
- /actuator/** - /actuator/**
- /hystrix.sender - /hystrix.sender
- /v1/user/findUserByUsername/** - /v1/user/findUserByUsername/**
- /v1/tenant/findTenantByTenantCode/**
- /v1/menu/findMenuByRole/** - /v1/menu/findMenuByRole/**
- /v1/menu/findAllMenu - /v1/menu/findAllMenu
- /v1/user/register - /v1/user/register
...@@ -159,4 +160,4 @@ cluster: ...@@ -159,4 +160,4 @@ cluster:
logging: logging:
level: level:
root: info root: info
com.github.tangyi: debug com.github.tangyi: debug
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false"> <configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue="spring-microservice-exam"/> <springProperty scop="context" name="spring.application.name" source="spring.application.name"
<property name="log.path" value="logs/${spring.application.name}" /> defaultValue="spring-microservice-exam"/>
<property name="log.path" value="logs/${spring.application.name}"/>
<!-- Console log output --> <!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
...@@ -40,8 +41,8 @@ ...@@ -40,8 +41,8 @@
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 --> <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console"/>
<appender-ref ref="debug" /> <appender-ref ref="debug"/>
<appender-ref ref="error" /> <appender-ref ref="error"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
Target Server Version : 50617 Target Server Version : 50617
File Encoding : 65001 File Encoding : 65001
Date: 22/05/2019 22:21:34 Date: 09/06/2019 16:45:45
*/ */
SET NAMES utf8mb4; SET NAMES utf8mb4;
...@@ -48,6 +48,6 @@ CREATE TABLE `oauth_client_details` ( ...@@ -48,6 +48,6 @@ CREATE TABLE `oauth_client_details` (
-- ---------------------------- -- ----------------------------
-- Records of oauth_client_details -- Records of oauth_client_details
-- ---------------------------- -- ----------------------------
INSERT INTO `oauth_client_details` VALUES ('471037a0c1be4df99b40e3f84141cc56', 'web_app', NULL, 'spring-microservice-exam-secret', '$2a$10$IWLD8r7e0rKMW.ZhGsGCUO./MZUNDKudIswSToa9puXJwty.h59.u', 'read,write', 'password,authorization_code,refresh_token,implicit', NULL, NULL, '3600', '21600', NULL, NULL, 'admin', '2019-03-30 23:43:07', 'admin', '2019-05-22 22:16:18', '0', 'EXAM', NULL); INSERT INTO `oauth_client_details` VALUES ('471037a0c1be4df99b40e3f84141cc56', 'web_app', NULL, 'spring-microservice-exam-secret', '$2a$10$IWLD8r7e0rKMW.ZhGsGCUO./MZUNDKudIswSToa9puXJwty.h59.u', 'read,write', 'password,authorization_code,refresh_token,implicit', NULL, NULL, '3600', '21600', NULL, NULL, 'admin', '2019-03-30 23:43:07', 'admin', '2019-06-07 21:48:31', '0', 'EXAM', NULL);
SET FOREIGN_KEY_CHECKS = 1; SET FOREIGN_KEY_CHECKS = 1;
...@@ -5,7 +5,7 @@ DOCKERHOME=/spring-microservice-exam ...@@ -5,7 +5,7 @@ DOCKERHOME=/spring-microservice-exam
# 镜像名称前缀、标签 # 镜像名称前缀、标签
BASE_IMAGE_NAME=registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam BASE_IMAGE_NAME=registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam
BSEE_IMAGE_TAG=2.0 BSEE_IMAGE_TAG=3.0.0
# 各服务的镜像名称 # 各服务的镜像名称
CONFIG_SERVICE=$BASE_IMAGE_NAME/config-service:$BSEE_IMAGE_TAG CONFIG_SERVICE=$BASE_IMAGE_NAME/config-service:$BSEE_IMAGE_TAG
......
doc/images/image_ui.png

105 KB | W: | H:

doc/images/image_ui.png

113 KB | W: | H:

doc/images/image_ui.png
doc/images/image_ui.png
doc/images/image_ui.png
doc/images/image_ui.png
  • 2-up
  • Swipe
  • Onion skin
doc/images/image_ui_attachment.png

43 KB | W: | H:

doc/images/image_ui_attachment.png

63.3 KB | W: | H:

doc/images/image_ui_attachment.png
doc/images/image_ui_attachment.png
doc/images/image_ui_attachment.png
doc/images/image_ui_attachment.png
  • 2-up
  • Swipe
  • Onion skin
doc/images/image_ui_exam.png

61.8 KB | W: | H:

doc/images/image_ui_exam.png

62.9 KB | W: | H:

doc/images/image_ui_exam.png
doc/images/image_ui_exam.png
doc/images/image_ui_exam.png
doc/images/image_ui_exam.png
  • 2-up
  • Swipe
  • Onion skin
doc/images/image_ui_exam_subject.png

157 KB | W: | H:

doc/images/image_ui_exam_subject.png

120 KB | W: | H:

doc/images/image_ui_exam_subject.png
doc/images/image_ui_exam_subject.png
doc/images/image_ui_exam_subject.png
doc/images/image_ui_exam_subject.png
  • 2-up
  • Swipe
  • Onion skin
doc/images/image_ui_menu.png

123 KB | W: | H:

doc/images/image_ui_menu.png

99.8 KB | W: | H:

doc/images/image_ui_menu.png
doc/images/image_ui_menu.png
doc/images/image_ui_menu.png
doc/images/image_ui_menu.png
  • 2-up
  • Swipe
  • Onion skin
doc/images/image_ui_subject.png

101 KB | W: | H:

doc/images/image_ui_subject.png

128 KB | W: | H:

doc/images/image_ui_subject.png
doc/images/image_ui_subject.png
doc/images/image_ui_subject.png
doc/images/image_ui_subject.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
- consul - consul
- fastDfs(推荐基于docker安装,安装步骤网上很多) - fastDfs(推荐基于docker安装,安装步骤网上很多)
开发工具:`IntelliJ IDEA``WebStorm``IntelliJ IDEA`需要安装插件:`lombok` 开发工具:`IntelliJ IDEA``IntelliJ IDEA`需要安装插件:`lombok`
#### 项目下载 #### 项目下载
...@@ -79,7 +79,7 @@ fastDfs的IP和端口号: ...@@ -79,7 +79,7 @@ fastDfs的IP和端口号:
![image](images/deploy/npm_run.png) ![image](images/deploy/npm_run.png)
`WebStorm`导入项目: `IntelliJ IDEA`导入项目:
![image](images/deploy/import_exam_ui.png) ![image](images/deploy/import_exam_ui.png)
......
...@@ -70,7 +70,7 @@ services: ...@@ -70,7 +70,7 @@ services:
# 配置中心 # 配置中心
# --------------------------- # ---------------------------
config-service: config-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/config-service:2.0 image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/config-service:3.0.0
container_name: config-service container_name: config-service
env_file: docker-compose.env # 从文件中获取配置 env_file: docker-compose.env # 从文件中获取配置
restart: always restart: always
......
...@@ -4,7 +4,7 @@ services: ...@@ -4,7 +4,7 @@ services:
# api网关 # api网关
# --------------------------- # ---------------------------
gateway-service: gateway-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/gateway-service:2.0 image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/gateway-service:3.0.0
container_name: gateway-service container_name: gateway-service
env_file: docker-compose.env # 从文件中获取配置 env_file: docker-compose.env # 从文件中获取配置
restart: always restart: always
...@@ -17,7 +17,7 @@ services: ...@@ -17,7 +17,7 @@ services:
# 授权服务 # 授权服务
# --------------------------- # ---------------------------
auth-service: auth-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/auth-service:2.0 image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/auth-service:3.0.0
container_name: auth-service container_name: auth-service
env_file: docker-compose.env # 从文件中获取配置 env_file: docker-compose.env # 从文件中获取配置
restart: always restart: always
...@@ -30,7 +30,7 @@ services: ...@@ -30,7 +30,7 @@ services:
# 用户服务 # 用户服务
# --------------------------- # ---------------------------
user-service: user-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/user-service:2.0 image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/user-service:3.0.0
container_name: user-service container_name: user-service
env_file: docker-compose.env # 从文件中获取配置 env_file: docker-compose.env # 从文件中获取配置
restart: always restart: always
...@@ -43,7 +43,7 @@ services: ...@@ -43,7 +43,7 @@ services:
# 考试服务 # 考试服务
# --------------------------- # ---------------------------
exam-service: exam-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/exam-service:2.0 image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/exam-service:3.0.0
container_name: exam-service container_name: exam-service
env_file: docker-compose.env # 从文件中获取配置 env_file: docker-compose.env # 从文件中获取配置
restart: always restart: always
...@@ -56,7 +56,7 @@ services: ...@@ -56,7 +56,7 @@ services:
# 监控服务 # 监控服务
# --------------------------- # ---------------------------
monitor-service: monitor-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/monitor-service:2.0 image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/monitor-service:3.0.0
container_name: monitor-service container_name: monitor-service
env_file: docker-compose.env # 从文件中获取配置 env_file: docker-compose.env # 从文件中获取配置
restart: always restart: always
......
// 租户标识,默认gitee
TENANT_CODE=gitee
// 环境配置 // 环境配置
SPRING_PROFILES_ACTIVE=native SPRING_PROFILES_ACTIVE=native
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId> <artifactId>spring-microservice-exam</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>gateway-service</artifactId> <artifactId>gateway-service</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
......
package com.github.tangyi.gateway.config; package com.github.tangyi.gateway.config;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.model.Route;
import com.github.tangyi.common.core.utils.JsonMapper;
import com.github.tangyi.common.core.vo.RoutePredicateVo;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.springframework.cloud.gateway.config.GatewayProperties; import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider; import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* Swagger聚合文档 * Swagger聚合文档
* 目前问题:结合动态更新路由之后,GatewayProperties获取不到新的路由列表,导致swagger-ui显示不了 * 目前问题:结合动态更新路由之后,GatewayProperties获取不到新的路由列表,导致swagger-ui显示不了
* 解决办法:从Redis里读取路由数据
* *
* @author tangyi * @author tangyi
* @date 2019/3/26 15:39 * @date 2019/3/26 15:39
*/ */
@Slf4j
@Component @Component
@Primary @Primary
@AllArgsConstructor @AllArgsConstructor
...@@ -31,10 +36,10 @@ public class RegistrySwaggerResourcesProvider implements SwaggerResourcesProvide ...@@ -31,10 +36,10 @@ public class RegistrySwaggerResourcesProvider implements SwaggerResourcesProvide
private final RouteLocator routeLocator; private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
private final SwaggerProviderConfig swaggerProviderConfig; private final SwaggerProviderConfig swaggerProviderConfig;
private final RedisTemplate redisTemplate;
@Override @Override
public List<SwaggerResource> get() { public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>(); List<SwaggerResource> resources = new ArrayList<>();
...@@ -45,17 +50,31 @@ public class RegistrySwaggerResourcesProvider implements SwaggerResourcesProvide ...@@ -45,17 +50,31 @@ public class RegistrySwaggerResourcesProvider implements SwaggerResourcesProvide
if (swaggerProviderConfig.getProviders().contains(route.getId())) if (swaggerProviderConfig.getProviders().contains(route.getId()))
routes.add(route.getId()); routes.add(route.getId());
}); });
// 结合配置的route-路径(Path),和route过滤,只获取有效的route节点 // 结合配置的route-路径(Path),和route过滤,只获取有效的route节点
List<RouteDefinition> routeDefinitions = gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).collect(Collectors.toList()); Object object = redisTemplate.opsForValue().get(CommonConstant.ROUTE_KEY);
routeDefinitions.forEach(routeDefinition -> { if (object != null) {
List<PredicateDefinition> predicates = routeDefinition.getPredicates().stream() List<Route> routeList = JsonMapper.getInstance().fromJson(object.toString(), JsonMapper.getInstance().createCollectionType(ArrayList.class, Route.class));
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName())).collect(Collectors.toList()); if (CollectionUtils.isNotEmpty(routeList)) {
predicates.forEach(predicateDefinition -> { for (Route route : routeList) {
resources.add(swaggerResource(routeDefinition.getId(), if (routes.contains(route.getRouteId())) {
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0") try {
.replace("/**", API_URI))); List<RoutePredicateVo> routePredicateVoList = JsonMapper.getInstance().fromJson(route.getPredicates(), JsonMapper.getInstance().createCollectionType(ArrayList.class, RoutePredicateVo.class));
}); if (CollectionUtils.isNotEmpty(routePredicateVoList)) {
}); String genKey;
RoutePredicateVo routePredicateVo = routePredicateVoList.stream().filter(routePredicate -> routePredicate.getArgs().containsKey(NameUtils.GENERATED_NAME_PREFIX + "0")).findFirst().orElse(null);
if (routePredicateVo != null) {
genKey = routePredicateVo.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0").replace("/**", API_URI);
resources.add(swaggerResource(route.getRouteId(), genKey));
}
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
}
}
return resources; return resources;
} }
......
...@@ -11,6 +11,7 @@ import java.util.List; ...@@ -11,6 +11,7 @@ import java.util.List;
/** /**
* 提供swagger文档的服务 * 提供swagger文档的服务
*
* @author tangyi * @author tangyi
* @date 2019/3/27 16:24 * @date 2019/3/27 16:24
*/ */
......
...@@ -22,11 +22,6 @@ public class GatewayConstant { ...@@ -22,11 +22,6 @@ public class GatewayConstant {
public static final String REGISTER = "/user/register"; public static final String REGISTER = "/user/register";
/** /**
* 密码类型
*/
public static final String GRANT_TYPE_PASSWORD = "password";
/**
* 刷新token类型 * 刷新token类型
*/ */
public static final String GRANT_TYPE_REFRESH_TOKEN = "refresh_token"; public static final String GRANT_TYPE_REFRESH_TOKEN = "refresh_token";
......
...@@ -51,7 +51,7 @@ public class GatewayRouteController { ...@@ -51,7 +51,7 @@ public class GatewayRouteController {
* *
* @return Mono * @return Mono
*/ */
@GetMapping("/routeList") @GetMapping("routeList")
public Mono<List<Map<String, Object>>> routes() { public Mono<List<Map<String, Object>>> routes() {
Mono<Map<String, RouteDefinition>> routeDefs = this.routeDefinitionLocator Mono<Map<String, RouteDefinition>> routeDefs = this.routeDefinitionLocator
.getRouteDefinitions().collectMap(RouteDefinition::getId); .getRouteDefinitions().collectMap(RouteDefinition::getId);
...@@ -135,7 +135,7 @@ public class GatewayRouteController { ...@@ -135,7 +135,7 @@ public class GatewayRouteController {
* @author tangyi * @author tangyi
* @date 2019/04/07 12:32 * @date 2019/04/07 12:32
*/ */
@GetMapping("/refresh") @GetMapping("refresh")
public ResponseBean<Boolean> refresh() { public ResponseBean<Boolean> refresh() {
amqpTemplate.convertAndSend(MqConstant.REFRESH_GATEWAY_ROUTE_QUEUE, "refresh"); amqpTemplate.convertAndSend(MqConstant.REFRESH_GATEWAY_ROUTE_QUEUE, "refresh");
return new ResponseBean<>(Boolean.TRUE); return new ResponseBean<>(Boolean.TRUE);
......
...@@ -2,6 +2,7 @@ package com.github.tangyi.gateway.filters; ...@@ -2,6 +2,7 @@ package com.github.tangyi.gateway.filters;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.gateway.constants.GatewayConstant; import com.github.tangyi.gateway.constants.GatewayConstant;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
...@@ -55,8 +56,8 @@ public class DecodePasswordFilter implements GlobalFilter, Ordered { ...@@ -55,8 +56,8 @@ public class DecodePasswordFilter implements GlobalFilter, Ordered {
GatewayConstant.MOBILE_TOKEN_URL)) { GatewayConstant.MOBILE_TOKEN_URL)) {
String grantType = request.getQueryParams().getFirst(GatewayConstant.GRANT_TYPE); String grantType = request.getQueryParams().getFirst(GatewayConstant.GRANT_TYPE);
// 授权类型为密码模式则解密 // 授权类型为密码模式则解密
if (GatewayConstant.GRANT_TYPE_PASSWORD.equals(grantType) || StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.REGISTER)) { if (CommonConstant.GRANT_TYPE_PASSWORD.equals(grantType) || StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.REGISTER)) {
String password = request.getQueryParams().getFirst(GatewayConstant.GRANT_TYPE_PASSWORD); String password = request.getQueryParams().getFirst(CommonConstant.GRANT_TYPE_PASSWORD);
if (password == null || password.isEmpty()) { if (password == null || password.isEmpty()) {
log.info("password is empty..."); log.info("password is empty...");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
...@@ -70,7 +71,7 @@ public class DecodePasswordFilter implements GlobalFilter, Ordered { ...@@ -70,7 +71,7 @@ public class DecodePasswordFilter implements GlobalFilter, Ordered {
} catch (Exception e) { } catch (Exception e) {
log.error("password decrypt fail:{}", password); log.error("password decrypt fail:{}", password);
} }
URI newUri = UriComponentsBuilder.fromUri(uri).replaceQueryParam(GatewayConstant.GRANT_TYPE_PASSWORD, password).build(true).toUri(); URI newUri = UriComponentsBuilder.fromUri(uri).replaceQueryParam(CommonConstant.GRANT_TYPE_PASSWORD, password).build(true).toUri();
request = request.mutate().uri(newUri).build(); request = request.mutate().uri(newUri).build();
return chain.filter(exchange.mutate().request(request).build()); return chain.filter(exchange.mutate().request(request).build());
} }
......
package com.github.tangyi.gateway.filters; package com.github.tangyi.gateway.filters;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.exceptions.CommonException; import com.github.tangyi.common.core.exceptions.CommonException;
import com.github.tangyi.common.core.exceptions.InvalidAccessTokenException;
import com.github.tangyi.common.core.utils.JsonMapper; import com.github.tangyi.common.core.utils.JsonMapper;
import com.github.tangyi.gateway.constants.GatewayConstant; import com.github.tangyi.gateway.constants.GatewayConstant;
import com.github.tangyi.gateway.model.AccessToken; import com.github.tangyi.gateway.model.AccessToken;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GatewayFilterChain;
...@@ -72,7 +75,7 @@ public class TokenRequestGlobalFilter implements GlobalFilter, Ordered { ...@@ -72,7 +75,7 @@ public class TokenRequestGlobalFilter implements GlobalFilter, Ordered {
&& StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.OAUTH_TOKEN_URL, GatewayConstant.REGISTER, GatewayConstant.MOBILE_TOKEN_URL)) { && StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.OAUTH_TOKEN_URL, GatewayConstant.REGISTER, GatewayConstant.MOBILE_TOKEN_URL)) {
String grantType = request.getQueryParams().getFirst(GatewayConstant.GRANT_TYPE); String grantType = request.getQueryParams().getFirst(GatewayConstant.GRANT_TYPE);
// 授权类型为密码模式 // 授权类型为密码模式
if (GatewayConstant.GRANT_TYPE_PASSWORD.equals(grantType) || GatewayConstant.GRANT_TYPE_REFRESH_TOKEN.equals(grantType) || StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.REGISTER)) { if (CommonConstant.GRANT_TYPE_PASSWORD.equals(grantType) || GatewayConstant.GRANT_TYPE_REFRESH_TOKEN.equals(grantType)) {
// 装饰器 // 装饰器
ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) { ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()) {
@Override @Override
...@@ -93,8 +96,8 @@ public class TokenRequestGlobalFilter implements GlobalFilter, Ordered { ...@@ -93,8 +96,8 @@ public class TokenRequestGlobalFilter implements GlobalFilter, Ordered {
String accessTokenContent = joiner.join(contentList); String accessTokenContent = joiner.join(contentList);
log.trace("生成的accessToken: {}", accessTokenContent); log.trace("生成的accessToken: {}", accessTokenContent);
AccessToken accessToken = JsonMapper.getInstance().fromJson(accessTokenContent, AccessToken.class); AccessToken accessToken = JsonMapper.getInstance().fromJson(accessTokenContent, AccessToken.class);
if (accessToken == null) if (accessToken == null || StringUtils.isBlank(accessToken.getJti()))
throw new CommonException("token转换失败!"); throw new InvalidAccessTokenException("token转换失败!");
// 真正的access_token和refresh_token // 真正的access_token和refresh_token
String realAccessToken = accessToken.getAccessToken(), realRefreshToken = accessToken.getRefreshToken(); String realAccessToken = accessToken.getAccessToken(), realRefreshToken = accessToken.getRefreshToken();
// 转换token // 转换token
......
...@@ -2,6 +2,7 @@ package com.github.tangyi.gateway.filters; ...@@ -2,6 +2,7 @@ package com.github.tangyi.gateway.filters;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.github.tangyi.common.core.constant.CommonConstant; import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.exceptions.InvalidAccessTokenException;
import com.github.tangyi.gateway.constants.GatewayConstant; import com.github.tangyi.gateway.constants.GatewayConstant;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
...@@ -71,7 +72,10 @@ public class TokenResponseGlobalFilter implements GlobalFilter, Ordered { ...@@ -71,7 +72,10 @@ public class TokenResponseGlobalFilter implements GlobalFilter, Ordered {
log.trace("jti authorization: {}", authorization); log.trace("jti authorization: {}", authorization);
// 从Redis里获取实际的access_token // 从Redis里获取实际的access_token
Object object = redisTemplate.opsForValue().get(GatewayConstant.GATEWAY_ACCESS_TOKENS + authorization); Object object = redisTemplate.opsForValue().get(GatewayConstant.GATEWAY_ACCESS_TOKENS + authorization);
authorization = object == null ? authorization : CommonConstant.TOKEN_SPLIT + object.toString(); // 缓存里没有access_token,抛异常,统一异常处理会返回403,前端自动重新获取access_token
if (object == null)
throw new InvalidAccessTokenException("access_token已失效.");
authorization = CommonConstant.TOKEN_SPLIT + object.toString();
String realAuthorization = authorization; String realAuthorization = authorization;
log.trace("jti->token:{}", realAuthorization); log.trace("jti->token:{}", realAuthorization);
// 更新请求头,参考源码:SetRequestHeaderGatewayFilterFactory // 更新请求头,参考源码:SetRequestHeaderGatewayFilterFactory
......
...@@ -41,7 +41,7 @@ public class ValidateCodeFilter implements GlobalFilter, Ordered { ...@@ -41,7 +41,7 @@ public class ValidateCodeFilter implements GlobalFilter, Ordered {
&& StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.OAUTH_TOKEN_URL, GatewayConstant.REGISTER, GatewayConstant.MOBILE_TOKEN_URL)) { && StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.OAUTH_TOKEN_URL, GatewayConstant.REGISTER, GatewayConstant.MOBILE_TOKEN_URL)) {
String grantType = request.getQueryParams().getFirst(GatewayConstant.GRANT_TYPE); String grantType = request.getQueryParams().getFirst(GatewayConstant.GRANT_TYPE);
// 授权类型为密码模式、注册才校验验证码 // 授权类型为密码模式、注册才校验验证码
if (GatewayConstant.GRANT_TYPE_PASSWORD.equals(grantType) || StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.REGISTER)) { if (CommonConstant.GRANT_TYPE_PASSWORD.equals(grantType) || StrUtil.containsAnyIgnoreCase(uri.getPath(), GatewayConstant.REGISTER)) {
// 校验验证码 // 校验验证码
checkCode(request); checkCode(request);
} }
......
package com.github.tangyi.gateway.handler; package com.github.tangyi.gateway.handler;
import com.github.tangyi.common.core.exceptions.InvalidAccessTokenException;
import com.github.tangyi.common.core.exceptions.InvalidValidateCodeException; import com.github.tangyi.common.core.exceptions.InvalidValidateCodeException;
import com.github.tangyi.common.core.exceptions.ValidateCodeExpiredException; import com.github.tangyi.common.core.exceptions.ValidateCodeExpiredException;
import com.github.tangyi.common.core.model.ResponseBean; import com.github.tangyi.common.core.model.ResponseBean;
...@@ -84,7 +85,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler { ...@@ -84,7 +85,7 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
int code = ResponseBean.FAIL; int code = ResponseBean.FAIL;
if (ex instanceof NotFoundException) { if (ex instanceof NotFoundException) {
httpStatus = HttpStatus.NOT_FOUND; httpStatus = HttpStatus.NOT_FOUND;
msg = "Service Not Found"; msg = "没有服务提供者.";
} else if (ex instanceof ResponseStatusException) { } else if (ex instanceof ResponseStatusException) {
ResponseStatusException responseStatusException = (ResponseStatusException) ex; ResponseStatusException responseStatusException = (ResponseStatusException) ex;
httpStatus = responseStatusException.getStatus(); httpStatus = responseStatusException.getStatus();
...@@ -99,12 +100,17 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler { ...@@ -99,12 +100,17 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
msg = ex.getMessage(); msg = ex.getMessage();
// 验证码过期 // 验证码过期
code = ResponseBean.VALIDATE_CODE_EXPIRED_ERROR; code = ResponseBean.VALIDATE_CODE_EXPIRED_ERROR;
} else if (ex instanceof InvalidAccessTokenException) {
httpStatus = HttpStatus.FORBIDDEN;
msg = ex.getMessage();
// token非法,返回403
code = HttpStatus.FORBIDDEN.value();
} else { } else {
httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
msg = "Internal Server Error"; msg = "服务器内部错误.";
} }
// 封装响应体 // 封装响应体
ResponseBean<HttpStatus> responseBean = new ResponseBean<>(httpStatus, msg); ResponseBean<String> responseBean = new ResponseBean<>(msg, msg);
responseBean.setStatus(httpStatus.value()); responseBean.setStatus(httpStatus.value());
responseBean.setCode(code); responseBean.setCode(code);
// 错误记录 // 错误记录
...@@ -118,7 +124,6 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler { ...@@ -118,7 +124,6 @@ public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
.switchIfEmpty(Mono.error(ex)) .switchIfEmpty(Mono.error(ex))
.flatMap((handler) -> handler.handle(newRequest)) .flatMap((handler) -> handler.handle(newRequest))
.flatMap((response) -> write(exchange, response)); .flatMap((response) -> write(exchange, response));
} }
private Mono<ServerResponse> renderErrorResponse(ServerRequest request) { private Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
......
...@@ -57,4 +57,9 @@ public class AccessToken implements Serializable { ...@@ -57,4 +57,9 @@ public class AccessToken implements Serializable {
*/ */
@JsonProperty("token_type") @JsonProperty("token_type")
private String tokenType; private String tokenType;
/**
* 租户标识
*/
private String tenantCode;
} }
...@@ -12,7 +12,6 @@ import lombok.extern.slf4j.Slf4j; ...@@ -12,7 +12,6 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.FilterDefinition; import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinition;
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false"> <configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue="spring-microservice-exam"/> <springProperty scop="context" name="spring.application.name" source="spring.application.name"
<property name="log.path" value="logs/${spring.application.name}" /> defaultValue="spring-microservice-exam"/>
<property name="log.path" value="logs/${spring.application.name}"/>
<!-- Console log output --> <!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
...@@ -40,8 +41,8 @@ ...@@ -40,8 +41,8 @@
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 --> <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console"/>
<appender-ref ref="debug" /> <appender-ref ref="debug"/>
<appender-ref ref="error" /> <appender-ref ref="error"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
...@@ -31,7 +31,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -31,7 +31,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
http.headers().frameOptions().disable(); http.headers().frameOptions().disable();
http.authorizeRequests() http.authorizeRequests()
.antMatchers("/actuator/**", "/hystrix/**","/hystrix","*.sender").permitAll() .antMatchers("/actuator/**", "/hystrix/**", "/hystrix", "*.sender").permitAll()
.antMatchers(adminContextPath + "/assets/**").permitAll() .antMatchers(adminContextPath + "/assets/**").permitAll()
.antMatchers(adminContextPath + "/login").permitAll() .antMatchers(adminContextPath + "/login").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false"> <configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue="spring-microservice-exam"/> <springProperty scop="context" name="spring.application.name" source="spring.application.name"
<property name="log.path" value="logs/${spring.application.name}" /> defaultValue="spring-microservice-exam"/>
<property name="log.path" value="logs/${spring.application.name}"/>
<!-- Console log output --> <!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
...@@ -40,8 +41,8 @@ ...@@ -40,8 +41,8 @@
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 --> <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console"/>
<appender-ref ref="debug" /> <appender-ref ref="debug"/>
<appender-ref ref="error" /> <appender-ref ref="error"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId> <artifactId>spring-microservice-exam</artifactId>
<version>2.0</version> <version>3.0.0</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>spring-microservice-exam</name> <name>spring-microservice-exam</name>
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>service-api-impl</artifactId> <artifactId>service-api-impl</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>auth-service</artifactId> <artifactId>auth-service</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
......
...@@ -2,7 +2,6 @@ package com.github.tangyi.auth; ...@@ -2,7 +2,6 @@ package com.github.tangyi.auth;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.EnableFeignClients;
......
package com.github.tangyi.auth.config; package com.github.tangyi.auth.config;
import com.github.tangyi.auth.security.CustomTokenConverter;
import com.github.tangyi.auth.security.TenantTokenFilter;
import com.github.tangyi.common.security.core.ClientDetailsServiceImpl; import com.github.tangyi.common.security.core.ClientDetailsServiceImpl;
import com.github.tangyi.common.security.exceptions.CustomOauthException; import com.github.tangyi.common.security.exceptions.CustomOauthException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
...@@ -78,7 +80,7 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf ...@@ -78,7 +80,7 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
@Bean @Bean
protected JwtAccessTokenConverter jwtTokenEnhancer() { protected JwtAccessTokenConverter jwtTokenEnhancer() {
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(keyProperties.getKeyStore().getLocation(), keyProperties.getKeyStore().getPassword().toCharArray()); KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(keyProperties.getKeyStore().getLocation(), keyProperties.getKeyStore().getPassword().toCharArray());
JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); CustomTokenConverter converter = new CustomTokenConverter();
converter.setKeyPair(keyStoreKeyFactory.getKeyPair(keyProperties.getKeyStore().getAlias())); converter.setKeyPair(keyStoreKeyFactory.getKeyPair(keyProperties.getKeyStore().getAlias()));
return converter; return converter;
} }
...@@ -143,7 +145,9 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf ...@@ -143,7 +145,9 @@ public class CustomAuthorizationServerConfigurer extends AuthorizationServerConf
.tokenKeyAccess("permitAll()") .tokenKeyAccess("permitAll()")
// 开启/oauth/check_token验证端口认证权限访问 // 开启/oauth/check_token验证端口认证权限访问
.checkTokenAccess("isAuthenticated()") .checkTokenAccess("isAuthenticated()")
.allowFormAuthenticationForClients(); .allowFormAuthenticationForClients()
// 增加租户信息过滤器
.addTokenEndpointAuthenticationFilter(new TenantTokenFilter());
} }
} }
package com.github.tangyi.auth.config; package com.github.tangyi.auth.config;
import com.github.tangyi.auth.security.CustomUserDetailsAuthenticationProvider;
import com.github.tangyi.auth.security.CustomUserDetailsService;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import javax.annotation.Resource;
/** /**
* Spring Security配置 * Spring Security配置
* *
* @author tangyi * @author tangyi
* @date 2019-03-14 14:35 * @date 2019-03-14 14:35
*/ */
@AllArgsConstructor
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) @EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter { public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource private final CustomUserDetailsService userDetailsService;
private UserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 前后端分离,关闭csrf
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated();
}
@Bean @Bean
public BCryptPasswordEncoder encoder() { public BCryptPasswordEncoder encoder() {
...@@ -34,23 +44,24 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -34,23 +44,24 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
} }
@Autowired @Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.userDetailsService(userDetailsService) auth.authenticationProvider(authProvider());
.passwordEncoder(encoder());
} }
@Override /**
* 认证Provider,提供获取用户信息、认证、授权等功能
*
* @return AuthenticationProvider
*/
@Bean @Bean
protected AuthenticationManager authenticationManager() throws Exception { public AuthenticationProvider authProvider() {
return super.authenticationManager(); return new CustomUserDetailsAuthenticationProvider(encoder(), userDetailsService);
} }
@Override @Override
protected void configure(HttpSecurity http) throws Exception { @Bean
http. protected AuthenticationManager authenticationManager() throws Exception {
csrf().disable() return super.authenticationManager();
.authorizeRequests()
.anyRequest().authenticated();
} }
} }
...@@ -57,13 +57,12 @@ public class SwaggerConfig implements WebMvcConfigurer { ...@@ -57,13 +57,12 @@ public class SwaggerConfig implements WebMvcConfigurer {
.title("Swagger API") .title("Swagger API")
.description("https://gitee.com/wells2333/spring-microservice-exam") .description("https://gitee.com/wells2333/spring-microservice-exam")
.termsOfServiceUrl("https://gitee.com/wells2333/spring-microservice-exam") .termsOfServiceUrl("https://gitee.com/wells2333/spring-microservice-exam")
.contact(new Contact("tangyi","https://gitee.com/wells2333/spring-microservice-exam","1633736729@qq.com")) .contact(new Contact("tangyi", "https://gitee.com/wells2333/spring-microservice-exam", "1633736729@qq.com"))
.version("2.0") .version("2.0")
.build(); .build();
} }
/** /**
*
* 显示swagger-ui.html文档展示页,还必须注入swagger资源: * 显示swagger-ui.html文档展示页,还必须注入swagger资源:
* *
* @param registry * @param registry
......
...@@ -32,7 +32,7 @@ public class AuthenticationController extends BaseController { ...@@ -32,7 +32,7 @@ public class AuthenticationController extends BaseController {
* @param authentication 信息 * @param authentication 信息
* @return 用户信息 * @return 用户信息
*/ */
@RequestMapping("/user") @RequestMapping("user")
public Object user(Authentication authentication) { public Object user(Authentication authentication) {
return authentication.getPrincipal(); return authentication.getPrincipal();
} }
...@@ -43,7 +43,7 @@ public class AuthenticationController extends BaseController { ...@@ -43,7 +43,7 @@ public class AuthenticationController extends BaseController {
* @param accesstoken access_token * @param accesstoken access_token
* @return ReturnT * @return ReturnT
*/ */
@PostMapping("/removeToken") @PostMapping("removeToken")
public ResponseBean<Boolean> removeToken(@RequestHeader("Authorization") String accesstoken) { public ResponseBean<Boolean> removeToken(@RequestHeader("Authorization") String accesstoken) {
if (accesstoken.startsWith(CommonConstant.AUTHORIZATION_BEARER)) if (accesstoken.startsWith(CommonConstant.AUTHORIZATION_BEARER))
accesstoken = accesstoken.split(CommonConstant.AUTHORIZATION_BEARER)[1]; accesstoken = accesstoken.split(CommonConstant.AUTHORIZATION_BEARER)[1];
......
...@@ -10,7 +10,6 @@ import com.github.tangyi.common.core.utils.SysUtil; ...@@ -10,7 +10,6 @@ import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.utils.SecurityUtil;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
...@@ -18,7 +17,6 @@ import io.swagger.annotations.ApiOperation; ...@@ -18,7 +17,6 @@ import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
...@@ -120,7 +118,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -120,7 +118,7 @@ public class OauthClientDetailsController extends BaseController {
@ApiImplicitParam(name = "oauthClientDetails", value = "客户端实体oauthClientDetails", required = true, dataType = "OauthClientDetails") @ApiImplicitParam(name = "oauthClientDetails", value = "客户端实体oauthClientDetails", required = true, dataType = "OauthClientDetails")
@Log("新增客户端") @Log("新增客户端")
public ResponseBean<Boolean> oauthClient(@RequestBody OauthClientDetails oauthClientDetails) { public ResponseBean<Boolean> oauthClient(@RequestBody OauthClientDetails oauthClientDetails) {
oauthClientDetails.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); oauthClientDetails.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode());
// 加密密钥 // 加密密钥
oauthClientDetails.setClientSecret(bCryptPasswordEncoder.encode(oauthClientDetails.getClientSecretPlainText())); oauthClientDetails.setClientSecret(bCryptPasswordEncoder.encode(oauthClientDetails.getClientSecretPlainText()));
return new ResponseBean<>(oauthClientDetailsService.insert(oauthClientDetails) > 0); return new ResponseBean<>(oauthClientDetailsService.insert(oauthClientDetails) > 0);
...@@ -144,7 +142,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -144,7 +142,7 @@ public class OauthClientDetailsController extends BaseController {
// 有调整过明文则重新加密密钥 // 有调整过明文则重新加密密钥
if (tempOauthClientDetails != null && !tempOauthClientDetails.getClientSecretPlainText().equals(oauthClientDetails.getClientSecretPlainText())) if (tempOauthClientDetails != null && !tempOauthClientDetails.getClientSecretPlainText().equals(oauthClientDetails.getClientSecretPlainText()))
oauthClientDetails.setClientSecret(bCryptPasswordEncoder.encode(oauthClientDetails.getClientSecretPlainText())); oauthClientDetails.setClientSecret(bCryptPasswordEncoder.encode(oauthClientDetails.getClientSecretPlainText()));
oauthClientDetails.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); oauthClientDetails.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode());
return new ResponseBean<>(oauthClientDetailsService.update(oauthClientDetails) > 0); return new ResponseBean<>(oauthClientDetailsService.update(oauthClientDetails) > 0);
} }
...@@ -165,7 +163,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -165,7 +163,7 @@ public class OauthClientDetailsController extends BaseController {
OauthClientDetails oauthClientDetails = new OauthClientDetails(); OauthClientDetails oauthClientDetails = new OauthClientDetails();
oauthClientDetails.setId(id); oauthClientDetails.setId(id);
oauthClientDetails.setNewRecord(false); oauthClientDetails.setNewRecord(false);
oauthClientDetails.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); oauthClientDetails.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode());
return new ResponseBean<>(oauthClientDetailsService.delete(oauthClientDetails) > 0); return new ResponseBean<>(oauthClientDetailsService.delete(oauthClientDetails) > 0);
} }
...@@ -177,7 +175,7 @@ public class OauthClientDetailsController extends BaseController { ...@@ -177,7 +175,7 @@ public class OauthClientDetailsController extends BaseController {
* @author tangyi * @author tangyi
* @date 2019/03/30 17:01 * @date 2019/03/30 17:01
*/ */
@PostMapping("/deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('sys:client:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')") @PreAuthorize("hasAuthority('sys:client:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "批量删除客户端", notes = "根据客户端id批量删除客户端") @ApiOperation(value = "批量删除客户端", notes = "根据客户端id批量删除客户端")
@ApiImplicitParam(name = "oauthClientDetails", value = "客户端信息", dataType = "OauthClientDetails") @ApiImplicitParam(name = "oauthClientDetails", value = "客户端信息", dataType = "OauthClientDetails")
......
package com.github.tangyi.auth.model;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
/**
* 用户信息
*
* @author tangyi
* @date 2019/5/28 21:13
*/
@Data
public class CustomUserDetails extends User {
private static final long serialVersionUID = 1L;
private String tenantCode;
/**
* 构造方法
*
* @param username username
* @param password password
* @param enabled enabled
* @param authorities authorities
* @param tenantCode tenantCode
*/
public CustomUserDetails(String username, String password, boolean enabled, Collection<? extends GrantedAuthority> authorities, String tenantCode) {
super(username, password, enabled, true, true, true, authorities);
this.tenantCode = tenantCode;
}
}
package com.github.tangyi.auth.security;
import com.github.tangyi.auth.model.CustomUserDetails;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.constant.ServiceConstant;
import com.github.tangyi.common.core.model.Log;
import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.user.api.feign.UserServiceClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import java.security.Principal;
/**
* 监听登录成功事件,记录登录信息
*
* @author tangyi
* @date 2019-05-30 23:23
*/
@Slf4j
@AllArgsConstructor
@Component
public class CustomAuthenticationSuccessHandler {
private final UserServiceClient userServiceClient;
@EventListener({AuthenticationSuccessEvent.class, InteractiveAuthenticationSuccessEvent.class})
public void processAuthenticationSuccessEvent(AbstractAuthenticationEvent event) {
// 注意:登录包括oauth2客户端、用户名密码登录都会触发AuthenticationSuccessEvent,这里只记录用户名密码登录的日志
if (event.getAuthentication().getPrincipal() instanceof CustomUserDetails) {
CustomUserDetails userDetails = (CustomUserDetails) event.getAuthentication().getPrincipal();
String tenantCode = userDetails.getTenantCode();
String username = userDetails.getUsername();
log.info("CustomAuthenticationSuccessHandler->登录成功, tenantCode: {}, username: {}", tenantCode, username);
// 记录日志
Log logInfo = new Log();
logInfo.setCommonValue(username, SysUtil.getSysCode(), tenantCode);
logInfo.setTitle("用户登录");
logInfo.setType(CommonConstant.STATUS_NORMAL);
// 获取ip、浏览器信息
this.initLogInfo(logInfo, event.getSource());
logInfo.setServiceId(ServiceConstant.AUTH_SERVICE);
saveLoginSuccessLog(logInfo);
}
}
/**
* 参考源码:
* org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter
* org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationDetails
*
* @param logInfo logInfo
* @param source source
*/
private void initLogInfo(Log logInfo, Object source) {
if (source instanceof OAuth2Authentication) {
OAuth2Authentication auth2Authentication = (OAuth2Authentication) source;
Object details = auth2Authentication.getDetails();
if (details instanceof OAuth2AuthenticationDetails) {
OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) details;
logInfo.setIp(oAuth2AuthenticationDetails.getRemoteAddress());
}
} else if (source instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) source;
Object details = token.getDetails();
if (details instanceof WebAuthenticationDetails) {
WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) details;
logInfo.setIp(webAuthenticationDetails.getRemoteAddress());
}
}
}
/**
* 获取用户名
*
* @param authentication authentication
* @return String
*/
private String getUsername(Authentication authentication) {
String username = "";
Object principal = authentication.getPrincipal();
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
} else if (principal instanceof Principal) {
username = ((Principal) principal).getName();
}
return username;
}
/**
* 异步记录登录日志
*
* @author tangyi
* @date 2019/05/30 23:30
*/
@Async
public void saveLoginSuccessLog(Log logInfo) {
try {
userServiceClient.saveLog(logInfo);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
}
package com.github.tangyi.auth.security;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.tenant.TenantContextHolder;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import java.util.HashMap;
import java.util.Map;
/**
* 扩展JwtAccessTokenConverter,增加租户code
*
* @author tangyi
* @date 2019/5/28 22:53
*/
public class CustomTokenConverter extends JwtAccessTokenConverter {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
if (authentication.getOAuth2Request().getGrantType().equalsIgnoreCase(CommonConstant.GRANT_TYPE_PASSWORD)) {
final Map<String, Object> additionalInfo = new HashMap<>();
// 加入tenantCode
additionalInfo.put("tenantCode", TenantContextHolder.getTenantCode());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
}
return super.enhance(accessToken, authentication);
}
}
package com.github.tangyi.auth.security;
import com.github.tangyi.common.core.exceptions.TenantNotFoundException;
import com.github.tangyi.common.core.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* 认证Provider,提供获取用户信息、认证、授权等功能
*
* @author tangyi
* @date 2019/5/28 21:26
*/
@Slf4j
public class CustomUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
private static final String USER_NOT_FOUND_PASSWORD = "userNotFoundPassword";
private PasswordEncoder passwordEncoder;
private CustomUserDetailsService userDetailsService;
private String userNotFoundEncodedPassword;
public CustomUserDetailsAuthenticationProvider(PasswordEncoder passwordEncoder, CustomUserDetailsService userDetailsService) {
this.passwordEncoder = passwordEncoder;
this.userDetailsService = userDetailsService;
}
@Override
protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
if (authentication.getCredentials() == null) {
log.debug("认证失败: 密码为空.");
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "密码为空."));
}
// 获取密码
String presentedPassword = authentication.getCredentials().toString();
// 匹配密码
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
log.debug("认证失败: 密码错误.");
throw new BadCredentialsException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "密码错误."));
}
}
@Override
protected void doAfterPropertiesSet() throws Exception {
if (this.userDetailsService == null)
throw new IllegalArgumentException("UserDetailsService不能为空.");
this.userNotFoundEncodedPassword = this.passwordEncoder.encode(USER_NOT_FOUND_PASSWORD);
}
/**
* 加载用户信息
*
* @param username username
* @param authentication authentication
* @return UserDetails
* @throws AuthenticationException
*/
@Override
protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException, TenantNotFoundException{
UserDetails loadedUser;
try {
// 加载用户信息
loadedUser = this.userDetailsService.loadUserByUsernameAndTenantCode(authentication.getPrincipal().toString(), TenantContextHolder.getTenantCode());
} catch (TenantNotFoundException tenantNotFound) {
throw tenantNotFound;
} catch (UsernameNotFoundException notFound) {
if (authentication.getCredentials() != null) {
String presentedPassword = authentication.getCredentials().toString();
passwordEncoder.matches(presentedPassword, userNotFoundEncodedPassword);
}
throw notFound;
} catch (Exception repositoryProblem) {
throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
}
if (loadedUser == null) {
throw new InternalAuthenticationServiceException("获取用户信息失败.");
}
return loadedUser;
}
}
package com.github.tangyi.auth.security;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
/**
* 查询用户信息接口
*
* @author tangyi
* @date 2019/5/28 21:05
*/
public interface CustomUserDetailsService {
/**
* 根据用户名和租户标识查询
*
* @param username username
* @param tenantCode tenantCode
* @return UserDetails
* @author tangyi
* @date 2019/05/28 21:06
*/
UserDetails loadUserByUsernameAndTenantCode(String username, String tenantCode) throws UsernameNotFoundException;
}
package com.github.tangyi.auth.service; package com.github.tangyi.auth.security;
import com.github.tangyi.auth.model.CustomUserDetails;
import com.github.tangyi.auth.properties.SysProperties; import com.github.tangyi.auth.properties.SysProperties;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.exceptions.TenantNotFoundException;
import com.github.tangyi.common.core.vo.Role; import com.github.tangyi.common.core.vo.Role;
import com.github.tangyi.common.core.vo.UserVo; import com.github.tangyi.common.core.vo.UserVo;
import com.github.tangyi.common.security.core.GrantedAuthorityImpl; import com.github.tangyi.common.security.core.GrantedAuthorityImpl;
import com.github.tangyi.common.security.core.UserDetailsImpl;
import com.github.tangyi.user.api.constant.MenuConstant; import com.github.tangyi.user.api.constant.MenuConstant;
import com.github.tangyi.user.api.feign.UserServiceClient; import com.github.tangyi.user.api.feign.UserServiceClient;
import com.github.tangyi.user.api.module.Menu; import com.github.tangyi.user.api.module.Menu;
import com.github.tangyi.user.api.module.Tenant;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.apache.commons.lang.StringUtils;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
* 模拟从数据库获取用户信息 * 从数据库获取用户信息
* *
* @author tangyi * @author tangyi
* @date 2019-03-14 14:36 * @date 2019-03-14 14:36
*/ */
@Service @AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService { @Service("userDetailsService")
public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
@Autowired private final UserServiceClient userServiceClient;
private UserServiceClient userServiceClient;
@Autowired private final SysProperties sysProperties;
private SysProperties sysProperties;
/** /**
* 加载用户信息 * 加载用户信息
* *
* @param username 用户名 * @param username 用户名
* @return UserDetails * @return UserDetails
* @throws UsernameNotFoundException * @throws UsernameNotFoundException,TenantNotFoundException
*/ */
@Override @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { public UserDetails loadUserByUsernameAndTenantCode(String username, String tenantCode) throws UsernameNotFoundException, TenantNotFoundException {
UserDetails userDetails; if (StringUtils.isBlank(tenantCode))
try { throw new TenantNotFoundException("租户code不能为空.");
UserVo userVo = userServiceClient.findUserByUsername(username); // 先获取租户信息
if (userVo == null) Tenant tenant = userServiceClient.findTenantByTenantCode(tenantCode);
throw new UsernameNotFoundException("User name not found."); if (tenant == null)
userDetails = new UserDetailsImpl(username, userVo.getPassword(), userVo.getStatus(), getAuthority(userVo)); throw new TenantNotFoundException("租户不存在.");
} catch (Exception e) { UserVo userVo = userServiceClient.findUserByUsername(username, tenantCode);
throw new UsernameNotFoundException("Exception occurred wile reading user info."); if (userVo == null)
} throw new UsernameNotFoundException("用户名不存在.");
return userDetails; return new CustomUserDetails(username, userVo.getPassword(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode());
} }
/** /**
...@@ -80,17 +82,16 @@ public class UserDetailsServiceImpl implements UserDetailsService { ...@@ -80,17 +82,16 @@ public class UserDetailsServiceImpl implements UserDetailsService {
// 判断是否是管理员,是则查找所有菜单权限 // 判断是否是管理员,是则查找所有菜单权限
if (userVo.getUsername().equals(sysProperties.getAdminUser())) { if (userVo.getUsername().equals(sysProperties.getAdminUser())) {
// 查找所有菜单权限,因为角色一般是一个,这里只会执行一次 // 查找所有菜单权限,因为角色一般是一个,这里只会执行一次
menuStream = userServiceClient.findAllMenu().stream(); menuStream = userServiceClient.findAllMenu(userVo.getTenantCode()).stream();
} else { } else {
// 根据角色查找菜单权限 // 根据角色查找菜单权限
menuStream = userServiceClient.findMenuByRole(role.getRoleCode()).stream(); menuStream = userServiceClient.findMenuByRole(role.getRoleCode(), userVo.getTenantCode()).stream();
}
if (Optional.ofNullable(menuStream).isPresent()) {
menuStream
// 菜单权限
.filter(menu -> MenuConstant.MENU_TYPE_PERMISSION.equals(menu.getType()))
.forEach(menu -> authorities.add(new GrantedAuthorityImpl(menu.getPermission())));
} }
// 菜单权限
List<GrantedAuthority> menus = menuStream
.filter(menu -> MenuConstant.MENU_TYPE_PERMISSION.equals(menu.getType()))
.map(menu -> new GrantedAuthorityImpl(menu.getPermission())).collect(Collectors.toList());
authorities.addAll(menus);
}); });
} }
return authorities; return authorities;
......
package com.github.tangyi.auth.security;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.*;
import java.io.IOException;
/**
* 获取请求里的租户code
*
* @author tangyi
* @date 2019/5/28 22:53
*/
@Slf4j
public class TenantTokenFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
String tenantCode = servletRequest.getParameter(CommonConstant.TENANT_CODE);
if (tenantCode != null)
TenantContextHolder.setTenantCode(tenantCode);
log.info("租户code:{}", tenantCode);
filterChain.doFilter(servletRequest, servletResponse);
}
}
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false"> <configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue="spring-microservice-exam"/> <springProperty scop="context" name="spring.application.name" source="spring.application.name"
<property name="log.path" value="logs/${spring.application.name}" /> defaultValue="spring-microservice-exam"/>
<property name="log.path" value="logs/${spring.application.name}"/>
<!-- Console log output --> <!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
...@@ -40,8 +41,8 @@ ...@@ -40,8 +41,8 @@
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 --> <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console"/>
<appender-ref ref="debug" /> <appender-ref ref="debug"/>
<appender-ref ref="error" /> <appender-ref ref="error"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
del_flag = 1 del_flag = 1
WHERE id in WHERE id in
<foreach item="item" index="index" collection="array" open="(" <foreach item="item" index="index" collection="array" open="("
separator="," close=")"> #{item} separator="," close=")">#{item}
</foreach> </foreach>
</delete> </delete>
</mapper> </mapper>
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.github.tangyi</groupId> <groupId>com.github.tangyi</groupId>
<artifactId>service-api-impl</artifactId> <artifactId>service-api-impl</artifactId>
<version>2.0</version> <version>3.0.0</version>
</parent> </parent>
<artifactId>exam-service</artifactId> <artifactId>exam-service</artifactId>
<name>${project.artifactId}</name> <name>${project.artifactId}</name>
......
...@@ -20,8 +20,8 @@ import org.springframework.security.config.annotation.method.configuration.Enabl ...@@ -20,8 +20,8 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
@RefreshScope @RefreshScope
public class ExamServiceApplication { public class ExamServiceApplication {
public static void main(String[] args) { public static void main(String[] args) {
SpringApplication.run(ExamServiceApplication.class, args); SpringApplication.run(ExamServiceApplication.class, args);
} }
} }
...@@ -57,13 +57,12 @@ public class SwaggerConfig implements WebMvcConfigurer { ...@@ -57,13 +57,12 @@ public class SwaggerConfig implements WebMvcConfigurer {
.title("Swagger API") .title("Swagger API")
.description("https://gitee.com/wells2333/spring-microservice-exam") .description("https://gitee.com/wells2333/spring-microservice-exam")
.termsOfServiceUrl("https://gitee.com/wells2333/spring-microservice-exam") .termsOfServiceUrl("https://gitee.com/wells2333/spring-microservice-exam")
.contact(new Contact("tangyi","https://gitee.com/wells2333/spring-microservice-exam","1633736729@qq.com")) .contact(new Contact("tangyi", "https://gitee.com/wells2333/spring-microservice-exam", "1633736729@qq.com"))
.version("2.0") .version("2.0")
.build(); .build();
} }
/** /**
*
* 显示swagger-ui.html文档展示页,还必须注入swagger资源: * 显示swagger-ui.html文档展示页,还必须注入swagger资源:
* *
* @param registry * @param registry
......
...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.PageUtil; ...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.SubjectDto; import com.github.tangyi.exam.api.dto.SubjectDto;
import com.github.tangyi.exam.api.module.Answer; import com.github.tangyi.exam.api.module.Answer;
import com.github.tangyi.exam.service.AnswerService; import com.github.tangyi.exam.service.AnswerService;
...@@ -17,9 +16,10 @@ import io.swagger.annotations.ApiImplicitParams; ...@@ -17,9 +16,10 @@ import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/** /**
* 答题controller * 答题controller
* *
...@@ -48,11 +48,8 @@ public class AnswerController extends BaseController { ...@@ -48,11 +48,8 @@ public class AnswerController extends BaseController {
@ApiImplicitParam(name = "id", value = "答题ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "答题ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<Answer> answer(@PathVariable String id) { public ResponseBean<Answer> answer(@PathVariable String id) {
Answer answer = new Answer(); Answer answer = new Answer();
if (StringUtils.isNotBlank(id)) { answer.setId(id);
answer.setId(id); return new ResponseBean<>(answerService.get(answer));
answer = answerService.get(answer);
}
return new ResponseBean<>(answer);
} }
/** /**
...@@ -81,6 +78,7 @@ public class AnswerController extends BaseController { ...@@ -81,6 +78,7 @@ public class AnswerController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
Answer answer) { Answer answer) {
answer.setTenantCode(SysUtil.getTenantCode());
return answerService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), answer); return answerService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), answer);
} }
...@@ -96,8 +94,8 @@ public class AnswerController extends BaseController { ...@@ -96,8 +94,8 @@ public class AnswerController extends BaseController {
@ApiOperation(value = "创建答题", notes = "创建答题") @ApiOperation(value = "创建答题", notes = "创建答题")
@ApiImplicitParam(name = "answer", value = "答题实体answer", required = true, dataType = "Answer") @ApiImplicitParam(name = "answer", value = "答题实体answer", required = true, dataType = "Answer")
@Log("新增答题") @Log("新增答题")
public ResponseBean<Boolean> addAnswer(@RequestBody Answer answer) { public ResponseBean<Boolean> addAnswer(@RequestBody @Valid Answer answer) {
answer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); answer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(answerService.insert(answer) > 0); return new ResponseBean<>(answerService.insert(answer) > 0);
} }
...@@ -113,8 +111,8 @@ public class AnswerController extends BaseController { ...@@ -113,8 +111,8 @@ public class AnswerController extends BaseController {
@ApiOperation(value = "更新答题信息", notes = "根据答题id更新答题的基本信息") @ApiOperation(value = "更新答题信息", notes = "根据答题id更新答题的基本信息")
@ApiImplicitParam(name = "answer", value = "答题实体answer", required = true, dataType = "Answer") @ApiImplicitParam(name = "answer", value = "答题实体answer", required = true, dataType = "Answer")
@Log("修改答题") @Log("修改答题")
public ResponseBean<Boolean> updateAnswer(@RequestBody Answer answer) { public ResponseBean<Boolean> updateAnswer(@RequestBody @Valid Answer answer) {
answer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); answer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(answerService.update(answer) > 0); return new ResponseBean<>(answerService.update(answer) > 0);
} }
...@@ -135,7 +133,7 @@ public class AnswerController extends BaseController { ...@@ -135,7 +133,7 @@ public class AnswerController extends BaseController {
try { try {
Answer answer = answerService.get(id); Answer answer = answerService.get(id);
if (answer != null) { if (answer != null) {
answer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); answer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
success = answerService.delete(answer) > 0; success = answerService.delete(answer) > 0;
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -156,7 +154,7 @@ public class AnswerController extends BaseController { ...@@ -156,7 +154,7 @@ public class AnswerController extends BaseController {
@ApiOperation(value = "保存答题", notes = "保存答题") @ApiOperation(value = "保存答题", notes = "保存答题")
@ApiImplicitParam(name = "answer", value = "答题信息", dataType = "Answer") @ApiImplicitParam(name = "answer", value = "答题信息", dataType = "Answer")
@Log("保存答题") @Log("保存答题")
public ResponseBean<Boolean> save(@RequestBody Answer answer) { public ResponseBean<Boolean> save(@RequestBody @Valid Answer answer) {
return new ResponseBean<>(answerService.save(answer) > 0); return new ResponseBean<>(answerService.save(answer) > 0);
} }
...@@ -171,7 +169,7 @@ public class AnswerController extends BaseController { ...@@ -171,7 +169,7 @@ public class AnswerController extends BaseController {
@PostMapping("saveAndNext") @PostMapping("saveAndNext")
@ApiOperation(value = "保存答题", notes = "保存答题") @ApiOperation(value = "保存答题", notes = "保存答题")
@ApiImplicitParam(name = "answer", value = "答题信息", dataType = "Answer") @ApiImplicitParam(name = "answer", value = "答题信息", dataType = "Answer")
public ResponseBean<SubjectDto> saveAndNext(@RequestBody Answer answer) { public ResponseBean<SubjectDto> saveAndNext(@RequestBody @Valid Answer answer) {
return new ResponseBean<>(answerService.saveAndNext(answer)); return new ResponseBean<>(answerService.saveAndNext(answer));
} }
......
...@@ -8,7 +8,6 @@ import com.github.tangyi.common.core.utils.SysUtil; ...@@ -8,7 +8,6 @@ import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.module.Course; import com.github.tangyi.exam.api.module.Course;
import com.github.tangyi.exam.service.CourseService; import com.github.tangyi.exam.service.CourseService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
...@@ -21,6 +20,8 @@ import org.apache.commons.lang.StringUtils; ...@@ -21,6 +20,8 @@ import org.apache.commons.lang.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
/** /**
* 课程controller * 课程controller
* *
...@@ -49,11 +50,8 @@ public class CourseController extends BaseController { ...@@ -49,11 +50,8 @@ public class CourseController extends BaseController {
@ApiImplicitParam(name = "id", value = "课程ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "课程ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<Course> course(@PathVariable String id) { public ResponseBean<Course> course(@PathVariable String id) {
Course course = new Course(); Course course = new Course();
if (StringUtils.isNotBlank(id)) { course.setId(id);
course.setId(id); return new ResponseBean<>(courseService.get(course));
course = courseService.get(course);
}
return new ResponseBean<>(course);
} }
/** /**
...@@ -82,6 +80,7 @@ public class CourseController extends BaseController { ...@@ -82,6 +80,7 @@ public class CourseController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
Course course) { Course course) {
course.setTeacher(SysUtil.getTenantCode());
return courseService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), course); return courseService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), course);
} }
...@@ -94,12 +93,12 @@ public class CourseController extends BaseController { ...@@ -94,12 +93,12 @@ public class CourseController extends BaseController {
* @date 2018/11/10 21:31 * @date 2018/11/10 21:31
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:course:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:course:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "创建课程", notes = "创建课程") @ApiOperation(value = "创建课程", notes = "创建课程")
@ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course") @ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course")
@Log("新增课程") @Log("新增课程")
public ResponseBean<Boolean> addCourse(@RequestBody Course course) { public ResponseBean<Boolean> addCourse(@RequestBody @Valid Course course) {
course.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); course.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(courseService.insert(course) > 0); return new ResponseBean<>(courseService.insert(course) > 0);
} }
...@@ -112,12 +111,12 @@ public class CourseController extends BaseController { ...@@ -112,12 +111,12 @@ public class CourseController extends BaseController {
* @date 2018/11/10 21:31 * @date 2018/11/10 21:31
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:course:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:course:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "更新课程信息", notes = "根据课程id更新课程的基本信息") @ApiOperation(value = "更新课程信息", notes = "根据课程id更新课程的基本信息")
@ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course") @ApiImplicitParam(name = "course", value = "课程实体course", required = true, dataType = "Course")
@Log("更新课程") @Log("更新课程")
public ResponseBean<Boolean> updateCourse(@RequestBody Course course) { public ResponseBean<Boolean> updateCourse(@RequestBody @Valid Course course) {
course.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); course.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(courseService.update(course) > 0); return new ResponseBean<>(courseService.update(course) > 0);
} }
...@@ -130,7 +129,7 @@ public class CourseController extends BaseController { ...@@ -130,7 +129,7 @@ public class CourseController extends BaseController {
* @date 2018/11/10 21:32 * @date 2018/11/10 21:32
*/ */
@DeleteMapping("{id}") @DeleteMapping("{id}")
@PreAuthorize("hasAuthority('exam:course:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:course:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "删除课程", notes = "根据ID删除课程") @ApiOperation(value = "删除课程", notes = "根据ID删除课程")
@ApiImplicitParam(name = "id", value = "课程ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "课程ID", required = true, paramType = "path")
@Log("删除课程") @Log("删除课程")
...@@ -141,7 +140,7 @@ public class CourseController extends BaseController { ...@@ -141,7 +140,7 @@ public class CourseController extends BaseController {
course.setId(id); course.setId(id);
course = courseService.get(course); course = courseService.get(course);
if (course != null) { if (course != null) {
course.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); course.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
success = courseService.delete(course) > 0; success = courseService.delete(course) > 0;
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -158,8 +157,8 @@ public class CourseController extends BaseController { ...@@ -158,8 +157,8 @@ public class CourseController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/12/4 11:26 * @date 2018/12/4 11:26
*/ */
@PostMapping("/deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('exam:course:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:course:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "批量删除课程", notes = "根据课程id批量删除课程") @ApiOperation(value = "批量删除课程", notes = "根据课程id批量删除课程")
@ApiImplicitParam(name = "course", value = "课程信息", dataType = "Course") @ApiImplicitParam(name = "course", value = "课程信息", dataType = "Course")
@Log("批量删除课程") @Log("批量删除课程")
......
...@@ -12,7 +12,7 @@ import java.security.Principal; ...@@ -12,7 +12,7 @@ import java.security.Principal;
@RestController @RestController
public class ExamController { public class ExamController {
@GetMapping("/sayHello") @GetMapping("sayHello")
public String sayHello(Principal principal, String name) { public String sayHello(Principal principal, String name) {
return "hello, " + name + ", principal: " + principal.toString(); return "hello, " + name + ", principal: " + principal.toString();
} }
......
...@@ -2,7 +2,6 @@ package com.github.tangyi.exam.controller; ...@@ -2,7 +2,6 @@ package com.github.tangyi.exam.controller;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.github.tangyi.common.core.constant.CommonConstant; import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.exceptions.CommonException;
import com.github.tangyi.common.core.model.ResponseBean; import com.github.tangyi.common.core.model.ResponseBean;
import com.github.tangyi.common.core.utils.*; import com.github.tangyi.common.core.utils.*;
import com.github.tangyi.common.core.vo.DeptVo; import com.github.tangyi.common.core.vo.DeptVo;
...@@ -10,7 +9,6 @@ import com.github.tangyi.common.core.vo.UserVo; ...@@ -10,7 +9,6 @@ import com.github.tangyi.common.core.vo.UserVo;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.ExamRecordDto; import com.github.tangyi.exam.api.dto.ExamRecordDto;
import com.github.tangyi.exam.api.dto.StartExamDto; import com.github.tangyi.exam.api.dto.StartExamDto;
import com.github.tangyi.exam.api.module.ExamRecord; import com.github.tangyi.exam.api.module.ExamRecord;
...@@ -35,6 +33,7 @@ import org.springframework.web.bind.annotation.*; ...@@ -35,6 +33,7 @@ import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
...@@ -76,11 +75,8 @@ public class ExamRecordController extends BaseController { ...@@ -76,11 +75,8 @@ public class ExamRecordController extends BaseController {
@ApiImplicitParam(name = "id", value = "考试记录ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "考试记录ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<ExamRecord> examRecord(@PathVariable String id) { public ResponseBean<ExamRecord> examRecord(@PathVariable String id) {
ExamRecord examRecord = new ExamRecord(); ExamRecord examRecord = new ExamRecord();
if (StringUtils.isNotBlank(id)) { examRecord.setId(id);
examRecord.setId(id); return new ResponseBean<>(examRecordService.get(examRecord));
examRecord = examRecordService.get(examRecord);
}
return new ResponseBean<>(examRecord);
} }
/** /**
...@@ -109,6 +105,7 @@ public class ExamRecordController extends BaseController { ...@@ -109,6 +105,7 @@ public class ExamRecordController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
ExamRecord examRecord) { ExamRecord examRecord) {
examRecord.setTenantCode(SysUtil.getTenantCode());
PageInfo<ExamRecordDto> examRecordDtoPageInfo = new PageInfo<>(); PageInfo<ExamRecordDto> examRecordDtoPageInfo = new PageInfo<>();
List<ExamRecordDto> examRecordDtoList = new ArrayList<>(); List<ExamRecordDto> examRecordDtoList = new ArrayList<>();
// 查询考试记录 // 查询考试记录
...@@ -194,11 +191,7 @@ public class ExamRecordController extends BaseController { ...@@ -194,11 +191,7 @@ public class ExamRecordController extends BaseController {
@ApiOperation(value = "创建考试记录", notes = "创建考试记录") @ApiOperation(value = "创建考试记录", notes = "创建考试记录")
@ApiImplicitParam(name = "examRecord", value = "考试记录实体examRecord", required = true, dataType = "ExamRecord") @ApiImplicitParam(name = "examRecord", value = "考试记录实体examRecord", required = true, dataType = "ExamRecord")
@Log("新增考试记录") @Log("新增考试记录")
public ResponseBean<ExamRecord> addExamRecord(@RequestBody ExamRecord examRecord) { public ResponseBean<ExamRecord> addExamRecord(@RequestBody @Valid ExamRecord examRecord) {
if (StringUtils.isEmpty(examRecord.getExaminationId()))
throw new CommonException("参数校验失败,考试id为空!");
if (StringUtils.isEmpty(examRecord.getUserId()))
throw new CommonException("参数校验失败,用户id为空!");
Examination examination = new Examination(); Examination examination = new Examination();
examination.setId(examRecord.getExaminationId()); examination.setId(examRecord.getExaminationId());
// 查找考试信息 // 查找考试信息
...@@ -207,7 +200,7 @@ public class ExamRecordController extends BaseController { ...@@ -207,7 +200,7 @@ public class ExamRecordController extends BaseController {
examRecord.setExaminationName(examination.getExaminationName()); examRecord.setExaminationName(examination.getExaminationName());
examRecord.setCourseId(examination.getCourseId()); examRecord.setCourseId(examination.getCourseId());
} }
examRecord.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); examRecord.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
examRecord.setStartTime(examRecord.getCreateDate()); examRecord.setStartTime(examRecord.getCreateDate());
examRecordService.insert(examRecord); examRecordService.insert(examRecord);
return new ResponseBean<>(examRecord); return new ResponseBean<>(examRecord);
...@@ -225,8 +218,8 @@ public class ExamRecordController extends BaseController { ...@@ -225,8 +218,8 @@ public class ExamRecordController extends BaseController {
@ApiOperation(value = "更新考试记录信息", notes = "根据考试记录id更新考试记录的基本信息") @ApiOperation(value = "更新考试记录信息", notes = "根据考试记录id更新考试记录的基本信息")
@ApiImplicitParam(name = "examRecord", value = "考试记录实体examRecord", required = true, dataType = "ExamRecord") @ApiImplicitParam(name = "examRecord", value = "考试记录实体examRecord", required = true, dataType = "ExamRecord")
@Log("更新考试记录") @Log("更新考试记录")
public ResponseBean<Boolean> updateExamRecord(@RequestBody ExamRecord examRecord) { public ResponseBean<Boolean> updateExamRecord(@RequestBody @Valid ExamRecord examRecord) {
examRecord.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); examRecord.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(examRecordService.update(examRecord) > 0); return new ResponseBean<>(examRecordService.update(examRecord) > 0);
} }
...@@ -247,7 +240,7 @@ public class ExamRecordController extends BaseController { ...@@ -247,7 +240,7 @@ public class ExamRecordController extends BaseController {
try { try {
ExamRecord examRecord = examRecordService.get(id); ExamRecord examRecord = examRecordService.get(id);
if (examRecord != null) { if (examRecord != null) {
examRecord.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); examRecord.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
success = examRecordService.delete(examRecord) > 0; success = examRecordService.delete(examRecord) > 0;
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -263,8 +256,8 @@ public class ExamRecordController extends BaseController { ...@@ -263,8 +256,8 @@ public class ExamRecordController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/12/31 22:28 * @date 2018/12/31 22:28
*/ */
@PostMapping("/export") @PostMapping("export")
@PreAuthorize("hasAuthority('exam:examRecord:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:examRecord:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "导出考试成绩", notes = "根据成绩id导出成绩") @ApiOperation(value = "导出考试成绩", notes = "根据成绩id导出成绩")
@ApiImplicitParam(name = "examRecordDto", value = "成绩信息", required = true, dataType = "ExamRecordDto") @ApiImplicitParam(name = "examRecordDto", value = "成绩信息", required = true, dataType = "ExamRecordDto")
@Log("导出考试记录") @Log("导出考试记录")
...@@ -282,7 +275,9 @@ public class ExamRecordController extends BaseController { ...@@ -282,7 +275,9 @@ public class ExamRecordController extends BaseController {
examRecordList = examRecordService.findListById(examRecord); examRecordList = examRecordService.findListById(examRecord);
} else { } else {
// 导出全部 // 导出全部
examRecordList = examRecordService.findList(new ExamRecord()); ExamRecord examRecord = new ExamRecord();
examRecord.setTenantCode(SysUtil.getTenantCode());
examRecordList = examRecordService.findList(examRecord);
} }
// 查询考试、用户、部门数据 // 查询考试、用户、部门数据
if (CollectionUtils.isNotEmpty(examRecordList)) { if (CollectionUtils.isNotEmpty(examRecordList)) {
......
...@@ -8,7 +8,6 @@ import com.github.tangyi.common.core.utils.SysUtil; ...@@ -8,7 +8,6 @@ import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.ExaminationDto; import com.github.tangyi.exam.api.dto.ExaminationDto;
import com.github.tangyi.exam.api.module.Course; import com.github.tangyi.exam.api.module.Course;
import com.github.tangyi.exam.api.module.Examination; import com.github.tangyi.exam.api.module.Examination;
...@@ -26,6 +25,8 @@ import org.springframework.beans.BeanUtils; ...@@ -26,6 +25,8 @@ import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -59,11 +60,8 @@ public class ExaminationController extends BaseController { ...@@ -59,11 +60,8 @@ public class ExaminationController extends BaseController {
@ApiImplicitParam(name = "id", value = "考试ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "考试ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<Examination> examination(@PathVariable String id) { public ResponseBean<Examination> examination(@PathVariable String id) {
Examination examination = new Examination(); Examination examination = new Examination();
if (StringUtils.isNotBlank(id)) { examination.setId(id);
examination.setId(id); return new ResponseBean<>(examinationService.get(examination));
examination = examinationService.get(examination);
}
return new ResponseBean<>(examination);
} }
/** /**
...@@ -92,6 +90,7 @@ public class ExaminationController extends BaseController { ...@@ -92,6 +90,7 @@ public class ExaminationController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
Examination examination) { Examination examination) {
examination.setTenantCode(SysUtil.getTenantCode());
PageInfo<Examination> page = examinationService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), examination); PageInfo<Examination> page = examinationService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), examination);
PageInfo<ExaminationDto> examinationDtoPageInfo = new PageInfo<>(); PageInfo<ExaminationDto> examinationDtoPageInfo = new PageInfo<>();
BeanUtils.copyProperties(page, examinationDtoPageInfo); BeanUtils.copyProperties(page, examinationDtoPageInfo);
...@@ -122,15 +121,15 @@ public class ExaminationController extends BaseController { ...@@ -122,15 +121,15 @@ public class ExaminationController extends BaseController {
* @date 2018/11/10 21:14 * @date 2018/11/10 21:14
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:exam:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "创建考试", notes = "创建考试") @ApiOperation(value = "创建考试", notes = "创建考试")
@ApiImplicitParam(name = "examinationDto", value = "考试实体examinationDto", required = true, dataType = "ExaminationDto") @ApiImplicitParam(name = "examinationDto", value = "考试实体examinationDto", required = true, dataType = "ExaminationDto")
@Log("新增考试") @Log("新增考试")
public ResponseBean<Boolean> addExamination(@RequestBody ExaminationDto examinationDto) { public ResponseBean<Boolean> addExamination(@RequestBody @Valid ExaminationDto examinationDto) {
Examination examination = new Examination(); Examination examination = new Examination();
BeanUtils.copyProperties(examinationDto, examination); BeanUtils.copyProperties(examinationDto, examination);
examination.setCourseId(examinationDto.getCourse().getId()); examination.setCourseId(examinationDto.getCourse().getId());
examination.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); examination.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(examinationService.insert(examination) > 0); return new ResponseBean<>(examinationService.insert(examination) > 0);
} }
...@@ -143,15 +142,15 @@ public class ExaminationController extends BaseController { ...@@ -143,15 +142,15 @@ public class ExaminationController extends BaseController {
* @date 2018/11/10 21:15 * @date 2018/11/10 21:15
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:exam:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "更新考试信息", notes = "根据考试id更新考试的基本信息") @ApiOperation(value = "更新考试信息", notes = "根据考试id更新考试的基本信息")
@ApiImplicitParam(name = "examinationDto", value = "考试实体answer", required = true, dataType = "ExaminationDto") @ApiImplicitParam(name = "examinationDto", value = "考试实体answer", required = true, dataType = "ExaminationDto")
@Log("更新考试") @Log("更新考试")
public ResponseBean<Boolean> updateExamination(@RequestBody ExaminationDto examinationDto) { public ResponseBean<Boolean> updateExamination(@RequestBody @Valid ExaminationDto examinationDto) {
Examination examination = new Examination(); Examination examination = new Examination();
BeanUtils.copyProperties(examinationDto, examination); BeanUtils.copyProperties(examinationDto, examination);
examination.setCourseId(examinationDto.getCourse().getId()); examination.setCourseId(examinationDto.getCourse().getId());
examination.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); examination.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(examinationService.update(examination) > 0); return new ResponseBean<>(examinationService.update(examination) > 0);
} }
...@@ -164,7 +163,7 @@ public class ExaminationController extends BaseController { ...@@ -164,7 +163,7 @@ public class ExaminationController extends BaseController {
* @date 2018/11/10 21:20 * @date 2018/11/10 21:20
*/ */
@DeleteMapping("{id}") @DeleteMapping("{id}")
@PreAuthorize("hasAuthority('exam:exam:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "删除考试", notes = "根据ID删除考试") @ApiOperation(value = "删除考试", notes = "根据ID删除考试")
@ApiImplicitParam(name = "id", value = "考试ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "考试ID", required = true, paramType = "path")
@Log("删除考试") @Log("删除考试")
...@@ -175,7 +174,7 @@ public class ExaminationController extends BaseController { ...@@ -175,7 +174,7 @@ public class ExaminationController extends BaseController {
examination.setId(id); examination.setId(id);
examination = examinationService.get(examination); examination = examinationService.get(examination);
if (examination != null) { if (examination != null) {
examination.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); examination.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
success = examinationService.delete(examination) > 0; success = examinationService.delete(examination) > 0;
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -192,8 +191,8 @@ public class ExaminationController extends BaseController { ...@@ -192,8 +191,8 @@ public class ExaminationController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/12/03 22:03 * @date 2018/12/03 22:03
*/ */
@PostMapping("/deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('exam:exam:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "批量删除考试", notes = "根据考试id批量删除考试") @ApiOperation(value = "批量删除考试", notes = "根据考试id批量删除考试")
@ApiImplicitParam(name = "examinationDto", value = "考试信息", dataType = "ExaminationDto") @ApiImplicitParam(name = "examinationDto", value = "考试信息", dataType = "ExaminationDto")
@Log("批量删除考试") @Log("批量删除考试")
...@@ -211,14 +210,15 @@ public class ExaminationController extends BaseController { ...@@ -211,14 +210,15 @@ public class ExaminationController extends BaseController {
/** /**
* 查询考试数量 * 查询考试数量
* *
* @param tenantCode 租户标识
* @return ResponseBean * @return ResponseBean
* @author tangyi * @author tangyi
* @date 2019/3/1 15:30 * @date 2019/3/1 15:30
*/ */
@GetMapping("/examinationCount") @GetMapping("examinationCount")
public ResponseBean<Integer> findExaminationCount() { public ResponseBean<Integer> findExaminationCount(@RequestParam @NotBlank String tenantCode) {
Examination examination = new Examination(); Examination examination = new Examination();
examination.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); examination.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), tenantCode);
return new ResponseBean<>(examinationService.findExaminationCount(examination)); return new ResponseBean<>(examinationService.findExaminationCount(examination));
} }
} }
...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.PageUtil; ...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.PageUtil;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.IncorrectAnswerDto; import com.github.tangyi.exam.api.dto.IncorrectAnswerDto;
import com.github.tangyi.exam.api.module.IncorrectAnswer; import com.github.tangyi.exam.api.module.IncorrectAnswer;
import com.github.tangyi.exam.api.module.Subject; import com.github.tangyi.exam.api.module.Subject;
...@@ -20,10 +19,10 @@ import io.swagger.annotations.ApiOperation; ...@@ -20,10 +19,10 @@ import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -57,11 +56,8 @@ public class IncorrectAnswerController extends BaseController { ...@@ -57,11 +56,8 @@ public class IncorrectAnswerController extends BaseController {
@ApiImplicitParam(name = "id", value = "错题ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "错题ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<IncorrectAnswer> examRecord(@PathVariable String id) { public ResponseBean<IncorrectAnswer> examRecord(@PathVariable String id) {
IncorrectAnswer incorrectAnswer = new IncorrectAnswer(); IncorrectAnswer incorrectAnswer = new IncorrectAnswer();
if (StringUtils.isNotBlank(id)) { incorrectAnswer.setId(id);
incorrectAnswer.setId(id); return new ResponseBean<>(incorrectAnswerService.get(incorrectAnswer));
incorrectAnswer = incorrectAnswerService.get(incorrectAnswer);
}
return new ResponseBean<>(incorrectAnswer);
} }
/** /**
...@@ -90,6 +86,7 @@ public class IncorrectAnswerController extends BaseController { ...@@ -90,6 +86,7 @@ public class IncorrectAnswerController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
IncorrectAnswer incorrectAnswer) { IncorrectAnswer incorrectAnswer) {
incorrectAnswer.setTenantCode(SysUtil.getTenantCode());
// 查找错题 // 查找错题
PageInfo<IncorrectAnswer> incorrectAnswerPageInfo = incorrectAnswerService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), incorrectAnswer); PageInfo<IncorrectAnswer> incorrectAnswerPageInfo = incorrectAnswerService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), incorrectAnswer);
PageInfo<IncorrectAnswerDto> pageInfo = new PageInfo<>(); PageInfo<IncorrectAnswerDto> pageInfo = new PageInfo<>();
...@@ -132,8 +129,8 @@ public class IncorrectAnswerController extends BaseController { ...@@ -132,8 +129,8 @@ public class IncorrectAnswerController extends BaseController {
@ApiOperation(value = "创建错题", notes = "创建错题") @ApiOperation(value = "创建错题", notes = "创建错题")
@ApiImplicitParam(name = "incorrectAnswer", value = "错题实体incorrectAnswer", required = true, dataType = "IncorrectAnswer") @ApiImplicitParam(name = "incorrectAnswer", value = "错题实体incorrectAnswer", required = true, dataType = "IncorrectAnswer")
@Log("新增错题") @Log("新增错题")
public ResponseBean<Boolean> addIncorrectAnswer(@RequestBody IncorrectAnswer incorrectAnswer) { public ResponseBean<Boolean> addIncorrectAnswer(@RequestBody @Valid IncorrectAnswer incorrectAnswer) {
incorrectAnswer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); incorrectAnswer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(incorrectAnswerService.insert(incorrectAnswer) > 0); return new ResponseBean<>(incorrectAnswerService.insert(incorrectAnswer) > 0);
} }
...@@ -149,8 +146,8 @@ public class IncorrectAnswerController extends BaseController { ...@@ -149,8 +146,8 @@ public class IncorrectAnswerController extends BaseController {
@ApiOperation(value = "更新错题信息", notes = "根据错题id更新错题的基本信息") @ApiOperation(value = "更新错题信息", notes = "根据错题id更新错题的基本信息")
@ApiImplicitParam(name = "incorrectAnswer", value = "错题实体incorrectAnswer", required = true, dataType = "IncorrectAnswer") @ApiImplicitParam(name = "incorrectAnswer", value = "错题实体incorrectAnswer", required = true, dataType = "IncorrectAnswer")
@Log("更新错题") @Log("更新错题")
public ResponseBean<Boolean> updateIncorrectAnswer(@RequestBody IncorrectAnswer incorrectAnswer) { public ResponseBean<Boolean> updateIncorrectAnswer(@RequestBody @Valid IncorrectAnswer incorrectAnswer) {
incorrectAnswer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); incorrectAnswer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(incorrectAnswerService.update(incorrectAnswer) > 0); return new ResponseBean<>(incorrectAnswerService.update(incorrectAnswer) > 0);
} }
...@@ -171,7 +168,7 @@ public class IncorrectAnswerController extends BaseController { ...@@ -171,7 +168,7 @@ public class IncorrectAnswerController extends BaseController {
try { try {
IncorrectAnswer incorrectAnswer = incorrectAnswerService.get(id); IncorrectAnswer incorrectAnswer = incorrectAnswerService.get(id);
if (incorrectAnswer != null) { if (incorrectAnswer != null) {
incorrectAnswer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); incorrectAnswer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
success = incorrectAnswerService.delete(incorrectAnswer) > 0; success = incorrectAnswerService.delete(incorrectAnswer) > 0;
} }
} catch (Exception e) { } catch (Exception e) {
......
...@@ -8,7 +8,6 @@ import com.github.tangyi.common.core.utils.SysUtil; ...@@ -8,7 +8,6 @@ import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.core.vo.AttachmentVo; import com.github.tangyi.common.core.vo.AttachmentVo;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.KnowledgeDto; import com.github.tangyi.exam.api.dto.KnowledgeDto;
import com.github.tangyi.exam.api.module.Knowledge; import com.github.tangyi.exam.api.module.Knowledge;
import com.github.tangyi.exam.service.KnowledgeService; import com.github.tangyi.exam.service.KnowledgeService;
...@@ -24,6 +23,7 @@ import org.apache.commons.lang.StringUtils; ...@@ -24,6 +23,7 @@ import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
...@@ -59,11 +59,8 @@ public class KnowledgeController extends BaseController { ...@@ -59,11 +59,8 @@ public class KnowledgeController extends BaseController {
@ApiImplicitParam(name = "id", value = "知识ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "知识ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<Knowledge> knowledge(@PathVariable String id) { public ResponseBean<Knowledge> knowledge(@PathVariable String id) {
Knowledge knowledge = new Knowledge(); Knowledge knowledge = new Knowledge();
if (StringUtils.isNotBlank(id)) { knowledge.setId(id);
knowledge.setId(id); return new ResponseBean<>(knowledgeService.get(knowledge));
knowledge = knowledgeService.get(knowledge);
}
return new ResponseBean<>(knowledge);
} }
/** /**
...@@ -92,6 +89,7 @@ public class KnowledgeController extends BaseController { ...@@ -92,6 +89,7 @@ public class KnowledgeController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
Knowledge knowledge) { Knowledge knowledge) {
knowledge.setTenantCode(SysUtil.getTenantCode());
// 查询知识 // 查询知识
PageInfo<Knowledge> knowledgePageInfo = knowledgeService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), knowledge); PageInfo<Knowledge> knowledgePageInfo = knowledgeService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), knowledge);
PageInfo<KnowledgeDto> knowledgeDtoPageInfo = new PageInfo<>(); PageInfo<KnowledgeDto> knowledgeDtoPageInfo = new PageInfo<>();
...@@ -147,8 +145,8 @@ public class KnowledgeController extends BaseController { ...@@ -147,8 +145,8 @@ public class KnowledgeController extends BaseController {
@ApiOperation(value = "创建知识", notes = "创建知识") @ApiOperation(value = "创建知识", notes = "创建知识")
@ApiImplicitParam(name = "knowledge", value = "知识实体knowledge", required = true, dataType = "Knowledge") @ApiImplicitParam(name = "knowledge", value = "知识实体knowledge", required = true, dataType = "Knowledge")
@Log("新增知识") @Log("新增知识")
public ResponseBean<Boolean> addKnowledge(@RequestBody Knowledge knowledge) { public ResponseBean<Boolean> addKnowledge(@RequestBody @Valid Knowledge knowledge) {
knowledge.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); knowledge.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(knowledgeService.insert(knowledge) > 0); return new ResponseBean<>(knowledgeService.insert(knowledge) > 0);
} }
...@@ -164,8 +162,8 @@ public class KnowledgeController extends BaseController { ...@@ -164,8 +162,8 @@ public class KnowledgeController extends BaseController {
@ApiOperation(value = "更新知识信息", notes = "根据知识id更新知识的基本信息") @ApiOperation(value = "更新知识信息", notes = "根据知识id更新知识的基本信息")
@ApiImplicitParam(name = "knowledge", value = "知识实体knowledge", required = true, dataType = "Knowledge") @ApiImplicitParam(name = "knowledge", value = "知识实体knowledge", required = true, dataType = "Knowledge")
@Log("更新知识") @Log("更新知识")
public ResponseBean<Boolean> updateKnowledge(@RequestBody Knowledge knowledge) { public ResponseBean<Boolean> updateKnowledge(@RequestBody @Valid Knowledge knowledge) {
knowledge.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); knowledge.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(knowledgeService.update(knowledge) > 0); return new ResponseBean<>(knowledgeService.update(knowledge) > 0);
} }
...@@ -188,7 +186,7 @@ public class KnowledgeController extends BaseController { ...@@ -188,7 +186,7 @@ public class KnowledgeController extends BaseController {
knowledge.setId(id); knowledge.setId(id);
knowledge = knowledgeService.get(knowledge); knowledge = knowledgeService.get(knowledge);
if (knowledge != null) { if (knowledge != null) {
knowledge.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); knowledge.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
success = knowledgeService.delete(knowledge) > 0; success = knowledgeService.delete(knowledge) > 0;
} }
// 删除附件 // 删除附件
...@@ -208,7 +206,7 @@ public class KnowledgeController extends BaseController { ...@@ -208,7 +206,7 @@ public class KnowledgeController extends BaseController {
* @author tangyi * @author tangyi
* @date 2019/1/1 15:15 * @date 2019/1/1 15:15
*/ */
@PostMapping("/deleteAll") @PostMapping("deleteAll")
@ApiOperation(value = "批量删除知识", notes = "根据知识id批量删除知识") @ApiOperation(value = "批量删除知识", notes = "根据知识id批量删除知识")
@ApiImplicitParam(name = "knowledge", value = "知识信息", dataType = "Knowledge") @ApiImplicitParam(name = "knowledge", value = "知识信息", dataType = "Knowledge")
@Log("批量删除知识") @Log("批量删除知识")
......
...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.*; ...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.*;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.SubjectBankDto; import com.github.tangyi.exam.api.dto.SubjectBankDto;
import com.github.tangyi.exam.api.module.SubjectBank; import com.github.tangyi.exam.api.module.SubjectBank;
import com.github.tangyi.exam.api.module.SubjectCategory; import com.github.tangyi.exam.api.module.SubjectCategory;
...@@ -20,13 +19,14 @@ import lombok.AllArgsConstructor; ...@@ -20,13 +19,14 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -61,11 +61,8 @@ public class SubjectBankController extends BaseController { ...@@ -61,11 +61,8 @@ public class SubjectBankController extends BaseController {
@ApiImplicitParam(name = "id", value = "题库ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "题库ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<SubjectBank> subjectBank(@PathVariable String id) { public ResponseBean<SubjectBank> subjectBank(@PathVariable String id) {
SubjectBank subjectBank = new SubjectBank(); SubjectBank subjectBank = new SubjectBank();
if (StringUtils.isNotBlank(id)) { subjectBank.setId(id);
subjectBank.setId(id); return new ResponseBean<>(subjectBankService.get(subjectBank));
subjectBank = subjectBankService.get(subjectBank);
}
return new ResponseBean<>(subjectBank);
} }
/** /**
...@@ -94,6 +91,7 @@ public class SubjectBankController extends BaseController { ...@@ -94,6 +91,7 @@ public class SubjectBankController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
SubjectBank subjectBank) { SubjectBank subjectBank) {
subjectBank.setTenantCode(SysUtil.getTenantCode());
PageInfo<SubjectBank> page = subjectBankService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), subjectBank); PageInfo<SubjectBank> page = subjectBankService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), subjectBank);
if (CollectionUtils.isNotEmpty(page.getList())) { if (CollectionUtils.isNotEmpty(page.getList())) {
// 查询分类信息 // 查询分类信息
...@@ -125,12 +123,12 @@ public class SubjectBankController extends BaseController { ...@@ -125,12 +123,12 @@ public class SubjectBankController extends BaseController {
* @date 2018/12/9 14:14 * @date 2018/12/9 14:14
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:subject:bank:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:bank:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "创建题库", notes = "创建题库") @ApiOperation(value = "创建题库", notes = "创建题库")
@ApiImplicitParam(name = "subjectBank", value = "题库实体subjectBank", required = true, dataType = "SubjectBank") @ApiImplicitParam(name = "subjectBank", value = "题库实体subjectBank", required = true, dataType = "SubjectBank")
@Log("新增题库") @Log("新增题库")
public ResponseBean<Boolean> addSubjectBank(@RequestBody SubjectBank subjectBank) { public ResponseBean<Boolean> addSubjectBank(@RequestBody @Valid SubjectBank subjectBank) {
subjectBank.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subjectBank.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(subjectBankService.insert(subjectBank) > 0); return new ResponseBean<>(subjectBankService.insert(subjectBank) > 0);
} }
...@@ -143,12 +141,12 @@ public class SubjectBankController extends BaseController { ...@@ -143,12 +141,12 @@ public class SubjectBankController extends BaseController {
* @date 2018/12/9 14:15 * @date 2018/12/9 14:15
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:subject:bank:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:bank:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "更新题库信息", notes = "根据题库id更新题库的基本信息") @ApiOperation(value = "更新题库信息", notes = "根据题库id更新题库的基本信息")
@ApiImplicitParam(name = "subjectBank", value = "题库实体subjectBank", required = true, dataType = "SubjectBank") @ApiImplicitParam(name = "subjectBank", value = "题库实体subjectBank", required = true, dataType = "SubjectBank")
@Log("更新题库") @Log("更新题库")
public ResponseBean<Boolean> updateSubjectBank(@RequestBody SubjectBank subjectBank) { public ResponseBean<Boolean> updateSubjectBank(@RequestBody @Valid SubjectBank subjectBank) {
subjectBank.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subjectBank.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(subjectBankService.update(subjectBank) > 0); return new ResponseBean<>(subjectBankService.update(subjectBank) > 0);
} }
...@@ -161,7 +159,7 @@ public class SubjectBankController extends BaseController { ...@@ -161,7 +159,7 @@ public class SubjectBankController extends BaseController {
* @date 2018/12/9 14:15 * @date 2018/12/9 14:15
*/ */
@DeleteMapping("{id}") @DeleteMapping("{id}")
@PreAuthorize("hasAuthority('exam:subject:bank:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:bank:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "删除题库", notes = "根据ID删除题库") @ApiOperation(value = "删除题库", notes = "根据ID删除题库")
@ApiImplicitParam(name = "id", value = "题库ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "题库ID", required = true, paramType = "path")
@Log("删除题库") @Log("删除题库")
...@@ -172,7 +170,7 @@ public class SubjectBankController extends BaseController { ...@@ -172,7 +170,7 @@ public class SubjectBankController extends BaseController {
subjectBank.setId(id); subjectBank.setId(id);
subjectBank = subjectBankService.get(subjectBank); subjectBank = subjectBankService.get(subjectBank);
if (subjectBank != null) { if (subjectBank != null) {
subjectBank.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subjectBank.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
success = subjectBankService.delete(subjectBank) > 0; success = subjectBankService.delete(subjectBank) > 0;
} }
} catch (Exception e) { } catch (Exception e) {
...@@ -188,8 +186,8 @@ public class SubjectBankController extends BaseController { ...@@ -188,8 +186,8 @@ public class SubjectBankController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/12/9 14:16 * @date 2018/12/9 14:16
*/ */
@PostMapping("/export") @PostMapping("export")
@PreAuthorize("hasAuthority('exam:subject:bank:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:bank:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "导出题目", notes = "根据分类id导出题目") @ApiOperation(value = "导出题目", notes = "根据分类id导出题目")
@ApiImplicitParam(name = "subjectBankDto", value = "分类信息", required = true, dataType = "SubjectBankDto") @ApiImplicitParam(name = "subjectBankDto", value = "分类信息", required = true, dataType = "SubjectBankDto")
@Log("导出题库题目") @Log("导出题库题目")
...@@ -229,12 +227,12 @@ public class SubjectBankController extends BaseController { ...@@ -229,12 +227,12 @@ public class SubjectBankController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/12/9 14:19 * @date 2018/12/9 14:19
*/ */
@RequestMapping("/import") @RequestMapping("import")
@PreAuthorize("hasAuthority('exam:subject:bank:import') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:bank:import') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "导入题目", notes = "导入题目") @ApiOperation(value = "导入题目", notes = "导入题目")
@ApiImplicitParam(name = "categoryId", value = "分类ID", required = true, dataType = "String") @ApiImplicitParam(name = "categoryId", value = "分类ID", required = true, dataType = "String")
@Log("导入题库题目") @Log("导入题库题目")
public ResponseBean<Boolean> importSubjectBank(String categoryId, @ApiParam(value = "要上传的文件", required = true) MultipartFile file) { public ResponseBean<Boolean> importSubjectBank(@NotBlank String categoryId, @ApiParam(value = "要上传的文件", required = true) MultipartFile file) {
try { try {
log.debug("开始导入题目数据,分类ID:{}", categoryId); log.debug("开始导入题目数据,分类ID:{}", categoryId);
List<SubjectBank> subjectBanks = MapUtil.map2Java(SubjectBank.class, List<SubjectBank> subjectBanks = MapUtil.map2Java(SubjectBank.class,
...@@ -243,13 +241,12 @@ public class SubjectBankController extends BaseController { ...@@ -243,13 +241,12 @@ public class SubjectBankController extends BaseController {
for (SubjectBank subjectBank : subjectBanks) { for (SubjectBank subjectBank : subjectBanks) {
// 初始化考试ID // 初始化考试ID
if (StringUtils.isBlank(subjectBank.getId())) { if (StringUtils.isBlank(subjectBank.getId())) {
subjectBank.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subjectBank.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
subjectBank.setCategoryId(categoryId); subjectBank.setCategoryId(categoryId);
subjectBankService.insert(subjectBank); subjectBankService.insert(subjectBank);
} else { } else {
// 绑定分类ID // 绑定分类ID
if (StringUtils.isNotBlank(categoryId)) subjectBank.setCategoryId(categoryId);
subjectBank.setCategoryId(categoryId);
subjectBankService.update(subjectBank); subjectBankService.update(subjectBank);
} }
} }
...@@ -269,8 +266,8 @@ public class SubjectBankController extends BaseController { ...@@ -269,8 +266,8 @@ public class SubjectBankController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/12/04 9:55 * @date 2018/12/04 9:55
*/ */
@PostMapping("/deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('exam:subject:bank:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:bank:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "批量删除题目", notes = "根据题目id批量删除题目") @ApiOperation(value = "批量删除题目", notes = "根据题目id批量删除题目")
@ApiImplicitParam(name = "subjectBankDto", value = "题目信息", dataType = "SubjectBankDto") @ApiImplicitParam(name = "subjectBankDto", value = "题目信息", dataType = "SubjectBankDto")
@Log("批量删除题库题目") @Log("批量删除题库题目")
......
...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.TreeUtil; ...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.TreeUtil;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.SubjectCategoryDto; import com.github.tangyi.exam.api.dto.SubjectCategoryDto;
import com.github.tangyi.exam.api.module.SubjectCategory; import com.github.tangyi.exam.api.module.SubjectCategory;
import com.github.tangyi.exam.service.SubjectCategoryService; import com.github.tangyi.exam.service.SubjectCategoryService;
...@@ -16,10 +15,10 @@ import io.swagger.annotations.ApiImplicitParam; ...@@ -16,10 +15,10 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
...@@ -46,11 +45,13 @@ public class SubjectCategoryController extends BaseController { ...@@ -46,11 +45,13 @@ public class SubjectCategoryController extends BaseController {
* @author tangyi * @author tangyi
* @date 2018/12/04 22:03 * @date 2018/12/04 22:03
*/ */
@GetMapping(value = "/categories") @GetMapping(value = "categories")
@ApiOperation(value = "获取分类列表") @ApiOperation(value = "获取分类列表")
public List<SubjectCategoryDto> menus() { public List<SubjectCategoryDto> menus() {
SubjectCategory subjectCategory = new SubjectCategory();
subjectCategory.setTenantCode(SysUtil.getTenantCode());
// 查询所有分类 // 查询所有分类
List<SubjectCategory> subjectCategoryList = categoryService.findList(new SubjectCategory()); List<SubjectCategory> subjectCategoryList = categoryService.findList(subjectCategory);
if (CollectionUtils.isNotEmpty(subjectCategoryList)) { if (CollectionUtils.isNotEmpty(subjectCategoryList)) {
// 转成dto // 转成dto
List<SubjectCategoryDto> subjectCategorySetTreeList = subjectCategoryList.stream().map(SubjectCategoryDto::new).distinct().collect(Collectors.toList()); List<SubjectCategoryDto> subjectCategorySetTreeList = subjectCategoryList.stream().map(SubjectCategoryDto::new).distinct().collect(Collectors.toList());
...@@ -73,11 +74,8 @@ public class SubjectCategoryController extends BaseController { ...@@ -73,11 +74,8 @@ public class SubjectCategoryController extends BaseController {
@ApiImplicitParam(name = "id", value = "分类ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "分类ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<SubjectCategory> subjectCategory(@PathVariable String id) { public ResponseBean<SubjectCategory> subjectCategory(@PathVariable String id) {
SubjectCategory subjectCategory = new SubjectCategory(); SubjectCategory subjectCategory = new SubjectCategory();
if (StringUtils.isNotBlank(id)) { subjectCategory.setId(id);
subjectCategory.setId(id); return new ResponseBean<>(categoryService.get(subjectCategory));
subjectCategory = categoryService.get(subjectCategory);
}
return new ResponseBean<>(subjectCategory);
} }
/** /**
...@@ -89,12 +87,12 @@ public class SubjectCategoryController extends BaseController { ...@@ -89,12 +87,12 @@ public class SubjectCategoryController extends BaseController {
* @date 2018/12/04 22:00 * @date 2018/12/04 22:00
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:subject:category:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:category:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "创建分类", notes = "创建分类") @ApiOperation(value = "创建分类", notes = "创建分类")
@ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory") @ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory")
@Log("新增题目分类") @Log("新增题目分类")
public ResponseBean<Boolean> addSubjectCategory(@RequestBody SubjectCategory subjectCategory) { public ResponseBean<Boolean> addSubjectCategory(@RequestBody @Valid SubjectCategory subjectCategory) {
subjectCategory.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subjectCategory.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(categoryService.insert(subjectCategory) > 0); return new ResponseBean<>(categoryService.insert(subjectCategory) > 0);
} }
...@@ -107,12 +105,12 @@ public class SubjectCategoryController extends BaseController { ...@@ -107,12 +105,12 @@ public class SubjectCategoryController extends BaseController {
* @date 2018/12/04 22:01 * @date 2018/12/04 22:01
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:subject:category:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:category:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "更新分类信息", notes = "根据分类id更新分类的基本信息") @ApiOperation(value = "更新分类信息", notes = "根据分类id更新分类的基本信息")
@ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory") @ApiImplicitParam(name = "subjectCategory", value = "分类实体subjectCategory", required = true, dataType = "SubjectCategory")
@Log("更新题目分类") @Log("更新题目分类")
public ResponseBean<Boolean> updateSubjectCategory(@RequestBody SubjectCategory subjectCategory) { public ResponseBean<Boolean> updateSubjectCategory(@RequestBody @Valid SubjectCategory subjectCategory) {
subjectCategory.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subjectCategory.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(categoryService.update(subjectCategory) > 0); return new ResponseBean<>(categoryService.update(subjectCategory) > 0);
} }
...@@ -125,7 +123,7 @@ public class SubjectCategoryController extends BaseController { ...@@ -125,7 +123,7 @@ public class SubjectCategoryController extends BaseController {
* @date 2018/12/04 22:02 * @date 2018/12/04 22:02
*/ */
@DeleteMapping("/{id}") @DeleteMapping("/{id}")
@PreAuthorize("hasAuthority('exam:subject:category:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:subject:category:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "删除分类", notes = "根据ID删除分类") @ApiOperation(value = "删除分类", notes = "根据ID删除分类")
@ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "分类ID", required = true, paramType = "path")
@Log("删除题目分类") @Log("删除题目分类")
......
...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.*; ...@@ -7,7 +7,6 @@ import com.github.tangyi.common.core.utils.*;
import com.github.tangyi.common.core.web.BaseController; import com.github.tangyi.common.core.web.BaseController;
import com.github.tangyi.common.log.annotation.Log; import com.github.tangyi.common.log.annotation.Log;
import com.github.tangyi.common.security.constant.SecurityConstant; import com.github.tangyi.common.security.constant.SecurityConstant;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.dto.SubjectDto; import com.github.tangyi.exam.api.dto.SubjectDto;
import com.github.tangyi.exam.api.module.Examination; import com.github.tangyi.exam.api.module.Examination;
import com.github.tangyi.exam.api.module.Subject; import com.github.tangyi.exam.api.module.Subject;
...@@ -26,6 +25,8 @@ import org.springframework.web.multipart.MultipartFile; ...@@ -26,6 +25,8 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -66,11 +67,8 @@ public class SubjectController extends BaseController { ...@@ -66,11 +67,8 @@ public class SubjectController extends BaseController {
@ApiImplicitParam(name = "id", value = "题目ID", required = true, dataType = "String", paramType = "path") @ApiImplicitParam(name = "id", value = "题目ID", required = true, dataType = "String", paramType = "path")
public ResponseBean<Subject> subject(@PathVariable String id) { public ResponseBean<Subject> subject(@PathVariable String id) {
Subject subject = new Subject(); Subject subject = new Subject();
if (StringUtils.isNotBlank(id)) { subject.setId(id);
subject.setId(id); return new ResponseBean<>(subjectService.get(subject));
subject = subjectService.get(subject);
}
return new ResponseBean<>(subject);
} }
/** /**
...@@ -99,6 +97,7 @@ public class SubjectController extends BaseController { ...@@ -99,6 +97,7 @@ public class SubjectController extends BaseController {
@RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort, @RequestParam(value = CommonConstant.SORT, required = false, defaultValue = CommonConstant.PAGE_SORT_DEFAULT) String sort,
@RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order, @RequestParam(value = CommonConstant.ORDER, required = false, defaultValue = CommonConstant.PAGE_ORDER_DEFAULT) String order,
Subject subject) { Subject subject) {
subject.setTenantCode(SysUtil.getTenantCode());
return subjectService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), subject); return subjectService.findPage(PageUtil.pageInfo(pageNum, pageSize, sort, order), subject);
} }
...@@ -111,14 +110,13 @@ public class SubjectController extends BaseController { ...@@ -111,14 +110,13 @@ public class SubjectController extends BaseController {
* @date 2018/11/10 21:43 * @date 2018/11/10 21:43
*/ */
@PostMapping @PostMapping
@PreAuthorize("hasAuthority('exam:exam:subject:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:subject:add') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "创建题目", notes = "创建题目") @ApiOperation(value = "创建题目", notes = "创建题目")
@ApiImplicitParam(name = "subject", value = "题目实体subject", required = true, dataType = "Subject") @ApiImplicitParam(name = "subject", value = "题目实体subject", required = true, dataType = "Subject")
@Log("新增题目") @Log("新增题目")
public ResponseBean<Boolean> addSubject(@RequestBody Subject subject) { public ResponseBean<Boolean> addSubject(@RequestBody @Valid Subject subject) {
Assert.notNull(subject.getExaminationId(), CommonConstant.IllEGAL_ARGUMENT);
boolean success = false; boolean success = false;
subject.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subject.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
if (subjectService.insert(subject) > 0) { if (subjectService.insert(subject) > 0) {
// 更新考试的题目数 // 更新考试的题目数
Examination examination = new Examination(); Examination examination = new Examination();
...@@ -139,12 +137,12 @@ public class SubjectController extends BaseController { ...@@ -139,12 +137,12 @@ public class SubjectController extends BaseController {
* @date 2018/11/10 21:43 * @date 2018/11/10 21:43
*/ */
@PutMapping @PutMapping
@PreAuthorize("hasAuthority('exam:exam:subject:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:subject:edit') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "更新题目信息", notes = "根据题目id更新题目的基本信息") @ApiOperation(value = "更新题目信息", notes = "根据题目id更新题目的基本信息")
@ApiImplicitParam(name = "subject", value = "角色实体subject", required = true, dataType = "Subject") @ApiImplicitParam(name = "subject", value = "角色实体subject", required = true, dataType = "Subject")
@Log("更新题目") @Log("更新题目")
public ResponseBean<Boolean> updateSubject(@RequestBody Subject subject) { public ResponseBean<Boolean> updateSubject(@RequestBody @Valid Subject subject) {
subject.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subject.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return new ResponseBean<>(subjectService.update(subject) > 0); return new ResponseBean<>(subjectService.update(subject) > 0);
} }
...@@ -157,7 +155,7 @@ public class SubjectController extends BaseController { ...@@ -157,7 +155,7 @@ public class SubjectController extends BaseController {
* @date 2018/11/10 21:43 * @date 2018/11/10 21:43
*/ */
@DeleteMapping("{id}") @DeleteMapping("{id}")
@PreAuthorize("hasAuthority('exam:exam:subject:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:subject:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "删除题目", notes = "根据ID删除题目") @ApiOperation(value = "删除题目", notes = "根据ID删除题目")
@ApiImplicitParam(name = "id", value = "题目ID", required = true, paramType = "path") @ApiImplicitParam(name = "id", value = "题目ID", required = true, paramType = "path")
@Log("删除题目") @Log("删除题目")
...@@ -168,7 +166,7 @@ public class SubjectController extends BaseController { ...@@ -168,7 +166,7 @@ public class SubjectController extends BaseController {
subject.setId(id); subject.setId(id);
subject = subjectService.get(subject); subject = subjectService.get(subject);
if (subject != null) { if (subject != null) {
subject.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subject.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
if (subjectService.delete(subject) > 0) { if (subjectService.delete(subject) > 0) {
// 更新考试的题目数 // 更新考试的题目数
Examination examination = new Examination(); Examination examination = new Examination();
...@@ -192,7 +190,7 @@ public class SubjectController extends BaseController { ...@@ -192,7 +190,7 @@ public class SubjectController extends BaseController {
* @date 2018/11/28 12:53 * @date 2018/11/28 12:53
*/ */
@PostMapping("/export") @PostMapping("/export")
@PreAuthorize("hasAuthority('exam:exam:subject:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:subject:export') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "导出题目", notes = "根据分类id导出题目") @ApiOperation(value = "导出题目", notes = "根据分类id导出题目")
@ApiImplicitParam(name = "subjectDto", value = "题目信息", required = true, dataType = "SubjectDto") @ApiImplicitParam(name = "subjectDto", value = "题目信息", required = true, dataType = "SubjectDto")
@Log("导出题目") @Log("导出题目")
...@@ -216,6 +214,7 @@ public class SubjectController extends BaseController { ...@@ -216,6 +214,7 @@ public class SubjectController extends BaseController {
.filter(Objects::nonNull).collect(Collectors.toList()); .filter(Objects::nonNull).collect(Collectors.toList());
} else if (StringUtils.isNotEmpty(subjectDto.getExaminationId())) { // 根据考试id导出 } else if (StringUtils.isNotEmpty(subjectDto.getExaminationId())) { // 根据考试id导出
Subject subject = new Subject(); Subject subject = new Subject();
subject.setTenantCode(SysUtil.getTenantCode());
subject.setExaminationId(subjectDto.getExaminationId()); subject.setExaminationId(subjectDto.getExaminationId());
subjects = subjectService.findList(subject); subjects = subjectService.findList(subject);
} }
...@@ -235,11 +234,11 @@ public class SubjectController extends BaseController { ...@@ -235,11 +234,11 @@ public class SubjectController extends BaseController {
* @date 2018/11/28 12:59 * @date 2018/11/28 12:59
*/ */
@RequestMapping("import") @RequestMapping("import")
@PreAuthorize("hasAuthority('exam:exam:subject:import') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:subject:import') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "导入题目", notes = "导入题目") @ApiOperation(value = "导入题目", notes = "导入题目")
@ApiImplicitParam(name = "examinationId", value = "考试ID", required = true, dataType = "String") @ApiImplicitParam(name = "examinationId", value = "考试ID", required = true, dataType = "String")
@Log("导入题目") @Log("导入题目")
public ResponseBean<Boolean> importSubject(String examinationId, @ApiParam(value = "要上传的文件", required = true) MultipartFile file) { public ResponseBean<Boolean> importSubject(@NotBlank String examinationId, @ApiParam(value = "要上传的文件", required = true) MultipartFile file) {
boolean success = false; boolean success = false;
Assert.notNull(examinationId, CommonConstant.IllEGAL_ARGUMENT); Assert.notNull(examinationId, CommonConstant.IllEGAL_ARGUMENT);
try { try {
...@@ -250,7 +249,7 @@ public class SubjectController extends BaseController { ...@@ -250,7 +249,7 @@ public class SubjectController extends BaseController {
subjectStream.forEach(subject -> { subjectStream.forEach(subject -> {
// 初始化考试ID // 初始化考试ID
if (StringUtils.isBlank(subject.getId())) { if (StringUtils.isBlank(subject.getId())) {
subject.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); subject.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
subject.setExaminationId(examinationId); subject.setExaminationId(examinationId);
subjectService.insert(subject); subjectService.insert(subject);
} }
...@@ -278,7 +277,7 @@ public class SubjectController extends BaseController { ...@@ -278,7 +277,7 @@ public class SubjectController extends BaseController {
* @date 2018/12/04 9:55 * @date 2018/12/04 9:55
*/ */
@PostMapping("deleteAll") @PostMapping("deleteAll")
@PreAuthorize("hasAuthority('exam:exam:subject:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "', '" + SecurityConstant.ROLE_TEACHER + "')") @PreAuthorize("hasAuthority('exam:exam:subject:del') or hasAnyRole('" + SecurityConstant.ROLE_ADMIN + "')")
@ApiOperation(value = "批量删除题目", notes = "根据题目id批量删除题目") @ApiOperation(value = "批量删除题目", notes = "根据题目id批量删除题目")
@ApiImplicitParam(name = "subjectDto", value = "题目信息", dataType = "SubjectDto") @ApiImplicitParam(name = "subjectDto", value = "题目信息", dataType = "SubjectDto")
@Log("批量删除题目") @Log("批量删除题目")
...@@ -324,8 +323,8 @@ public class SubjectController extends BaseController { ...@@ -324,8 +323,8 @@ public class SubjectController extends BaseController {
@ApiImplicitParam(name = "examRecordId", value = "考试记录ID", required = true, dataType = "String"), @ApiImplicitParam(name = "examRecordId", value = "考试记录ID", required = true, dataType = "String"),
@ApiImplicitParam(name = "userId", value = "用户ID", dataType = "String") @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "String")
}) })
public ResponseBean<SubjectDto> subjectAnswer(@RequestParam("serialNumber") String serialNumber, public ResponseBean<SubjectDto> subjectAnswer(@RequestParam("serialNumber") @NotBlank String serialNumber,
@RequestParam("examRecordId") String examRecordId, @RequestParam("examRecordId") @NotBlank String examRecordId,
@RequestParam(value = "userId", required = false) String userId) { @RequestParam(value = "userId", required = false) String userId) {
return new ResponseBean<>(answerService.subjectAnswer(serialNumber, examRecordId, userId)); return new ResponseBean<>(answerService.subjectAnswer(serialNumber, examRecordId, userId));
} }
......
package com.github.tangyi.exam.error;
import com.github.tangyi.common.core.model.ResponseBean;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import java.util.List;
import java.util.stream.Collectors;
/**
* 全局异常处理
*
* @author tangyi
* @date 2019/05/25 15:36
*/
@ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
/**
* 处理参数校验异常
*
* @param ex ex
* @param headers headers
* @param status status
* @param request request
* @return ResponseEntity
*/
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
HttpHeaders headers,
HttpStatus status, WebRequest request) {
// 获取所有异常信息
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.toList());
ResponseBean<List<String>> responseBean = new ResponseBean<>(errors);
responseBean.setStatus(status.value());
return new ResponseEntity<>(responseBean, headers, status);
}
}
...@@ -11,5 +11,5 @@ import org.apache.ibatis.annotations.Mapper; ...@@ -11,5 +11,5 @@ import org.apache.ibatis.annotations.Mapper;
* @date 2018/12/9 14:10 * @date 2018/12/9 14:10
*/ */
@Mapper @Mapper
public interface SubjectBankMapper extends CrudMapper<SubjectBank> { public interface SubjectBankMapper extends CrudMapper<SubjectBank> {
} }
...@@ -4,7 +4,6 @@ import com.github.tangyi.common.core.constant.MqConstant; ...@@ -4,7 +4,6 @@ import com.github.tangyi.common.core.constant.MqConstant;
import com.github.tangyi.common.core.exceptions.CommonException; import com.github.tangyi.common.core.exceptions.CommonException;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.common.core.utils.SysUtil; import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.exam.api.constants.ExamRecordConstant; import com.github.tangyi.exam.api.constants.ExamRecordConstant;
import com.github.tangyi.exam.api.constants.SubjectConstant; import com.github.tangyi.exam.api.constants.SubjectConstant;
import com.github.tangyi.exam.api.dto.StartExamDto; import com.github.tangyi.exam.api.dto.StartExamDto;
...@@ -127,7 +126,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> { ...@@ -127,7 +126,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> {
*/ */
@Transactional @Transactional
public int save(Answer answer) { public int save(Answer answer) {
answer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); answer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
return super.save(answer); return super.save(answer);
} }
...@@ -143,12 +142,12 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> { ...@@ -143,12 +142,12 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> {
public SubjectDto saveAndNext(Answer answer) { public SubjectDto saveAndNext(Answer answer) {
Answer tempAnswer = this.getAnswer(answer); Answer tempAnswer = this.getAnswer(answer);
if (tempAnswer != null) { if (tempAnswer != null) {
tempAnswer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); tempAnswer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
tempAnswer.setAnswer(answer.getAnswer()); tempAnswer.setAnswer(answer.getAnswer());
tempAnswer.setOptionAnswer(answer.getOptionAnswer()); tempAnswer.setOptionAnswer(answer.getOptionAnswer());
this.update(tempAnswer); this.update(tempAnswer);
} else { } else {
answer.setCommonValue(SecurityUtil.getCurrentUsername(), SysUtil.getSysCode()); answer.setCommonValue(SysUtil.getUser(), SysUtil.getSysCode(), SysUtil.getTenantCode());
this.insert(answer); this.insert(answer);
} }
return this.subjectAnswer(answer.getSerialNumber(), answer.getExamRecordId(), answer.getUserId()); return this.subjectAnswer(answer.getSerialNumber(), answer.getExamRecordId(), answer.getUserId());
...@@ -210,7 +209,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> { ...@@ -210,7 +209,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> {
incorrectAnswer.setSubjectId(tempAnswer.getSubjectId()); incorrectAnswer.setSubjectId(tempAnswer.getSubjectId());
incorrectAnswer.setSerialNumber(tempSubject.getSerialNumber()); incorrectAnswer.setSerialNumber(tempSubject.getSerialNumber());
incorrectAnswer.setUserId(tempAnswer.getUserId()); incorrectAnswer.setUserId(tempAnswer.getUserId());
incorrectAnswer.setIncorrectAnswer(tempAnswer.getAnswer()); incorrectAnswer.setIncorrectAnswer(tempAnswer.getOptionAnswer());
incorrectAnswers.add(incorrectAnswer); incorrectAnswers.add(incorrectAnswer);
}); });
}); });
...@@ -257,10 +256,10 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> { ...@@ -257,10 +256,10 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> {
@Transactional @Transactional
public boolean submitAsync(Answer answer) { public boolean submitAsync(Answer answer) {
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
String currentUsername = SecurityUtil.getCurrentUsername(); String currentUsername = SysUtil.getUser();
answer.setModifier(currentUsername); answer.setModifier(currentUsername);
ExamRecord examRecord = new ExamRecord(); ExamRecord examRecord = new ExamRecord();
examRecord.setCommonValue(currentUsername, SysUtil.getSysCode()); examRecord.setCommonValue(currentUsername, SysUtil.getSysCode(), SysUtil.getTenantCode());
examRecord.setId(answer.getExamRecordId()); examRecord.setId(answer.getExamRecordId());
// 提交时间 // 提交时间
examRecord.setEndTime(examRecord.getCreateDate()); examRecord.setEndTime(examRecord.getCreateDate());
...@@ -284,7 +283,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> { ...@@ -284,7 +283,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> {
@Transactional @Transactional
public StartExamDto start(ExamRecord examRecord) { public StartExamDto start(ExamRecord examRecord) {
StartExamDto startExamDto = new StartExamDto(); StartExamDto startExamDto = new StartExamDto();
String currentUsername = SecurityUtil.getCurrentUsername(), applicationCode = SysUtil.getSysCode(); String currentUsername = SysUtil.getUser(), applicationCode = SysUtil.getSysCode(), tenantCode = SysUtil.getTenantCode();
// 创建考试记录 // 创建考试记录
if (StringUtils.isEmpty(examRecord.getExaminationId())) if (StringUtils.isEmpty(examRecord.getExaminationId()))
throw new CommonException("参数校验失败,考试id为空!"); throw new CommonException("参数校验失败,考试id为空!");
...@@ -298,7 +297,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> { ...@@ -298,7 +297,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> {
examRecord.setExaminationName(examination.getExaminationName()); examRecord.setExaminationName(examination.getExaminationName());
examRecord.setCourseId(examination.getCourseId()); examRecord.setCourseId(examination.getCourseId());
} }
examRecord.setCommonValue(currentUsername, applicationCode); examRecord.setCommonValue(currentUsername, applicationCode, tenantCode);
examRecord.setStartTime(examRecord.getCreateDate()); examRecord.setStartTime(examRecord.getCreateDate());
// 默认未提交状态 // 默认未提交状态
examRecord.setSubmitStatus(ExamRecordConstant.STATUS_NOT_SUBMITTED); examRecord.setSubmitStatus(ExamRecordConstant.STATUS_NOT_SUBMITTED);
...@@ -322,7 +321,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> { ...@@ -322,7 +321,7 @@ public class AnswerService extends CrudService<AnswerMapper, Answer> {
BeanUtils.copyProperties(subject, subjectDto); BeanUtils.copyProperties(subject, subjectDto);
// 创建第一题的答题 // 创建第一题的答题
Answer answer = new Answer(); Answer answer = new Answer();
answer.setCommonValue(currentUsername, applicationCode); answer.setCommonValue(currentUsername, applicationCode, tenantCode);
answer.setUserId(examRecord.getUserId()); answer.setUserId(examRecord.getUserId());
answer.setExaminationId(examRecord.getExaminationId()); answer.setExaminationId(examRecord.getExaminationId());
answer.setExamRecordId(examRecord.getId()); answer.setExamRecordId(examRecord.getId());
......
package com.github.tangyi.exam.service; package com.github.tangyi.exam.service;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.exam.mapper.CourseMapper;
import com.github.tangyi.exam.api.module.Course; import com.github.tangyi.exam.api.module.Course;
import com.github.tangyi.exam.mapper.CourseMapper;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
package com.github.tangyi.exam.service; package com.github.tangyi.exam.service;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.exam.mapper.IncorrectAnswerMapper;
import com.github.tangyi.exam.api.module.ExamRecord; import com.github.tangyi.exam.api.module.ExamRecord;
import com.github.tangyi.exam.api.module.IncorrectAnswer; import com.github.tangyi.exam.api.module.IncorrectAnswer;
import com.github.tangyi.exam.mapper.IncorrectAnswerMapper;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
package com.github.tangyi.exam.service; package com.github.tangyi.exam.service;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.exam.mapper.KnowledgeMapper;
import com.github.tangyi.exam.api.module.Knowledge; import com.github.tangyi.exam.api.module.Knowledge;
import com.github.tangyi.exam.mapper.KnowledgeMapper;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
package com.github.tangyi.exam.service; package com.github.tangyi.exam.service;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.exam.mapper.SubjectBankMapper;
import com.github.tangyi.exam.api.module.SubjectBank; import com.github.tangyi.exam.api.module.SubjectBank;
import com.github.tangyi.exam.mapper.SubjectBankMapper;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
package com.github.tangyi.exam.service; package com.github.tangyi.exam.service;
import com.github.tangyi.common.core.service.CrudService; import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.exam.mapper.SubjectCategoryMapper;
import com.github.tangyi.exam.api.module.SubjectCategory; import com.github.tangyi.exam.api.module.SubjectCategory;
import com.github.tangyi.exam.mapper.SubjectCategoryMapper;
import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
......
...@@ -41,6 +41,7 @@ public class SubjectBankUtil { ...@@ -41,6 +41,7 @@ public class SubjectBankUtil {
map.put("modifyDate", "修改时间"); map.put("modifyDate", "修改时间");
map.put("delFlag", "删除标记"); map.put("delFlag", "删除标记");
map.put("applicationCode", "系统编码"); map.put("applicationCode", "系统编码");
map.put("tenantCode", "租户标识");
return map; return map;
} }
} }
...@@ -41,6 +41,7 @@ public class SubjectUtil { ...@@ -41,6 +41,7 @@ public class SubjectUtil {
map.put("modifyDate", "修改时间"); map.put("modifyDate", "修改时间");
map.put("delFlag", "删除标记"); map.put("delFlag", "删除标记");
map.put("applicationCode", "系统编码"); map.put("applicationCode", "系统编码");
map.put("tenantCode", "租户标识");
return map; return map;
} }
} }
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="false"> <configuration debug="false" scan="false">
<springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue="spring-microservice-exam"/> <springProperty scop="context" name="spring.application.name" source="spring.application.name"
<property name="log.path" value="logs/${spring.application.name}" /> defaultValue="spring-microservice-exam"/>
<property name="log.path" value="logs/${spring.application.name}"/>
<!-- Console log output --> <!-- Console log output -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder> <encoder>
...@@ -40,8 +41,8 @@ ...@@ -40,8 +41,8 @@
<!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 --> <!-- Level: FATAL 0 ERROR 3 WARN 4 INFO 6 DEBUG 7 -->
<root level="info"> <root level="info">
<appender-ref ref="console" /> <appender-ref ref="console"/>
<appender-ref ref="debug" /> <appender-ref ref="debug"/>
<appender-ref ref="error" /> <appender-ref ref="error"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment