Commit 09a3162dc0322ec7c3665fe611d36401b351e2f0

Authored by 黄 x
1 parent 699e9493

feat: 合并yunteng的IOT代码

Showing 100 changed files with 3386 additions and 429 deletions

Too many changes to show.

To preserve performance only 100 of 187 files are displayed.

  1 +package org.thingsboard.server.controller.yunteng;
  2 +
  3 +
  4 +import lombok.RequiredArgsConstructor;
  5 +import org.springframework.util.Assert;
  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.RoleDTO;
  9 +import org.thingsboard.server.common.data.yunteng.dto.request.RoleReqDTO;
  10 +import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
  11 +import org.thingsboard.server.common.data.yunteng.enums.RoleEnum;
  12 +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData;
  13 +import org.thingsboard.server.controller.BaseController;
  14 +import org.thingsboard.server.dao.yunteng.service.RoleService;
  15 +
  16 +import java.util.HashMap;
  17 +import java.util.List;
  18 +import java.util.Set;
  19 +
  20 +import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
  21 +
  22 +
  23 +@RestController
  24 +@RequestMapping("api/v1/role")
  25 +@RequiredArgsConstructor
  26 +public class RoleController extends BaseController {
  27 +
  28 + private final RoleService roleService;
  29 +
  30 + @GetMapping(params = {PAGE_SIZE, PAGE})
  31 + public PageData<RoleDTO> pageRole(
  32 + @RequestParam(PAGE_SIZE) int pageSize,
  33 + @RequestParam(PAGE) int page,
  34 + @RequestParam(value = "roleName", required = false) String roleName,
  35 + @RequestParam(value = "status", required = false) Integer status,
  36 + @RequestParam(value = "roleType", required = false) RoleEnum roleType,
  37 + @RequestParam(value = ORDER_FILED, required = false) String orderBy,
  38 + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType) throws ThingsboardException {
  39 + HashMap<String, Object> queryMap = new HashMap<>();
  40 + queryMap.put(PAGE_SIZE, pageSize);
  41 + queryMap.put(PAGE, page);
  42 + queryMap.put(ORDER_FILED, orderBy);
  43 + queryMap.put("roleName", roleName);
  44 + if (status != null) {
  45 + queryMap.put("status", status == 1);
  46 + }
  47 + if(roleType !=null){
  48 + queryMap.put("roleType", roleType.name());
  49 + }
  50 + if (orderType != null) {
  51 + queryMap.put(ORDER_TYPE, orderType.name());
  52 + }
  53 + return roleService.page(getCurrentUser().isSysadmin(), getCurrentUser().isPlatformAdmin(), getCurrentUser().getCurrentTenantId(),queryMap);
  54 + }
  55 +
  56 + @DeleteMapping
  57 + public void deleteRole(@RequestBody String[] ids) throws ThingsboardException {
  58 + roleService.deleteRole(ids,getCurrentUser().getCurrentTenantId());
  59 + }
  60 +
  61 + @GetMapping("/me/permissions")
  62 + public Set<String> getPermissions() throws ThingsboardException {
  63 + return roleService.getPermissions(getCurrentUser().isSysadmin(), getCurrentUser().isTenantAdmin(), getCurrentUser().getCurrentTenantId(), getCurrentUser().getCurrentUserId());
  64 + }
  65 +
  66 + @PutMapping("updateRoleStatus/{roleId}/{status}")
  67 + public void updateRoleStatus(
  68 + @PathVariable("roleId") String roleId, @PathVariable("status") int status) throws ThingsboardException {
  69 + Assert.isTrue(status == 0 || status == 1, "role status is not correct");
  70 + roleService.updateRoleStatus(roleId, status, getCurrentUser().isSysadmin() ,getCurrentUser().getCurrentTenantId());
  71 + }
  72 +
  73 + @PostMapping("saveOrUpdateRoleInfoWithMenu")
  74 + public RoleDTO saveOrUpdateRoleInfoWithMenu(@RequestBody RoleReqDTO roleReqDTO) throws ThingsboardException {
  75 + return roleService.saveOrUpdateRoleInfoWithMenu(
  76 + roleReqDTO,
  77 + getCurrentUser().isSysadmin(),
  78 + getCurrentUser().isPlatformAdmin(),
  79 + getCurrentUser().getCurrentTenantId());
  80 + }
  81 +
  82 + @PostMapping("/find/list")
  83 + public List<RoleDTO> findRoleInfoList(@RequestBody RoleDTO roleDTO) throws ThingsboardException {
  84 + return roleService.findRoleInfo(getCurrentUser().isTenantAdmin(), getCurrentUser().getCurrentTenantId(),getCurrentUser().getCurrentUserId(), roleDTO);
  85 + }
  86 +}
  1 +package org.thingsboard.server.controller.yunteng;
  2 +
  3 +import lombok.RequiredArgsConstructor;
  4 +import org.springframework.http.ResponseEntity;
  5 +import org.springframework.security.access.prepost.PreAuthorize;
  6 +import org.springframework.util.Assert;
  7 +import org.springframework.validation.annotation.Validated;
  8 +import org.springframework.web.bind.annotation.*;
  9 +import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
  10 +import org.thingsboard.server.common.data.exception.ThingsboardException;
  11 +import org.thingsboard.server.common.data.yunteng.common.UpdateGroup;
  12 +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException;
  13 +import org.thingsboard.server.common.data.yunteng.dto.MenuDTO;
  14 +import org.thingsboard.server.common.data.yunteng.dto.TenantDTO;
  15 +import org.thingsboard.server.common.data.yunteng.dto.UserDTO;
  16 +import org.thingsboard.server.common.data.yunteng.dto.request.TenantReqDTO;
  17 +import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
  18 +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData;
  19 +import org.thingsboard.server.controller.BaseController;
  20 +import org.thingsboard.server.dao.yunteng.service.MenuService;
  21 +import org.thingsboard.server.dao.yunteng.service.YtTenantService;
  22 +import org.thingsboard.server.dao.yunteng.service.YtUserService;
  23 +
  24 +import java.net.URI;
  25 +import java.util.*;
  26 +
  27 +import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
  28 +
  29 +@RestController
  30 +@RequestMapping("api/v1/admin")
  31 +@RequiredArgsConstructor
  32 +@PreAuthorize("hasAnyRole('SYS_ADMIN','PLATFORM_ADMIN')")
  33 +public class YtAdminController extends BaseController {
  34 +
  35 + private final YtTenantService ytTenantService;
  36 + private final MenuService menuService;
  37 + private final YtUserService userService;
  38 +
  39 + @PostMapping("/tenant")
  40 + public ResponseEntity<TenantDTO> saveTenant(@RequestBody TenantReqDTO tenantReqDTO) {
  41 + TenantDTO newTenant = ytTenantService.createNewTenant(tenantReqDTO);
  42 + URI location =
  43 + ServletUriComponentsBuilder.fromCurrentRequest()
  44 + .path("/tenant/getById/{id}")
  45 + .buildAndExpand(newTenant.getId())
  46 + .toUri();
  47 + return ResponseEntity.created(location).body(newTenant);
  48 + }
  49 +
  50 + @GetMapping(
  51 + path = "tenant/page",
  52 + params = {PAGE_SIZE, PAGE})
  53 + public PageData<TenantDTO> pageUser(
  54 + @RequestParam(PAGE_SIZE) int pageSize,
  55 + @RequestParam(PAGE) int page,
  56 + @RequestParam(value = "tenantName", required = false) String tenantName,
  57 + @RequestParam(value = ORDER_FILED, required = false) String orderBy,
  58 + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType) {
  59 + HashMap<String, Object> queryMap = new HashMap<>();
  60 + queryMap.put(PAGE_SIZE, pageSize);
  61 + queryMap.put(PAGE, page);
  62 + queryMap.put(ORDER_FILED, orderBy);
  63 + if (orderType != null) {
  64 + queryMap.put(ORDER_TYPE, orderType.name());
  65 + }
  66 + queryMap.put("tenantName", tenantName);
  67 + return ytTenantService.page(queryMap);
  68 + }
  69 +
  70 + @PutMapping("/tenant")
  71 + public TenantDTO updateTenant(@RequestBody TenantDTO tenantDTO) {
  72 + Assert.notNull(tenantDTO, "tenant cannot be null");
  73 + Assert.notNull(tenantDTO.getId(), "tenant id cannot be null when update");
  74 + return ytTenantService.updateTenant(tenantDTO);
  75 + }
  76 +
  77 + @GetMapping("/tenant/roles/{tenantCode}")
  78 + public ResponseEntity<List<String>> getTenantRolesByTenantCode(
  79 + @PathVariable("tenantCode") String tenantCode) {
  80 + return ResponseEntity.ok(ytTenantService.getTenantRolesByTenantCode(tenantCode));
  81 + }
  82 +
  83 + @DeleteMapping("/tenant")
  84 + public void deleteTenant(@RequestBody String[] ids) {
  85 + Assert.notNull(ids, "ids cannot be null");
  86 + if (ids.length == 0) {
  87 + throw new DataValidationException("id cannot be empty");
  88 + }
  89 + ytTenantService.deleteTenants(ids);
  90 + }
  91 +
  92 + @DeleteMapping("/user/deleteTenantAdmin")
  93 + public void deleteTenantAdmin(@RequestBody String[] ids) throws ThingsboardException {
  94 + Assert.notNull(ids, "ids cannot be null");
  95 + userService.deleteUser(
  96 + new HashSet<>(Arrays.asList(ids)),
  97 + getCurrentUser().isSysadmin(),
  98 + getCurrentUser().getCurrentTenantId());
  99 + }
  100 +
  101 + @GetMapping("/tenant/getById/{id}")
  102 + public ResponseEntity<TenantDTO> getTenant(@PathVariable("id") String id) {
  103 + return ResponseEntity.of(ytTenantService.findById(id));
  104 + }
  105 +
  106 + @PostMapping("/tenant/adminUser")
  107 + public ResponseEntity<UserDTO> createTenantAdmin(
  108 + @RequestParam(value = "sendEmail", required = false, defaultValue = "false")
  109 + boolean sendEmail,
  110 + @RequestParam(value = "sendMsg", required = false, defaultValue = "false") boolean sendMsg,
  111 + @RequestBody UserDTO userDTO)
  112 + throws ThingsboardException {
  113 + UserDTO newUserDTO =
  114 + userService.saveAccount(
  115 + userDTO,
  116 + sendEmail,
  117 + sendMsg,
  118 + getCurrentUser().isSysadmin(),
  119 + getCurrentUser().getCurrentTenantId());
  120 + Optional<UserDTO> optional =
  121 + userService.getUser(
  122 + newUserDTO.getId(),
  123 + getCurrentUser().isSysadmin(),
  124 + getCurrentUser().getCurrentTenantId());
  125 + return ResponseEntity.ok(optional.get());
  126 + }
  127 +
  128 + @GetMapping("/menu/getAll")
  129 + public ResponseEntity<List<MenuDTO>> getMenus() throws ThingsboardException {
  130 + return ResponseEntity.ok(menuService.getAllMenus(getCurrentUser().getCurrentTenantId()));
  131 + }
  132 +
  133 + @GetMapping("me/menus")
  134 + public ResponseEntity<List<MenuDTO>> getMyMenus() throws ThingsboardException {
  135 + return ResponseEntity.ok(
  136 + menuService.getMyMenus(
  137 + getCurrentUser().getCurrentTenantId(),
  138 + getCurrentUser().getCurrentUserId(),
  139 + getCurrentUser().isSysadmin(), getCurrentUser().isTenantAdmin()));
  140 + }
  141 +
  142 + @PutMapping("/menu/assign/{tenantCode}")
  143 + public void assignMenuToTenant(
  144 + @RequestBody String[] menuIds, @PathVariable("tenantCode") String tenantCode) throws ThingsboardException {
  145 + menuService.assignMenuToTenant(getCurrentUser().getCurrentTenantId(), menuIds);
  146 + }
  147 +
  148 + @PostMapping("tenant/updateOrCreateTenant")
  149 + public TenantDTO updateOrCreateTenant(
  150 + @Validated(UpdateGroup.class) @RequestBody TenantReqDTO tenantReqDTO) {
  151 + return ytTenantService.updateOrCreateTenant(tenantReqDTO);
  152 + }
  153 +}
  1 +package org.thingsboard.server.controller.yunteng;
  2 +
  3 +import io.swagger.annotations.Api;
  4 +import io.swagger.annotations.ApiOperation;
  5 +import io.swagger.annotations.ApiResponse;
  6 +import io.swagger.annotations.ApiResponses;
  7 +import lombok.RequiredArgsConstructor;
  8 +import org.apache.commons.lang3.StringUtils;
  9 +import org.springframework.http.ResponseEntity;
  10 +import org.springframework.security.access.prepost.PreAuthorize;
  11 +import org.springframework.util.Assert;
  12 +import org.springframework.validation.annotation.Validated;
  13 +import org.springframework.web.bind.annotation.*;
  14 +import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
  15 +import org.thingsboard.server.common.data.exception.ThingsboardException;
  16 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  17 +import org.thingsboard.server.common.data.yunteng.common.DeleteGroup;
  18 +import org.thingsboard.server.common.data.yunteng.utils.Demo;
  19 +import org.thingsboard.server.common.data.yunteng.utils.ExcelUtil;
  20 +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
  21 +import org.thingsboard.server.common.data.yunteng.dto.UserDTO;
  22 +import org.thingsboard.server.common.data.yunteng.dto.UserInfoDTO;
  23 +import org.thingsboard.server.common.data.yunteng.dto.request.AccountReqDTO;
  24 +import org.thingsboard.server.common.data.yunteng.dto.request.RoleOrOrganizationReqDTO;
  25 +import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
  26 +import org.thingsboard.server.common.data.yunteng.enums.RoleEnum;
  27 +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData;
  28 +import org.thingsboard.server.common.data.yunteng.utils.tools.ResponseResult;
  29 +import org.thingsboard.server.controller.BaseController;
  30 +import org.thingsboard.server.dao.yunteng.service.YtUserService;
  31 +
  32 +import javax.servlet.http.HttpServletRequest;
  33 +import javax.servlet.http.HttpServletResponse;
  34 +import java.io.IOException;
  35 +import java.net.URI;
  36 +import java.util.HashMap;
  37 +import java.util.List;
  38 +
  39 +import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*;
  40 +
  41 +@RestController
  42 +@RequestMapping("api/v1/user")
  43 +@RequiredArgsConstructor
  44 +@Api(value = "用户接口")
  45 +public class YtUserController extends BaseController {
  46 +
  47 + private final YtUserService userService;
  48 +
  49 + @GetMapping("{userId}")
  50 + public ResponseEntity<UserDTO> getUser(@PathVariable("userId") String userId)
  51 + throws ThingsboardException {
  52 + return ResponseEntity.of(
  53 + userService.getUser(
  54 + userId, getCurrentUser().isSysadmin(), getCurrentUser().getCurrentTenantId()));
  55 + }
  56 +
  57 + @GetMapping("me/info")
  58 + @ApiResponses({@ApiResponse(code = 200, message = "OK", response = UserInfoDTO.class)})
  59 + @ApiOperation(value = "获取当前用户信息")
  60 + public UserInfoDTO myInfo() throws ThingsboardException {
  61 + return userService.me(
  62 + getCurrentUser().getCurrentUserId(),
  63 + getCurrentUser().getCurrentTenantId(),
  64 + getCurrentUser().getRoles());
  65 + }
  66 +
  67 + @GetMapping(
  68 + path = "page",
  69 + params = {PAGE_SIZE, PAGE})
  70 + public PageData<UserDTO> pageUser(
  71 + @RequestParam(PAGE_SIZE) int pageSize,
  72 + @RequestParam(PAGE) int page,
  73 + @RequestParam(value = "realName", required = false) String realName,
  74 + @RequestParam(value = "username", required = false) String username,
  75 + @RequestParam(value = "tenantCode", required = false) String tenantCode,
  76 + @RequestParam(value = "roleType", required = false) RoleEnum roleType,
  77 + @RequestParam(value = ORDER_FILED, required = false) String orderBy,
  78 + @RequestParam(value = ORDER_TYPE, required = false) OrderTypeEnum orderType)
  79 + throws ThingsboardException {
  80 + HashMap<String, Object> queryMap = new HashMap<>();
  81 + queryMap.put(PAGE_SIZE, pageSize);
  82 + queryMap.put(PAGE, page);
  83 + queryMap.put(ORDER_FILED, orderBy);
  84 + queryMap.put("realName", realName);
  85 + queryMap.put("username", username);
  86 + if (getCurrentUser().isSysadmin()) {
  87 + if (StringUtils.isEmpty(tenantCode)) {
  88 + tenantCode = getCurrentUser().getCurrentTenantId();
  89 + }
  90 + queryMap.put("tenantCode", tenantCode);
  91 + }
  92 + if (null != roleType) {
  93 + queryMap.put("roleType", roleType.name());
  94 + }
  95 + if (orderType != null) {
  96 + queryMap.put(ORDER_TYPE, orderType.name());
  97 + }
  98 + return userService.page(
  99 + queryMap,
  100 + getCurrentUser().isSysadmin(),
  101 + getCurrentUser().isPlatformAdmin(),
  102 + getCurrentUser().isTenantAdmin(),
  103 + getCurrentUser().getCurrentTenantId());
  104 + }
  105 +
  106 + @PutMapping
  107 + public UserDTO updateUser(@RequestBody UserDTO userDTO) throws ThingsboardException {
  108 + return userService.updateUser(
  109 + userDTO, getCurrentUser().isSysadmin(), getCurrentUser().getCurrentTenantId());
  110 + }
  111 +
  112 + @PostMapping
  113 + public ResponseEntity<UserDTO> addUser(
  114 + @RequestParam(value = "sendEmail", required = false, defaultValue = "false")
  115 + boolean sendEmail,
  116 + @RequestParam(value = "sendMsg", required = false, defaultValue = "false") boolean sendMsg,
  117 + @Validated({AddGroup.class}) @RequestBody UserDTO userDTO)
  118 + throws ThingsboardException {
  119 + UserDTO newUserDTO =
  120 + userService.saveAccount(
  121 + userDTO,
  122 + sendEmail,
  123 + sendMsg,
  124 + getCurrentUser().isSysadmin(),
  125 + getCurrentUser().getCurrentTenantId());
  126 + URI location =
  127 + ServletUriComponentsBuilder.fromCurrentRequest()
  128 + .path("{id}")
  129 + .buildAndExpand(newUserDTO.getId())
  130 + .toUri();
  131 + return ResponseEntity.created(location).body(newUserDTO);
  132 + }
  133 +
  134 + @PreAuthorize("hasRole('SYS_ADMIN')")
  135 + @PostMapping("saveTenantAdmin")
  136 + public UserDTO saveTenantAdmin(@RequestBody UserDTO userDTO) throws ThingsboardException {
  137 + Assert.isTrue(StringUtils.isNotBlank(userDTO.getTenantCode()), "tenant code must exist");
  138 + Assert.notNull(userDTO.getUsername(), "username must exist");
  139 + Assert.notNull(userDTO.getRealName(), "real name must exist");
  140 + return userService.saveTenantAdmin(
  141 + userDTO, getCurrentUser().isSysadmin(), getCurrentUser().getCurrentTenantId());
  142 + }
  143 +
  144 + @DeleteMapping
  145 + public void deleteUser(@Validated({DeleteGroup.class}) @RequestBody DeleteDTO deleteDTO)
  146 + throws ThingsboardException {
  147 + userService.deleteUser(
  148 + deleteDTO.getIds(), getCurrentUser().isSysadmin(), getCurrentUser().getCurrentTenantId());
  149 + }
  150 +
  151 + @RequestMapping(
  152 + value = "/{userId}/activationLink",
  153 + method = RequestMethod.GET,
  154 + produces = "text/plain")
  155 + public String getActivationLink(
  156 + @PathVariable("userId") String strUserId, HttpServletRequest request) {
  157 +
  158 + return null;
  159 + }
  160 +
  161 + @GetMapping("getGroupUserByGroupId/{groupId}")
  162 + public ResponseEntity<List<UserDTO>> getGroupUserByGroupId(
  163 + @PathVariable("groupId") String groupId) throws ThingsboardException {
  164 + return ResponseEntity.of(
  165 + userService.getOrganizationUserByOrganizationId(
  166 + groupId, getCurrentUser().getCurrentTenantId()));
  167 + }
  168 +
  169 + @Demo("这是一个演示的请求,查询当前用户,并将其导出到excel,参照完毕请务必删除")
  170 + @GetMapping("export")
  171 + public void export(HttpServletResponse response) throws IOException, ThingsboardException {
  172 + UserInfoDTO me =
  173 + userService.me(
  174 + getCurrentUser().getCurrentUserId(),
  175 + getCurrentUser().getCurrentTenantId(),
  176 + getCurrentUser().getRoles());
  177 + ExcelUtil.exportExcel(response, "用户信息", "user info", List.of(me), UserInfoDTO.class);
  178 + }
  179 +
  180 + @GetMapping("/accountExist/{username}")
  181 + public ResponseResult<UserDTO> accountExist(@PathVariable String username)
  182 + throws ThingsboardException {
  183 + return ResponseResult.success(
  184 + userService.accountExist(username, getCurrentUser().getCurrentTenantId()));
  185 + }
  186 +
  187 + @PostMapping("/relation")
  188 + public String[] getUserRoleOrGroup(
  189 + @Validated @RequestBody RoleOrOrganizationReqDTO roleOrGroupReqDTO) {
  190 + return userService.getUserRoleOrOrganization(roleOrGroupReqDTO);
  191 + }
  192 +
  193 + @PostMapping("/reset")
  194 + @ApiOperation(value = "修改密码")
  195 + public ResponseResult<Boolean> changePassword(@RequestBody AccountReqDTO accountReqDTO) {
  196 + return ResponseResult.success(userService.changePassword(accountReqDTO));
  197 + }
  198 +}
