diff --git a/rc-service/pom.xml b/rc-service/pom.xml index 67220e9..190be9d 100644 --- a/rc-service/pom.xml +++ b/rc-service/pom.xml @@ -62,16 +62,10 @@ io.micrometer micrometer-registry-prometheus - - com.github.sud - sud-mgp-auth-java - 1.0.4 - - - - com.auth0 - java-jwt - 3.10.3 + + com.auth0 + java-jwt + 3.10.3 diff --git a/rc-service/rc-service-external/external-application/src/main/java/com/red/circle/external/app/censor/TencentCensorProperties.java b/rc-service/rc-service-external/external-application/src/main/java/com/red/circle/external/app/censor/TencentCensorProperties.java new file mode 100644 index 0000000..44a20ab --- /dev/null +++ b/rc-service/rc-service-external/external-application/src/main/java/com/red/circle/external/app/censor/TencentCensorProperties.java @@ -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; + } +} diff --git a/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/censor/impl/CensorImageClientServiceImpl.java b/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/censor/impl/CensorImageClientServiceImpl.java index 57cfe57..c873ab8 100644 --- a/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/censor/impl/CensorImageClientServiceImpl.java +++ b/rc-service/rc-service-external/external-inner-endpoint/src/main/java/com/red/circle/external/inner/service/censor/impl/CensorImageClientServiceImpl.java @@ -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)); + } + +} diff --git a/rc-service/rc-service-external/external-start/src/main/resources/application.yml b/rc-service/rc-service-external/external-start/src/main/resources/application.yml index 770ca94..3eb16af 100644 --- a/rc-service/rc-service-external/external-start/src/main/resources/application.yml +++ b/rc-service/rc-service-external/external-start/src/main/resources/application.yml @@ -38,3 +38,8 @@ management: rtc: appId: ceb9e2620d454bca9725f7a7f11d4019 certificate: 1fe700671f1641a8b42a474d4ad990a7 + +red-circle: + censor: + tencent: + enabled: false diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyCreateExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyCreateExe.java index 644add4..8e96cef 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyCreateExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyCreateExe.java @@ -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(), diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyInfoEditExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyInfoEditExe.java index e035d1d..feb3358 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyInfoEditExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/family/FamilyInfoEditExe.java @@ -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( diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/UpdateUserProfileCmdExe.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/UpdateUserProfileCmdExe.java index 28f9fe3..6be7d74 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/UpdateUserProfileCmdExe.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/command/user/UpdateUserProfileCmdExe.java @@ -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 approvalParam = CollectionUtils.newArrayList(); - if (StringUtils.isNotBlank(updateUserProfile.getUserAvatar())) { - approvalParam.add( + private void submitApproval(UserProfile updateUserProfile, UserProfile originalUserProfile) { + List 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 approvalParam, + UserProfile updateUserProfile, List newPhotos, List 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 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 newPhotos, List originalPhotos) { + /** + * 处理照片状态:新照片默认先通过,机审回写最终状态,已存在照片保持原状态. + */ + private void processPhotoStatus(List newPhotos, List 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())); } diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserProfileAppConvertor.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserProfileAppConvertor.java index 52e831c..6268f9f 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserProfileAppConvertor.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/convertor/user/UserProfileAppConvertor.java @@ -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 diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/CensorProfileListener.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/CensorProfileListener.java index 2083525..fb24bfa 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/CensorProfileListener.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/CensorProfileListener.java @@ -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); diff --git a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/team/CreateRoomSuccessListener.java b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/team/CreateRoomSuccessListener.java index e079bd1..b62a1b7 100644 --- a/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/team/CreateRoomSuccessListener.java +++ b/rc-service/rc-service-other/other-application/src/main/java/com/red/circle/other/app/listener/team/CreateRoomSuccessListener.java @@ -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)); + } + + } +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudCode.java b/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudCode.java new file mode 100644 index 0000000..009ed99 --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudCode.java @@ -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; + } +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudMGPAuth.java b/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudMGPAuth.java new file mode 100644 index 0000000..ea54ee4 --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudMGPAuth.java @@ -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; + } +} diff --git a/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudUid.java b/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudUid.java new file mode 100644 index 0000000..a470e5b --- /dev/null +++ b/rc-service/rc-service-other/other-client/src/main/java/tech/sud/mgp/auth/api/SudUid.java @@ -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; + } +} diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/approval/ApprovalUserSettingDataService.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/approval/ApprovalUserSettingDataService.java index 07f41c9..7c2949e 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/approval/ApprovalUserSettingDataService.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/database/rds/service/approval/ApprovalUserSettingDataService.java @@ -42,13 +42,24 @@ public interface ApprovalUserSettingDataService extends BaseService 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 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; } diff --git a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/approval/ProfileApprovalGatewayImpl.java b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/approval/ProfileApprovalGatewayImpl.java index 712e1ba..7218fb6 100644 --- a/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/approval/ProfileApprovalGatewayImpl.java +++ b/rc-service/rc-service-other/other-infrastructure/src/main/java/com/red/circle/other/infra/gateway/approval/ProfileApprovalGatewayImpl.java @@ -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)