Merge branch 'master' of https://gitee.com/zhijiantianya/ruoyi-vue-pro into feature/mall_product

# Conflicts:
#	sql/mysql/mall.sql
#	sql/mysql/ruoyi-vue-pro.sql
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/wallet/vo/recharge/AppPayWalletRechargeCreateReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
#	yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java
This commit is contained in:
YunaiV
2023-11-04 20:48:27 +08:00
194 changed files with 1637 additions and 2116 deletions

View File

@ -24,8 +24,8 @@ public class SocialClientApiImpl implements SocialClientApi {
private SocialClientService socialClientService;
@Override
public String getAuthorizeUrl(Integer type, Integer userType, String redirectUri) {
return socialClientService.getAuthorizeUrl(type, userType, redirectUri);
public String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri) {
return socialClientService.getAuthorizeUrl(socialType, userType, redirectUri);
}
@Override

View File

@ -33,8 +33,8 @@ public class SocialUserApiImpl implements SocialUserApi {
}
@Override
public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) {
return socialUserService.getSocialUser(userType, type, code, state);
public SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state) {
return socialUserService.getSocialUser(userType, socialType, code, state);
}
}

View File

@ -148,7 +148,8 @@ public class AuthController {
})
public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
@RequestParam("redirectUri") String redirectUri) {
return success(socialClientService.getAuthorizeUrl(type, UserTypeEnum.ADMIN.getValue(), redirectUri));
return success(socialClientService.getAuthorizeUrl(
type, UserTypeEnum.ADMIN.getValue(), redirectUri));
}
@PostMapping("/social-login")

View File

