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 | +} |
application/src/main/java/org/thingsboard/server/controller/yunteng/YtAdminController.java
0 → 100644
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 | +} |
application/src/main/java/org/thingsboard/server/controller/yunteng/YtUserController.java
0 → 100644
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 | } |
@@ -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 | } |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/common/CommonService.java
0 → 100644
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.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 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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/constant/FastIotConstants.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/constant/ModelConstants.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/constant/QueryConstant.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/constant/SecurityConstant.java
0 → 100644
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 | +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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/core/cache/CacheUtils.java
0 → 100644
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 | +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 NoneTenantAssetException extends RuntimeException { | ||
4 | + private static final long serialVersionUID = 9135599998185288967L; | ||
5 | + | ||
6 | + public NoneTenantAssetException(String message) { | ||
7 | + super(message); | ||
8 | + } | ||
9 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/core/message/ErrorMessage.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/AlarmProfileDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/DeviceProfileDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/FileUploadResponse.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/MessageConfigDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/MessageTemplateDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/OrganizationDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/PlainRolesDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/SysDictItemDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/UserDetailsDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/UserInfoDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/UserRoleDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/request/AccountReqDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/request/CodeTTL.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/request/EmailReqDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/request/LoginRequest.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/request/RoleReqDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/request/SmsReqDTO.java
0 → 100644
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 | +} |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/dto/request/TenantReqDTO.java
0 → 100644
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 | +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 | +} |