Showing
187 changed files
with
8072 additions
and
430 deletions
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 | +} | ... | ... |
1 | +package org.thingsboard.server.common.data.yunteng.utils; | |
2 | + | |
3 | +import org.springframework.core.annotation.AliasFor; | |
4 | + | |
5 | +import java.lang.annotation.*; | |
6 | + | |
7 | +/** 表示这个是一个<em>演示</em>,这不是一个正式方法,参照写法完成以后,请删掉demo的方法或者字段演示 */ | |
8 | +@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD}) | |
9 | +@Retention(RetentionPolicy.SOURCE) | |
10 | +@Documented | |
11 | +public @interface Demo { | |
12 | + String value() default ""; | |
13 | + | |
14 | + @AliasFor(attribute = "value") | |
15 | + String description() default ""; | |
16 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/ExcelUtil.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils; | |
2 | + | |
3 | +import com.alibaba.excel.EasyExcel; | |
4 | +import org.apache.commons.lang3.StringUtils; | |
5 | +import org.springframework.beans.BeanUtils; | |
6 | + | |
7 | +import javax.servlet.http.HttpServletResponse; | |
8 | +import java.io.IOException; | |
9 | +import java.net.URLEncoder; | |
10 | +import java.nio.charset.StandardCharsets; | |
11 | +import java.time.LocalDateTime; | |
12 | +import java.time.format.DateTimeFormatter; | |
13 | +import java.util.ArrayList; | |
14 | +import java.util.List; | |
15 | + | |
16 | +public class ExcelUtil { | |
17 | + private ExcelUtil() {} | |
18 | + | |
19 | + public static void exportExcel( | |
20 | + HttpServletResponse response, | |
21 | + String fileName, | |
22 | + String sheetName, | |
23 | + List<?> list, | |
24 | + Class<?> pojoClass) | |
25 | + throws IOException { | |
26 | + if (StringUtils.isBlank(fileName)) { | |
27 | + fileName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); | |
28 | + } | |
29 | + | |
30 | + response.setContentType("application/vnd.ms-excel"); | |
31 | + response.setCharacterEncoding("UTF-8"); | |
32 | + fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8); | |
33 | + response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx"); | |
34 | + EasyExcel.write(response.getOutputStream(), pojoClass).sheet(sheetName).doWrite(list); | |
35 | + } | |
36 | + | |
37 | + @SuppressWarnings("all") | |
38 | + public static void exportExcelToTarget( | |
39 | + HttpServletResponse response, | |
40 | + String fileName, | |
41 | + String sheetName, | |
42 | + List<?> sourceList, | |
43 | + Class<?> targetClass) | |
44 | + throws Exception { | |
45 | + List<Object> targetList = new ArrayList<>(sourceList.size()); | |
46 | + | |
47 | + for (Object source : sourceList) { | |
48 | + Object target = targetClass.newInstance(); | |
49 | + BeanUtils.copyProperties(source, target); | |
50 | + targetList.add(target); | |
51 | + } | |
52 | + | |
53 | + exportExcel(response, fileName, sheetName, targetList, targetClass); | |
54 | + } | |
55 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/JacksonUtil.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2021 The Thingsboard Authors | |
3 | + * | |
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 | |
6 | + * | |
7 | + * <p>http://www.apache.org/licenses/LICENSE-2.0 | |
8 | + * | |
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 | |
12 | + * limitations under the License. | |
13 | + */ | |
14 | +package org.thingsboard.server.common.data.yunteng.utils; | |
15 | + | |
16 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
17 | +import com.fasterxml.jackson.core.type.TypeReference; | |
18 | +import com.fasterxml.jackson.databind.DeserializationFeature; | |
19 | +import com.fasterxml.jackson.databind.JsonNode; | |
20 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
21 | +import com.fasterxml.jackson.databind.node.ObjectNode; | |
22 | + | |
23 | +import java.io.IOException; | |
24 | +import java.util.Arrays; | |
25 | + | |
26 | +public class JacksonUtil { | |
27 | + | |
28 | + public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); | |
29 | + | |
30 | + static { | |
31 | + OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); | |
32 | + } | |
33 | + | |
34 | + public static <T> T convertValue(Object fromValue, Class<T> toValueType) { | |
35 | + try { | |
36 | + return fromValue != null ? OBJECT_MAPPER.convertValue(fromValue, toValueType) : null; | |
37 | + } catch (IllegalArgumentException e) { | |
38 | + throw new IllegalArgumentException( | |
39 | + "The given object value: " + fromValue + " cannot be converted to " + toValueType, e); | |
40 | + } | |
41 | + } | |
42 | + | |
43 | + public static <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef) { | |
44 | + try { | |
45 | + return fromValue != null ? OBJECT_MAPPER.convertValue(fromValue, toValueTypeRef) : null; | |
46 | + } catch (IllegalArgumentException e) { | |
47 | + throw new IllegalArgumentException( | |
48 | + "The given object value: " + fromValue + " cannot be converted to " + toValueTypeRef, e); | |
49 | + } | |
50 | + } | |
51 | + | |
52 | + public static <T> T fromString(String string, Class<T> clazz) { | |
53 | + try { | |
54 | + return string != null ? OBJECT_MAPPER.readValue(string, clazz) : null; | |
55 | + } catch (IOException e) { | |
56 | + throw new IllegalArgumentException( | |
57 | + "The given string value: " + string + " cannot be transformed to Json object", e); | |
58 | + } | |
59 | + } | |
60 | + | |
61 | + public static <T> T fromString(String string, TypeReference<T> valueTypeRef) { | |
62 | + try { | |
63 | + return string != null ? OBJECT_MAPPER.readValue(string, valueTypeRef) : null; | |
64 | + } catch (IOException e) { | |
65 | + throw new IllegalArgumentException( | |
66 | + "The given string value: " + string + " cannot be transformed to Json object", e); | |
67 | + } | |
68 | + } | |
69 | + | |
70 | + public static <T> T fromBytes(byte[] bytes, Class<T> clazz) { | |
71 | + try { | |
72 | + return bytes != null ? OBJECT_MAPPER.readValue(bytes, clazz) : null; | |
73 | + } catch (IOException e) { | |
74 | + throw new IllegalArgumentException( | |
75 | + "The given string value: " | |
76 | + + Arrays.toString(bytes) | |
77 | + + " cannot be transformed to Json object", | |
78 | + e); | |
79 | + } | |
80 | + } | |
81 | + | |
82 | + public static JsonNode fromBytes(byte[] bytes) { | |
83 | + try { | |
84 | + return OBJECT_MAPPER.readTree(bytes); | |
85 | + } catch (IOException e) { | |
86 | + throw new IllegalArgumentException( | |
87 | + "The given byte[] value: " | |
88 | + + Arrays.toString(bytes) | |
89 | + + " cannot be transformed to Json object", | |
90 | + e); | |
91 | + } | |
92 | + } | |
93 | + | |
94 | + public static String toString(Object value) { | |
95 | + try { | |
96 | + return value != null ? OBJECT_MAPPER.writeValueAsString(value) : null; | |
97 | + } catch (JsonProcessingException e) { | |
98 | + throw new IllegalArgumentException( | |
99 | + "The given Json object value: " + value + " cannot be transformed to a String", e); | |
100 | + } | |
101 | + } | |
102 | + | |
103 | + public static JsonNode toJsonNode(String value) { | |
104 | + if (value == null || value.isEmpty()) { | |
105 | + return null; | |
106 | + } | |
107 | + try { | |
108 | + return OBJECT_MAPPER.readTree(value); | |
109 | + } catch (IOException e) { | |
110 | + throw new IllegalArgumentException(e); | |
111 | + } | |
112 | + } | |
113 | + | |
114 | + public static ObjectNode newObjectNode() { | |
115 | + return OBJECT_MAPPER.createObjectNode(); | |
116 | + } | |
117 | + | |
118 | + public static <T> T clone(T value) { | |
119 | + @SuppressWarnings("unchecked") | |
120 | + Class<T> valueClass = (Class<T>) value.getClass(); | |
121 | + return fromString(toString(value), valueClass); | |
122 | + } | |
123 | + | |
124 | + public static <T> JsonNode valueToTree(T value) { | |
125 | + return OBJECT_MAPPER.valueToTree(value); | |
126 | + } | |
127 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/ReflectUtils.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils; | |
2 | + | |
3 | +import lombok.extern.slf4j.Slf4j; | |
4 | +import org.springframework.beans.BeanUtils; | |
5 | + | |
6 | +import java.lang.reflect.Constructor; | |
7 | +import java.lang.reflect.Field; | |
8 | +import java.util.ArrayList; | |
9 | +import java.util.Arrays; | |
10 | +import java.util.Collection; | |
11 | +import java.util.List; | |
12 | + | |
13 | +@Slf4j | |
14 | +public class ReflectUtils { | |
15 | + | |
16 | + public static <T> Constructor<?> getEmptyParameterConstructor(Class<T> clazz) { | |
17 | + Constructor<?> constructor = null; | |
18 | + Constructor<?>[] constructors = clazz.getConstructors(); | |
19 | + for (Constructor<?> con : constructors) { | |
20 | + if (con.getParameterCount() == 0) { | |
21 | + constructor = con; | |
22 | + break; | |
23 | + } | |
24 | + } | |
25 | + return constructor; | |
26 | + } | |
27 | + | |
28 | + @SuppressWarnings("unchecked") | |
29 | + public static <T> List<T> sourceToTarget( | |
30 | + Collection<?> sourceList, Class<T> target, String... ignoreProperties) { | |
31 | + if (sourceList == null) { | |
32 | + return null; | |
33 | + } | |
34 | + | |
35 | + List<T> targetList = new ArrayList<>(sourceList.size()); | |
36 | + Constructor<?> constructor = getEmptyParameterConstructor(target); | |
37 | + if (constructor != null) { | |
38 | + try { | |
39 | + for (Object source : sourceList) { | |
40 | + T targetObject = (T) constructor.newInstance(); | |
41 | + BeanUtils.copyProperties(source, targetObject, ignoreProperties); | |
42 | + targetList.add(targetObject); | |
43 | + } | |
44 | + } catch (Exception e) { | |
45 | + log.error("convert error ", e); | |
46 | + } | |
47 | + } | |
48 | + return targetList; | |
49 | + } | |
50 | + | |
51 | + | |
52 | + /** | |
53 | + * 获取类的所有属性,包含父类的【public private protected】 | |
54 | + * @param clazz 不确定类型 | |
55 | + * @return 返回List<Field> | |
56 | + */ | |
57 | + public static List<Field> getAllDeclaredFields(Class<?> clazz){ | |
58 | + List<Field> fieldList = new ArrayList<>(); | |
59 | + for (;clazz !=null;clazz=clazz.getSuperclass()){ | |
60 | + fieldList.addAll(Arrays.asList(clazz.getDeclaredFields())); | |
61 | + } | |
62 | + return fieldList; | |
63 | + } | |
64 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/RequestUtils.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils; | |
2 | + | |
3 | +import javax.servlet.http.HttpServletRequest; | |
4 | + | |
5 | +public class RequestUtils { | |
6 | + public static String getClientIpAddr(HttpServletRequest request) { | |
7 | + String ip = request.getHeader("X-Forwarded-For"); | |
8 | + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |
9 | + ip = request.getHeader("Proxy-Client-IP"); | |
10 | + } | |
11 | + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |
12 | + ip = request.getHeader("WL-Proxy-Client-IP"); | |
13 | + } | |
14 | + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |
15 | + ip = request.getHeader("HTTP_CLIENT_IP"); | |
16 | + } | |
17 | + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |
18 | + ip = request.getHeader("HTTP_X_FORWARDED_FOR"); | |
19 | + } | |
20 | + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { | |
21 | + ip = request.getRemoteAddr(); | |
22 | + } | |
23 | + return ip; | |
24 | + } | |
25 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/tools/PageData.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils.tools; | |
2 | + | |
3 | +import lombok.Data; | |
4 | +import lombok.NoArgsConstructor; | |
5 | + | |
6 | +import java.io.Serializable; | |
7 | +import java.util.Collection; | |
8 | + | |
9 | +@Data | |
10 | +@NoArgsConstructor | |
11 | +public class PageData<T> implements Serializable { | |
12 | + private static final long serialVersionUID = -5385636733740491124L; | |
13 | + private int total; | |
14 | + private Collection<T> items; | |
15 | + | |
16 | + public PageData(Collection<T> list, long total) { | |
17 | + this.items = list; | |
18 | + this.total = (int) total; | |
19 | + } | |
20 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/tools/ResponseResult.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils.tools; | |
2 | + | |
3 | +import lombok.Data; | |
4 | +import lombok.NoArgsConstructor; | |
5 | +import org.springframework.http.HttpStatus; | |
6 | + | |
7 | +import java.io.Serializable; | |
8 | + | |
9 | +@Data | |
10 | +@NoArgsConstructor | |
11 | +public class ResponseResult<T> implements Serializable { | |
12 | + | |
13 | + private static final long serialVersionUID = -8043533414600873987L; | |
14 | + | |
15 | + /** | |
16 | + * 状态码 | |
17 | + */ | |
18 | + private Integer code; | |
19 | + | |
20 | + /** | |
21 | + * 消息 | |
22 | + */ | |
23 | + private String message; | |
24 | + | |
25 | + /** | |
26 | + * 数据 | |
27 | + */ | |
28 | + private T data; | |
29 | + | |
30 | + /** | |
31 | + * 成功返回数据 | |
32 | + * @param message 消息 | |
33 | + * @return Result<T> | |
34 | + */ | |
35 | + public static <T> ResponseResult<T> success(String message){ | |
36 | + ResponseResult<T> responseResult = new ResponseResult<>(); | |
37 | + responseResult.setMessage(message); | |
38 | + responseResult.setCode(HttpStatus.OK.value()); | |
39 | + return responseResult; | |
40 | + } | |
41 | + | |
42 | + /** | |
43 | + * 成功返回数据 | |
44 | + * @param data 数据 | |
45 | + * @return Result<T> | |
46 | + */ | |
47 | + public static <T> ResponseResult<T> success(T data){ | |
48 | + ResponseResult<T> responseResult = new ResponseResult<>(); | |
49 | + responseResult.setCode(HttpStatus.OK.value()); | |
50 | + responseResult.setMessage(HttpStatus.OK.getReasonPhrase()); | |
51 | + responseResult.setData(data); | |
52 | + return responseResult; | |
53 | + } | |
54 | + | |
55 | + /** | |
56 | + * 失败返回数据 | |
57 | + * @param message 消息 | |
58 | + * @return Result<T> | |
59 | + */ | |
60 | + public static <T> ResponseResult<T> failed(String message){ | |
61 | + ResponseResult<T> responseResult = new ResponseResult<>(); | |
62 | + responseResult.setMessage(message); | |
63 | + responseResult.setCode(HttpStatus.INTERNAL_SERVER_ERROR.value()); | |
64 | + return responseResult; | |
65 | + } | |
66 | + | |
67 | + /** | |
68 | + * 失败返回数据 | |
69 | + * @param code 状态码 | |
70 | + * @param message 消息 | |
71 | + * @return Result<T> | |
72 | + */ | |
73 | + public static <T> ResponseResult<T> failed(int code, String message){ | |
74 | + ResponseResult<T> responseResult = new ResponseResult<>(); | |
75 | + responseResult.setMessage(message); | |
76 | + responseResult.setCode(code); | |
77 | + return responseResult; | |
78 | + } | |
79 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/tools/TBPageData.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils.tools; | |
2 | + | |
3 | +import com.fasterxml.jackson.annotation.JsonProperty; | |
4 | +import lombok.Data; | |
5 | +import lombok.NoArgsConstructor; | |
6 | +import org.thingsboard.common.util.JacksonUtil; | |
7 | + | |
8 | +import java.io.Serializable; | |
9 | +import java.util.ArrayList; | |
10 | +import java.util.Collection; | |
11 | +import java.util.List; | |
12 | + | |
13 | +@Data | |
14 | +@NoArgsConstructor | |
15 | +public class TBPageData<T> implements Serializable { | |
16 | + | |
17 | + private static final long serialVersionUID = -914237744254466700L; | |
18 | + | |
19 | + private Collection<T> data; | |
20 | + private int totalPages; | |
21 | + private long totalElements; | |
22 | + | |
23 | + @JsonProperty("hasNext") | |
24 | + private boolean hasNext; | |
25 | + | |
26 | + public TBPageData(Collection<T> data, int totalPages, long totalElements, boolean hasNext) { | |
27 | + this.data = data; | |
28 | + this.totalPages = totalPages; | |
29 | + this.totalElements = totalElements; | |
30 | + this.hasNext = hasNext; | |
31 | + } | |
32 | + | |
33 | + public <D> TBPageData<D> getPageData(TBPageData<T> data, Class<D> target){ | |
34 | + List<D> targetList = new ArrayList<>(); | |
35 | + for(T t:data.getData()){ | |
36 | + targetList.add(JacksonUtil.convertValue(t,target)); | |
37 | + } | |
38 | + return new TBPageData<>(targetList,data.totalPages,data.totalElements,data.hasNext); | |
39 | + } | |
40 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/yunteng/utils/tree/TreeUtils.java
0 → 100644
1 | +package org.thingsboard.server.common.data.yunteng.utils.tree; | |
2 | + | |
3 | +import com.google.common.collect.Lists; | |
4 | +import com.google.common.collect.Sets; | |
5 | + | |
6 | +import java.util.*; | |
7 | + | |
8 | +public class TreeUtils { | |
9 | + public static <T extends TreeDTO<T>> List<T> buildTree(List<T> treeList) { | |
10 | + Map<String, T> dtoMap = new LinkedHashMap<>(treeList.size()); | |
11 | + HashSet<T> dtoSet = Sets.newHashSet(treeList); | |
12 | + dtoSet.forEach(dto -> dtoMap.put(dto.getId(), dto)); | |
13 | + List<T> result = Lists.newArrayList(); | |
14 | + for (T node : dtoMap.values()) { | |
15 | + T parent = dtoMap.get(node.getParentId()); | |
16 | + if (parent != null && !(node.getId().equals(parent.getId()))) { | |
17 | + parent.getChildren().add(node); | |
18 | + continue; | |
19 | + } | |
20 | + result.add(node); | |
21 | + } | |
22 | + Collections.sort(result); | |
23 | + result.forEach(node -> Collections.sort(node.getChildren())); | |
24 | + return result; | |
25 | + } | |
26 | +} | ... | ... |
... | ... | @@ -246,6 +246,13 @@ |
246 | 246 | <groupId>org.eclipse.leshan</groupId> |
247 | 247 | <artifactId>leshan-core</artifactId> |
248 | 248 | </dependency> |
249 | + | |
250 | + <!--mybatis--> | |
251 | + <dependency> | |
252 | + <groupId>com.baomidou</groupId> | |
253 | + <artifactId>mybatis-plus-boot-starter</artifactId> | |
254 | + <version>${mybatis-plus.version}</version> | |
255 | + </dependency> | |
249 | 256 | </dependencies> |
250 | 257 | <build> |
251 | 258 | <plugins> | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +import java.time.LocalDateTime; | |
9 | + | |
10 | +@Data | |
11 | +@EqualsAndHashCode(callSuper = false) | |
12 | +@TableName(ModelConstants.Table.ADMIN_SETTING_TABLE_NAME) | |
13 | +public class AdminSetting extends BaseEntity { | |
14 | + | |
15 | + private static final long serialVersionUID = -881433375246560135L; | |
16 | + | |
17 | + private String configJson; | |
18 | + private String key; | |
19 | + private LocalDateTime createTime; | |
20 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.FieldFill; | |
4 | +import com.baomidou.mybatisplus.annotation.TableField; | |
5 | +import com.baomidou.mybatisplus.annotation.TableName; | |
6 | +import lombok.Data; | |
7 | +import lombok.EqualsAndHashCode; | |
8 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
9 | + | |
10 | +import java.time.LocalDateTime; | |
11 | + | |
12 | +/** | |
13 | + * @Description | |
14 | + * @Author cxy 告警联系人实体表 | |
15 | + * @Date 2021/11/2 11:17 | |
16 | + */ | |
17 | +@Data | |
18 | +@EqualsAndHashCode(callSuper = true) | |
19 | +@TableName(ModelConstants.Table.IOTFS_ALARM_CONTACT_TABLE_NAME) | |
20 | +public class AlarmContact extends TenantBaseEntity{ | |
21 | + | |
22 | + private static final long serialVersionUID= -3982884827995610164L; | |
23 | + | |
24 | + private String username; | |
25 | + | |
26 | + private String organizationId; | |
27 | + | |
28 | + | |
29 | + private String phone; | |
30 | + | |
31 | + private String email; | |
32 | + | |
33 | + private String wechat; | |
34 | + private String dingtalk; | |
35 | + | |
36 | + private String remark; | |
37 | + | |
38 | + private String addPeople; | |
39 | + | |
40 | + private String tenantCode; | |
41 | + | |
42 | + @TableField(fill = FieldFill.INSERT) | |
43 | + private LocalDateTime createTime; | |
44 | + | |
45 | + private String creator; | |
46 | + | |
47 | + private String updater; | |
48 | + | |
49 | + @TableField(fill = FieldFill.UPDATE) | |
50 | + private LocalDateTime updateTime; | |
51 | + | |
52 | + | |
53 | + | |
54 | + | |
55 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@EqualsAndHashCode(callSuper = true) | |
10 | +@TableName(ModelConstants.Table.IOTFS_ALARM_PROFILE_TABLE_NAME) | |
11 | +public class AlarmProfile extends TenantBaseEntity { | |
12 | + | |
13 | + private static final long serialVersionUID = -4922707705163155569L; | |
14 | + private String alarmContactId; | |
15 | + private String deviceProfileId; | |
16 | + private String messageMode; | |
17 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.FieldFill; | |
4 | +import com.baomidou.mybatisplus.annotation.TableField; | |
5 | +import lombok.Getter; | |
6 | +import lombok.Setter; | |
7 | + | |
8 | +import java.time.LocalDateTime; | |
9 | + | |
10 | +@Getter | |
11 | +@Setter | |
12 | +public class AuditRelatedEntity extends BaseEntity { | |
13 | + | |
14 | + private static final long serialVersionUID = -5865650870569216315L; | |
15 | + | |
16 | + @TableField(fill = FieldFill.INSERT) | |
17 | + private String creator; | |
18 | + | |
19 | + @TableField(fill = FieldFill.INSERT) | |
20 | + private LocalDateTime createTime; | |
21 | + | |
22 | + @TableField(fill = FieldFill.INSERT_UPDATE) | |
23 | + private String updater; | |
24 | + | |
25 | + @TableField(fill = FieldFill.INSERT_UPDATE) | |
26 | + private LocalDateTime updateTime; | |
27 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.IdType; | |
4 | +import com.baomidou.mybatisplus.annotation.TableId; | |
5 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
6 | +import lombok.Getter; | |
7 | +import lombok.Setter; | |
8 | +import org.springframework.beans.BeanUtils; | |
9 | +import org.thingsboard.server.common.data.yunteng.core.exception.DTOCreationException; | |
10 | +import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils; | |
11 | + | |
12 | +import java.io.Serializable; | |
13 | +import java.lang.reflect.Constructor; | |
14 | +import java.lang.reflect.InvocationTargetException; | |
15 | + | |
16 | +@Getter | |
17 | +@Setter | |
18 | +public class BaseEntity implements Serializable { | |
19 | + private static final long serialVersionUID = 8948437944054606982L; | |
20 | + | |
21 | + @TableId(type = IdType.ASSIGN_UUID) | |
22 | + private String id; | |
23 | + | |
24 | + @JsonIgnore | |
25 | + public <T> void copyToDTO(T dto, String... ignoreProperties) { | |
26 | + BeanUtils.copyProperties(this, dto, ignoreProperties); | |
27 | + } | |
28 | + | |
29 | + @JsonIgnore | |
30 | + @SuppressWarnings("unchecked") | |
31 | + public <T> T getDTO(Class<T> clazz) { | |
32 | + Constructor<?> constructor = ReflectUtils.getEmptyParameterConstructor(clazz); | |
33 | + if (constructor != null) { | |
34 | + try { | |
35 | + T t = (T) constructor.newInstance(); | |
36 | + BeanUtils.copyProperties(this, t); | |
37 | + return t; | |
38 | + } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { | |
39 | + throw new DTOCreationException( | |
40 | + "try to get dto from class [" + clazz.getName() + "] failed " + e.getMessage()); | |
41 | + } | |
42 | + } else { | |
43 | + throw new DTOCreationException("try to get dto from class [" + clazz.getName() + "] failed"); | |
44 | + } | |
45 | + } | |
46 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@EqualsAndHashCode(callSuper = true) | |
10 | +@TableName(ModelConstants.Table.IOTFS_DEVICE_TYPE_TABLE_NAME) | |
11 | +public class DeviceType extends TenantBaseEntity { | |
12 | + | |
13 | + private static final long serialVersionUID = -3777232331298040322L; | |
14 | + | |
15 | + private String name; | |
16 | + | |
17 | + private String parentId; | |
18 | + | |
19 | + private String path; | |
20 | + | |
21 | + private Integer sort; | |
22 | + | |
23 | + private String description; | |
24 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableField; | |
4 | +import com.baomidou.mybatisplus.annotation.TableName; | |
5 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | |
6 | +import com.fasterxml.jackson.databind.JsonNode; | |
7 | +import lombok.Data; | |
8 | +import lombok.EqualsAndHashCode; | |
9 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
10 | + | |
11 | +import java.time.LocalDateTime; | |
12 | + | |
13 | +@Data | |
14 | +@EqualsAndHashCode(callSuper = false) | |
15 | +@TableName(value = ModelConstants.Table.MAIL_LOG_TABLE_NAME,autoResultMap = true) | |
16 | +public class MailLog extends BaseEntity { | |
17 | + private static final long serialVersionUID = -8847842025838559296L; | |
18 | + | |
19 | + /** 发件人 */ | |
20 | + private String emailFrom; | |
21 | + | |
22 | + /** 收件人 */ | |
23 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
24 | + private JsonNode emailTo; | |
25 | + | |
26 | + /** 抄送人 */ | |
27 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
28 | + private JsonNode emailCc; | |
29 | + | |
30 | + /** 密送人 */ | |
31 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
32 | + private JsonNode emailBcc; | |
33 | + | |
34 | + /** 邮件主题 */ | |
35 | + private String emailSubject; | |
36 | + | |
37 | + /** 邮件内容 */ | |
38 | + private String emailBody; | |
39 | + | |
40 | + /** 状态:ResponseCodeEnum枚举值 */ | |
41 | + private String status; | |
42 | + | |
43 | + /** 发送时间 */ | |
44 | + private LocalDateTime sendTime; | |
45 | + | |
46 | + /** 租户Code */ | |
47 | + private String tenantCode; | |
48 | + | |
49 | + /** 模板ID */ | |
50 | + private String messageTemplateId; | |
51 | + | |
52 | + /**备注*/ | |
53 | + private String remark; | |
54 | + | |
55 | + /**用途*/ | |
56 | + private String templatePurpose; | |
57 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableField; | |
4 | +import com.baomidou.mybatisplus.annotation.TableName; | |
5 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | |
6 | +import com.fasterxml.jackson.databind.JsonNode; | |
7 | +import lombok.Data; | |
8 | +import lombok.EqualsAndHashCode; | |
9 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
10 | +import org.thingsboard.server.common.data.yunteng.enums.MenuTypeEnum; | |
11 | + | |
12 | +@Data | |
13 | +@EqualsAndHashCode(callSuper = true) | |
14 | +@TableName(ModelConstants.Table.MENU_TABLE_NAME) | |
15 | +public class Menu extends TenantBaseEntity { | |
16 | + | |
17 | + private static final long serialVersionUID = 6319718763792214142L; | |
18 | + private String name; | |
19 | + | |
20 | + private String parentId; | |
21 | + | |
22 | + private String path; | |
23 | + | |
24 | + private MenuTypeEnum type; | |
25 | + | |
26 | + private String permission; | |
27 | + | |
28 | + private Integer sort; | |
29 | + | |
30 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
31 | + private JsonNode meta; | |
32 | + | |
33 | + private String alias; | |
34 | + | |
35 | + private String redirect; | |
36 | + | |
37 | + private Boolean caseSensitive; | |
38 | + | |
39 | + private String component; | |
40 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableField; | |
4 | +import com.baomidou.mybatisplus.annotation.TableName; | |
5 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | |
6 | +import com.fasterxml.jackson.databind.JsonNode; | |
7 | +import lombok.Data; | |
8 | +import lombok.EqualsAndHashCode; | |
9 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
10 | + | |
11 | +@Data | |
12 | +@EqualsAndHashCode(callSuper = true) | |
13 | +@TableName(value = ModelConstants.Table.MESSAGE_CONFIG_TABLE_NAME,autoResultMap = true) | |
14 | +public class MessageConfig extends TenantBaseEntity { | |
15 | + | |
16 | + private static final long serialVersionUID = -3624943194108704138L; | |
17 | + | |
18 | + /** 配置名称 */ | |
19 | + private String configName; | |
20 | + | |
21 | + /** 平台类型 */ | |
22 | + private String platformType; | |
23 | + | |
24 | + /** 消息类型 */ | |
25 | + private String messageType; | |
26 | + | |
27 | + /** json配置 */ | |
28 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
29 | + private JsonNode config; | |
30 | + | |
31 | + /** 状态:0禁用 1启用 */ | |
32 | + private Integer status; | |
33 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@EqualsAndHashCode(callSuper = true) | |
10 | +@TableName(ModelConstants.Table.MESSAGE_TEMPLATE_TABLE_NAME) | |
11 | +public class MessageTemplate extends TenantBaseEntity { | |
12 | + | |
13 | + private static final long serialVersionUID = 6347635507829273091L; | |
14 | + | |
15 | + /** 模板名称 */ | |
16 | + private String templateName; | |
17 | + | |
18 | + /** 模板签名 */ | |
19 | + private String signName; | |
20 | + | |
21 | + /** 模板CODE */ | |
22 | + private String templateCode; | |
23 | + | |
24 | + /** 消息配置 */ | |
25 | + private String messageConfigId; | |
26 | + | |
27 | + /** 模板用途 */ | |
28 | + private String templatePurpose; | |
29 | + | |
30 | + /** 消息类型 */ | |
31 | + private String messageType; | |
32 | + | |
33 | + /** 状态:0禁用 1启用 */ | |
34 | + private Integer status; | |
35 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@EqualsAndHashCode(callSuper = true) | |
10 | +@TableName(ModelConstants.Table.IOTFS_ORGANIZATION_TABLE_NAME) | |
11 | +public class Organization extends TenantBaseEntity { | |
12 | + private String parentId; | |
13 | + private String name; | |
14 | + private int sort; | |
15 | + private String remark; | |
16 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
6 | +import org.thingsboard.server.common.data.yunteng.core.RequestMethod; | |
7 | +import org.thingsboard.server.common.data.yunteng.enums.RateLimitType; | |
8 | + | |
9 | +import java.time.LocalTime; | |
10 | + | |
11 | +@Data | |
12 | +@TableName(ModelConstants.Table.RATE_LIMIT_TABLE_NAME) | |
13 | +public class RateLimiterEntity { | |
14 | + private String id; | |
15 | + private String path; | |
16 | + private double qps; | |
17 | + private RateLimitType rateLimitType; | |
18 | + private boolean enabled; | |
19 | + private LocalTime enableTime; | |
20 | + private LocalTime endTime; | |
21 | + private RequestMethod requestMethod; | |
22 | + private Integer sort; | |
23 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@EqualsAndHashCode(callSuper = false) | |
10 | +@TableName(ModelConstants.Table.ROLE_TABLE_NAME) | |
11 | +public class Role extends TenantBaseEntity { | |
12 | + | |
13 | + private static final long serialVersionUID = 3915852360063998830L; | |
14 | + private String name; | |
15 | + | |
16 | + private String remark; | |
17 | + | |
18 | + private String roleType; | |
19 | + | |
20 | + private String code; | |
21 | + | |
22 | + private boolean enabled = true; | |
23 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.FieldFill; | |
4 | +import com.baomidou.mybatisplus.annotation.TableField; | |
5 | +import com.baomidou.mybatisplus.annotation.TableName; | |
6 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | |
7 | +import com.fasterxml.jackson.databind.JsonNode; | |
8 | +import lombok.Data; | |
9 | +import lombok.EqualsAndHashCode; | |
10 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
11 | + | |
12 | +import java.time.LocalDateTime; | |
13 | + | |
14 | +@Data | |
15 | +@EqualsAndHashCode(callSuper = false) | |
16 | +@TableName(value = ModelConstants.Table.SMS_LOG_TABLE_NAME,autoResultMap = true) | |
17 | +public class SmsLog extends BaseEntity { | |
18 | + | |
19 | + private static final long serialVersionUID = 2778820322396894328L; | |
20 | + | |
21 | + /** 短信平台类型 */ | |
22 | + private String type; | |
23 | + | |
24 | + /** 发送状态:ResponseCodeEnum枚举值 */ | |
25 | + private String status; | |
26 | + | |
27 | + /** 发送时间 */ | |
28 | + @TableField(fill = FieldFill.INSERT) | |
29 | + private LocalDateTime sendTime; | |
30 | + | |
31 | + /** 发送手机号 */ | |
32 | + private String toPhone; | |
33 | + | |
34 | + /** 发送模板参数 */ | |
35 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
36 | + private JsonNode templateParam; | |
37 | + | |
38 | + /** 租户Code */ | |
39 | + private String tenantCode; | |
40 | + | |
41 | + /** 模板ID */ | |
42 | + private String messageTemplateId; | |
43 | + | |
44 | + /**用途*/ | |
45 | + private String templatePurpose; | |
46 | + | |
47 | + /**备注*/ | |
48 | + private String remark; | |
49 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@EqualsAndHashCode(callSuper = true) | |
10 | +@TableName(ModelConstants.Table.DEPT_TABLE_NAME) | |
11 | +public class SysDept extends TenantBaseEntity { | |
12 | + | |
13 | + | |
14 | + private static final long serialVersionUID = -7160697827758883893L; | |
15 | + private String deptName; | |
16 | + | |
17 | + private String parentId; | |
18 | + | |
19 | + private Integer orderNo; | |
20 | + | |
21 | + | |
22 | + private String remark; | |
23 | + private Integer status; | |
24 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@EqualsAndHashCode(callSuper = false) | |
10 | +@TableName(ModelConstants.Table.DICT_TABLE_NAME) | |
11 | +public class SysDict extends TenantBaseEntity { | |
12 | + | |
13 | + private static final long serialVersionUID = -5381101569947327544L; | |
14 | + | |
15 | + /** 字典名称 */ | |
16 | + private String dictName; | |
17 | + | |
18 | + /** 字典编码 */ | |
19 | + private String dictCode; | |
20 | + | |
21 | + /** 字典描述 */ | |
22 | + private String description; | |
23 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.RequiredArgsConstructor; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +@Data | |
9 | +@RequiredArgsConstructor | |
10 | +@TableName(ModelConstants.Table.DICT_ITEM_TABLE_NAME) | |
11 | +public class SysDictItem extends TenantBaseEntity { | |
12 | + | |
13 | + private static final long serialVersionUID = 9177617160310722864L; | |
14 | + /** 字典id */ | |
15 | + private String dictId; | |
16 | + | |
17 | + /** 字典项文本 */ | |
18 | + private String itemText; | |
19 | + | |
20 | + /** 字典值 */ | |
21 | + private String itemValue; | |
22 | + | |
23 | + /** 描述 */ | |
24 | + private String description; | |
25 | + | |
26 | + /** 排序 */ | |
27 | + private Integer sort; | |
28 | + | |
29 | + /** 状态 */ | |
30 | + private Integer status; | |
31 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +import java.time.LocalDateTime; | |
9 | + | |
10 | +@Data | |
11 | +@EqualsAndHashCode(callSuper = false) | |
12 | +@TableName(ModelConstants.Table.TENANT_TABLE_NAME) | |
13 | +public class Tenant extends AuditRelatedEntity { | |
14 | + | |
15 | + private static final long serialVersionUID = 4848421848961008112L; | |
16 | + private String name; | |
17 | + | |
18 | + private String tenantCode; | |
19 | + | |
20 | + private String icon; | |
21 | + | |
22 | + private boolean enabled = true; | |
23 | + | |
24 | + private String description; | |
25 | + | |
26 | + private String defaultConfig; | |
27 | + | |
28 | + private LocalDateTime tenantExpireTime; | |
29 | + | |
30 | + /** TB的租户ID */ | |
31 | + private String tenantId; | |
32 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.FieldFill; | |
4 | +import com.baomidou.mybatisplus.annotation.TableField; | |
5 | +import lombok.Getter; | |
6 | +import lombok.Setter; | |
7 | + | |
8 | +import java.time.LocalDateTime; | |
9 | + | |
10 | +@Getter | |
11 | +@Setter | |
12 | +public class TenantBaseEntity extends BaseEntity { | |
13 | + | |
14 | + private static final long serialVersionUID = -4315734960161684909L; | |
15 | + | |
16 | + private String tenantCode; | |
17 | + | |
18 | + @TableField(fill = FieldFill.INSERT) | |
19 | + private String creator; | |
20 | + | |
21 | + @TableField(fill = FieldFill.UPDATE) | |
22 | + private String updater; | |
23 | + | |
24 | + @TableField(fill = FieldFill.INSERT) | |
25 | + private LocalDateTime createTime; | |
26 | + | |
27 | + @TableField(fill = FieldFill.UPDATE) | |
28 | + private LocalDateTime updateTime; | |
29 | + | |
30 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +import java.io.Serializable; | |
9 | + | |
10 | +@Data | |
11 | +@EqualsAndHashCode(callSuper = false) | |
12 | +@TableName(ModelConstants.Table.TENANT_MENU_TABLE_NAME) | |
13 | +public class TenantMenu implements Serializable { | |
14 | + private static final long serialVersionUID = -8775371485677702427L; | |
15 | + /** 菜单ID */ | |
16 | + private String menuId; | |
17 | + /** 租户ID */ | |
18 | + private String tenantCode; | |
19 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +import java.io.Serializable; | |
9 | + | |
10 | +@Data | |
11 | +@EqualsAndHashCode(callSuper = false) | |
12 | +@TableName(ModelConstants.Table.TENANT_ROLE_TABLE_NAME) | |
13 | +public class TenantRole implements Serializable { | |
14 | + | |
15 | + private static final long serialVersionUID = 7332631758506821892L; | |
16 | + /** 角色ID */ | |
17 | + private String roleId; | |
18 | + /** 租户ID */ | |
19 | + private String tenantCode; | |
20 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.FieldStrategy; | |
4 | +import com.baomidou.mybatisplus.annotation.TableField; | |
5 | +import com.baomidou.mybatisplus.annotation.TableName; | |
6 | +import lombok.Data; | |
7 | +import lombok.EqualsAndHashCode; | |
8 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
9 | + | |
10 | +import java.time.LocalDateTime; | |
11 | + | |
12 | +/** user是所有可登录系统用户 */ | |
13 | +@Data | |
14 | +@EqualsAndHashCode(callSuper = false) | |
15 | +@TableName(ModelConstants.Table.USER_TABLE_NAME) | |
16 | +public class User extends TenantBaseEntity { | |
17 | + private static final long serialVersionUID = 834982016421849497L; | |
18 | + private String username; | |
19 | + | |
20 | + private String realName; | |
21 | + | |
22 | + private String password; | |
23 | + | |
24 | + @TableField(updateStrategy = FieldStrategy.IGNORED) | |
25 | + private String activateToken; | |
26 | + | |
27 | + private String phoneNumber; | |
28 | + | |
29 | + private String email; | |
30 | + | |
31 | + private String avatar; | |
32 | + | |
33 | + private boolean enabled = true; | |
34 | + | |
35 | + private LocalDateTime accountExpireTime; | |
36 | + | |
37 | + private String deptId; | |
38 | + | |
39 | + /** 0:超级管理员;1:租户账号;2:租户下的账号 */ | |
40 | + private Integer level; | |
41 | +} | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/yunteng/entities/UserOrganizationMapping.java
0 → 100644
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.AllArgsConstructor; | |
5 | +import lombok.Data; | |
6 | +import lombok.NoArgsConstructor; | |
7 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
8 | + | |
9 | +@Data | |
10 | +@AllArgsConstructor | |
11 | +@NoArgsConstructor | |
12 | +@TableName(ModelConstants.Table.IOTFS_USER_ORGANIZATION_MAPPING_TABLE_NAME) | |
13 | +public class UserOrganizationMapping { | |
14 | + private String userId; | |
15 | + private String organizationId; | |
16 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableName; | |
4 | +import lombok.Data; | |
5 | +import lombok.EqualsAndHashCode; | |
6 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
7 | + | |
8 | +import java.io.Serializable; | |
9 | + | |
10 | +@Data | |
11 | +@EqualsAndHashCode(callSuper = false) | |
12 | +@TableName(ModelConstants.Table.USER_ROLE_TABLE_NAME) | |
13 | +public class UserRole implements Serializable { | |
14 | + | |
15 | + private static final long serialVersionUID = -1018514294019250455L; | |
16 | + | |
17 | + /** 用户ID */ | |
18 | + private String userId; | |
19 | + /** 角色ID */ | |
20 | + private String roleId; | |
21 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.entities; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.annotation.TableField; | |
4 | +import com.baomidou.mybatisplus.annotation.TableName; | |
5 | +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; | |
6 | +import com.fasterxml.jackson.databind.JsonNode; | |
7 | +import lombok.Data; | |
8 | +import lombok.EqualsAndHashCode; | |
9 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
10 | +import org.thingsboard.server.common.data.yunteng.enums.DeviceCredentialsEnum; | |
11 | +import org.thingsboard.server.common.data.yunteng.enums.DeviceState; | |
12 | +import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; | |
13 | + | |
14 | +import java.time.LocalDateTime; | |
15 | + | |
16 | +@Data | |
17 | +@EqualsAndHashCode(callSuper = true) | |
18 | +@TableName(value = ModelConstants.Table.IOTFS_DEVICE_TABLE_NAME) | |
19 | +public class YtDevice extends TenantBaseEntity { | |
20 | + private String name; | |
21 | + | |
22 | + @TableField(typeHandler = JacksonTypeHandler.class) | |
23 | + private JsonNode deviceInfo; | |
24 | + | |
25 | + private LocalDateTime activeTime; | |
26 | + private DeviceState deviceState; | |
27 | + private String profileId; | |
28 | + private String deviceToken; | |
29 | + private String tbDeviceId; | |
30 | + private String deviceTypeId; | |
31 | + private LocalDateTime lastConnectTime; | |
32 | + private String label; | |
33 | + private DeviceTypeEnum deviceType; | |
34 | + private DeviceCredentialsEnum deviceCredentials; | |
35 | + private String organizationId; | |
36 | + /** 告警状态:0:正常 1:告警 */ | |
37 | + private Integer alarmStatus; | |
38 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import lombok.RequiredArgsConstructor; | |
4 | +import lombok.extern.slf4j.Slf4j; | |
5 | +import org.apache.commons.lang3.RandomStringUtils; | |
6 | +import org.springframework.stereotype.Service; | |
7 | +import org.thingsboard.server.common.data.yunteng.common.CommonService; | |
8 | +import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
9 | +import org.thingsboard.server.common.data.yunteng.dto.SysDictItemDTO; | |
10 | +import org.thingsboard.server.dao.yunteng.mapper.SysDictItemMapper; | |
11 | +import org.thingsboard.server.dao.yunteng.service.YtDeviceService; | |
12 | + | |
13 | +@Slf4j | |
14 | +@Service | |
15 | +@RequiredArgsConstructor | |
16 | +public class CommonServiceImpl implements CommonService { | |
17 | + | |
18 | + private final SysDictItemMapper sysDictItemMapper; | |
19 | + private final YtDeviceService deviceService; | |
20 | + @Override | |
21 | + public SysDictItemDTO getDictValueByCodeAndText(String dictCode, String codeValue) { | |
22 | + return sysDictItemMapper.getDictValueByCodeAndText(dictCode, codeValue); | |
23 | + } | |
24 | + | |
25 | + @Override | |
26 | + public String generateDeviceToken(String tenantId) { | |
27 | + String deviceToken = RandomStringUtils.randomAlphabetic(20); | |
28 | + DeviceDTO deviceDTO = new DeviceDTO(); | |
29 | + deviceDTO.setDeviceToken(deviceToken); | |
30 | + //检查数据库是否已存在对应的DeviceToken | |
31 | + if(deviceService.findDeviceInfo(tenantId,deviceDTO).size()>0){ | |
32 | + generateDeviceToken(tenantId); | |
33 | + } | |
34 | + return deviceToken; | |
35 | + } | |
36 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
4 | +import com.google.common.collect.Lists; | |
5 | +import com.google.common.collect.Sets; | |
6 | +import lombok.RequiredArgsConstructor; | |
7 | +import lombok.extern.slf4j.Slf4j; | |
8 | +import org.apache.commons.lang3.StringUtils; | |
9 | +import org.springframework.http.HttpStatus; | |
10 | +import org.springframework.security.access.AccessDeniedException; | |
11 | +import org.springframework.stereotype.Service; | |
12 | +import org.springframework.transaction.annotation.Transactional; | |
13 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
14 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | |
15 | +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException; | |
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.dto.MenuDTO; | |
19 | +import org.thingsboard.server.common.data.yunteng.enums.MenuTypeEnum; | |
20 | +import org.thingsboard.server.dao.yunteng.entities.Menu; | |
21 | +import org.thingsboard.server.dao.yunteng.mapper.MenuMapper; | |
22 | +import org.thingsboard.server.dao.yunteng.mapper.RoleMapper; | |
23 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
24 | +import org.thingsboard.server.dao.yunteng.service.MenuService; | |
25 | + | |
26 | +import java.util.*; | |
27 | + | |
28 | +@Service | |
29 | +@Slf4j | |
30 | +@RequiredArgsConstructor | |
31 | +public class MenuServiceImpl extends AbstractBaseService<MenuMapper, Menu> implements MenuService { | |
32 | + | |
33 | + private final RoleMapper roleMapper; | |
34 | + private final CacheUtils cacheUtils; | |
35 | + | |
36 | + @Override | |
37 | + public List<MenuDTO> getAllMenus(String tenantId) { | |
38 | + | |
39 | + List<Menu> menus = | |
40 | + baseMapper.selectList( | |
41 | + new QueryWrapper<Menu>().lambda().eq(Menu::getTenantCode, tenantId)); | |
42 | + Map<String, MenuDTO> menuDTOMap = new LinkedHashMap<>(menus.size()); | |
43 | + menus.forEach(menu -> menuDTOMap.put(menu.getId(), menu.getDTO(MenuDTO.class))); | |
44 | + return buildMenuDTOTree(menuDTOMap); | |
45 | + } | |
46 | + | |
47 | + @Override | |
48 | + public List<MenuDTO> getMyMenus(String tenantId,String userId,boolean isSysAdmin,boolean isTenantAdmin) { | |
49 | + List<MenuDTO> menuDTOs; | |
50 | + if (isSysAdmin) { | |
51 | + menuDTOs = baseMapper.selectSysAdminMenu(); | |
52 | + } | |
53 | + else if (isTenantAdmin) { | |
54 | + menuDTOs = baseMapper.selectTenantMenu(tenantId); | |
55 | + } | |
56 | + else { | |
57 | + menuDTOs = baseMapper.selectMyMenu(userId); | |
58 | + } | |
59 | + Map<String, MenuDTO> menuDTOMap = new LinkedHashMap<>(menuDTOs.size()); | |
60 | + menuDTOs.forEach(menuDTO -> menuDTOMap.put(menuDTO.getId(), menuDTO)); | |
61 | + return buildMenuDTOTree(menuDTOMap); | |
62 | + } | |
63 | + | |
64 | + private List<MenuDTO> buildMenuDTOTree(Map<String, MenuDTO> menuDTOMap) { | |
65 | + List<MenuDTO> result = Lists.newArrayList(); | |
66 | + for (MenuDTO node : menuDTOMap.values()) { | |
67 | + MenuDTO parent = menuDTOMap.get(node.getParentId()); | |
68 | + if (parent != null && !(node.getId().equals(parent.getId()))) { | |
69 | + parent.getChildren().add(node); | |
70 | + continue; | |
71 | + } | |
72 | + result.add(node); | |
73 | + } | |
74 | + Collections.sort(result); | |
75 | + result.forEach(node -> Collections.sort(node.getChildren())); | |
76 | + return result; | |
77 | + } | |
78 | + | |
79 | + @Override | |
80 | + @Transactional | |
81 | + public MenuDTO saveMenu(String tenantId,boolean isSysAdmin,MenuDTO menuDTO) { | |
82 | + if (menuDTO.getType() == null) { | |
83 | + menuDTO.setType(MenuTypeEnum.CUSTOM); | |
84 | + } | |
85 | + if (!isSysAdmin | |
86 | + && menuDTO.getType().equals(MenuTypeEnum.SYSADMIN)) { | |
87 | + throw new FastIotException( | |
88 | + ErrorMessage.ACCESS_DENIED.setMessage("Non-system admin cannot save system menu"), | |
89 | + HttpStatus.FORBIDDEN); | |
90 | + } | |
91 | + if (menuDTO.getType().equals(MenuTypeEnum.CUSTOM) | |
92 | + && StringUtils.isAllBlank(menuDTO.getName())) { | |
93 | + throw new DataValidationException("menu name is required when save custom menu"); | |
94 | + } | |
95 | + int count = | |
96 | + baseMapper.selectCount( | |
97 | + new QueryWrapper<Menu>().lambda().eq(Menu::getPath, menuDTO.getPath())); | |
98 | + if (count > 0) { | |
99 | + throw new DataValidationException("menu with path " + menuDTO + " already exist"); | |
100 | + } | |
101 | + menuDTO.setTenantCode(tenantId); | |
102 | + Menu menu = menuDTO.getEntity(Menu.class); | |
103 | + int insertCount = baseMapper.insert(menu); | |
104 | + if (insertCount > 0) { | |
105 | + menu.copyToDTO(menuDTO); | |
106 | + return menuDTO; | |
107 | + } | |
108 | + return null; | |
109 | + } | |
110 | + | |
111 | + @Override | |
112 | + public Optional<MenuDTO> getMenu(String id) { | |
113 | + return Optional.ofNullable(baseMapper.selectById(id)).map(menu -> menu.getDTO(MenuDTO.class)); | |
114 | + } | |
115 | + | |
116 | + @Override | |
117 | + @Transactional | |
118 | + public MenuDTO updateMenu(String tenantId,boolean isSysAdmin,MenuDTO menuDTO) { | |
119 | + Menu menu = baseMapper.selectById(menuDTO.getId()); | |
120 | + if (menu == null) { | |
121 | + throw new DataValidationException("cannot find menu to update"); | |
122 | + } else { | |
123 | + if (!isSysAdmin) { | |
124 | + if (!tenantId.equals(menuDTO.getTenantCode())) { | |
125 | + throw new AccessDeniedException("You don't have permission to update this menu"); | |
126 | + } | |
127 | + } | |
128 | + menuDTO.copyToEntity(menu); | |
129 | + baseMapper.updateById(menu); | |
130 | + if (!Objects.equals(menuDTO.getPermission(), menu.getPermission())) { | |
131 | + cacheUtils.invalidateCacheName(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY); | |
132 | + } | |
133 | + menu.copyToDTO(menuDTO); | |
134 | + } | |
135 | + return menuDTO; | |
136 | + } | |
137 | + | |
138 | + @Override | |
139 | + @Transactional | |
140 | + public boolean deleteMenus(String tenantId,String[] menuIds) { | |
141 | + Set<String> ids = Set.of(menuIds); | |
142 | + // 1. 判断是否所有的id都属于此人,admin也不可删除租户的menu | |
143 | + int notTenantMenuCount = | |
144 | + baseMapper.selectCount( | |
145 | + new QueryWrapper<Menu>() | |
146 | + .lambda() | |
147 | + .ne(Menu::getTenantCode, tenantId) | |
148 | + .in(Menu::getId, ids)); | |
149 | + if (notTenantMenuCount > 0) { | |
150 | + throw new AccessDeniedException("cannot delete menu that not create by you"); | |
151 | + } | |
152 | + // 2. 删除角色对应的menu | |
153 | + roleMapper.deleteRoleMenuMappingByMenuIds(ids); | |
154 | + // 3. 删除租户对应menu | |
155 | + baseMapper.deleteTenantMenuMappingByMenuIds(ids); | |
156 | + // 4. 删除menu | |
157 | + baseMapper.deleteBatchIds(ids); | |
158 | + cacheUtils.invalidateCacheName(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY); | |
159 | + return true; | |
160 | + } | |
161 | + | |
162 | + @Override | |
163 | + @Transactional | |
164 | + public boolean assignMenuToTenant(String tenantId,String[] menuId) { | |
165 | + Set<String> ids = Set.of(menuId); | |
166 | + int menuCountInDB = | |
167 | + baseMapper.selectCount(new QueryWrapper<Menu>().lambda().in(Menu::getId, ids)); | |
168 | + if (menuCountInDB != menuId.length) { | |
169 | + throw new DataValidationException("please ensure all menu id are valid"); | |
170 | + } | |
171 | + Set<String> existMenus = baseMapper.selectTenantMenuIds(tenantId); | |
172 | + Set<String> toDel = Sets.difference(existMenus, ids); | |
173 | + Set<String> toAdd = Sets.difference(ids, existMenus); | |
174 | + if (!toDel.isEmpty()) { | |
175 | + baseMapper.removeMenuFromTenant(tenantId, toDel); | |
176 | + } | |
177 | + if (!toAdd.isEmpty()) { | |
178 | + baseMapper.addMenuToTenant(tenantId, toAdd); | |
179 | + } | |
180 | + if (!toDel.isEmpty() && !toAdd.isEmpty()) { | |
181 | + cacheUtils.invalidate( | |
182 | + FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY, | |
183 | + FastIotConstants.CacheConfigKey.USER_PERMISSION_PREFIX + tenantId); | |
184 | + } | |
185 | + return true; | |
186 | + } | |
187 | + | |
188 | + @Override | |
189 | + @Transactional | |
190 | + public boolean assignMenuToRole(String[] menuId, String roleId) { | |
191 | + Set<String> ids = Set.of(menuId); | |
192 | + if (!ids.isEmpty()) { | |
193 | + int menuCountInDB = | |
194 | + baseMapper.selectCount(new QueryWrapper<Menu>().lambda().in(Menu::getId, ids)); | |
195 | + if (menuCountInDB != menuId.length) { | |
196 | + throw new DataValidationException("please ensure all menu id are valid"); | |
197 | + } | |
198 | + } | |
199 | + Set<String> existMenus = baseMapper.selectRoleMenuIds(roleId); | |
200 | + Set<String> toDel = Sets.difference(existMenus, ids); | |
201 | + Set<String> toAdd = Sets.difference(ids, existMenus); | |
202 | + if (!toDel.isEmpty()) { | |
203 | + baseMapper.removeMenuFromRole(roleId, toDel); | |
204 | + } | |
205 | + if (!toAdd.isEmpty()) { | |
206 | + baseMapper.addMenuToRole(roleId, toAdd); | |
207 | + } | |
208 | + if (!toAdd.isEmpty() && !toDel.isEmpty()) { | |
209 | + cacheUtils.invalidateCacheName(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY); | |
210 | + } | |
211 | + return true; | |
212 | + } | |
213 | + | |
214 | + @Override | |
215 | + public Set<String> getMenuIdsByRoleId(String roleId) { | |
216 | + return roleMapper.getMenuIdsByRoleId(roleId); | |
217 | + } | |
218 | +} | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/yunteng/impl/MessageTemplateServiceImpl.java
0 → 100644
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
3 | +import lombok.RequiredArgsConstructor; | |
4 | +import lombok.extern.slf4j.Slf4j; | |
5 | +import org.apache.commons.lang3.StringUtils; | |
6 | +import org.springframework.stereotype.Service; | |
7 | +import org.springframework.transaction.annotation.Transactional; | |
8 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
9 | +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException; | |
10 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
11 | +import org.thingsboard.server.common.data.yunteng.dto.MessageTemplateDTO; | |
12 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
13 | +import org.thingsboard.server.dao.yunteng.entities.MessageTemplate; | |
14 | +import org.thingsboard.server.dao.yunteng.mapper.MessageTemplateMapper; | |
15 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
16 | +import org.thingsboard.server.dao.yunteng.service.MessageTemplateService; | |
17 | + | |
18 | +import java.util.List; | |
19 | +import java.util.Map; | |
20 | +import java.util.Set; | |
21 | + | |
22 | +@Service | |
23 | +@Slf4j | |
24 | +@RequiredArgsConstructor | |
25 | +public class MessageTemplateServiceImpl | |
26 | + extends AbstractBaseService<MessageTemplateMapper, MessageTemplate> | |
27 | + implements MessageTemplateService { | |
28 | + @Override | |
29 | + public PageData<MessageTemplateDTO> page(Map<String, Object> queryMap) { | |
30 | +// queryMap.put("tenantCode",SecurityContext.getCurrentUser().getTenantCode()); | |
31 | + IPage<MessageTemplate> configIPage = getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME,false); | |
32 | + IPage<MessageTemplateDTO> iPage = baseMapper.getTemplatePage(configIPage,queryMap); | |
33 | + return getPageData(iPage, MessageTemplateDTO.class); | |
34 | + } | |
35 | + | |
36 | + @Override | |
37 | + @Transactional | |
38 | + public MessageTemplateDTO saveMessageTemplate(MessageTemplateDTO templateDTO) { | |
39 | + MessageTemplate messageTemplate = new MessageTemplate(); | |
40 | + templateDTO.copyToEntity(messageTemplate); | |
41 | +// messageTemplate.setTenantCode(SecurityContext.getCurrentUser().getTenantCode()); | |
42 | + baseMapper.insert(messageTemplate); | |
43 | + messageTemplate.copyToDTO(templateDTO); | |
44 | + return templateDTO; | |
45 | + } | |
46 | + | |
47 | + @Override | |
48 | + @Transactional | |
49 | + public boolean deleteMessageTemplate(Set<String> ids) { | |
50 | + return baseMapper.deleteBatchIds(ids) > 0; | |
51 | + } | |
52 | + | |
53 | + @Override | |
54 | + @Transactional | |
55 | + public MessageTemplateDTO updateMessageTemplate(MessageTemplateDTO templateDTO) { | |
56 | + | |
57 | +// String tenantCode = SecurityContext.getCurrentUser().getTenantCode(); | |
58 | + //查询该租户下 是否已经启用相同消息类型、相同用途的模板 | |
59 | + MessageTemplateDTO queryTemplate = new MessageTemplateDTO(); | |
60 | + queryTemplate.setTemplatePurpose(templateDTO.getTemplatePurpose()); | |
61 | + queryTemplate.setMessageType(templateDTO.getMessageType()); | |
62 | +// queryTemplate.setTemplateCode(tenantCode); | |
63 | + if(StringUtils.isEmpty(templateDTO.getTemplatePurpose()) || StringUtils.isEmpty(templateDTO.getMessageType())){ | |
64 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
65 | + } | |
66 | + List<MessageTemplateDTO> messageTemplateDTOList = baseMapper.findMessageTemplate(queryTemplate); | |
67 | + if(null!=messageTemplateDTOList && messageTemplateDTOList.size()>0){ | |
68 | + throw new DataValidationException(ErrorMessage.NOT_SET_PASSWORD_TEMPLATE.getMessage()); | |
69 | + } | |
70 | + MessageTemplate messageTemplate = baseMapper.selectById(templateDTO.getId()); | |
71 | + templateDTO.copyToEntity(messageTemplate); | |
72 | +// messageTemplate.setTenantCode(tenantCode); | |
73 | + baseMapper.updateById(messageTemplate); | |
74 | + messageTemplate.copyToDTO(templateDTO); | |
75 | + return templateDTO; | |
76 | + } | |
77 | + | |
78 | + @Override | |
79 | + public List<MessageTemplateDTO> findMessageTemplate(MessageTemplateDTO templateDTO) { | |
80 | +// templateDTO.setTenantCode(SecurityContext.getCurrentUser().getTenantCode()); | |
81 | + return baseMapper.findMessageTemplate(templateDTO); | |
82 | + } | |
83 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
4 | +import com.google.common.collect.Lists; | |
5 | +import com.google.common.collect.Sets; | |
6 | +import lombok.RequiredArgsConstructor; | |
7 | +import org.apache.commons.lang3.StringUtils; | |
8 | +import org.springframework.stereotype.Service; | |
9 | +import org.springframework.transaction.annotation.Transactional; | |
10 | +import org.springframework.util.Assert; | |
11 | +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException; | |
12 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
13 | +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
14 | +import org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO; | |
15 | +import org.thingsboard.server.dao.yunteng.entities.UserOrganizationMapping; | |
16 | +import org.thingsboard.server.dao.yunteng.entities.Organization; | |
17 | +import org.thingsboard.server.dao.yunteng.entities.User; | |
18 | +import org.thingsboard.server.dao.yunteng.mapper.DeviceMapper; | |
19 | +import org.thingsboard.server.dao.yunteng.mapper.OrganizationMapper; | |
20 | +import org.thingsboard.server.dao.yunteng.mapper.UserMapper; | |
21 | +import org.thingsboard.server.dao.yunteng.mapper.UserOrganizationMappingMapper; | |
22 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
23 | +import org.thingsboard.server.dao.yunteng.service.OrganizationService; | |
24 | + | |
25 | +import java.util.*; | |
26 | +import java.util.stream.Collectors; | |
27 | + | |
28 | +@Service | |
29 | +@RequiredArgsConstructor | |
30 | +public class OrganizationServiceImpl extends AbstractBaseService<OrganizationMapper, Organization> | |
31 | + implements OrganizationService { | |
32 | + | |
33 | + private final UserOrganizationMappingMapper userOrganizationMappingMapper; | |
34 | + private final UserMapper userMapper; | |
35 | + private final DeviceMapper deviceMapper; | |
36 | + | |
37 | + @Override | |
38 | + @Transactional | |
39 | + public OrganizationDTO saveOrganization(OrganizationDTO organizationDTO) { | |
40 | + Assert.notNull(organizationDTO.getName(), "organization name cannot be null"); | |
41 | + if (StringUtils.isNotBlank(organizationDTO.getParentId())) { | |
42 | + Organization organization = baseMapper.selectById(organizationDTO.getParentId()); | |
43 | + if (organization == null) { | |
44 | + throw new DataValidationException("parent organization not exist!"); | |
45 | + } else { | |
46 | + if (!organization | |
47 | + .getTenantCode() | |
48 | + .equals(null)) {//TODO getCurrentUser().getTenantCode() | |
49 | + throw new DataValidationException("parent organization not exist."); | |
50 | + } | |
51 | + } | |
52 | + } | |
53 | + Organization organization = new Organization(); | |
54 | + //organizationDTO.setTenantCode(getCurrentUser().getTenantCode()); | |
55 | + organizationDTO.copyToEntity(organization, "id"); | |
56 | + baseMapper.insert(organization); | |
57 | + organization.copyToDTO(organizationDTO); | |
58 | + return organizationDTO; | |
59 | + } | |
60 | + | |
61 | + @Override | |
62 | + @Transactional | |
63 | + public boolean deleteOrganizations(DeleteDTO deleteDTO) { | |
64 | + if(null == deleteDTO || deleteDTO.getIds().isEmpty()){ | |
65 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
66 | + } | |
67 | + String[] ids = deleteDTO.getIds().toArray(new String[deleteDTO.getIds().size()]); | |
68 | + Set<String> idToDelete = | |
69 | + baseMapper | |
70 | + .findOrganizationTreeList( | |
71 | + null, Arrays.asList(ids))//TODO getCurrentUser().getTenantCode() | |
72 | + .stream() | |
73 | + .map(OrganizationDTO::getId) | |
74 | + .collect(Collectors.toSet()); | |
75 | + if (idToDelete.size() != ids.length) { | |
76 | + throw new DataValidationException("待删除数据存在子项,不能删除!"); | |
77 | + } | |
78 | + List<UserOrganizationMapping> userOrganizationMappingList = | |
79 | + userOrganizationMappingMapper.selectList( | |
80 | + new QueryWrapper<UserOrganizationMapping>() | |
81 | + .lambda() | |
82 | + .in(UserOrganizationMapping::getOrganizationId, idToDelete)); | |
83 | + if (!userOrganizationMappingList.isEmpty()) { | |
84 | + throw new DataValidationException("待删除数据存在关联用户,不能删除!"); | |
85 | + } | |
86 | + // 查询是否有设备使用该组织 | |
87 | +// List<Device> deviceList = deviceMapper.selectList( | |
88 | +// new QueryWrapper<Device>() | |
89 | +// .lambda() | |
90 | +// .eq(Device::getTenantCode, getCurrentUser().getTenantCode()) | |
91 | +// .eq(Device::getOrganizationId,ids)); | |
92 | +// if (!deviceList.isEmpty()) { | |
93 | +// throw new DataValidationException("待删除数据存在关联设备,不能删除!"); | |
94 | +// } | |
95 | +// doDeleteUserOrganizationMapping(idToDelete); | |
96 | + return baseMapper.deleteBatchIds(idToDelete)>0; | |
97 | + } | |
98 | + | |
99 | + private void doDeleteUserOrganizationMapping(Collection<String> organizationIds) { | |
100 | + userOrganizationMappingMapper.delete( | |
101 | + new QueryWrapper<UserOrganizationMapping>() | |
102 | + .lambda() | |
103 | + .in(UserOrganizationMapping::getOrganizationId, organizationIds)); | |
104 | + } | |
105 | + | |
106 | + @Override | |
107 | + @Transactional | |
108 | + public OrganizationDTO updateOrganization(OrganizationDTO organizationDTO) { | |
109 | +// Organization organization = baseMapper.selectById(organizationDTO.getId()); | |
110 | +// Organization parent = null; | |
111 | +// if (StringUtils.isNotBlank(organizationDTO.getParentId())) { | |
112 | +// Organization parentOrganization = baseMapper.selectById(organizationDTO.getParentId()); | |
113 | +// if (parentOrganization | |
114 | +// .getTenantCode() | |
115 | +// .equals(getCurrentUser().getTenantCode())) { | |
116 | +// parent = parentOrganization; | |
117 | +// } | |
118 | +// } | |
119 | +// if (organization == null) { | |
120 | +// return null; | |
121 | +// } | |
122 | +// if (organization.getName().equals(organizationDTO.getName()) | |
123 | +// && organization.getSort() == organizationDTO.getSort() | |
124 | +// && organization.getRemark().equals(organizationDTO.getRemark()) | |
125 | +// && Objects.equals(organization.getParentId(), organizationDTO.getParentId())) { | |
126 | +// return organizationDTO; | |
127 | +// } | |
128 | +// organization.setName(organizationDTO.getName()); | |
129 | +// organization.setRemark(organizationDTO.getRemark()); | |
130 | +// organization.setSort(organizationDTO.getSort()); | |
131 | +// if (parent != null) { | |
132 | +// organization.setParentId(parent.getId()); | |
133 | +// } | |
134 | +// baseMapper.updateById(organization); | |
135 | +// organization.copyToDTO(organizationDTO); | |
136 | +// return organizationDTO; | |
137 | + return null; | |
138 | + } | |
139 | + | |
140 | + @Override | |
141 | + public List<OrganizationDTO> getMyOrganizations() { | |
142 | +// if (getCurrentUser().isTenantAdmin()) { | |
143 | +// return findOrganizationTree(getCurrentUser().getTenantCode()); | |
144 | +// } else { | |
145 | +// Set<String> organizationIds = | |
146 | +// userOrganizationMappingMapper | |
147 | +// .selectList( | |
148 | +// new QueryWrapper<UserOrganizationMapping>() | |
149 | +// .lambda() | |
150 | +// .in( | |
151 | +// UserOrganizationMapping::getUserId, | |
152 | +// getCurrentUser().getUserId())) | |
153 | +// .stream() | |
154 | +// .map(UserOrganizationMapping::getOrganizationId) | |
155 | +// .collect(Collectors.toSet()); | |
156 | +// List<Organization> organizations = | |
157 | +// baseMapper.selectList( | |
158 | +// new QueryWrapper<Organization>() | |
159 | +// .lambda() | |
160 | +// .eq(Organization::getTenantCode, getCurrentUser().getTenantCode()) | |
161 | +// .in(organizationIds.size() > 0, Organization::getId, organizationIds)); | |
162 | +// return TreeUtils.buildTree(ReflectUtils.sourceToTarget(organizations, OrganizationDTO.class)); | |
163 | +// } | |
164 | + return null; | |
165 | + } | |
166 | + | |
167 | + private List<OrganizationDTO> findOrganizationTree(String tenantCode) { | |
168 | + List<OrganizationDTO> organizationTreeList = | |
169 | + baseMapper.findOrganizationTreeList(tenantCode, null); | |
170 | + return buildOrganizationDTOTree(organizationTreeList); | |
171 | + } | |
172 | + | |
173 | + private List<OrganizationDTO> buildOrganizationDTOTree( | |
174 | + List<OrganizationDTO> organizationTreeList) { | |
175 | + Map<String, OrganizationDTO> organizationDTOMap = | |
176 | + new LinkedHashMap<>(organizationTreeList.size()); | |
177 | + HashSet<OrganizationDTO> organizationDTOSet = Sets.newHashSet(organizationTreeList); | |
178 | + organizationDTOSet.forEach( | |
179 | + organizationDTO -> organizationDTOMap.put(organizationDTO.getId(), organizationDTO)); | |
180 | + List<OrganizationDTO> result = Lists.newArrayList(); | |
181 | + for (OrganizationDTO node : organizationDTOMap.values()) { | |
182 | + OrganizationDTO parent = organizationDTOMap.get(node.getParentId()); | |
183 | + if (parent != null && !(node.getId().equals(parent.getId()))) { | |
184 | + parent.getChildren().add(node); | |
185 | + continue; | |
186 | + } | |
187 | + result.add(node); | |
188 | + } | |
189 | + Collections.sort(result); | |
190 | + result.forEach(node -> Collections.sort(node.getChildren())); | |
191 | + return result; | |
192 | + } | |
193 | + | |
194 | + @Override | |
195 | + @Transactional | |
196 | + public void bindUserToOrganization(String userId, String[] organizationIds) { | |
197 | +// User user = userMapper.selectById(userId); | |
198 | +// if (user == null) { | |
199 | +// throw new DataValidationException("所选用户不存在"); | |
200 | +// } | |
201 | +// if (!user.getTenantCode().equals(getCurrentUser().getTenantCode())) { | |
202 | +// throw new DataValidationException("所选用户不可用"); | |
203 | +// } | |
204 | +// if (null != organizationIds && organizationIds.length > 0) { | |
205 | +// Set<String> newBinding = | |
206 | +// baseMapper | |
207 | +// .findOrganizationTreeList( | |
208 | +// getCurrentUser().getTenantCode(), Arrays.asList(organizationIds)) | |
209 | +// .stream() | |
210 | +// .map(OrganizationDTO::getId) | |
211 | +// .collect(Collectors.toSet()); | |
212 | +// Set<String> existBinding = | |
213 | +// userOrganizationMappingMapper | |
214 | +// .selectList( | |
215 | +// new QueryWrapper<UserOrganizationMapping>() | |
216 | +// .lambda() | |
217 | +// .eq(UserOrganizationMapping::getUserId, userId)) | |
218 | +// .stream() | |
219 | +// .map(UserOrganizationMapping::getOrganizationId) | |
220 | +// .collect(Collectors.toSet()); | |
221 | +// Set<String> toDel = Sets.difference(existBinding, newBinding); | |
222 | +// Set<String> toAdd = Sets.difference(newBinding, existBinding); | |
223 | +// if (!toDel.isEmpty()) { | |
224 | +// userOrganizationMappingMapper.delete( | |
225 | +// new QueryWrapper<UserOrganizationMapping>() | |
226 | +// .lambda() | |
227 | +// .in(UserOrganizationMapping::getUserId, userId) | |
228 | +// .in(UserOrganizationMapping::getOrganizationId, toDel)); | |
229 | +// } | |
230 | +// if (!toAdd.isEmpty()) { | |
231 | +// toAdd.stream() | |
232 | +// .map(organizationId -> new UserOrganizationMapping(userId, organizationId)) | |
233 | +// .forEach(userOrganizationMappingMapper::insert); | |
234 | +// } | |
235 | +// } | |
236 | + } | |
237 | + | |
238 | + @Override | |
239 | + @Transactional | |
240 | + public void unBindUserToOrganization(Set<String> userIds) { | |
241 | + for (String userId : userIds) { | |
242 | + User user = userMapper.selectById(userId); | |
243 | + if (user == null) { | |
244 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
245 | + } | |
246 | + userOrganizationMappingMapper.delete( | |
247 | + new QueryWrapper<UserOrganizationMapping>() | |
248 | + .lambda() | |
249 | + .eq(UserOrganizationMapping::getUserId, userId)); | |
250 | + } | |
251 | + } | |
252 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import com.google.common.collect.Sets; | |
6 | +import lombok.RequiredArgsConstructor; | |
7 | +import lombok.extern.slf4j.Slf4j; | |
8 | +import org.apache.commons.lang3.RandomStringUtils; | |
9 | +import org.apache.commons.lang3.StringUtils; | |
10 | +import org.springframework.boot.actuate.endpoint.SecurityContext; | |
11 | +import org.springframework.security.access.AccessDeniedException; | |
12 | +import org.springframework.stereotype.Service; | |
13 | +import org.springframework.transaction.annotation.Transactional; | |
14 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
15 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | |
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.dto.RoleDTO; | |
19 | +import org.thingsboard.server.common.data.yunteng.dto.request.RoleReqDTO; | |
20 | +import org.thingsboard.server.common.data.yunteng.enums.RoleEnum; | |
21 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
22 | +import org.thingsboard.server.dao.yunteng.entities.Role; | |
23 | +import org.thingsboard.server.dao.yunteng.entities.TenantMenu; | |
24 | +import org.thingsboard.server.dao.yunteng.entities.TenantRole; | |
25 | +import org.thingsboard.server.dao.yunteng.entities.UserRole; | |
26 | +import org.thingsboard.server.dao.yunteng.mapper.*; | |
27 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
28 | +import org.thingsboard.server.dao.yunteng.service.MenuService; | |
29 | +import org.thingsboard.server.dao.yunteng.service.RoleService; | |
30 | + | |
31 | +import java.util.List; | |
32 | +import java.util.Map; | |
33 | +import java.util.Optional; | |
34 | +import java.util.Set; | |
35 | +import java.util.stream.Collectors; | |
36 | + | |
37 | +@Service | |
38 | +@Slf4j | |
39 | +@RequiredArgsConstructor | |
40 | +public class RoleServiceImpl extends AbstractBaseService<RoleMapper, Role> implements RoleService { | |
41 | + | |
42 | + private final MenuMapper menuMapper; | |
43 | + private final CacheUtils cacheUtils; | |
44 | + private final MenuService menuService; | |
45 | + private final TenantMenuMapper tenantMenuMapper; | |
46 | + private final TenantRoleMapper tenantRoleMapper; | |
47 | + private final UserRoleMapper userRoleMapper; | |
48 | + | |
49 | + @Override | |
50 | + public PageData<RoleDTO> page(boolean isSysadmin,boolean isPlatformAdmin, String tenantId,Map<String, Object> queryMap) { | |
51 | + IPage<Role> roleIPage = | |
52 | + baseMapper.selectPage( | |
53 | + getPage(queryMap, "create_time", false), | |
54 | + new QueryWrapper<Role>() | |
55 | + .lambda() | |
56 | + .eq(queryMap.get("status") != null, Role::isEnabled, queryMap.get("status")) | |
57 | + .eq(queryMap.get("roleType") != null, Role::getRoleType, queryMap.get("roleType")) | |
58 | + .ne(queryMap.get("roleType") == null, Role::getRoleType, RoleEnum.ROLE_TENANT_ADMIN) | |
59 | + .ne( | |
60 | + queryMap.get("roleType") == null | |
61 | + && isPlatformAdmin, | |
62 | + Role::getRoleType, | |
63 | + RoleEnum.ROLE_SYS_ADMIN) | |
64 | + .eq( | |
65 | + !isSysadmin, | |
66 | + Role::getTenantCode, | |
67 | + tenantId) | |
68 | + .like( | |
69 | + queryMap.get("roleName") != null, | |
70 | + Role::getName, | |
71 | + String.valueOf(queryMap.get("roleName")))); | |
72 | + return getPageData(roleIPage, RoleDTO.class); | |
73 | + } | |
74 | + | |
75 | + @Override | |
76 | + @Transactional | |
77 | + public boolean deleteRole(String[] roleIds,String tenantId) { | |
78 | + Set<String> ids = Set.of(roleIds); | |
79 | + int notTenantMenuCount = | |
80 | + baseMapper.selectCount( | |
81 | + new QueryWrapper<Role>() | |
82 | + .lambda() | |
83 | + .ne(Role::getTenantCode, tenantId) | |
84 | + .in(Role::getId, ids)); | |
85 | + if (notTenantMenuCount > 0) { | |
86 | + throw new AccessDeniedException("cannot delete role that not create by you"); | |
87 | + } | |
88 | + // 判断该角色下面是否有用户 | |
89 | + Set<String> userIds = baseMapper.checkRoleUserMappingByRoleIds(ids); | |
90 | + if (null != userIds && userIds.size() > 0) { | |
91 | + throw new FastIotException(ErrorMessage.ROLE_IN_USE); | |
92 | + } | |
93 | + // delete sys_role_menu mapping | |
94 | + baseMapper.deleteRoleMenuMappingByRoleIds(ids); | |
95 | + // delete role | |
96 | + baseMapper.deleteBatchIds(ids); | |
97 | + // FIXME 频繁删除role造成缓存效果不大 | |
98 | + cacheUtils.invalidateCacheName(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY); | |
99 | + return true; | |
100 | + } | |
101 | + | |
102 | + @Override | |
103 | + public Set<String> getPermissions(boolean isSysadmin,boolean isTenantAdmin,String tenantId,String useerId) { | |
104 | + Set<String> permissions = Sets.newHashSet(); | |
105 | + Set<String> allPermission; | |
106 | + String cacheKey; | |
107 | + boolean cachePresent; | |
108 | + if (isSysadmin) { | |
109 | + cacheKey = | |
110 | + FastIotConstants.CacheConfigKey.USER_PERMISSION_PREFIX + RoleEnum.ROLE_SYS_ADMIN.name(); | |
111 | + Optional<Set<String>> optionalPermission = | |
112 | + cacheUtils.get(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY, cacheKey); | |
113 | + cachePresent = optionalPermission.isPresent(); | |
114 | + allPermission = optionalPermission.orElseGet(menuMapper::getAllPermission); | |
115 | + } else if (isTenantAdmin) { | |
116 | + cacheKey = | |
117 | + FastIotConstants.CacheConfigKey.USER_PERMISSION_PREFIX | |
118 | + + tenantId; | |
119 | + Optional<Set<String>> optionalPermission = | |
120 | + cacheUtils.get(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY, cacheKey); | |
121 | + cachePresent = optionalPermission.isPresent(); | |
122 | + allPermission = | |
123 | + optionalPermission.orElseGet( | |
124 | + () -> | |
125 | + menuMapper.getAllPermissionsByTenantCode(tenantId)); | |
126 | + } else { | |
127 | + cacheKey = | |
128 | + FastIotConstants.CacheConfigKey.USER_PERMISSION_PREFIX | |
129 | + + useerId; | |
130 | + Optional<Set<String>> optionalPermission = | |
131 | + cacheUtils.get(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY, cacheKey); | |
132 | + cachePresent = optionalPermission.isPresent(); | |
133 | + allPermission = | |
134 | + optionalPermission.orElseGet( | |
135 | + () -> | |
136 | + menuMapper.getAllPermissionsByUserId(useerId)); | |
137 | + } | |
138 | + if (cachePresent) { | |
139 | + return allPermission; | |
140 | + } else { | |
141 | + allPermission.forEach( | |
142 | + permission -> permissions.addAll(Sets.newHashSet(permission.split(",")))); | |
143 | + cacheUtils.put(FastIotConstants.CacheConfigKey.CACHE_CONFIG_KEY, cacheKey, permissions); | |
144 | + } | |
145 | + return permissions; | |
146 | + } | |
147 | + | |
148 | + @Override | |
149 | + @Transactional | |
150 | + public void updateRoleStatus(String roleId, int status,boolean isSysadmin,String tenantId) { | |
151 | + Optional.ofNullable( | |
152 | + baseMapper.selectOne( | |
153 | + new QueryWrapper<Role>() | |
154 | + .lambda() | |
155 | + .eq(Role::getId, roleId) | |
156 | + .eq( | |
157 | + !isSysadmin, | |
158 | + Role::getTenantCode, | |
159 | + tenantId))) | |
160 | + .ifPresent( | |
161 | + role -> { | |
162 | + role.setEnabled(status == 1); | |
163 | + baseMapper.updateById(role); | |
164 | + }); | |
165 | + } | |
166 | + | |
167 | + @Override | |
168 | + @Transactional | |
169 | + public RoleDTO saveOrUpdateRoleInfoWithMenu(RoleReqDTO roleReqDTO,boolean isSysadmin,boolean isPlatformAdmin,String tenantId) { | |
170 | + Role role; | |
171 | + // 默认普通管理员角色,即租户管理员添加的角色 | |
172 | + var roleType = RoleEnum.ROLE_NORMAL_USER.name(); | |
173 | + if (null != roleReqDTO.getRoleType()) { | |
174 | + roleType = roleReqDTO.getRoleType().name(); | |
175 | + } else { | |
176 | + if (isSysadmin | |
177 | + || isPlatformAdmin) { | |
178 | + roleType = RoleEnum.ROLE_PLATFORM_ADMIN.name(); | |
179 | + } | |
180 | + } | |
181 | + boolean update = StringUtils.isNotBlank(roleReqDTO.getId()); | |
182 | + if (update) { | |
183 | + // do update | |
184 | + role = | |
185 | + baseMapper.selectOne( | |
186 | + new QueryWrapper<Role>() | |
187 | + .lambda() | |
188 | + .eq(Role::getId, roleReqDTO.getId()) | |
189 | + .eq( | |
190 | + !isSysadmin, | |
191 | + Role::getTenantCode, | |
192 | + tenantId)); | |
193 | + if (role == null) { | |
194 | + return null; | |
195 | + } else { | |
196 | + role.setRemark(roleReqDTO.getRemark()); | |
197 | + role.setName(roleReqDTO.getName()); | |
198 | + role.setEnabled(roleReqDTO.getStatus() == 1); | |
199 | + baseMapper.updateById(role); | |
200 | + } | |
201 | + } else { | |
202 | + // do save | |
203 | + role = new Role(); | |
204 | + role.setRoleType(roleType); | |
205 | + role.setCode(RandomStringUtils.randomAlphabetic(10)); | |
206 | + role.setRemark(roleReqDTO.getRemark()); | |
207 | + role.setName(roleReqDTO.getName()); | |
208 | + role.setEnabled(roleReqDTO.getStatus() == 1); | |
209 | + role.setTenantCode(tenantId); | |
210 | + baseMapper.insert(role); | |
211 | + } | |
212 | + // do update or save menu associate with this roleId | |
213 | + menuService.assignMenuToRole( | |
214 | + roleReqDTO.getMenu().toArray(new String[roleReqDTO.getMenu().size()]), role.getId()); | |
215 | + // 如果是租户管理员角色并且是更新,则需要更新租户菜单表 | |
216 | + if (role.getRoleType().equals(RoleEnum.ROLE_TENANT_ADMIN.name()) && update) { | |
217 | + List<String> menus = roleReqDTO.getMenu(); | |
218 | + // 先删除以前的租户菜单,再更新新的租户菜单 | |
219 | + // 1、查询这个角色有几个租户用户 | |
220 | + // 2、删除并更新对应租户的信息 | |
221 | + List<TenantRole> tenantRoles = | |
222 | + tenantRoleMapper.selectList( | |
223 | + new QueryWrapper<TenantRole>().lambda().eq(TenantRole::getRoleId, role.getId())); | |
224 | + tenantRoles.forEach( | |
225 | + tenantRole -> { | |
226 | + String updateTenantCode = tenantRole.getTenantCode(); | |
227 | + int deleteCount = | |
228 | + tenantMenuMapper.delete( | |
229 | + new QueryWrapper<TenantMenu>() | |
230 | + .lambda() | |
231 | + .eq(TenantMenu::getTenantCode, updateTenantCode)); | |
232 | + if (deleteCount > 0) { | |
233 | + menus.forEach( | |
234 | + menu -> { | |
235 | + TenantMenu tenantMenu = new TenantMenu(); | |
236 | + tenantMenu.setMenuId(menu); | |
237 | + tenantMenu.setTenantCode(updateTenantCode); | |
238 | + tenantMenuMapper.insert(tenantMenu); | |
239 | + }); | |
240 | + } | |
241 | + }); | |
242 | + } | |
243 | + return role.getDTO(RoleDTO.class); | |
244 | + } | |
245 | + | |
246 | + @Override | |
247 | + public List<RoleDTO> findRoleInfo(boolean isTenantAdmin,String tenantId,String userId,RoleDTO roleDTO) { | |
248 | + if (StringUtils.isEmpty(roleDTO.getTenantCode())) { | |
249 | + roleDTO.setTenantCode(tenantId); | |
250 | + } | |
251 | + if (isTenantAdmin) { | |
252 | + // 租户管理员既要查询自己拥有的角色,也要查询自己创建的角色 | |
253 | + List<String> roleIds = | |
254 | + userRoleMapper | |
255 | + .selectList(new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, userId)) | |
256 | + .stream() | |
257 | + .map(UserRole::getRoleId) | |
258 | + .collect(Collectors.toList()); | |
259 | + roleDTO.setRoleIds(roleIds.toArray(new String[roleIds.size()])); | |
260 | + } | |
261 | + return baseMapper.findRoleInfo(roleDTO); | |
262 | + } | |
263 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
4 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
5 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
6 | +import com.fasterxml.jackson.databind.JsonNode; | |
7 | +import lombok.RequiredArgsConstructor; | |
8 | +import lombok.extern.slf4j.Slf4j; | |
9 | +import org.apache.commons.lang3.StringUtils; | |
10 | +import org.springframework.stereotype.Service; | |
11 | +import org.springframework.transaction.annotation.Transactional; | |
12 | +import org.thingsboard.server.common.data.DeviceProfile; | |
13 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
14 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
15 | +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException; | |
16 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
17 | +import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
18 | +import org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO; | |
19 | +import org.thingsboard.server.common.data.yunteng.enums.DeviceState; | |
20 | +import org.thingsboard.server.common.data.yunteng.enums.DeviceTypeEnum; | |
21 | +import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils; | |
22 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
23 | +import org.thingsboard.server.dao.yunteng.entities.Organization; | |
24 | +import org.thingsboard.server.dao.yunteng.entities.YtDevice; | |
25 | +import org.thingsboard.server.dao.yunteng.mapper.DeviceMapper; | |
26 | +import org.thingsboard.server.dao.yunteng.mapper.DeviceProfileMapper; | |
27 | +import org.thingsboard.server.dao.yunteng.mapper.OrganizationMapper; | |
28 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
29 | +import org.thingsboard.server.dao.yunteng.service.YtDeviceService; | |
30 | + | |
31 | +import java.util.*; | |
32 | +import java.util.stream.Collectors; | |
33 | + | |
34 | +@Service | |
35 | +@RequiredArgsConstructor | |
36 | +@Slf4j | |
37 | +public class YtDeviceServiceImpl extends AbstractBaseService<DeviceMapper, YtDevice> | |
38 | + implements YtDeviceService { | |
39 | + | |
40 | +// private final TBConfig tbConfig; | |
41 | +// private final TBConnectService tbConnectService; | |
42 | +// private final TbDBService tbDBService; | |
43 | + private final DeviceProfileMapper deviceProfileMapper; | |
44 | + private final OrganizationMapper organizationMapper; | |
45 | + | |
46 | + @Override | |
47 | + // @Transactional | |
48 | + // 事务会导致 tbDBService 多数据源失效 | |
49 | + public DeviceDTO insertOrUpdate(String tenantId,DeviceDTO deviceDTO) { | |
50 | + if (StringUtils.isBlank(deviceDTO.getId())) { | |
51 | + return insert(tenantId,deviceDTO); | |
52 | + } else { | |
53 | + return update(tenantId,deviceDTO); | |
54 | + } | |
55 | + } | |
56 | + | |
57 | + private DeviceDTO update(String tenantId,DeviceDTO deviceDTO) { | |
58 | + YtDevice device = baseMapper.selectById(deviceDTO.getId()); | |
59 | + if (!device.getTenantCode().equals(tenantId)) { | |
60 | + return null; | |
61 | + } | |
62 | + validateDeviceDTO(tenantId,deviceDTO, false); | |
63 | + List<YtDevice> devices = | |
64 | + baseMapper.selectList( | |
65 | + new QueryWrapper<YtDevice>() | |
66 | + .lambda() | |
67 | +// .eq(YtDevice::getDeviceToken, deviceDTO.getDeviceToken()) | |
68 | + ); | |
69 | + if (!devices.isEmpty()) { | |
70 | + // 如果device token已经存在,那么必定只有一个,不会有多个 | |
71 | + YtDevice deviceExistWithSameToken = devices.get(0); | |
72 | + if (!deviceExistWithSameToken.getId().equals(deviceDTO.getId())) { | |
73 | + throw new DataValidationException("设备Device Token已经存在!"); | |
74 | + } | |
75 | + } | |
76 | + // 首先update tb, 需要更新的字段有 | |
77 | + // name, tbDeviceProfileId, label, isGateway, deviceToken | |
78 | + /*if (tbConfig.isEnabled()) { | |
79 | + validateUpdate(deviceDTO); | |
80 | + deviceDTO.setTbDeviceId(device.getTbDeviceId()); | |
81 | + // 判断name, tbDeviceProfileId, label, isGateway是否有更新 | |
82 | + boolean changed = detectDeviceChange(deviceDTO, device); | |
83 | + if (changed) { | |
84 | + Device tbDevice = buildTbDeviceFromDeviceDTO(deviceDTO); | |
85 | + try { | |
86 | + tbConnectService.saveDevice(tbDevice, deviceDTO.getDeviceToken()).get(); | |
87 | + } catch (InterruptedException | ExecutionException e) { | |
88 | + log.error("update device to tb error:{}", e.getMessage()); | |
89 | + throw new FastIotException(ErrorMessage.CONNECT_TO_TB_ERROR); | |
90 | + } | |
91 | + } | |
92 | + // update deviceToken | |
93 | + if (!deviceDTO.getDeviceToken().equals(device.getDeviceToken())) { | |
94 | + CredentialEntity credentialEntity = | |
95 | + tbDBService.findDeviceCredentialsByDeviceId(deviceDTO.getTbDeviceId()); | |
96 | + if (credentialEntity == null) { | |
97 | + log.error("tb 无此设备信息->tbDeviceId[{}]", deviceDTO.getTbDeviceId()); | |
98 | + throw new FastIotException(ErrorMessage.CONNECT_TO_TB_ERROR.setMessage("tb 无此设备信息")); | |
99 | + } | |
100 | + credentialEntity.setCredentialsId(deviceDTO.getDeviceToken()); | |
101 | + TBCredential tbCredential = buildTBCredential(credentialEntity); | |
102 | + try { | |
103 | + TBCredential newTbCredentials = tbConnectService.saveDeviceCredential(tbCredential).get(); | |
104 | + if (newTbCredentials == null) { | |
105 | + throw new FastIotException( | |
106 | + ErrorMessage.CONNECT_TO_TB_ERROR.setMessage("update tb credentials error")); | |
107 | + } | |
108 | + } catch (InterruptedException | ExecutionException e) { | |
109 | + log.error("update device to tb error:{}", e.getMessage()); | |
110 | + throw new FastIotException(ErrorMessage.CONNECT_TO_TB_ERROR); | |
111 | + } | |
112 | + } | |
113 | + }*/ | |
114 | + deviceDTO.copyToEntity( | |
115 | + device, | |
116 | + ModelConstants.TablePropertyMapping.ACTIVE_TIME, | |
117 | + ModelConstants.TablePropertyMapping.DEVICE_STATE, | |
118 | + ModelConstants.TablePropertyMapping.TB_DEVICE_ID, | |
119 | + ModelConstants.TablePropertyMapping.TENANT_CODE, | |
120 | + ModelConstants.TablePropertyMapping.CREATOR, | |
121 | + ModelConstants.TablePropertyMapping.UPDATER, | |
122 | + ModelConstants.TablePropertyMapping.CREATE_TIME, | |
123 | + ModelConstants.TablePropertyMapping.UPDATE, | |
124 | + ModelConstants.TablePropertyMapping.UPDATE_TIME); | |
125 | + baseMapper.updateById(device); | |
126 | + return device.getDTO(DeviceDTO.class); | |
127 | + } | |
128 | + | |
129 | +// private TBCredential buildTBCredential(CredentialEntity credentialEntity) { | |
130 | +// Assert.notNull(credentialEntity, "credentialEntity cannot be null"); | |
131 | +// TBCredential tbCredential = new TBCredential(); | |
132 | +// tbCredential.setCredentialsId(credentialEntity.getCredentialsId()); | |
133 | +// tbCredential.setCredentialsType(credentialEntity.getCredentialsType()); | |
134 | +// tbCredential.setCreateTime(credentialEntity.getCreatedTime()); | |
135 | +// tbCredential.setCredentialsValue(credentialEntity.getCredentialsValue()); | |
136 | +// Id deviceId = new Id(); | |
137 | +// deviceId.setEntityType(EntityType.DEVICE); | |
138 | +// deviceId.setId(credentialEntity.getDeviceId()); | |
139 | +// tbCredential.setDeviceId(deviceId); | |
140 | +// Id id = new Id(); | |
141 | +// id.setId(credentialEntity.getId()); | |
142 | +// tbCredential.setId(id); | |
143 | +// return tbCredential; | |
144 | +// } | |
145 | + | |
146 | + private void validateUpdate(DeviceDTO deviceDTO) { | |
147 | + if (StringUtils.isAllBlank(deviceDTO.getName())) { | |
148 | + throw new DataValidationException("device name must be specific"); | |
149 | + } | |
150 | + } | |
151 | + | |
152 | + private boolean detectDeviceChange(DeviceDTO deviceDTO, YtDevice device) { | |
153 | + boolean changed = | |
154 | + !deviceDTO.getName().equalsIgnoreCase(device.getName()) | |
155 | + || !deviceDTO.getProfileId().equalsIgnoreCase(device.getProfileId()); | |
156 | + if (changed) { | |
157 | + return true; | |
158 | + } | |
159 | + boolean dtoGateway = | |
160 | + Optional.ofNullable(deviceDTO.getDeviceType()) | |
161 | + .map(deviceType -> deviceType.equals(DeviceTypeEnum.GATEWAY)) | |
162 | + .orElse(false); | |
163 | + boolean entityGateway = | |
164 | + Optional.ofNullable(device.getDeviceType()) | |
165 | + .map(deviceType -> deviceType.equals(DeviceTypeEnum.GATEWAY)) | |
166 | + .orElse(false); | |
167 | + if (entityGateway != dtoGateway) { | |
168 | + changed = true; | |
169 | + } | |
170 | + if (changed) { | |
171 | + return true; | |
172 | + } | |
173 | + String dtoDesc = | |
174 | + Optional.ofNullable(deviceDTO.getDeviceInfo()) | |
175 | + .map(deviceInfo -> deviceInfo.get("description")) | |
176 | + .map(JsonNode::asText) | |
177 | + .orElse(""); | |
178 | + String dtoLabel = deviceDTO.getLabel() == null ? "" : deviceDTO.getLabel(); | |
179 | + String entityDesc = | |
180 | + Optional.ofNullable(device.getDeviceInfo()) | |
181 | + .map(deviceInfo -> deviceInfo.get("description")) | |
182 | + .map(JsonNode::asText) | |
183 | + .orElse(""); | |
184 | + String entityLabel = device.getLabel() == null ? "" : device.getLabel(); | |
185 | + if (!dtoDesc.equals(entityDesc) || !dtoLabel.equals(entityLabel)) { | |
186 | + changed = true; | |
187 | + } | |
188 | + return changed; | |
189 | + } | |
190 | + | |
191 | + private void validateDeviceDTO(String tenantId,DeviceDTO deviceDTO, boolean insert) { | |
192 | + if (StringUtils.isBlank(deviceDTO.getName())) { | |
193 | + throw new DataValidationException("device name cannot be black"); | |
194 | + } | |
195 | + // validate IOT DB | |
196 | + if (StringUtils.isBlank(deviceDTO.getProfileId())) { | |
197 | + throw new DataValidationException("device profile cannot be black"); | |
198 | + } | |
199 | + if (StringUtils.isBlank(deviceDTO.getDeviceToken()) && !insert) { | |
200 | + throw new DataValidationException("device token cannot be black"); | |
201 | + } | |
202 | + // 验证设备名称是否已经存在 如果此处直接使用deviceDTO 将有误 | |
203 | + if (insert) { | |
204 | + DeviceDTO check = new DeviceDTO(); | |
205 | + check.setName(deviceDTO.getName()); | |
206 | + if (findDeviceInfo(tenantId,check).size() > 0) { | |
207 | + throw new DataValidationException(ErrorMessage.NAME_ALREADY_EXISTS.getMessage()); | |
208 | + } | |
209 | + } | |
210 | + // 验证数据profileId的正确性 | |
211 | + DeviceProfile deviceProfile = deviceProfileMapper.selectById(deviceDTO.getProfileId()); | |
212 | + Organization organization = organizationMapper.selectById(deviceDTO.getOrganizationId()); | |
213 | + if (null == deviceProfile || null == organization) { | |
214 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
215 | +// } else if (StringUtils.isEmpty(deviceProfile.getTbProfileId())) { | |
216 | +// throw new DataValidationException("tb_device profile is nonexistent"); | |
217 | + } else if (!deviceProfile | |
218 | + .getTenantId() | |
219 | + .equals(tenantId) | |
220 | + || !organization.getTenantCode().equals(tenantId)) { | |
221 | + throw new DataValidationException(ErrorMessage.TENANT_MISMATCHING.getMessage()); | |
222 | + } | |
223 | + } | |
224 | + | |
225 | + private DeviceDTO insert(String tenantId,DeviceDTO deviceDTO) { | |
226 | + validateDeviceDTO(tenantId,deviceDTO, true); | |
227 | + if (StringUtils.isNotBlank(deviceDTO.getDeviceToken())) { | |
228 | + List<YtDevice> devices = | |
229 | + baseMapper.selectList( | |
230 | + new QueryWrapper<YtDevice>() | |
231 | + .lambda() | |
232 | + .eq(YtDevice::getDeviceToken, deviceDTO.getDeviceToken())); | |
233 | + if (!devices.isEmpty()) { | |
234 | + throw new DataValidationException("设备Device Token已经存在!"); | |
235 | + } | |
236 | + } | |
237 | + YtDevice device = new YtDevice(); | |
238 | + deviceDTO.copyToEntity( | |
239 | + device, | |
240 | + ModelConstants.TablePropertyMapping.ACTIVE_TIME, | |
241 | + ModelConstants.TablePropertyMapping.DEVICE_STATE, | |
242 | + ModelConstants.TablePropertyMapping.TB_DEVICE_ID, | |
243 | + ModelConstants.TablePropertyMapping.TENANT_CODE, | |
244 | + ModelConstants.TablePropertyMapping.CREATOR, | |
245 | + ModelConstants.TablePropertyMapping.UPDATER, | |
246 | + ModelConstants.TablePropertyMapping.CREATE_TIME, | |
247 | + ModelConstants.TablePropertyMapping.UPDATE, | |
248 | + ModelConstants.TablePropertyMapping.UPDATE_TIME); | |
249 | + device.setTenantCode(tenantId); | |
250 | + // First insert into TB | |
251 | +// if (tbConfig.isEnabled()) { | |
252 | +// Device tbDevice = buildTbDeviceFromDeviceDTO(deviceDTO); | |
253 | +// try { | |
254 | +// Device insertedTbDevice = | |
255 | +// tbConnectService.saveDevice(tbDevice, deviceDTO.getDeviceToken()).get(); | |
256 | +// if (insertedTbDevice == null) { | |
257 | +// throw new FastIotException(ErrorMessage.CONNECT_TO_TB_ERROR); | |
258 | +// } | |
259 | +// // 判断插入的DTO是否设置了deviceToken,如果不存在,获取Tb的deviceToken存入DB | |
260 | +// if (StringUtils.isAllBlank(device.getDeviceToken())) { | |
261 | +// String deviceTokenFromDB = | |
262 | +// tbDBService.getDeviceTokenFromDB(insertedTbDevice.getId().getId()); | |
263 | +// device.setDeviceToken(deviceTokenFromDB); | |
264 | +// } | |
265 | +// device.setTbDeviceId(insertedTbDevice.getId().getId()); | |
266 | +// } catch (InterruptedException | ExecutionException e) { | |
267 | +// log.error("insert device into tb error:{}", e.getMessage()); | |
268 | +// throw new FastIotException(ErrorMessage.CONNECT_TO_TB_ERROR); | |
269 | +// } | |
270 | +// } | |
271 | + device.setAlarmStatus(0); | |
272 | + /** 默认待激活状态 */ | |
273 | + device.setDeviceState(DeviceState.INACTIVE); | |
274 | + baseMapper.insert(device); | |
275 | + return device.getDTO(DeviceDTO.class); | |
276 | + } | |
277 | + | |
278 | +// private Device buildTbDeviceFromDeviceDTO(DeviceDTO deviceDTO) { | |
279 | +// Device tbDevice = new Device(); | |
280 | +// if (StringUtils.isNotBlank(deviceDTO.getTbDeviceId())) { | |
281 | +// Id id = new Id(); | |
282 | +// id.setId(deviceDTO.getTbDeviceId()); | |
283 | +// id.setEntityType(EntityType.DEVICE); | |
284 | +// tbDevice.setId(id); | |
285 | +// } | |
286 | +// Device.AdditionalInfo additionalInfo = new Device.AdditionalInfo(); | |
287 | +// additionalInfo.setGateway( | |
288 | +// Optional.ofNullable(deviceDTO.getDeviceType()) | |
289 | +// .map(deviceType -> deviceType.equals(DeviceTypeEnum.GATEWAY)) | |
290 | +// .orElse(false)); | |
291 | +// | |
292 | +// additionalInfo.setDescription( | |
293 | +// Optional.ofNullable(deviceDTO.getDeviceInfo()) | |
294 | +// .map(deviceInfo -> deviceInfo.get("description")) | |
295 | +// .map(JsonNode::asText) | |
296 | +// .orElse("")); | |
297 | +// additionalInfo.setOverwriteActivityTime(false); | |
298 | +// | |
299 | +// Id deviceProfileId = new Id(); | |
300 | +// deviceProfileId.setEntityType(EntityType.DEVICE_PROFILE); | |
301 | +// DeviceProfile deviceProfile = deviceProfileMapper.selectById(deviceDTO.getProfileId()); | |
302 | +// deviceProfileId.setId(deviceProfile != null ? deviceProfile.getTbProfileId() : null); | |
303 | +// | |
304 | +// tbDevice.setAdditionalInfo(additionalInfo); | |
305 | +// tbDevice.setCustomerId(null); | |
306 | +// tbDevice.setDeviceProfileId(deviceProfileId); | |
307 | +// tbDevice.setLabel(deviceDTO.getLabel()); | |
308 | +// tbDevice.setName(deviceDTO.getName()); | |
309 | +// tbDevice.setCreatedTime(LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli()); | |
310 | +// return tbDevice; | |
311 | +// } | |
312 | + | |
313 | + @Override | |
314 | + @Transactional | |
315 | + public void deleteDevices(String tenantId,Set<String> ids) { | |
316 | + LambdaQueryWrapper<YtDevice> queryWrapper = | |
317 | + new QueryWrapper<YtDevice>() | |
318 | + .lambda() | |
319 | + .eq(YtDevice::getTenantCode, tenantId) | |
320 | + .in(YtDevice::getId, ids); | |
321 | + | |
322 | + List<String> tbDeviceIds = | |
323 | + baseMapper.selectList(queryWrapper).stream() | |
324 | + .map(YtDevice::getTbDeviceId) | |
325 | + .collect(Collectors.toList()); | |
326 | + baseMapper.delete(queryWrapper); | |
327 | + // 忽略删除进度,也不管是否删除了 | |
328 | +/* if (tbConfig.isEnabled()) { | |
329 | + tbDeviceIds.forEach(tbConnectService::deleteDevice); | |
330 | + }*/ | |
331 | + } | |
332 | + | |
333 | + @Override | |
334 | + public Optional<DeviceDTO> getDevice(String tenantId,String id) { | |
335 | + return Optional.ofNullable( | |
336 | + baseMapper.selectOne( | |
337 | + new QueryWrapper<YtDevice>() | |
338 | + .lambda() | |
339 | + .eq(YtDevice::getTenantCode, tenantId) | |
340 | + .eq(YtDevice::getId, id))) | |
341 | + .map(device -> device.getDTO(DeviceDTO.class)); | |
342 | + } | |
343 | + | |
344 | + @Override | |
345 | + public PageData<DeviceDTO> page(String tenantId,Map<String, Object> queryMap) { | |
346 | + queryMap.put("tenantCode", tenantId); | |
347 | + String organizationId = (String) queryMap.get("organizationId"); | |
348 | + if (!StringUtils.isEmpty(organizationId)) { | |
349 | + List<String> organizationIds = new ArrayList<>(); | |
350 | + organizationIds.add(organizationId); | |
351 | + // 查询该组织的所有子类 | |
352 | + List<OrganizationDTO> organizationDTOS = | |
353 | + organizationMapper.findOrganizationTreeList( | |
354 | + tenantId, organizationIds); | |
355 | + List<String> queryOrganizationIds = new ArrayList<>(); | |
356 | + organizationDTOS.forEach( | |
357 | + item -> { | |
358 | + queryOrganizationIds.add(item.getId()); | |
359 | + }); | |
360 | + queryMap.put("organizationIds", queryOrganizationIds); | |
361 | + } | |
362 | + IPage<YtDevice> page = getPage(queryMap, FastIotConstants.DefaultOrder.CREATE_TIME, false); | |
363 | + IPage<DeviceDTO> deviceIPage = baseMapper.getDevicePage(page, queryMap); | |
364 | + return getPageData(deviceIPage, DeviceDTO.class); | |
365 | + } | |
366 | + | |
367 | + @Override | |
368 | + public List<DeviceDTO> findDeviceInfo(String tenantId,DeviceDTO deviceDTO) { | |
369 | + List<YtDevice> deviceList = | |
370 | + baseMapper.selectList( | |
371 | + new QueryWrapper<YtDevice>() | |
372 | + .lambda() | |
373 | + .eq( | |
374 | + StringUtils.isNotBlank(deviceDTO.getDeviceToken()), | |
375 | + YtDevice::getDeviceToken, | |
376 | + deviceDTO.getDeviceToken()) | |
377 | + .eq(true, YtDevice::getTenantCode, tenantId) | |
378 | + .like( | |
379 | + StringUtils.isNotBlank(deviceDTO.getName()), | |
380 | + YtDevice::getName, | |
381 | + deviceDTO.getName())); | |
382 | + return ReflectUtils.sourceToTarget(deviceList, DeviceDTO.class); | |
383 | + } | |
384 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
5 | +import com.fasterxml.jackson.databind.JsonNode; | |
6 | +import com.fasterxml.jackson.databind.node.ObjectNode; | |
7 | +import lombok.RequiredArgsConstructor; | |
8 | +import lombok.extern.slf4j.Slf4j; | |
9 | +import org.apache.commons.lang3.RandomStringUtils; | |
10 | +import org.apache.commons.lang3.StringUtils; | |
11 | +import org.springframework.beans.factory.annotation.Autowired; | |
12 | +import org.springframework.stereotype.Service; | |
13 | +import org.springframework.transaction.annotation.Transactional; | |
14 | +import org.thingsboard.common.util.JacksonUtil; | |
15 | +import org.thingsboard.server.common.data.yunteng.config.sms.YtDefaultSmsSenderFactory; | |
16 | +import org.thingsboard.server.common.data.yunteng.config.sms.SmsProviderConfiguration; | |
17 | +import org.thingsboard.server.common.data.yunteng.config.sms.SmsSender; | |
18 | +import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; | |
19 | +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException; | |
20 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
21 | +import org.thingsboard.server.common.data.yunteng.dto.request.CodeTTL; | |
22 | +import org.thingsboard.server.common.data.yunteng.dto.request.SmsReqDTO; | |
23 | +import org.thingsboard.server.common.data.yunteng.enums.MessageTypeEnum; | |
24 | +import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum; | |
25 | +import org.thingsboard.server.common.data.yunteng.enums.ResponseCodeEnum; | |
26 | +import org.thingsboard.server.dao.yunteng.entities.MessageConfig; | |
27 | +import org.thingsboard.server.dao.yunteng.entities.MessageTemplate; | |
28 | +import org.thingsboard.server.dao.yunteng.entities.SmsLog; | |
29 | +import org.thingsboard.server.dao.yunteng.entities.User; | |
30 | +import org.thingsboard.server.dao.yunteng.mapper.MessageConfigMapper; | |
31 | +import org.thingsboard.server.dao.yunteng.mapper.MessageTemplateMapper; | |
32 | +import org.thingsboard.server.dao.yunteng.mapper.SmsLogMapper; | |
33 | +import org.thingsboard.server.dao.yunteng.mapper.UserMapper; | |
34 | +import org.thingsboard.server.dao.yunteng.service.YtSmsService; | |
35 | + | |
36 | +import java.time.LocalDateTime; | |
37 | +import java.util.LinkedHashMap; | |
38 | +import java.util.List; | |
39 | + | |
40 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.CacheConfigKey.MOBILE_LOGIN_SMS_CODE; | |
41 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.DEFAULT_DELIMITER; | |
42 | + | |
43 | +@Slf4j | |
44 | +@Service | |
45 | +@RequiredArgsConstructor | |
46 | +public class YtSmsServiceImpl implements YtSmsService { | |
47 | + | |
48 | + private final MessageTemplateMapper messageTemplateMapper; | |
49 | + | |
50 | + private final MessageConfigMapper messageConfigMapper; | |
51 | + | |
52 | + private YtDefaultSmsSenderFactory ytDefaultSmsSenderFactory; | |
53 | + | |
54 | + private final SmsLogMapper smsLogMapper; | |
55 | + | |
56 | + private CacheUtils cacheUtils; | |
57 | + | |
58 | + private final UserMapper userMapper; | |
59 | + | |
60 | + @Override | |
61 | + @Transactional | |
62 | + public boolean sendSms(SmsReqDTO smsReqDTO) { | |
63 | + String phoneNumbers = smsReqDTO.getPhoneNumbers(); | |
64 | + LinkedHashMap<String, String> templateParam = smsReqDTO.getParams(); | |
65 | + String templateId = smsReqDTO.getId(); | |
66 | + if (StringUtils.isEmpty(phoneNumbers) || StringUtils.isEmpty(templateId)) { | |
67 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
68 | + } | |
69 | + MessageTemplate messageTemplate = messageTemplateMapper.selectById(templateId); | |
70 | + if (null != messageTemplate) { | |
71 | + MessageConfig messageConfig = | |
72 | + messageConfigMapper.selectById(messageTemplate.getMessageConfigId()); | |
73 | + JsonNode configJsonNode = messageConfig.getConfig(); | |
74 | + ObjectNode configObjectNode = (ObjectNode) configJsonNode; | |
75 | + configObjectNode.put("type", messageConfig.getPlatformType()); | |
76 | + SmsProviderConfiguration smsProviderConfiguration = | |
77 | + JacksonUtil.convertValue(configObjectNode, SmsProviderConfiguration.class); | |
78 | + if (null != smsProviderConfiguration) { | |
79 | + SmsSender smsSender = ytDefaultSmsSenderFactory.createSmsSender(smsProviderConfiguration); | |
80 | + String result = | |
81 | + smsSender.sendSms( | |
82 | + phoneNumbers, | |
83 | + messageTemplate.getTemplateCode(), | |
84 | + templateParam, | |
85 | + messageTemplate.getSignName()); | |
86 | + // 记录短信日志 | |
87 | + String status = ResponseCodeEnum.SUCCESS.name(); | |
88 | + String remark = smsReqDTO.getRemark()==null?"":smsReqDTO.getRemark(); | |
89 | + if(!ResponseCodeEnum.SUCCESS.name().equals(result)){ | |
90 | + status = ResponseCodeEnum.FAILED.name(); | |
91 | + remark += result; | |
92 | + } | |
93 | + SmsLog smsLog = new SmsLog(); | |
94 | + smsLog.setToPhone(phoneNumbers); | |
95 | + smsLog.setType(messageConfig.getPlatformType()); | |
96 | + smsLog.setStatus(status); | |
97 | + smsLog.setRemark(remark); | |
98 | + smsLog.setMessageTemplateId(messageTemplate.getId()); | |
99 | + smsLog.setTemplateParam(JacksonUtil.toJsonNode(JacksonUtil.toString(templateParam))); | |
100 | + smsLog.setSendTime(LocalDateTime.now()); | |
101 | + smsLog.setTenantCode(messageTemplate.getTenantCode()); | |
102 | + smsLog.setTemplatePurpose(smsReqDTO.getTemplatePurpose()); | |
103 | + smsLogMapper.insert(smsLog); | |
104 | + return ResponseCodeEnum.SUCCESS.name().equals(result); | |
105 | + } | |
106 | + } | |
107 | + return false; | |
108 | + } | |
109 | + | |
110 | + @Override | |
111 | + @Transactional | |
112 | + public boolean sendLoginSmsCode(String phoneNumber) { | |
113 | + // 检查手机号码是否存在系统,以免乱发消息 | |
114 | + if (userMapper | |
115 | + .selectList(new QueryWrapper<User>().lambda().eq(User::getPhoneNumber, phoneNumber)) | |
116 | + .isEmpty()) { | |
117 | + throw new DataValidationException("电话号码未在系统注册,请联系你的管理员"); | |
118 | + } | |
119 | + // 获取是否有验证码存在,防止发送数量过多 | |
120 | + String key = | |
121 | + MsgTemplatePurposeEnum.FOR_LOGIN.name() | |
122 | + + DEFAULT_DELIMITER | |
123 | + + MessageTypeEnum.PHONE_MESSAGE.name() | |
124 | + + DEFAULT_DELIMITER | |
125 | + + phoneNumber; | |
126 | + boolean canSend = | |
127 | + cacheUtils | |
128 | + .get(MOBILE_LOGIN_SMS_CODE, key) | |
129 | + .map( | |
130 | + o -> { | |
131 | + CodeTTL codeTTL = (CodeTTL) o; | |
132 | + return System.currentTimeMillis() - codeTTL.getSendTs() | |
133 | + >= 60 * 1000; // 大于1分钟才允许下次再发送短信 | |
134 | + }) | |
135 | + .orElse(true); | |
136 | + if (!canSend) { | |
137 | + return false; | |
138 | + } | |
139 | + List<MessageTemplate> messageTemplates = | |
140 | + messageTemplateMapper.selectList( | |
141 | + new QueryWrapper<MessageTemplate>() | |
142 | + .lambda() | |
143 | + .eq(MessageTemplate::getTemplatePurpose, MsgTemplatePurposeEnum.FOR_LOGIN.name()) | |
144 | + .eq(MessageTemplate::getMessageType, MessageTypeEnum.PHONE_MESSAGE.name())); | |
145 | + if (messageTemplates.isEmpty()) { | |
146 | + throw new DataValidationException("no sms provider config"); | |
147 | + } | |
148 | + String code = RandomStringUtils.randomNumeric(6); | |
149 | + LinkedHashMap<String, String> params = new LinkedHashMap<>(); | |
150 | + params.put("code", code); | |
151 | + MessageTemplate messageTemplate = messageTemplates.get(0); | |
152 | + SmsReqDTO smsReqDTO = new SmsReqDTO(); | |
153 | + smsReqDTO.setParams(params); | |
154 | + smsReqDTO.setPhoneNumbers(phoneNumber); | |
155 | + smsReqDTO.setId(messageTemplate.getId()); | |
156 | + smsReqDTO.setTemplatePurpose(MsgTemplatePurposeEnum.FOR_LOGIN.name()); | |
157 | + if (this.sendSms(smsReqDTO)) { | |
158 | + cacheUtils.put(MOBILE_LOGIN_SMS_CODE, key, new CodeTTL(code, System.currentTimeMillis())); | |
159 | + return true; | |
160 | + } else { | |
161 | + cacheUtils.invalidate(MOBILE_LOGIN_SMS_CODE, key); | |
162 | + return false; | |
163 | + } | |
164 | + } | |
165 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import lombok.RequiredArgsConstructor; | |
6 | +import org.apache.commons.lang3.RandomStringUtils; | |
7 | +import org.apache.commons.lang3.StringUtils; | |
8 | +import org.springframework.beans.BeanUtils; | |
9 | +import org.springframework.stereotype.Service; | |
10 | +import org.springframework.transaction.annotation.Transactional; | |
11 | +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException; | |
12 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
13 | +import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; | |
14 | +import org.thingsboard.server.common.data.yunteng.dto.request.TenantReqDTO; | |
15 | +import org.thingsboard.server.common.data.yunteng.enums.TenantStatusEnum; | |
16 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
17 | +import org.thingsboard.server.dao.yunteng.entities.Tenant; | |
18 | +import org.thingsboard.server.dao.yunteng.entities.TenantMenu; | |
19 | +import org.thingsboard.server.dao.yunteng.entities.TenantRole; | |
20 | +import org.thingsboard.server.dao.yunteng.entities.User; | |
21 | +import org.thingsboard.server.dao.yunteng.mapper.*; | |
22 | +import org.thingsboard.server.dao.yunteng.service.AbstractBaseService; | |
23 | +import org.thingsboard.server.dao.yunteng.service.YtTenantService; | |
24 | + | |
25 | +import java.time.LocalDateTime; | |
26 | +import java.util.*; | |
27 | + | |
28 | +@Service | |
29 | +@RequiredArgsConstructor | |
30 | +public class YtTenantServiceImpl extends AbstractBaseService<TenantMapper, Tenant> | |
31 | + implements YtTenantService { | |
32 | + | |
33 | + private final MenuMapper menuMapper; | |
34 | + private final RoleMapper roleMapper; | |
35 | + private final UserMapper userMapper; | |
36 | + private final TenantMenuMapper tenantMenuMapper; | |
37 | + private final TenantRoleMapper tenantRoleMapper; | |
38 | + | |
39 | + @Override | |
40 | + @Transactional | |
41 | + public TenantDTO createNewTenant(TenantReqDTO tenantReqDTO) { | |
42 | + TenantDTO tenantDTO = new TenantDTO(); | |
43 | + BeanUtils.copyProperties(tenantReqDTO, tenantDTO); | |
44 | + processTenantCode(tenantDTO); | |
45 | + Tenant tenant = tenantDTO.getEntity(Tenant.class); | |
46 | + baseMapper.insert(tenant); | |
47 | + // 调用TB API | |
48 | + tenant.copyToDTO(tenantDTO); | |
49 | + saveTenantMapping(tenantDTO.getTenantCode(), tenantReqDTO.getRoleIds()); | |
50 | + return tenantDTO; | |
51 | + } | |
52 | + | |
53 | + @Override | |
54 | + public PageData<TenantDTO> page(Map<String, Object> queryMap) { | |
55 | + IPage<Tenant> tenantIPage = getPage(queryMap, "create_time", true); | |
56 | + IPage<TenantDTO> userPage = | |
57 | + baseMapper.getTenantPage(tenantIPage, (String) queryMap.get("tenantName")); | |
58 | + PageData<TenantDTO> pageData = getPageData(userPage, TenantDTO.class); | |
59 | + determineTenantStatus(pageData.getItems()); | |
60 | + return pageData; | |
61 | + } | |
62 | + | |
63 | + private void determineTenantStatus(Collection<TenantDTO> tenantDTOList) { | |
64 | + tenantDTOList.forEach( | |
65 | + tenantDTO -> { | |
66 | + if (!tenantDTO.isEnabled()) { | |
67 | + tenantDTO.setTenantStatus(TenantStatusEnum.DISABLED); | |
68 | + } else { | |
69 | + tenantDTO.setTenantStatus(TenantStatusEnum.NORMAL); | |
70 | + if (tenantDTO.getTenantExpireTime() != null | |
71 | + && LocalDateTime.now().isAfter(tenantDTO.getTenantExpireTime())) { | |
72 | + tenantDTO.setTenantStatus(TenantStatusEnum.EXPIRED); | |
73 | + } | |
74 | + } | |
75 | + }); | |
76 | + } | |
77 | + | |
78 | + private void processTenantCode(TenantDTO tenantDTO) { | |
79 | + if (tenantDTO.getTenantCode() != null) { | |
80 | + if (tenantDTO.getTenantCode().length() > 30) { | |
81 | + throw new DataValidationException("tenant code too long"); | |
82 | + } | |
83 | + int count = | |
84 | + baseMapper.selectCount( | |
85 | + new QueryWrapper<Tenant>() | |
86 | + .lambda() | |
87 | + .eq(Tenant::getTenantCode, tenantDTO.getTenantCode())); | |
88 | + if (count > 0) { | |
89 | + throw new DataValidationException("tenant code already exist"); | |
90 | + } | |
91 | + } else { | |
92 | + tenantDTO.setTenantCode(RandomStringUtils.randomAlphabetic(20)); | |
93 | + } | |
94 | + } | |
95 | + | |
96 | + @Override | |
97 | + @Transactional | |
98 | + public TenantDTO updateTenant(TenantDTO tenantDTO) { | |
99 | + Tenant tenant = baseMapper.selectById(tenantDTO.getId()); | |
100 | + if (tenant == null) { | |
101 | + throw new DataValidationException("tenant does not exist"); | |
102 | + } | |
103 | + String existTenantCode = tenant.getTenantCode(); | |
104 | + tenantDTO.copyToEntity(tenant); | |
105 | + // tenantCode is immutable | |
106 | + tenant.setTenantCode(existTenantCode); | |
107 | + baseMapper.updateById(tenant); | |
108 | + tenant.copyToDTO(tenantDTO); | |
109 | + return tenantDTO; | |
110 | + } | |
111 | + | |
112 | + @Override | |
113 | + @Transactional | |
114 | + public boolean deleteTenants(String[] idArr) { | |
115 | + Set<String> ids = Set.of(idArr); | |
116 | + | |
117 | + Set<String> tenantCodes = baseMapper.getTenantCodesByTenantIds(ids); | |
118 | + // 1. GET ALL ROLE_ID | |
119 | + Set<String> allRoleIds = roleMapper.getAllIdsByTenantCode(tenantCodes); | |
120 | + // 2. DELETE SYS_ROLE SYS_ROLE_MENU SYS_USER_ROLE | |
121 | + if (!allRoleIds.isEmpty()) { | |
122 | + roleMapper.deleteBatchIds(allRoleIds); | |
123 | + roleMapper.deleteRoleMenuMappingByRoleIds(allRoleIds); | |
124 | + roleMapper.deleteRoleUserMappingByRoleIds(allRoleIds); | |
125 | + } | |
126 | + // 3. DELETE SYS_MENU SYS_TENANT_MENU | |
127 | + Set<String> allMenuIds = menuMapper.getAllIdsByTenantCode(tenantCodes); | |
128 | + if (!allMenuIds.isEmpty()) { | |
129 | + menuMapper.deleteBatchIds(allMenuIds); | |
130 | + menuMapper.deleteTenantMenuMappingByMenuIds(allMenuIds); | |
131 | + } | |
132 | + // 4. DELETE USER | |
133 | + userMapper.delete(new QueryWrapper<User>().lambda().in(User::getTenantCode, tenantCodes)); | |
134 | + // 5. TELL RULE ENGINE TO STOP TENANT | |
135 | + // 6. DELETE OTHER RESOURCES IF ANY | |
136 | + // 7. DELETE TENANT | |
137 | + baseMapper.deleteBatchIds(ids); | |
138 | + // 删除 TENANT_ROLE、TENANT_MENU | |
139 | + deleteTenantRolesByTenantCode(tenantCodes); | |
140 | + deleteTenantMenusByTenantCode(tenantCodes); | |
141 | + // TODO 调用TB的API删除TB租户信息 | |
142 | + | |
143 | + return true; | |
144 | + } | |
145 | + | |
146 | + /** | |
147 | + * 通过租户Code删除租户角色关系 | |
148 | + * @param tenantCodes 租户Code | |
149 | + */ | |
150 | + private void deleteTenantRolesByTenantCode(Set<String> tenantCodes) { | |
151 | + tenantRoleMapper.delete( | |
152 | + new QueryWrapper<TenantRole>().lambda().in(TenantRole::getTenantCode, tenantCodes)); | |
153 | + } | |
154 | + | |
155 | + /** | |
156 | + * 通过租户Code删除租户角色关系 | |
157 | + * @param tenantCodes 租户Code | |
158 | + */ | |
159 | + private void deleteTenantMenusByTenantCode(Set<String> tenantCodes) { | |
160 | + tenantMenuMapper.delete( | |
161 | + new QueryWrapper<TenantMenu>().lambda().in(TenantMenu::getTenantCode, tenantCodes)); | |
162 | + } | |
163 | + | |
164 | + @Override | |
165 | + public Optional<TenantDTO> findById(String id) { | |
166 | + return Optional.ofNullable(baseMapper.selectById(id)) | |
167 | + .map(tenant -> tenant.getDTO(TenantDTO.class)); | |
168 | + } | |
169 | + | |
170 | + @Override | |
171 | + @Transactional | |
172 | + public TenantDTO updateOrCreateTenant(TenantReqDTO tenantReqDTO) { | |
173 | + if (StringUtils.isNotBlank(tenantReqDTO.getId())) { | |
174 | + Tenant tenant; | |
175 | + tenant = baseMapper.selectById(tenantReqDTO.getId()); | |
176 | + if (tenant != null) { | |
177 | + BeanUtils.copyProperties(tenantReqDTO, tenant); | |
178 | + baseMapper.updateById(tenant); | |
179 | + } | |
180 | + return null; | |
181 | + } else { | |
182 | + return createNewTenant(tenantReqDTO); | |
183 | + } | |
184 | + } | |
185 | + | |
186 | + @Override | |
187 | + public List<String> getTenantRolesByTenantCode(String tenantCode) { | |
188 | + if(StringUtils.isEmpty(tenantCode)){ | |
189 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
190 | + } | |
191 | + List<String> roles = new ArrayList<>(); | |
192 | + List<TenantRole> tenantRoleList = tenantRoleMapper | |
193 | + .selectList( | |
194 | + new QueryWrapper<TenantRole>().lambda().eq(TenantRole::getTenantCode, tenantCode)); | |
195 | + tenantRoleList.forEach(role->roles.add(role.getRoleId())); | |
196 | + return roles; | |
197 | + } | |
198 | + | |
199 | + /** | |
200 | + * 保存租户与菜单、角色的映射关系 | |
201 | + * | |
202 | + * @param tenantCode 租户Code | |
203 | + * @param roleIds 角色IDS | |
204 | + */ | |
205 | + private void saveTenantMapping(String tenantCode, String[] roleIds) { | |
206 | + // 添加租户角色关系 | |
207 | + for (String roleId : roleIds) { | |
208 | + saveTenantRoleMapping(roleId,tenantCode); | |
209 | + // 查询roleId有多少菜单 | |
210 | + Set<String> menuIds = roleMapper.getMenuIdsByRoleId(roleId); | |
211 | + // 添加租户菜单关系 | |
212 | + for (String menuId : menuIds) { | |
213 | + saveTenantMenuMapping(menuId,tenantCode); | |
214 | + } | |
215 | + } | |
216 | + } | |
217 | + | |
218 | + /** | |
219 | + * 保存租户与菜单的关系 | |
220 | + * @param menuId 菜单ID | |
221 | + * @param tenantCode 租户Code | |
222 | + */ | |
223 | + private void saveTenantMenuMapping(String menuId,String tenantCode){ | |
224 | + TenantMenu tenantMenu = new TenantMenu(); | |
225 | + tenantMenu.setMenuId(menuId); | |
226 | + tenantMenu.setTenantCode(tenantCode); | |
227 | + tenantMenuMapper.insert(tenantMenu); | |
228 | + } | |
229 | + | |
230 | + /** | |
231 | + * 保存租户与角色的关系 | |
232 | + * @param roleId 角色ID | |
233 | + * @param tenantCode 租户Code | |
234 | + */ | |
235 | + private void saveTenantRoleMapping(String roleId,String tenantCode){ | |
236 | + TenantRole tenantRole = new TenantRole(); | |
237 | + tenantRole.setTenantCode(tenantCode); | |
238 | + tenantRole.setRoleId(roleId); | |
239 | + tenantRoleMapper.insert(tenantRole); | |
240 | + } | |
241 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.impl; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |
6 | +import com.fasterxml.jackson.databind.JsonNode; | |
7 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
8 | +import com.google.common.collect.Sets; | |
9 | +import lombok.RequiredArgsConstructor; | |
10 | +import lombok.extern.slf4j.Slf4j; | |
11 | +import org.apache.commons.lang3.RandomStringUtils; | |
12 | +import org.apache.commons.lang3.StringUtils; | |
13 | +import org.springframework.security.access.AccessDeniedException; | |
14 | +import org.springframework.security.crypto.password.PasswordEncoder; | |
15 | +import org.springframework.stereotype.Service; | |
16 | +import org.springframework.transaction.annotation.Transactional; | |
17 | +import org.springframework.util.Assert; | |
18 | +import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; | |
19 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
20 | +import org.thingsboard.server.common.data.yunteng.core.exception.DataValidationException; | |
21 | +import org.thingsboard.server.common.data.yunteng.core.exception.FastIotException; | |
22 | +import org.thingsboard.server.common.data.yunteng.core.exception.NoneTenantAssetException; | |
23 | +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; | |
24 | +import org.thingsboard.server.common.data.yunteng.dto.*; | |
25 | +import org.thingsboard.server.common.data.yunteng.dto.request.AccountReqDTO; | |
26 | +import org.thingsboard.server.common.data.yunteng.dto.request.RoleOrOrganizationReqDTO; | |
27 | +import org.thingsboard.server.common.data.yunteng.dto.request.SendResetPasswordEmailMsg; | |
28 | +import org.thingsboard.server.common.data.yunteng.dto.request.SmsReqDTO; | |
29 | +import org.thingsboard.server.common.data.yunteng.enums.MessageTypeEnum; | |
30 | +import org.thingsboard.server.common.data.yunteng.enums.MsgTemplatePurposeEnum; | |
31 | +import org.thingsboard.server.common.data.yunteng.enums.RoleEnum; | |
32 | +import org.thingsboard.server.common.data.yunteng.enums.UserStatusEnum; | |
33 | +import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils; | |
34 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
35 | +import org.thingsboard.server.dao.yunteng.entities.*; | |
36 | +import org.thingsboard.server.dao.yunteng.mapper.*; | |
37 | +import org.thingsboard.server.dao.yunteng.service.*; | |
38 | + | |
39 | +import java.time.LocalDateTime; | |
40 | +import java.util.*; | |
41 | +import java.util.stream.Collectors; | |
42 | + | |
43 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.CHINA_MOBILE_PATTERN; | |
44 | +import static org.thingsboard.server.common.data.yunteng.constant.FastIotConstants.EMAIL_PATTERN; | |
45 | +import static org.thingsboard.server.common.data.yunteng.constant.ModelConstants.TablePropertyMapping.*; | |
46 | + | |
47 | +@Service | |
48 | +@Slf4j | |
49 | +@RequiredArgsConstructor | |
50 | +public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> implements YtUserService { | |
51 | + | |
52 | + private final AdminSettingMapper adminSettingMapper; | |
53 | + private final ObjectMapper mapper; | |
54 | + private final TenantMapper tenantMapper; | |
55 | + private final RoleMapper roleMapper; | |
56 | + private final OrganizationMapper organizationMapper; | |
57 | + private final UserOrganizationMappingMapper userOrganizationMappingMapper; | |
58 | + private final UserRoleMapper userRoleMapper; | |
59 | + private final TenantRoleMapper tenantRoleMapper; | |
60 | + | |
61 | + private final YtSmsService ytSmsService; | |
62 | + private final MessageTemplateService messageTemplateService; | |
63 | + private final OrganizationService groupService; | |
64 | + | |
65 | + public static final String ACTIVATE_URL_PATTERN = "%s/api/noauth/activate?activateToken=%s"; | |
66 | + private final PasswordEncoder passwordEncoder; | |
67 | + /** 默认密码 */ | |
68 | + private static final String DEFAULT_PWD = "123456"; | |
69 | + | |
70 | + @Override | |
71 | + public List<UserDetailsDTO> findUserDetailsByUsername(String username) { | |
72 | + // 多个租户可能存在多个username相同的情况 | |
73 | + return baseMapper.findUserDetailsByUserName(username); | |
74 | + } | |
75 | + | |
76 | + @Override | |
77 | + @Transactional | |
78 | + public UserDTO saveAccount(UserDTO userDTO, boolean sendEmail, boolean sendMsg,boolean isSysadmin,String tenantId) { | |
79 | + boolean isAdminOperate = isSysadmin; | |
80 | + if (StringUtils.isAllBlank(userDTO.getUsername())) { | |
81 | + throw new DataValidationException("username is required"); | |
82 | + } | |
83 | + validatePhoneNumberAndEmail(userDTO); | |
84 | + if (sendMsg && StringUtils.isAllBlank(userDTO.getPhoneNumber())) { | |
85 | + throw new DataValidationException( | |
86 | + "you must specify user phone number if you want send activate email to this user"); | |
87 | + } | |
88 | + if (sendEmail && StringUtils.isAllBlank(userDTO.getEmail())) { | |
89 | + throw new DataValidationException( | |
90 | + "you must specify user email if you want send activate email to this user"); | |
91 | + } | |
92 | + User user = new User(); | |
93 | + userDTO.copyToEntity(user, ID, CREATE_TIME, UPDATE_TIME, TENANT_CODE, ACTIVATE_TOKEN); | |
94 | + boolean userExist; | |
95 | + if (StringUtils.isNotBlank(userDTO.getPassword())) { | |
96 | + user.setPassword(passwordEncoder.encode(userDTO.getPassword())); | |
97 | + } | |
98 | + if (isAdminOperate) { | |
99 | + // 添加的租户管理员 | |
100 | + if (StringUtils.isNotBlank(userDTO.getTenantCode())) { | |
101 | + user.setTenantCode(userDTO.getTenantCode()); | |
102 | + user.setPassword(passwordEncoder.encode(DEFAULT_PWD)); | |
103 | + int tenantExist = | |
104 | + tenantMapper.selectCount( | |
105 | + new QueryWrapper<Tenant>() | |
106 | + .lambda() | |
107 | + .eq(Tenant::getTenantCode, userDTO.getTenantCode())); | |
108 | + if (tenantExist == 0) { | |
109 | + throw new DataValidationException("tenant must exist"); | |
110 | + } | |
111 | + } else { | |
112 | + // 添加的平台系统其他用户 | |
113 | + user.setLevel(FastIotConstants.LevelValue.IS_OTHER_ADMIN); | |
114 | + user.setTenantCode(tenantId); | |
115 | + } | |
116 | + userExist = | |
117 | + baseMapper.selectCount( | |
118 | + new QueryWrapper<User>() | |
119 | + .lambda() | |
120 | + .eq(User::getUsername, userDTO.getUsername()) | |
121 | + .eq(User::getTenantCode, userDTO.getTenantCode())) | |
122 | + > 0; | |
123 | + } else { | |
124 | + user.setLevel(FastIotConstants.LevelValue.IS_NORMAL); | |
125 | + user.setTenantCode(tenantId); | |
126 | + userExist = | |
127 | + baseMapper.selectCount( | |
128 | + new QueryWrapper<User>() | |
129 | + .lambda() | |
130 | + .eq(User::getUsername, userDTO.getUsername()) | |
131 | + .eq(User::getTenantCode, tenantId)) | |
132 | + > 0; | |
133 | + } | |
134 | + if (userExist) { | |
135 | + throw new DataValidationException(ErrorMessage.NAME_ALREADY_EXISTS.getMessage()); | |
136 | + } else { | |
137 | + baseMapper.insert(user); | |
138 | + for (String roleId : userDTO.getRoleIds()) { | |
139 | + // 添加用户角色信息 | |
140 | + UserRole userRole = new UserRole(); | |
141 | + userRole.setUserId(user.getId()); | |
142 | + userRole.setRoleId(roleId); | |
143 | + userRoleMapper.insert(userRole); | |
144 | + } | |
145 | + // 绑定用户和组织的关系 | |
146 | + groupService.bindUserToOrganization(user.getId(), userDTO.getOrganizationIds()); | |
147 | + user.copyToDTO(userDTO, PASSWORD, ACTIVATE_TOKEN); | |
148 | + return userDTO; | |
149 | + } | |
150 | + } | |
151 | + | |
152 | + private void validatePhoneNumberAndEmail(UserDTO userDTO) { | |
153 | + if (StringUtils.isNotBlank(userDTO.getPhoneNumber())) { | |
154 | + if (!CHINA_MOBILE_PATTERN.matcher(userDTO.getPhoneNumber()).matches()) { | |
155 | + throw new DataValidationException(ErrorMessage.PROVIDE_CORRECT_PHONE_NUMBER.getMessage()); | |
156 | + } | |
157 | + } | |
158 | + if (StringUtils.isNotBlank(userDTO.getEmail())) { | |
159 | + if (!EMAIL_PATTERN.matcher(userDTO.getEmail()).matches()) { | |
160 | + throw new DataValidationException(ErrorMessage.PROVIDE_CORRECT_EMAIL.getMessage()); | |
161 | + } | |
162 | + } | |
163 | + if (StringUtils.isAllBlank(userDTO.getEmail()) | |
164 | + && StringUtils.isAllBlank(userDTO.getPhoneNumber())) { | |
165 | + throw new DataValidationException(ErrorMessage.PHONE_NUMBER_OR_EMAIL_REQUIRED.getMessage()); | |
166 | + } | |
167 | + } | |
168 | + | |
169 | + @Override | |
170 | + public String getActivationLink(String userId,boolean isSysadmin,String tenantId) { | |
171 | + User user = baseMapper.selectById(userId); | |
172 | + if (!isSysadmin | |
173 | + && tenantId.equals(user.getTenantCode())) { | |
174 | + throw new AccessDeniedException( | |
175 | + "you don't have permission to get activation link for this user"); | |
176 | + } | |
177 | + if (StringUtils.isAllBlank(user.getActivateToken())) { | |
178 | + throw new DataValidationException("user already activated"); | |
179 | + } | |
180 | + try { | |
181 | + List<AdminSetting> generalSetting = | |
182 | + adminSettingMapper.selectList( | |
183 | + new QueryWrapper<AdminSetting>() | |
184 | + .lambda() | |
185 | + .eq(AdminSetting::getKey, ModelConstants.AdminSettingConfigKey.GENERAL_SETTING)); | |
186 | + AdminSetting adminSetting = generalSetting.get(0); | |
187 | + JsonNode configNode = mapper.readTree(adminSetting.getConfigJson()); | |
188 | + String baseUrl = configNode.get(FastIotConstants.ConfigJSONKey.BASE_URL).asText(); | |
189 | + return String.format(ACTIVATE_URL_PATTERN, baseUrl, user.getActivateToken()); | |
190 | + } catch (Exception e) { | |
191 | + throw new RuntimeException("error occurs"); | |
192 | + } | |
193 | + } | |
194 | + | |
195 | + @Override | |
196 | + public UserInfoDTO me(String userId,String tenantId,Set<String> currentRoles) { | |
197 | + User user = baseMapper.selectById(userId); | |
198 | + UserInfoDTO userInfoDTO = new UserInfoDTO(); | |
199 | + if (!StringUtils.isEmpty(user.getActivateToken())) { | |
200 | + userInfoDTO.setNeedSetPwd(false); | |
201 | + } | |
202 | + userInfoDTO.setUserId(userId); | |
203 | + userInfoDTO.setRealName(user.getRealName()); | |
204 | + userInfoDTO.setAvatar(user.getAvatar()); | |
205 | + userInfoDTO.setTenantCode(tenantId); | |
206 | + userInfoDTO.setRoles(currentRoles); | |
207 | + Set<Role> roles = roleMapper.selectRoleByUserId(userId); | |
208 | + Set<PlainRolesDTO> plainRolesDTOSet = Sets.newHashSet(); | |
209 | + roles.forEach( | |
210 | + role -> { | |
211 | + PlainRolesDTO plainRolesDTO = new PlainRolesDTO(); | |
212 | + plainRolesDTO.setRoleId(role.getId()); | |
213 | + plainRolesDTO.setRoleName(role.getName()); | |
214 | + plainRolesDTOSet.add(plainRolesDTO); | |
215 | + }); | |
216 | + userInfoDTO.setPlainRoles(plainRolesDTOSet); | |
217 | + return userInfoDTO; | |
218 | + } | |
219 | + | |
220 | + @Override | |
221 | + public Optional<UserDTO> getUser(String userId,boolean isSysadmin,String tenantId) { | |
222 | + User user = baseMapper.selectById(userId); | |
223 | + if (user != null) { | |
224 | + UserDTO userDTO = new UserDTO(); | |
225 | + user.copyToDTO(userDTO, PASSWORD, ACTIVATE_TOKEN); | |
226 | + if (!isSysadmin | |
227 | + && !tenantId.equals(user.getTenantCode())) { | |
228 | + return Optional.empty(); | |
229 | + } | |
230 | + return Optional.of(userDTO); | |
231 | + } else { | |
232 | + return Optional.empty(); | |
233 | + } | |
234 | + } | |
235 | + | |
236 | + @Override | |
237 | + @Transactional | |
238 | + public UserDTO updateUser(UserDTO userDTO,boolean isSysadmin,String tenantId) { | |
239 | + Assert.notNull(userDTO.getId(), "user is must be specified"); | |
240 | + User user = baseMapper.selectById(userDTO.getId()); | |
241 | + if (!isSysadmin | |
242 | + && !user.getTenantCode().equals(tenantId)) { | |
243 | + throw new NoneTenantAssetException("this user not belong to current tenant"); | |
244 | + } | |
245 | + if (!user.getUsername().equals(userDTO.getUsername())) { | |
246 | + throw new DataValidationException("username is immutable"); | |
247 | + } | |
248 | + validatePhoneNumberAndEmail(userDTO); | |
249 | + user.setRealName(userDTO.getRealName()); | |
250 | + user.setEnabled(userDTO.isEnabled()); | |
251 | + user.setPhoneNumber(userDTO.getPhoneNumber()); | |
252 | + user.setEmail(userDTO.getEmail()); | |
253 | + user.setAccountExpireTime(userDTO.getAccountExpireTime()); | |
254 | + if (!userDTO.getPassword().equals("******")) { | |
255 | + user.setPassword(passwordEncoder.encode(userDTO.getPassword())); | |
256 | + } | |
257 | + baseMapper.updateById(user); | |
258 | + user.copyToDTO(userDTO, PASSWORD, ACTIVATE_TOKEN); | |
259 | + return userDTO; | |
260 | + } | |
261 | + | |
262 | + @Override | |
263 | + public PageData<UserDTO> page( | |
264 | + Map<String, Object> queryMap, | |
265 | + boolean isSysadmin, | |
266 | + boolean isPlatformAdmin, | |
267 | + boolean isTenantAdmin, | |
268 | + String tenantId) { | |
269 | + IPage<UserDTO> userPage = new Page<>(); | |
270 | + IPage<User> userIPage = getPage(queryMap, "create_time", true); | |
271 | + if (isSysadmin) { | |
272 | + String roleType = (String) queryMap.get("roleType"); | |
273 | + if (StringUtils.isEmpty(roleType)) { | |
274 | + roleType = RoleEnum.ROLE_PLATFORM_ADMIN.name(); | |
275 | + } | |
276 | + userPage = | |
277 | + baseMapper.getAdminUserPage( | |
278 | + userIPage, tenantId, roleType); | |
279 | + } | |
280 | + else if(isPlatformAdmin){ | |
281 | + //平台管理员只能管理租户 | |
282 | + userPage = baseMapper.selectAllTenantUser(userIPage); | |
283 | + }else if(isTenantAdmin){ | |
284 | + Map<String, Object> map = new HashMap<>(); | |
285 | + map.put("realName", queryMap.get("realName")); | |
286 | + map.put("username", queryMap.get("username")); | |
287 | + map.put("tenantCode", tenantId); | |
288 | + userPage = baseMapper.getUserPage(userIPage, map); | |
289 | + } | |
290 | + if (null != userPage) { | |
291 | + userPage | |
292 | + .getRecords() | |
293 | + .forEach( | |
294 | + record -> { | |
295 | + fillUserStatus(record); | |
296 | + if (StringUtils.isNotBlank(record.getActivateToken())) { | |
297 | + record.setHasPassword(true); | |
298 | + } else { | |
299 | + record.setHasPassword(false); | |
300 | + } | |
301 | + }); | |
302 | + } | |
303 | + return getPageData(userPage, UserDTO.class); | |
304 | + } | |
305 | + | |
306 | + private void fillUserStatus(UserDTO userDTO) { | |
307 | + userDTO.setUserStatusEnum(UserStatusEnum.NORMAL); | |
308 | + if (!userDTO.isEnabled()) { | |
309 | + userDTO.setUserStatusEnum(UserStatusEnum.DISABLED); | |
310 | + } else { | |
311 | + if (userDTO.getAccountExpireTime() != null) { | |
312 | + if (userDTO.getAccountExpireTime().isBefore(LocalDateTime.now())) { | |
313 | + userDTO.setUserStatusEnum(UserStatusEnum.EXPIRED); | |
314 | + } | |
315 | + } | |
316 | + } | |
317 | + } | |
318 | + | |
319 | + @Override | |
320 | + @Transactional | |
321 | + public boolean deleteUser(Set<String> userIds,boolean isSysadmin,String tenantId) { | |
322 | + // 1. 判断是否所有的id都属于此人 | |
323 | + if (!isSysadmin) { | |
324 | + int notTenantUserCount = | |
325 | + baseMapper.selectCount( | |
326 | + new QueryWrapper<User>() | |
327 | + .lambda() | |
328 | + .ne(User::getTenantCode, tenantId) | |
329 | + .in(User::getId, userIds)); | |
330 | + if (notTenantUserCount > 0) { | |
331 | + throw new AccessDeniedException("cannot delete user that not belong to your tenant"); | |
332 | + } | |
333 | + } | |
334 | + // 2. 删除人员对应的 role | |
335 | + roleMapper.deleteRoleUserMappingByUserIds(userIds); | |
336 | + | |
337 | + // 3. 解绑人员对应的group | |
338 | + | |
339 | + groupService.unBindUserToOrganization(userIds); | |
340 | + | |
341 | + // 4. 删除人员 | |
342 | + baseMapper.deleteBatchIds(userIds); | |
343 | + | |
344 | + return true; | |
345 | + } | |
346 | + | |
347 | + @Override | |
348 | + @Transactional | |
349 | + public UserDTO saveTenantAdmin(UserDTO userDTO,boolean isSysadmin,String tenantId) { | |
350 | + if (StringUtils.isNotBlank(userDTO.getId())) { | |
351 | + return updateUser(userDTO,isSysadmin,tenantId); | |
352 | + } | |
353 | + validatePhoneNumberAndEmail(userDTO); | |
354 | + User user = new User(); | |
355 | + userDTO.copyToEntity(user, ID, PASSWORD, CREATE_TIME, UPDATE_TIME, ACTIVATE_TOKEN); | |
356 | + user.setPassword(passwordEncoder.encode(DEFAULT_PWD)); | |
357 | + List<User> users = | |
358 | + baseMapper.selectList( | |
359 | + new QueryWrapper<User>().lambda().eq(User::getUsername, userDTO.getUsername())); | |
360 | + if (!users.isEmpty()) { | |
361 | + throw new DataValidationException("用户已存在"); | |
362 | + } | |
363 | + baseMapper.insert(user); | |
364 | + List<TenantRole> tenantRoleList = | |
365 | + tenantRoleMapper.selectList( | |
366 | + new QueryWrapper<TenantRole>() | |
367 | + .lambda() | |
368 | + .eq(TenantRole::getTenantCode, userDTO.getTenantCode())); | |
369 | + // 保存用户与角色的映射信息 | |
370 | + if (null == tenantRoleList || tenantRoleList.size() == 0) { | |
371 | + throw new FastIotException(ErrorMessage.INVALID_PARAMETER); | |
372 | + } | |
373 | + for (TenantRole tenantRole : tenantRoleList) { | |
374 | + roleMapper.saveUserRoleMapping(user.getId(), tenantRole.getRoleId()); | |
375 | + } | |
376 | + user.copyToDTO(userDTO, PASSWORD, ACTIVATE_TOKEN); | |
377 | + return userDTO; | |
378 | + } | |
379 | + | |
380 | + @Override | |
381 | + @Transactional | |
382 | + public void resetPassword(String userId,boolean isSysadmin,String tenantId) { | |
383 | + if (isSysadmin) { | |
384 | + baseMapper.setPassword2NullAndInsertActiveToken( | |
385 | + userId, RandomStringUtils.randomAlphabetic(10)); | |
386 | + } else { | |
387 | + User user = baseMapper.selectById(userId); | |
388 | + if (user == null) { | |
389 | + return; | |
390 | + } | |
391 | + if (tenantId.equals(user.getTenantCode())) { | |
392 | + baseMapper.setPassword2NullAndInsertActiveToken( | |
393 | + userId, RandomStringUtils.randomAlphabetic(10)); | |
394 | + } | |
395 | + } | |
396 | + } | |
397 | + | |
398 | + @Override | |
399 | + public List<UserDetailsDTO> getUserByPhoneNumber(String phoneNumber) { | |
400 | + return baseMapper.findUserDetailsByPhoneNumber(phoneNumber); | |
401 | + } | |
402 | + | |
403 | + @Override | |
404 | + public void sendRestPasswordMsg(SendResetPasswordEmailMsg msg) { | |
405 | + // 通过用户ID查询用户信息 | |
406 | + User user = baseMapper.selectById(msg.getUserId()); | |
407 | + if (null == user) { | |
408 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
409 | + } | |
410 | + | |
411 | + // 通过模板用途和状态查询模板信息 | |
412 | + MessageTemplateDTO messageTemplateDTO = new MessageTemplateDTO(); | |
413 | + String messageType = msg.getMessageTypeEnum().name(); | |
414 | + messageTemplateDTO.setMessageType(messageType); | |
415 | + messageTemplateDTO.setTemplatePurpose(MsgTemplatePurposeEnum.FOR_SET_PASSWORD.name()); | |
416 | + messageTemplateDTO.setStatus(1); | |
417 | + List<MessageTemplateDTO> templateDTOList = | |
418 | + messageTemplateService.findMessageTemplate(messageTemplateDTO); | |
419 | + if (null == templateDTOList || templateDTOList.size() < 1) { | |
420 | + throw new DataValidationException(ErrorMessage.EXIST_ENABLE_TEMPLATE.getMessage()); | |
421 | + } | |
422 | + if (messageType.equalsIgnoreCase(MessageTypeEnum.PHONE_MESSAGE.name())) { | |
423 | + SmsReqDTO smsReqDTO = new SmsReqDTO(); | |
424 | + smsReqDTO.setPhoneNumbers(user.getPhoneNumber()); | |
425 | + smsReqDTO.setId(templateDTOList.get(0).getId()); | |
426 | + LinkedHashMap<String, String> params = new LinkedHashMap<>(); | |
427 | + params.put("name", user.getRealName()); | |
428 | + smsReqDTO.setParams(params); | |
429 | + ytSmsService.sendSms(smsReqDTO); | |
430 | + } | |
431 | + } | |
432 | + | |
433 | + @Override | |
434 | + public Optional<List<UserDTO>> getOrganizationUserByOrganizationId(String groupId,String tenantId) { | |
435 | + Organization group = organizationMapper.selectById(groupId); | |
436 | + if (group == null | |
437 | + || !group.getTenantCode().equals(tenantId)) { | |
438 | + return Optional.empty(); | |
439 | + } | |
440 | + Set<String> userIds = | |
441 | + userOrganizationMappingMapper | |
442 | + .selectList( | |
443 | + new QueryWrapper<UserOrganizationMapping>() | |
444 | + .lambda() | |
445 | + .eq(UserOrganizationMapping::getOrganizationId, group)) | |
446 | + .stream() | |
447 | + .map(UserOrganizationMapping::getUserId) | |
448 | + .collect(Collectors.toSet()); | |
449 | + List<User> users = baseMapper.selectBatchIds(userIds); | |
450 | + return Optional.ofNullable(ReflectUtils.sourceToTarget(users, UserDTO.class)); | |
451 | + } | |
452 | + | |
453 | + @Override | |
454 | + public String[] getUserRoleOrOrganization(RoleOrOrganizationReqDTO roleOrGroupReqDTO) { | |
455 | + String userId = roleOrGroupReqDTO.getUserId(); | |
456 | + if (StringUtils.isEmpty(userId)) { | |
457 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
458 | + } | |
459 | + if (roleOrGroupReqDTO.isQueryRole()) { | |
460 | + List<String> roleIds = | |
461 | + userRoleMapper | |
462 | + .selectList(new QueryWrapper<UserRole>().lambda().eq(UserRole::getUserId, userId)) | |
463 | + .stream() | |
464 | + .map(UserRole::getRoleId) | |
465 | + .collect(Collectors.toList()); | |
466 | + return roleIds.toArray(new String[roleIds.size()]); | |
467 | + } | |
468 | + if (roleOrGroupReqDTO.isQueryOrganization()) { | |
469 | + List<String> roleIds = | |
470 | + userOrganizationMappingMapper | |
471 | + .selectList( | |
472 | + new QueryWrapper<UserOrganizationMapping>() | |
473 | + .lambda() | |
474 | + .eq(UserOrganizationMapping::getUserId, userId)) | |
475 | + .stream() | |
476 | + .map(UserOrganizationMapping::getOrganizationId) | |
477 | + .collect(Collectors.toList()); | |
478 | + return roleIds.toArray(new String[roleIds.size()]); | |
479 | + } | |
480 | + return null; | |
481 | + } | |
482 | + | |
483 | + @Override | |
484 | + @Transactional | |
485 | + public boolean changePassword(AccountReqDTO accountReqDTO) { | |
486 | + User user = baseMapper.selectById(accountReqDTO.getUserId()); | |
487 | + if (null == user | |
488 | + || StringUtils.isEmpty(accountReqDTO.getPassword()) | |
489 | + || StringUtils.isEmpty(accountReqDTO.getResetPassword())) { | |
490 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
491 | + } | |
492 | + if (!StringUtils.isEmpty(user.getPassword())) { | |
493 | + // 判断用户密码是否正确 | |
494 | + boolean isMatch = passwordEncoder.matches(accountReqDTO.getPassword(), user.getPassword()); | |
495 | + if (!isMatch) { | |
496 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
497 | + } | |
498 | + } | |
499 | + // 修改密码 | |
500 | + user.setPassword(passwordEncoder.encode(accountReqDTO.getResetPassword())); | |
501 | + user.setActivateToken(RandomStringUtils.randomAlphabetic(10)); | |
502 | + return baseMapper.updateById(user) > 0; | |
503 | + } | |
504 | + | |
505 | + @Override | |
506 | + public UserDTO accountExist(String userName,String tenantId) { | |
507 | + if (StringUtils.isEmpty(userName)) { | |
508 | + throw new DataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); | |
509 | + } | |
510 | + UserDTO userDTO = new UserDTO(); | |
511 | + userDTO.setTenantCode(tenantId); | |
512 | + userDTO.setUsername(userName); | |
513 | + return baseMapper.findUserInfo(userDTO); | |
514 | + } | |
515 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.AdminSetting; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface AdminSettingMapper extends BaseMapper<AdminSetting> { | |
9 | + | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.AlarmContact; | |
6 | + | |
7 | +/** @Description 告警联系人持久化数据层 @Author cxy @Date 2021/11/2 11:52 */ | |
8 | +@Mapper | |
9 | +public interface AlarmContactMapper extends BaseMapper<AlarmContact> {} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.thingsboard.server.dao.yunteng.entities.AlarmProfile; | |
7 | + | |
8 | +@Mapper | |
9 | +public interface AlarmProfileMapper extends BaseMapper<AlarmProfile> { | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.apache.ibatis.annotations.Param; | |
7 | +import org.thingsboard.server.common.data.Device; | |
8 | +import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
9 | +import org.thingsboard.server.dao.yunteng.entities.YtDevice; | |
10 | + | |
11 | +import java.util.Map; | |
12 | + | |
13 | +@Mapper | |
14 | +public interface DeviceMapper extends BaseMapper<YtDevice> { | |
15 | + | |
16 | + IPage<DeviceDTO> getDevicePage( | |
17 | + IPage<?> page, @Param("queryMap") Map<String, Object> queryMap); | |
18 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.thingsboard.server.common.data.DeviceProfile; | |
7 | +import org.thingsboard.server.common.data.yunteng.dto.DeviceProfileDTO; | |
8 | + | |
9 | +import java.util.List; | |
10 | + | |
11 | +@Mapper | |
12 | +public interface DeviceProfileMapper extends BaseMapper<DeviceProfile> { | |
13 | + | |
14 | + List<DeviceProfileDTO> getDeviceProfileInfo(DeviceProfileDTO deviceProfileDTO); | |
15 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.thingsboard.server.dao.yunteng.entities.DeviceType; | |
7 | + | |
8 | +@Mapper | |
9 | +public interface DeviceTypeMapper extends BaseMapper<DeviceType> { | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.MailLog; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface MaiLogMapper extends BaseMapper<MailLog> { | |
9 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | + | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.apache.ibatis.annotations.Param; | |
7 | +import org.thingsboard.server.common.data.yunteng.dto.MenuDTO; | |
8 | +import org.thingsboard.server.dao.yunteng.entities.Menu; | |
9 | + | |
10 | +import java.util.Collection; | |
11 | +import java.util.List; | |
12 | +import java.util.Set; | |
13 | + | |
14 | +@Mapper | |
15 | +public interface MenuMapper extends BaseMapper<Menu> { | |
16 | + List<MenuDTO> selectTenantMenu(String tenantCode); | |
17 | + | |
18 | + List<MenuDTO> selectSysAdminMenu(); | |
19 | + | |
20 | + List<MenuDTO> selectMyMenu(String userId); | |
21 | + | |
22 | + int deleteTenantMenuMappingByMenuIds(@Param("menuIds") Collection<String> menuIds); | |
23 | + | |
24 | + Set<String> selectTenantMenuIds(String tenantCode); | |
25 | + | |
26 | + Set<String> selectRoleMenuIds(String roleId); | |
27 | + | |
28 | + Set<String> getAllIdsByTenantCode(@Param("tenantCodes") Collection<String> tenantCodes); | |
29 | + | |
30 | + int addMenuToTenant( | |
31 | + @Param("tenantCode") String tenantCode, @Param("menuIds") Collection<String> menuIds); | |
32 | + | |
33 | + int addMenuToRole( | |
34 | + @Param("roleId") String roleId, @Param("menuIds") Collection<String> menuIds); | |
35 | + | |
36 | + int removeMenuFromTenant( | |
37 | + @Param("tenantCode") String tenantCode, @Param("menuIds") Collection<String> menuIds); | |
38 | + | |
39 | + int removeMenuFromRole( | |
40 | + @Param("roleId") String roleId, @Param("menuIds") Collection<String> menuIds); | |
41 | + | |
42 | + Set<String> getAllPermission(); | |
43 | + | |
44 | + Set<String> getAllPermissionsByTenantCode(String tenantCode); | |
45 | + | |
46 | + Set<String> getAllPermissionsByUserId(String userId); | |
47 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.apache.ibatis.annotations.Param; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.MessageConfigDTO; | |
7 | +import org.thingsboard.server.dao.yunteng.entities.MessageConfig; | |
8 | + | |
9 | +@Mapper | |
10 | +public interface MessageConfigMapper extends BaseMapper<MessageConfig> { | |
11 | + MessageConfigDTO getEnableConfigByMessageAndPlatform( | |
12 | + @Param("messageType") String messageType, | |
13 | + @Param("platformType") String platformType, | |
14 | + @Param("tenantCode") String tenantCode); | |
15 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.apache.ibatis.annotations.Param; | |
7 | +import org.thingsboard.server.common.data.yunteng.dto.MessageTemplateDTO; | |
8 | +import org.thingsboard.server.dao.yunteng.entities.MessageTemplate; | |
9 | + | |
10 | +import java.util.List; | |
11 | +import java.util.Map; | |
12 | + | |
13 | +@Mapper | |
14 | +public interface MessageTemplateMapper extends BaseMapper<MessageTemplate> { | |
15 | + /** | |
16 | + * 获取模板分页数据 | |
17 | + * | |
18 | + * @param page 分页数据 | |
19 | + * @param queryMap 查询参数 | |
20 | + * @return | |
21 | + */ | |
22 | + IPage<MessageTemplateDTO> getTemplatePage( | |
23 | + IPage<?> page, @Param("queryMap") Map<String, Object> queryMap); | |
24 | + | |
25 | + /** | |
26 | + * 查询模板信息 | |
27 | + * @param templateDTO 请求参数 | |
28 | + * @return 模板信息列表 List<MessageTemplateDTO> | |
29 | + */ | |
30 | + List<MessageTemplateDTO> findMessageTemplate(MessageTemplateDTO templateDTO); | |
31 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.apache.ibatis.annotations.Param; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO; | |
7 | +import org.thingsboard.server.dao.yunteng.entities.Organization; | |
8 | + | |
9 | +import java.util.Collection; | |
10 | +import java.util.List; | |
11 | + | |
12 | +@Mapper | |
13 | +public interface OrganizationMapper extends BaseMapper<Organization> { | |
14 | + /** | |
15 | + * 通过租户code和组织Id递归查询其组织及子组织的List | |
16 | + * | |
17 | + * @param tenantCode 租户code | |
18 | + * @param organizationIds 待查询的组织ID,可以为空 | |
19 | + * @return 组织及子组织,直到叶节点 | |
20 | + */ | |
21 | + List<OrganizationDTO> findOrganizationTreeList( | |
22 | + @Param("tenantCode") String tenantCode, @Param("organizationIds") Collection<String> organizationIds); | |
23 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.RateLimiterEntity; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface RateLimiterMapper extends BaseMapper<RateLimiterEntity> { | |
9 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.apache.ibatis.annotations.Param; | |
7 | +import org.thingsboard.server.common.data.yunteng.dto.RoleDTO; | |
8 | +import org.thingsboard.server.dao.yunteng.entities.Role; | |
9 | + | |
10 | +import java.util.Collection; | |
11 | +import java.util.List; | |
12 | +import java.util.Set; | |
13 | + | |
14 | +@Mapper | |
15 | +public interface RoleMapper extends BaseMapper<Role> { | |
16 | + void deleteRoleBatchByTenantIds(@Param("tenantIds") Collection<String> tenantIds); | |
17 | + | |
18 | + int deleteRoleMenuMappingByRoleIds(@Param("roleIds") Collection<String> roleIds); | |
19 | + | |
20 | + int deleteRoleMenuMappingByMenuIds(@Param("menuIds") Collection<String> menuIds); | |
21 | + | |
22 | + int deleteRoleUserMappingByRoleIds(@Param("roleIds") Collection<String> roleIds); | |
23 | + | |
24 | + int deleteRoleUserMappingByUserIds(@Param("userIds") Collection<String> userIds); | |
25 | + | |
26 | + Set<String> getAllIdsByTenantCode(@Param("tenantCodes") Collection<String> tenantCodes); | |
27 | + | |
28 | + Set<String> checkRoleUserMappingByRoleIds(@Param("ids") Collection<String> ids); | |
29 | + | |
30 | + Set<Role> selectRoleByUserId(String userId); | |
31 | + | |
32 | + Set<String> getMenuIdsByRoleId(String roleId); | |
33 | + | |
34 | + void saveUserRoleMapping(@Param("userId")String userId,@Param("roleId")String roleId); | |
35 | + | |
36 | + List<RoleDTO> findRoleInfo(RoleDTO roleDTO); | |
37 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.SmsLog; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface SmsLogMapper extends BaseMapper<SmsLog> { | |
9 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.SysDept; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface SysDeptMapper extends BaseMapper<SysDept> { | |
9 | + | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.apache.ibatis.annotations.Param; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.SysDictItemDTO; | |
7 | +import org.thingsboard.server.dao.yunteng.entities.SysDictItem; | |
8 | + | |
9 | +import java.util.List; | |
10 | + | |
11 | +@Mapper | |
12 | +public interface SysDictItemMapper extends BaseMapper<SysDictItem> { | |
13 | + /** | |
14 | + * 通过dict表的Code和dictItem的codeText查询字典表的值 | |
15 | + * | |
16 | + * @param dictCode 字典表Code | |
17 | + * @param itemValue 字典Item表文本值 | |
18 | + * @return 返回字典Item表文本对应的文本 | |
19 | + */ | |
20 | + SysDictItemDTO getDictValueByCodeAndText( | |
21 | + @Param("dictCode") String dictCode, | |
22 | + @Param("itemValue") String itemValue); | |
23 | + /** | |
24 | + * 根据租户Code和字典表ID查询字典值 | |
25 | + * | |
26 | + * @param dictId 字典表ID | |
27 | + * @return List<SysDictItemDTO> | |
28 | + */ | |
29 | + List<SysDictItemDTO> getDictItemInfo( | |
30 | + @Param("dictId") String dictId, | |
31 | + @Param("dictCode") String dictCode); | |
32 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.apache.ibatis.annotations.Param; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.SysDictDTO; | |
7 | +import org.thingsboard.server.dao.yunteng.entities.SysDict; | |
8 | + | |
9 | +@Mapper | |
10 | +public interface SysDictMapper extends BaseMapper<SysDict> { | |
11 | + | |
12 | + /** | |
13 | + * 根据租户Code和字典编码获取字典信息 | |
14 | + * | |
15 | + * @param tenantCode 租户Code | |
16 | + * @param dictCode 字典信息 | |
17 | + * @return SysDictDTO字典信息 | |
18 | + */ | |
19 | + SysDictDTO getDictInfoByCode( | |
20 | + @Param("tenantCode") String tenantCode, | |
21 | + @Param("dictCode") String dictCode); | |
22 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.apache.ibatis.annotations.Param; | |
7 | +import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; | |
8 | +import org.thingsboard.server.dao.yunteng.entities.Tenant; | |
9 | + | |
10 | +import java.util.Collection; | |
11 | +import java.util.Set; | |
12 | + | |
13 | +@Mapper | |
14 | +public interface TenantMapper extends BaseMapper<Tenant> { | |
15 | + Set<String> getTenantCodesByTenantIds(@Param("tenantIds") Collection<String> tenantIds); | |
16 | + | |
17 | + IPage<TenantDTO> getTenantPage(IPage<?> page, @Param("tenantName") String tenantName); | |
18 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.thingsboard.server.dao.yunteng.entities.TenantMenu; | |
7 | + | |
8 | +@Mapper | |
9 | +public interface TenantMenuMapper extends BaseMapper<TenantMenu> { | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.TenantRole; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface TenantRoleMapper extends BaseMapper<TenantRole> { | |
9 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.apache.ibatis.annotations.Param; | |
7 | +import org.thingsboard.server.common.data.yunteng.dto.UserDTO; | |
8 | +import org.thingsboard.server.common.data.yunteng.dto.UserDetailsDTO; | |
9 | +import org.thingsboard.server.dao.yunteng.entities.User; | |
10 | + | |
11 | +import java.util.Collection; | |
12 | +import java.util.List; | |
13 | +import java.util.Map; | |
14 | +import java.util.Set; | |
15 | + | |
16 | +@Mapper | |
17 | +public interface UserMapper extends BaseMapper<User> { | |
18 | + | |
19 | + List<UserDetailsDTO> findUserDetailsByUserName(String username); | |
20 | + | |
21 | + List<UserDetailsDTO> findUserDetailsByPhoneNumber(String phoneNumber); | |
22 | + | |
23 | + IPage<UserDTO> getUserPage(IPage<?> page, @Param("queryMap") Map<String, Object> queryMap); | |
24 | + | |
25 | + IPage<UserDTO> getAdminUserPage( | |
26 | + IPage<?> page, @Param("tenantCode") String tenantCode, @Param("roleType") String roleType); | |
27 | + | |
28 | + IPage<UserDTO> selectAllTenantUser(IPage<?> page); | |
29 | + | |
30 | + Set<String> getAllIdsByTenantCode(@Param("tenantCodes") Collection<String> tenantCodes); | |
31 | + | |
32 | + void setPassword2NullAndInsertActiveToken( | |
33 | + @Param("userId") String userId, @Param("activeToken") String activeToken); | |
34 | + | |
35 | + UserDTO findUserInfo(UserDTO userDTO); | |
36 | +} | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/yunteng/mapper/UserOrganizationMappingMapper.java
0 → 100644
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
4 | +import org.apache.ibatis.annotations.Mapper; | |
5 | +import org.thingsboard.server.dao.yunteng.entities.UserOrganizationMapping; | |
6 | + | |
7 | +@Mapper | |
8 | +public interface UserOrganizationMappingMapper extends BaseMapper<UserOrganizationMapping> {} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.mapper; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
5 | +import org.apache.ibatis.annotations.Mapper; | |
6 | +import org.thingsboard.server.dao.yunteng.entities.UserRole; | |
7 | + | |
8 | +@Mapper | |
9 | +public interface UserRoleMapper extends BaseMapper<UserRole> { | |
10 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | + | |
4 | +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |
5 | +import com.baomidou.mybatisplus.core.mapper.BaseMapper; | |
6 | +import com.baomidou.mybatisplus.core.metadata.IPage; | |
7 | +import com.baomidou.mybatisplus.core.metadata.OrderItem; | |
8 | +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; | |
9 | +import org.apache.commons.lang3.StringUtils; | |
10 | +import org.springframework.beans.factory.annotation.Autowired; | |
11 | +import org.thingsboard.server.common.data.yunteng.constant.ModelConstants; | |
12 | +import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum; | |
13 | +import org.thingsboard.server.common.data.yunteng.utils.ReflectUtils; | |
14 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
15 | +import org.thingsboard.server.common.data.yunteng.utils.tools.TBPageData; | |
16 | +import org.thingsboard.server.dao.yunteng.entities.BaseEntity; | |
17 | + | |
18 | +import java.util.List; | |
19 | +import java.util.Map; | |
20 | + | |
21 | +import static org.thingsboard.server.common.data.yunteng.constant.QueryConstant.*; | |
22 | + | |
23 | +public abstract class AbstractBaseService<M extends BaseMapper<T>, T extends BaseEntity> | |
24 | + implements BaseService<T> { | |
25 | + | |
26 | + @Autowired protected M baseMapper; | |
27 | + | |
28 | + @Override | |
29 | + public List<T> findAllByTenant(String tenantId) { | |
30 | + QueryWrapper<T> wrapper = new QueryWrapper<>(); | |
31 | + wrapper.eq(StringUtils.isNotBlank(tenantId), ModelConstants.TableFields.TENANT_ID, tenantId); | |
32 | + return baseMapper.selectList(wrapper); | |
33 | + } | |
34 | + | |
35 | + protected IPage<T> getPage(Map<String, Object> params, String defaultOrderField, boolean isAsc) { | |
36 | + int curPage = 1; | |
37 | + int limit = 10; | |
38 | + if (params.get(PAGE) != null) { | |
39 | + curPage = Integer.parseInt(params.get(PAGE).toString()); | |
40 | + } | |
41 | + | |
42 | + if (params.get(PAGE_SIZE) != null) { | |
43 | + limit = Integer.parseInt(params.get(PAGE_SIZE).toString()); | |
44 | + } | |
45 | + | |
46 | + Page<T> page = new Page<>(curPage, limit); | |
47 | + String orderField = (String) params.get(ORDER_FILED); | |
48 | + String order = (String) params.get(ORDER_TYPE); | |
49 | + if (StringUtils.isNotBlank(orderField) && StringUtils.isNotBlank(order)) { | |
50 | + return OrderTypeEnum.ASC.name().equalsIgnoreCase(order) | |
51 | + ? page.addOrder(OrderItem.asc(orderField)) | |
52 | + : page.addOrder(OrderItem.desc(orderField)); | |
53 | + } else if (StringUtils.isBlank(defaultOrderField)) { | |
54 | + return page; | |
55 | + } else { | |
56 | + if (isAsc) { | |
57 | + page.addOrder(OrderItem.asc(defaultOrderField)); | |
58 | + } else { | |
59 | + page.addOrder(OrderItem.desc(defaultOrderField)); | |
60 | + } | |
61 | + return page; | |
62 | + } | |
63 | + } | |
64 | + | |
65 | + protected <D> PageData<D> getPageData(IPage<?> iPage, Class<D> target) { | |
66 | + List<D> targetList = ReflectUtils.sourceToTarget(iPage.getRecords(), target); | |
67 | + return new PageData<>(targetList, iPage.getTotal()); | |
68 | + } | |
69 | + | |
70 | + protected <D> PageData<D> getPageData(TBPageData<T> tbPageData, Class<D> target){ | |
71 | + List<D> targetList = ReflectUtils.sourceToTarget(tbPageData.getData(),target); | |
72 | + return new PageData<>(targetList, tbPageData.getTotalElements()); | |
73 | + } | |
74 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | + | |
4 | + | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.MenuDTO; | |
6 | + | |
7 | +import java.util.List; | |
8 | +import java.util.Optional; | |
9 | +import java.util.Set; | |
10 | + | |
11 | +public interface MenuService { | |
12 | + | |
13 | + /** | |
14 | + * sysadmin获取所有的menu,但是不获取租户自己创建的menu | |
15 | + * | |
16 | + * @return list 树状menu | |
17 | + */ | |
18 | + List<MenuDTO> getAllMenus(String tenantId); | |
19 | + | |
20 | + /** | |
21 | + * 获取自己的menu, 如果是tenant admin, 获取已分配的所有菜单,如果是普通用户,获取自己被租户管理员分配的菜单 | |
22 | + * | |
23 | + * @return list 树状menu | |
24 | + */ | |
25 | + List<MenuDTO> getMyMenus(String tenantId,String userId,boolean isSysAdmin,boolean isTenantAdmin); | |
26 | + | |
27 | + MenuDTO saveMenu(String tenantId,boolean isSysAdmin,MenuDTO menuDTO); | |
28 | + | |
29 | + Optional<MenuDTO> getMenu(String id); | |
30 | + | |
31 | + MenuDTO updateMenu(String tenantId,boolean isSysAdmin,MenuDTO menuDTO); | |
32 | + | |
33 | + boolean deleteMenus(String tenantId,String[] ids); | |
34 | + | |
35 | + boolean assignMenuToTenant(String tenantId,String[] menuId); | |
36 | + | |
37 | + boolean assignMenuToRole(String[] menuId, String roleId); | |
38 | + | |
39 | + Set<String> getMenuIdsByRoleId(String roleId); | |
40 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | + | |
4 | + | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.MessageTemplateDTO; | |
6 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
7 | + | |
8 | +import java.util.List; | |
9 | +import java.util.Map; | |
10 | +import java.util.Set; | |
11 | + | |
12 | +public interface MessageTemplateService { | |
13 | + | |
14 | + PageData<MessageTemplateDTO> page(Map<String, Object> queryMap); | |
15 | + | |
16 | + MessageTemplateDTO saveMessageTemplate(MessageTemplateDTO templateDTO); | |
17 | + | |
18 | + boolean deleteMessageTemplate(Set<String> ids); | |
19 | + | |
20 | + MessageTemplateDTO updateMessageTemplate(MessageTemplateDTO templateDTO); | |
21 | + | |
22 | + /** | |
23 | + * 查询模板信息 | |
24 | + * @param templateDTO 请求信息 | |
25 | + * @return MessageTemplateDTO模板信息 | |
26 | + */ | |
27 | + List<MessageTemplateDTO> findMessageTemplate(MessageTemplateDTO templateDTO); | |
28 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | + | |
4 | + | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO; | |
7 | + | |
8 | +import java.util.List; | |
9 | +import java.util.Set; | |
10 | + | |
11 | +public interface OrganizationService { | |
12 | + OrganizationDTO saveOrganization(OrganizationDTO organizationDTO); | |
13 | + | |
14 | + boolean deleteOrganizations(DeleteDTO deleteDTO); | |
15 | + | |
16 | + List<OrganizationDTO> getMyOrganizations(); | |
17 | + | |
18 | + OrganizationDTO updateOrganization(OrganizationDTO organizationDTO); | |
19 | + | |
20 | + void bindUserToOrganization(String userId, String[] organizationIds); | |
21 | + | |
22 | + void unBindUserToOrganization(Set<String> userIds); | |
23 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | + | |
4 | +import org.thingsboard.server.common.data.yunteng.dto.RoleDTO; | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.request.RoleReqDTO; | |
6 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
7 | + | |
8 | +import java.util.List; | |
9 | +import java.util.Map; | |
10 | +import java.util.Set; | |
11 | + | |
12 | +public interface RoleService { | |
13 | + PageData<RoleDTO> page(boolean isSysadmin,boolean isPlatformAdmin, String tenantId,Map<String, Object> queryMap); | |
14 | + | |
15 | + boolean deleteRole(String[] roleIds,String tenantId); | |
16 | + | |
17 | + Set<String> getPermissions(boolean isSysadmin,boolean isTenantAdmin,String tenantId,String useerId); | |
18 | + | |
19 | + void updateRoleStatus(String roleId, int status,boolean isSysadmin,String tenantId); | |
20 | + | |
21 | + RoleDTO saveOrUpdateRoleInfoWithMenu(RoleReqDTO roleReqDTO,boolean isSysadmin,boolean isPlatformAdmin,String tenantId); | |
22 | + | |
23 | + /** | |
24 | + * 查询所有的角色信息 | |
25 | + * @param roleDTO 过滤条件 | |
26 | + * @return 所有角色信息 | |
27 | + */ | |
28 | + List<RoleDTO> findRoleInfo(boolean isTenantAdmin,String tenantId,String userId,RoleDTO roleDTO); | |
29 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | +import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; | |
4 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
5 | + | |
6 | +import java.util.List; | |
7 | +import java.util.Map; | |
8 | +import java.util.Optional; | |
9 | +import java.util.Set; | |
10 | + | |
11 | +public interface YtDeviceService { | |
12 | + DeviceDTO insertOrUpdate(String tenantId,DeviceDTO deviceDTO); | |
13 | + | |
14 | + void deleteDevices(String tenantId,Set<String> ids); | |
15 | + | |
16 | + Optional<DeviceDTO> getDevice(String tenantId,String id); | |
17 | + | |
18 | + PageData<DeviceDTO> page(String tenantId,Map<String, Object> queryMap); | |
19 | + | |
20 | + /** | |
21 | + * 查询所有的设备信息 | |
22 | + * @param deviceDTO 过滤参数 | |
23 | + * @return List<DeviceDTO> | |
24 | + */ | |
25 | + List<DeviceDTO> findDeviceInfo(String tenantId,DeviceDTO deviceDTO); | |
26 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | + | |
4 | + | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.TenantDTO; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.request.TenantReqDTO; | |
7 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
8 | + | |
9 | +import java.util.List; | |
10 | +import java.util.Map; | |
11 | +import java.util.Optional; | |
12 | + | |
13 | +public interface YtTenantService { | |
14 | + TenantDTO createNewTenant(TenantReqDTO tenantReqDTO); | |
15 | + | |
16 | + TenantDTO updateTenant(TenantDTO tenantDTO); | |
17 | + | |
18 | + boolean deleteTenants(String[] ids); | |
19 | + | |
20 | + Optional<TenantDTO> findById(String id); | |
21 | + | |
22 | + PageData<TenantDTO> page(Map<String, Object> queryMap); | |
23 | + | |
24 | + TenantDTO updateOrCreateTenant(TenantReqDTO tenantReqDTO); | |
25 | + | |
26 | + List<String> getTenantRolesByTenantCode(String tenantCode); | |
27 | +} | ... | ... |
1 | +package org.thingsboard.server.dao.yunteng.service; | |
2 | + | |
3 | +import org.thingsboard.server.common.data.yunteng.dto.UserDTO; | |
4 | +import org.thingsboard.server.common.data.yunteng.dto.UserDetailsDTO; | |
5 | +import org.thingsboard.server.common.data.yunteng.dto.UserInfoDTO; | |
6 | +import org.thingsboard.server.common.data.yunteng.dto.request.AccountReqDTO; | |
7 | +import org.thingsboard.server.common.data.yunteng.dto.request.RoleOrOrganizationReqDTO; | |
8 | +import org.thingsboard.server.common.data.yunteng.dto.request.SendResetPasswordEmailMsg; | |
9 | +import org.thingsboard.server.common.data.yunteng.utils.tools.PageData; | |
10 | + | |
11 | +import java.util.List; | |
12 | +import java.util.Map; | |
13 | +import java.util.Optional; | |
14 | +import java.util.Set; | |
15 | + | |
16 | +public interface YtUserService { | |
17 | + List<UserDetailsDTO> findUserDetailsByUsername(String username); | |
18 | + | |
19 | + UserDTO saveAccount(UserDTO userDTO, boolean sendEmail, boolean sendMsg,boolean isSysadmin,String tenantId); | |
20 | + | |
21 | + String getActivationLink(String userId,boolean isSysadmin,String tenantId); | |
22 | + | |
23 | + Optional<UserDTO> getUser(String userId,boolean isSysadmin,String tenantId); | |
24 | + | |
25 | + UserInfoDTO me(String userId,String tenantId,Set<String> currentRoles); | |
26 | + | |
27 | + PageData<UserDTO> page(Map<String, Object> queryMap,boolean isSysadmin,boolean isPlatformAdmin,boolean isTenantAdmin,String tenantId); | |
28 | + | |
29 | + UserDTO updateUser(UserDTO userDTO,boolean isSysadmin,String tenantId); | |
30 | + | |
31 | + boolean deleteUser(Set<String> userIds,boolean isSysadmin,String tenantId); | |
32 | + | |
33 | + UserDTO saveTenantAdmin(UserDTO userDTO,boolean isSysadmin,String tenantId); | |
34 | + | |
35 | + void resetPassword(String userId,boolean isSysadmin,String tenantId); | |
36 | + | |
37 | + List<UserDetailsDTO> getUserByPhoneNumber(String phoneNumber); | |
38 | + | |
39 | + /** | |
40 | + * 发送密码重置新消息 | |
41 | + * | |
42 | + * @param msg 请求信息 | |
43 | + */ | |
44 | + void sendRestPasswordMsg(SendResetPasswordEmailMsg msg); | |
45 | + | |
46 | + /** | |
47 | + * 判断账号是否注册过 | |
48 | + * | |
49 | + * @param username 账号 | |
50 | + * @return 账号信息 | |
51 | + */ | |
52 | + UserDTO accountExist(String username,String tenantId); | |
53 | + | |
54 | + Optional<List<UserDTO>> getOrganizationUserByOrganizationId(String organizationId,String tenantId); | |
55 | + | |
56 | + /** | |
57 | + * 查询用户关联的Role或者Group | |
58 | + * | |
59 | + * @param roleOrOrganizationReqDTO 参数 | |
60 | + * @return 返回关联的Role或者Group | |
61 | + */ | |
62 | + String[] getUserRoleOrOrganization(RoleOrOrganizationReqDTO roleOrOrganizationReqDTO); | |
63 | + | |
64 | + /** | |
65 | + * 修改密码 | |
66 | + * | |
67 | + * @param accountReqDTO 账号信息 | |
68 | + * @return 修改成功、失败 | |
69 | + */ | |
70 | + boolean changePassword(AccountReqDTO accountReqDTO); | |
71 | +} | ... | ... |
dao/src/main/resources/mapper/MenuMapper.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.MenuMapper"> | |
5 | + <resultMap type="org.thingsboard.server.common.data.yunteng.dto.MenuDTO" id="menuDTOMap"> | |
6 | + <result property="id" column="id"/> | |
7 | + <result property="name" column="name"/> | |
8 | + <result property="parentId" column="parent_id"/> | |
9 | + <result property="path" column="path"/> | |
10 | + <result property="type" column="type" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> | |
11 | + <result property="permission" column="permission"/> | |
12 | + <result property="sort" column="sort"/> | |
13 | + <result property="tenantCode" column="tenant_code"/> | |
14 | + <result property="component" column="component"/> | |
15 | + <result property="meta" column="meta" | |
16 | + typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/> | |
17 | + <result property="alias" column="alias"/> | |
18 | + <result property="redirect" column="redirect"/> | |
19 | + <result property="caseSensitive" column="case_sensitive"/> | |
20 | + <result property="createTime" column="create_time"/> | |
21 | + <result property="updateTime" column="update_time"/> | |
22 | + </resultMap> | |
23 | + <sql id="menuDTOMapColumn"> | |
24 | + id, | |
25 | + parent_id, | |
26 | + path, | |
27 | + type, | |
28 | + permission, | |
29 | + sort, | |
30 | + component, | |
31 | + name, | |
32 | + meta, | |
33 | + alias, | |
34 | + redirect, | |
35 | + case_sensitive, | |
36 | + create_time, | |
37 | + update_time, | |
38 | + tenant_code | |
39 | + </sql> | |
40 | + <select id="selectTenantMenu" resultMap="menuDTOMap"> | |
41 | + SELECT | |
42 | + <include refid="menuDTOMapColumn"> | |
43 | + </include> | |
44 | + FROM sys_menu | |
45 | + WHERE id IN (SELECT menu_id FROM sys_tenant_menu WHERE tenant_code = #{tenantCode}) | |
46 | + </select> | |
47 | + | |
48 | + <select id="selectMyMenu" resultMap="menuDTOMap"> | |
49 | + SELECT | |
50 | + <include refid="menuDTOMapColumn"> | |
51 | + </include> | |
52 | + FROM sys_menu | |
53 | + WHERE id IN (SELECT menu_id | |
54 | + FROM sys_role_menu | |
55 | + WHERE role_id IN (SELECT id FROM sys_role WHERE id in (SELECT role_id FROM sys_user_role WHERE user_id | |
56 | + = #{userId}) AND enabled=true)) | |
57 | + </select> | |
58 | + | |
59 | + <delete id="deleteTenantMenuMappingByMenuIds"> | |
60 | + DELETE FROM sys_tenant_menu WHERE menu_id IN | |
61 | + <foreach collection="menuIds" item="menuId" open="(" separator="," close=")"> | |
62 | + #{menuId} | |
63 | + </foreach> | |
64 | + </delete> | |
65 | + | |
66 | + <select id="selectTenantMenuIds" resultType="java.lang.String"> | |
67 | + SELECT menu_id | |
68 | + FROM sys_tenant_menu | |
69 | + WHERE tenant_code = #{tenantCode} | |
70 | + </select> | |
71 | + | |
72 | + <select id="selectRoleMenuIds" resultType="java.lang.String"> | |
73 | + SELECT menu_id | |
74 | + FROM sys_role_menu | |
75 | + WHERE role_id = #{roleId} | |
76 | + </select> | |
77 | + | |
78 | + <insert id="addMenuToTenant"> | |
79 | + INSERT INTO sys_tenant_menu(menu_id , tenant_code) VALUES | |
80 | + <foreach collection="menuIds" item="menuId" index="index" separator=","> | |
81 | + (#{menuId},#{tenantCode}) | |
82 | + </foreach> | |
83 | + </insert> | |
84 | + | |
85 | + <insert id="addMenuToRole"> | |
86 | + INSERT INTO sys_role_menu(menu_id , role_id) VALUES | |
87 | + <foreach collection="menuIds" item="menuId" index="index" separator=","> | |
88 | + (#{menuId},#{roleId}) | |
89 | + </foreach> | |
90 | + </insert> | |
91 | + <delete id="removeMenuFromTenant"> | |
92 | + DELETE FROM sys_tenant_menu WHERE | |
93 | + tenant_code =#{tenantCode} AND menu_id IN | |
94 | + <foreach collection="menuIds" item="menuId" open="(" separator="," close=")"> | |
95 | + #{menuId} | |
96 | + </foreach> | |
97 | + </delete> | |
98 | + | |
99 | + <delete id="removeMenuFromRole"> | |
100 | + DELETE FROM sys_role_menu WHERE | |
101 | + role_id =#{roleId} AND menu_id IN | |
102 | + <foreach collection="menuIds" item="menuId" open="(" separator="," close=")"> | |
103 | + #{menuId} | |
104 | + </foreach> | |
105 | + </delete> | |
106 | + | |
107 | + <select id="getAllIdsByTenantCode" resultType="java.lang.String"> | |
108 | + SELECT id FROM sys_menu WHERE tenant_code IN | |
109 | + <foreach collection="tenantCodes" item="tenantCode" open="(" separator="," close=")"> | |
110 | + #{tenantCode} | |
111 | + </foreach> | |
112 | + </select> | |
113 | + | |
114 | + <select id="getAllPermission" resultType="java.lang.String"> | |
115 | + SELECT permission | |
116 | + FROM sys_menu | |
117 | + </select> | |
118 | + | |
119 | + <select id="getAllPermissionsByTenantCode" resultType="java.lang.String"> | |
120 | + SELECT permission | |
121 | + FROM sys_menu | |
122 | + WHERE id IN | |
123 | + (SELECT menu_id FROM sys_tenant_menu WHERE tenant_code = #{tenantCode}) | |
124 | + </select> | |
125 | + | |
126 | + <select id="getAllPermissionsByUserId" resultType="java.lang.String"> | |
127 | + SELECT permission | |
128 | + FROM sys_menu | |
129 | + WHERE id IN | |
130 | + (SELECT menu_id | |
131 | + FROM sys_role_menu | |
132 | + WHERE role_id IN ( | |
133 | + SELECT role_id | |
134 | + FROM sys_user_role | |
135 | + WHERE user_id = #{userId})) | |
136 | + </select> | |
137 | + | |
138 | + <select id="selectSysAdminMenu" resultMap="menuDTOMap"> | |
139 | + SELECT | |
140 | + <include refid="menuDTOMapColumn"> | |
141 | + </include> | |
142 | + FROM sys_menu | |
143 | + WHERE type = 'SYSADMIN' | |
144 | + </select> | |
145 | +</mapper> | ... | ... |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.OrganizationMapper"> | |
5 | + <resultMap type="org.thingsboard.server.common.data.yunteng.dto.OrganizationDTO" id="organizationDTOMap"> | |
6 | + <result property="id" column="id"/> | |
7 | + <result property="parentId" column="parent_id"/> | |
8 | + <result property="sort" column="sort"/> | |
9 | + <result property="name" column="name"/> | |
10 | + <result property="creator" column="creator"/> | |
11 | + <result property="createTime" column="create_time"/> | |
12 | + <result property="updater" column="updater"/> | |
13 | + <result property="updateTime" column="update_time"/> | |
14 | + <result property="remark" column="remark"/> | |
15 | + </resultMap> | |
16 | + | |
17 | + <select id="findOrganizationTreeList" resultMap="organizationDTOMap"> | |
18 | + WITH RECURSIVE organization AS ( | |
19 | + SELECT id, parent_id, name, sort,creator,create_time,updater,update_time,remark,tenant_code | |
20 | + FROM iotfs_organization | |
21 | + WHERE tenant_code = #{tenantCode} | |
22 | + <if test="organizationIds !=null and organizationIds.size() > 0"> | |
23 | + AND id IN | |
24 | + <foreach collection="organizationIds" item="organizationId" open="(" separator="," close=")"> | |
25 | + #{organizationId} | |
26 | + </foreach> | |
27 | + </if> | |
28 | + UNION ALL | |
29 | + SELECT ig.id, ig.parent_id, ig.name, ig.sort,ig.creator,ig.create_time,ig.updater,ig.update_time,ig.remark,ig.tenant_code | |
30 | + FROM iotfs_organization ig | |
31 | + JOIN organization ON ig.parent_id = organization.id | |
32 | + WHERE ig.tenant_code = #{tenantCode} | |
33 | + ) | |
34 | + SELECT id, parent_id, name, sort,creator,create_time,updater,update_time,remark,tenant_code | |
35 | + FROM organization WHERE tenant_code = #{tenantCode} | |
36 | + </select> | |
37 | +</mapper> | ... | ... |
dao/src/main/resources/mapper/RoleMapper.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.RoleMapper"> | |
5 | + <resultMap id="roleDtoMap" type="org.thingsboard.server.common.data.yunteng.dto.RoleDTO"> | |
6 | + <result property="id" column="id"/> | |
7 | + <result property="name" column="name"/> | |
8 | + <result property="roleType" column="role_type"/> | |
9 | + <result property="tenantCode" column="tenant_code"/> | |
10 | + <result property="enabled" column="enabled"/> | |
11 | + <result property="creator" column="creator"/> | |
12 | + <result property="createTime" column="create_time"/> | |
13 | + <result property="updater" column="updater"/> | |
14 | + <result property="updateTime" column="update_time"/> | |
15 | + <result property="code" column="code"/> | |
16 | + </resultMap> | |
17 | + <select id="checkRoleUserMappingByRoleIds" resultType="java.lang.String"> | |
18 | + SELECT user_id FROM sys_user_role WHERE role_id IN | |
19 | + <foreach collection="ids" item="id" open="(" separator="," close=")"> | |
20 | + #{id} | |
21 | + </foreach> | |
22 | + GROUP BY user_id | |
23 | + </select> | |
24 | + <delete id="deleteRoleBatchByTenantIds"> | |
25 | + DELETE FROM sys_role WHERE tenant_code in ( | |
26 | + SELECT tenant_code FROM sys_tenant WHERE id IN | |
27 | + <foreach collection="tenantIds" item="tenantId" open="(" separator="," close=")"> | |
28 | + #{tenantId} | |
29 | + </foreach> | |
30 | + ) | |
31 | + </delete> | |
32 | + | |
33 | + <delete id="deleteRoleMenuMappingByRoleIds"> | |
34 | + DELETE FROM sys_role_menu WHERE role_id IN | |
35 | + <foreach collection="roleIds" item="roleId" open="(" separator="," close=")"> | |
36 | + #{roleId} | |
37 | + </foreach> | |
38 | + </delete> | |
39 | + | |
40 | + <delete id="deleteRoleUserMappingByRoleIds"> | |
41 | + DELETE FROM sys_user_role WHERE role_id IN | |
42 | + <foreach collection="roleIds" item="roleId" open="(" separator="," close=")"> | |
43 | + #{roleId} | |
44 | + </foreach> | |
45 | + </delete> | |
46 | + | |
47 | + <delete id="deleteRoleUserMappingByUserIds"> | |
48 | + DELETE FROM sys_user_role WHERE user_id IN | |
49 | + <foreach collection="userIds" item="userId" open="(" separator="," close=")"> | |
50 | + #{userId} | |
51 | + </foreach> | |
52 | + </delete> | |
53 | + | |
54 | + <delete id="deleteRoleMenuMappingByMenuIds"> | |
55 | + DELETE FROM sys_role_menu WHERE menu_id IN | |
56 | + <foreach collection="menuIds" item="menuId" open="(" separator="," close=")"> | |
57 | + #{menuId} | |
58 | + </foreach> | |
59 | + </delete> | |
60 | + | |
61 | + <select id="getAllIdsByTenantCode" resultType="java.lang.String"> | |
62 | + SELECT id from sys_role WHERE tenant_code IN | |
63 | + <foreach collection="tenantCodes" item="tenantCode" open="(" separator="," close=")"> | |
64 | + #{tenantCode} | |
65 | + </foreach> | |
66 | + </select> | |
67 | + | |
68 | + <select id="selectRoleByUserId" resultType="org.thingsboard.server.dao.yunteng.entities.Role"> | |
69 | + SELECT * | |
70 | + FROM sys_role | |
71 | + WHERE id IN (SELECT role_id FROM sys_user_role WHERE user_id = #{userId}) | |
72 | + </select> | |
73 | + | |
74 | + <select id="getMenuIdsByRoleId" resultType="java.lang.String"> | |
75 | + SELECT menu_id | |
76 | + FROM sys_role_menu | |
77 | + WHERE role_id = #{roleId} | |
78 | + </select> | |
79 | + | |
80 | + <delete id="saveUserRoleMapping"> | |
81 | + INSERT INTO sys_user_role(user_id, role_id) | |
82 | + VALUES (#{userId}, #{roleId}) | |
83 | + </delete> | |
84 | + | |
85 | + <select id="findRoleInfo" resultMap="roleDtoMap"> | |
86 | + SELECT id,name,role_type,tenant_code,creator,create_time,updater,update_time,remark,code FROM sys_role | |
87 | + <where> | |
88 | + enabled='t' | |
89 | + <if test="roleType !=null and roleType !=''">AND role_type=#{roleType}</if> | |
90 | + <if test="tenantCode !=null and tenantCode !=''">AND tenant_code=#{tenantCode}</if> | |
91 | + <if test="code !=null and code !=''">AND code=#{code}</if> | |
92 | + <if test="roleIds !=null">OR id IN | |
93 | + <foreach collection="roleIds" item="id" open="(" separator="," close=")"> | |
94 | + #{id} | |
95 | + </foreach> | |
96 | + </if> | |
97 | + </where> | |
98 | + | |
99 | + </select> | |
100 | +</mapper> | ... | ... |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.SysDictItemMapper"> | |
5 | + <resultMap id="sysDictItemDTOMap" type="org.thingsboard.server.common.data.yunteng.dto.SysDictItemDTO"> | |
6 | + <result property="id" column="id"/> | |
7 | + <result property="dictId" column="dict_id"/> | |
8 | + <result property="itemText" column="item_text"/> | |
9 | + <result property="itemValue" column="item_value"/> | |
10 | + <result property="description" column="description"/> | |
11 | + <result property="sort" column="sort"/> | |
12 | + <result property="status" column="status"/> | |
13 | + <result property="creator" column="creator"/> | |
14 | + <result property="createTime" column="create_time"/> | |
15 | + <result property="updater" column="updater"/> | |
16 | + <result property="updateTime" column="update_time"/> | |
17 | + <association property="sysDict" javaType="org.thingsboard.server.common.data.yunteng.dto.SysDictDTO"> | |
18 | + <result property="dictName" column="dict_name"/> | |
19 | + <result property="dictCode" column="dict_code"/> | |
20 | + </association> | |
21 | + </resultMap> | |
22 | + <sql id="columns"> | |
23 | + sdi.id,sdi.dict_id,sdi.item_text,sdi.item_value,sdi.description,sdi.sort, | |
24 | + sdi.status,sdi.create_time,sdi.update_time,sd. dict_name,sd.dict_code | |
25 | + </sql> | |
26 | + <select id="getDictValueByCodeAndText" resultMap="sysDictItemDTOMap"> | |
27 | + SELECT | |
28 | + sd. dict_name,sd.dict_code,sdi.id,sdi.item_text,sdi.sort | |
29 | + FROM | |
30 | + sys_dict_item sdi | |
31 | + LEFT JOIN sys_dict sd ON sd.ID = sdi.dict_id | |
32 | + <where> | |
33 | + sdi.status = 1 | |
34 | + <if test="tenantCode !=null and tenantCode!=''">AND sd.tenant_code=#{tenantCode}</if> | |
35 | + <if test="dictCode !=null and dictCode!=''">AND sd.dict_code = #{dictCode}</if> | |
36 | + <if test="itemValue !=null and itemValue!=''">AND sdi.item_value = #{itemValue}</if> | |
37 | + </where> | |
38 | + </select> | |
39 | + | |
40 | + <select id="getDictItemInfo" resultMap="sysDictItemDTOMap"> | |
41 | + SELECT | |
42 | + <include refid="columns"/> | |
43 | + FROM | |
44 | + sys_dict_item sdi | |
45 | + LEFT JOIN sys_dict sd ON sd.ID = sdi.dict_id | |
46 | + <where> | |
47 | + <if test="dictId !=null and dictId!=''">AND sdi.dict_id=#{dictId}</if> | |
48 | + <if test="dictCode !=null and dictCode!=''">AND sd.dict_code=#{dictCode}</if> | |
49 | + </where> | |
50 | + </select> | |
51 | +</mapper> | ... | ... |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.SysDictMapper"> | |
5 | + <resultMap id="smsDictDTOMap" type="org.thingsboard.server.common.data.yunteng.dto.SysDictDTO" > | |
6 | + <result property="id" column="id"/> | |
7 | + <result property="dictName" column="dict_name"/> | |
8 | + <result property="dictCode" column="dict_code"/> | |
9 | + <result property="description" column="description"/> | |
10 | + <result property="tenantCode" column="tenant_code"/> | |
11 | + <result property="creator" column="creator"/> | |
12 | + <result property="createTime" column="create_time"/> | |
13 | + <result property="updater" column="updater"/> | |
14 | + <result property="updateTime" column="update_time"/> | |
15 | + </resultMap> | |
16 | + <sql id="columns"> | |
17 | + id,dict_name,dict_code,description,tenant_code,creator,create_time,updater,update_time | |
18 | + </sql> | |
19 | + <select id="getDictInfoByCode" resultMap="smsDictDTOMap"> | |
20 | + SELECT | |
21 | + <include refid="columns"/> | |
22 | + FROM sys_dict | |
23 | + <where> | |
24 | + <if test="tenantCode != null and tenantCode !=''">tenant_code=#{tenantCode}</if> | |
25 | + <if test="dictCode != null and dictCode !=''">AND dict_code=#{dictCode}</if> | |
26 | + </where> | |
27 | + </select> | |
28 | +</mapper> | ... | ... |
dao/src/main/resources/mapper/UserMapper.xml
0 → 100644
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.UserMapper"> | |
5 | + <resultMap type="org.thingsboard.server.common.data.yunteng.dto.UserDetailsDTO" id="userDetailsMap"> | |
6 | + <result property="id" column="id"/> | |
7 | + <result property="username" column="username"/> | |
8 | + <result property="password" column="password"/> | |
9 | + <result property="enabled" column="enabled"/> | |
10 | + <result property="accountExpireTime" column="account_expire_time"/> | |
11 | + <association property="tenant" javaType="org.thingsboard.server.common.data.yunteng.dto.TenantDTO"> | |
12 | + <result column="tenant_name" property="name"/> | |
13 | + <result column="tenant_code" property="tenantCode"/> | |
14 | + <result column="tenant_enabled" property="enabled"/> | |
15 | + <result column="tenant_expire_time" property="tenantExpireTime"/> | |
16 | + </association> | |
17 | + <collection property="roles" javaType="java.util.Set" ofType="org.thingsboard.server.common.data.yunteng.dto.UserDetailRoleDTO"> | |
18 | + <result column="role_type" property="roleType" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/> | |
19 | + </collection> | |
20 | + </resultMap> | |
21 | + <resultMap type="org.thingsboard.server.common.data.yunteng.dto.UserDTO" id="userDTOMap"> | |
22 | + <result property="id" column="id"/> | |
23 | + <result property="username" column="username"/> | |
24 | + <result property="password" column="password"/> | |
25 | + <result property="realName" column="real_name"/> | |
26 | + <result property="enabled" column="enabled"/> | |
27 | + <result property="phoneNumber" column="phone_number"/> | |
28 | + <result property="email" column="email"/> | |
29 | + <result property="avatar" column="avatar"/> | |
30 | + <result property="deptId" column="dept_id"/> | |
31 | + <result property="tenantName" column="tenant_name"/> | |
32 | + <result property="tenantCode" column="tenant_code"/> | |
33 | + <result property="createTime" column="create_time"/> | |
34 | + <result property="updateTime" column="update_time"/> | |
35 | + <result property="accountExpireTime" column="account_expire_time"/> | |
36 | + <result property="level" column="level"/> | |
37 | + </resultMap> | |
38 | + | |
39 | + <sql id="columns"> | |
40 | + su.id AS id, | |
41 | + su.username AS username, | |
42 | + su.password AS password, | |
43 | + su.phone_number AS phone_number, | |
44 | + su.email AS email, | |
45 | + su.avatar AS avatar, | |
46 | + su.enabled AS enabled, | |
47 | + su.account_expire_time AS account_expire_time, | |
48 | + su.tenant_code AS tenant_code, | |
49 | + su.create_time AS create_time, | |
50 | + su.update_time AS update_time, | |
51 | + su.real_name AS real_name, | |
52 | + su.dept_id AS dept_id, | |
53 | + su.level AS level | |
54 | + </sql> | |
55 | + | |
56 | + <select id="findUserDetailsByUserName" resultMap="userDetailsMap"> | |
57 | + SELECT su.id as id, | |
58 | + su.username as username, | |
59 | + su.password as password, | |
60 | + su.enabled as enabled, | |
61 | + su.account_expire_time as account_expire_time, | |
62 | + st.name as tenant_name, | |
63 | + st.tenant_code as tenant_code, | |
64 | + st.enabled as tenant_enabled, | |
65 | + st.tenant_expire_time as tenant_expire_time, | |
66 | + rr.role_type as role_type | |
67 | + FROM sys_user su | |
68 | + LEFT JOIN sys_tenant st ON su.tenant_code = st.tenant_code | |
69 | + LEFT JOIN ( | |
70 | + SELECT sur.user_id, | |
71 | + sr.role_type | |
72 | + FROM sys_user_role sur | |
73 | + LEFT JOIN sys_role sr ON sur.role_id = sr.id | |
74 | + WHERE sur.user_id = (SELECT id FROM sys_user WHERE username = #{username}) | |
75 | + ) rr ON su.id = rr.user_id | |
76 | + WHERE su.username = #{username}; | |
77 | + </select> | |
78 | + | |
79 | + <select id="getUserPage" resultMap="userDTOMap"> | |
80 | + SELECT | |
81 | + <include refid="columns"/>, | |
82 | + st.name AS tenant_name | |
83 | + FROM sys_user su | |
84 | + LEFT JOIN sys_tenant st ON su.tenant_code = st.tenant_code | |
85 | + <where> | |
86 | + <if test="queryMap.realName!=null and queryMap.realName!=''"> | |
87 | + AND su.real_name LIKE CONCAT('%',#{queryMap.realName}::TEXT,'%') | |
88 | + </if> | |
89 | + <if test="queryMap.username!=null and queryMap.username!=''"> | |
90 | + AND su.username LIKE CONCAT('%',#{queryMap.username}::TEXT,'%') | |
91 | + </if> | |
92 | + <if test="queryMap.tenantCode !=null and queryMap.tenantCode!=''"> | |
93 | + AND su.tenant_code=#{queryMap.tenantCode} | |
94 | + </if> | |
95 | + </where> | |
96 | + </select> | |
97 | + | |
98 | + <select id="getAdminUserPage" resultMap="userDTOMap"> | |
99 | + SELECT | |
100 | + <include refid="columns"/>, | |
101 | + st.name AS tenant_name | |
102 | + FROM sys_user su | |
103 | + LEFT JOIN sys_tenant st ON su.tenant_code = st.tenant_code | |
104 | + WHERE su.ID IN (SELECT user_id | |
105 | + FROM sys_user_role | |
106 | + WHERE role_id IN (SELECT ID | |
107 | + FROM sys_role | |
108 | + WHERE role_type = #{roleType} | |
109 | + <if test="roleType == 'ROLE_PLATFORM_ADMIN'"> | |
110 | + OR role_type = 'ROLE_SYS_ADMIN' | |
111 | + </if> | |
112 | + AND tenant_code = #{tenantCode})) | |
113 | + </select> | |
114 | + <select id="selectAllTenantUser" resultMap="userDTOMap"> | |
115 | + SELECT | |
116 | + <include refid="columns"/>, | |
117 | + st.name AS tenant_name | |
118 | + FROM sys_user su | |
119 | + LEFT JOIN sys_tenant st ON su.tenant_code = st.tenant_code | |
120 | + WHERE su.level = 2; | |
121 | + </select> | |
122 | + <select id="getAllIdsByTenantCode" resultType="java.lang.String"> | |
123 | + SELECT id FROM sys_user WHERE tenant_code IN | |
124 | + <foreach collection="tenantCodes" item="tenantCode" open="(" separator="," close=")"> | |
125 | + #{tenantCode} | |
126 | + </foreach> | |
127 | + </select> | |
128 | + | |
129 | + <update id="setPassword2NullAndInsertActiveToken"> | |
130 | + UPDATE sys_user | |
131 | + SET password=null, | |
132 | + activate_token=#{activeToken} | |
133 | + WHERE id = #{userId} | |
134 | + </update> | |
135 | + | |
136 | + <select id="findUserDetailsByPhoneNumber" resultMap="userDetailsMap"> | |
137 | + SELECT su.id as id, | |
138 | + su.username as username, | |
139 | + su.password as password, | |
140 | + su.enabled as enabled, | |
141 | + su.account_expire_time as account_expire_time, | |
142 | + st.name as tenant_name, | |
143 | + st.tenant_code as tenant_code, | |
144 | + st.enabled as tenant_enabled, | |
145 | + st.tenant_expire_time as tenant_expire_time, | |
146 | + rr.role_type as role_type | |
147 | + FROM sys_user su | |
148 | + LEFT JOIN sys_tenant st ON su.tenant_code = st.tenant_code | |
149 | + LEFT JOIN ( | |
150 | + SELECT sur.user_id, | |
151 | + sr.role_type | |
152 | + FROM sys_user_role sur | |
153 | + LEFT JOIN sys_role sr ON sur.role_id = sr.id | |
154 | + WHERE sur.user_id = (SELECT id FROM sys_user WHERE phone_number = #{phoneNumber}) | |
155 | + ) rr ON su.id = rr.user_id | |
156 | + WHERE su.phone_number = #{phoneNumber}; | |
157 | + </select> | |
158 | + <select id="findUserInfo" resultMap="userDTOMap"> | |
159 | + SELECT | |
160 | + <include refid="columns"/> | |
161 | + FROM sys_user su | |
162 | + <where> | |
163 | + <if test="username !=null and username!=''">AND su.username=#{username}</if> | |
164 | + <if test="tenantCode !=null and tenantCode!=''">AND su.tenant_code=#{tenantCode}</if> | |
165 | + </where> | |
166 | + </select> | |
167 | +</mapper> | ... | ... |
1 | +<?xml version="1.0" encoding="UTF-8"?> | |
2 | +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> | |
3 | + | |
4 | +<mapper namespace="org.thingsboard.server.dao.yunteng.mapper.UserRoleMapper"> | |
5 | + <resultMap type="org.thingsboard.server.common.data.yunteng.dto.UserRoleDTO" id="userRoleMap"> | |
6 | + <result property="userId" column="user_id"/> | |
7 | + <result property="roleId" column="role_id"/> | |
8 | + </resultMap> | |
9 | +</mapper> | ... | ... |
... | ... | @@ -55,7 +55,7 @@ |
55 | 55 | <cassandra-driver-core.version>3.11.0</cassandra-driver-core.version> |
56 | 56 | <guava.version>30.0-jre</guava.version> |
57 | 57 | <caffeine.version>2.6.1</caffeine.version> |
58 | - <commons-lang3.version>3.4</commons-lang3.version> | |
58 | + <commons-lang3.version>3.12.0</commons-lang3.version> | |
59 | 59 | <commons-codec.version>1.15</commons-codec.version> |
60 | 60 | <commons-io.version>2.11.0</commons-io.version> |
61 | 61 | <commons-logging.version>1.2</commons-logging.version> |
... | ... | @@ -130,6 +130,13 @@ |
130 | 130 | <!-- BLACKBOX TEST SCOPE --> |
131 | 131 | <testcontainers.version>1.16.0</testcontainers.version> |
132 | 132 | <zeroturnaround.version>1.12</zeroturnaround.version> |
133 | + <!-- 新增的开始 --> | |
134 | + <mybatis-plus.version>3.4.1</mybatis-plus.version> | |
135 | + <aliyun.sdk.core>4.5.20</aliyun.sdk.core> | |
136 | + <aliyun.sdk.dysmsapi>2.1.0</aliyun.sdk.dysmsapi> | |
137 | + <jakarta.mail.version>2.0.1</jakarta.mail.version> | |
138 | + <io.minio.version>8.3.1</io.minio.version> | |
139 | + <com.alibaba.easyexcel.version>3.0.1</com.alibaba.easyexcel.version> | |
133 | 140 | </properties> |
134 | 141 | |
135 | 142 | <modules> | ... | ... |