feat(REQ-2040): 同步接口
This commit is contained in:
parent
4506422fc9
commit
86d7501f01
11
README.md
11
README.md
@ -1,5 +1,6 @@
|
||||
# 项目介绍
|
||||
一个通用的聚合服务:通用黑名单服务
|
||||
一个通用的聚合服务:
|
||||
* 通用黑白名单服务
|
||||
|
||||
# vm参数
|
||||
## dev环境
|
||||
@ -18,13 +19,19 @@
|
||||
-DCUSTOM_ENV=test
|
||||
-Dserver.port=8080
|
||||
|
||||
# 各模块结构
|
||||
# 黑白名单中各模块结构
|
||||
## all-login 登录白名单
|
||||
~~~json
|
||||
{
|
||||
"phone": "手机号"
|
||||
}
|
||||
~~~
|
||||
## ou_register_black_list 企业注册黑名单
|
||||
~~~json
|
||||
{
|
||||
"phone": "手机号"
|
||||
}
|
||||
~~~
|
||||
## attendance-pass 考勤黑名单
|
||||
~~~json
|
||||
{
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package cn.axzo.nanopart.api;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.nanopart.api.annotation.CheckSign;
|
||||
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListExcelImportReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
|
||||
@ -13,6 +16,7 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
@ -84,4 +88,36 @@ public interface BlackAndWhiteListApi {
|
||||
@PostMapping("api/black-white-list/import")
|
||||
ApiResult<BlackAndWhiteListExcelImportResp> importBlackAndWhiteListExcel(@RequestParam(value = "type") @NotNull(message = "名单类型不能为空") ListTypeEnum type,
|
||||
@RequestParam(value = "module") @NotBlank(message = "模块不能为空") String module, @RequestParam(value = "url", required = false) String url, @RequestPart(value = "file") MultipartFile file);
|
||||
|
||||
/**
|
||||
* 平台同步黑白名单
|
||||
* <p>
|
||||
* 每次最多同步1000条记录且整体上同步策略采用增量更新策略,
|
||||
* 若总记录数超过1000条请自行分片多次调用
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 该接口需要验签,参与签名的字段为header中的:appKey,timestamp,
|
||||
* 签名字段为header中的sign
|
||||
* </p>
|
||||
*
|
||||
* @param req @{link BlackAndWhiteListPlatformSyncReq}
|
||||
* @return true-同步成功,false-同步失败
|
||||
*/
|
||||
@PostMapping("api/black-white-list/plat-sync")
|
||||
ApiResult<Boolean> platformSync(@RequestBody @Validated BlackAndWhiteListPlatformSyncReq req);
|
||||
|
||||
/**
|
||||
* TODO 该接口目前耗时较长待优化
|
||||
* 内部自同步黑白名单
|
||||
* <p>
|
||||
* 例如将其他模块的黑名单同步到登录模块黑名单
|
||||
* </p>
|
||||
*
|
||||
* @param req @{link BlackAndWhiteListInternalSyncReq}
|
||||
* @return 同步结果,成功返回同步记录总数
|
||||
*/
|
||||
@CheckSign
|
||||
@PostMapping("api/black-white-list/inner-sync")
|
||||
ApiResult<Long> internalSync(@RequestBody @Validated BlackAndWhiteListInternalSyncReq req);
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ public class CheckSignAspect {
|
||||
|
||||
@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.PostMapping)")
|
||||
public void postMapping() {
|
||||
log.info("post");
|
||||
}
|
||||
|
||||
@Pointcut(value = "@annotation(org.springframework.web.bind.annotation.GetMapping)")
|
||||
@ -68,10 +69,14 @@ public class CheckSignAspect {
|
||||
public void mappingAnnotations() {
|
||||
}
|
||||
|
||||
// @Pointcut(value = "@annotation(cn.axzo.nanopart.api.annotation.CheckSign)")
|
||||
// public void checkSign() {
|
||||
// }
|
||||
|
||||
/**
|
||||
* 切入含有@CheckSign && @RestController 注解的类
|
||||
*/
|
||||
@Before(value = "@within(checkSign) && @within(restController)")
|
||||
@Before(value = "@within(checkSign) && @within(restController)", argNames = "joinPoint,checkSign,restController")
|
||||
public void classHandler(JoinPoint joinPoint, CheckSign checkSign, RestController restController) {
|
||||
handle(joinPoint, checkSign);
|
||||
}
|
||||
@ -127,7 +132,11 @@ public class CheckSignAspect {
|
||||
if (StringUtils.isBlank(value)) {
|
||||
throw new BizException(new RespCode("403", "验签失败"));
|
||||
}
|
||||
data.append(field).append("=").append(value).append("&");
|
||||
data.append(field).append("=").append(value);
|
||||
// 判断最后一个字段,如果是最后一个字段则不拼接"&"
|
||||
if (field.equals(checkSign.requireSignFields()[checkSign.requireSignFields().length - 1])) {
|
||||
data.append("&");
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("data:{}", data);
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
package cn.axzo.nanopart.api.config;
|
||||
|
||||
import cn.axzo.nanopart.api.constant.NanopartConstant;
|
||||
import cn.axzo.nanopart.api.constant.BlackAndWhiteListConstant;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
@EnableFeignClients(NanopartConstant.BASIC_FEIGN_PACKAGE)
|
||||
@EnableFeignClients(BlackAndWhiteListConstant.BASIC_FEIGN_PACKAGE)
|
||||
public class NanopartApiAutoConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ package cn.axzo.nanopart.api.constant;
|
||||
* @modifiedBy:
|
||||
* @version: 1.0
|
||||
*/
|
||||
public class NanopartConstant {
|
||||
public class BlackAndWhiteListConstant {
|
||||
|
||||
public static final String BASIC_FEIGN_PACKAGE = "cn.axzo.nanopart.api";
|
||||
public static final String PHONE_REGEXP = "^1[3456789]\\d{9}$";
|
||||
@ -1,7 +1,7 @@
|
||||
package cn.axzo.nanopart.api.request;
|
||||
|
||||
|
||||
import cn.axzo.nanopart.api.constant.NanopartConstant;
|
||||
import cn.axzo.nanopart.api.constant.BlackAndWhiteListConstant;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
@ -21,6 +21,6 @@ public class BlackAndWhiteListInReq {
|
||||
@NotBlank(message = "模块名称不能为空格")
|
||||
private String module;
|
||||
|
||||
@Pattern(regexp = NanopartConstant.PHONE_REGEXP,message = "手机号格式错误")
|
||||
@Pattern(regexp = BlackAndWhiteListConstant.PHONE_REGEXP,message = "手机号格式错误")
|
||||
private String phone;
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
package cn.axzo.nanopart.api.request;
|
||||
|
||||
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 黑白名单内部自同步请求
|
||||
*
|
||||
* @author chenwenjian
|
||||
* @version 1.0
|
||||
* @date 2024/1/3 16:46
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BlackAndWhiteListInternalSyncReq {
|
||||
|
||||
@NotNull(message = "同步类型不能为空")
|
||||
private ListTypeEnum type;
|
||||
|
||||
/**
|
||||
* 同步源模块
|
||||
*/
|
||||
@NotBlank(message = "同步源模块不能为空")
|
||||
private String sourceModule;
|
||||
|
||||
/**
|
||||
* 同步源字段
|
||||
*/
|
||||
@NotEmpty(message = "同步源字段不能为空")
|
||||
private List<String> sourceFields;
|
||||
|
||||
/**
|
||||
* 同步目标模块
|
||||
*/
|
||||
@NotBlank(message = "同步目标模块不能为空")
|
||||
private String targetModule;
|
||||
|
||||
/**
|
||||
* 同步目标字段
|
||||
*/
|
||||
@NotEmpty(message = "同步目标字段不能为空")
|
||||
private List<String> targetFields;
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
package cn.axzo.nanopart.api.request;
|
||||
|
||||
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 黑白名单平台同步请求
|
||||
*
|
||||
* @author chenwenjian
|
||||
* @version 1.0
|
||||
* @date 2024/1/2 18:17
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BlackAndWhiteListPlatformSyncReq {
|
||||
|
||||
/**
|
||||
* 名单类型,0为黑名单,1为白名单
|
||||
*/
|
||||
@NotNull(message = "名单类型错误")
|
||||
private ListTypeEnum type;
|
||||
|
||||
/**
|
||||
* 模块名,自主定义,例:cms-login
|
||||
*/
|
||||
@NotBlank(message = "模块名不能为空")
|
||||
private String module;
|
||||
|
||||
/**
|
||||
* 参数,例:[{"name":"username","value":"admin"},{"name":"password","value":"123456"}]
|
||||
* 单次同步数量最多1000条
|
||||
*/
|
||||
@NotEmpty(message = "参数不能为空")
|
||||
private List<Map<String, Object>> params;
|
||||
|
||||
/**
|
||||
* 同步时使用的业务唯一字段名,例:username
|
||||
*/
|
||||
@NotBlank(message = "同步时使用的业务唯一字段名")
|
||||
private String businessUniqueField;
|
||||
|
||||
/**
|
||||
* 是否同步至登录黑名单
|
||||
*/
|
||||
private Boolean isSyncLogin;
|
||||
|
||||
/**
|
||||
* 同步至登录黑名单时params中代表手机号的字段名,例:userPhone
|
||||
* <p>
|
||||
* 因为目前登录黑名单以手机号作为判断依据,所以当isSyncLogin为true时此字段必填
|
||||
* </p>
|
||||
*/
|
||||
private String syncLoginField;
|
||||
|
||||
/**
|
||||
* 是否同步至注册黑名单
|
||||
*/
|
||||
private Boolean isSyncRegister;
|
||||
|
||||
/**
|
||||
* 同步至注册黑名单时params中代表手机号的字段名,例:userPhone
|
||||
* <p>
|
||||
* 因为目前注册黑名单以手机号作为判断依据,所以当isSyncRegister为true时此字段必填
|
||||
* </p>
|
||||
*/
|
||||
private String syncRegisterField;
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
package cn.axzo.nanopart.api.request;
|
||||
|
||||
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
@ -15,6 +18,9 @@ import java.util.Map;
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BlackAndWhiteListReq {
|
||||
|
||||
/**
|
||||
|
||||
@ -33,5 +33,9 @@
|
||||
<artifactId>black-list-api</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-context</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
package cn.axzo.nanopart.server.constant;
|
||||
|
||||
/**
|
||||
* @author chenwenjian
|
||||
* @version 1.0
|
||||
* @date 2024/1/3 11:28
|
||||
*/
|
||||
public class BlackAndWhiteListConstant {
|
||||
|
||||
/**
|
||||
* 所有平台登录黑名单模块名
|
||||
*/
|
||||
public static final String ALL_LOGIN = "all-login";
|
||||
|
||||
/**
|
||||
* 企业注册黑名单模块名
|
||||
*/
|
||||
public static final String OU_REGISTER_BLACK_LIST = "ou_register_black_list";
|
||||
}
|
||||
@ -3,13 +3,17 @@ package cn.axzo.nanopart.server.controller;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.nanopart.api.BlackAndWhiteListApi;
|
||||
import cn.axzo.nanopart.api.annotation.CheckSign;
|
||||
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListExcelImportReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
|
||||
import cn.axzo.nanopart.server.dao.entity.SaasBlackWhiteList;
|
||||
import cn.axzo.nanopart.server.service.BlackAndWhiteListService;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
@ -44,12 +48,12 @@ public class BlackAndWhiteListController implements BlackAndWhiteListApi {
|
||||
|
||||
@Override
|
||||
public ApiResult<Long> create(BlackAndWhiteListReq req) {
|
||||
return blackAndWhiteListService.create(req);
|
||||
return ApiResult.ok(blackAndWhiteListService.create(req));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult<Void> delete(BlackAndWhiteListReq req) {
|
||||
return blackAndWhiteListService.delete(req);
|
||||
return ApiResult.ok(blackAndWhiteListService.delete(req));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,12 +63,12 @@ public class BlackAndWhiteListController implements BlackAndWhiteListApi {
|
||||
|
||||
@Override
|
||||
public ApiResult<List<BlackAndWhiteListResp>> detail(BlackAndWhiteListReq req) {
|
||||
return blackAndWhiteListService.detail(req);
|
||||
return ApiResult.ok(blackAndWhiteListService.detail(req));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult<Boolean> isInBlackOrWhiteList(BlackAndWhiteListReq req) {
|
||||
return blackAndWhiteListService.isInBlackOrWhiteList(req);
|
||||
return ApiResult.ok(blackAndWhiteListService.isInBlackOrWhiteList(req));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,4 +77,29 @@ public class BlackAndWhiteListController implements BlackAndWhiteListApi {
|
||||
return ApiResult.ok(blackAndWhiteListService.importBlackAndWhiteListExcel(type, module, url, file));
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台同步黑白名单
|
||||
*
|
||||
* @param req @{link BlackAndWhiteListPlatformSyncReq}
|
||||
* @return
|
||||
*/
|
||||
@CheckSign(requireSignFields = {"appKey", "timestamp"})
|
||||
@Override
|
||||
public ApiResult<Boolean> platformSync(BlackAndWhiteListPlatformSyncReq req) {
|
||||
log.info("平台同步参数:req = {}", JSONUtil.toJsonStr(req));
|
||||
return ApiResult.ok(blackAndWhiteListService.platformSync(req));
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部自同步黑白名单
|
||||
*
|
||||
* @param req @{link BlackAndWhiteListInternalSyncReq}
|
||||
* @return 同步结果的记录id
|
||||
*/
|
||||
@CheckSign(requireSignFields = {"appKey", "timestamp"})
|
||||
@Override
|
||||
public ApiResult<Long> internalSync(BlackAndWhiteListInternalSyncReq req) {
|
||||
return ApiResult.ok(blackAndWhiteListService.internalSync(req));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ import cn.axzo.nanopart.server.dao.entity.SaasBlackWhiteList;
|
||||
import cn.axzo.nanopart.server.dao.mapper.BlackAndWhiteListMapper;
|
||||
import cn.azxo.framework.common.utils.StringUtils;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@ -33,7 +34,7 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
|
||||
|
||||
private final BlackAndWhiteListMapper blackAndWhiteListMapper;
|
||||
|
||||
public Long create(BlackAndWhiteListReq req){
|
||||
public Long create(BlackAndWhiteListReq req) {
|
||||
SaasBlackWhiteList blackWhiteList = BeanMapper.copyBean(req, SaasBlackWhiteList.class, (req1, saasBlackWhiteList) -> saasBlackWhiteList.setType(req1.getType().getValue()));
|
||||
Date nowTime = new Date(System.currentTimeMillis());
|
||||
blackWhiteList.setCreateAt(nowTime);
|
||||
@ -44,13 +45,13 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
|
||||
|
||||
public Void delete(BlackAndWhiteListReq req) {
|
||||
List<SaasBlackWhiteList> blackWhiteLists = detail(req);
|
||||
if (CollectionUtil.isNotEmpty(blackWhiteLists)){
|
||||
if (CollectionUtil.isNotEmpty(blackWhiteLists)) {
|
||||
blackWhiteLists.forEach(saasBlackWhiteList -> {
|
||||
lambdaUpdate().eq(SaasBlackWhiteList::getId,saasBlackWhiteList.getId())
|
||||
.eq(SaasBlackWhiteList::getIsDelete,0)
|
||||
.set(SaasBlackWhiteList::getIsDelete,saasBlackWhiteList.getId())
|
||||
lambdaUpdate().eq(SaasBlackWhiteList::getId, saasBlackWhiteList.getId())
|
||||
.eq(SaasBlackWhiteList::getIsDelete, 0)
|
||||
.set(SaasBlackWhiteList::getIsDelete, saasBlackWhiteList.getId())
|
||||
.update();
|
||||
log.info("deleted record:{}", JSONObject.valueToString(saasBlackWhiteList));
|
||||
log.info("deleted record:{}", JSONUtil.toJsonStr(saasBlackWhiteList));
|
||||
});
|
||||
}
|
||||
return null;
|
||||
@ -58,10 +59,10 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
|
||||
|
||||
public List<SaasBlackWhiteList> detail(BlackAndWhiteListReq req) {
|
||||
QueryWrapper<SaasBlackWhiteList> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("type",req.getType().getValue())
|
||||
.eq(StringUtils.isNotBlank(req.getModule()),"module",req.getModule())
|
||||
.eq("is_delete",0)
|
||||
.groupBy("type","param");
|
||||
queryWrapper.eq("type", req.getType().getValue())
|
||||
.eq(StringUtils.isNotBlank(req.getModule()), "module", req.getModule())
|
||||
.eq("is_delete", 0)
|
||||
.groupBy("type", "param");
|
||||
buildQueryWrapper(queryWrapper, req.getParam(), "");
|
||||
return blackAndWhiteListMapper.selectList(queryWrapper);
|
||||
}
|
||||
@ -83,4 +84,50 @@ public class BlackAndWhiteListRepository extends ServiceImpl<BlackAndWhiteListMa
|
||||
.set(SaasBlackWhiteList::getIsDelete, 1)
|
||||
.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 按模块删除名单
|
||||
*
|
||||
* @param type 名单类型
|
||||
* @param module 模块名
|
||||
* @return 删除结果,true:删除成功,false:删除失败
|
||||
*/
|
||||
public Boolean deleteByModule(Integer type, String module) {
|
||||
return lambdaUpdate()
|
||||
.eq(SaasBlackWhiteList::getType, type)
|
||||
.eq(SaasBlackWhiteList::getModule, module)
|
||||
.eq(SaasBlackWhiteList::getIsDelete, 0)
|
||||
.set(SaasBlackWhiteList::getIsDelete, 1)
|
||||
.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新名单参数
|
||||
*
|
||||
* @param id 名单id
|
||||
* @param param 名单参数
|
||||
* @return 更新结果,true:更新成功,false:更新失败
|
||||
*/
|
||||
public boolean updateParamById(Long id, Map<String, Object> param) {
|
||||
return lambdaUpdate()
|
||||
.eq(SaasBlackWhiteList::getIsDelete, id)
|
||||
.eq(SaasBlackWhiteList::getIsDelete, 0)
|
||||
.set(SaasBlackWhiteList::getParam, param)
|
||||
.update();
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据模块名获取名单
|
||||
*
|
||||
* @param type 名单类型
|
||||
* @param module 模块名
|
||||
* @return 名单列表
|
||||
*/
|
||||
public List<SaasBlackWhiteList> getListByModule(Integer type, String module) {
|
||||
return lambdaQuery()
|
||||
.eq(SaasBlackWhiteList::getType, type)
|
||||
.eq(SaasBlackWhiteList::getModule, module)
|
||||
.eq(SaasBlackWhiteList::getIsDelete, 0)
|
||||
.list();
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,8 @@ package cn.axzo.nanopart.server.service;
|
||||
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
|
||||
@ -19,15 +21,19 @@ import java.util.List;
|
||||
*/
|
||||
public interface BlackAndWhiteListService {
|
||||
|
||||
ApiResult<Long> create(BlackAndWhiteListReq req);
|
||||
Long create(BlackAndWhiteListReq req);
|
||||
|
||||
ApiResult<Void> delete(BlackAndWhiteListReq req);
|
||||
Void delete(BlackAndWhiteListReq req);
|
||||
|
||||
ApiResult<List<BlackAndWhiteListResp>> detail(BlackAndWhiteListReq req);
|
||||
List<BlackAndWhiteListResp> detail(BlackAndWhiteListReq req);
|
||||
|
||||
ApiResult<Boolean> isInBlackOrWhiteList(BlackAndWhiteListReq req);
|
||||
Boolean isInBlackOrWhiteList(BlackAndWhiteListReq req);
|
||||
|
||||
BlackAndWhiteListExcelImportResp importBlackAndWhiteListExcel(ListTypeEnum type, String module, String url, MultipartFile file);
|
||||
|
||||
Boolean deleteByIds(List<Long> ids);
|
||||
|
||||
Boolean platformSync(BlackAndWhiteListPlatformSyncReq req);
|
||||
|
||||
Long internalSync(BlackAndWhiteListInternalSyncReq req);
|
||||
}
|
||||
|
||||
@ -2,20 +2,26 @@ package cn.axzo.nanopart.server.service.impl;
|
||||
|
||||
import cn.axzo.basics.common.BeanMapper;
|
||||
import cn.axzo.basics.common.exception.ServiceException;
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.nanopart.api.constant.enums.ListTypeEnum;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListInternalSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListPlatformSyncReq;
|
||||
import cn.axzo.nanopart.api.request.BlackAndWhiteListReq;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListExcelImportResp;
|
||||
import cn.axzo.nanopart.api.response.BlackAndWhiteListResp;
|
||||
import cn.axzo.nanopart.server.constant.BlackAndWhiteListConstant;
|
||||
import cn.axzo.nanopart.server.dao.entity.SaasBlackWhiteList;
|
||||
import cn.axzo.nanopart.server.dao.repository.BlackAndWhiteListRepository;
|
||||
import cn.axzo.nanopart.server.service.BlackAndWhiteListService;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.context.config.annotation.RefreshScope;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
@ -24,11 +30,14 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -40,11 +49,18 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RefreshScope
|
||||
@RequiredArgsConstructor
|
||||
public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
|
||||
|
||||
private final BlackAndWhiteListRepository blackAndWhiteListRepository;
|
||||
|
||||
/**
|
||||
* 黑白名单外部平台单次最大同步记录数
|
||||
*/
|
||||
@Value("${sync.fragmentSize:1000}")
|
||||
private Long fragmentSize;
|
||||
|
||||
/**
|
||||
* 新增一条黑白名单记录
|
||||
*
|
||||
@ -52,17 +68,17 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
|
||||
* @return 记录id
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<Long> create(BlackAndWhiteListReq req) {
|
||||
public Long create(BlackAndWhiteListReq req) {
|
||||
// 黑白名单创建互斥,若存在于黑名单中则不允许存在于白名单中,反之亦然
|
||||
BlackAndWhiteListReq reverseReq = BeanMapper.copyBean(req, BlackAndWhiteListReq.class, (req1, req2) -> req2.setType((req1.getType().equals(ListTypeEnum.BLACK_LIST)) ? ListTypeEnum.WHITE_LIST : ListTypeEnum.BLACK_LIST));
|
||||
if (isInBlackOrWhiteList(reverseReq).getData()) {
|
||||
if (isInBlackOrWhiteList(reverseReq)) {
|
||||
throw new ServiceException("该记录已存在于" + reverseReq.getType().getDescription() + "中,不能创建对应" + req.getType().getDescription());
|
||||
}
|
||||
// 同类型名单内唯一性校验
|
||||
if (isInBlackOrWhiteList(req).getData()) {
|
||||
if (isInBlackOrWhiteList(req)) {
|
||||
throw new ServiceException("该记录已存在于" + req.getType().getDescription() + "中");
|
||||
}
|
||||
return ApiResult.ok(blackAndWhiteListRepository.create(req));
|
||||
return blackAndWhiteListRepository.create(req);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -72,8 +88,8 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
|
||||
* @return null
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<Void> delete(BlackAndWhiteListReq req) {
|
||||
return ApiResult.ok(blackAndWhiteListRepository.delete(req));
|
||||
public Void delete(BlackAndWhiteListReq req) {
|
||||
return blackAndWhiteListRepository.delete(req);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,10 +99,9 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
|
||||
* @return 记录列表
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<List<BlackAndWhiteListResp>> detail(BlackAndWhiteListReq req) {
|
||||
public List<BlackAndWhiteListResp> detail(BlackAndWhiteListReq req) {
|
||||
List<SaasBlackWhiteList> saasBlackWhiteLists = blackAndWhiteListRepository.detail(req);
|
||||
List<BlackAndWhiteListResp> blackAndWhiteListResps = BeanMapper.copyList(saasBlackWhiteLists, BlackAndWhiteListResp.class);
|
||||
return ApiResult.ok(blackAndWhiteListResps);
|
||||
return BeanMapper.copyList(saasBlackWhiteLists, BlackAndWhiteListResp.class);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,9 +111,9 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
|
||||
* @return 记录存在返回true,否则返回false
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<Boolean> isInBlackOrWhiteList(BlackAndWhiteListReq req) {
|
||||
public Boolean isInBlackOrWhiteList(BlackAndWhiteListReq req) {
|
||||
List<SaasBlackWhiteList> blackWhiteLists = blackAndWhiteListRepository.detail(req);
|
||||
return ApiResult.ok(CollectionUtil.isNotEmpty(blackWhiteLists));
|
||||
return CollectionUtil.isNotEmpty(blackWhiteLists);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -144,6 +159,135 @@ public class BlackAndWhiteListServiceImpl implements BlackAndWhiteListService {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 平台同步黑白名单
|
||||
*
|
||||
* @param req {@link BlackAndWhiteListPlatformSyncReq}
|
||||
* @return true-同步成功,false-同步失败
|
||||
*/
|
||||
@Override
|
||||
public Boolean platformSync(BlackAndWhiteListPlatformSyncReq req) {
|
||||
if (Objects.isNull(req.getType())) {
|
||||
throw new ServiceException("请选择正确的名单类型");
|
||||
}
|
||||
if (req.getParams().size() > fragmentSize) {
|
||||
throw new ServiceException("请主动进行分片多次同步,单次同步数小于" + fragmentSize + "条数据");
|
||||
}
|
||||
// 存入本次同步的黑/白名单记录
|
||||
req.getParams().forEach(param -> {
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put(req.getBusinessUniqueField(), param.get(req.getBusinessUniqueField()));
|
||||
List<BlackAndWhiteListResp> detail = detail(BlackAndWhiteListReq.builder()
|
||||
.type(req.getType())
|
||||
.module(req.getModule())
|
||||
.param(map)
|
||||
.build());
|
||||
// 该记录原来不存在,即未同步过,直接新增一条
|
||||
if (detail.size() == 0) {
|
||||
create(BlackAndWhiteListReq.builder()
|
||||
.type(req.getType())
|
||||
.module(req.getModule())
|
||||
.param(param)
|
||||
.build());
|
||||
} else if (detail.size() == 1) {
|
||||
updateParamById(detail.get(0).getId(), param);
|
||||
} else {
|
||||
log.warn("指定唯一字段:{},不唯一记录:{}", req.getBusinessUniqueField(), JSONUtil.toJsonStr(detail));
|
||||
throw new ServiceException("请检查指定的【业务唯一字段名:" + req.getBusinessUniqueField() + "】是否正确,记录中存在不唯一值");
|
||||
}
|
||||
});
|
||||
// 同步至登录黑名单
|
||||
if (Objects.nonNull(req.getIsSyncLogin()) && req.getIsSyncLogin()){
|
||||
internalSync(BlackAndWhiteListInternalSyncReq.builder()
|
||||
.type(req.getType())
|
||||
.sourceModule(req.getModule())
|
||||
.sourceFields(Collections.singletonList(req.getSyncLoginField()))
|
||||
.targetModule(BlackAndWhiteListConstant.ALL_LOGIN).build());
|
||||
}
|
||||
// 同步至注册黑名单
|
||||
if (Objects.nonNull(req.getIsSyncRegister()) && req.getIsSyncRegister()){
|
||||
internalSync(BlackAndWhiteListInternalSyncReq.builder()
|
||||
.type(req.getType())
|
||||
.sourceModule(req.getModule())
|
||||
.sourceFields(Collections.singletonList(req.getSyncRegisterField()))
|
||||
.targetModule(BlackAndWhiteListConstant.OU_REGISTER_BLACK_LIST).build());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 内部自同步黑白名单
|
||||
*
|
||||
* @param req {@link BlackAndWhiteListInternalSyncReq}
|
||||
* @return 同步成功的记录总条数
|
||||
*/
|
||||
public Long internalSync(BlackAndWhiteListInternalSyncReq req) {
|
||||
AtomicReference<Long> count = new AtomicReference<>(0L);
|
||||
// 获取所有源记录
|
||||
List<SaasBlackWhiteList> sourceList = blackAndWhiteListRepository.getListByModule(req.getType().getValue(), req.getSourceModule());
|
||||
|
||||
sourceList.stream().map(s -> {
|
||||
// 抽取出需要同步的字段值
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
req.getSourceFields().forEach(sf -> map.put(sf, s.getParam().get(sf)));
|
||||
return map;
|
||||
}).forEach(m -> {
|
||||
// 判断是否存在目标记录,不存在则新增一条
|
||||
if (!isInBlackOrWhiteList(BlackAndWhiteListReq.builder()
|
||||
.type(req.getType())
|
||||
.module(req.getTargetModule())
|
||||
.param(m)
|
||||
.build())) {
|
||||
create(BlackAndWhiteListReq.builder()
|
||||
.type(req.getType())
|
||||
.module(req.getTargetModule())
|
||||
.param(m)
|
||||
.build());
|
||||
count.getAndSet(count.get() + 1);
|
||||
}
|
||||
});
|
||||
return count.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定模块名的所有黑/白名单记录
|
||||
*
|
||||
* @param type 名单类型
|
||||
* @param module 模块名
|
||||
* @return 黑/白名单记录列表
|
||||
*/
|
||||
public List<BlackAndWhiteListResp> getListByModule(ListTypeEnum type, String module) {
|
||||
return BeanMapper.copyList(blackAndWhiteListRepository.getListByModule(type.getValue(), module), BlackAndWhiteListResp.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新指定id的黑白名单记录
|
||||
*
|
||||
* @param id 记录id
|
||||
* @param param 记录参数
|
||||
* @return true-更新成功,false-更新失败
|
||||
*/
|
||||
public boolean updateParamById(Long id, Map<String, Object> param) {
|
||||
return blackAndWhiteListRepository.updateParamById(id, param);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定模块名的所有黑/白名单记录
|
||||
*
|
||||
* @param type 名单类型
|
||||
* @param module 模块名
|
||||
* @return true-删除成功,false-删除失败
|
||||
*/
|
||||
public Boolean deleteByModule(ListTypeEnum type, String module) {
|
||||
if (Objects.isNull(type)) {
|
||||
throw new ServiceException("待删除名单类型不能为空");
|
||||
}
|
||||
if (!StringUtils.hasText(module)) {
|
||||
throw new ServiceException("待删除模块名不能为空");
|
||||
}
|
||||
return blackAndWhiteListRepository.deleteByModule(type.getValue(), module);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用EasyExcel读取Excel数据
|
||||
*
|
||||
|
||||
@ -4,12 +4,14 @@ import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
|
||||
@MapperScan(value = {"cn.axzo.**.mapper"})
|
||||
@SpringBootApplication
|
||||
@EnableFeignClients(basePackages = {
|
||||
"cn.axzo.nanopart.api"
|
||||
})
|
||||
@EnableAspectJAutoProxy()
|
||||
public class NanopartApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(NanopartApplication.class, args);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user