@@ -20,13 +20,16 @@ import org.springframework.security.authentication.AuthenticationProvider; @@ -20,13 +20,16 @@ import org.springframework.security.authentication.AuthenticationProvider;
20 import org.springframework.security.core.Authentication; 20 import org.springframework.security.core.Authentication;
21 import org.springframework.security.core.AuthenticationException; 21 import org.springframework.security.core.AuthenticationException;
22 import org.springframework.stereotype.Component; 22 import org.springframework.stereotype.Component;
23 -import org.thingsboard.server.service.security.auth.TokenOutdatingService;  
24 import org.thingsboard.server.service.security.auth.JwtAuthenticationToken; 23 import org.thingsboard.server.service.security.auth.JwtAuthenticationToken;
  24 +import org.thingsboard.server.service.security.auth.TokenOutdatingService;
25 import org.thingsboard.server.service.security.exception.JwtExpiredTokenException; 25 import org.thingsboard.server.service.security.exception.JwtExpiredTokenException;
26 import org.thingsboard.server.service.security.model.SecurityUser; 26 import org.thingsboard.server.service.security.model.SecurityUser;
27 import org.thingsboard.server.service.security.model.token.JwtTokenFactory; 27 import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
28 import org.thingsboard.server.service.security.model.token.RawAccessJwtToken; 28 import org.thingsboard.server.service.security.model.token.RawAccessJwtToken;
29 29
  30 +/**
  31 + * Jwt身份提供者
  32 + */
30 @Component 33 @Component
31 @RequiredArgsConstructor 34 @RequiredArgsConstructor
32 public class JwtAuthenticationProvider implements AuthenticationProvider { 35 public class JwtAuthenticationProvider implements AuthenticationProvider {
@@ -34,11 +37,18 @@ public class JwtAuthenticationProvider implements AuthenticationProvider { @@ -34,11 +37,18 @@ public class JwtAuthenticationProvider implements AuthenticationProvider {
34 private final JwtTokenFactory tokenFactory; 37 private final JwtTokenFactory tokenFactory;
35 private final TokenOutdatingService tokenOutdatingService; 38 private final TokenOutdatingService tokenOutdatingService;
36 39
  40 + /**
  41 + * 进行身份鉴定
  42 + * @param authentication 证明
  43 + * @return 证明
  44 + * @throws AuthenticationException 身份验证异常
  45 + */
37 @Override 46 @Override
38 public Authentication authenticate(Authentication authentication) throws AuthenticationException { 47 public Authentication authenticate(Authentication authentication) throws AuthenticationException {
39 RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials(); 48 RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials();
40 SecurityUser securityUser = tokenFactory.parseAccessJwtToken(rawAccessToken); 49 SecurityUser securityUser = tokenFactory.parseAccessJwtToken(rawAccessToken);
41 50
  51 + //token失效了 过时了
42 if (tokenOutdatingService.isOutdated(rawAccessToken, securityUser.getId())) { 52 if (tokenOutdatingService.isOutdated(rawAccessToken, securityUser.getId())) {
43 throw new JwtExpiredTokenException("Token is outdated"); 53 throw new JwtExpiredTokenException("Token is outdated");
44 } 54 }
@@ -33,15 +33,15 @@ import org.thingsboard.server.common.data.id.EntityId; @@ -33,15 +33,15 @@ import org.thingsboard.server.common.data.id.EntityId;
33 import org.thingsboard.server.common.data.id.TenantId; 33 import org.thingsboard.server.common.data.id.TenantId;
34 import org.thingsboard.server.common.data.id.UserId; 34 import org.thingsboard.server.common.data.id.UserId;
35 import org.thingsboard.server.common.data.security.Authority; 35 import org.thingsboard.server.common.data.security.Authority;
36 -import org.thingsboard.server.service.security.auth.TokenOutdatingService;  
37 -import org.thingsboard.server.common.data.security.UserCredentials;  
38 -import org.thingsboard.server.dao.customer.CustomerService;  
39 -import org.thingsboard.server.dao.user.UserService;  
40 import org.thingsboard.server.service.security.auth.RefreshAuthenticationToken; 36 import org.thingsboard.server.service.security.auth.RefreshAuthenticationToken;
  37 +import org.thingsboard.server.service.security.auth.TokenOutdatingService;
41 import org.thingsboard.server.service.security.model.SecurityUser; 38 import org.thingsboard.server.service.security.model.SecurityUser;
42 import org.thingsboard.server.service.security.model.UserPrincipal; 39 import org.thingsboard.server.service.security.model.UserPrincipal;
43 import org.thingsboard.server.service.security.model.token.JwtTokenFactory; 40 import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
44 import org.thingsboard.server.service.security.model.token.RawAccessJwtToken; 41 import org.thingsboard.server.service.security.model.token.RawAccessJwtToken;
  42 +import org.thingsboard.server.common.data.security.UserCredentials;
  43 +import org.thingsboard.server.dao.customer.CustomerService;
  44 +import org.thingsboard.server.dao.user.UserService;
45 45
46 import java.util.UUID; 46 import java.util.UUID;
47 47
@@ -17,6 +17,14 @@ package org.thingsboard.server.service.security.auth.jwt.extractor; @@ -17,6 +17,14 @@ package org.thingsboard.server.service.security.auth.jwt.extractor;
17 17
18 import javax.servlet.http.HttpServletRequest; 18 import javax.servlet.http.HttpServletRequest;
19 19
  20 +/**
  21 + * 令牌器接口
  22 + */
20 public interface TokenExtractor { 23 public interface TokenExtractor {
  24 + /**
  25 + * 提取令牌
  26 + * @param request 请求
  27 + * @return 令牌
  28 + */
21 public String extract(HttpServletRequest request); 29 public String extract(HttpServletRequest request);
22 } 30 }
@@ -16,7 +16,6 @@ @@ -16,7 +16,6 @@
16 package org.thingsboard.server.service.security.auth.oauth2; 16 package org.thingsboard.server.service.security.auth.oauth2;
17 17
18 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
19 -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;  
20 import org.springframework.security.core.AuthenticationException; 19 import org.springframework.security.core.AuthenticationException;
21 import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; 20 import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
22 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; 21 import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
@@ -26,7 +25,6 @@ import org.thingsboard.server.common.data.id.CustomerId; @@ -26,7 +25,6 @@ import org.thingsboard.server.common.data.id.CustomerId;
26 import org.thingsboard.server.common.data.id.EntityId; 25 import org.thingsboard.server.common.data.id.EntityId;
27 import org.thingsboard.server.common.data.id.TenantId; 26 import org.thingsboard.server.common.data.id.TenantId;
28 import org.thingsboard.server.service.security.system.SystemSecurityService; 27 import org.thingsboard.server.service.security.system.SystemSecurityService;
29 -import org.thingsboard.server.utils.MiscUtils;  
30 28
31 import javax.servlet.ServletException; 29 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServletRequest; 30 import javax.servlet.http.HttpServletRequest;
@@ -31,10 +31,10 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -31,10 +31,10 @@ import org.thingsboard.server.common.data.id.TenantId;
31 import org.thingsboard.server.common.data.oauth2.OAuth2Registration; 31 import org.thingsboard.server.common.data.oauth2.OAuth2Registration;
32 import org.thingsboard.server.common.data.security.model.JwtToken; 32 import org.thingsboard.server.common.data.security.model.JwtToken;
33 import org.thingsboard.server.dao.oauth2.OAuth2Service; 33 import org.thingsboard.server.dao.oauth2.OAuth2Service;
  34 +import org.thingsboard.server.service.security.system.SystemSecurityService;
34 import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; 35 import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
35 import org.thingsboard.server.service.security.model.SecurityUser; 36 import org.thingsboard.server.service.security.model.SecurityUser;
36 import org.thingsboard.server.service.security.model.token.JwtTokenFactory; 37 import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
37 -import org.thingsboard.server.service.security.system.SystemSecurityService;  
38 38
39 import javax.servlet.http.HttpServletRequest; 39 import javax.servlet.http.HttpServletRequest;
40 import javax.servlet.http.HttpServletResponse; 40 import javax.servlet.http.HttpServletResponse;
1 /** 1 /**
2 * Copyright © 2016-2021 The Thingsboard Authors 2 * Copyright © 2016-2021 The Thingsboard Authors
3 * 3 *
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at 4 + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5 + * except in compliance with the License. You may obtain a copy of the License at
7 * 6 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 7 + * <p>http://www.apache.org/licenses/LICENSE-2.0
9 * 8 *
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and 9 + * <p>Unless required by applicable law or agreed to in writing, software distributed under the
  10 + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  11 + * express or implied. See the License for the specific language governing permissions and
14 * limitations under the License. 12 * limitations under the License.
15 */ 13 */
16 package org.thingsboard.server.service.security.auth.rest; 14 package org.thingsboard.server.service.security.auth.rest;
17 15
18 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
19 import org.springframework.beans.factory.annotation.Autowired; 17 import org.springframework.beans.factory.annotation.Autowired;
20 -import org.springframework.security.authentication.AuthenticationProvider;  
21 -import org.springframework.security.authentication.BadCredentialsException;  
22 -import org.springframework.security.authentication.InsufficientAuthenticationException;  
23 -import org.springframework.security.authentication.LockedException;  
24 -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 18 +import org.springframework.security.authentication.*;
25 import org.springframework.security.core.Authentication; 19 import org.springframework.security.core.Authentication;
26 import org.springframework.security.core.AuthenticationException; 20 import org.springframework.security.core.AuthenticationException;
27 import org.springframework.security.core.userdetails.UsernameNotFoundException; 21 import org.springframework.security.core.userdetails.UsernameNotFoundException;
  22 +import org.springframework.security.crypto.password.PasswordEncoder;
28 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
29 import org.springframework.util.Assert; 24 import org.springframework.util.Assert;
30 import org.thingsboard.server.common.data.Customer; 25 import org.thingsboard.server.common.data.Customer;
@@ -36,167 +31,331 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -36,167 +31,331 @@ import org.thingsboard.server.common.data.id.TenantId;
36 import org.thingsboard.server.common.data.id.UserId; 31 import org.thingsboard.server.common.data.id.UserId;
37 import org.thingsboard.server.common.data.security.Authority; 32 import org.thingsboard.server.common.data.security.Authority;
38 import org.thingsboard.server.common.data.security.UserCredentials; 33 import org.thingsboard.server.common.data.security.UserCredentials;
  34 +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
  35 +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils;
  36 +import org.thingsboard.server.common.data.yunteng.dto.UserDetailsDTO;
  37 +import org.thingsboard.server.common.data.yunteng.dto.request.CodeTTL;
  38 +import org.thingsboard.server.common.data.yunteng.enums.MessageTypeEnum;
  39 +import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum;
39 import org.thingsboard.server.dao.audit.AuditLogService; 40 import org.thingsboard.server.dao.audit.AuditLogService;
40 import org.thingsboard.server.dao.customer.CustomerService; 41 import org.thingsboard.server.dao.customer.CustomerService;
41 -import org.thingsboard.server.dao.user.UserService;  
42 import org.thingsboard.server.service.security.model.SecurityUser; 42 import org.thingsboard.server.service.security.model.SecurityUser;
43 import org.thingsboard.server.service.security.model.UserPrincipal; 43 import org.thingsboard.server.service.security.model.UserPrincipal;
44 import org.thingsboard.server.service.security.system.SystemSecurityService; 44 import org.thingsboard.server.service.security.system.SystemSecurityService;
  45 +import org.thingsboard.server.dao.user.UserService;
  46 +import org.thingsboard.server.dao.yunteng.service.YtUserService;
45 import ua_parser.Client; 47 import ua_parser.Client;
46 48
  49 +import java.time.LocalDateTime;
  50 +import java.util.List;
  51 +import java.util.Objects;
  52 +import java.util.Optional;
47 import java.util.UUID; 53 import java.util.UUID;
48 54
  55 +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.CacheConfigKey.MOBILE_LOGIN_SMS_CODE;
  56 +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.DEFAULT_DELIMITER;
49 57
50 @Component 58 @Component
51 @Slf4j 59 @Slf4j
52 public class RestAuthenticationProvider implements AuthenticationProvider { 60 public class RestAuthenticationProvider implements AuthenticationProvider {
53 61
54 - private final SystemSecurityService systemSecurityService;  
55 - private final UserService userService;  
56 - private final CustomerService customerService;  
57 - private final AuditLogService auditLogService;  
58 -  
59 - @Autowired  
60 - public RestAuthenticationProvider(final UserService userService,  
61 - final CustomerService customerService,  
62 - final SystemSecurityService systemSecurityService,  
63 - final AuditLogService auditLogService) {  
64 - this.userService = userService;  
65 - this.customerService = customerService;  
66 - this.systemSecurityService = systemSecurityService;  
67 - this.auditLogService = auditLogService;  
68 - }  
69 -  
70 - @Override  
71 - public Authentication authenticate(Authentication authentication) throws AuthenticationException {  
72 - Assert.notNull(authentication, "No authentication data provided");  
73 -  
74 - Object principal = authentication.getPrincipal();  
75 - if (!(principal instanceof UserPrincipal)) {  
76 - throw new BadCredentialsException("Authentication Failed. Bad user principal.");  
77 - } 62 + private final SystemSecurityService systemSecurityService;
  63 + private final UserService userService;
  64 + private final CustomerService customerService;
  65 + private final AuditLogService auditLogService;
78 66
79 - UserPrincipal userPrincipal = (UserPrincipal) principal;  
80 - if (userPrincipal.getType() == UserPrincipal.Type.USER_NAME) {  
81 - String username = userPrincipal.getValue();  
82 - String password = (String) authentication.getCredentials();  
83 - return authenticateByUsernameAndPassword(authentication, userPrincipal, username, password);  
84 - } else {  
85 - String publicId = userPrincipal.getValue();  
86 - return authenticateByPublicId(userPrincipal, publicId);  
87 - } 67 + @Autowired
  68 + public RestAuthenticationProvider(
  69 + final UserService userService,
  70 + final CustomerService customerService,
  71 + final SystemSecurityService systemSecurityService,
  72 + final AuditLogService auditLogService) {
  73 + this.userService = userService;
  74 + this.customerService = customerService;
  75 + this.systemSecurityService = systemSecurityService;
  76 + this.auditLogService = auditLogService;
  77 + }
  78 +
  79 + @Override
  80 + public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  81 + Assert.notNull(authentication, "No authentication data provided");
  82 +
  83 + Object principal = authentication.getPrincipal();
  84 + if (!(principal instanceof UserPrincipal)) {
  85 + throw new BadCredentialsException("Authentication Failed. Bad user principal.");
88 } 86 }
89 87
90 - private Authentication authenticateByUsernameAndPassword(Authentication authentication, UserPrincipal userPrincipal, String username, String password) {  
91 - User user = userService.findUserByEmail(TenantId.SYS_TENANT_ID, username);  
92 - if (user == null) {  
93 - throw new UsernameNotFoundException("User not found: " + username);  
94 - } 88 + UserPrincipal userPrincipal = (UserPrincipal) principal;
  89 + if (userPrincipal.getType() == UserPrincipal.Type.USER_NAME) {
  90 + String username = userPrincipal.getValue();
  91 + String password = (String) authentication.getCredentials();
  92 + String ytUserName = username;
  93 + UserDetailsDTO ytDetailDTO = new UserDetailsDTO();
  94 + if (!FastIotConstants.EMAIL_PATTERN.matcher(username).matches()) {
  95 + username += FastIotConstants.DEFAULT_EMAIL_SUFFIX_FOR_TB;
  96 + ytDetailDTO = ytUserDetailsByUserName(ytUserName, password).get();
  97 + }
  98 + return authenticateByUsernameAndPassword(
  99 + ytDetailDTO, authentication, userPrincipal, username, password);
  100 + } else if (userPrincipal.getType() == UserPrincipal.Type.SMS_CODE) {
  101 + return ytUserDetailsByPhone(
  102 + authentication,
  103 + userPrincipal,
  104 + userPrincipal.getValue(),
  105 + (String) authentication.getCredentials());
  106 + } else {
  107 + String publicId = userPrincipal.getValue();
  108 + return authenticateByPublicId(userPrincipal, publicId);
  109 + }
  110 + }
95 111
96 - try { 112 + private Authentication authenticateByUsernameAndPassword(
  113 + UserDetailsDTO ytDetailDTO,
  114 + Authentication authentication,
  115 + UserPrincipal userPrincipal,
  116 + String username,
  117 + String password) {
97 118
98 - UserCredentials userCredentials = userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, user.getId());  
99 - if (userCredentials == null) {  
100 - throw new UsernameNotFoundException("User credentials not found");  
101 - } 119 + // TODO 先验证sys_user账号密码是否正确,正确后,在账号后面加上后缀验证TB用户是否正确
  120 + Object principal = authentication.getPrincipal();
  121 + if (!(principal instanceof UserPrincipal)) {
  122 + throw new BadCredentialsException("Authentication Failed. Bad user principal.");
  123 + }
102 124
103 - try {  
104 - systemSecurityService.validateUserCredentials(user.getTenantId(), userCredentials, username, password);  
105 - } catch (LockedException e) {  
106 - logLoginAction(user, authentication, ActionType.LOCKOUT, null);  
107 - throw e;  
108 - } 125 + User user = userService.findUserByEmail(TenantId.SYS_TENANT_ID, username);
  126 + if (user == null) {
  127 + throw new UsernameNotFoundException("User not found: " + username);
  128 + }
109 129
110 - if (user.getAuthority() == null)  
111 - throw new InsufficientAuthenticationException("User has no authority assigned"); 130 + try {
112 131
113 - SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), userPrincipal);  
114 - logLoginAction(user, authentication, ActionType.LOGIN, null);  
115 - return new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities());  
116 - } catch (Exception e) {  
117 - logLoginAction(user, authentication, ActionType.LOGIN, e);  
118 - throw e;  
119 - } 132 + UserCredentials userCredentials =
  133 + userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, user.getId());
  134 + if (userCredentials == null) {
  135 + throw new UsernameNotFoundException("User credentials not found");
  136 + }
  137 +
  138 + try {
  139 + systemSecurityService.validateUserCredentials(
  140 + user.getTenantId(), userCredentials, username, password);
  141 + } catch (LockedException e) {
  142 + logLoginAction(user, authentication, ActionType.LOCKOUT, null);
  143 + throw e;
  144 + }
  145 +
  146 + if (user.getAuthority() == null)
  147 + throw new InsufficientAuthenticationException("User has no authority assigned");
  148 +
  149 + user.setUserDetailsDTO(ytDetailDTO);
  150 + SecurityUser securityUser =
  151 + new SecurityUser(user, userCredentials.isEnabled(), userPrincipal);
  152 + logLoginAction(user, authentication, ActionType.LOGIN, null);
  153 + return new UsernamePasswordAuthenticationToken(
  154 + securityUser, null, securityUser.getAuthorities());
  155 + } catch (Exception e) {
  156 + logLoginAction(user, authentication, ActionType.LOGIN, e);
  157 + throw e;
120 } 158 }
  159 + }
121 160
122 - private Authentication authenticateByPublicId(UserPrincipal userPrincipal, String publicId) {  
123 - CustomerId customerId;  
124 - try {  
125 - customerId = new CustomerId(UUID.fromString(publicId));  
126 - } catch (Exception e) {  
127 - throw new BadCredentialsException("Authentication Failed. Public Id is not valid.");  
128 - }  
129 - Customer publicCustomer = customerService.findCustomerById(TenantId.SYS_TENANT_ID, customerId);  
130 - if (publicCustomer == null) {  
131 - throw new UsernameNotFoundException("Public entity not found: " + publicId);  
132 - }  
133 - if (!publicCustomer.isPublic()) {  
134 - throw new BadCredentialsException("Authentication Failed. Public Id is not valid.");  
135 - }  
136 - User user = new User(new UserId(EntityId.NULL_UUID));  
137 - user.setTenantId(publicCustomer.getTenantId());  
138 - user.setCustomerId(publicCustomer.getId());  
139 - user.setEmail(publicId);  
140 - user.setAuthority(Authority.CUSTOMER_USER);  
141 - user.setFirstName("Public");  
142 - user.setLastName("Public");  
143 -  
144 - SecurityUser securityUser = new SecurityUser(user, true, userPrincipal);  
145 -  
146 - return new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities());  
147 - }  
148 -  
149 - @Override  
150 - public boolean supports(Class<?> authentication) {  
151 - return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));  
152 - }  
153 -  
154 - private void logLoginAction(User user, Authentication authentication, ActionType actionType, Exception e) {  
155 - String clientAddress = "Unknown";  
156 - String browser = "Unknown";  
157 - String os = "Unknown";  
158 - String device = "Unknown";  
159 - if (authentication != null && authentication.getDetails() != null) {  
160 - if (authentication.getDetails() instanceof RestAuthenticationDetails) {  
161 - RestAuthenticationDetails details = (RestAuthenticationDetails)authentication.getDetails();  
162 - clientAddress = details.getClientAddress();  
163 - if (details.getUserAgent() != null) {  
164 - Client userAgent = details.getUserAgent();  
165 - if (userAgent.userAgent != null) {  
166 - browser = userAgent.userAgent.family;  
167 - if (userAgent.userAgent.major != null) {  
168 - browser += " " + userAgent.userAgent.major;  
169 - if (userAgent.userAgent.minor != null) {  
170 - browser += "." + userAgent.userAgent.minor;  
171 - if (userAgent.userAgent.patch != null) {  
172 - browser += "." + userAgent.userAgent.patch;  
173 - }  
174 - }  
175 - }  
176 - }  
177 - if (userAgent.os != null) {  
178 - os = userAgent.os.family;  
179 - if (userAgent.os.major != null) {  
180 - os += " " + userAgent.os.major;  
181 - if (userAgent.os.minor != null) {  
182 - os += "." + userAgent.os.minor;  
183 - if (userAgent.os.patch != null) {  
184 - os += "." + userAgent.os.patch;  
185 - if (userAgent.os.patchMinor != null) {  
186 - os += "." + userAgent.os.patchMinor;  
187 - }  
188 - }  
189 - }  
190 - }  
191 - }  
192 - if (userAgent.device != null) {  
193 - device = userAgent.device.family;  
194 - } 161 + private Authentication authenticateByPublicId(UserPrincipal userPrincipal, String publicId) {
  162 + CustomerId customerId;
  163 + try {
  164 + customerId = new CustomerId(UUID.fromString(publicId));
  165 + } catch (Exception e) {
  166 + throw new BadCredentialsException("Authentication Failed. Public Id is not valid.");
  167 + }
  168 + Customer publicCustomer = customerService.findCustomerById(TenantId.SYS_TENANT_ID, customerId);
  169 + if (publicCustomer == null) {
  170 + throw new UsernameNotFoundException("Public entity not found: " + publicId);
  171 + }
  172 + if (!publicCustomer.isPublic()) {
  173 + throw new BadCredentialsException("Authentication Failed. Public Id is not valid.");
  174 + }
  175 + User user = new User(new UserId(EntityId.NULL_UUID));
  176 + user.setTenantId(publicCustomer.getTenantId());
  177 + user.setCustomerId(publicCustomer.getId());
  178 + user.setEmail(publicId);
  179 + user.setAuthority(Authority.CUSTOMER_USER);
  180 + user.setFirstName("Public");
  181 + user.setLastName("Public");
  182 +
  183 + SecurityUser securityUser = new SecurityUser(user, true, userPrincipal);
  184 +
  185 + return new UsernamePasswordAuthenticationToken(
  186 + securityUser, null, securityUser.getAuthorities());
  187 + }
  188 +
  189 + @Override
  190 + public boolean supports(Class<?> authentication) {
  191 + return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
  192 + }
  193 +
  194 + private void logLoginAction(
  195 + User user, Authentication authentication, ActionType actionType, Exception e) {
  196 + String clientAddress = "Unknown";
  197 + String browser = "Unknown";
  198 + String os = "Unknown";
  199 + String device = "Unknown";
  200 + if (authentication != null && authentication.getDetails() != null) {
  201 + if (authentication.getDetails() instanceof RestAuthenticationDetails) {
  202 + RestAuthenticationDetails details = (RestAuthenticationDetails) authentication.getDetails();
  203 + clientAddress = details.getClientAddress();
  204 + if (details.getUserAgent() != null) {
  205 + Client userAgent = details.getUserAgent();
  206 + if (userAgent.userAgent != null) {
  207 + browser = userAgent.userAgent.family;
  208 + if (userAgent.userAgent.major != null) {
  209 + browser += " " + userAgent.userAgent.major;
  210 + if (userAgent.userAgent.minor != null) {
  211 + browser += "." + userAgent.userAgent.minor;
  212 + if (userAgent.userAgent.patch != null) {
  213 + browser += "." + userAgent.userAgent.patch;
  214 + }
  215 + }
  216 + }
  217 + }
  218 + if (userAgent.os != null) {
  219 + os = userAgent.os.family;
  220 + if (userAgent.os.major != null) {
  221 + os += " " + userAgent.os.major;
  222 + if (userAgent.os.minor != null) {
  223 + os += "." + userAgent.os.minor;
  224 + if (userAgent.os.patch != null) {
  225 + os += "." + userAgent.os.patch;
  226 + if (userAgent.os.patchMinor != null) {
  227 + os += "." + userAgent.os.patchMinor;
  228 + }
195 } 229 }
  230 + }
196 } 231 }
  232 + }
  233 + if (userAgent.device != null) {
  234 + device = userAgent.device.family;
  235 + }
197 } 236 }
198 - auditLogService.logEntityAction(  
199 - user.getTenantId(), user.getCustomerId(), user.getId(),  
200 - user.getName(), user.getId(), null, actionType, e, clientAddress, browser, os, device); 237 + }
  238 + }
  239 + auditLogService.logEntityAction(
  240 + user.getTenantId(),
  241 + user.getCustomerId(),
  242 + user.getId(),
  243 + user.getName(),
  244 + user.getId(),
  245 + null,
  246 + actionType,
  247 + e,
  248 + clientAddress,
  249 + browser,
  250 + os,
  251 + device);
  252 + }
  253 +
  254 + @Autowired private YtUserService ytUserService;
  255 + @Autowired private CacheUtils cacheUtils;
  256 + @Autowired private PasswordEncoder passwordEncoder;
  257 +
  258 + private Optional<UserDetailsDTO> ytUserDetailsByUserName(String username, String password) {
  259 + List<UserDetailsDTO> users = ytUserService.findUserDetailsByUsername(username);
  260 +
  261 + if (users.isEmpty()) {
  262 + throw new UsernameNotFoundException("User not found: " + username);
  263 + }
  264 + Optional<UserDetailsDTO> optionalUser =
  265 + users.stream()
  266 + .filter(user -> passwordEncoder.matches(password, user.getPassword()))
  267 + .findAny();
  268 + if (optionalUser.isEmpty()) {
  269 + throw new BadCredentialsException("Authentication Failed. Username or Password not valid.");
  270 + }
  271 + if (doValidate(optionalUser)) {
  272 + return optionalUser;
  273 + }
  274 + return Optional.empty();
  275 + }
  276 +
  277 + private Authentication ytUserDetailsByPhone(
  278 + Authentication authentication, UserPrincipal userPrincipal, String phoneNumber, String code) {
  279 + List<UserDetailsDTO> users = ytUserService.getUserByPhoneNumber(phoneNumber);
  280 + if (users.isEmpty()) {
  281 + throw new UsernameNotFoundException("phone number not found: " + phoneNumber);
  282 + }
  283 + String key =
  284 + MsgTemplatePurposeEnum.FOR_LOGIN.name()
  285 + + DEFAULT_DELIMITER
  286 + + MessageTypeEnum.PHONE_MESSAGE.name()
  287 + + DEFAULT_DELIMITER
  288 + + phoneNumber;
  289 +
  290 + boolean correct =
  291 + cacheUtils
  292 + .get(MOBILE_LOGIN_SMS_CODE, key)
  293 + .map(
  294 + o -> {
  295 + CodeTTL codeTTL = (CodeTTL) o;
  296 + if (System.currentTimeMillis() - codeTTL.getSendTs() < 5 * 60 * 1000) {
  297 + return Objects.equals(codeTTL.getCode(), code);
  298 + } else {
  299 + return false;
  300 + }
  301 + })
  302 + .orElse(false);
  303 + Optional<UserDetailsDTO> optionalUser;
  304 + if (!correct) {
  305 + optionalUser = Optional.empty();
  306 + } else {
  307 + optionalUser = Optional.of(users.get(0));
  308 + }
  309 + if (optionalUser.isEmpty()) {
  310 + throw new BadCredentialsException("验证码不正确");
  311 + }
  312 +
  313 + String tbEmail =
  314 + optionalUser.get().getUsername() + FastIotConstants.DEFAULT_EMAIL_SUFFIX_FOR_TB;
  315 + User user = userService.findUserByEmail(TenantId.SYS_TENANT_ID, tbEmail);
  316 + if (user == null) {
  317 + throw new UsernameNotFoundException("User not found: " + tbEmail);
  318 + }
  319 +
  320 + try {
  321 + if (user.getAuthority() == null)
  322 + throw new InsufficientAuthenticationException("User has no authority assigned");
  323 +
  324 + user.setUserDetailsDTO(optionalUser.get());
  325 + SecurityUser securityUser = new SecurityUser(user, true, userPrincipal);
  326 + logLoginAction(user, authentication, ActionType.LOGIN, null);
  327 + return new UsernamePasswordAuthenticationToken(
  328 + securityUser, null, securityUser.getAuthorities());
  329 + } catch (Exception e) {
  330 + logLoginAction(user, authentication, ActionType.LOGIN, e);
  331 + throw e;
  332 + }
  333 + }
  334 +
  335 + private boolean doValidate(Optional<UserDetailsDTO> optionalUser) {
  336 + UserDetailsDTO detailsDTO = optionalUser.get();
  337 + boolean tenantEnabled = detailsDTO.getTenant().isEnabled();
  338 + if (!tenantEnabled) {
  339 + throw new LockedException("tenant has been disabled");
  340 + }
  341 + Optional.ofNullable(detailsDTO.getTenant().getTenantExpireTime())
  342 + .ifPresent(
  343 + expireTime -> {
  344 + if (LocalDateTime.now().isAfter(expireTime)) {
  345 + throw new AccountExpiredException("tenant has expired");
  346 + }
  347 + });
  348 + Optional.ofNullable(detailsDTO.getAccountExpireTime())
  349 + .ifPresent(
  350 + expireTime -> {
  351 + if (LocalDateTime.now().isAfter(expireTime)) {
  352 + throw new AccountExpiredException("user account has expired");
  353 + }
  354 + });
  355 + boolean enabled = detailsDTO.isEnabled();
  356 + if (!enabled) {
  357 + throw new LockedException("account has been disabled");
201 } 358 }
  359 + return true;
  360 + }
