|
@@ -3,6 +3,7 @@ package cn.com.qmth.examcloud.core.examwork.service.impl;
|
|
|
import cn.com.qmth.examcloud.api.commons.enums.CURD;
|
|
|
import cn.com.qmth.examcloud.api.commons.enums.ExamType;
|
|
|
import cn.com.qmth.examcloud.api.commons.exchange.PageInfo;
|
|
|
+import cn.com.qmth.examcloud.api.commons.security.bean.User;
|
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
|
import cn.com.qmth.examcloud.commons.helpers.DynamicEnum;
|
|
|
import cn.com.qmth.examcloud.commons.helpers.DynamicEnumManager;
|
|
@@ -10,7 +11,9 @@ import cn.com.qmth.examcloud.commons.helpers.poi.ExcelReader;
|
|
|
import cn.com.qmth.examcloud.commons.util.BooleanUtil;
|
|
|
import cn.com.qmth.examcloud.commons.util.DateUtil;
|
|
|
import cn.com.qmth.examcloud.commons.util.DateUtil.DatePatterns;
|
|
|
+import cn.com.qmth.examcloud.commons.util.JsonUtil;
|
|
|
import cn.com.qmth.examcloud.commons.util.PathUtil;
|
|
|
+import cn.com.qmth.examcloud.commons.util.StringUtil;
|
|
|
import cn.com.qmth.examcloud.core.basic.api.OrgCloudService;
|
|
|
import cn.com.qmth.examcloud.core.basic.api.bean.OrgBean;
|
|
|
import cn.com.qmth.examcloud.core.basic.api.request.GetOrgReq;
|
|
@@ -26,13 +29,16 @@ import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamIpLimitEntity;
|
|
|
import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamOrgPropertyEntity;
|
|
|
import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamPropertyEntity;
|
|
|
import cn.com.qmth.examcloud.core.examwork.dao.entity.ExamSpecialSettingsEntity;
|
|
|
+import cn.com.qmth.examcloud.core.examwork.dao.enums.IpLimitType;
|
|
|
import cn.com.qmth.examcloud.core.examwork.service.ExamService;
|
|
|
import cn.com.qmth.examcloud.core.examwork.service.ExamStudentService;
|
|
|
import cn.com.qmth.examcloud.core.examwork.service.bean.ExamInfo;
|
|
|
+import cn.com.qmth.examcloud.core.examwork.service.bean.ExamIpLimitInfo;
|
|
|
import cn.com.qmth.examcloud.core.examwork.service.bean.ExamSpecialSettingsInfo;
|
|
|
import cn.com.qmth.examcloud.core.examwork.service.cache.ExamPropertyCache;
|
|
|
import cn.com.qmth.examcloud.core.examwork.service.cache.ExamSettingsCache;
|
|
|
import cn.com.qmth.examcloud.support.cache.CacheHelper;
|
|
|
+import cn.com.qmth.examcloud.support.cache.bean.ExamPropertyCacheBean;
|
|
|
import cn.com.qmth.examcloud.support.cache.bean.StudentCacheBean;
|
|
|
import cn.com.qmth.examcloud.support.privilege.PrivilegeDefine;
|
|
|
import cn.com.qmth.examcloud.support.privilege.PrivilegeManager;
|
|
@@ -40,6 +46,7 @@ import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
|
|
|
import cn.com.qmth.examcloud.task.api.request.SyncExamReq;
|
|
|
import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
|
|
|
import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
|
|
|
+import cn.com.qmth.examcloud.web.redis.RedisClient;
|
|
|
import com.google.common.collect.Lists;
|
|
|
import com.google.common.collect.Maps;
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
@@ -48,19 +55,23 @@ import org.jsoup.Jsoup;
|
|
|
import org.jsoup.nodes.Document;
|
|
|
import org.jsoup.nodes.Element;
|
|
|
import org.jsoup.select.Elements;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.data.domain.PageRequest;
|
|
|
import org.springframework.data.domain.Sort;
|
|
|
import org.springframework.data.jpa.domain.Specification;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import javax.persistence.criteria.Predicate;
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
import java.io.File;
|
|
|
import java.util.*;
|
|
|
import java.util.Map.Entry;
|
|
|
import java.util.regex.Matcher;
|
|
|
import java.util.regex.Pattern;
|
|
|
import java.util.stream.Collectors;
|
|
|
+import java.util.stream.Stream;
|
|
|
|
|
|
/**
|
|
|
* 类注释
|
|
@@ -104,6 +115,9 @@ public class ExamServiceImpl implements ExamService {
|
|
|
@Autowired
|
|
|
ExamIpLimitRepo examIpLimitRepo;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ RedisClient redisClient;
|
|
|
+
|
|
|
private static final String[] EXAM_ORG_SETTINGS_EXCEL_HEADER = new String[]{"学习中心ID", "学习中心代码",
|
|
|
"学习中心名称", "是否可以考试(是/否)", "开始考试时间 yyyy-MM-dd hh:mm:ss", "结束考试时间 yyyy-MM-dd hh:mm:ss"};
|
|
|
|
|
@@ -828,7 +842,207 @@ public class ExamServiceImpl implements ExamService {
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public PageInfo<ExamIpLimitEntity> pageIpLimited(Integer curPage, Integer pageSize, Long examId, Integer limitType, String ip) {
|
|
|
+ public PageInfo<ExamIpLimitInfo> pageIpLimited(Integer curPage, Integer pageSize, Long examId, Integer limitType, String ip) {
|
|
|
+ Specification<ExamIpLimitEntity> spec = getSpec(examId, limitType, ip);
|
|
|
+
|
|
|
+ PageRequest pageRequest = PageRequest.of(curPage, pageSize, Sort.by(Sort.Direction.DESC, "creationTime"));
|
|
|
+ PageInfo<ExamIpLimitEntity> pages = new PageInfo<>(examIpLimitRepo.findAll(spec, pageRequest));
|
|
|
+
|
|
|
+ PageInfo<ExamIpLimitInfo> pageInfo = new PageInfo<>();
|
|
|
+ List<ExamIpLimitInfo> list = new ArrayList<>();
|
|
|
+ pages.getList().forEach(e->{
|
|
|
+ ExamIpLimitInfo domain = new ExamIpLimitInfo();
|
|
|
+ BeanUtils.copyProperties(e,domain);
|
|
|
+ Optional<ExamEntity> byId = examRepo.findById(examId);
|
|
|
+ byId.ifPresent(examEntity -> domain.setExamName(examEntity.getName()));
|
|
|
+ list.add(domain);
|
|
|
+ });
|
|
|
+ pageInfo.setList(list);
|
|
|
+ pageInfo.setTotal(pages.getTotal());
|
|
|
+ return pageInfo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<ExamIpLimitEntity> findAllIpLimits(Long examId, Integer limitType, String ip) {
|
|
|
+ Specification<ExamIpLimitEntity> spec = getSpec(examId, limitType, ip);
|
|
|
+ long count = examIpLimitRepo.count(spec);
|
|
|
+ if (100000 < count) {
|
|
|
+ throw new StatusException("620200", "数据量过大,无法导出");
|
|
|
+ }
|
|
|
+ return examIpLimitRepo.findAll(spec);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean getIpLimited(HttpServletRequest request, Long examId, User accessUser) {
|
|
|
+ //是否开启Ip限制
|
|
|
+ ExamPropertyCacheBean ipLimitProperty = CacheHelper.getExamProperty(examId, "IP_LIMIT");
|
|
|
+ boolean ipLimited = ipLimitProperty!=null && StringUtil.isTrue(ipLimitProperty.getValue());
|
|
|
+
|
|
|
+ DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
|
|
|
+ DynamicEnum ipTotalLimit = manager.getByName("IP_TOTAL_LIMIT");
|
|
|
+ DynamicEnum ipCenterLimit = manager.getByName("IP_CENTER_LIMIT");
|
|
|
+
|
|
|
+ if (ipLimited) {
|
|
|
+ String realIp = request.getHeader("x-forwarded-for");
|
|
|
+ if (StringUtils.isBlank(realIp)) {
|
|
|
+ realIp = request.getHeader("x-real-ip");
|
|
|
+ }
|
|
|
+ realIp = realIp.trim();
|
|
|
+ //整体控制
|
|
|
+ Integer totalLimit = getExamLimitProperty(examId, ipTotalLimit.getId(), 0);
|
|
|
+ if (totalLimit == 1) {
|
|
|
+ //在白名单中
|
|
|
+ int count = examIpLimitRepo.countByExamIdAndLimitTypeAndIp(examId, IpLimitType.Has_access.getId(),realIp);
|
|
|
+ if (count>0) {
|
|
|
+ //学习中心访问控制
|
|
|
+ Integer centerLimit = getExamLimitProperty(examId,ipCenterLimit.getId(), 0);
|
|
|
+ if (centerLimit == 1) {
|
|
|
+ StudentCacheBean studentCache = CacheHelper.getStudent(accessUser.getUserId());
|
|
|
+ Long orgId = studentCache.getOrgId();
|
|
|
+ String key = "IP_" + orgId;
|
|
|
+ String value = redisClient.get(key, String.class);
|
|
|
+ //机构是否在时间范围内登陆过
|
|
|
+ if (value != null) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
+ Set<String> userKeyList = JsonUtil.fromJson(value, Set.class);
|
|
|
+
|
|
|
+ for (String userKey : userKeyList) {
|
|
|
+ User curUser = redisClient.get(userKey, User.class);
|
|
|
+ if (null != curUser) {
|
|
|
+ String clientIp = curUser.getClientIp();
|
|
|
+ if (null != clientIp) {
|
|
|
+ // IP取前三段
|
|
|
+ clientIp = clientIp.substring(0, clientIp.lastIndexOf(".") + 1);
|
|
|
+ if (realIp.startsWith(clientIp)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //不在黑名单中
|
|
|
+ int count = examIpLimitRepo.countByExamIdAndLimitTypeAndIp(examId,IpLimitType.No_Access.getId(), realIp);
|
|
|
+ return count != 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void saveIpLimit(String ids, ExamIpLimitEntity entity) {
|
|
|
+ //ids不为空,说明是批量设置限制类型
|
|
|
+ if (StringUtils.isNotBlank(ids)) {
|
|
|
+ List<Long> ipIds = getIdsByPath(ids);
|
|
|
+ if(entity.getLimitType()!=null){
|
|
|
+ examIpLimitRepo.updateLimitType(entity.getLimitType(),entity.getExamId(),ipIds);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ Long id = entity.getId();
|
|
|
+ Date now = new Date();
|
|
|
+ //新增
|
|
|
+ if (id==null) {
|
|
|
+ entity.setCreationTime(now);
|
|
|
+ examIpLimitRepo.save(entity);
|
|
|
+ } else {
|
|
|
+ //更新
|
|
|
+ Optional<ExamIpLimitEntity> byId = examIpLimitRepo.findById(id);
|
|
|
+ if (byId.isPresent()){
|
|
|
+ ExamIpLimitEntity ipLimitEntity = byId.get();
|
|
|
+ if(StringUtils.isNotBlank(entity.getIp())){
|
|
|
+ ipLimitEntity.setIp(entity.getIp());
|
|
|
+ }
|
|
|
+ if(entity.getLimitType()!=null){
|
|
|
+ ipLimitEntity.setLimitType(entity.getLimitType());
|
|
|
+ }
|
|
|
+ ipLimitEntity.setUpdateTime(now);
|
|
|
+ examIpLimitRepo.save(ipLimitEntity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void deleteIpLimit(String ids) {
|
|
|
+ examIpLimitRepo.deleteByIdIn(getIdsByPath(ids));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void deleteIpLimit(Long examId) {
|
|
|
+ examIpLimitRepo.deleteAllByExamId(examId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Map<String, Integer> getIpLimitedProperty(Long examId) {
|
|
|
+ Map<String,Integer> map = new HashMap<>();
|
|
|
+
|
|
|
+ DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
|
|
|
+ DynamicEnum ipTotalLimit = manager.getByName("IP_TOTAL_LIMIT");
|
|
|
+ DynamicEnum ipCenterLimit = manager.getByName("IP_CENTER_LIMIT");
|
|
|
+
|
|
|
+ map.put("totalLimit", getExamLimitProperty(examId,ipTotalLimit.getId(),0));
|
|
|
+ map.put("centerLimit",getExamLimitProperty(examId,ipCenterLimit.getId(),0));
|
|
|
+ return map;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void updateIpLimitedProperty(Long examId, Map<String, Object> map) {
|
|
|
+ DynamicEnumManager manager = ExamProperty.getDynamicEnumManager();
|
|
|
+ DynamicEnum ipTotalLimit = manager.getByName("IP_TOTAL_LIMIT");
|
|
|
+ DynamicEnum ipCenterLimit = manager.getByName("IP_CENTER_LIMIT");
|
|
|
+
|
|
|
+ ExamPropertyEntity totalEntity = examPropertyRepo.findByExamIdAndKeyId(examId, ipTotalLimit.getId());
|
|
|
+ ExamPropertyEntity centerEntity = examPropertyRepo.findByExamIdAndKeyId(examId, ipCenterLimit.getId());
|
|
|
+
|
|
|
+ String totalLimit = map.get("totalLimit").toString();
|
|
|
+ String centerLimit = map.get("centerLimit").toString();
|
|
|
+
|
|
|
+ saveIpLimitEntity(totalEntity,totalLimit,ipTotalLimit,examId);
|
|
|
+ saveIpLimitEntity(centerEntity,centerLimit,ipCenterLimit,examId);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveIpLimitEntity(ExamPropertyEntity propertyEntity, String limitValue, DynamicEnum dynamicEnum, Long examId) {
|
|
|
+ Date now = new Date();
|
|
|
+ if (propertyEntity!=null) {
|
|
|
+ propertyEntity.setValue(limitValue);
|
|
|
+ propertyEntity.setUpdateTime(now);
|
|
|
+ examPropertyRepo.save(propertyEntity);
|
|
|
+ } else {
|
|
|
+ ExamPropertyEntity entity = new ExamPropertyEntity();
|
|
|
+ entity.setExamId(examId);
|
|
|
+ entity.setCreationTime(now);
|
|
|
+ entity.setKeyId(dynamicEnum.getId());
|
|
|
+ entity.setValue(limitValue);
|
|
|
+ examPropertyRepo.save(entity);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional
|
|
|
+ public void saveAllIpLimits(List<ExamIpLimitEntity> list) {
|
|
|
+ examIpLimitRepo.saveAll(list);
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Long> getIdsByPath(String ids) {
|
|
|
+ return Stream.of(ids.split(",")).map(s -> Long.parseLong(s.trim()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ private Integer getExamLimitProperty(Long examId, Long keyId ,Integer defaultValue) {
|
|
|
+ ExamPropertyEntity propertyEntity = examPropertyRepo.findByExamIdAndKeyId(examId, keyId);
|
|
|
+ return propertyEntity != null && StringUtils.isNotBlank(propertyEntity.getValue())
|
|
|
+ ? Integer.valueOf(propertyEntity.getValue()) : defaultValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Specification<ExamIpLimitEntity> getSpec(Long examId, Integer limitType, String ip){
|
|
|
Specification<ExamIpLimitEntity> spec = (root, query, cb) -> {
|
|
|
List<Predicate> predicates = new ArrayList<>();
|
|
|
if(examId!=null){
|
|
@@ -842,8 +1056,7 @@ public class ExamServiceImpl implements ExamService {
|
|
|
}
|
|
|
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
|
|
|
};
|
|
|
- PageRequest pageRequest = PageRequest.of(curPage, pageSize, Sort.by(Sort.Direction.DESC, "creationTime"));
|
|
|
- return new PageInfo<>(examIpLimitRepo.findAll(spec, pageRequest));
|
|
|
+ return spec;
|
|
|
}
|
|
|
|
|
|
}
|