Commit d1cb0d70d272c7ccba37eefdb8d6f8b7582915b2
Merge branch '20220304' into 'master'
feat: 密码找回 See merge request huang/thingsboard3.3.2!55
Showing
10 changed files
with
180 additions
and
37 deletions
1 | package org.thingsboard.server.controller.yunteng; | 1 | package org.thingsboard.server.controller.yunteng; |
2 | 2 | ||
3 | +import io.swagger.annotations.ApiOperation; | ||
3 | import lombok.RequiredArgsConstructor; | 4 | import lombok.RequiredArgsConstructor; |
4 | import org.springframework.util.Assert; | 5 | import org.springframework.util.Assert; |
5 | -import org.springframework.web.bind.annotation.PathVariable; | ||
6 | -import org.springframework.web.bind.annotation.PostMapping; | ||
7 | -import org.springframework.web.bind.annotation.RequestMapping; | ||
8 | -import org.springframework.web.bind.annotation.RestController; | 6 | +import org.springframework.web.bind.annotation.*; |
7 | +import org.thingsboard.server.common.data.exception.ThingsboardException; | ||
8 | +import org.thingsboard.server.common.data.yunteng.dto.request.AccountReqDTO; | ||
9 | +import org.thingsboard.server.common.data.yunteng.dto.request.SendResetPasswordEmailMsg; | ||
10 | +import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum; | ||
9 | import org.thingsboard.server.dao.yunteng.service.YtSmsService; | 11 | import org.thingsboard.server.dao.yunteng.service.YtSmsService; |
12 | +import org.thingsboard.server.dao.yunteng.service.YtUserService; | ||
10 | 13 | ||
11 | import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.CHINA_MOBILE_PATTERN; | 14 | import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.CHINA_MOBILE_PATTERN; |
12 | 15 | ||
@@ -16,11 +19,24 @@ import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstan | @@ -16,11 +19,24 @@ import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstan | ||
16 | public class YtNoAuthController { | 19 | public class YtNoAuthController { |
17 | 20 | ||
18 | private final YtSmsService smsService; | 21 | private final YtSmsService smsService; |
22 | + private final YtUserService userService; | ||
19 | 23 | ||
20 | @PostMapping("/sendLoginSmsCode/{phoneNumber}") | 24 | @PostMapping("/sendLoginSmsCode/{phoneNumber}") |
21 | public boolean sendVerificationCode(@PathVariable("phoneNumber") String phoneNumber) { | 25 | public boolean sendVerificationCode(@PathVariable("phoneNumber") String phoneNumber) { |
22 | Assert.isTrue( | 26 | Assert.isTrue( |
23 | CHINA_MOBILE_PATTERN.matcher(phoneNumber).matches(), "please input correct phone number"); | 27 | CHINA_MOBILE_PATTERN.matcher(phoneNumber).matches(), "please input correct phone number"); |
24 | - return smsService.sendLoginSmsCode(phoneNumber); | 28 | + return smsService.sendSmsCode(phoneNumber, MsgTemplatePurposeEnum.FOR_LOGIN); |
29 | + } | ||
30 | + | ||
31 | + @PostMapping("/reset/{userId}") | ||
32 | + @ApiOperation("密码找回") | ||
33 | + public void saveForgetPassword(@PathVariable("phoneNumber") String phoneNumber,@RequestBody AccountReqDTO forget) throws ThingsboardException { | ||
34 | + userService.forgetPassword(phoneNumber,forget); | ||
35 | + } | ||
36 | + | ||
37 | + @PostMapping("/resetCode/{phoneNumber}") | ||
38 | + @ApiOperation("密码找回短信验证码") | ||
39 | + public void forgetPasswordCode(@PathVariable("phoneNumber") String phoneNumber) { | ||
40 | + smsService.sendSmsCode(phoneNumber, MsgTemplatePurposeEnum.FOR_FORGET_PASSWORD); | ||
25 | } | 41 | } |
26 | } | 42 | } |
@@ -10,6 +10,7 @@ import org.thingsboard.server.dao.yunteng.service.YtUserService; | @@ -10,6 +10,7 @@ import org.thingsboard.server.dao.yunteng.service.YtUserService; | ||
10 | @RestController | 10 | @RestController |
11 | @RequestMapping("/api/yt/tenant") | 11 | @RequestMapping("/api/yt/tenant") |
12 | @RequiredArgsConstructor | 12 | @RequiredArgsConstructor |
13 | +@Deprecated | ||
13 | public class YtTenantController extends BaseController { | 14 | public class YtTenantController extends BaseController { |
14 | 15 | ||
15 | private final YtUserService userService; | 16 | private final YtUserService userService; |
1 | package org.thingsboard.server.common.data.yunteng.dto; | 1 | package org.thingsboard.server.common.data.yunteng.dto; |
2 | 2 | ||
3 | +import com.fasterxml.jackson.databind.JsonNode; | ||
3 | import io.swagger.annotations.ApiModelProperty; | 4 | import io.swagger.annotations.ApiModelProperty; |
4 | import lombok.Data; | 5 | import lombok.Data; |
5 | import lombok.EqualsAndHashCode; | 6 | import lombok.EqualsAndHashCode; |
7 | +import org.thingsboard.common.util.JacksonUtil; | ||
8 | +import org.thingsboard.server.common.data.DeviceProfileType; | ||
6 | import org.thingsboard.server.common.data.DeviceTransportType; | 9 | import org.thingsboard.server.common.data.DeviceTransportType; |
7 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; | 10 | import org.thingsboard.server.common.data.device.profile.DeviceProfileData; |
8 | import org.thingsboard.server.common.data.yunteng.common.AddGroup; | 11 | import org.thingsboard.server.common.data.yunteng.common.AddGroup; |
@@ -50,26 +53,39 @@ public class DeviceProfileDTO extends TenantDTO { | @@ -50,26 +53,39 @@ public class DeviceProfileDTO extends TenantDTO { | ||
50 | /**默认消息队列*/ | 53 | /**默认消息队列*/ |
51 | private String defaultQueueName; | 54 | private String defaultQueueName; |
52 | 55 | ||
56 | + /**设备配置图片*/ | ||
57 | + private String image; | ||
58 | + /**是否默认设备配置*/ | ||
59 | + private boolean isDefault; | ||
60 | + private String type; | ||
61 | + | ||
53 | public DeviceProfileDTO() { | 62 | public DeviceProfileDTO() { |
54 | } | 63 | } |
55 | 64 | ||
56 | - public DeviceProfileDTO(UUID id, String name, Long time, String description, DeviceTransportType transportType, UUID defaultRuleChainId) { | 65 | + public DeviceProfileDTO(UUID id, String name, Long time, String description, DeviceTransportType transportType, UUID defaultRuleChainId,boolean isDefault,String image,DeviceProfileType type,Object profileData) { |
57 | setId(id.toString()); | 66 | setId(id.toString()); |
58 | setCreateTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC)); | 67 | setCreateTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC)); |
59 | this.name = name; | 68 | this.name = name; |
69 | + this.isDefault = isDefault; | ||
70 | + this.image = image; | ||
60 | this.description = description; | 71 | this.description = description; |
72 | + this.type = type.name(); | ||
61 | this.transportType = transportType.name(); | 73 | this.transportType = transportType.name(); |
62 | this.defaultRuleChainId = Optional.ofNullable(defaultRuleChainId).map(chainId -> chainId.toString()).orElse(null); | 74 | this.defaultRuleChainId = Optional.ofNullable(defaultRuleChainId).map(chainId -> chainId.toString()).orElse(null); |
75 | + this.profileData = JacksonUtil.convertValue(profileData, DeviceProfileData.class); | ||
76 | + | ||
63 | } | 77 | } |
64 | 78 | ||
65 | - public DeviceProfileDTO(UUID id, String name, Long time, String description, String convertJs, DeviceTransportType transportType, DeviceProfileData profileData, String defaultRuleChainId) { | 79 | + public DeviceProfileDTO(UUID id, String name, Long time, String description, DeviceTransportType transportType, String defaultRuleChainId,boolean isDefault,String image,DeviceProfileType type, String convertJs) { |
66 | setId(id.toString()); | 80 | setId(id.toString()); |
67 | setCreateTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC)); | 81 | setCreateTime(LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneOffset.UTC)); |
68 | this.name = name; | 82 | this.name = name; |
83 | + this.isDefault = isDefault; | ||
84 | + this.image = image; | ||
69 | this.description = description; | 85 | this.description = description; |
86 | + this.type = type.name(); | ||
70 | this.convertJs = convertJs; | 87 | this.convertJs = convertJs; |
71 | this.transportType = transportType.name(); | 88 | this.transportType = transportType.name(); |
72 | this.defaultRuleChainId = defaultRuleChainId.toString(); | 89 | this.defaultRuleChainId = defaultRuleChainId.toString(); |
73 | - this.profileData = profileData; | ||
74 | } | 90 | } |
75 | } | 91 | } |
@@ -106,9 +106,10 @@ public class YtSmsServiceImpl implements YtSmsService { | @@ -106,9 +106,10 @@ public class YtSmsServiceImpl implements YtSmsService { | ||
106 | return false; | 106 | return false; |
107 | } | 107 | } |
108 | 108 | ||
109 | + | ||
109 | @Override | 110 | @Override |
110 | @Transactional | 111 | @Transactional |
111 | - public boolean sendLoginSmsCode(String phoneNumber) { | 112 | + public boolean sendSmsCode(String phoneNumber,MsgTemplatePurposeEnum purpose) { |
112 | // 检查手机号码是否存在系统,以免乱发消息 | 113 | // 检查手机号码是否存在系统,以免乱发消息 |
113 | if (userMapper | 114 | if (userMapper |
114 | .selectList(new QueryWrapper<User>().lambda().eq(User::getPhoneNumber, phoneNumber)) | 115 | .selectList(new QueryWrapper<User>().lambda().eq(User::getPhoneNumber, phoneNumber)) |
@@ -117,7 +118,7 @@ public class YtSmsServiceImpl implements YtSmsService { | @@ -117,7 +118,7 @@ public class YtSmsServiceImpl implements YtSmsService { | ||
117 | } | 118 | } |
118 | // 获取是否有验证码存在,防止发送数量过多 | 119 | // 获取是否有验证码存在,防止发送数量过多 |
119 | String key = | 120 | String key = |
120 | - MsgTemplatePurposeEnum.FOR_LOGIN.name() | 121 | + purpose.name() |
121 | + DEFAULT_DELIMITER | 122 | + DEFAULT_DELIMITER |
122 | + MessageTypeEnum.PHONE_MESSAGE.name() | 123 | + MessageTypeEnum.PHONE_MESSAGE.name() |
123 | + DEFAULT_DELIMITER | 124 | + DEFAULT_DELIMITER |
@@ -139,7 +140,7 @@ public class YtSmsServiceImpl implements YtSmsService { | @@ -139,7 +140,7 @@ public class YtSmsServiceImpl implements YtSmsService { | ||
139 | messageTemplateMapper.selectList( | 140 | messageTemplateMapper.selectList( |
140 | new QueryWrapper<MessageTemplate>() | 141 | new QueryWrapper<MessageTemplate>() |
141 | .lambda() | 142 | .lambda() |
142 | - .eq(MessageTemplate::getTemplatePurpose, MsgTemplatePurposeEnum.FOR_LOGIN.name()) | 143 | + .eq(MessageTemplate::getTemplatePurpose, purpose.name()) |
143 | .eq(MessageTemplate::getMessageType, MessageTypeEnum.PHONE_MESSAGE.name())); | 144 | .eq(MessageTemplate::getMessageType, MessageTypeEnum.PHONE_MESSAGE.name())); |
144 | if (messageTemplates.isEmpty()) { | 145 | if (messageTemplates.isEmpty()) { |
145 | throw new YtDataValidationException("no sms provider config"); | 146 | throw new YtDataValidationException("no sms provider config"); |
@@ -152,7 +153,7 @@ public class YtSmsServiceImpl implements YtSmsService { | @@ -152,7 +153,7 @@ public class YtSmsServiceImpl implements YtSmsService { | ||
152 | smsReqDTO.setParams(params); | 153 | smsReqDTO.setParams(params); |
153 | smsReqDTO.setPhoneNumbers(phoneNumber); | 154 | smsReqDTO.setPhoneNumbers(phoneNumber); |
154 | smsReqDTO.setId(messageTemplate.getId()); | 155 | smsReqDTO.setId(messageTemplate.getId()); |
155 | - smsReqDTO.setTemplatePurpose(MsgTemplatePurposeEnum.FOR_LOGIN.name()); | 156 | + smsReqDTO.setTemplatePurpose(purpose.name()); |
156 | if (this.sendSms(smsReqDTO)) { | 157 | if (this.sendSms(smsReqDTO)) { |
157 | cacheUtils.put(MOBILE_LOGIN_SMS_CODE, key, new CodeTTL(code, System.currentTimeMillis())); | 158 | cacheUtils.put(MOBILE_LOGIN_SMS_CODE, key, new CodeTTL(code, System.currentTimeMillis())); |
158 | return true; | 159 | return true; |
@@ -11,28 +11,34 @@ import lombok.RequiredArgsConstructor; | @@ -11,28 +11,34 @@ import lombok.RequiredArgsConstructor; | ||
11 | import lombok.extern.slf4j.Slf4j; | 11 | import lombok.extern.slf4j.Slf4j; |
12 | import org.apache.commons.lang3.RandomStringUtils; | 12 | import org.apache.commons.lang3.RandomStringUtils; |
13 | import org.apache.commons.lang3.StringUtils; | 13 | import org.apache.commons.lang3.StringUtils; |
14 | +import org.springframework.context.ApplicationEventPublisher; | ||
14 | import org.springframework.scheduling.annotation.Async; | 15 | import org.springframework.scheduling.annotation.Async; |
15 | import org.springframework.security.access.AccessDeniedException; | 16 | import org.springframework.security.access.AccessDeniedException; |
17 | +import org.springframework.security.authentication.BadCredentialsException; | ||
16 | import org.springframework.security.crypto.password.PasswordEncoder; | 18 | import org.springframework.security.crypto.password.PasswordEncoder; |
17 | import org.springframework.stereotype.Service; | 19 | import org.springframework.stereotype.Service; |
18 | import org.springframework.transaction.annotation.Transactional; | 20 | import org.springframework.transaction.annotation.Transactional; |
21 | +import org.thingsboard.server.common.data.edge.EdgeEventActionType; | ||
19 | import org.thingsboard.server.common.data.id.EntityId; | 22 | import org.thingsboard.server.common.data.id.EntityId; |
23 | +import org.thingsboard.server.common.data.id.TenantId; | ||
24 | +import org.thingsboard.server.common.data.id.UserId; | ||
20 | import org.thingsboard.server.common.data.query.TsValue; | 25 | import org.thingsboard.server.common.data.query.TsValue; |
26 | +import org.thingsboard.server.common.data.security.UserCredentials; | ||
27 | +import org.thingsboard.server.common.data.security.event.UserAuthDataChangedEvent; | ||
21 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | 28 | import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; |
22 | import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | 29 | import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; |
30 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | ||
23 | import org.thingsboard.server.common.data.yunteng.core.exception.YtDataValidationException; | 31 | import org.thingsboard.server.common.data.yunteng.core.exception.YtDataValidationException; |
24 | import org.thingsboard.server.common.data.yunteng.core.exception.NoneTenantAssetException; | 32 | import org.thingsboard.server.common.data.yunteng.core.exception.NoneTenantAssetException; |
25 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | 33 | import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; |
26 | import org.thingsboard.server.common.data.yunteng.dto.*; | 34 | import org.thingsboard.server.common.data.yunteng.dto.*; |
27 | -import org.thingsboard.server.common.data.yunteng.dto.request.AccountReqDTO; | ||
28 | -import org.thingsboard.server.common.data.yunteng.dto.request.RoleOrOrganizationReqDTO; | ||
29 | -import org.thingsboard.server.common.data.yunteng.dto.request.SendResetPasswordEmailMsg; | ||
30 | -import org.thingsboard.server.common.data.yunteng.dto.request.SmsReqDTO; | 35 | +import org.thingsboard.server.common.data.yunteng.dto.request.*; |
31 | import org.thingsboard.server.common.data.yunteng.enums.MessageTypeEnum; | 36 | import org.thingsboard.server.common.data.yunteng.enums.MessageTypeEnum; |
32 | import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum; | 37 | import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum; |
33 | import org.thingsboard.server.common.data.yunteng.enums.UserStatusEnum; | 38 | import org.thingsboard.server.common.data.yunteng.enums.UserStatusEnum; |
34 | import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils; | 39 | import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils; |
35 | import org.thingsboard.server.common.data.yunteng.utils.tools.YtPageData; | 40 | import org.thingsboard.server.common.data.yunteng.utils.tools.YtPageData; |
41 | +import org.thingsboard.server.dao.user.UserService; | ||
36 | import org.thingsboard.server.dao.yunteng.entities.*; | 42 | import org.thingsboard.server.dao.yunteng.entities.*; |
37 | import org.thingsboard.server.dao.yunteng.mapper.*; | 43 | import org.thingsboard.server.dao.yunteng.mapper.*; |
38 | import org.thingsboard.server.dao.yunteng.service.*; | 44 | import org.thingsboard.server.dao.yunteng.service.*; |
@@ -43,8 +49,9 @@ import java.util.*; | @@ -43,8 +49,9 @@ import java.util.*; | ||
43 | import java.util.concurrent.CompletableFuture; | 49 | import java.util.concurrent.CompletableFuture; |
44 | import java.util.stream.Collectors; | 50 | import java.util.stream.Collectors; |
45 | 51 | ||
46 | -import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.CHINA_MOBILE_PATTERN; | ||
47 | -import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.EMAIL_PATTERN; | 52 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.*; |
53 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.CacheConfigKey.MOBILE_LOGIN_SMS_CODE; | ||
54 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.DEFAULT_DELIMITER; | ||
48 | import static org.thingsboard.server.common.data.yunteng.constant.ModelConstants.TablePropertyMapping.*; | 55 | import static org.thingsboard.server.common.data.yunteng.constant.ModelConstants.TablePropertyMapping.*; |
49 | 56 | ||
50 | @Service | 57 | @Service |
@@ -68,6 +75,10 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | @@ -68,6 +75,10 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | ||
68 | public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; | 75 | public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; |
69 | private final PasswordEncoder passwordEncoder; | 76 | private final PasswordEncoder passwordEncoder; |
70 | 77 | ||
78 | + private CacheUtils cacheUtils; | ||
79 | + private final UserService tbUserService; | ||
80 | + private final ApplicationEventPublisher eventPublisher; | ||
81 | + | ||
71 | @Override | 82 | @Override |
72 | public List<UserDetailsDTO> findUserDetailsByUsername(String username) { | 83 | public List<UserDetailsDTO> findUserDetailsByUsername(String username) { |
73 | // 多个租户可能存在多个username相同的情况 | 84 | // 多个租户可能存在多个username相同的情况 |
@@ -427,6 +438,52 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | @@ -427,6 +438,52 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | ||
427 | } | 438 | } |
428 | 439 | ||
429 | @Override | 440 | @Override |
441 | + public void forgetPassword(String phoneNumber,AccountReqDTO forget) { | ||
442 | + String key = | ||
443 | + MsgTemplatePurposeEnum.FOR_FORGET_PASSWORD.name() | ||
444 | + + DEFAULT_DELIMITER | ||
445 | + + MessageTypeEnum.PHONE_MESSAGE.name() | ||
446 | + + DEFAULT_DELIMITER | ||
447 | + + phoneNumber; | ||
448 | + boolean correct = | ||
449 | + cacheUtils | ||
450 | + .get(MOBILE_LOGIN_SMS_CODE, key) | ||
451 | + .map( | ||
452 | + o -> { | ||
453 | + CodeTTL codeTTL = (CodeTTL) o; | ||
454 | + if (System.currentTimeMillis() - codeTTL.getSendTs() < 5 * 60 * 1000) { | ||
455 | + return Objects.equals(codeTTL.getCode(), forget.getUserId()); | ||
456 | + } else { | ||
457 | + return false; | ||
458 | + } | ||
459 | + }) | ||
460 | + .orElse(false); | ||
461 | + if (!correct) { | ||
462 | + throw new BadCredentialsException("验证码不正确"); | ||
463 | + } | ||
464 | + String pwd = forget.getPassword(); | ||
465 | + if (StringUtils.isEmpty(pwd) | ||
466 | + || StringUtils.isEmpty(forget.getResetPassword()) | ||
467 | + || !pwd.equals(forget.getResetPassword())) { | ||
468 | + throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | ||
469 | + } | ||
470 | + | ||
471 | + User user = baseMapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getPhoneNumber, phoneNumber)); | ||
472 | + | ||
473 | + UserId userId = new UserId(UUID.fromString(user.getTbUser())); | ||
474 | + UserCredentials userCredentials = | ||
475 | + tbUserService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, userId); | ||
476 | + | ||
477 | + String encodePwd = passwordEncoder.encode(pwd); | ||
478 | + userCredentials.setPassword(encodePwd); | ||
479 | + user.setPassword(encodePwd); | ||
480 | + tbUserService.replaceUserCredentials(new TenantId(UUID.fromString(user.getTenantId())), userCredentials); | ||
481 | + eventPublisher.publishEvent(new UserAuthDataChangedEvent(userId)); | ||
482 | + | ||
483 | + changePassword(user); | ||
484 | + } | ||
485 | + | ||
486 | + @Override | ||
430 | public List<UserDetailsDTO> getUserByPhoneNumber(String phoneNumber) { | 487 | public List<UserDetailsDTO> getUserByPhoneNumber(String phoneNumber) { |
431 | return baseMapper.findUserDetailsByPhoneNumber(phoneNumber); | 488 | return baseMapper.findUserDetailsByPhoneNumber(phoneNumber); |
432 | } | 489 | } |
@@ -586,6 +643,11 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | @@ -586,6 +643,11 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | ||
586 | @Override | 643 | @Override |
587 | public User validateChangePasswordAccount(AccountReqDTO accountReqDTO) { | 644 | public User validateChangePasswordAccount(AccountReqDTO accountReqDTO) { |
588 | User user = baseMapper.selectById(accountReqDTO.getUserId()); | 645 | User user = baseMapper.selectById(accountReqDTO.getUserId()); |
646 | + checkPassword(accountReqDTO, user); | ||
647 | + return user; | ||
648 | + } | ||
649 | + | ||
650 | + private void checkPassword(AccountReqDTO accountReqDTO, User user) { | ||
589 | if (null == user | 651 | if (null == user |
590 | || StringUtils.isEmpty(accountReqDTO.getPassword()) | 652 | || StringUtils.isEmpty(accountReqDTO.getPassword()) |
591 | || StringUtils.isEmpty(accountReqDTO.getResetPassword())) { | 653 | || StringUtils.isEmpty(accountReqDTO.getResetPassword())) { |
@@ -597,7 +659,6 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | @@ -597,7 +659,6 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> | ||
597 | throw new YtDataValidationException(ErrorMessage.USERNAME_PASSWORD_INCORRECT.getMessage()); | 659 | throw new YtDataValidationException(ErrorMessage.USERNAME_PASSWORD_INCORRECT.getMessage()); |
598 | } | 660 | } |
599 | user.setPassword(accountReqDTO.getResetPassword()); | 661 | user.setPassword(accountReqDTO.getResetPassword()); |
600 | - return user; | ||
601 | } | 662 | } |
602 | 663 | ||
603 | /** | 664 | /** |
@@ -30,7 +30,7 @@ import java.util.UUID; | @@ -30,7 +30,7 @@ import java.util.UUID; | ||
30 | public interface YtDeviceProfileRepository extends JpaRepository<DeviceProfileEntity, UUID> { | 30 | public interface YtDeviceProfileRepository extends JpaRepository<DeviceProfileEntity, UUID> { |
31 | 31 | ||
32 | 32 | ||
33 | - @Query("SELECT new org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO(d.id, d.name, d.createdTime,d.description, d.transportType, d.defaultRuleChainId) " + | 33 | + @Query("SELECT new org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO(d.id, d.name, d.createdTime,d.description, d.transportType, d.defaultRuleChainId,d.isDefault,d.image,d.type,d.profileData) " + |
34 | "FROM DeviceProfileEntity d WHERE " + | 34 | "FROM DeviceProfileEntity d WHERE " + |
35 | "d.tenantId = :tenantId AND d.transportType = :transportType AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") | 35 | "d.tenantId = :tenantId AND d.transportType = :transportType AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") |
36 | Page<DeviceProfileDTO> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, | 36 | Page<DeviceProfileDTO> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, |
@@ -38,7 +38,7 @@ public interface YtDeviceProfileRepository extends JpaRepository<DeviceProfileEn | @@ -38,7 +38,7 @@ public interface YtDeviceProfileRepository extends JpaRepository<DeviceProfileEn | ||
38 | @Param("transportType") DeviceTransportType transportType, | 38 | @Param("transportType") DeviceTransportType transportType, |
39 | Pageable pageable); | 39 | Pageable pageable); |
40 | 40 | ||
41 | - @Query("SELECT new org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO(d.id, d.name, d.createdTime,d.description, d.transportType, d.defaultRuleChainId) " + | 41 | + @Query("SELECT new org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO(d.id, d.name, d.createdTime,d.description, d.transportType, d.defaultRuleChainId,d.isDefault,d.image,d.type,d.profileData) " + |
42 | "FROM DeviceProfileEntity d WHERE " + | 42 | "FROM DeviceProfileEntity d WHERE " + |
43 | "d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") | 43 | "d.tenantId = :tenantId AND LOWER(d.searchText) LIKE LOWER(CONCAT('%', :textSearch, '%'))") |
44 | Page<DeviceProfileDTO> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, | 44 | Page<DeviceProfileDTO> findDeviceProfileInfos(@Param("tenantId") UUID tenantId, |
@@ -46,7 +46,7 @@ public interface YtDeviceProfileRepository extends JpaRepository<DeviceProfileEn | @@ -46,7 +46,7 @@ public interface YtDeviceProfileRepository extends JpaRepository<DeviceProfileEn | ||
46 | Pageable pageable); | 46 | Pageable pageable); |
47 | 47 | ||
48 | 48 | ||
49 | - @Query("SELECT new org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO(d.id, d.name, d.createdTime,d.description, d.transportType, d.defaultRuleChainId) " + | 49 | + @Query("SELECT new org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO(d.id, d.name, d.createdTime,d.description, d.transportType, d.defaultRuleChainId,d.isDefault,d.image,d.type,d.profileData) " + |
50 | "FROM DeviceProfileEntity d WHERE d.tenantId = :tenantId ") | 50 | "FROM DeviceProfileEntity d WHERE d.tenantId = :tenantId ") |
51 | List<DeviceProfileDTO> findDeviceProfileByTenantId(@Param("tenantId") UUID tenantId); | 51 | List<DeviceProfileDTO> findDeviceProfileByTenantId(@Param("tenantId") UUID tenantId); |
52 | 52 |
@@ -2,9 +2,16 @@ package org.thingsboard.server.dao.yunteng.service; | @@ -2,9 +2,16 @@ package org.thingsboard.server.dao.yunteng.service; | ||
2 | 2 | ||
3 | 3 | ||
4 | import org.thingsboard.server.common.data.yunteng.dto.request.SmsReqDTO; | 4 | import org.thingsboard.server.common.data.yunteng.dto.request.SmsReqDTO; |
5 | +import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum; | ||
5 | 6 | ||
6 | public interface YtSmsService { | 7 | public interface YtSmsService { |
7 | boolean sendSms(SmsReqDTO smsReqDTO); | 8 | boolean sendSms(SmsReqDTO smsReqDTO); |
8 | 9 | ||
9 | - boolean sendLoginSmsCode(String phoneNumber); | 10 | + /** |
11 | + * 推送短信验证码 | ||
12 | + * @param phoneNumber 手机号 | ||
13 | + * @param purpose 模板用途 | ||
14 | + * @return | ||
15 | + */ | ||
16 | + boolean sendSmsCode(String phoneNumber, MsgTemplatePurposeEnum purpose); | ||
10 | } | 17 | } |
@@ -42,6 +42,8 @@ public interface YtUserService { | @@ -42,6 +42,8 @@ public interface YtUserService { | ||
42 | 42 | ||
43 | void resetPassword(String userId, boolean isPtSysadmin, String tenantId); | 43 | void resetPassword(String userId, boolean isPtSysadmin, String tenantId); |
44 | 44 | ||
45 | + void forgetPassword(String phoneNumber,AccountReqDTO forget); | ||
46 | + | ||
45 | List<UserDetailsDTO> getUserByPhoneNumber(String phoneNumber); | 47 | List<UserDetailsDTO> getUserByPhoneNumber(String phoneNumber); |
46 | 48 | ||
47 | void validateUserNameAndPhoneNumberAndEmail(UserDTO userDTO); | 49 | void validateUserNameAndPhoneNumberAndEmail(UserDTO userDTO); |
@@ -3,10 +3,8 @@ | @@ -3,10 +3,8 @@ | ||
3 | */ | 3 | */ |
4 | package org.thingsboard.rule.engine.yunteng.scene; | 4 | package org.thingsboard.rule.engine.yunteng.scene; |
5 | 5 | ||
6 | -import com.fasterxml.jackson.databind.JsonNode; | ||
7 | import lombok.extern.slf4j.Slf4j; | 6 | import lombok.extern.slf4j.Slf4j; |
8 | -import org.thingsboard.common.util.JacksonUtil; | ||
9 | -import org.thingsboard.rule.engine.action.TbAlarmResult; | 7 | +import org.jetbrains.annotations.NotNull; |
10 | import org.thingsboard.rule.engine.api.TbContext; | 8 | import org.thingsboard.rule.engine.api.TbContext; |
11 | import org.thingsboard.server.common.data.DataConstants; | 9 | import org.thingsboard.server.common.data.DataConstants; |
12 | import org.thingsboard.server.common.data.device.profile.AlarmCondition; | 10 | import org.thingsboard.server.common.data.device.profile.AlarmCondition; |
@@ -14,7 +12,6 @@ import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter; | @@ -14,7 +12,6 @@ import org.thingsboard.server.common.data.device.profile.AlarmConditionFilter; | ||
14 | import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey; | 12 | import org.thingsboard.server.common.data.device.profile.AlarmConditionFilterKey; |
15 | import org.thingsboard.server.common.data.rule.RuleNodeState; | 13 | import org.thingsboard.server.common.data.rule.RuleNodeState; |
16 | import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO; | 14 | import org.thingsboard.server.common.data.yunteng.dto.TriggerDTO; |
17 | -import org.thingsboard.server.common.data.yunteng.enums.ActionTypeEnum; | ||
18 | import org.thingsboard.server.common.data.yunteng.utils.SpringBeanUtils; | 15 | import org.thingsboard.server.common.data.yunteng.utils.SpringBeanUtils; |
19 | import org.thingsboard.server.common.msg.TbMsg; | 16 | import org.thingsboard.server.common.msg.TbMsg; |
20 | import org.thingsboard.server.common.msg.TbMsgMetaData; | 17 | import org.thingsboard.server.common.msg.TbMsgMetaData; |
@@ -41,6 +38,12 @@ class ReactState { | @@ -41,6 +38,12 @@ class ReactState { | ||
41 | */ | 38 | */ |
42 | private ConcurrentHashMap<String, TriggerState> triggerState = new ConcurrentHashMap<>(); | 39 | private ConcurrentHashMap<String, TriggerState> triggerState = new ConcurrentHashMap<>(); |
43 | 40 | ||
41 | + /**场景联动的执行条件状态 | ||
42 | + * 键:设备主键 | ||
43 | + * 值:设备指标参与的触发器 | ||
44 | + */ | ||
45 | + private ConcurrentHashMap<String, TriggerState> conditionState = new ConcurrentHashMap<>(); | ||
46 | + | ||
44 | 47 | ||
45 | 48 | ||
46 | 49 | ||
@@ -71,18 +74,36 @@ class ReactState { | @@ -71,18 +74,36 @@ class ReactState { | ||
71 | public void process(TbContext ctx, TbMsg msg,String deviceId) throws ExecutionException, InterruptedException { | 74 | public void process(TbContext ctx, TbMsg msg,String deviceId) throws ExecutionException, InterruptedException { |
72 | TriggerState triggerState = getOrCreateTriggerState(deviceId); | 75 | TriggerState triggerState = getOrCreateTriggerState(deviceId); |
73 | boolean matched = false; | 76 | boolean matched = false; |
74 | - if(triggerState != null && actions != null){ | 77 | + if( actions != null){ |
78 | + ctx.tellSuccess(msg); | ||
79 | + } | ||
80 | + | ||
81 | + if(triggerState != null){ | ||
75 | matched = triggerState.process(ctx,msg); | 82 | matched = triggerState.process(ctx,msg); |
76 | } | 83 | } |
77 | 84 | ||
78 | - if(matched){ | ||
79 | - // TODO 执行条件 | 85 | + |
86 | + if(matched && conditions != null ){ | ||
87 | + matched = false; | ||
88 | + for(DoCondition item:conditions){ | ||
89 | + TriggerState conditionState = getOrCreateConditionState(item.getEntityId(),item.getTriggerCondition()); | ||
90 | + boolean result = false; | ||
91 | + if( conditionState != null){ | ||
92 | + result =conditionState.process(ctx,msg); | ||
93 | + } | ||
94 | + if( result){ | ||
95 | + matched = true; | ||
96 | + break; | ||
97 | + } | ||
98 | + } | ||
80 | } | 99 | } |
81 | 100 | ||
82 | if(matched){ | 101 | if(matched){ |
83 | for(DoAction item: actions){ | 102 | for(DoAction item: actions){ |
84 | pushMsg(ctx, msg, item); | 103 | pushMsg(ctx, msg, item); |
85 | } | 104 | } |
105 | + }else{ | ||
106 | + ctx.tellSuccess(msg); | ||
86 | } | 107 | } |
87 | 108 | ||
88 | } | 109 | } |
@@ -99,18 +120,35 @@ class ReactState { | @@ -99,18 +120,35 @@ class ReactState { | ||
99 | TriggerService triggerService = SpringBeanUtils.getBean(TriggerService.class); | 120 | TriggerService triggerService = SpringBeanUtils.getBean(TriggerService.class); |
100 | TriggerDTO trigger =triggerService.getTrigger(reactId,deviceId); | 121 | TriggerDTO trigger =triggerService.getTrigger(reactId,deviceId); |
101 | if(trigger != null){ | 122 | if(trigger != null){ |
102 | - AlarmCondition condition = trigger.getTriggerCondition(); | ||
103 | - Set<AlarmConditionFilterKey> filterKeys = new HashSet<>(); | ||
104 | - for(AlarmConditionFilter filter :condition.getCondition()){ | ||
105 | - filterKeys.add(filter.getKey()); | ||
106 | - } | ||
107 | - TriggerState state = new TriggerState(deviceId,condition, filterKeys,null); | 123 | + TriggerState state = createTriggerState(deviceId, trigger.getTriggerCondition()); |
108 | triggerState.put(deviceId, state); | 124 | triggerState.put(deviceId, state); |
109 | - return state; | 125 | + return state; |
110 | } | 126 | } |
111 | return null; | 127 | return null; |
112 | } | 128 | } |
113 | 129 | ||
130 | + protected TriggerState getOrCreateConditionState(String deviceId,AlarmCondition condition) { | ||
131 | + if(conditionState.containsKey(deviceId)){ | ||
132 | + return conditionState.get(deviceId); | ||
133 | + }else{ | ||
134 | + TriggerState state = createTriggerState(deviceId, condition); | ||
135 | + conditionState.put(deviceId, state); | ||
136 | + return state; | ||
137 | + } | ||
138 | + | ||
139 | + } | ||
140 | + | ||
141 | + @NotNull | ||
142 | + private TriggerState createTriggerState(String deviceId, AlarmCondition condition) { | ||
143 | + Set<AlarmConditionFilterKey> filterKeys = new HashSet<>(); | ||
144 | + for(AlarmConditionFilter filter :condition.getCondition()){ | ||
145 | + filterKeys.add(filter.getKey()); | ||
146 | + } | ||
147 | + TriggerState state = new TriggerState(deviceId,condition, filterKeys,null); | ||
148 | + | ||
149 | + return state; | ||
150 | + } | ||
151 | + | ||
114 | private void pushMsg(TbContext ctx, TbMsg msg, DoAction action) { | 152 | private void pushMsg(TbContext ctx, TbMsg msg, DoAction action) { |
115 | TbMsgMetaData metaData = //lastMsgMetaData != null ? lastMsgMetaData.copy() : | 153 | TbMsgMetaData metaData = //lastMsgMetaData != null ? lastMsgMetaData.copy() : |
116 | new TbMsgMetaData(); | 154 | new TbMsgMetaData(); |
@@ -110,6 +110,7 @@ public class TbSceneReactNode implements TbNode { | @@ -110,6 +110,7 @@ public class TbSceneReactNode implements TbNode { | ||
110 | @Override | 110 | @Override |
111 | public void onPartitionChangeMsg(TbContext ctx, PartitionChangeMsg msg) { | 111 | public void onPartitionChangeMsg(TbContext ctx, PartitionChangeMsg msg) { |
112 | // Cleanup the cache for all entities that are no longer assigned to current server partitions | 112 | // Cleanup the cache for all entities that are no longer assigned to current server partitions |
113 | + reactStates.clear(); | ||
113 | } | 114 | } |
114 | 115 | ||
115 | protected ReactState getOrCreateReactState(TbContext ctx, TbSceneReactNodeConfig config, String sceneId) { | 116 | protected ReactState getOrCreateReactState(TbContext ctx, TbSceneReactNodeConfig config, String sceneId) { |