@ -6,9 +6,9 @@ tenant-id: {{adminTenentId}}
{
"templateCode": "test_01",
"mobile": "156016913900",
"params": {
"key01": "value01",
"key02": "value02"
"mobile": "15601691390",
"templateParams": {
"operation": "value01",
"code": "value02"
}
}

View File

@ -31,5 +31,4 @@ public interface DictDataConvert {
List<AppDictDataRespVO> convertList03(List<DictDataDO> list);
List<DictDataRespDTO> convertList04(List<DictDataDO> list);
}

View File

@ -1,10 +1,10 @@
package cn.iocoder.yudao.module.system.mq.consumer.mail;
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
import cn.iocoder.yudao.module.system.service.mail.MailSendService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@ -16,12 +16,13 @@ import javax.annotation.Resource;
*/
@Component
@Slf4j
public class MailSendConsumer extends AbstractStreamMessageListener<MailSendMessage> {
public class MailSendConsumer {
@Resource
private MailSendService mailSendService;
@Override
@EventListener
@Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
public void onMessage(MailSendMessage message) {
log.info("[onMessage][消息内容({})]", message);
mailSendService.doSendMail(message);

View File

@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.system.mq.consumer.sms;
import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@ -15,12 +16,13 @@ import javax.annotation.Resource;
*/
@Component
@Slf4j
public class SmsSendConsumer extends AbstractStreamMessageListener<SmsSendMessage> {
public class SmsSendConsumer {
@Resource
private SmsSendService smsSendService;
@Override
@EventListener
@Async // Spring Event 默认在 Producer 发送的线程,通过 @Async 实现异步
public void onMessage(SmsSendMessage message) {
log.info("[onMessage][消息内容({})]", message);
smsSendService.doSendSms(message);

View File

@ -1,8 +1,6 @@
package cn.iocoder.yudao.module.system.mq.message.mail;
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@ -13,8 +11,7 @@ import javax.validation.constraints.NotNull;
* @author 芋道源码
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class MailSendMessage extends AbstractStreamMessage {
public class MailSendMessage {
/**
* 邮件日志编号
@ -47,9 +44,4 @@ public class MailSendMessage extends AbstractStreamMessage {
@NotEmpty(message = "邮件内容不能为空")
private String content;
@Override
public String getStreamKey() {
return "system.mail.send";
}
}

View File

@ -1,9 +1,7 @@
package cn.iocoder.yudao.module.system.mq.message.sms;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.validation.constraints.NotNull;
import java.util.List;
@ -14,8 +12,7 @@ import java.util.List;
* @author 芋道源码
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class SmsSendMessage extends AbstractStreamMessage {
public class SmsSendMessage {
/**
* 短信日志编号
@ -42,9 +39,4 @@ public class SmsSendMessage extends AbstractStreamMessage {
*/
private List<KeyValue<String, Object>> templateParams;
@Override
public String getStreamKey() {
return "system.sms.send";
}
}

View File

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.system.mq.producer.mail;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import cn.iocoder.yudao.module.system.mq.message.mail.MailSendMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@ -18,7 +18,7 @@ import javax.annotation.Resource;
public class MailProducer {
@Resource
private RedisMQTemplate redisMQTemplate;
private ApplicationContext applicationContext;
/**
* 发送 {@link MailSendMessage} 消息
@ -35,7 +35,7 @@ public class MailProducer {
MailSendMessage message = new MailSendMessage()
.setLogId(sendLogId).setMail(mail).setAccountId(accountId)
.setNickname(nickname).setTitle(title).setContent(content);
redisMQTemplate.send(message);
applicationContext.publishEvent(message);
}
}

View File

@ -1,9 +1,9 @@
package cn.iocoder.yudao.module.system.mq.producer.sms;
import cn.iocoder.yudao.framework.common.core.KeyValue;
import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
import cn.iocoder.yudao.module.system.mq.message.sms.SmsSendMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@ -20,7 +20,7 @@ import java.util.List;
public class SmsProducer {
@Resource
private RedisMQTemplate redisMQTemplate;
private ApplicationContext applicationContext;
/**
* 发送 {@link SmsSendMessage} 消息
@ -35,7 +35,7 @@ public class SmsProducer {
Long channelId, String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
SmsSendMessage message = new SmsSendMessage().setLogId(logId).setMobile(mobile);
message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
redisMQTemplate.send(message);
applicationContext.publishEvent(message);
}
}

View File

@ -91,8 +91,8 @@ public interface SensitiveWordService {
* 判断文本是否包含敏感词
*
* @param text 文本
* @param tags 表述数组
* @return 是否包含
* @param tags 标签数组
* @return 是否包含敏感词
*/
boolean isTextValid(String text, List<String> tags);

View File

@ -258,6 +258,7 @@ public class SensitiveWordServiceImpl implements SensitiveWordService {
if (trie == null) {
continue;
}
// 如果有一个标签不合法,则返回 false 不合法
if (!trie.isValid(text)) {
return false;
}

View File

@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory;
import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateCreateReqVO;
@ -53,9 +52,6 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
@Resource
private SmsChannelService smsChannelService;
@Resource
private SmsClientFactory smsClientFactory;
@Override
public Long createSmsTemplate(SmsTemplateCreateReqVO createReqVO) {
// 校验短信渠道
@ -173,7 +169,7 @@ public class SmsTemplateServiceImpl implements SmsTemplateService {
@VisibleForTesting
void validateApiTemplate(Long channelId, String apiTemplateId) {
// 获得短信模板
SmsClient smsClient = smsClientFactory.getSmsClient(channelId);
SmsClient smsClient = smsChannelService.getSmsClient(channelId);
Assert.notNull(smsClient, String.format("短信客户端(%d) 不存在", channelId));
SmsCommonResult<SmsTemplateRespDTO> templateResult = smsClient.getSmsTemplate(apiTemplateId);
// 校验短信模板是否正确

View File

@ -38,12 +38,12 @@ public interface SocialUserService {
/**
* 取消绑定社交用户
*
* @param userId 用户编号
* @param userId 用户编号
* @param userType 全局用户类型
* @param type 社交平台的类型 {@link SocialTypeEnum}
* @param openid 社交平台的 openid
* @param socialType 社交平台的类型 {@link SocialTypeEnum}
* @param openid 社交平台的 openid
*/
void unbindSocialUser(Long userId, Integer userType, Integer type, String openid);
void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid);
/**
* 获得社交用户
@ -51,12 +51,12 @@ public interface SocialUserService {
* 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
*
* @param userType 用户类型
* @param type 社交平台的类型
* @param code 授权码
* @param state state
* @param socialType 社交平台的类型
* @param code 授权码
* @param state state
* @return 社交用户
*/
SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state);
SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state);
// ==================== 社交用户 CRUD ====================

View File

@ -84,9 +84,9 @@ public class SocialUserServiceImpl implements SocialUserService {
}
@Override
public void unbindSocialUser(Long userId, Integer userType, Integer type, String openid) {
public void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid) {
// 获得 openid 对应的 SocialUserDO 社交用户
SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(type, openid);
SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid);
if (socialUser == null) {
throw exception(SOCIAL_USER_NOT_FOUND);
}
@ -96,9 +96,9 @@ public class SocialUserServiceImpl implements SocialUserService {
}
@Override
public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) {
public SocialUserRespDTO getSocialUser(Integer userType, Integer socialType, String code, String state) {
// 获得社交用户
SocialUserDO socialUser = authSocialUser(type, userType, code, state);
SocialUserDO socialUser = authSocialUser(socialType, userType, code, state);
Assert.notNull(socialUser, "社交用户不能为空");
// 如果未绑定的社交用户,则无法自动登录,进行报错

View File

@ -30,9 +30,10 @@ public class SimpleTrie {
* @param strs 字符串数组
*/
public SimpleTrie(Collection<String> strs) {
children = new HashMap<>();
// 排序,优先使用较短的前缀
strs = CollUtil.sort(strs, String::compareTo);
// 构建树
CollUtil.sort(strs, String::compareTo); // 排序,优先使用较短的前缀
children = new HashMap<>();
for (String str : strs) {
Map<Character, Object> child = children;
// 遍历每个字符
@ -56,11 +57,11 @@ public class SimpleTrie {
* 验证文本是否合法,即不包含敏感词
*
* @param text 文本
* @return 是否 ok
* @return 是否 true-合法 false-不合法
*/
public boolean isValid(String text) {
// 遍历 text使用每一个 [i, n) 段的字符串,使用 children 前缀树匹配,是否包含敏感词
for (int i = 0; i < text.length() - 1; i++) {
for (int i = 0; i < text.length(); i++) {
Map<Character, Object> child = (Map<Character, Object>) children.get(text.charAt(i));
if (child == null) {
continue;
@ -74,14 +75,17 @@ public class SimpleTrie {
}
/**
* 验证文本从指定位置开始,是否包含某个敏感词
* 验证文本从指定位置开始,是否包含某个敏感词
*
* @param text 文本
* @param index 开始位置
* @param child 节点(当前遍历到的)
* @return 是否包含
* @return 是否不包含 true-不包含 false-包含
*/
private boolean recursion(String text, int index, Map<Character, Object> child) {
if (child.containsKey(CHARACTER_END)) {
return false;
}
if (index == text.length()) {
return true;
}
@ -99,7 +103,7 @@ public class SimpleTrie {
*/
public List<String> validate(String text) {
Set<String> results = new HashSet<>();
for (int i = 0; i < text.length() - 1; i++) {
for (int i = 0; i < text.length(); i++) {
Character c = text.charAt(i);
Map<Character, Object> child = (Map<Character, Object>) children.get(c);
if (child == null) {
@ -127,6 +131,9 @@ public class SimpleTrie {
*/
@SuppressWarnings("unchecked")
private static boolean recursionWithResult(String text, int index, Map<Character, Object> child, StringBuilder result) {
if (child.containsKey(CHARACTER_END)) {
return false;
}
if (index == text.length()) {
return true;
}

View File

@ -56,20 +56,28 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
SensitiveWordDO wordDO2 = randomPojo(SensitiveWordDO.class, o -> o.setName("笨蛋")
.setTags(singletonList("蔬菜")).setStatus(CommonStatusEnum.ENABLE.getStatus()));
sensitiveWordMapper.insert(wordDO2);
SensitiveWordDO wordDO3 = randomPojo(SensitiveWordDO.class, o -> o.setName("")
.setTags(singletonList("测试")).setStatus(CommonStatusEnum.ENABLE.getStatus()));
sensitiveWordMapper.insert(wordDO3);
SensitiveWordDO wordDO4 = randomPojo(SensitiveWordDO.class, o -> o.setName("白痴")
.setTags(singletonList("测试")).setStatus(CommonStatusEnum.ENABLE.getStatus()));
sensitiveWordMapper.insert(wordDO4);
// 调用
sensitiveWordService.initLocalCache();
// 断言 sensitiveWordTagsCache 缓存
assertEquals(SetUtils.asSet("论坛", "蔬菜"), sensitiveWordService.getSensitiveWordTagSet());
assertEquals(SetUtils.asSet("论坛", "蔬菜", "测试"), sensitiveWordService.getSensitiveWordTagSet());
// 断言 sensitiveWordCache
assertEquals(2, sensitiveWordService.getSensitiveWordCache().size());
assertEquals(4, sensitiveWordService.getSensitiveWordCache().size());
assertPojoEquals(wordDO1, sensitiveWordService.getSensitiveWordCache().get(0));
assertPojoEquals(wordDO2, sensitiveWordService.getSensitiveWordCache().get(1));
assertPojoEquals(wordDO3, sensitiveWordService.getSensitiveWordCache().get(2));
// 断言 tagSensitiveWordTries 缓存
assertNotNull(sensitiveWordService.getDefaultSensitiveWordTrie());
assertEquals(2, sensitiveWordService.getTagSensitiveWordTries().size());
assertEquals(3, sensitiveWordService.getTagSensitiveWordTries().size());
assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("论坛"));
assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("蔬菜"));
assertNotNull(sensitiveWordService.getTagSensitiveWordTries().get("测试"));
}
@Test
@ -231,11 +239,17 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
testInitLocalCache();
// 准备参数
String text = "你是傻瓜,你是笨蛋";
// 调用
List<String> result = sensitiveWordService.validateText(text, null);
// 断言
assertEquals(Arrays.asList("傻瓜", "笨蛋"), result);
// 准备参数
String text2 = "你是傻瓜,你是笨蛋,你是白";
// 调用
List<String> result2 = sensitiveWordService.validateText(text2, null);
// 断言
assertEquals(Arrays.asList("傻瓜", "笨蛋",""), result2);
}
@Test
@ -243,11 +257,18 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
testInitLocalCache();
// 准备参数
String text = "你是傻瓜,你是笨蛋";
// 调用
List<String> result = sensitiveWordService.validateText(text, singletonList("论坛"));
// 断言
assertEquals(singletonList("傻瓜"), result);
// 准备参数
String text2 = "你是白";
// 调用
List<String> result2 = sensitiveWordService.validateText(text2, singletonList("测试"));
// 断言
assertEquals(singletonList(""), result2);
}
@Test
@ -255,9 +276,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
testInitLocalCache();
// 准备参数
String text = "你是傻瓜,你是笨蛋";
// 调用,断言
assertFalse(sensitiveWordService.isTextValid(text, null));
// 准备参数
String text2 = "你是白";
// 调用,断言
assertFalse(sensitiveWordService.isTextValid(text2, null));
}
@Test
@ -265,9 +290,13 @@ public class SensitiveWordServiceImplTest extends BaseDbUnitTest {
testInitLocalCache();
// 准备参数
String text = "你是傻瓜,你是笨蛋";
// 调用,断言
assertFalse(sensitiveWordService.isTextValid(text, singletonList("论坛")));
// 准备参数
String text2 = "你是白";
// 调用,断言
assertFalse(sensitiveWordService.isTextValid(text2, singletonList("测试")));
}
}

View File

@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.sms.core.client.SmsClient;
import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory;
import cn.iocoder.yudao.framework.sms.core.client.SmsCommonResult;
import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
@ -36,7 +35,7 @@ import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.when;
@Import(SmsTemplateServiceImpl.class)
public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
@ -50,8 +49,6 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
@MockBean
private SmsChannelService smsChannelService;
@MockBean
private SmsClientFactory smsClientFactory;
@MockBean
private SmsClient smsClient;
@Test
@ -82,7 +79,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
});
when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
// mock 获得 API 短信模板成功
when(smsClientFactory.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class,
o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode())));
@ -117,7 +114,7 @@ public class SmsTemplateServiceImplTest extends BaseDbUnitTest {
});
when(smsChannelService.getSmsChannel(eq(channelDO.getId()))).thenReturn(channelDO);
// mock 获得 API 短信模板成功
when(smsClientFactory.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
when(smsChannelService.getSmsClient(eq(reqVO.getChannelId()))).thenReturn(smsClient);
when(smsClient.getSmsTemplate(eq(reqVO.getApiTemplateId()))).thenReturn(randomPojo(SmsCommonResult.class, SmsTemplateRespDTO.class,
o -> o.setCode(GlobalErrorCodeConstants.SUCCESS.getCode())));