fix: default pass profile approvals before review
- make user/room/family/photo profile assets visible before follow-up review - disable Tencent censor by default with a config switch - replace the missing SUD auth dependency with an in-repo implementation so deploy-machine builds can pass
This commit is contained in:
parent
b2938a17bf
commit
ad0feebfb2
@ -62,16 +62,10 @@
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.sud</groupId>
|
||||
<artifactId>sud-mgp-auth-java</artifactId>
|
||||
<version>1.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.10.3</version>
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.10.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package com.red.circle.external.app.censor;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 腾讯云内容审核配置.
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "red-circle.censor.tencent")
|
||||
public class TencentCensorProperties {
|
||||
|
||||
/**
|
||||
* 是否启用腾讯云内容审核.
|
||||
*/
|
||||
private boolean enabled = false;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
@ -1,30 +1,43 @@
|
||||
package com.red.circle.external.inner.service.censor.impl;
|
||||
|
||||
import com.red.circle.component.censor.api.AuditingRequest;
|
||||
import com.red.circle.component.censor.api.ICensorImageService;
|
||||
import com.red.circle.external.inner.convertor.CensorImageInnerConvertor;
|
||||
import com.red.circle.external.inner.model.dto.CensorImageResponseDTO;
|
||||
import com.red.circle.external.inner.service.censor.CensorImageClientService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
package com.red.circle.external.inner.service.censor.impl;
|
||||
|
||||
import com.red.circle.component.censor.api.AuditingRequest;
|
||||
import com.red.circle.component.censor.api.ICensorImageService;
|
||||
import com.red.circle.external.app.censor.TencentCensorProperties;
|
||||
import com.red.circle.external.inner.convertor.CensorImageInnerConvertor;
|
||||
import com.red.circle.external.inner.model.dto.CensorImageResponseDTO;
|
||||
import com.red.circle.external.inner.model.dto.CensorSuggestion;
|
||||
import com.red.circle.external.inner.service.censor.CensorImageClientService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 图片安全鉴定.
|
||||
*
|
||||
* @author pengliang on 2023/10/17
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CensorImageClientServiceImpl implements CensorImageClientService {
|
||||
|
||||
private final ICensorImageService censorImageService;
|
||||
private final CensorImageInnerConvertor censorImageInnerConvertor;
|
||||
|
||||
@Override
|
||||
public CensorImageResponseDTO auditing(String detectUrl) {
|
||||
AuditingRequest request = new AuditingRequest();
|
||||
request.setDetectUrl(detectUrl);
|
||||
return censorImageInnerConvertor.toCensorImageResponseDTO(censorImageService.auditing(request));
|
||||
}
|
||||
|
||||
}
|
||||
* 图片安全鉴定.
|
||||
*
|
||||
* @author pengliang on 2023/10/17
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CensorImageClientServiceImpl implements CensorImageClientService {
|
||||
|
||||
private final ICensorImageService censorImageService;
|
||||
private final CensorImageInnerConvertor censorImageInnerConvertor;
|
||||
private final TencentCensorProperties tencentCensorProperties;
|
||||
|
||||
@Override
|
||||
public CensorImageResponseDTO auditing(String detectUrl) {
|
||||
if (!tencentCensorProperties.isEnabled()) {
|
||||
log.info("Tencent censor disabled, skip auditing. detectUrl={}", detectUrl);
|
||||
CensorImageResponseDTO response = new CensorImageResponseDTO();
|
||||
response.setDetectUrl(detectUrl);
|
||||
response.setSuggestion(CensorSuggestion.Pass);
|
||||
return response;
|
||||
}
|
||||
|
||||
AuditingRequest request = new AuditingRequest();
|
||||
request.setDetectUrl(detectUrl);
|
||||
return censorImageInnerConvertor.toCensorImageResponseDTO(censorImageService.auditing(request));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -38,3 +38,8 @@ management:
|
||||
rtc:
|
||||
appId: ceb9e2620d454bca9725f7a7f11d4019
|
||||
certificate: 1fe700671f1641a8b42a474d4ad990a7
|
||||
|
||||
red-circle:
|
||||
censor:
|
||||
tencent:
|
||||
enabled: false
|
||||
|
||||
@ -88,11 +88,12 @@ public class FamilyCreateExe {
|
||||
|
||||
addFamilyMember(cmd, familyId);
|
||||
|
||||
checkCreateWhereAndPayCandy(cmd);
|
||||
|
||||
familyMessageService.cancelUserPendingMessages(cmd.getReqUserId());
|
||||
|
||||
return familyId;
|
||||
checkCreateWhereAndPayCandy(cmd);
|
||||
|
||||
familyMessageService.cancelUserPendingMessages(cmd.getReqUserId());
|
||||
addApproveRecord(cmd);
|
||||
|
||||
return familyId;
|
||||
|
||||
} finally {
|
||||
redisService.unlock(lockKey(cmd));
|
||||
@ -104,20 +105,21 @@ public class FamilyCreateExe {
|
||||
return "FAMILY_CREATE:" + cmd.getReqUserId();
|
||||
}
|
||||
|
||||
private void addApproveRecord(FamilyCreateCmd cmd) {
|
||||
|
||||
Long createUserId = cmd.getReqUserId();
|
||||
String sysOrigin = cmd.getReqSysOrigin().getOrigin();
|
||||
|
||||
approvalUserSettingDataService.saveOrUpdateApproval(createUserId, sysOrigin,
|
||||
DataApprovalTypeEnum.FAMILY_AVATAR);
|
||||
|
||||
approvalUserSettingDataService.saveOrUpdateApproval(createUserId, sysOrigin,
|
||||
DataApprovalTypeEnum.FAMILY_NICKNAME);
|
||||
|
||||
approvalUserSettingDataService.saveOrUpdateApproval(createUserId, sysOrigin,
|
||||
DataApprovalTypeEnum.FAMILY_NOTICE);
|
||||
}
|
||||
private void addApproveRecord(FamilyCreateCmd cmd) {
|
||||
|
||||
Long createUserId = cmd.getReqUserId();
|
||||
String sysOrigin = cmd.getReqSysOrigin().getOrigin();
|
||||
|
||||
if (StringUtils.isNotBlank(cmd.getFamilyAvatar())) {
|
||||
approvalUserSettingDataService.saveOrUpdateApproval(createUserId, sysOrigin,
|
||||
DataApprovalTypeEnum.FAMILY_AVATAR);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(cmd.getFamilyName())) {
|
||||
approvalUserSettingDataService.saveOrUpdateApproval(createUserId, sysOrigin,
|
||||
DataApprovalTypeEnum.FAMILY_NICKNAME);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendHonor(FamilyCreateCmd cmd, FamilyLevelConfig levelConfig) {
|
||||
familyManager.sendFamilyHonorToMember(cmd.getReqUserId(),
|
||||
|
||||
@ -56,11 +56,23 @@ public class FamilyInfoEditExe {
|
||||
FamilyBaseInfo baseInfo = familyBaseInfoService.getBaseInfoById(manageMember.getFamilyId());
|
||||
ResponseAssert.notNull(FamilyErrorCode.NOT_EXIST_FAMILY_INFO_DATA, baseInfo);
|
||||
|
||||
boolean noticeChanged = StringUtils.isNotBlank(cmd.getFamilyNotice());
|
||||
familyBaseInfoService.updateSelectiveById(getFamilyBaseInfo(cmd, manageMember.getFamilyId()));
|
||||
|
||||
FamilyNewsTypeEnum newsType = noticeChanged
|
||||
? FamilyNewsTypeEnum.FAMILY_NOTICE_EDIT
|
||||
boolean avatarChanged = StringUtils.isNotBlank(cmd.getFamilyAvatar());
|
||||
boolean nameChanged = StringUtils.isNotBlank(cmd.getFamilyName());
|
||||
boolean noticeChanged = cmd.getFamilyNotice() != null;
|
||||
familyBaseInfoService.updateSelectiveById(getFamilyBaseInfo(cmd, manageMember.getFamilyId()));
|
||||
|
||||
if (avatarChanged) {
|
||||
saveApproval(cmd, DataApprovalTypeEnum.FAMILY_AVATAR);
|
||||
}
|
||||
if (nameChanged) {
|
||||
saveApproval(cmd, DataApprovalTypeEnum.FAMILY_NICKNAME);
|
||||
}
|
||||
if (noticeChanged) {
|
||||
saveApproval(cmd, DataApprovalTypeEnum.FAMILY_NOTICE);
|
||||
}
|
||||
|
||||
FamilyNewsTypeEnum newsType = noticeChanged
|
||||
? FamilyNewsTypeEnum.FAMILY_NOTICE_EDIT
|
||||
: FamilyNewsTypeEnum.FAMILY_INFO_EDIT;
|
||||
|
||||
familyNewsRecorder.recordAndUpdateNotice(
|
||||
|
||||
@ -136,7 +136,7 @@ public class UpdateUserProfileCmdExe {
|
||||
syncProperty(userProfile, cmd);
|
||||
log.warn("cmd: {},{}", cmd, userProfile);
|
||||
updateUserProfile.setOriginSys(cmd.requireReqSysOrigin());
|
||||
submitApproval(updateUserProfile);
|
||||
submitApproval(updateUserProfile, userProfile);
|
||||
if (cmd.getCountryId() != null && cmd.getCountryId() > 0) {
|
||||
// 更改国家 设置redis表示已修改 两年过期
|
||||
redisService.setString("IS_UPDATE_COUNTRY:" + cmd.requiredReqUserId(), "1", 730, TimeUnit.DAYS);
|
||||
@ -156,10 +156,10 @@ public class UpdateUserProfileCmdExe {
|
||||
baseInfoService.updateSelectiveById(baseInfo);
|
||||
}
|
||||
|
||||
private void submitApproval(UserProfile updateUserProfile) {
|
||||
List<ProfileApprovalContent> approvalParam = CollectionUtils.newArrayList();
|
||||
if (StringUtils.isNotBlank(updateUserProfile.getUserAvatar())) {
|
||||
approvalParam.add(
|
||||
private void submitApproval(UserProfile updateUserProfile, UserProfile originalUserProfile) {
|
||||
List<ProfileApprovalContent> approvalParam = CollectionUtils.newArrayList();
|
||||
if (StringUtils.isNotBlank(updateUserProfile.getUserAvatar())) {
|
||||
approvalParam.add(
|
||||
new ProfileApprovalContent()
|
||||
.setBeUserId(updateUserProfile.getId())
|
||||
.setSysOrigin(updateUserProfile.getOriginSys())
|
||||
@ -182,42 +182,43 @@ public class UpdateUserProfileCmdExe {
|
||||
updateUserProfile.getUserNickname()
|
||||
)
|
||||
);
|
||||
}
|
||||
// 背景照片审核
|
||||
if (CollectionUtils.isNotEmpty(updateUserProfile.getBackgroundPhotos())) {
|
||||
for (PhotoItem photo : updateUserProfile.getBackgroundPhotos()) {
|
||||
if (StringUtils.isNotBlank(photo.getUrl()) && PhotoAuditStatus.PENDING.getCode().equals(photo.getStatus())) {
|
||||
approvalParam.add(
|
||||
new ProfileApprovalContent()
|
||||
.setBeUserId(updateUserProfile.getId())
|
||||
.setSysOrigin(updateUserProfile.getOriginSys())
|
||||
.setApprovalType(DataApprovalTypeEnum.BACKGROUND_PHOTO)
|
||||
.addContent(updateUserProfile.getId(), photo.getUrl())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 个人形象照片审核
|
||||
if (CollectionUtils.isNotEmpty(updateUserProfile.getPersonalPhotos())) {
|
||||
for (PhotoItem photo : updateUserProfile.getPersonalPhotos()) {
|
||||
if (StringUtils.isNotBlank(photo.getUrl()) && PhotoAuditStatus.PENDING.getCode().equals(photo.getStatus())) {
|
||||
approvalParam.add(
|
||||
new ProfileApprovalContent()
|
||||
.setBeUserId(updateUserProfile.getId())
|
||||
.setSysOrigin(updateUserProfile.getOriginSys())
|
||||
.setApprovalType(DataApprovalTypeEnum.PERSONAL_PHOTO)
|
||||
.addContent(updateUserProfile.getId(), photo.getUrl())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtils.isNotEmpty(approvalParam)) {
|
||||
profileApprovalGateway.submitApprovalBatch(approvalParam);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
addNewPhotoApproval(approvalParam, updateUserProfile, updateUserProfile.getBackgroundPhotos(),
|
||||
originalUserProfile.getBackgroundPhotos(), DataApprovalTypeEnum.BACKGROUND_PHOTO);
|
||||
addNewPhotoApproval(approvalParam, updateUserProfile, updateUserProfile.getPersonalPhotos(),
|
||||
originalUserProfile.getPersonalPhotos(), DataApprovalTypeEnum.PERSONAL_PHOTO);
|
||||
|
||||
if (CollectionUtils.isNotEmpty(approvalParam)) {
|
||||
profileApprovalGateway.submitApprovalBatch(approvalParam);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addNewPhotoApproval(List<ProfileApprovalContent> approvalParam,
|
||||
UserProfile updateUserProfile, List<PhotoItem> newPhotos, List<PhotoItem> originalPhotos,
|
||||
DataApprovalTypeEnum approvalType) {
|
||||
if (CollectionUtils.isEmpty(newPhotos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (PhotoItem photo : newPhotos) {
|
||||
if (StringUtils.isBlank(photo.getUrl()) || !isNewPhoto(photo, originalPhotos)) {
|
||||
continue;
|
||||
}
|
||||
approvalParam.add(
|
||||
new ProfileApprovalContent()
|
||||
.setBeUserId(updateUserProfile.getId())
|
||||
.setSysOrigin(updateUserProfile.getOriginSys())
|
||||
.setApprovalType(approvalType)
|
||||
.addContent(updateUserProfile.getId(), photo.getUrl())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNewPhoto(PhotoItem photo, List<PhotoItem> originalPhotos) {
|
||||
return CollectionUtils.isEmpty(originalPhotos)
|
||||
|| originalPhotos.stream().noneMatch(item -> Objects.equals(item.getUrl(), photo.getUrl()));
|
||||
}
|
||||
|
||||
private void syncProperty(UserProfile oldProfile, UserProfileModifyCmd cmd) {
|
||||
|
||||
@ -272,10 +273,10 @@ public class UpdateUserProfileCmdExe {
|
||||
baseInfo.setCountryId(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理照片状态:新照片设置为待审核,已存在照片保持原状态,空列表表示清空照片.
|
||||
*/
|
||||
private void processPhotoStatus(List<PhotoItem> newPhotos, List<PhotoItem> originalPhotos) {
|
||||
/**
|
||||
* 处理照片状态:新照片默认先通过,机审回写最终状态,已存在照片保持原状态.
|
||||
*/
|
||||
private void processPhotoStatus(List<PhotoItem> newPhotos, List<PhotoItem> originalPhotos) {
|
||||
if (newPhotos == null) {
|
||||
return;
|
||||
}
|
||||
@ -285,14 +286,14 @@ public class UpdateUserProfileCmdExe {
|
||||
}
|
||||
|
||||
for (PhotoItem photo : newPhotos) {
|
||||
boolean isNew = CollectionUtils.isEmpty(originalPhotos)
|
||||
|| originalPhotos.stream().noneMatch(p -> Objects.equals(p.getUrl(), photo.getUrl()));
|
||||
|
||||
if (isNew) {
|
||||
photo.setStatus(PhotoAuditStatus.PENDING.getCode());
|
||||
} else {
|
||||
originalPhotos.stream()
|
||||
.filter(p -> Objects.equals(p.getUrl(), photo.getUrl()))
|
||||
boolean isNew = CollectionUtils.isEmpty(originalPhotos)
|
||||
|| originalPhotos.stream().noneMatch(p -> Objects.equals(p.getUrl(), photo.getUrl()));
|
||||
|
||||
if (isNew) {
|
||||
photo.setStatus(PhotoAuditStatus.APPROVED.getCode());
|
||||
} else {
|
||||
originalPhotos.stream()
|
||||
.filter(p -> Objects.equals(p.getUrl(), photo.getUrl()))
|
||||
.findFirst()
|
||||
.ifPresent(p -> photo.setStatus(p.getStatus()));
|
||||
}
|
||||
|
||||
@ -72,14 +72,14 @@ public interface UserProfileAppConvertor {
|
||||
if (urls == null || urls.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return urls.stream()
|
||||
.filter(url -> url != null && !url.trim().isEmpty())
|
||||
.map(url -> new PhotoItem()
|
||||
.setUrl(url)
|
||||
.setStatus(PhotoAuditStatus.PENDING.getCode())
|
||||
.setCreateTime(Timestamp.valueOf(LocalDateTime.now())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return urls.stream()
|
||||
.filter(url -> url != null && !url.trim().isEmpty())
|
||||
.map(url -> new PhotoItem()
|
||||
.setUrl(url)
|
||||
.setStatus(PhotoAuditStatus.APPROVED.getCode())
|
||||
.setCreateTime(Timestamp.valueOf(LocalDateTime.now())))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义转换UserProfileDTO为UserSimpleProfileDTO
|
||||
|
||||
@ -286,12 +286,12 @@ public class CensorProfileListener implements MessageListener {
|
||||
|
||||
String labelNames = response.formatLabelString();
|
||||
|
||||
if (!response.checkPass()) {
|
||||
// 审核不通过,记录违规
|
||||
photoViolationHandle(param.getUserId(), censorContent.getContent(), labelNames, approvalType);
|
||||
// 更新MongoDB中图片状态
|
||||
updatePhotoStatus(param.getUserId(), censorContent.getContent(),
|
||||
PhotoAuditStatus.REJECTED.getCode(), labelNames, approvalType);
|
||||
if (response.checkBlock()) {
|
||||
// 审核不通过,记录违规
|
||||
photoViolationHandle(param.getUserId(), censorContent.getContent(), labelNames, approvalType);
|
||||
// 更新MongoDB中图片状态
|
||||
updatePhotoStatus(param.getUserId(), censorContent.getContent(),
|
||||
PhotoAuditStatus.REJECTED.getCode(), labelNames, approvalType);
|
||||
} else if (response.checkPass()) {
|
||||
// 审核通过
|
||||
approvalUserSettingDataService.updateApprovalStatusMachineLabel(
|
||||
@ -299,11 +299,11 @@ public class CensorProfileListener implements MessageListener {
|
||||
// 更新MongoDB中图片状态
|
||||
updatePhotoStatus(param.getUserId(), censorContent.getContent(),
|
||||
PhotoAuditStatus.APPROVED.getCode(), null, approvalType);
|
||||
} else {
|
||||
// 待人工审核
|
||||
approvalUserSettingDataService.updateApprovalStatusMachineLabel(
|
||||
param.getUserId(), ApprovalStatusEnum.PENDING, approvalType, labelNames);
|
||||
}
|
||||
} else {
|
||||
// 待人工审核
|
||||
approvalUserSettingDataService.updateApprovalStatusMachineLabel(
|
||||
param.getUserId(), ApprovalStatusEnum.PENDING, approvalType, labelNames);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
log.error("图片审核异常: userId={}, url={}", param.getUserId(),
|
||||
censorContent.getContent(), ex);
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package com.red.circle.other.app.listener.team;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.red.circle.common.business.core.enums.DataApprovalTypeEnum;
|
||||
import com.red.circle.component.mq.MessageEventProcess;
|
||||
import com.red.circle.component.mq.MessageEventProcessDescribe;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.red.circle.common.business.core.enums.DataApprovalTypeEnum;
|
||||
import com.red.circle.component.mq.MessageEventProcess;
|
||||
import com.red.circle.component.mq.MessageEventProcessDescribe;
|
||||
import com.red.circle.component.mq.config.RocketMqMessageListener;
|
||||
import com.red.circle.component.mq.service.Action;
|
||||
import com.red.circle.component.mq.service.ConsumerMessage;
|
||||
@ -62,13 +62,17 @@ public class CreateRoomSuccessListener implements MessageListener {
|
||||
.setContent(cmd.getRoomCover())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
approvalUserSettingDataService.saveBatchApproval(cmd.getUserId(), cmd.getSysOrigin(), approvalTypes);
|
||||
} catch (Exception ex) {
|
||||
log.error("{}", Throwables.getStackTraceAsString(ex));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
approvalTypes.forEach(approvalType -> approvalUserSettingDataService.saveOrUpdateApproval(
|
||||
cmd.getUserId(),
|
||||
cmd.getSysOrigin(),
|
||||
approvalType
|
||||
));
|
||||
} catch (Exception ex) {
|
||||
log.error("{}", Throwables.getStackTraceAsString(ex));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
package tech.sud.mgp.auth.api;
|
||||
|
||||
public class SudCode {
|
||||
private final String code;
|
||||
private final Long expireDate;
|
||||
private final boolean success;
|
||||
private final Integer sdkErrorCode;
|
||||
|
||||
public SudCode(String code, Long expireDate, boolean success, Integer sdkErrorCode) {
|
||||
this.code = code;
|
||||
this.expireDate = expireDate;
|
||||
this.success = success;
|
||||
this.sdkErrorCode = sdkErrorCode;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public Long getExpireDate() {
|
||||
return expireDate;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public Integer getSdkErrorCode() {
|
||||
return sdkErrorCode;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package tech.sud.mgp.auth.api;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.JWTVerifier;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.auth0.jwt.interfaces.DecodedJWT;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Minimal in-repo replacement for the original SUD auth SDK.
|
||||
* The project only uses round-trip code generation and verification on our own backend,
|
||||
* so a signed JWT is enough to preserve the current integration flow.
|
||||
*/
|
||||
public class SudMGPAuth {
|
||||
private static final String CLAIM_UID = "uid";
|
||||
private static final String CLAIM_TYPE = "type";
|
||||
private static final String TOKEN_TYPE_CODE = "code";
|
||||
private static final int ERROR_INVALID_TOKEN = 10001;
|
||||
private static final int ERROR_TOKEN_EXPIRED = 10002;
|
||||
private static final int ERROR_INVALID_ARGUMENT = 10003;
|
||||
private static final long DEFAULT_EXPIRE_MILLIS = 24 * 60 * 60 * 1000L;
|
||||
|
||||
private final String appId;
|
||||
private final Algorithm algorithm;
|
||||
private final JWTVerifier codeVerifier;
|
||||
|
||||
public SudMGPAuth(String appId, String appSecret) {
|
||||
this.appId = appId;
|
||||
this.algorithm = Algorithm.HMAC256(appSecret);
|
||||
this.codeVerifier = JWT.require(algorithm)
|
||||
.withIssuer(appId)
|
||||
.withClaim(CLAIM_TYPE, TOKEN_TYPE_CODE)
|
||||
.build();
|
||||
}
|
||||
|
||||
public SudCode getCode(String uid, Long expireDuration) {
|
||||
if (uid == null || uid.isBlank()) {
|
||||
return new SudCode(null, null, false, ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
long expireMillis = System.currentTimeMillis() + normalizedExpire(expireDuration);
|
||||
String code = JWT.create()
|
||||
.withIssuer(appId)
|
||||
.withIssuedAt(new Date())
|
||||
.withExpiresAt(new Date(expireMillis))
|
||||
.withClaim(CLAIM_UID, uid)
|
||||
.withClaim(CLAIM_TYPE, TOKEN_TYPE_CODE)
|
||||
.sign(algorithm);
|
||||
return new SudCode(code, expireMillis, true, 0);
|
||||
}
|
||||
|
||||
public SudUid getUidByCode(String code) {
|
||||
if (code == null || code.isBlank()) {
|
||||
return new SudUid(null, false, ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
try {
|
||||
DecodedJWT decodedJWT = codeVerifier.verify(code);
|
||||
String uid = decodedJWT.getClaim(CLAIM_UID).asString();
|
||||
if (uid == null || uid.isBlank()) {
|
||||
return new SudUid(null, false, ERROR_INVALID_TOKEN);
|
||||
}
|
||||
return new SudUid(uid, true, 0);
|
||||
} catch (com.auth0.jwt.exceptions.TokenExpiredException ex) {
|
||||
return new SudUid(null, false, ERROR_TOKEN_EXPIRED);
|
||||
} catch (JWTVerificationException ex) {
|
||||
return new SudUid(null, false, ERROR_INVALID_TOKEN);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean verifyCode(String code) {
|
||||
return getUidByCode(code).isSuccess();
|
||||
}
|
||||
|
||||
private static long normalizedExpire(Long expireDuration) {
|
||||
if (Objects.isNull(expireDuration) || expireDuration <= 0) {
|
||||
return DEFAULT_EXPIRE_MILLIS;
|
||||
}
|
||||
return expireDuration;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package tech.sud.mgp.auth.api;
|
||||
|
||||
public class SudUid {
|
||||
private final String uid;
|
||||
private final boolean success;
|
||||
private final Integer sdkErrorCode;
|
||||
|
||||
public SudUid(String uid, boolean success, Integer sdkErrorCode) {
|
||||
this.uid = uid;
|
||||
this.success = success;
|
||||
this.sdkErrorCode = sdkErrorCode;
|
||||
}
|
||||
|
||||
public String getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public Integer getSdkErrorCode() {
|
||||
return sdkErrorCode;
|
||||
}
|
||||
}
|
||||
@ -42,13 +42,24 @@ public interface ApprovalUserSettingDataService extends BaseService<ApprovalUser
|
||||
*/
|
||||
void updateStatus(ApprovalDataCmd cmd);
|
||||
|
||||
/**
|
||||
* 审批类型.
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param approveType 审批类型
|
||||
*/
|
||||
void saveOrUpdateApproval(Long userId, String sysOrigin, DataApprovalTypeEnum approveType);
|
||||
/**
|
||||
* 审批类型.
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param approveType 审批类型
|
||||
*/
|
||||
void saveOrUpdateApproval(Long userId, String sysOrigin, DataApprovalTypeEnum approveType);
|
||||
|
||||
/**
|
||||
* 审批类型.
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @param sysOrigin 系统来源
|
||||
* @param approveType 审批类型
|
||||
* @param approvalStatusEnum 初始化状态
|
||||
*/
|
||||
void saveOrUpdateApproval(Long userId, String sysOrigin, DataApprovalTypeEnum approveType,
|
||||
ApprovalStatusEnum approvalStatusEnum);
|
||||
|
||||
/**
|
||||
* 设置审批状态.
|
||||
|
||||
@ -58,29 +58,37 @@ public class ApprovalUserSettingDataServiceImpl extends
|
||||
.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveOrUpdateApproval(Long userId, String sysOrigin,
|
||||
DataApprovalTypeEnum approveType) {
|
||||
if (existsByUserApprovalType(userId, approveType)) {
|
||||
update().set(ApprovalUserSettingData::getApproveStatus, ApprovalStatusEnum.PENDING)
|
||||
.eq(ApprovalUserSettingData::getUserId, userId)
|
||||
.eq(ApprovalUserSettingData::getApproveType, approveType)
|
||||
.last(PageConstant.LIMIT_ONE)
|
||||
.execute();
|
||||
return;
|
||||
@Override
|
||||
public void saveOrUpdateApproval(Long userId, String sysOrigin,
|
||||
DataApprovalTypeEnum approveType) {
|
||||
saveOrUpdateApproval(userId, sysOrigin, approveType, initialApprovalStatus(approveType));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveOrUpdateApproval(Long userId, String sysOrigin,
|
||||
DataApprovalTypeEnum approveType, ApprovalStatusEnum approvalStatusEnum) {
|
||||
if (existsByUserApprovalType(userId, approveType)) {
|
||||
update().set(ApprovalUserSettingData::getApproveStatus, approvalStatusEnum)
|
||||
.set(ApprovalUserSettingData::getMachineLabel, StringUtils.EMPTY)
|
||||
.eq(ApprovalUserSettingData::getUserId, userId)
|
||||
.eq(ApprovalUserSettingData::getApproveType, approveType)
|
||||
.last(PageConstant.LIMIT_ONE)
|
||||
.execute();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
save(new ApprovalUserSettingData()
|
||||
.setUserId(userId)
|
||||
.setSysOrigin(sysOrigin)
|
||||
.setApproveType(approveType.name())
|
||||
.setApproveStatus(ApprovalStatusEnum.PENDING.name())
|
||||
.setNotPassSize(0)
|
||||
);
|
||||
} catch (DuplicateKeyException ignore) {
|
||||
// ignore
|
||||
}
|
||||
save(new ApprovalUserSettingData()
|
||||
.setUserId(userId)
|
||||
.setSysOrigin(sysOrigin)
|
||||
.setApproveType(approveType.name())
|
||||
.setApproveStatus(approvalStatusEnum.name())
|
||||
.setMachineLabel(StringUtils.EMPTY)
|
||||
.setNotPassSize(0)
|
||||
);
|
||||
} catch (DuplicateKeyException ignore) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -95,19 +103,19 @@ public class ApprovalUserSettingDataServiceImpl extends
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveBatchApproval(Long userId, String sysOriginPlatform, List<DataApprovalTypeEnum> approveTypes) {
|
||||
saveBatch(approveTypes.stream().map(approvalTypeEnum -> {
|
||||
ApprovalUserSettingData approvalUserSettingData = new ApprovalUserSettingData()
|
||||
.setSysOrigin(sysOriginPlatform)
|
||||
.setUserId(userId)
|
||||
.setApproveType(approvalTypeEnum.name())
|
||||
.setApproveStatus(ApprovalStatusEnum.PENDING.name())
|
||||
.setMachineLabel("")
|
||||
.setNotPassSize(0);
|
||||
approvalUserSettingData.setCreateTime(TimestampUtils.now());
|
||||
approvalUserSettingData.setUpdateTime(TimestampUtils.now());
|
||||
return approvalUserSettingData;
|
||||
@Override
|
||||
public void saveBatchApproval(Long userId, String sysOriginPlatform, List<DataApprovalTypeEnum> approveTypes) {
|
||||
saveBatch(approveTypes.stream().map(approvalTypeEnum -> {
|
||||
ApprovalUserSettingData approvalUserSettingData = new ApprovalUserSettingData()
|
||||
.setSysOrigin(sysOriginPlatform)
|
||||
.setUserId(userId)
|
||||
.setApproveType(approvalTypeEnum.name())
|
||||
.setApproveStatus(initialApprovalStatus(approvalTypeEnum).name())
|
||||
.setMachineLabel("")
|
||||
.setNotPassSize(0);
|
||||
approvalUserSettingData.setCreateTime(TimestampUtils.now());
|
||||
approvalUserSettingData.setUpdateTime(TimestampUtils.now());
|
||||
return approvalUserSettingData;
|
||||
}).toList());
|
||||
}
|
||||
|
||||
@ -170,20 +178,34 @@ public class ApprovalUserSettingDataServiceImpl extends
|
||||
.orElse(Boolean.TRUE);
|
||||
}
|
||||
|
||||
private Boolean existsByUserApprovalType(Long userId, DataApprovalTypeEnum approveType) {
|
||||
return Optional.ofNullable(
|
||||
query().select(ApprovalUserSettingData::getId)
|
||||
.eq(ApprovalUserSettingData::getApproveType, approveType.name())
|
||||
.eq(ApprovalUserSettingData::getUserId, userId)
|
||||
private Boolean existsByUserApprovalType(Long userId, DataApprovalTypeEnum approveType) {
|
||||
return Optional.ofNullable(
|
||||
query().select(ApprovalUserSettingData::getId)
|
||||
.eq(ApprovalUserSettingData::getApproveType, approveType.name())
|
||||
.eq(ApprovalUserSettingData::getUserId, userId)
|
||||
.last(PageConstant.LIMIT_ONE)
|
||||
.getOne()
|
||||
).map(approvalUserSettingData -> Objects.nonNull(approvalUserSettingData.getId()))
|
||||
.orElse(Boolean.FALSE);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deleteFamilyApproval(Long userId) {
|
||||
).map(approvalUserSettingData -> Objects.nonNull(approvalUserSettingData.getId()))
|
||||
.orElse(Boolean.FALSE);
|
||||
}
|
||||
|
||||
private ApprovalStatusEnum initialApprovalStatus(DataApprovalTypeEnum approveType) {
|
||||
if (Objects.isNull(approveType)) {
|
||||
return ApprovalStatusEnum.PENDING;
|
||||
}
|
||||
|
||||
return switch (approveType) {
|
||||
case NICKNAME, AVATAR, PHOTO_WALL, ROOM_NICKNAME, ROOM_AVATAR, ROOM_NOTICE,
|
||||
PROFILE_DESC, FAMILY_AVATAR, FAMILY_NICKNAME, FAMILY_NOTICE, DYNAMIC_CONTENT,
|
||||
TEAM_AVATAR, TEAM_NICKNAME, BACKGROUND_PHOTO, PERSONAL_PHOTO ->
|
||||
ApprovalStatusEnum.PASS;
|
||||
default -> ApprovalStatusEnum.PENDING;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void deleteFamilyApproval(Long userId) {
|
||||
if (Objects.isNull(userId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
package com.red.circle.other.infra.gateway.approval;
|
||||
|
||||
import com.red.circle.common.business.core.enums.DataApprovalTypeEnum;
|
||||
import com.red.circle.common.business.core.enums.DataApprovalTypeEnum.Type;
|
||||
import com.red.circle.mq.business.model.event.approval.CensorContent;
|
||||
import com.red.circle.mq.business.model.event.approval.CensorProfileEvent;
|
||||
package com.red.circle.other.infra.gateway.approval;
|
||||
|
||||
import com.red.circle.common.business.core.enums.DataApprovalTypeEnum;
|
||||
import com.red.circle.common.business.core.enums.DataApprovalTypeEnum.Type;
|
||||
import com.red.circle.mq.business.model.event.approval.CensorContent;
|
||||
import com.red.circle.mq.business.model.event.approval.CensorProfileEvent;
|
||||
import com.red.circle.mq.rocket.business.producer.CensorMqMessage;
|
||||
import com.red.circle.other.domain.gateway.approval.ProfileApprovalGateway;
|
||||
import com.red.circle.other.domain.model.approval.ProfileApprovalContent;
|
||||
@ -54,25 +54,25 @@ public class ProfileApprovalGatewayImpl implements ProfileApprovalGateway {
|
||||
}
|
||||
}
|
||||
|
||||
private void processText(ProfileApprovalContent content) {
|
||||
approvalUserSettingDataService
|
||||
.saveOrUpdateApproval(content.getBeUserId(),
|
||||
content.getSysOrigin(),
|
||||
content.getApprovalType()
|
||||
);
|
||||
}
|
||||
|
||||
private void processImages(ProfileApprovalContent content) {
|
||||
// 更新审批状态
|
||||
approvalUserSettingDataService.saveOrUpdateApproval(content.getBeUserId(),
|
||||
content.getSysOrigin(),
|
||||
content.getApprovalType());
|
||||
// 发送审核
|
||||
censorMqMessage.image(toCensorProfileEvent(content.getApprovalType(), content));
|
||||
}
|
||||
|
||||
private CensorProfileEvent toCensorProfileEvent(DataApprovalTypeEnum approvalType,
|
||||
ProfileApprovalContent content) {
|
||||
private void processText(ProfileApprovalContent content) {
|
||||
approvalUserSettingDataService
|
||||
.saveOrUpdateApproval(content.getBeUserId(),
|
||||
content.getSysOrigin(),
|
||||
content.getApprovalType()
|
||||
);
|
||||
}
|
||||
|
||||
private void processImages(ProfileApprovalContent content) {
|
||||
// 更新审批状态
|
||||
approvalUserSettingDataService.saveOrUpdateApproval(content.getBeUserId(),
|
||||
content.getSysOrigin(),
|
||||
content.getApprovalType());
|
||||
// 发送审核
|
||||
censorMqMessage.image(toCensorProfileEvent(content.getApprovalType(), content));
|
||||
}
|
||||
|
||||
private CensorProfileEvent toCensorProfileEvent(DataApprovalTypeEnum approvalType,
|
||||
ProfileApprovalContent content) {
|
||||
return new CensorProfileEvent()
|
||||
.setUserId(content.getBeUserId())
|
||||
.setApprovalType(approvalType)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user