202 } 361 }
@@ -24,9 +24,9 @@ import org.springframework.security.web.WebAttributes; @@ -24,9 +24,9 @@ import org.springframework.security.web.WebAttributes;
24 import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 24 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
25 import org.springframework.stereotype.Component; 25 import org.springframework.stereotype.Component;
26 import org.thingsboard.server.common.data.security.model.JwtToken; 26 import org.thingsboard.server.common.data.security.model.JwtToken;
27 -import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;  
28 import org.thingsboard.server.service.security.model.SecurityUser; 27 import org.thingsboard.server.service.security.model.SecurityUser;
29 import org.thingsboard.server.service.security.model.token.JwtTokenFactory; 28 import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
  29 +import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
30 30
31 import javax.servlet.ServletException; 31 import javax.servlet.ServletException;
32 import javax.servlet.http.HttpServletRequest; 32 import javax.servlet.http.HttpServletRequest;
@@ -28,7 +28,6 @@ import org.springframework.security.core.context.SecurityContextHolder; @@ -28,7 +28,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
28 import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; 28 import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
29 import org.springframework.security.web.authentication.AuthenticationFailureHandler; 29 import org.springframework.security.web.authentication.AuthenticationFailureHandler;
30 import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 30 import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
31 -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;  
32 import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; 31 import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException;
33 import org.thingsboard.server.service.security.model.UserPrincipal; 32 import org.thingsboard.server.service.security.model.UserPrincipal;
34 33
1 /** 1 /**
2 * Copyright © 2016-2021 The Thingsboard Authors 2 * Copyright © 2016-2021 The Thingsboard Authors
3 * 3 *
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at 4 + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5 + * except in compliance with the License. You may obtain a copy of the License at
7 * 6 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 7 + * <p>http://www.apache.org/licenses/LICENSE-2.0
9 * 8 *
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and 9 + * <p>Unless required by applicable law or agreed to in writing, software distributed under the
  10 + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  11 + * express or implied. See the License for the specific language governing permissions and
14 * limitations under the License. 12 * limitations under the License.
15 */ 13 */
16 package org.thingsboard.server.service.security.model; 14 package org.thingsboard.server.service.security.model;
17 15
  16 +import lombok.Getter;
  17 +import lombok.Setter;
18 import org.springframework.security.core.GrantedAuthority; 18 import org.springframework.security.core.GrantedAuthority;
19 import org.springframework.security.core.authority.SimpleGrantedAuthority; 19 import org.springframework.security.core.authority.SimpleGrantedAuthority;
20 import org.thingsboard.server.common.data.User; 20 import org.thingsboard.server.common.data.User;
21 import org.thingsboard.server.common.data.id.UserId; 21 import org.thingsboard.server.common.data.id.UserId;
  22 +import org.thingsboard.server.common.data.yunteng.dto.UserDetailRoleDTO;
  23 +import org.thingsboard.server.common.data.yunteng.enums.RoleEnum;
22 24
  25 +import java.time.LocalDateTime;
23 import java.util.Collection; 26 import java.util.Collection;
  27 +import java.util.Optional;
  28 +import java.util.Set;
