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 | 20 | import org.springframework.security.core.Authentication; |
21 | 21 | import org.springframework.security.core.AuthenticationException; |
22 | 22 | import org.springframework.stereotype.Component; |
23 | -import org.thingsboard.server.service.security.auth.TokenOutdatingService; | |
24 | 23 | import org.thingsboard.server.service.security.auth.JwtAuthenticationToken; |
24 | +import org.thingsboard.server.service.security.auth.TokenOutdatingService; | |
25 | 25 | import org.thingsboard.server.service.security.exception.JwtExpiredTokenException; |
26 | 26 | import org.thingsboard.server.service.security.model.SecurityUser; |
27 | 27 | import org.thingsboard.server.service.security.model.token.JwtTokenFactory; |
28 | 28 | import org.thingsboard.server.service.security.model.token.RawAccessJwtToken; |
29 | 29 | |
30 | +/** | |
31 | + * Jwt身份提供者 | |
32 | + */ | |
30 | 33 | @Component |
31 | 34 | @RequiredArgsConstructor |
32 | 35 | public class JwtAuthenticationProvider implements AuthenticationProvider { |
... | ... | @@ -34,11 +37,18 @@ public class JwtAuthenticationProvider implements AuthenticationProvider { |
34 | 37 | private final JwtTokenFactory tokenFactory; |
35 | 38 | private final TokenOutdatingService tokenOutdatingService; |
36 | 39 | |
40 | + /** | |
41 | + * 进行身份鉴定 | |
42 | + * @param authentication 证明 | |
43 | + * @return 证明 | |
44 | + * @throws AuthenticationException 身份验证异常 | |
45 | + */ | |
37 | 46 | @Override |
38 | 47 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { |
39 | 48 | RawAccessJwtToken rawAccessToken = (RawAccessJwtToken) authentication.getCredentials(); |
40 | 49 | SecurityUser securityUser = tokenFactory.parseAccessJwtToken(rawAccessToken); |
41 | 50 | |
51 | + //token失效了 过时了 | |
42 | 52 | if (tokenOutdatingService.isOutdated(rawAccessToken, securityUser.getId())) { |
43 | 53 | throw new JwtExpiredTokenException("Token is outdated"); |
44 | 54 | } | ... | ... |
... | ... | @@ -33,15 +33,15 @@ import org.thingsboard.server.common.data.id.EntityId; |
33 | 33 | import org.thingsboard.server.common.data.id.TenantId; |
34 | 34 | import org.thingsboard.server.common.data.id.UserId; |
35 | 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 | 36 | import org.thingsboard.server.service.security.auth.RefreshAuthenticationToken; |
37 | +import org.thingsboard.server.service.security.auth.TokenOutdatingService; | |
41 | 38 | import org.thingsboard.server.service.security.model.SecurityUser; |
42 | 39 | import org.thingsboard.server.service.security.model.UserPrincipal; |
43 | 40 | import org.thingsboard.server.service.security.model.token.JwtTokenFactory; |
44 | 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 | 46 | import java.util.UUID; |
47 | 47 | ... | ... |
... | ... | @@ -17,6 +17,14 @@ package org.thingsboard.server.service.security.auth.jwt.extractor; |
17 | 17 | |
18 | 18 | import javax.servlet.http.HttpServletRequest; |
19 | 19 | |
20 | +/** | |
21 | + * 令牌器接口 | |
22 | + */ | |
20 | 23 | public interface TokenExtractor { |
24 | + /** | |
25 | + * 提取令牌 | |
26 | + * @param request 请求 | |
27 | + * @return 令牌 | |
28 | + */ | |
21 | 29 | public String extract(HttpServletRequest request); |
22 | 30 | } |
\ No newline at end of file | ... | ... |
... | ... | @@ -16,7 +16,6 @@ |
16 | 16 | package org.thingsboard.server.service.security.auth.oauth2; |
17 | 17 | |
18 | 18 | import org.springframework.beans.factory.annotation.Autowired; |
19 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |
20 | 19 | import org.springframework.security.core.AuthenticationException; |
21 | 20 | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; |
22 | 21 | import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; |
... | ... | @@ -26,7 +25,6 @@ import org.thingsboard.server.common.data.id.CustomerId; |
26 | 25 | import org.thingsboard.server.common.data.id.EntityId; |
27 | 26 | import org.thingsboard.server.common.data.id.TenantId; |
28 | 27 | import org.thingsboard.server.service.security.system.SystemSecurityService; |
29 | -import org.thingsboard.server.utils.MiscUtils; | |
30 | 28 | |
31 | 29 | import javax.servlet.ServletException; |
32 | 30 | import javax.servlet.http.HttpServletRequest; | ... | ... |
... | ... | @@ -31,10 +31,10 @@ import org.thingsboard.server.common.data.id.TenantId; |
31 | 31 | import org.thingsboard.server.common.data.oauth2.OAuth2Registration; |
32 | 32 | import org.thingsboard.server.common.data.security.model.JwtToken; |
33 | 33 | import org.thingsboard.server.dao.oauth2.OAuth2Service; |
34 | +import org.thingsboard.server.service.security.system.SystemSecurityService; | |
34 | 35 | import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; |
35 | 36 | import org.thingsboard.server.service.security.model.SecurityUser; |
36 | 37 | import org.thingsboard.server.service.security.model.token.JwtTokenFactory; |
37 | -import org.thingsboard.server.service.security.system.SystemSecurityService; | |
38 | 38 | |
39 | 39 | import javax.servlet.http.HttpServletRequest; |
40 | 40 | import javax.servlet.http.HttpServletResponse; | ... | ... |
1 | 1 | /** |
2 | 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 | 12 | * limitations under the License. |
15 | 13 | */ |
16 | 14 | package org.thingsboard.server.service.security.auth.rest; |
17 | 15 | |
18 | 16 | import lombok.extern.slf4j.Slf4j; |
19 | 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 | 19 | import org.springframework.security.core.Authentication; |
26 | 20 | import org.springframework.security.core.AuthenticationException; |
27 | 21 | import org.springframework.security.core.userdetails.UsernameNotFoundException; |
22 | +import org.springframework.security.crypto.password.PasswordEncoder; | |
28 | 23 | import org.springframework.stereotype.Component; |
29 | 24 | import org.springframework.util.Assert; |
30 | 25 | import org.thingsboard.server.common.data.Customer; |
... | ... | @@ -36,167 +31,331 @@ import org.thingsboard.server.common.data.id.TenantId; |
36 | 31 | import org.thingsboard.server.common.data.id.UserId; |
37 | 32 | import org.thingsboard.server.common.data.security.Authority; |
38 | 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 | 40 | import org.thingsboard.server.dao.audit.AuditLogService; |
40 | 41 | import org.thingsboard.server.dao.customer.CustomerService; |
41 | -import org.thingsboard.server.dao.user.UserService; | |
42 | 42 | import org.thingsboard.server.service.security.model.SecurityUser; |
43 | 43 | import org.thingsboard.server.service.security.model.UserPrincipal; |
44 | 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 | 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 | 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 | 58 | @Component |
51 | 59 | @Slf4j |
52 | 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 | 24 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
25 | 25 | import org.springframework.stereotype.Component; |
26 | 26 | import org.thingsboard.server.common.data.security.model.JwtToken; |
27 | -import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; | |
28 | 27 | import org.thingsboard.server.service.security.model.SecurityUser; |
29 | 28 | import org.thingsboard.server.service.security.model.token.JwtTokenFactory; |
29 | +import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository; | |
30 | 30 | |
31 | 31 | import javax.servlet.ServletException; |
32 | 32 | import javax.servlet.http.HttpServletRequest; | ... | ... |
... | ... | @@ -28,7 +28,6 @@ import org.springframework.security.core.context.SecurityContextHolder; |
28 | 28 | import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; |
29 | 29 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; |
30 | 30 | import org.springframework.security.web.authentication.AuthenticationSuccessHandler; |
31 | -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; | |
32 | 31 | import org.thingsboard.server.service.security.exception.AuthMethodNotSupportedException; |
33 | 32 | import org.thingsboard.server.service.security.model.UserPrincipal; |
34 | 33 | ... | ... |
1 | 1 | /** |
2 | 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 | 12 | * limitations under the License. |
15 | 13 | */ |
16 | 14 | package org.thingsboard.server.service.security.model; |
17 | 15 | |
16 | +import lombok.Getter; | |
17 | +import lombok.Setter; | |
18 | 18 | import org.springframework.security.core.GrantedAuthority; |
19 | 19 | import org.springframework.security.core.authority.SimpleGrantedAuthority; |
20 | 20 | import org.thingsboard.server.common.data.User; |
21 | 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 | 26 | import java.util.Collection; |
27 | +import java.util.Optional; | |
28 | +import java.util.Set; | |
24 | 29 | import java.util.stream.Collectors; |
25 | 30 | import java.util.stream.Stream; |
26 | 31 | |
27 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.service.security.permission; |
17 | 17 | |
18 | -import org.thingsboard.server.common.data.HasCustomerId; | |
19 | 18 | import org.thingsboard.server.common.data.HasTenantId; |
20 | 19 | import org.thingsboard.server.common.data.id.EntityId; |
21 | -import org.thingsboard.server.common.data.id.TenantId; | |
22 | 20 | import org.thingsboard.server.service.security.model.SecurityUser; |
23 | 21 | |
24 | 22 | import java.util.Arrays; | ... | ... |
... | ... | @@ -22,7 +22,6 @@ import io.jsonwebtoken.Claims; |
22 | 22 | import io.jsonwebtoken.Header; |
23 | 23 | import io.jsonwebtoken.Jwt; |
24 | 24 | import io.jsonwebtoken.Jwts; |
25 | -import lombok.Getter; | |
26 | 25 | import lombok.extern.slf4j.Slf4j; |
27 | 26 | import org.apache.commons.lang3.RandomStringUtils; |
28 | 27 | import org.apache.commons.lang3.StringUtils; | ... | ... |
... | ... | @@ -15,81 +15,27 @@ |
15 | 15 | */ |
16 | 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 | 18 | import lombok.extern.slf4j.Slf4j; |
26 | -import org.apache.commons.lang3.StringUtils; | |
27 | -import org.hamcrest.Matcher; | |
28 | -import org.junit.After; | |
29 | 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 | 20 | import org.junit.runner.RunWith; |
36 | -import org.springframework.beans.factory.annotation.Autowired; | |
37 | 21 | import org.springframework.boot.test.context.SpringBootContextLoader; |
38 | 22 | import org.springframework.boot.test.context.SpringBootTest; |
39 | 23 | import org.springframework.boot.web.server.LocalServerPort; |
40 | 24 | import org.springframework.context.annotation.ComponentScan; |
41 | 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 | 26 | import org.springframework.test.annotation.DirtiesContext; |
50 | 27 | import org.springframework.test.context.ActiveProfiles; |
51 | 28 | import org.springframework.test.context.ContextConfiguration; |
52 | 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 | 31 | import java.net.URI; |
77 | 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 | 34 | import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; |
84 | -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch; | |
85 | 35 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; |
86 | 36 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; |
87 | 37 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; |
88 | -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; | |
89 | 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 | 40 | @ActiveProfiles("test") |
95 | 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 | 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 | 29 | @Test |
30 | 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 | 15 | */ |
16 | 16 | package org.thingsboard.server.controller.sql; |
17 | 17 | |
18 | -import org.thingsboard.server.controller.BaseAdminControllerTest; | |
18 | +import org.thingsboard.server.controller.BaseYtAdminControllerTest; | |
19 | 19 | import org.thingsboard.server.dao.service.DaoSqlTest; |
20 | 20 | |
21 | 21 | /** |
22 | 22 | * Created by Valerii Sosliuk on 6/28/2017. |
23 | 23 | */ |
24 | 24 | @DaoSqlTest |
25 | -public class AdminControllerSqlTest extends BaseAdminControllerTest { | |
25 | +public class YtAdminControllerSqlTest extends BaseYtAdminControllerTest { | |
26 | 26 | } | ... | ... |
... | ... | @@ -100,6 +100,78 @@ |
100 | 100 | <groupId>io.swagger</groupId> |
101 | 101 | <artifactId>swagger-annotations</artifactId> |
102 | 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 | 175 | </dependencies> |
104 | 176 | |
105 | 177 | <build> | ... | ... |
1 | 1 | /** |
2 | 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 | 12 | * limitations under the License. |
15 | 13 | */ |
16 | 14 | package org.thingsboard.server.common.data; |
... | ... | @@ -21,6 +19,8 @@ import com.fasterxml.jackson.databind.JsonNode; |
21 | 19 | import io.swagger.annotations.ApiModel; |
22 | 20 | import io.swagger.annotations.ApiModelProperty; |
23 | 21 | import lombok.EqualsAndHashCode; |
22 | +import lombok.Getter; | |
23 | +import lombok.Setter; | |
24 | 24 | import org.thingsboard.server.common.data.id.CustomerId; |
25 | 25 | import org.thingsboard.server.common.data.id.EntityId; |
26 | 26 | import org.thingsboard.server.common.data.id.TenantId; |
... | ... | @@ -28,167 +28,202 @@ import org.thingsboard.server.common.data.id.UserId; |
28 | 28 | import org.thingsboard.server.common.data.security.Authority; |
29 | 29 | import org.thingsboard.server.common.data.validation.Length; |
30 | 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 | 36 | @ApiModel |
33 | 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 | +} | |
\ No newline at end of file | ... | ... |
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 | +public class DTOCreationException extends RuntimeException { | |
4 | + | |
5 | + private static final long serialVersionUID = 5255597864949518781L; | |
6 | + | |
7 | + public DTOCreationException(String message) { | |
8 | + super(message); | |
9 | + } | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.core.exception; | |
2 | + | |
3 | +import lombok.Getter; | |
4 | + | |
5 | +public class DataValidationException extends RuntimeException { | |
6 | + private static final long serialVersionUID = 3556952261254572635L; | |
7 | + | |
8 | + @Getter public boolean log = false; | |
9 | + | |
10 | + public DataValidationException(String message) { | |
11 | + super(message); | |
12 | + } | |
13 | + | |
14 | + public DataValidationException(String message, boolean log) { | |
15 | + super(message); | |
16 | + this.log = log; | |
17 | + } | |
18 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.core.exception; | |
2 | + | |
3 | +public class EntityCreationException extends RuntimeException { | |
4 | + | |
5 | + private static final long serialVersionUID = 5255597864949518781L; | |
6 | + | |
7 | + public EntityCreationException(String message) { | |
8 | + super(message); | |
9 | + } | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.core.exception; | |
2 | + | |
3 | +import lombok.Getter; | |
4 | +import org.springframework.http.HttpStatus; | |
5 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
6 | + | |
7 | +public class FastIotException extends RuntimeException { | |
8 | + private static final long serialVersionUID = 4036257507478854844L; | |
9 | + | |
10 | + @Getter private final HttpStatus httpStatus; | |
11 | + | |
12 | + @Getter private final ErrorMessage error; | |
13 | + | |
14 | + public FastIotException(ErrorMessage errorMessage) { | |
15 | + super(errorMessage.getMessage()); | |
16 | + this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; | |
17 | + this.error = errorMessage; | |
18 | + } | |
19 | + | |
20 | + public FastIotException(ErrorMessage errorMessage, HttpStatus httpStatus) { | |
21 | + super(errorMessage.getMessage()); | |
22 | + this.httpStatus = httpStatus; | |
23 | + this.error = errorMessage; | |
24 | + } | |
25 | + | |
26 | + public FastIotException() { | |
27 | + super(ErrorMessage.INTERNAL_ERROR.getMessage()); | |
28 | + this.error = ErrorMessage.INTERNAL_ERROR; | |
29 | + this.httpStatus = HttpStatus.INTERNAL_SERVER_ERROR; | |
30 | + } | |
31 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.core.exception; | |
2 | + | |
3 | +public class FileNotFoundException extends RuntimeException{ | |
4 | + private static final long serialVersionUID = 3466865879043055822L; | |
5 | + | |
6 | + public FileNotFoundException(String message) { | |
7 | + super(message); | |
8 | + } | |
9 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.core.exception; | |
2 | + | |
3 | +public class FileStorageException extends RuntimeException{ | |
4 | + private static final long serialVersionUID = -8866081834891143120L; | |
5 | + | |
6 | + public FileStorageException(String message) { | |
7 | + super(message); | |
8 | + } | |
9 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.core.exception; | |
2 | + | |
3 | +public class NoneTenantAssetException extends RuntimeException { | |
4 | + private static final long serialVersionUID = 9135599998185288967L; | |
5 | + | |
6 | + public NoneTenantAssetException(String message) { | |
7 | + super(message); | |
8 | + } | |
9 | +} | ... | ... |
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 | +} | ... | ... |