Browse Source

Merge pull request #14235 from dashevchenko/tenantUserDeletion

Added validation that prohibits last tenant admin deletion
pull/14241/head
Viacheslav Klimov 7 months ago
committed by GitHub
parent
commit
dd1dee6cfb
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 3
      application/src/main/java/org/thingsboard/server/controller/UserController.java
  2. 20
      application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java
  3. 1
      common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java
  4. 5
      dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java
  5. 2
      dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java
  6. 1
      dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java
  7. 5
      dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java

3
application/src/main/java/org/thingsboard/server/controller/UserController.java

@ -266,6 +266,9 @@ public class UserController extends BaseController {
if (user.getAuthority() == Authority.SYS_ADMIN && getCurrentUser().getId().equals(userId)) {
throw new ThingsboardException("Sysadmin is not allowed to delete himself", ThingsboardErrorCode.PERMISSION_DENIED);
}
if (user.getAuthority() == Authority.TENANT_ADMIN && userService.countTenantAdmins(user.getTenantId()) == 1) {
throw new ThingsboardException("At least one tenant administrator must remain!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
}
tbUserService.delete(getTenantId(), getCurrentUser().getCustomerId(), user, getCurrentUser());
}

20
application/src/test/java/org/thingsboard/server/controller/UserControllerTest.java

@ -284,6 +284,26 @@ public class UserControllerTest extends AbstractControllerTest {
ActionType.ADDED, new DataValidationException(msgError));
}
@Test
public void testShouldNotDeleteLastTenantAdmin() throws Exception {
loginSysAdmin();
User tenantAdmin2 = new User();
tenantAdmin2.setAuthority(Authority.TENANT_ADMIN);
tenantAdmin2.setTenantId(tenantId);
tenantAdmin2.setEmail("tenant2@thingsboard.io");
tenantAdmin2 = doPost("/api/user", tenantAdmin2, User.class);
// delete second tenant admin - ok
doDelete("/api/user/" + tenantAdmin2.getId().getId().toString())
.andExpect(status().isOk());
// delete last tenant admin - forbidden
doDelete("/api/user/" + tenantAdminUser.getId().getId().toString())
.andExpect(status().isBadRequest())
.andExpect(statusReason(containsString("At least one tenant administrator must remain!")));
}
@Test
public void testSaveUserWithInvalidEmail() throws Exception {
loginSysAdmin();

1
common/dao-api/src/main/java/org/thingsboard/server/dao/user/UserService.java

@ -109,4 +109,5 @@ public interface UserService extends EntityDaoService {
void removeMobileSession(TenantId tenantId, String mobileToken);
int countTenantAdmins(TenantId tenantId);
}

5
dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java

@ -136,6 +136,11 @@ public class JpaUserDao extends JpaAbstractDao<UserEntity, User> implements User
DaoUtil.toPageable(pageLink)));
}
@Override
public int countTenantAdmins(UUID tenantId) {
return userRepository.countByTenantIdAndAuthority(tenantId, Authority.TENANT_ADMIN);
}
@Override
public Long countByTenantId(TenantId tenantId) {
return userRepository.countByTenantId(tenantId.getId());

2
dao/src/main/java/org/thingsboard/server/dao/sql/user/UserRepository.java

@ -78,4 +78,6 @@ public interface UserRepository extends JpaRepository<UserEntity, UUID> {
"u.customerId, u.version, u.firstName, u.lastName, u.email, u.phone, u.additionalInfo) " +
"FROM UserEntity u WHERE u.id > :id ORDER BY u.id")
List<UserFields> findNextBatch(@Param("id") UUID id, Limit limit);
int countByTenantIdAndAuthority(UUID tenantId, Authority authority);
}

1
dao/src/main/java/org/thingsboard/server/dao/user/UserDao.java

@ -101,4 +101,5 @@ public interface UserDao extends Dao<User>, TenantEntityDao<User> {
PageData<User> findByAuthorityAndTenantProfilesIds(Authority authority, List<TenantProfileId> tenantProfilesIds, PageLink pageLink);
int countTenantAdmins(UUID tenantId);
}

5
dao/src/main/java/org/thingsboard/server/dao/user/UserServiceImpl.java

@ -485,6 +485,11 @@ public class UserServiceImpl extends AbstractCachedEntityService<UserCacheKey, U
}
}
@Override
public int countTenantAdmins(TenantId tenantId) {
return userDao.countTenantAdmins(tenantId.getId());
}
private Optional<UserMobileSessionInfo> findMobileSessionInfo(TenantId tenantId, UserId userId) {
return Optional.ofNullable(userSettingsService.findUserSettings(tenantId, userId, UserSettingsType.MOBILE))
.map(UserSettings::getSettings).map(settings -> JacksonUtil.treeToValue(settings, UserMobileSessionInfo.class));

Loading…
Cancel
Save