24 import java.util.stream.Collectors; 29 import java.util.stream.Collectors;
25 import java.util.stream.Stream; 30 import java.util.stream.Stream;
26 31
27 public class SecurityUser extends User { 32 public class SecurityUser extends User {
28 33
29 - private static final long serialVersionUID = -797397440703066079L; 34 + private static final long serialVersionUID = -797397440703066079L;
30 35
31 - private Collection<GrantedAuthority> authorities;  
32 - private boolean enabled;  
33 - private UserPrincipal userPrincipal; 36 + private Collection<GrantedAuthority> authorities;
  37 + private boolean enabled;
  38 + private UserPrincipal userPrincipal;
  39 + @Getter
  40 + private String currentTenantId;
  41 + @Getter
  42 + private String currentUserId;
  43 + @Getter @Setter private LocalDateTime userExpireTime;
  44 + @Getter @Setter private LocalDateTime tenantExpireTime;
  45 + @Getter @Setter private boolean sysadmin = false;
  46 + @Getter @Setter private boolean tenantAdmin = false;
  47 + @Getter @Setter private boolean platformAdmin = false;
  48 + @Getter @Setter private Set<String> roles;
34 49
35 - public SecurityUser() {  
36 - super();  
37 - } 50 + public SecurityUser() {
  51 + super();
  52 + }
38 53
39 - public SecurityUser(UserId id) {  
40 - super(id);  
41 - } 54 + public SecurityUser(UserId id) {
  55 + super(id);
  56 + }
42 57
43 - public SecurityUser(User user, boolean enabled, UserPrincipal userPrincipal) {  
44 - super(user);  
45 - this.enabled = enabled;  
46 - this.userPrincipal = userPrincipal;  
47 - } 58 + public SecurityUser(User user, boolean enabled, UserPrincipal userPrincipal) {
  59 + super(user);
  60 + this.enabled = enabled;
  61 + this.userPrincipal = userPrincipal;
  62 + this.currentTenantId = user.getTenantId().getId().toString();
  63 + this.currentUserId = user.getUserDetailsDTO().getId();
  64 + Optional.ofNullable(user.getUserDetailsDTO().getRoles()).map(roleDTOS -> {
  65 + this.roles =
  66 + roleDTOS.stream()
  67 + .map(UserDetailRoleDTO::getRoleType)
  68 + .map(RoleEnum::name)
  69 + .collect(Collectors.toSet());
  70 + this.sysadmin =
  71 + this.roles.stream().anyMatch(role -> role.equals(RoleEnum.ROLE_SYS_ADMIN.name()));
  72 + this.tenantAdmin =
  73 + this.roles.stream().anyMatch(role -> role.equals(RoleEnum.ROLE_TENANT_ADMIN.name()));
  74 + this.platformAdmin =
  75 + this.roles.stream().anyMatch(role -> role.equals(RoleEnum.ROLE_PLATFORM_ADMIN.name()));
  76 + return roleDTOS;
  77 + });
48 78
49 - public Collection<GrantedAuthority> getAuthorities() {  
50 - if (authorities == null) {  
51 - authorities = Stream.of(SecurityUser.this.getAuthority())  
52 - .map(authority -> new SimpleGrantedAuthority(authority.name()))  
53 - .collect(Collectors.toList());  
54 - }  
55 - return authorities;  
56 - } 79 + }
57 80
58 - public boolean isEnabled() {  
59 - return enabled; 81 + public Collection<GrantedAuthority> getAuthorities() {
  82 + if (authorities == null) {
  83 + authorities =
  84 + Stream.of(SecurityUser.this.getAuthority())
  85 + .map(authority -> new SimpleGrantedAuthority(authority.name()))
  86 + .collect(Collectors.toList());
60 } 87 }
  88 + return authorities;
  89 + }
61 90
62 - public UserPrincipal getUserPrincipal() {  
63 - return userPrincipal;  
64 - } 91 + public boolean isEnabled() {
  92 + return enabled;
  93 + }
65 94
66 - public void setEnabled(boolean enabled) {  
67 - this.enabled = enabled;  
68 - } 95 + public UserPrincipal getUserPrincipal() {
  96 + return userPrincipal;
  97 + }
69 98
70 - public void setUserPrincipal(UserPrincipal userPrincipal) {  
71 - this.userPrincipal = userPrincipal;  
72 - } 99 + public void setEnabled(boolean enabled) {
  100 + this.enabled = enabled;
  101 + }
73 102
  103 + public void setUserPrincipal(UserPrincipal userPrincipal) {
  104 + this.userPrincipal = userPrincipal;
  105 + }
74 } 106 }
@@ -37,7 +37,8 @@ public class UserPrincipal implements Serializable { @@ -37,7 +37,8 @@ public class UserPrincipal implements Serializable {
37 37
38 public enum Type { 38 public enum Type {
39 USER_NAME, 39 USER_NAME,
40 - PUBLIC_ID 40 + PUBLIC_ID,
  41 + SMS_CODE
41 } 42 }
42 43
43 } 44 }
@@ -15,10 +15,8 @@ @@ -15,10 +15,8 @@
15 */ 15 */
16 package org.thingsboard.server.service.security.permission; 16 package org.thingsboard.server.service.security.permission;
17 17
18 -import org.thingsboard.server.common.data.HasCustomerId;  
19 import org.thingsboard.server.common.data.HasTenantId; 18 import org.thingsboard.server.common.data.HasTenantId;
20 import org.thingsboard.server.common.data.id.EntityId; 19 import org.thingsboard.server.common.data.id.EntityId;
21 -import org.thingsboard.server.common.data.id.TenantId;  
22 import org.thingsboard.server.service.security.model.SecurityUser; 20 import org.thingsboard.server.service.security.model.SecurityUser;
23 21
24 import java.util.Arrays; 22 import java.util.Arrays;
@@ -22,7 +22,6 @@ import io.jsonwebtoken.Claims; @@ -22,7 +22,6 @@ import io.jsonwebtoken.Claims;
22 import io.jsonwebtoken.Header; 22 import io.jsonwebtoken.Header;
23 import io.jsonwebtoken.Jwt; 23 import io.jsonwebtoken.Jwt;
24 import io.jsonwebtoken.Jwts; 24 import io.jsonwebtoken.Jwts;
25 -import lombok.Getter;  
26 import lombok.extern.slf4j.Slf4j; 25 import lombok.extern.slf4j.Slf4j;
27 import org.apache.commons.lang3.RandomStringUtils; 26 import org.apache.commons.lang3.RandomStringUtils;
28 import org.apache.commons.lang3.StringUtils; 27 import org.apache.commons.lang3.StringUtils;
@@ -15,81 +15,27 @@ @@ -15,81 +15,27 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
18 -import com.fasterxml.jackson.core.type.TypeReference;  
19 -import com.fasterxml.jackson.databind.JsonNode;  
20 -import com.fasterxml.jackson.databind.ObjectMapper;  
21 -import io.jsonwebtoken.Claims;  
22 -import io.jsonwebtoken.Header;  
23 -import io.jsonwebtoken.Jwt;  
24 -import io.jsonwebtoken.Jwts;  
25 import lombok.extern.slf4j.Slf4j; 18 import lombok.extern.slf4j.Slf4j;
26 -import org.apache.commons.lang3.StringUtils;  
27 -import org.hamcrest.Matcher;  
28 -import org.junit.After;  
29 import org.junit.Assert; 19 import org.junit.Assert;
30 -import org.junit.Before;  
31 -import org.junit.Rule;  
32 -import org.junit.rules.TestRule;  
33 -import org.junit.rules.TestWatcher;  
34 -import org.junit.runner.Description;  
35 import org.junit.runner.RunWith; 20 import org.junit.runner.RunWith;
36 -import org.springframework.beans.factory.annotation.Autowired;  
37 import org.springframework.boot.test.context.SpringBootContextLoader; 21 import org.springframework.boot.test.context.SpringBootContextLoader;
38 import org.springframework.boot.test.context.SpringBootTest; 22 import org.springframework.boot.test.context.SpringBootTest;
39 import org.springframework.boot.web.server.LocalServerPort; 23 import org.springframework.boot.web.server.LocalServerPort;
40 import org.springframework.context.annotation.ComponentScan; 24 import org.springframework.context.annotation.ComponentScan;
41 import org.springframework.context.annotation.Configuration; 25 import org.springframework.context.annotation.Configuration;
42 -import org.springframework.http.HttpHeaders;  
43 -import org.springframework.http.MediaType;  
44 -import org.springframework.http.converter.HttpMessageConverter;  
45 -import org.springframework.http.converter.StringHttpMessageConverter;  
46 -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;  
47 -import org.springframework.mock.http.MockHttpInputMessage;  
48 -import org.springframework.mock.http.MockHttpOutputMessage;  
49 import org.springframework.test.annotation.DirtiesContext; 26 import org.springframework.test.annotation.DirtiesContext;
50 import org.springframework.test.context.ActiveProfiles; 27 import org.springframework.test.context.ActiveProfiles;
51 import org.springframework.test.context.ContextConfiguration; 28 import org.springframework.test.context.ContextConfiguration;
52 import org.springframework.test.context.junit4.SpringRunner; 29 import org.springframework.test.context.junit4.SpringRunner;
53 -import org.springframework.test.web.servlet.MockMvc;  
54 -import org.springframework.test.web.servlet.MvcResult;  
55 -import org.springframework.test.web.servlet.ResultActions;  
56 -import org.springframework.test.web.servlet.ResultMatcher;  
57 -import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;  
58 -import org.springframework.util.LinkedMultiValueMap;  
59 -import org.springframework.util.MultiValueMap;  
60 -import org.springframework.web.context.WebApplicationContext;  
61 -import org.thingsboard.server.common.data.BaseData;  
62 -import org.thingsboard.server.common.data.Customer;  
63 -import org.thingsboard.server.common.data.Tenant;  
64 -import org.thingsboard.server.common.data.User;  
65 -import org.thingsboard.server.common.data.id.TenantId;  
66 -import org.thingsboard.server.common.data.id.UUIDBased;  
67 -import org.thingsboard.server.common.data.page.PageLink;  
68 -import org.thingsboard.server.common.data.page.TimePageLink;  
69 -import org.thingsboard.server.common.data.security.Authority;  
70 -import org.thingsboard.server.config.ThingsboardSecurityConfiguration;  
71 -import org.thingsboard.server.service.mail.TestMailService;  
72 -import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRequest;  
73 -import org.thingsboard.server.service.security.auth.rest.LoginRequest;  
74 30
75 -import java.io.IOException;  
76 import java.net.URI; 31 import java.net.URI;
77 import java.net.URISyntaxException; 32 import java.net.URISyntaxException;
78 -import java.util.ArrayList;  
79 -import java.util.Arrays;  
80 -import java.util.Comparator;  
81 -import java.util.List;  
82 33
83 import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; 34 import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;
84 -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;  
85 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; 35 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
86 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 36 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
87 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 37 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
88 -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;  
89 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; 38 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
90 -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.request;  
91 -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;  
92 -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;  
93 39
94 @ActiveProfiles("test") 40 @ActiveProfiles("test")
95 @RunWith(SpringRunner.class) 41 @RunWith(SpringRunner.class)
application/src/test/java/org/thingsboard/server/controller/BaseYtAdminControllerTest.java renamed from application/src/test/java/org/thingsboard/server/controller/BaseAdminControllerTest.java
@@ -24,7 +24,7 @@ import static org.hamcrest.Matchers.*; @@ -24,7 +24,7 @@ import static org.hamcrest.Matchers.*;
24 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 24 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
25 25
26 26
27 -public abstract class BaseAdminControllerTest extends AbstractControllerTest { 27 +public abstract class BaseYtAdminControllerTest extends AbstractControllerTest {
28 28
29 @Test 29 @Test
30 public void testFindAdminSettingsByKey() throws Exception { 30 public void testFindAdminSettingsByKey() throws Exception {
application/src/test/java/org/thingsboard/server/controller/sql/YtAdminControllerSqlTest.java renamed from application/src/test/java/org/thingsboard/server/controller/sql/AdminControllerSqlTest.java
@@ -15,12 +15,12 @@ @@ -15,12 +15,12 @@
15 */ 15 */
16 package org.thingsboard.server.controller.sql; 16 package org.thingsboard.server.controller.sql;
17 17
18 -import org.thingsboard.server.controller.BaseAdminControllerTest; 18 +import org.thingsboard.server.controller.BaseYtAdminControllerTest;
19 import org.thingsboard.server.dao.service.DaoSqlTest; 19 import org.thingsboard.server.dao.service.DaoSqlTest;
20 20
21 /** 21 /**
22 * Created by Valerii Sosliuk on 6/28/2017. 22 * Created by Valerii Sosliuk on 6/28/2017.
23 */ 23 */
24 @DaoSqlTest 24 @DaoSqlTest
25 -public class AdminControllerSqlTest extends BaseAdminControllerTest { 25 +public class YtAdminControllerSqlTest extends BaseYtAdminControllerTest {
26 } 26 }
@@ -100,6 +100,78 @@ @@ -100,6 +100,78 @@
100 <groupId>io.swagger</groupId> 100 <groupId>io.swagger</groupId>
101 <artifactId>swagger-annotations</artifactId> 101 <artifactId>swagger-annotations</artifactId>
102 </dependency> 102 </dependency>
  103 + <dependency>
  104 + <groupId>org.springframework.boot</groupId>
  105 + <artifactId>spring-boot-autoconfigure</artifactId>
  106 + </dependency>
  107 + <dependency>
  108 + <groupId>org.springframework</groupId>
  109 + <artifactId>spring-context</artifactId>
  110 + </dependency>
  111 + <dependency>
  112 + <groupId>org.springframework</groupId>
  113 + <artifactId>spring-context-support</artifactId>
  114 + </dependency>
  115 + <dependency>
  116 + <groupId>org.springframework.data</groupId>
  117 + <artifactId>spring-data-redis</artifactId>
  118 + </dependency>
  119 +
  120 + <!--阿里短信SDK -->
  121 + <dependency>
  122 + <groupId>com.aliyun</groupId>
  123 + <artifactId>aliyun-java-sdk-core</artifactId>
  124 + <version>${aliyun.sdk.core}</version>
  125 + </dependency>
  126 + <dependency>
  127 + <groupId>com.aliyun</groupId>
  128 + <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
  129 + <version>${aliyun.sdk.dysmsapi}</version>
  130 + </dependency>
  131 + <!-- 邮件发送 -->
  132 + <dependency>
  133 + <groupId>com.sun.mail</groupId>
  134 + <artifactId>jakarta.mail</artifactId>
  135 + <version>${jakarta.mail.version}</version>
  136 + </dependency>
  137 +
  138 + <!--minio-->
  139 + <dependency>
  140 + <groupId>io.minio</groupId>
  141 + <artifactId>minio</artifactId>
  142 + <version>${io.minio.version}</version>
  143 + </dependency>
  144 + <!--alibaba easyExcel-->
  145 + <dependency>
  146 + <groupId>com.alibaba</groupId>
  147 + <artifactId>easyexcel</artifactId>
  148 + <version>${com.alibaba.easyexcel.version}</version>
  149 + </dependency>
  150 + <!-- aspectj -->
  151 + <dependency>
  152 + <groupId>org.aspectj</groupId>
  153 + <artifactId>aspectjweaver</artifactId>
  154 + <version>1.9.6</version>
  155 + <scope>runtime</scope>
  156 + </dependency>
  157 + <dependency>
  158 + <groupId>org.thingsboard.common</groupId>
  159 + <artifactId>util</artifactId>
  160 + </dependency>
  161 + <dependency>
  162 + <groupId>org.springframework</groupId>
  163 + <artifactId>spring-web</artifactId>
  164 + </dependency>
  165 +
  166 + <dependency>
  167 + <groupId>org.springframework.boot</groupId>
  168 + <artifactId>spring-boot-starter-web</artifactId>
  169 + </dependency>
  170 + <dependency>
  171 + <groupId>org.aspectj</groupId>
  172 + <artifactId>aspectjrt</artifactId>
  173 + <version>1.9.6</version>
  174 + </dependency>
103 </dependencies> 175 </dependencies>
104 176
105 <build> 177 <build>
1 /** 1 /**
2 * Copyright © 2016-2021 The Thingsboard Authors 2 * Copyright © 2016-2021 The Thingsboard Authors
3 * 3 *
4 - * Licensed under the Apache License, Version 2.0 (the "License");  
5 - * you may not use this file except in compliance with the License.  
6 - * You may obtain a copy of the License at 4 + * <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
  5 + * except in compliance with the License. You may obtain a copy of the License at
7 * 6 *
8 - * http://www.apache.org/licenses/LICENSE-2.0 7 + * <p>http://www.apache.org/licenses/LICENSE-2.0
9 * 8 *
10 - * Unless required by applicable law or agreed to in writing, software  
11 - * distributed under the License is distributed on an "AS IS" BASIS,  
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
13 - * See the License for the specific language governing permissions and 9 + * <p>Unless required by applicable law or agreed to in writing, software distributed under the
  10 + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  11 + * express or implied. See the License for the specific language governing permissions and
14 * limitations under the License. 12 * limitations under the License.
15 */ 13 */
16 package org.thingsboard.server.common.data; 14 package org.thingsboard.server.common.data;
@@ -21,6 +19,8 @@ import com.fasterxml.jackson.databind.JsonNode; @@ -21,6 +19,8 @@ import com.fasterxml.jackson.databind.JsonNode;
21 import io.swagger.annotations.ApiModel; 19 import io.swagger.annotations.ApiModel;
22 import io.swagger.annotations.ApiModelProperty; 20 import io.swagger.annotations.ApiModelProperty;
23 import lombok.EqualsAndHashCode; 21 import lombok.EqualsAndHashCode;
  22 +import lombok.Getter;
  23 +import lombok.Setter;
24 import org.thingsboard.server.common.data.id.CustomerId; 24 import org.thingsboard.server.common.data.id.CustomerId;
25 import org.thingsboard.server.common.data.id.EntityId; 25 import org.thingsboard.server.common.data.id.EntityId;
26 import org.thingsboard.server.common.data.id.TenantId; 26 import org.thingsboard.server.common.data.id.TenantId;
@@ -28,167 +28,202 @@ import org.thingsboard.server.common.data.id.UserId; @@ -28,167 +28,202 @@ import org.thingsboard.server.common.data.id.UserId;
28 import org.thingsboard.server.common.data.security.Authority; 28 import org.thingsboard.server.common.data.security.Authority;
29 import org.thingsboard.server.common.data.validation.Length; 29 import org.thingsboard.server.common.data.validation.Length;
30 import org.thingsboard.server.common.data.validation.NoXss; 30 import org.thingsboard.server.common.data.validation.NoXss;
  31 +import org.thingsboard.server.common.data.yunteng.dto.UserDetailRoleDTO;
  32 +import org.thingsboard.server.common.data.yunteng.dto.UserDetailsDTO;
  33 +
  34 +import java.util.Set;
31 35
32 @ApiModel 36 @ApiModel
33 @EqualsAndHashCode(callSuper = true) 37 @EqualsAndHashCode(callSuper = true)
34 -public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements HasName, HasTenantId, HasCustomerId {  
35 -  
36 - private static final long serialVersionUID = 8250339805336035966L;  
37 -  
38 - private TenantId tenantId;  
39 - private CustomerId customerId;  
40 - private String email;  
41 - private Authority authority;  
42 - @NoXss  
43 - @Length(fieldName = "first name")  
44 - private String firstName;  
45 - @NoXss  
46 - @Length(fieldName = "last name")  
47 - private String lastName;  
48 -  
49 - public User() {  
50 - super();  
51 - }  
52 -  
53 - public User(UserId id) {  
54 - super(id);  
55 - }  
56 -  
57 - public User(User user) {  
58 - super(user);  
59 - this.tenantId = user.getTenantId();  
60 - this.customerId = user.getCustomerId();  
61 - this.email = user.getEmail();  
62 - this.authority = user.getAuthority();  
63 - this.firstName = user.getFirstName();  
64 - this.lastName = user.getLastName();  
65 - }  
66 -  
67 -  
68 - @ApiModelProperty(position = 1, value = "JSON object with the User Id. " +  
69 - "Specify this field to update the device. " +  
70 - "Referencing non-existing User Id will cause error. " +  
71 - "Omit this field to create new customer." )  
72 - @Override  
73 - public UserId getId() {  
74 - return super.getId();  
75 - }  
76 -  
77 - @ApiModelProperty(position = 2, value = "Timestamp of the user creation, in milliseconds", example = "1609459200000", readOnly = true)  
78 - @Override  
79 - public long getCreatedTime() {  
80 - return super.getCreatedTime();  
81 - }  
82 -  
83 - @ApiModelProperty(position = 3, value = "JSON object with the Tenant Id.", readOnly = true)  
84 - public TenantId getTenantId() {  
85 - return tenantId;  
86 - }  
87 -  
88 - public void setTenantId(TenantId tenantId) {  
89 - this.tenantId = tenantId;  
90 - }  
91 -  
92 - @ApiModelProperty(position = 4, value = "JSON object with the Customer Id.", readOnly = true)  
93 - public CustomerId getCustomerId() {  
94 - return customerId;  
95 - }  
96 -  
97 - public void setCustomerId(CustomerId customerId) {  
98 - this.customerId = customerId;  
99 - }  
100 -  
101 - @ApiModelProperty(position = 5, required = true, value = "Email of the user", example = "user@example.com")  
102 - public String getEmail() {  
103 - return email;  
104 - }  
105 -  
106 - public void setEmail(String email) {  
107 - this.email = email;  
108 - }  
109 -  
110 - @ApiModelProperty(position = 6, readOnly = true, value = "Duplicates the email of the user, readonly", example = "user@example.com")  
111 - @Override  
112 - @JsonProperty(access = JsonProperty.Access.READ_ONLY)  
113 - public String getName() {  
114 - return email;  
115 - }  
116 -  
117 - @ApiModelProperty(position = 7, required = true, value = "Authority", example = "SYS_ADMIN, TENANT_ADMIN or CUSTOMER_USER")  
118 - public Authority getAuthority() {  
119 - return authority;  
120 - }  
121 -  
122 - public void setAuthority(Authority authority) {  
123 - this.authority = authority;  
124 - }  
125 -  
126 - @ApiModelProperty(position = 8, required = true, value = "First name of the user", example = "John")  
127 - public String getFirstName() {  
128 - return firstName;  
129 - }  
130 -  
131 - public void setFirstName(String firstName) {  
132 - this.firstName = firstName;  
133 - }  
134 -  
135 - @ApiModelProperty(position = 9, required = true, value = "Last name of the user", example = "Doe")  
136 - public String getLastName() {  
137 - return lastName;  
138 - }  
139 -  
140 - public void setLastName(String lastName) {  
141 - this.lastName = lastName;  
142 - }  
143 -  
144 - @ApiModelProperty(position = 10, value = "Additional parameters of the user", dataType = "com.fasterxml.jackson.databind.JsonNode")  
145 - @Override  
146 - public JsonNode getAdditionalInfo() {  
147 - return super.getAdditionalInfo();  
148 - }  
149 -  
150 - @Override  
151 - public String getSearchText() {  
152 - return getEmail();  
153 - }  
154 -  
155 - @Override  
156 - public String toString() {  
157 - StringBuilder builder = new StringBuilder();  
158 - builder.append("User [tenantId=");  
159 - builder.append(tenantId);  
160 - builder.append(", customerId=");  
161 - builder.append(customerId);  
162 - builder.append(", email=");  
163 - builder.append(email);  
164 - builder.append(", authority=");  
165 - builder.append(authority);  
166 - builder.append(", firstName=");  
167 - builder.append(firstName);  
168 - builder.append(", lastName=");  
169 - builder.append(lastName);  
170 - builder.append(", additionalInfo=");  
171 - builder.append(getAdditionalInfo());  
172 - builder.append(", createdTime=");  
173 - builder.append(createdTime);  
174 - builder.append(", id=");  
175 - builder.append(id);  
176 - builder.append("]");  
177 - return builder.toString();  
178 - }  
179 -  
180 - @JsonIgnore  
181 - public boolean isSystemAdmin() {  
182 - return tenantId == null || EntityId.NULL_UUID.equals(tenantId.getId());  
183 - }  
184 -  
185 - @JsonIgnore  
186 - public boolean isTenantAdmin() {  
187 - return !isSystemAdmin() && (customerId == null || EntityId.NULL_UUID.equals(customerId.getId()));  
188 - }  
189 -  
190 - @JsonIgnore  
191 - public boolean isCustomerUser() {  
192 - return !isSystemAdmin() && !isTenantAdmin();  
193 - } 38 +public class User extends SearchTextBasedWithAdditionalInfo<UserId>
  39 + implements HasName, HasTenantId, HasCustomerId {
  40 +
  41 + private static final long serialVersionUID = 8250339805336035966L;
  42 +
  43 + private TenantId tenantId;
  44 + private CustomerId customerId;
  45 + private String email;
  46 + private Authority authority;
  47 +
  48 + @NoXss
  49 + @Length(fieldName = "first name")
  50 + private String firstName;
  51 +
  52 + @NoXss
  53 + @Length(fieldName = "last name")
  54 + private String lastName;
  55 + /** 平台的用户详情 */
  56 + @Getter @Setter private UserDetailsDTO userDetailsDTO;
  57 +
  58 + public User() {
  59 + super();
  60 + }
  61 +
  62 + public User(UserId id) {
  63 + super(id);
  64 + }
  65 +
  66 + public User(User user) {
  67 + super(user);
  68 + this.tenantId = user.getTenantId();
  69 + this.customerId = user.getCustomerId();
  70 + this.email = user.getEmail();
  71 + this.authority = user.getAuthority();
  72 + this.firstName = user.getFirstName();
  73 + this.lastName = user.getLastName();
  74 + }
  75 +
  76 + @ApiModelProperty(
  77 + position = 1,
  78 + value =
  79 + "JSON object with the User Id. "
  80 + + "Specify this field to update the device. "
  81 + + "Referencing non-existing User Id will cause error. "
  82 + + "Omit this field to create new customer.")
  83 + @Override
  84 + public UserId getId() {
  85 + return super.getId();
  86 + }
  87 +
  88 + @ApiModelProperty(
  89 + position = 2,
  90 + value = "Timestamp of the user creation, in milliseconds",
  91 + example = "1609459200000",
  92 + readOnly = true)
  93 + @Override
  94 + public long getCreatedTime() {
  95 + return super.getCreatedTime();
  96 + }
  97 +
  98 + @ApiModelProperty(position = 3, value = "JSON object with the Tenant Id.", readOnly = true)
  99 + public TenantId getTenantId() {
  100 + return tenantId;
  101 + }
  102 +
  103 + public void setTenantId(TenantId tenantId) {
  104 + this.tenantId = tenantId;
  105 + }
  106 +
  107 + @ApiModelProperty(position = 4, value = "JSON object with the Customer Id.", readOnly = true)
  108 + public CustomerId getCustomerId() {
  109 + return customerId;
  110 + }
  111 +
  112 + public void setCustomerId(CustomerId customerId) {
  113 + this.customerId = customerId;
  114 + }
  115 +
  116 + @ApiModelProperty(
  117 + position = 5,
  118 + required = true,
  119 + value = "Email of the user",
  120 + example = "user@example.com")
  121 + public String getEmail() {
  122 + return email;
  123 + }
  124 +
  125 + public void setEmail(String email) {
  126 + this.email = email;
  127 + }
  128 +
  129 + @ApiModelProperty(
  130 + position = 6,
  131 + readOnly = true,
  132 + value = "Duplicates the email of the user, readonly",
  133 + example = "user@example.com")
  134 + @Override
  135 + @JsonProperty(access = JsonProperty.Access.READ_ONLY)
  136 + public String getName() {
  137 + return email;
  138 + }
  139 +
  140 + @ApiModelProperty(
  141 + position = 7,
  142 + required = true,
  143 + value = "Authority",
  144 + example = "SYS_ADMIN, TENANT_ADMIN or CUSTOMER_USER")
  145 + public Authority getAuthority() {
  146 + return authority;
  147 + }
  148 +
  149 + public void setAuthority(Authority authority) {
  150 + this.authority = authority;
  151 + }
  152 +
  153 + @ApiModelProperty(
  154 + position = 8,
  155 + required = true,
  156 + value = "First name of the user",
  157 + example = "John")
  158 + public String getFirstName() {
  159 + return firstName;
  160 + }
  161 +
  162 + public void setFirstName(String firstName) {
  163 + this.firstName = firstName;
  164 + }
  165 +
  166 + @ApiModelProperty(position = 9, required = true, value = "Last name of the user", example = "Doe")
  167 + public String getLastName() {
  168 + return lastName;
  169 + }
  170 +
  171 + public void setLastName(String lastName) {
  172 + this.lastName = lastName;
  173 + }
  174 +
  175 + @ApiModelProperty(
  176 + position = 10,
  177 + value = "Additional parameters of the user",
  178 + dataType = "com.fasterxml.jackson.databind.JsonNode")
  179 + @Override
  180 + public JsonNode getAdditionalInfo() {
  181 + return super.getAdditionalInfo();
  182 + }
  183 +
  184 + @Override
  185 + public String getSearchText() {
  186 + return getEmail();
  187 + }
  188 +
  189 + @Override
  190 + public String toString() {
  191 + StringBuilder builder = new StringBuilder();
  192 + builder.append("User [tenantId=");
  193 + builder.append(tenantId);
  194 + builder.append(", customerId=");
  195 + builder.append(customerId);
  196 + builder.append(", email=");
  197 + builder.append(email);
  198 + builder.append(", authority=");
  199 + builder.append(authority);
  200 + builder.append(", firstName=");
  201 + builder.append(firstName);
  202 + builder.append(", lastName=");
  203 + builder.append(lastName);
  204 + builder.append(", additionalInfo=");
  205 + builder.append(getAdditionalInfo());
  206 + builder.append(", createdTime=");
  207 + builder.append(createdTime);
  208 + builder.append(", id=");
  209 + builder.append(id);
  210 + builder.append("]");
  211 + return builder.toString();
  212 + }
  213 +
  214 + @JsonIgnore
  215 + public boolean isSystemAdmin() {
  216 + return tenantId == null || EntityId.NULL_UUID.equals(tenantId.getId());
  217 + }
  218 +
  219 + @JsonIgnore
  220 + public boolean isTenantAdmin() {
  221 + return !isSystemAdmin()
  222 + && (customerId == null || EntityId.NULL_UUID.equals(customerId.getId()));
  223 + }
  224 +
  225 + @JsonIgnore
  226 + public boolean isCustomerUser() {
  227 + return !isSystemAdmin() && !isTenantAdmin();
  228 + }
194 } 229 }
  1 +package org.thingsboard.server.common.data.yunteng.common;
  2 +
  3 +public interface AddGroup {
  4 +}
  1 +package org.thingsboard.server.common.data.yunteng.common;
  2 +
  3 +import org.thingsboard.server.common.data.yunteng.dto.SysDictItemDTO;
  4 +
  5 +public interface CommonService {
  6 + /**
  7 + * 通过dict表的Code和dictItem的codeText查询字典表的值
  8 + *
  9 + * @param dictCode 字典表Code
  10 + * @param codeValue 字典Item表文本值
  11 + * @return 返回字典Item表
  12 + */
  13 + SysDictItemDTO getDictValueByCodeAndText(String dictCode, String codeValue);
  14 +
  15 + /**
  16 + * 生成DeviceToken
  17 + * @return 返回DeviceToken
  18 + */
  19 + String generateDeviceToken(String tenantId);
  20 +}
  1 +package org.thingsboard.server.common.data.yunteng.common;
  2 +
  3 +public interface DeleteGroup {
  4 +}
  1 +package org.thingsboard.server.common.data.yunteng.common;
  2 +
  3 +public interface UpdateGroup {
  4 +}
  1 +package org.thingsboard.server.common.data.yunteng.common.aspect;
  2 +
  3 +
  4 +import com.fasterxml.jackson.databind.JsonNode;
  5 +import com.fasterxml.jackson.databind.node.ObjectNode;
  6 +import lombok.RequiredArgsConstructor;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.apache.commons.lang3.StringUtils;
  9 +import org.aspectj.lang.ProceedingJoinPoint;
  10 +import org.aspectj.lang.annotation.Around;
  11 +import org.aspectj.lang.annotation.Aspect;
  12 +import org.aspectj.lang.annotation.Pointcut;
  13 +import org.springframework.stereotype.Component;
  14 +import org.thingsboard.common.util.JacksonUtil;
  15 +import org.thingsboard.server.common.data.yunteng.common.CommonService;
  16 +import org.thingsboard.server.common.data.yunteng.common.aspect.annotation.AutoDict;
  17 +import org.thingsboard.server.common.data.yunteng.dto.SysDictItemDTO;
  18 +import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils;
  19 +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData;
  20 +import org.thingsboard.server.common.data.yunteng.utils.tools.ResponseResult;
  21 +
  22 +import java.lang.reflect.Field;
  23 +import java.time.LocalDateTime;
  24 +import java.time.format.DateTimeFormatter;
  25 +import java.util.ArrayList;
  26 +import java.util.List;
  27 +
  28 +@Aspect
  29 +@Component
  30 +@Slf4j
  31 +@RequiredArgsConstructor
  32 +public class SysDictAspect {
  33 +
  34 + private final CommonService commonService;
  35 +
  36 + /** 表对应字段加上_dictText即可显示出文本 */
  37 + private static final String DICT_TEXT_SUFFIX = "DictText";
  38 +
  39 + /** 定义切入点 */
  40 + @Pointcut("execution(* com.codeez..*.*Controller.*(..))")
  41 + public void exudeService() {}
  42 +
  43 + /**
  44 + * 执行环绕通知
  45 + *
  46 + * @param joinPoint 切面
  47 + * @return 返回类型: Object
  48 + */
  49 + @Around("exudeService()")
  50 + public Object aroundAdvise(ProceedingJoinPoint joinPoint) throws Throwable {
  51 + // 执行切点环绕通知,获取执行方法的返回值
  52 + Object returnObject = joinPoint.proceed();
  53 + return parseDictValue(returnObject);
  54 + }
  55 +
  56 + /**
  57 + * 解析数据字典值
  58 + *
  59 + * @param returnObject 数据字典Code对应的值
  60 + */
  61 + private Object parseDictValue(Object returnObject) throws IllegalAccessException {
  62 + if (returnObject instanceof ResponseResult) {
  63 + Object object = ((ResponseResult<?>) returnObject).getData();
  64 + if(null != object){
  65 + ObjectNode objectNode = getObjectNode(object, ((ResponseResult) returnObject).getData());
  66 + if(null == objectNode){
  67 + return returnObject;
  68 + }
  69 + returnObject = ResponseResult.success(objectNode);
  70 + }
  71 + }
  72 + if (returnObject instanceof PageData) {
  73 + Object object = returnObject;
  74 + List<ObjectNode> list = new ArrayList<>();
  75 + for (Object obj : ((PageData<?>) object).getItems()) {
  76 + ObjectNode objectNode = getObjectNode(obj, obj);
  77 + if(null == objectNode){
  78 + return returnObject;
  79 + }
  80 + list.add(objectNode);
  81 + }
  82 + returnObject =new PageData<>(list, ((PageData<?>) object).getTotal());
  83 + }
  84 + return returnObject;
  85 + }
  86 +
  87 + /**
  88 + * 通过dict表的Code和dictItem的codeText查询字典表的值
  89 + *
  90 + * @param code dict表的Code
  91 + * @param codeText dictItem的codeText
  92 + * @return 返回Item的值
  93 + */
  94 + private String getDictText(String code, Object codeText) {
  95 + SysDictItemDTO sysDictItemDTO =
  96 + commonService.getDictValueByCodeAndText(code, codeText.toString());
  97 + return sysDictItemDTO != null ? sysDictItemDTO.getItemText() : null;
  98 + }
  99 +
  100 + /**
  101 + * 获取添加字段后的ObjectNode
  102 + *
  103 + * @param object 对象
  104 + * @param sourceObject 源对象
  105 + * @return 添加字段后的ObjectNode
  106 + */
  107 + private ObjectNode getObjectNode(Object object, Object sourceObject)
  108 + throws IllegalAccessException {
  109 + ObjectNode objectNode = null;
  110 + for (Field field : ReflectUtils.getAllDeclaredFields(object.getClass())) {
  111 + // 忽略修饰符访问检查
  112 + field.setAccessible(true);
  113 + if (field.getAnnotation(AutoDict.class) != null) {
  114 + String dictCode = field.getAnnotation(AutoDict.class).dictCode();
  115 + // 如果dictCode为空字符串,则循环下一个
  116 + if (StringUtils.isEmpty(dictCode)) {
  117 + log.debug("dictCode为空字符串的字段为{}", field.getName());
  118 + continue;
  119 + }
  120 + Object codeText = field.get(object);
  121 + if (null != codeText) {
  122 + String textValue = getDictText(dictCode, codeText);
  123 + JsonNode jsonNode = JacksonUtil.toJsonNode(JacksonUtil.toString(sourceObject));
  124 + if(null == objectNode){
  125 + objectNode = (ObjectNode) jsonNode;
  126 + }
  127 + objectNode.put(field.getName() + DICT_TEXT_SUFFIX, textValue);
  128 + }
  129 + }
  130 + if(field.getType().getName().equals("java.time.LocalDateTime")){
  131 + Object content = field.get(object);
  132 + if(null != content && null !=objectNode){
  133 + DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  134 + objectNode.put(field.getName(),fmt.format((LocalDateTime)content));
  135 + }
  136 + }
  137 + }
  138 + return objectNode;
  139 + }
  140 +}
  1 +package org.thingsboard.server.common.data.yunteng.common.aspect.annotation;
  2 +
  3 +import java.lang.annotation.*;
  4 +
  5 +/**
  6 + * 字典注解
  7 + */
  8 +@Target(ElementType.FIELD)
  9 +@Retention(RetentionPolicy.RUNTIME)
  10 +@Documented
  11 +public @interface AutoDict {
  12 + /**
  13 + * 字典Code
  14 + * @return 返回类型 String
  15 + */
  16 + String dictCode();
  17 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.email;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class EmailConfiguration {
  7 +
  8 + /** 配置服务器 */
  9 + private String host;
  10 +
  11 + /** 配置端口 */
  12 + private Integer port;
  13 +
  14 + /** 配置用户名 */
  15 + private String username;
  16 +
  17 + /** 配置密码 */
  18 + private String password;
  19 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
  5 +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException;
  6 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  7 +
  8 +@Slf4j
  9 +public abstract class AbstractSmsSender implements SmsSender {
  10 +
  11 + protected void validatePhoneNumber(String phoneNumber) {
  12 + phoneNumber = phoneNumber.trim();
  13 + if (!FastIotConstants.CHINA_MOBILE_PATTERN.matcher(phoneNumber).matches()) {
  14 + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  15 + }
  16 + }
  17 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms;
  2 +import com.fasterxml.jackson.annotation.JsonIgnore;
  3 +import com.fasterxml.jackson.annotation.JsonSubTypes;
  4 +import com.fasterxml.jackson.annotation.JsonTypeInfo;
  5 +import org.thingsboard.server.common.data.yunteng.config.sms.ali.AliSmsProviderConfiguration;
  6 +import org.thingsboard.server.common.data.yunteng.config.sms.tencent.TencentSmsProviderConfiguration;
  7 +import org.thingsboard.server.common.data.yunteng.enums.SmsProviderTypeEnum;
  8 +
  9 +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
  10 +@JsonSubTypes({
  11 + @JsonSubTypes.Type(value = AliSmsProviderConfiguration.class, name = "ALI_CLOUD"),
  12 + @JsonSubTypes.Type(value = TencentSmsProviderConfiguration.class, name = "TENCENT_CLOUD")
  13 +})
  14 +public interface SmsProviderConfiguration {
  15 +
  16 + @JsonIgnore
  17 + SmsProviderTypeEnum getType();
  18 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms;
  2 +
  3 +import java.util.LinkedHashMap;
  4 +
  5 +public interface SmsSender {
  6 + String sendSms(String phone, String templateCode, LinkedHashMap<String,String> param,String signName);
  7 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms;
  2 +
  3 +public interface SmsSenderFactory {
  4 + SmsSender createSmsSender(SmsProviderConfiguration config);
  5 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms;
  2 +
  3 +import org.springframework.stereotype.Component;
  4 +import org.thingsboard.server.common.data.yunteng.config.sms.ali.AliSmsProviderConfiguration;
  5 +import org.thingsboard.server.common.data.yunteng.config.sms.ali.AliSmsSender;
  6 +import org.thingsboard.server.common.data.yunteng.config.sms.tencent.TencentSmsProviderConfiguration;
  7 +import org.thingsboard.server.common.data.yunteng.config.sms.tencent.TencentSmsSender;
  8 +
  9 +@Component
  10 +public class YtDefaultSmsSenderFactory implements SmsSenderFactory {
  11 + @Override
  12 + public SmsSender createSmsSender(
  13 + SmsProviderConfiguration config) {
  14 + switch (config.getType()) {
  15 + case ALI_CLOUD:
  16 + return new AliSmsSender(
  17 + (AliSmsProviderConfiguration) config);
  18 + case TENCENT_CLOUD:
  19 + return new TencentSmsSender(
  20 + (TencentSmsProviderConfiguration) config);
  21 + default:
  22 + throw new RuntimeException("Unknown SMS provider type " + config.getType());
  23 + }
  24 + }
  25 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms.ali;
  2 +
  3 +import lombok.Data;
  4 +import org.thingsboard.server.common.data.yunteng.config.sms.SmsProviderConfiguration;
  5 +import org.thingsboard.server.common.data.yunteng.enums.SmsProviderTypeEnum;
  6 +
  7 +@Data
  8 +public class AliSmsProviderConfiguration implements SmsProviderConfiguration {
  9 +
  10 + /** 阿里云AccessKeyId */
  11 + private String accessKeyId;
  12 +
  13 + /** 阿里云AccessKeySecret */
  14 + private String accessKeySecret;
  15 +
  16 + @Override
  17 + public SmsProviderTypeEnum getType() {
  18 + return SmsProviderTypeEnum.ALI_CLOUD;
  19 + }
  20 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms.ali;
  2 +
  3 +import com.aliyuncs.DefaultAcsClient;
  4 +import com.aliyuncs.IAcsClient;
  5 +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
  6 +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
  7 +import com.aliyuncs.exceptions.ClientException;
  8 +import com.aliyuncs.http.MethodType;
  9 +import com.aliyuncs.profile.DefaultProfile;
  10 +import com.aliyuncs.profile.IClientProfile;
  11 +import lombok.Data;
  12 +import lombok.extern.slf4j.Slf4j;
  13 +import org.apache.commons.lang3.StringUtils;
  14 +import org.thingsboard.common.util.JacksonUtil;
  15 +import org.thingsboard.server.common.data.yunteng.config.sms.AbstractSmsSender;
  16 +import org.thingsboard.server.common.data.yunteng.core.exception.FastIotException;
  17 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  18 +import org.thingsboard.server.common.data.yunteng.enums.ResponseCodeEnum;
  19 +
  20 +import java.util.LinkedHashMap;
  21 +
  22 +@Slf4j
  23 +public class AliSmsSender extends AbstractSmsSender {
  24 +
  25 + /** 阿里云短信参数配置 */
  26 + private final AliSmsProviderConfiguration config;
  27 +
  28 + private IClientProfile profile;
  29 +
  30 + public AliSmsSender(AliSmsProviderConfiguration config) {
  31 + if (StringUtils.isEmpty(config.getAccessKeyId())
  32 + || StringUtils.isEmpty(config.getAccessKeyId())) {
  33 + throw new FastIotException(ErrorMessage.INVALID_PARAMETER);
  34 + }
  35 + this.config = config;
  36 + initProfile();
  37 + }
  38 +
  39 + /** 使用AK&SK初始化账号Client */
  40 + private void initProfile() {
  41 + String endpoint = "dysmsapi.aliyuncs.com";
  42 + String product = "Dysmsapi";
  43 + String regionId = "cn-shanghai";
  44 + profile =
  45 + DefaultProfile.getProfile(regionId, config.getAccessKeyId(), config.getAccessKeySecret());
  46 + DefaultProfile.addEndpoint(regionId, product, endpoint);
  47 + }
  48 +
  49 + @Override
  50 + public String sendSms(
  51 + String phone, String templateCode, LinkedHashMap<String, String> param, String signName) {
  52 + validatePhoneNumber(phone);
  53 + IAcsClient client = new DefaultAcsClient(profile);
  54 + SendSmsRequest request = new SendSmsRequest();
  55 + request.setSysMethod(MethodType.POST);
  56 + request.setPhoneNumbers(phone);
  57 + request.setSignName(signName);
  58 + request.setTemplateCode(templateCode);
  59 + // 有参数的时候才处理
  60 + if (!param.isEmpty()) {
  61 + request.setTemplateParam(JacksonUtil.toString(param));
  62 + }
  63 + try {
  64 + SendSmsResponse response = client.getAcsResponse(request);
  65 + return response.getCode().equalsIgnoreCase(ResponseCodeEnum.OK.name())
  66 + ? ResponseCodeEnum.SUCCESS.name()
  67 + : response.getMessage();
  68 + } catch (ClientException e) {
  69 + e.printStackTrace();
  70 + return e.getMessage();
  71 + }
  72 + }
  73 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms.tencent;
  2 +
  3 +
  4 +import lombok.Data;
  5 +import org.thingsboard.server.common.data.yunteng.config.sms.SmsProviderConfiguration;
  6 +import org.thingsboard.server.common.data.yunteng.enums.SmsProviderTypeEnum;
  7 +
  8 +@Data
  9 +public class TencentSmsProviderConfiguration implements SmsProviderConfiguration {
  10 +
  11 + /** 腾讯云AppId */
  12 + private String appId;
  13 +
  14 + /** 腾讯云appKey */
  15 + private String appKey;
  16 +
  17 + @Override
  18 + public SmsProviderTypeEnum getType() {
  19 + return SmsProviderTypeEnum.TENCENT_CLOUD;
  20 + }
  21 +}
  1 +package org.thingsboard.server.common.data.yunteng.config.sms.tencent;
  2 +
  3 +
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.thingsboard.server.common.data.yunteng.config.sms.AbstractSmsSender;
  6 +
  7 +import java.util.LinkedHashMap;
  8 +
  9 +@Slf4j
  10 +public class TencentSmsSender extends AbstractSmsSender {
  11 +
  12 + public TencentSmsSender(TencentSmsProviderConfiguration config) {}
  13 +
  14 + @Override
  15 + public String sendSms(
  16 + String phone, String templateCode, LinkedHashMap<String, String> param, String signName) {
  17 + return "";
  18 + }
  19 +}
  1 +package org.thingsboard.server.common.data.yunteng.constant;
  2 +
  3 +import java.util.regex.Pattern;
  4 +
  5 +public interface FastIotConstants {
  6 +
  7 + class DefaultOrder {
  8 + public static final String CREATE_TIME="create_time";
  9 + }
  10 +
  11 + String MOBILE =
  12 + "^[1](([3][0-9])|([4][0,1,4-9])|([5][0-3,5-9])|([6][2,5,6,7])|([7][0-8])|([8][0-9])|([9][0-3,5-9]))[0-9]{8}$";
  13 + String EMAIL = "^[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}$";
  14 + Pattern EMAIL_PATTERN = Pattern.compile(EMAIL, Pattern.CASE_INSENSITIVE);
  15 + Pattern CHINA_MOBILE_PATTERN = Pattern.compile(MOBILE);
  16 +
  17 + class ConfigJSONKey {
  18 + public static final String BASE_URL = "baseUrl";
  19 + }
  20 +
  21 + String DEFAULT_DELIMITER = "#";
  22 +
  23 + class StateValue {
  24 + /** 禁用 */
  25 + public static final int DISABLE = 0;
  26 + /** 启用 */
  27 + public static final int ENABLE = 1;
  28 +
  29 + /** 删除成功 */
  30 + public static final String DELETE_SUCCESS = "删除成功";
  31 +
  32 + /** 删除失败 */
  33 + public static final String DELETE_FAILED = "删除成功";
  34 + }
  35 +
  36 + class LevelValue {
  37 + /** 超级管理员 */
  38 + public static final int IS_ADMIN=0;
  39 +
  40 + /** 系统平台其他管理员 */
  41 + public static final int IS_OTHER_ADMIN = 1;
  42 +
  43 + /** 租户管理员 */
  44 + public static final int IS_TENANT_ADMIN = 2;
  45 +
  46 + /** 普通用户 */
  47 + public static final int IS_NORMAL = 3;
  48 + }
  49 +
  50 + interface CacheConfigKey {
  51 + String CACHE_CONFIG_KEY = "FAST_IOT_CACHE";
  52 + String USER_PERMISSION_PREFIX = "user_permission_for_";
  53 + String MOBILE_LOGIN_SMS_CODE = "mobile_login_sms_code";
  54 + String DEFAULT_RULE_CHAIN = "default_rule_chain";
  55 + }
  56 +
  57 + String DEFAULT_EMAIL_SUFFIX_FOR_TB ="@yunteng.com";
  58 +
  59 + interface TBCacheConfig {
  60 + String TB_CACHE_CONFIG_KEY = "TB_CONNECT_CACHE";
  61 + String EXISTING_TENANT = "EXISTING_TENANT";
  62 + }
  63 +}
  1 +package org.thingsboard.server.common.data.yunteng.constant;
  2 +
  3 +public final class ModelConstants {
  4 + public static class Table {
  5 + /** 系统用户表 */
  6 + public static final String USER_TABLE_NAME = "sys_user";
  7 + /** 租户表 */
  8 + public static final String TENANT_TABLE_NAME = "sys_tenant";
  9 + /** 租户菜单表 */
  10 + public static final String TENANT_MENU_TABLE_NAME = "sys_tenant_menu";
  11 + /** 租户角色表 */
  12 + public static final String TENANT_ROLE_TABLE_NAME = "sys_tenant_role";
  13 + /** 菜单表 */
  14 + public static final String MENU_TABLE_NAME = "sys_menu";
  15 + /** 角色表 */
  16 + public static final String ROLE_TABLE_NAME = "sys_role";
  17 + /** 用户角色关系表 */
  18 + public static final String USER_ROLE_TABLE_NAME = "sys_user_role";
  19 + /** 系统用户设置表 */
  20 + public static final String ADMIN_SETTING_TABLE_NAME = "sys_admin_setting";
  21 + /** 字典表 */
  22 + public static final String DICT_TABLE_NAME = "sys_dict";
  23 + /** 字典值表 */
  24 + public static final String DICT_ITEM_TABLE_NAME = "sys_dict_item";
  25 + /** 消息字典表 */
  26 + public static final String MESSAGE_CONFIG_TABLE_NAME = "message_config";
  27 + /** 消息模板表 */
  28 + public static final String MESSAGE_TEMPLATE_TABLE_NAME = "message_template";
  29 + /** 短信发送记录表 */
  30 + public static final String SMS_LOG_TABLE_NAME = "sms_log";
  31 + /** 邮件发送记录表 */
  32 + public static final String MAIL_LOG_TABLE_NAME = "mail_log";
  33 + /** 限流表 */
  34 + public static final String RATE_LIMIT_TABLE_NAME = "sys_rate_limit";
  35 + /** 系统部门表 */
  36 + public static final String DEPT_TABLE_NAME = "sys_dept";
  37 + /** 组织表 */
  38 + public static final String IOTFS_ORGANIZATION_TABLE_NAME = "iotfs_organization";
  39 + /** 用户与组织映射表 */
  40 + public static final String IOTFS_USER_ORGANIZATION_MAPPING_TABLE_NAME = "iotfs_user_organization_mapping";
  41 + /** 设备表 */
  42 + public static final String IOTFS_DEVICE_TABLE_NAME = "iotfs_device";
  43 + /** 设备配置表 */
  44 + public static final String IOTFS_DEVICE_PROFILE_TABLE_NAME = "iotfs_device_profile";
  45 + /** 设备类型表 */
  46 + public static final String IOTFS_DEVICE_TYPE_TABLE_NAME = "iotfs_device_type";
  47 + /** 告警配置表 */
  48 + public static final String IOTFS_ALARM_PROFILE_TABLE_NAME = "iotfs_alarm_profile";
  49 + /** 告警联系人 */
  50 + public static final String IOTFS_ALARM_CONTACT_TABLE_NAME = "iotfs_alarm_contact";
  51 + }
  52 +
  53 + public static class TableFields {
  54 + public static final String TENANT_ID = "tenant_id";
  55 + }
  56 +
  57 + public static class TablePropertyMapping {
  58 + public static final String ID = "id";
  59 + public static final String CREATE_TIME = "createTime";
  60 + public static final String UPDATE_TIME = "updateTime";
  61 + public static final String CREATOR = "creator";
  62 + public static final String UPDATER = "updater";
  63 + public static final String UPDATE = "update";
  64 + public static final String TENANT_CODE = "tenantCode";
  65 + public static final String PASSWORD = "password";
  66 + public static final String ACTIVATE_TOKEN = "activateToken";
  67 + public static final String TB_DEVICE_ID = "tbDeviceId";
  68 + public static final String DEVICE_STATE = "deviceState";
  69 + public static final String ACTIVE_TIME = "activeTime";
  70 + }
  71 +
  72 + public static class AdminSettingConfigKey {
  73 + public static final String GENERAL_SETTING = "general";
  74 + }
  75 +}
  1 +package org.thingsboard.server.common.data.yunteng.constant;
  2 +
  3 +public class QueryConstant {
  4 + public static final String PAGE_SIZE = "pageSize";
  5 + public static final String PAGE = "page";
  6 + public static final String ORDER_FILED = "orderFiled";
  7 + public static final String ORDER_TYPE = "orderType";
  8 + public static final String CREATE_TIME="createTime";
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.constant;
  2 +
  3 +public final class SecurityConstant {
  4 + public static final String ROLE="role";
  5 + public static final String USER_ID="userId";
  6 + public static final String USER_NAME="username";
  7 + public static final String DISPLAY_NAME="displayName";
  8 + public static final String TENANT_CODE ="tenantCode";
  9 + public static final String TENANT_NAME="tenantName";
  10 + public static final String JWT_TOKEN_HEADER_PARAM="X-Authorization";
  11 +}
  1 +package org.thingsboard.server.common.data.yunteng.core;
  2 +
  3 +public enum RequestMethod {
  4 + GET,
  5 + HEAD,
  6 + POST,
  7 + PUT,
  8 + PATCH,
  9 + DELETE,
  10 + OPTIONS,
  11 + TRACE
  12 +}
  1 +package org.thingsboard.server.common.data.yunteng.core;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +import org.springframework.util.Assert;
  7 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  8 +
  9 +import java.io.Serializable;
  10 +
  11 +@Data
  12 +@AllArgsConstructor
  13 +@NoArgsConstructor
  14 +public class Result implements Serializable {
  15 + private static final long serialVersionUID = -7460365055472356522L;
  16 + private String msg = "success";
  17 + private int code = -1;
  18 + private Object data;
  19 +
  20 + public static Result ok(Object data) {
  21 + return new Result("success", 0, data);
  22 + }
  23 +
  24 + public static Result error() {
  25 + return error(ErrorMessage.OPERATION_FAILED.getCode(), ErrorMessage.OPERATION_FAILED);
  26 + }
  27 +
  28 + public static Result error(ErrorMessage ntlErrorMessage) {
  29 + return error(ntlErrorMessage.getCode(), ntlErrorMessage);
  30 + }
  31 +
  32 + public static Result error(int code, ErrorMessage ntlErrorMessage) {
  33 + Assert.isTrue(code != 0, "error code should not be zero in error response!");
  34 + return new Result(ntlErrorMessage.getMessage(), code, null);
  35 + }
  36 +
  37 + public static Result error(String msg) {
  38 + return new Result(msg, -1, null);
  39 + }
  40 +
  41 + public static Result error(int code, String msg) {
  42 + Assert.isTrue(code != 0, "error code should not be zero in error response!");
  43 + return new Result(msg, code, null);
  44 + }
  45 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.cache;
  2 +
  3 +import org.springframework.cache.CacheManager;
  4 +import org.springframework.stereotype.Component;
  5 +
  6 +import java.util.Objects;
  7 +import java.util.Optional;
  8 +
  9 +@Component
  10 +public class CacheUtils {
  11 +
  12 + private final String COMMON_STORE_AREA = "yun-teng-iot-common";
  13 +
  14 + private final CacheManager cacheManager;
  15 +
  16 + public CacheUtils(CacheManager cacheManager) {
  17 + this.cacheManager = cacheManager;
  18 + }
  19 +
  20 + public void put(String key, Object value) {
  21 + Objects.requireNonNull(cacheManager.getCache(COMMON_STORE_AREA)).put(key, value);
  22 + }
  23 +
  24 + public void put(String cacheName, String key, Object value) {
  25 + Objects.requireNonNull(cacheManager.getCache(cacheName)).put(key, value);
  26 + }
  27 +
  28 + public void invalidateCacheName(String cacheName) {
  29 + Objects.requireNonNull(cacheManager.getCache(cacheName)).invalidate();
  30 + }
  31 + public void invalidate(String key) {
  32 + Objects.requireNonNull(cacheManager.getCache(COMMON_STORE_AREA)).evictIfPresent(key);
  33 + }
  34 +
  35 + public void invalidate(String cacheName, String key) {
  36 + Objects.requireNonNull(cacheManager.getCache(cacheName)).evictIfPresent(key);
  37 + }
  38 +
  39 + @SuppressWarnings("unchecked")
  40 + public <T> Optional<T> get(String key) {
  41 + return Optional.ofNullable(
  42 + Objects.requireNonNull(cacheManager.getCache(COMMON_STORE_AREA)).get(key))
  43 + .map(v -> (T) v.get());
  44 + }
  45 +
  46 + @SuppressWarnings("unchecked")
  47 + public <T> Optional<T> get(String cacheName, String key) {
  48 + return Optional.ofNullable(Objects.requireNonNull(cacheManager.getCache(cacheName)).get(key))
  49 + .map(v -> (T) v.get());
  50 + }
  51 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.event;
  2 +
  3 +import org.springframework.context.ApplicationContext;
  4 +import org.springframework.context.ApplicationEvent;
  5 +
  6 +public class RateLimitChangeEvent extends ApplicationEvent {
  7 + private static final long serialVersionUID = 5948179374091197232L;
  8 +
  9 + /**
  10 + * Create a new ContextStartedEvent.
  11 + *
  12 + * @param source the {@code ApplicationContext} that the event is raised for (must not be {@code
  13 + * null})
  14 + */
  15 + public RateLimitChangeEvent(ApplicationContext source) {
  16 + super(source);
  17 + }
  18 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +public class DTOCreationException extends RuntimeException {
  4 +
  5 + private static final long serialVersionUID = 5255597864949518781L;
  6 +
  7 + public DTOCreationException(String message) {
  8 + super(message);
  9 + }
  10 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +import lombok.Getter;
  4 +
  5 +public class DataValidationException extends RuntimeException {
  6 + private static final long serialVersionUID = 3556952261254572635L;
  7 +
  8 + @Getter public boolean log = false;
  9 +
  10 + public DataValidationException(String message) {
  11 + super(message);
  12 + }
  13 +
  14 + public DataValidationException(String message, boolean log) {
  15 + super(message);
  16 + this.log = log;
  17 + }
  18 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +public class EntityCreationException extends RuntimeException {
  4 +
  5 + private static final long serialVersionUID = 5255597864949518781L;
  6 +
  7 + public EntityCreationException(String message) {
  8 + super(message);
  9 + }
  10 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +import lombok.Getter;
  4 +import org.springframework.http.HttpStatus;
  5 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  6 +
  7 +public class FastIotException extends RuntimeException {
  8 + private static final long serialVersionUID = 4036257507478854844L;
  9 +
  10 + @Getter private final HttpStatus httpStatus;
  11 +
  12 + @Getter private final ErrorMessage error;
  13 +
  14 + public FastIotException(ErrorMessage errorMessage) {
  15 + super(errorMessage.getMessage());
  16 + this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
  17 + this.error = errorMessage;
  18 + }
  19 +
  20 + public FastIotException(ErrorMessage errorMessage, HttpStatus httpStatus) {
  21 + super(errorMessage.getMessage());
  22 + this.httpStatus = httpStatus;
  23 + this.error = errorMessage;
  24 + }
  25 +
  26 + public FastIotException() {
  27 + super(ErrorMessage.INTERNAL_ERROR.getMessage());
  28 + this.error = ErrorMessage.INTERNAL_ERROR;
  29 + this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
  30 + }
  31 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +public class FileNotFoundException extends RuntimeException{
  4 + private static final long serialVersionUID = 3466865879043055822L;
  5 +
  6 + public FileNotFoundException(String message) {
  7 + super(message);
  8 + }
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +public class FileStorageException extends RuntimeException{
  4 + private static final long serialVersionUID = -8866081834891143120L;
  5 +
  6 + public FileStorageException(String message) {
  7 + super(message);
  8 + }
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +public class NoneTenantAssetException extends RuntimeException {
  4 + private static final long serialVersionUID = 9135599998185288967L;
  5 +
  6 + public NoneTenantAssetException(String message) {
  7 + super(message);
  8 + }
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.exception;
  2 +
  3 +public class TooManyRequestException extends RuntimeException {
  4 + private static final long serialVersionUID = 1055141330426574861L;
  5 +
  6 + public TooManyRequestException() {
  7 + super();
  8 + }
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.message;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +
  5 +@JsonFormat(shape = JsonFormat.Shape.OBJECT)
  6 +public enum ErrorMessage {
  7 + // ERROR STARTS FROM HERE
  8 + INTERNAL_ERROR(500000, "internal error"),
  9 + OPERATION_FAILED(500001, "operation failed"),
  10 + NO_PERMISSION(403001, "no permission"),
  11 + ACCOUNT_DISABLED(403002, "account disabled"),
  12 + ACCESS_DENIED(403003, "access denied"),
  13 + AUTHENTICATION_METHOD_NOT_SUPPORTED(403004, "authentication method not supported"),
  14 + USERNAME_PASSWORD_INCORRECT(401001, "incorrect username or password"),
  15 + TOKEN_EXPIRED(401002, "token has expired"),
  16 + NONE_TENANT_ASSET(401003, "not current tenant asset"),
  17 + AUTHENTICATION_FAILED_ACCOUNT_EXPIRED(401003, "account has expired"),
  18 + BAD_PARAMETER(400000, "query parameters not valid"),
  19 + INVALID_PARAMETER(400001, "invalid parameters"),
  20 + TOO_MANY_REQUEST(429001, "too many requests"),
  21 + EXIST_ENABLE_TEMPLATE(400002,"存在已启用相同类型及用途的模板"),
  22 + NOT_SET_PASSWORD_TEMPLATE(400003,"未设置用于密码重置的模板"),
  23 + PROVIDE_CORRECT_PHONE_NUMBER(400004,"请提供正确的电话号码"),
  24 + PROVIDE_CORRECT_EMAIL(400005,"请提供正确的邮箱"),
  25 + PHONE_NUMBER_OR_EMAIL_REQUIRED(400006,"必须提供电话或者邮箱"),
  26 + NAME_ALREADY_EXISTS(400007,"名称已存在"),
  27 + ROLE_IN_USE(400008,"该角色还存在用户使用"),
  28 + NONE_DEFAULT_RULE_CHAIN(400009,"该租户不存在默认的规则链"),
  29 + TENANT_MISMATCHING(400010,"租户不匹配"),
  30 + GET_CURRENT_USER_EXCEPTION(400011,"获取当前用户信息异常"),
  31 + CONNECT_TO_TB_ERROR(500001,"与TB联系错误"),
  32 + HAVE_NO_PERMISSION(500002,"没有修改权限");
  33 + private final int code;
  34 + private String message;
  35 +
  36 + ErrorMessage(int code, String message) {
  37 + this.code = code;
  38 + this.message = message;
  39 + }
  40 +
  41 + public ErrorMessage setMessage(String message) {
  42 + this.message = message;
  43 + return this;
  44 + }
  45 +
  46 + public int getCode() {
  47 + return code;
  48 + }
  49 +
  50 + public String getMessage() {
  51 + return message;
  52 + }
  53 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.utils;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.boot.context.properties.ConfigurationProperties;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +@ConfigurationProperties(prefix = "file.storage.local")
  8 +@Component
  9 +@Data
  10 +public class FileStorageProperties {
  11 + private String type;
  12 + private String uploadDir;
  13 + private String downloadPath;
  14 + private String uploadPath;
  15 + private boolean randomFileName;
  16 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.utils;
  2 +
  3 +
  4 +import org.springframework.http.ResponseEntity;
  5 +import org.springframework.web.multipart.MultipartFile;
  6 +import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse;
  7 +
  8 +import javax.servlet.http.HttpServletRequest;
  9 +import javax.servlet.http.HttpServletResponse;
  10 +
  11 +public interface FileStorageService {
  12 +
  13 + /**
  14 + * 上传文件
  15 + *
  16 + * @param file 待上传文件
  17 + * @return {@link FileUploadResponse} 实例对象
  18 + */
  19 + FileUploadResponse upload(MultipartFile file);
  20 +
  21 + /**
  22 + * 下载文件
  23 + *
  24 + * @param fileName 待下载文件名
  25 + * @param response {@link HttpServletResponse}
  26 + */
  27 + ResponseEntity<?> download(
  28 + String fileName, HttpServletRequest request, HttpServletResponse response);
  29 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.utils;
  2 +
  3 +import lombok.extern.slf4j.Slf4j;
  4 +import org.apache.commons.lang3.RandomStringUtils;
  5 +import org.springframework.beans.factory.annotation.Autowired;
  6 +import org.springframework.beans.factory.annotation.Value;
  7 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  8 +import org.springframework.core.io.Resource;
  9 +import org.springframework.core.io.UrlResource;
  10 +import org.springframework.http.HttpHeaders;
  11 +import org.springframework.http.MediaType;
  12 +import org.springframework.http.ResponseEntity;
  13 +import org.springframework.stereotype.Service;
  14 +import org.springframework.util.StringUtils;
  15 +import org.springframework.web.multipart.MultipartFile;
  16 +import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
  17 +import org.thingsboard.server.common.data.yunteng.core.exception.FileNotFoundException;
  18 +import org.thingsboard.server.common.data.yunteng.core.exception.FileStorageException;
  19 +import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse;
  20 +
  21 +import javax.servlet.http.HttpServletRequest;
  22 +import javax.servlet.http.HttpServletResponse;
  23 +import java.io.IOException;
  24 +import java.net.MalformedURLException;
  25 +import java.nio.file.Files;
  26 +import java.nio.file.Path;
  27 +import java.nio.file.Paths;
  28 +import java.nio.file.StandardCopyOption;
  29 +import java.util.Objects;
  30 +
  31 +@Service
  32 +@Slf4j
  33 +@ConditionalOnExpression("'${file.storage.type}'=='local'")
  34 +public class LocalFileStorageService implements FileStorageService {
  35 +
  36 + private final FileStorageProperties fileStorageProperties;
  37 + private final Path fileStorageLocation;
  38 +
  39 + @Value("${file.storage.local.staticUrl}")
  40 + private String ossFileUrl;
  41 +
  42 + @Autowired
  43 + public LocalFileStorageService(FileStorageProperties fileStorageProperties) {
  44 + this.fileStorageProperties = fileStorageProperties;
  45 + this.fileStorageLocation =
  46 + Paths.get(fileStorageProperties.getUploadDir()).toAbsolutePath().normalize();
  47 + try {
  48 + Files.createDirectories(this.fileStorageLocation);
  49 + } catch (Exception e) {
  50 + throw new RuntimeException(
  51 + "Could not create the directory where the uploaded files will be stored.");
  52 + }
  53 + }
  54 +
  55 + public String storeFile(MultipartFile file) {
  56 + // Normalize file name
  57 + String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
  58 +
  59 + try {
  60 + // random fileName if needed
  61 + if (fileStorageProperties.isRandomFileName()) {
  62 + if (fileName.contains(".")) {
  63 + fileName =
  64 + RandomStringUtils.randomAlphabetic(15)
  65 + + fileName.substring(fileName.lastIndexOf("."));
  66 + } else {
  67 + fileName = RandomStringUtils.randomAlphabetic(15);
  68 + }
  69 + }
  70 + // Check if the file's name contains invalid characters
  71 + if (fileName.contains("..")) {
  72 + throw new FileStorageException(
  73 + "Sorry! Filename contains invalid path sequence " + fileName);
  74 + }
  75 +
  76 + // Copy file to the target location (Replacing existing file with the same name)
  77 + Path targetLocation = this.fileStorageLocation.resolve(fileName);
  78 + Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
  79 +
  80 + return fileName;
  81 + } catch (IOException ex) {
  82 + throw new FileStorageException("Could not store file " + fileName + ". Please try again!");
  83 + }
  84 + }
  85 +
  86 + public Resource loadFileAsResource(String fileName) {
  87 + try {
  88 + Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
  89 + Resource resource = new UrlResource(filePath.toUri());
  90 + if (resource.exists()) {
  91 + return resource;
  92 + } else {
  93 + throw new FileNotFoundException("File not found " + fileName);
  94 + }
  95 + } catch (MalformedURLException ex) {
  96 + throw new FileNotFoundException("File not found " + fileName);
  97 + }
  98 + }
  99 +
  100 + @Override
  101 + public FileUploadResponse upload(MultipartFile file) {
  102 + String fileName = this.storeFile(file);
  103 + String fileDownloadPath =
  104 + ServletUriComponentsBuilder.fromCurrentRequestUri()
  105 + .path(fileStorageProperties.getDownloadPath())
  106 + .path(fileName)
  107 + .toUriString();
  108 + String realDownloadPath = fileDownloadPath.replace(fileStorageProperties.getUploadPath(), "");
  109 + String ossStaticPath =
  110 + ServletUriComponentsBuilder.fromCurrentContextPath().toUriString() + ossFileUrl;
  111 + ossStaticPath = ossStaticPath.replace("**", fileName);
  112 + return new FileUploadResponse(
  113 + fileName, realDownloadPath, file.getContentType(), file.getSize(), ossStaticPath);
  114 + }
  115 +
  116 + @Override
  117 + public ResponseEntity<?> download(
  118 + String fileName, HttpServletRequest request, HttpServletResponse response) {
  119 + Resource resource = this.loadFileAsResource(fileName);
  120 + String contentType = null;
  121 + try {
  122 + contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
  123 + } catch (IOException ex) {
  124 + log.info("Could not determine file type.");
  125 + }
  126 +
  127 + // Fallback to the default content type if type could not be determined
  128 + if (contentType == null) {
  129 + contentType = "application/octet-stream";
  130 + }
  131 +
  132 + return ResponseEntity.ok()
  133 + .contentType(MediaType.parseMediaType(contentType))
  134 + .header(
  135 + HttpHeaders.CONTENT_DISPOSITION,
  136 + "attachment; filename=\"" + resource.getFilename() + "\"")
  137 + .body(resource);
  138 + }
  139 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.utils;
  2 +
  3 +import lombok.Data;
  4 +import org.springframework.boot.context.properties.ConfigurationProperties;
  5 +import org.springframework.stereotype.Component;
  6 +
  7 +/**
  8 + * @author 徐浩然
  9 + * @desc minio配置文件
  10 + * @date 2021/12/1-15:35
  11 + */
  12 +@ConfigurationProperties(prefix = "file.storage.minio")
  13 +@Component
  14 +@Data
  15 +public class MinioFileStorageProperties {
  16 + /** minio储存地址 */
  17 + private String minioUrl;
  18 + /** minio账户 */
  19 + private String minioName;
  20 + /** minio访问密码 */
  21 + private String minioPass;
  22 + /** minio储存桶名称 */
  23 + private String bucketName;
  24 +
  25 + private boolean randomFileName;
  26 +}
  1 +package org.thingsboard.server.common.data.yunteng.core.utils;
  2 +
  3 +import io.minio.*;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.commons.lang3.RandomStringUtils;
  6 +import org.jetbrains.annotations.NotNull;
  7 +import org.springframework.beans.factory.annotation.Autowired;
  8 +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  9 +import org.springframework.http.HttpHeaders;
  10 +import org.springframework.http.HttpStatus;
  11 +import org.springframework.http.ResponseEntity;
  12 +import org.springframework.stereotype.Service;
  13 +import org.springframework.util.StringUtils;
  14 +import org.springframework.web.context.request.RequestContextHolder;
  15 +import org.springframework.web.context.request.ServletRequestAttributes;
  16 +import org.springframework.web.multipart.MultipartFile;
  17 +import org.thingsboard.server.common.data.yunteng.core.exception.FileStorageException;
  18 +import org.thingsboard.server.common.data.yunteng.dto.FileUploadResponse;
  19 +
  20 +import javax.servlet.http.HttpServletRequest;
  21 +import javax.servlet.http.HttpServletResponse;
  22 +import java.io.InputStream;
  23 +import java.io.OutputStream;
  24 +import java.util.Objects;
  25 +
  26 +@Service
  27 +@Slf4j
  28 +@ConditionalOnExpression("'${file.storage.type}'=='minio'")
  29 +public class MinioFileStorageService implements FileStorageService {
  30 +
  31 + private final MinioFileStorageProperties fileStorageProperties;
  32 + private MinioClient minioClient;
  33 +
  34 + @Autowired
  35 + public MinioFileStorageService(MinioFileStorageProperties fileStorageProperties) {
  36 + this.fileStorageProperties = fileStorageProperties;
  37 + // 创建客户端对象
  38 + this.minioClient =
  39 + MinioClient.builder()
  40 + .endpoint(fileStorageProperties.getMinioUrl())
  41 + .credentials(fileStorageProperties.getMinioName(), fileStorageProperties.getMinioPass())
  42 + .build();
  43 + // 创建储存桶
  44 + checkBucket();
  45 + }
  46 +
  47 + // 储存文件
  48 + public String storeFile(MultipartFile file) {
  49 + // Normalize file name
  50 + String fileName = StringUtils.cleanPath(Objects.requireNonNull(file.getOriginalFilename()));
  51 + // random fileName if needed
  52 + if (fileStorageProperties.isRandomFileName()) {
  53 + if (fileName.contains(".")) {
  54 + fileName =
  55 + RandomStringUtils.randomAlphabetic(15) + fileName.substring(fileName.lastIndexOf("."));
  56 + } else {
  57 + fileName = RandomStringUtils.randomAlphabetic(15);
  58 + }
  59 + }
  60 + // Check if the file's name contains invalid characters
  61 + if (fileName.contains("..")) {
  62 + throw new FileStorageException("Sorry! Filename contains invalid path sequence " + fileName);
  63 + }
  64 +
  65 + // 储存
  66 + try {
  67 + checkBucket();
  68 + PutObjectArgs build =
  69 + PutObjectArgs.builder()
  70 + .bucket(fileStorageProperties.getBucketName())
  71 + .object(fileName)
  72 + .contentType(file.getContentType())
  73 + .stream(file.getInputStream(), file.getInputStream().available(), -1)
  74 + .build();
  75 + minioClient.putObject(build);
  76 + return fileName;
  77 + } catch (Exception ex) {
  78 + ex.printStackTrace();
  79 + throw new FileStorageException("Could not store file " + fileName + ". Please try again!");
  80 + }
  81 + }
  82 +
  83 + @Override
  84 + public FileUploadResponse upload(MultipartFile file) {
  85 + String fileName = this.storeFile(file);
  86 + String staticPath = getPath(fileName);
  87 + String realDownloadPath = null;
  88 + try {
  89 + // 获取request
  90 + HttpServletRequest request =
  91 + ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  92 + // 生成下载接口的地址
  93 + realDownloadPath =
  94 + request.getRequestURL().toString().replace("upload", "downloadFile/" + fileName);
  95 + } catch (Exception e) {
  96 + e.printStackTrace();
  97 + log.info("Could not upload file " + fileName + ". Please try again!");
  98 + }
  99 + return new FileUploadResponse(
  100 + fileName, realDownloadPath, file.getContentType(), file.getSize(), staticPath);
  101 + }
  102 +
  103 + @Override
  104 + public ResponseEntity<?> download(
  105 + String fileName, HttpServletRequest request, HttpServletResponse response) {
  106 + // get object given the bucket and object name
  107 + try (
  108 + // 获取文件流
  109 + InputStream inputStream =
  110 + minioClient.getObject(
  111 + GetObjectArgs.builder()
  112 + .bucket(fileStorageProperties.getBucketName())
  113 + .object(fileName)
  114 + .build());
  115 + // 获取输出流
  116 + OutputStream outputStream = response.getOutputStream(); ) {
  117 + // 清空
  118 + response.reset();
  119 + // 写入流
  120 + byte[] buffer = inputStream.readAllBytes();
  121 + outputStream.write(buffer);
  122 + outputStream.flush();
  123 + // 配置header
  124 + response.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
  125 + response.addHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(buffer.length));
  126 + return ResponseEntity.status(HttpStatus.OK).body("download...");
  127 + } catch (Exception e) {
  128 + // 找不到文件时会抛出异常
  129 + String err = fileName + "file not found";
  130 + log.info(err);
  131 + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(err);
  132 + }
  133 + }
  134 +
  135 + // 检查储存桶情况
  136 + private void checkBucket() {
  137 + try {
  138 + // 桶是否存在
  139 + boolean exists =
  140 + minioClient.bucketExists(
  141 + BucketExistsArgs.builder().bucket(fileStorageProperties.getBucketName()).build());
  142 + if (!exists) {
  143 + // 不存在创建
  144 + minioClient.makeBucket(
  145 + MakeBucketArgs.builder().bucket(fileStorageProperties.getBucketName()).build());
  146 + // 设置储存桶策略
  147 + String str =
  148 + "{\"Statement\": [{\"Action\": [\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Effect\": \"Allow\",\"Principal\": \"*\",\"Resource\": \"arn:aws:s3:::%\"},{\"Action\": \"s3:GetObject\",\"Effect\": \"Allow\",\"Principal\": \"*\",\"Resource\": \"arn:aws:s3:::%/*\"}],\"Version\": \"2012-10-17\"}";
  149 + String replace = str.replace("%", fileStorageProperties.getBucketName());
  150 + minioClient.setBucketPolicy(
  151 + SetBucketPolicyArgs.builder()
  152 + .bucket(fileStorageProperties.getBucketName())
  153 + .config(replace)
  154 + .build());
  155 + }
  156 + } catch (Exception e) {
  157 + log.error(e.getMessage(), e);
  158 + }
  159 + }
  160 +
  161 + /**
  162 + * @param fileName 文件名
  163 + * @return 文件访问地址
  164 + */
  165 + @NotNull
  166 + private String getPath(String fileName) {
  167 + return fileStorageProperties
  168 + .getMinioUrl()
  169 + .concat("/")
  170 + .concat(fileStorageProperties.getBucketName())
  171 + .concat("/")
  172 + .concat(fileName);
  173 + }
  174 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +@Data
  6 +public class AlarmProfileDTO extends TenantDTO {
  7 + /** 告警联系人 通知多人“,”号分隔 */
  8 + private String alarmContactId;
  9 + /** 设备配置ID */
  10 + private String deviceProfileId;
  11 + /** 消息通知方式:多种方式“,”号分隔 MessageTypeEnum */
  12 + private String messageMode;
  13 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +
  4 +import com.fasterxml.jackson.annotation.JsonFormat;
  5 +import com.fasterxml.jackson.annotation.JsonIgnore;
  6 +import com.fasterxml.jackson.annotation.JsonInclude;
  7 +import lombok.Data;
  8 +import org.springframework.beans.BeanUtils;
  9 +import org.thingsboard.server.common.data.yunteng.common.UpdateGroup;
  10 +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants;
  11 +import org.thingsboard.server.common.data.yunteng.core.exception.EntityCreationException;
  12 +import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils;
  13 +
  14 +import javax.validation.constraints.NotEmpty;
  15 +import java.lang.reflect.Constructor;
  16 +import java.lang.reflect.InvocationTargetException;
  17 +import java.time.LocalDateTime;
  18 +
  19 +@Data
  20 +@JsonInclude(JsonInclude.Include.NON_NULL)
  21 +public class BaseDTO {
  22 + @NotEmpty(message = "ID不能为空或者空字符串",groups = {UpdateGroup.class})
  23 + private String id;
  24 + /**创建用户*/
  25 + private String creator;
  26 + /**创建时间*/
  27 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  28 + private LocalDateTime createTime;
  29 + /**更新用户*/
  30 + private String updater;
  31 + /**更新时间*/
  32 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  33 + private LocalDateTime updateTime;
  34 + @JsonIgnore
  35 + public <E> void copyToEntity(E entity, String... ignoreProperties) {
  36 + if (ignoreProperties.length == 0) {
  37 + BeanUtils.copyProperties(
  38 + this,
  39 + entity,
  40 + ModelConstants.TablePropertyMapping.CREATE_TIME,
  41 + ModelConstants.TablePropertyMapping.UPDATE_TIME,
  42 + ModelConstants.TablePropertyMapping.CREATOR,
  43 + ModelConstants.TablePropertyMapping.UPDATER);
  44 + } else {
  45 + BeanUtils.copyProperties(this, entity, ignoreProperties);
  46 + }
  47 + }
  48 +
  49 + @JsonIgnore
  50 + @SuppressWarnings("unchecked")
  51 + public <E> E getEntity(Class<E> clazz) {
  52 + Constructor<?> constructor = ReflectUtils.getEmptyParameterConstructor(clazz);
  53 + if (constructor != null) {
  54 + try {
  55 + E e = (E) constructor.newInstance();
  56 + BeanUtils.copyProperties(this, e);
  57 + return e;
  58 + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
  59 + throw new EntityCreationException(
  60 + "try to get entity from class [" + clazz.getName() + "] failed " + e.getMessage());
  61 + }
  62 + } else {
  63 + throw new EntityCreationException(
  64 + "try to get entity from class [" + clazz.getName() + "] failed");
  65 + }
  66 + }
  67 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.Data;
  4 +import org.thingsboard.server.common.data.yunteng.common.DeleteGroup;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +import javax.validation.constraints.Size;
  8 +import java.util.Set;
  9 +
  10 +@Data
  11 +public class DeleteDTO {
  12 + /** 删除主键IDS */
  13 + @NotNull(
  14 + message = "IDS不能为空",
  15 + groups = {DeleteGroup.class})
  16 + @Size(
  17 + min = 1,
  18 + message = "删除至少需要一个id",
  19 + groups = {DeleteGroup.class})
  20 + private Set<String> ids;
  21 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.fasterxml.jackson.annotation.JsonIgnore;
  5 +import com.fasterxml.jackson.databind.JsonNode;
  6 +import io.swagger.annotations.ApiModelProperty;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import org.thingsboard.server.common.data.security.DeviceCredentialsType;
  10 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  11 +import org.thingsboard.server.common.data.yunteng.enums.DeviceState;
  12 +import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum;
  13 +
  14 +import javax.validation.constraints.NotEmpty;
  15 +import javax.validation.constraints.NotNull;
  16 +import java.time.LocalDateTime;
  17 +
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@Data
  20 +public class DeviceDTO extends TenantDTO {
  21 + private String name;
  22 + /**
  23 + * 包含字段:
  24 + *
  25 + * <ul/>
  26 + * <li>gateway 网关,bool类型
  27 + * <li>description 描述字段
  28 + */
  29 + private JsonNode deviceInfo;
  30 +
  31 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  32 + private LocalDateTime activeTime;
  33 +
  34 + private DeviceState deviceState = DeviceState.INACTIVE;
  35 +
  36 + @NotEmpty(
  37 + message = "设备配置ID不能为空或者空字符串",
  38 + groups = {AddGroup.class})
  39 + @ApiModelProperty(value = "设备配置", required = true)
  40 + private String profileId;
  41 +
  42 + @NotEmpty(
  43 + message = "设备唯一编号不能为空或空字符串",
  44 + groups = {AddGroup.class})
  45 + @ApiModelProperty(value = "设备唯一编号", required = true)
  46 + private String deviceToken;
  47 + // 不用序列化给前端
  48 + @JsonIgnore private String tbDeviceId;
  49 + private String deviceTypeId;
  50 +
  51 + @NotEmpty(
  52 + message = "所属组织不能为空或者空字符串",
  53 + groups = {AddGroup.class})
  54 + @ApiModelProperty(value = "设备组织", required = true)
  55 + private String organizationId;
  56 + /** 标签 */
  57 + private String label;
  58 +
  59 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  60 + private LocalDateTime lastConnectTime;
  61 +
  62 + private DeviceProfileDTO deviceProfile;
  63 + private OrganizationDTO organizationDTO;
  64 +
  65 + @NotNull(
  66 + message = "设备类型不能为空",
  67 + groups = {AddGroup.class})
  68 + @ApiModelProperty(value = "设备类型:GATEWAY,DIRECT_CONNECTION,SENSOR", required = true)
  69 + private DeviceTypeEnum deviceType;
  70 + /** 设备凭证 */
  71 + private DeviceCredentialsType deviceCredentials;
  72 + /** 告警状态:0:正常 1:告警 */
  73 + private Integer alarmStatus;
  74 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.databind.JsonNode;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import org.thingsboard.server.common.data.DeviceTransportType;
  8 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  9 +
  10 +import javax.validation.constraints.NotEmpty;
  11 +
  12 +@EqualsAndHashCode(callSuper = true)
  13 +@Data
  14 +public class DeviceProfileDTO extends TenantDTO {
  15 + @NotEmpty(message = "设备配置名称不能为空或者空字符串", groups = AddGroup.class)
  16 + @ApiModelProperty(value = "设备配置名称")
  17 + private String name;
  18 +
  19 + private String description;
  20 + /** 转换脚本:TCP才会使用 */
  21 + private String convertJs;
  22 +
  23 + @NotEmpty(message = "传输协议不能为空或者空字符串", groups = AddGroup.class)
  24 + @ApiModelProperty(value = "传输协议", required = true)
  25 + @NotEmpty(message = "传输协议不能为空或者二空字符串")
  26 + private DeviceTransportType transportType;
  27 + /** TB的设备配置文件 */
  28 + private String tbProfileId;
  29 +
  30 + private JsonNode alarms;
  31 + /** 告警配置 */
  32 + private AlarmProfileDTO alarmProfile;
  33 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +
  6 +@Data
  7 +@AllArgsConstructor
  8 +public class FileUploadResponse {
  9 + private String fileName;
  10 + private String fileDownloadUri;
  11 + private String fileType;
  12 + private long size;
  13 + private String fileStaticUri;
  14 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.fasterxml.jackson.annotation.JsonIgnore;
  5 +import com.fasterxml.jackson.annotation.JsonInclude;
  6 +import com.fasterxml.jackson.databind.JsonNode;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import org.thingsboard.server.common.data.yunteng.enums.MenuTypeEnum;
  10 +
  11 +import java.time.LocalDateTime;
  12 +import java.util.ArrayList;
  13 +import java.util.List;
  14 +import java.util.Objects;
  15 +
  16 +@EqualsAndHashCode(callSuper = true)
  17 +@Data
  18 +public class MenuDTO extends BaseDTO implements Comparable<MenuDTO> {
  19 + private String id;
  20 + /**
  21 + * if menu type is system default, the menu name can be null; if menu type is not system default,
  22 + * menu name is user defined
  23 + */
  24 + private String name;
  25 +
  26 + // @JsonIgnore
  27 + private String parentId;
  28 + private List<MenuDTO> children;
  29 + private String path;
  30 + // @JsonIgnore
  31 + private MenuTypeEnum type;
  32 + private String permission;
  33 + private Integer sort;
  34 + @JsonIgnore private String tenantCode;
  35 + private String component;
  36 + private JsonNode meta;
  37 + @JsonIgnore private String alias;
  38 +
  39 + @JsonInclude(JsonInclude.Include.NON_NULL)
  40 + private String redirect;
  41 +
  42 + @JsonInclude(JsonInclude.Include.NON_NULL)
  43 + private Boolean caseSensitive;
  44 +
  45 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  46 + private LocalDateTime createTime;
  47 +
  48 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  49 + private LocalDateTime updateTime;
  50 +
  51 + public MenuDTO() {
  52 + this.children = new ArrayList<>();
  53 + }
  54 +
  55 + @Override
  56 + public int compareTo(MenuDTO o) {
  57 + return Objects.requireNonNullElse(this.getSort(), 0)
  58 + - Objects.requireNonNullElse(o.getSort(), 0);
  59 + }
  60 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.databind.JsonNode;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import org.thingsboard.server.common.data.yunteng.common.aspect.annotation.AutoDict;
  7 +
  8 +@EqualsAndHashCode(callSuper = false)
  9 +@Data
  10 +public class MessageConfigDTO extends TenantDTO {
  11 +
  12 + /** 配置名称 */
  13 + private String configName;
  14 + /** 短信平台类型 */
  15 + @AutoDict(dictCode = "platform_type")
  16 + private String platformType;
  17 +
  18 + /** 消息类型 */
  19 + @AutoDict(dictCode = "message_type")
  20 + private String messageType;
  21 +
  22 + /** json配置 */
  23 + private JsonNode config;
  24 +
  25 + /** 状态:0禁用 1启用 */
  26 + private Integer status;
  27 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.Data;
  4 +import lombok.EqualsAndHashCode;
  5 +import org.thingsboard.server.common.data.yunteng.common.aspect.annotation.AutoDict;
  6 +
  7 +@EqualsAndHashCode(callSuper = false)
  8 +@Data
  9 +public class MessageTemplateDTO extends TenantDTO {
  10 + /** 模板名称 */
  11 + private String templateName;
  12 +
  13 + /** 模板签名 */
  14 + private String signName;
  15 +
  16 + /** 模板CODE */
  17 + private String templateCode;
  18 +
  19 + /** 消息配置 */
  20 + private String messageConfigId;
  21 +
  22 + /**消息配置信息*/
  23 + private MessageConfigDTO messageConfig;
  24 +
  25 + /**消息类型*/
  26 + private String messageType;
  27 +
  28 + /** 模板用途 */
  29 + @AutoDict(dictCode = "template_purpose")
  30 + private String templatePurpose;
  31 +
  32 + /** 状态:0禁用 1启用 */
  33 + private Integer status;
  34 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import org.thingsboard.server.common.data.yunteng.utils.tree.TreeDTO;
  7 +
  8 +import java.util.ArrayList;
  9 +import java.util.List;
  10 +
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@Data
  13 +public class OrganizationDTO extends TenantDTO implements TreeDTO<OrganizationDTO> {
  14 + private String parentId;
  15 + private String name;
  16 + private int sort;
  17 + private List<OrganizationDTO> children;
  18 + private String remark;
  19 +
  20 + public OrganizationDTO() {
  21 + this.children = new ArrayList<>();
  22 + }
  23 +
  24 + @Override
  25 + public int compareTo(OrganizationDTO o) {
  26 + return this.getSort() - o.getSort();
  27 + }
  28 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +
  4 +import lombok.Data;
  5 +
  6 +@Data
  7 +public class PlainRolesDTO {
  8 + private String roleId;
  9 + private String roleName;
  10 +
  11 + @Override
  12 + public String toString() {
  13 + return "角色ID:" + roleId + " " + "角色名:" + roleName;
  14 + }
  15 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonAlias;
  4 +import com.fasterxml.jackson.annotation.JsonFormat;
  5 +import com.fasterxml.jackson.annotation.JsonProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +
  9 +import java.time.LocalDateTime;
  10 +
  11 +@EqualsAndHashCode(callSuper = true)
  12 +@Data
  13 +public class RoleDTO extends TenantDTO {
  14 + private String name;
  15 + private String remark;
  16 + private LocalDateTime createTime;
  17 + private String roleType;
  18 + private String code;
  19 + @JsonFormat(shape = JsonFormat.Shape.NUMBER)
  20 + @JsonAlias({"status", "enabled"})
  21 + @JsonProperty("status")
  22 + private boolean enabled = true;
  23 + private String[] roleIds;
  24 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.Data;
  4 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +
  8 +@Data
  9 +public class SysDictDTO extends TenantDTO{
  10 +
  11 + /** 字典名称 */
  12 + @NotEmpty(message = "字典名称不能为空或空字符串",groups = {AddGroup.class})
  13 + private String dictName;
  14 +
  15 + /** 字典编码 */
  16 + @NotEmpty(message = "字典编码不能为空或空字符串",groups = {AddGroup.class})
  17 + private String dictCode;
  18 +
  19 + /** 字典描述 */
  20 + private String description;
  21 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.Data;
  4 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +
  8 +@Data
  9 +public class SysDictItemDTO extends BaseDTO{
  10 + /** 字典ID */
  11 + @NotEmpty(message = "字典表ID不能为空或空字符串",groups = {AddGroup.class})
  12 + private String dictId;
  13 +
  14 + /** 字典文本 */
  15 + @NotEmpty(message = "字典Item文本不能为空或空字符串",groups = {AddGroup.class})
  16 + private String itemText;
  17 +
  18 + /** 字典值 */
  19 + @NotEmpty(message = "字典Item文本值不能为空或空字符串",groups = {AddGroup.class})
  20 + private String itemValue;
  21 +
  22 + /** 字典描述 */
  23 + private String description;
  24 +
  25 + /** 字典排序 默认排序1*/
  26 + private Integer sort;
  27 +
  28 + /** 字典状态 默认状态1 启用*/
  29 + private Integer status;
  30 +
  31 + /** 租户Code */
  32 + private String tenantCode;
  33 +
  34 + /**字典*/
  35 + private SysDictDTO sysDict;
  36 +
  37 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +
  4 +import com.fasterxml.jackson.annotation.JsonFormat;
  5 +import com.fasterxml.jackson.annotation.JsonInclude;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import org.thingsboard.server.common.data.yunteng.enums.TenantStatusEnum;
  9 +
  10 +import java.time.LocalDateTime;
  11 +
  12 +@EqualsAndHashCode(callSuper = false)
  13 +@Data
  14 +public class TenantDTO extends BaseDTO {
  15 + private String name;
  16 + private String icon;
  17 + private String tenantCode;
  18 + private boolean enabled;
  19 + private String description;
  20 + private String defaultConfig;
  21 + /** TB的租户ID */
  22 + private String tenantId;
  23 + /** 租户角色 */
  24 + private String[] roleIds;
  25 +
  26 + @JsonInclude(JsonInclude.Include.NON_NULL)
  27 + private TenantStatusEnum tenantStatus;
  28 +
  29 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  30 + private LocalDateTime tenantExpireTime;
  31 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.fasterxml.jackson.annotation.JsonInclude;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  8 +import org.thingsboard.server.common.data.yunteng.enums.UserStatusEnum;
  9 +
  10 +import javax.validation.constraints.NotEmpty;
  11 +import java.time.LocalDateTime;
  12 +import java.util.Set;
  13 +
  14 +@EqualsAndHashCode(callSuper = false)
  15 +@Data
  16 +public class UserDTO extends BaseDTO {
  17 +
  18 + @NotEmpty(message = "用户名不能为空或字符串", groups = AddGroup.class)
  19 + private String username;
  20 +
  21 + @NotEmpty(message = "姓名不能为空或字符串", groups = AddGroup.class)
  22 + private String realName;
  23 +
  24 + @JsonInclude(JsonInclude.Include.NON_NULL)
  25 + @NotEmpty(message = "密码不能为空或空字符串", groups = AddGroup.class)
  26 + private String password;
  27 +
  28 + @JsonInclude(JsonInclude.Include.NON_NULL)
  29 + private String activateToken;
  30 +
  31 + /** 所辖组织ids */
  32 + private String[] organizationIds;
  33 +
  34 + /** 角色ids */
  35 + private String[] roleIds;
  36 +
  37 + private String phoneNumber;
  38 + private String email;
  39 + private String avatar;
  40 + private boolean enabled;
  41 +
  42 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  43 + private LocalDateTime accountExpireTime;
  44 +
  45 + private boolean hasPassword;
  46 +
  47 + @JsonInclude(JsonInclude.Include.NON_NULL)
  48 + private String tenantCode;
  49 +
  50 + @JsonInclude(JsonInclude.Include.NON_NULL)
  51 + private String tenantName;
  52 +
  53 + @JsonInclude(JsonInclude.Include.NON_NULL)
  54 + private UserStatusEnum userStatusEnum;
  55 +
  56 + @JsonInclude(JsonInclude.Include.NON_NULL)
  57 + private Set<PlainRolesDTO> roles;
  58 +
  59 + private String deptId;
  60 +
  61 + /** 0:超级管理员;1:租户账号;2:租户下的账号 */
  62 + private Integer level;
  63 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.Data;
  4 +import org.thingsboard.server.common.data.yunteng.enums.RoleEnum;
  5 +
  6 +@Data
  7 +public class UserDetailRoleDTO {
  8 + private RoleEnum roleType;
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import java.io.Serializable;
  6 +import java.time.LocalDateTime;
  7 +import java.util.Set;
  8 +
  9 +/** for authentication */
  10 +@Data
  11 +public class UserDetailsDTO implements Serializable {
  12 +
  13 + private static final long serialVersionUID = -515966143236266646L;
  14 + private String id;
  15 + private String username;
  16 + private String password;
  17 + private boolean enabled;
  18 + private LocalDateTime accountExpireTime;
  19 + private TenantDTO tenant;
  20 + private String tenantId;
  21 + private Set<UserDetailRoleDTO> roles;
  22 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.alibaba.excel.annotation.ExcelIgnore;
  4 +import com.alibaba.excel.annotation.ExcelProperty;
  5 +import com.alibaba.excel.converters.Converter;
  6 +import com.alibaba.excel.converters.WriteConverterContext;
  7 +import com.alibaba.excel.enums.CellDataTypeEnum;
  8 +import com.alibaba.excel.metadata.data.WriteCellData;
  9 +import io.swagger.annotations.ApiModelProperty;
  10 +import lombok.Data;
  11 +import org.apache.commons.lang3.StringUtils;
  12 +
  13 +import java.util.Set;
  14 +
  15 +@Data
  16 +public class UserInfoDTO {
  17 + @ExcelProperty("用户Id")
  18 + @ApiModelProperty(value = "用户ID")
  19 + private String userId;
  20 +
  21 + @ApiModelProperty(value = "姓名")
  22 + private String realName;
  23 +
  24 + @ExcelIgnore
  25 + @ApiModelProperty(value = "头像")
  26 + private String avatar;
  27 +
  28 + @ApiModelProperty(value = "租户Code")
  29 + private String tenantCode;
  30 +
  31 + @ApiModelProperty(value = "租户名称")
  32 + private String tenantName;
  33 +
  34 + @ApiModelProperty(value = "主页地址")
  35 + private String homePath;
  36 + /** default: true */
  37 + @ApiModelProperty(value = "是否需要重置密码")
  38 + private boolean needSetPwd = true;
  39 +
  40 + /** 添加SetConverter,将Set字符串或者对象转成字符串,对象转成字符串会调用其toString方法,请重写toString方法 */
  41 + @ExcelProperty(converter = SetConverter.class)
  42 + private Set<String> roles;
  43 +
  44 + @ExcelProperty(converter = SetConverter.class)
  45 + private Set<PlainRolesDTO> plainRoles;
  46 +
  47 + public static class SetConverter implements Converter<Set<?>> {
  48 + @Override
  49 + public Class<?> supportJavaTypeKey() {
  50 + return Set.class;
  51 + }
  52 +
  53 + @Override
  54 + public WriteCellData<?> convertToExcelData(WriteConverterContext<Set<?>> context)
  55 + throws Exception {
  56 + return new WriteCellData<>(
  57 + CellDataTypeEnum.STRING, StringUtils.join(context.getValue(), ","));
  58 + }
  59 + }
  60 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonInclude;
  4 +import lombok.Data;
  5 +
  6 +import java.io.Serializable;
  7 +
  8 +@Data
  9 +@JsonInclude(JsonInclude.Include.NON_NULL)
  10 +public class UserRoleDTO implements Serializable {
  11 + private static final long serialVersionUID = -6930831157503627224L;
  12 + /** 用户ID */
  13 + private String userId;
  14 + /** 角色ID */
  15 + private String roleId;
  16 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +
  7 +@Data
  8 +@ApiModel(value = "密码修改")
  9 +public class AccountReqDTO {
  10 +
  11 + @ApiModelProperty(value = "用户ID",required = true)
  12 + private String userId;
  13 + @ApiModelProperty(value = "旧密码,旧密码为空表示设置初始密码")
  14 + private String password;
  15 + @ApiModelProperty(value = "新密码",required = true)
  16 + private String resetPassword;
  17 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonCreator;
  4 +import com.fasterxml.jackson.annotation.JsonProperty;
  5 +import lombok.Getter;
  6 +
  7 +@Getter
  8 +public class CodeLoginRequest {
  9 + private final String phoneNumber;
  10 + private final String code;
  11 +
  12 + @JsonCreator
  13 + public CodeLoginRequest(
  14 + @JsonProperty("phoneNumber") String phoneNumber, @JsonProperty("code") String code) {
  15 + this.phoneNumber = phoneNumber;
  16 + this.code = code;
  17 + }
  18 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Data;
  5 +import lombok.NoArgsConstructor;
  6 +
  7 +@Data
  8 +@AllArgsConstructor
  9 +@NoArgsConstructor
  10 +public class CodeTTL {
  11 + private String code;
  12 + private long sendTs;
  13 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import lombok.Data;
  4 +import lombok.RequiredArgsConstructor;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +import javax.validation.constraints.NotNull;
  8 +import java.io.File;
  9 +
  10 +@Data
  11 +@RequiredArgsConstructor
  12 +public class EmailReqDTO{
  13 +
  14 + /** 接收人 */
  15 + @NotEmpty(message = "缺少邮件接收人")
  16 + private String[] to;
  17 +
  18 + /** 抄送人 */
  19 + private String[] cc;
  20 +
  21 + /** 密送人 */
  22 + private String[] bcc;
  23 +
  24 + /** 主题 */
  25 + @NotNull(message = "主题不能为空")
  26 + private String subject;
  27 +
  28 + /** 内容 */
  29 + @NotEmpty(message ="内容不能为空")
  30 + private String body;
  31 +
  32 + /** 附件 */
  33 + private File[] files;
  34 +
  35 + /** 邮件格式:TEXT或者HTML */
  36 + @NotEmpty(message ="邮件格式不能为空")
  37 + private String emailFormatEnum;
  38 +
  39 + /** 模板ID */
  40 + @NotEmpty(message ="模板ID不能为空")
  41 + private String id;
  42 +
  43 + /**备注*/
  44 + private String remark;
  45 +
  46 + /**用途*/
  47 + private String templatePurpose;
  48 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonCreator;
  4 +import com.fasterxml.jackson.annotation.JsonProperty;
  5 +
  6 +public class LoginRequest {
  7 + private final String username;
  8 + private final String password;
  9 +
  10 + @JsonCreator
  11 + public LoginRequest(
  12 + @JsonProperty("username") String username, @JsonProperty("password") String password) {
  13 + this.username = username;
  14 + this.password = password;
  15 + }
  16 +
  17 + public String getUsername() {
  18 + return username;
  19 + }
  20 +
  21 + public String getPassword() {
  22 + return password;
  23 + }
  24 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import lombok.Data;
  4 +
  5 +import javax.validation.constraints.NotEmpty;
  6 +import java.io.Serializable;
  7 +
  8 +@Data
  9 +public class RoleOrOrganizationReqDTO implements Serializable {
  10 +
  11 + private static final long serialVersionUID = -5917331728153319765L;
  12 + /** 是否查询关联角色 */
  13 + private boolean queryRole;
  14 +
  15 + /** 是否查询关联组织 */
  16 + private boolean queryOrganization;
  17 +
  18 + /** 用户ID */
  19 + @NotEmpty(message = "用户ID不能为空或者空字符串")
  20 + private String userId;
  21 +
  22 + /** 角色或组织的ID */
  23 + private String id;
  24 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +
  4 +import lombok.Data;
  5 +import org.thingsboard.server.common.data.yunteng.enums.RoleEnum;
  6 +
  7 +import java.util.List;
  8 +
  9 +@Data
  10 +public class RoleReqDTO {
  11 + private String id;
  12 + private String name;
  13 + private String remark;
  14 + private RoleEnum roleType;
  15 + private int status;
  16 + private List<String> menu;
  17 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import lombok.Data;
  4 +import org.thingsboard.server.common.data.yunteng.enums.MessageTypeEnum;
  5 +
  6 +import javax.validation.constraints.NotEmpty;
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +@Data
  10 +public class SendResetPasswordEmailMsg {
  11 + @NotNull(message = "用户ID不能为空")
  12 + private String userId;
  13 +
  14 + @NotEmpty(message = "消息类型不能为空字符串")
  15 + private MessageTypeEnum messageTypeEnum;
  16 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import lombok.Data;
  4 +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +import javax.validation.constraints.Pattern;
  8 +import java.util.LinkedHashMap;
  9 +
  10 +@Data
  11 +public class SmsReqDTO {
  12 +
  13 + /** 模板参数 */
  14 + private LinkedHashMap<String, String> params;
  15 +
  16 + /** 手机号码 */
  17 + @Pattern(regexp = FastIotConstants.MOBILE, message = "请输入正确的手机号")
  18 + private String phoneNumbers;
  19 +
  20 + /** 模板ID */
  21 + @NotNull(message = "模板ID不能为空")
  22 + private String id;
  23 +
  24 + /** 备注 */
  25 + private String remark;
  26 +
  27 + /** 用途 */
  28 + private String templatePurpose;
  29 +}
  1 +package org.thingsboard.server.common.data.yunteng.dto.request;
  2 +
  3 +import com.fasterxml.jackson.annotation.JsonFormat;
  4 +import com.fasterxml.jackson.annotation.JsonInclude;
  5 +import lombok.Data;
  6 +import org.thingsboard.server.common.data.yunteng.common.AddGroup;
  7 +import org.thingsboard.server.common.data.yunteng.enums.TenantStatusEnum;
  8 +
  9 +import javax.validation.constraints.NotEmpty;
  10 +import javax.validation.constraints.NotNull;
  11 +import java.time.LocalDateTime;
  12 +
  13 +@Data
  14 +public class TenantReqDTO {
  15 + private String id;
  16 + private String icon;
  17 +
  18 + @NotEmpty(message = "租户名称不能为空或空字符串", groups = AddGroup.class)
  19 + private String name;
  20 +
  21 + private boolean enabled;
  22 + private String description;
  23 +
  24 + @NotNull(message = "角色不能为空", groups = AddGroup.class)
  25 + private String[] roleIds;
  26 +
  27 + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
  28 + private LocalDateTime tenantExpireTime;
  29 +
  30 + private String tenantCode;
  31 + private String defaultConfig;
  32 +
  33 + @JsonInclude(JsonInclude.Include.NON_NULL)
  34 + private TenantStatusEnum tenantStatus;
  35 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +/**
  4 + * 设备凭证
  5 + */
  6 +public enum DeviceCredentialsEnum {
  7 + ACCESS_TOKEN,
  8 + X509_CERTIFICATE,
  9 + MQTT_BASIC,
  10 + LWM2M_CREDENTIALS
  11 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum DeviceState {
  4 + INACTIVE,
  5 + ONLINE,
  6 + OFFLINE
  7 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum DeviceTypeEnum {
  4 + GATEWAY,
  5 + DIRECT_CONNECTION,
  6 + SENSOR
  7 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum MenuTypeEnum {
  4 + SYSADMIN,
  5 + CUSTOM
  6 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +/** 消息类型枚举值 */
  4 +public enum MessageTypeEnum {
  5 + EMAIL_MESSAGE,
  6 + PHONE_MESSAGE,
  7 + DING_TALK_MESSAGE,
  8 + WECHAT_MESSAGE
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum MsgTemplatePurposeEnum {
  4 + FOR_LOGIN,
  5 + FOR_FORGET_PASSWORD,
  6 + FOR_SET_PASSWORD,
  7 + FOR_ALARM_NOTICE,
  8 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum OrderTypeEnum {
  4 + ASC,
  5 + DESC
  6 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum RateLimitType {
  4 + /**
  5 + * 对所有请求进行限制
  6 + */
  7 + ALL,
  8 + /**
  9 + * 根据登录的用户限制
  10 + */
  11 + USER,
  12 + /**
  13 + * 根据IP限制
  14 + */
  15 + IP
  16 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +/** 请求响应枚举值 */
  4 +public enum ResponseCodeEnum {
  5 + SUCCESS,
  6 + FAILED,
  7 + SENDING,
  8 + OK
  9 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +public enum RoleEnum {
  4 + /**
  5 + * 超级管理员
  6 + */
  7 + ROLE_SYS_ADMIN,
  8 + /**
  9 + * 租户管理员
  10 + */
  11 + ROLE_TENANT_ADMIN,
  12 + /**
  13 + * 租户下普通用户
  14 + */
  15 + ROLE_NORMAL_USER,
  16 + /**
  17 + * 平台系统管理员
  18 + */
  19 + ROLE_PLATFORM_ADMIN;
  20 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +/** 短信平台枚举值 */
  4 +public enum SmsProviderTypeEnum {
  5 + ALI_CLOUD,
  6 + TENCENT_CLOUD
  7 +}
  1 +package org.thingsboard.server.common.data.yunteng.enums;
  2 +
  3 +/** 租户状态 */
  4 +public enum TenantStatusEnum {
  5 + NORMAL,
  6 + DISABLED,
  7 + EXPIRED
  8 +}