Commit 4275e0cddd0c1ef8d6b837ddd7d4fe2e7e390948

Authored by 黄 x
1 parent eea90075

feat: 平台删除租户管理员完成

... ... @@ -358,7 +358,7 @@ public abstract class BaseController {
358 358 }
359 359 }
360 360
361   - UUID toUUID(String id) {
  361 + protected UUID toUUID(String id) {
362 362 return UUID.fromString(id);
363 363 }
364 364
... ...
1 1 package org.thingsboard.server.controller.yunteng;
2 2
3 3 import lombok.RequiredArgsConstructor;
  4 +import org.apache.commons.lang3.StringUtils;
4 5 import org.springframework.http.ResponseEntity;
5 6 import org.springframework.security.access.prepost.PreAuthorize;
6 7 import org.springframework.util.Assert;
7 8 import org.springframework.validation.annotation.Validated;
8 9 import org.springframework.web.bind.annotation.*;
9 10 import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
  11 +import org.thingsboard.server.common.data.EntityType;
10 12 import org.thingsboard.server.common.data.Tenant;
  13 +import org.thingsboard.server.common.data.User;
  14 +import org.thingsboard.server.common.data.audit.ActionType;
11 15 import org.thingsboard.server.common.data.exception.ThingsboardException;
  16 +import org.thingsboard.server.common.data.id.EdgeId;
  17 +import org.thingsboard.server.common.data.id.UserId;
12 18 import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
  19 +import org.thingsboard.server.common.data.yunteng.common.DeleteGroup;
13 20 import org.thingsboard.server.common.data.yunteng.common.UpdateGroup;
14 21 import org.thingsboard.server.common.data.yunteng.core.exception.YtDataValidationException;
  22 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
  23 +import org.thingsboard.server.common.data.yunteng.dto.DeleteDTO;
15 24 import org.thingsboard.server.common.data.yunteng.dto.MenuDTO;
16 25 import org.thingsboard.server.common.data.yunteng.dto.TenantDTO;
17 26 import org.thingsboard.server.common.data.yunteng.dto.UserDTO;
... ... @@ -20,10 +29,12 @@ import org.thingsboard.server.common.data.yunteng.enums.OrderTypeEnum;
20 29 import org.thingsboard.server.common.data.yunteng.utils.tools.PageData;
21 30 import org.thingsboard.server.controller.BaseController;
22 31 import org.thingsboard.server.dao.tenant.TenantService;
  32 +import org.thingsboard.server.dao.user.UserService;
23 33 import org.thingsboard.server.dao.yunteng.service.MenuService;
24 34 import org.thingsboard.server.dao.yunteng.service.YtTenantService;
25 35 import org.thingsboard.server.dao.yunteng.service.YtUserService;
26 36 import org.thingsboard.server.service.install.InstallScripts;
  37 +import org.thingsboard.server.service.security.permission.Operation;
27 38
28 39 import java.io.IOException;
29 40 import java.net.URI;
... ... @@ -42,6 +53,7 @@ public class YtAdminController extends BaseController {
42 53 private final YtUserService userService;
43 54 private final TenantService tenantService;
44 55 private final InstallScripts installScripts;
  56 + private final UserService tbUserService;
45 57
46 58 @PostMapping("/tenant")
47 59 public ResponseEntity<TenantDTO> saveTenant(@RequestBody TenantReqDTO tenantReqDTO) {
... ... @@ -88,21 +100,26 @@ public class YtAdminController extends BaseController {
88 100 }
89 101
90 102 @DeleteMapping("/tenant")
91   - public void deleteTenant(@RequestBody String[] ids) {
92   - Assert.notNull(ids, "ids cannot be null");
93   - if (ids.length == 0) {
94   - throw new YtDataValidationException("id cannot be empty");
95   - }
96   - ytTenantService.deleteTenants(ids);
  103 + public void deleteTenant(@Validated(DeleteGroup.class) @RequestBody DeleteDTO deleteDTO) {
  104 + // TODO 删除TB
  105 + ytTenantService.deleteTenants(
  106 + deleteDTO.getIds().toArray(new String[deleteDTO.getIds().size()]));
97 107 }
98 108
99 109 @DeleteMapping("/user/deleteTenantAdmin")
100   - public void deleteTenantAdmin(@RequestBody String[] ids) throws ThingsboardException {
101   - Assert.notNull(ids, "ids cannot be null");
102   - userService.deleteUser(
103   - new HashSet<>(Arrays.asList(ids)),
104   - getCurrentUser().isPtSysadmin(),
105   - getCurrentUser().getCurrentTenantId());
  110 + public ResponseEntity<Boolean> deleteTenantAdmin(@Validated(DeleteGroup.class) @RequestBody DeleteDTO deleteDTO)
  111 + throws ThingsboardException {
  112 + for (String strUserId : deleteDTO.getIds()) {
  113 + UserDTO userDTO = userService.findUserInfoById(strUserId);
  114 + if(null != userDTO && StringUtils.isNotBlank(userDTO.getTbUser())){
  115 + deleteTenantAdmin(userDTO.getTbUser());
  116 + }else {
  117 + return ResponseEntity.ok(false);
  118 + }
  119 + }
  120 + boolean result = userService.deleteUser(
  121 + deleteDTO.getIds(), getCurrentUser().isPtSysadmin(), getCurrentUser().getCurrentTenantId());
  122 + return ResponseEntity.ok(result);
106 123 }
107 124
108 125 @GetMapping("/tenant/getById/{id}")
... ... @@ -143,32 +160,60 @@ public class YtAdminController extends BaseController {
143 160 menuService.getMyMenus(
144 161 getCurrentUser().getCurrentTenantId(),
145 162 getCurrentUser().getCurrentUserId(),
146   - getCurrentUser().isPtSysadmin(), getCurrentUser().isPtTenantAdmin()));
  163 + getCurrentUser().isPtSysadmin(),
  164 + getCurrentUser().isPtTenantAdmin()));
147 165 }
148 166
149 167 @PutMapping("/menu/assign/{tenantId}")
150 168 public void assignMenuToTenant(
151   - @RequestBody String[] menuIds, @PathVariable("tenantId") String tenantId) throws ThingsboardException {
  169 + @RequestBody String[] menuIds, @PathVariable("tenantId") String tenantId)
  170 + throws ThingsboardException {
152 171 menuService.assignMenuToTenant(getCurrentUser().getCurrentTenantId(), menuIds);
153 172 }
154 173
155 174 @PostMapping("tenant/updateOrCreateTenant")
156 175 public TenantDTO updateOrCreateTenant(
157   - @Validated(UpdateGroup.class) @RequestBody TenantReqDTO tenantReqDTO) throws IOException {
158   - boolean newTenant = tenantReqDTO.getId() == null;
159   - //增加TB的租户创建
160   - Tenant tbTenant = new Tenant();
161   - tbTenant.setTitle(tenantReqDTO.getName());
162   - tbTenant = tenantService.saveTenant(tbTenant);
163   - if(newTenant){
164   - installScripts.createDefaultRuleChains(tbTenant.getId());
165   - installScripts.createDefaultEdgeRuleChains(tbTenant.getId());
166   - }
167   - tenantProfileCache.evict(tbTenant.getId());
168   - tbClusterService.onTenantChange(tbTenant, null);
169   - tbClusterService.broadcastEntityStateChangeEvent(tbTenant.getId(), tbTenant.getId(),
170   - newTenant ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
171   - tenantReqDTO.setTenantId(tbTenant.getTenantId().toString());
  176 + @Validated(UpdateGroup.class) @RequestBody TenantReqDTO tenantReqDTO)
  177 + throws ThingsboardException {
  178 + updateOrSaveTenant(tenantReqDTO);
172 179 return ytTenantService.updateOrCreateTenant(tenantReqDTO);
173 180 }
  181 +
  182 + private void deleteTenantAdmin(String strUserId) throws ThingsboardException {
  183 + try {
  184 + UserId currentUserId = new UserId(toUUID(strUserId));
  185 + User user = checkUserId(currentUserId, Operation.DELETE);
  186 + List<EdgeId> relatedEdgeIds = findRelatedEdgeIds(getTenantId(), currentUserId);
  187 + tbUserService.deleteUser(getTenantId(), currentUserId);
  188 + logEntityAction(
  189 + currentUserId, user, user.getCustomerId(), ActionType.DELETED, null, strUserId);
  190 + sendDeleteNotificationMsg(getTenantId(), currentUserId, relatedEdgeIds);
  191 + } catch (Exception e) {
  192 + logEntityAction(emptyId(EntityType.USER), null, null, ActionType.DELETED, e, strUserId);
  193 + throw handleException(e);
  194 + }
  195 + }
  196 +
  197 + private void updateOrSaveTenant(TenantReqDTO tenantReqDTO) throws ThingsboardException {
  198 + try {
  199 + boolean isCreate = tenantReqDTO.getId() == null;
  200 + // 增加TB的租户创建
  201 + Tenant tbTenant = new Tenant();
  202 + tbTenant.setTitle(tenantReqDTO.getName());
  203 + tbTenant = tenantService.saveTenant(tbTenant);
  204 + if (isCreate) {
  205 + installScripts.createDefaultRuleChains(tbTenant.getId());
  206 + installScripts.createDefaultEdgeRuleChains(tbTenant.getId());
  207 + }
  208 + tenantProfileCache.evict(tbTenant.getId());
  209 + tbClusterService.onTenantChange(tbTenant, null);
  210 + tbClusterService.broadcastEntityStateChangeEvent(
  211 + tbTenant.getId(),
  212 + tbTenant.getId(),
  213 + isCreate ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
  214 + tenantReqDTO.setTenantId(tbTenant.getTenantId().toString());
  215 + } catch (Exception e) {
  216 + throw handleException(e);
  217 + }
  218 + }
174 219 }
... ...
... ... @@ -40,7 +40,6 @@ import org.thingsboard.server.controller.BaseController;
40 40 import org.thingsboard.server.dao.user.UserService;
41 41 import org.thingsboard.server.dao.yunteng.service.YtUserService;
42 42 import org.thingsboard.server.service.security.model.SecurityUser;
43   -import org.thingsboard.server.service.security.model.UserPrincipal;
44 43 import org.thingsboard.server.service.security.permission.Operation;
45 44
46 45 import javax.servlet.http.HttpServletRequest;
... ... @@ -152,6 +151,7 @@ public class YtUserController extends BaseController {
152 151 if(StringUtils.isAllBlank(userDTO.getTenantId())){
153 152 throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
154 153 }
  154 + userService.validateUserNameAndPhoneNumberAndEmail(userDTO);
155 155 TenantId tenantId = new TenantId(UUID.fromString(userDTO.getTenantId()));
156 156 try{
157 157 //创建TB的租户管理员
... ...
... ... @@ -29,6 +29,7 @@ public enum ErrorMessage {
29 29 TENANT_MISMATCHING(400010,"租户不匹配"),
30 30 GET_CURRENT_USER_EXCEPTION(400011,"获取当前用户信息异常"),
31 31 SEND_DESTINATION_NOT_FOUND(400012,"通知失败!找不到发送目标"),
  32 + USER_NAME_ALREADY_EXISTS(400013,"用户名已存在"),
32 33 CONNECT_TO_TB_ERROR(500001,"与TB联系错误"),
33 34 HAVE_NO_PERMISSION(500002,"没有修改权限");
34 35 private final int code;
... ...
1 1 package org.thingsboard.server.dao.yunteng.impl;
2 2
  3 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
3 4 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
4 5 import com.baomidou.mybatisplus.core.metadata.IPage;
5 6 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
... ... @@ -46,7 +47,8 @@ import static org.thingsboard.server.common.data.yunteng.constant.ModelConstants
46 47 @Service
47 48 @Slf4j
48 49 @RequiredArgsConstructor
49   -public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> implements YtUserService {
  50 +public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User>
  51 + implements YtUserService {
50 52
51 53 private final AdminSettingMapper adminSettingMapper;
52 54 private final ObjectMapper mapper;
... ... @@ -72,12 +74,9 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
72 74
73 75 @Override
74 76 @Transactional
75   - public UserDTO saveAccount(UserDTO userDTO, boolean sendEmail, boolean sendMsg,boolean isPtSysadmin,String tenantId) {
  77 + public UserDTO saveAccount(
  78 + UserDTO userDTO, boolean sendEmail, boolean sendMsg, boolean isPtSysadmin, String tenantId) {
76 79 boolean isAdminOperate = isPtSysadmin;
77   - if (StringUtils.isAllBlank(userDTO.getUsername())) {
78   - throw new YtDataValidationException("username is required");
79   - }
80   - validatePhoneNumberAndEmail(userDTO);
81 80 if (sendMsg && StringUtils.isAllBlank(userDTO.getPhoneNumber())) {
82 81 throw new YtDataValidationException(
83 82 "you must specify user phone number if you want send activate email to this user");
... ... @@ -99,9 +98,7 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
99 98 user.setPassword(passwordEncoder.encode(FastIotConstants.DEFAULT_PWD));
100 99 int tenantExist =
101 100 tenantMapper.selectCount(
102   - new QueryWrapper<Tenant>()
103   - .lambda()
104   - .eq(Tenant::getTenantId, userDTO.getTenantId()));
  101 + new QueryWrapper<Tenant>().lambda().eq(Tenant::getTenantId, userDTO.getTenantId()));
105 102 if (tenantExist == 0) {
106 103 throw new YtDataValidationException("tenant must exist");
107 104 }
... ... @@ -140,13 +137,22 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
140 137 userRoleMapper.insert(userRole);
141 138 }
142 139 // 绑定用户和组织的关系
143   - groupService.bindUserToOrganization(tenantId,user.getId(), userDTO.getOrganizationIds());
  140 + groupService.bindUserToOrganization(tenantId, user.getId(), userDTO.getOrganizationIds());
144 141 user.copyToDTO(userDTO, PASSWORD, ACTIVATE_TOKEN);
145 142 return userDTO;
146 143 }
147 144 }
148 145
149   - private void validatePhoneNumberAndEmail(UserDTO userDTO) {
  146 + @Override
  147 + public void validateUserNameAndPhoneNumberAndEmail(UserDTO userDTO) {
  148 + if(null == userDTO.getId()){
  149 + User existUser =
  150 + baseMapper.selectOne(
  151 + new LambdaQueryWrapper<User>().eq(User::getUsername, userDTO.getUsername()));
  152 + if (null != existUser) {
  153 + throw new YtDataValidationException(ErrorMessage.USER_NAME_ALREADY_EXISTS.getMessage());
  154 + }
  155 + }
150 156 if (StringUtils.isNotBlank(userDTO.getPhoneNumber())) {
151 157 if (!CHINA_MOBILE_PATTERN.matcher(userDTO.getPhoneNumber()).matches()) {
152 158 throw new YtDataValidationException(ErrorMessage.PROVIDE_CORRECT_PHONE_NUMBER.getMessage());
... ... @@ -164,10 +170,17 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
164 170 }
165 171
166 172 @Override
167   - public String getActivationLink(String userId,boolean isPtSysadmin,String tenantId) {
  173 + public UserDTO findUserInfoById(String id) {
  174 + if(StringUtils.isEmpty(id)){
  175 + throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  176 + }
  177 + return baseMapper.selectById(id).getDTO(UserDTO.class);
  178 + }
  179 +
  180 + @Override
  181 + public String getActivationLink(String userId, boolean isPtSysadmin, String tenantId) {
168 182 User user = baseMapper.selectById(userId);
169   - if (!isPtSysadmin
170   - && tenantId.equals(user.getTenantId())) {
  183 + if (!isPtSysadmin && tenantId.equals(user.getTenantId())) {
171 184 throw new AccessDeniedException(
172 185 "you don't have permission to get activation link for this user");
173 186 }
... ... @@ -190,7 +203,7 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
190 203 }
191 204
192 205 @Override
193   - public UserInfoDTO me(String userId,String tenantId,Set<String> currentRoles) {
  206 + public UserInfoDTO me(String userId, String tenantId, Set<String> currentRoles) {
194 207 User user = baseMapper.selectById(userId);
195 208 UserInfoDTO userInfoDTO = new UserInfoDTO();
196 209 if (!StringUtils.isEmpty(user.getActivateToken())) {
... ... @@ -215,13 +228,12 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
215 228 }
216 229
217 230 @Override
218   - public Optional<UserDTO> getUser(String userId,boolean isPtSysadmin,String tenantId) {
  231 + public Optional<UserDTO> getUser(String userId, boolean isPtSysadmin, String tenantId) {
219 232 User user = baseMapper.selectById(userId);
220 233 if (user != null) {
221 234 UserDTO userDTO = new UserDTO();
222 235 user.copyToDTO(userDTO, PASSWORD, ACTIVATE_TOKEN);
223   - if (!isPtSysadmin
224   - && !tenantId.equals(user.getTenantId())) {
  236 + if (!isPtSysadmin && !tenantId.equals(user.getTenantId())) {
225 237 return Optional.empty();
226 238 }
227 239 return Optional.of(userDTO);
... ... @@ -232,17 +244,16 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
232 244
233 245 @Override
234 246 @Transactional
235   - public UserDTO updateUser(UserDTO userDTO,boolean isPtSysadmin,String tenantId) {
  247 + public UserDTO updateUser(UserDTO userDTO, boolean isPtSysadmin, String tenantId) {
236 248 Assert.notNull(userDTO.getId(), "user is must be specified");
237 249 User user = baseMapper.selectById(userDTO.getId());
238   - if (!isPtSysadmin
239   - && !user.getTenantId().equals(tenantId)) {
  250 + if (!isPtSysadmin && !user.getTenantId().equals(tenantId)) {
240 251 throw new NoneTenantAssetException("this user not belong to current tenant");
241 252 }
242 253 if (!user.getUsername().equals(userDTO.getUsername())) {
243 254 throw new YtDataValidationException("username is immutable");
244 255 }
245   - validatePhoneNumberAndEmail(userDTO);
  256 + validateUserNameAndPhoneNumberAndEmail(userDTO);
246 257 user.setRealName(userDTO.getRealName());
247 258 user.setEnabled(userDTO.isEnabled());
248 259 user.setPhoneNumber(userDTO.getPhoneNumber());
... ... @@ -270,14 +281,11 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
270 281 if (StringUtils.isEmpty(roleType)) {
271 282 roleType = RoleEnum.PLATFORM_ADMIN.name();
272 283 }
273   - userPage =
274   - baseMapper.getAdminUserPage(
275   - userIPage, tenantId, roleType);
276   - }
277   - else if(isPlatformAdmin){
278   - //平台管理员只能管理租户
  284 + userPage = baseMapper.getAdminUserPage(userIPage, tenantId, roleType);
  285 + } else if (isPlatformAdmin) {
  286 + // 平台管理员只能管理租户
279 287 userPage = baseMapper.selectAllTenantUser(userIPage);
280   - }else if(isTenantAdmin){
  288 + } else if (isTenantAdmin) {
281 289 Map<String, Object> map = new HashMap<>();
282 290 map.put("realName", queryMap.get("realName"));
283 291 map.put("username", queryMap.get("username"));
... ... @@ -315,7 +323,7 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
315 323
316 324 @Override
317 325 @Transactional
318   - public boolean deleteUser(Set<String> userIds,boolean isPtSysadmin,String tenantId) {
  326 + public boolean deleteUser(Set<String> userIds, boolean isPtSysadmin, String tenantId) {
319 327 // 1. 判断是否所有的id都属于此人
320 328 if (!isPtSysadmin) {
321 329 int notTenantUserCount =
... ... @@ -343,11 +351,10 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
343 351
344 352 @Override
345 353 @Transactional
346   - public UserDTO saveTenantAdmin(UserDTO userDTO,boolean isPtSysadmin,String tenantId) {
  354 + public UserDTO saveTenantAdmin(UserDTO userDTO, boolean isPtSysadmin, String tenantId) {
347 355 if (StringUtils.isNotBlank(userDTO.getId())) {
348   - return updateUser(userDTO,isPtSysadmin,tenantId);
  356 + return updateUser(userDTO, isPtSysadmin, tenantId);
349 357 }
350   - validatePhoneNumberAndEmail(userDTO);
351 358 User user = new User();
352 359 userDTO.copyToEntity(user, ID, PASSWORD, CREATE_TIME, UPDATE_TIME, ACTIVATE_TOKEN);
353 360 user.setPassword(passwordEncoder.encode(FastIotConstants.DEFAULT_PWD));
... ... @@ -376,7 +383,7 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
376 383
377 384 @Override
378 385 @Transactional
379   - public void resetPassword(String userId,boolean isPtSysadmin,String tenantId) {
  386 + public void resetPassword(String userId, boolean isPtSysadmin, String tenantId) {
380 387 if (isPtSysadmin) {
381 388 baseMapper.setPassword2NullAndInsertActiveToken(
382 389 userId, RandomStringUtils.randomAlphabetic(10));
... ... @@ -428,10 +435,10 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
428 435 }
429 436
430 437 @Override
431   - public Optional<List<UserDTO>> getOrganizationUserByOrganizationId(String groupId,String tenantId) {
  438 + public Optional<List<UserDTO>> getOrganizationUserByOrganizationId(
  439 + String groupId, String tenantId) {
432 440 Organization group = organizationMapper.selectById(groupId);
433   - if (group == null
434   - || !group.getTenantId().equals(tenantId)) {
  441 + if (group == null || !group.getTenantId().equals(tenantId)) {
435 442 return Optional.empty();
436 443 }
437 444 Set<String> userIds =
... ... @@ -500,7 +507,7 @@ public class YtUserServiceImpl extends AbstractBaseService<UserMapper, User> imp
500 507 }
501 508
502 509 @Override
503   - public UserDTO accountExist(String userName,String tenantId) {
  510 + public UserDTO accountExist(String userName, String tenantId) {
504 511 if (StringUtils.isEmpty(userName)) {
505 512 throw new YtDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
506 513 }
... ...
... ... @@ -36,6 +36,9 @@ public interface YtUserService {
36 36
37 37 List<UserDetailsDTO> getUserByPhoneNumber(String phoneNumber);
38 38
  39 + void validateUserNameAndPhoneNumberAndEmail(UserDTO userDTO);
  40 +
  41 + UserDTO findUserInfoById(String id);
39 42 /**
40 43 * 发送密码重置新消息
41 44 *
... ...
... ... @@ -161,9 +161,7 @@
161 161 SELECT
162 162 <include refid="columns"/>
163 163 FROM sys_user su
164   - <where>
165   - <if test="username !=null and username!=''">AND su.username=#{username}</if>
166   - <if test="tenantId !=null and tenantId!=''">AND su.tenant_id=#{tenantId}</if>
167   - </where>
  164 + WHERE su.username=#{username}
  165 + AND su.tenant_id=#{tenantId}
168 166 </select>
169 167 </mapper>
... ...