Skip to content

Commit 0b92be6

Browse files
authored
Merge pull request #861 from utmstack/bugfix/v10.5.10/system-requires-at-least-one-admin-user
Bugfix/v10.5.10/system requires at least one admin user
2 parents 8ee4f59 + 56ed6cf commit 0b92be6

File tree

3 files changed

+39
-18
lines changed

3 files changed

+39
-18
lines changed

backend/src/main/java/com/park/utmstack/repository/UserRepository.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,8 @@ public interface UserRepository extends JpaRepository<User, Long> {
3737

3838
@Query(nativeQuery = true, value = "SELECT jhi_user.* FROM jhi_user WHERE jhi_user.id IN (SELECT jhi_user_authority.user_id FROM jhi_user_authority WHERE jhi_user_authority.authority_name = 'ROLE_ADMIN')")
3939
List<User> findAllAdmins();
40-
@Query(nativeQuery = true, value = "SELECT jhi_user.* \n" +
41-
"FROM jhi_user \n" +
42-
"WHERE jhi_user.id IN (\n" +
43-
" SELECT jhi_user_authority.user_id \n" +
44-
" FROM jhi_user_authority \n" +
45-
" WHERE jhi_user_authority.authority_name = 'ROLE_ADMIN' AND jhi_user.activated = true\n" +
46-
") \n" +
47-
"LIMIT 1")
40+
41+
@Query("SELECT u FROM User u JOIN FETCH u.authorities a WHERE a.name = 'ROLE_ADMIN' AND u.activated = true")
4842
Optional<User> findAnyAdminUser();
4943

5044
@EntityGraph(attributePaths = "authorities")

backend/src/main/java/com/park/utmstack/web/rest/UserResource.java

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import javax.validation.Valid;
3131
import java.net.URI;
3232
import java.util.List;
33+
import java.util.NoSuchElementException;
3334
import java.util.Optional;
3435
import java.util.stream.Collectors;
3536

@@ -137,28 +138,49 @@ public ResponseEntity<UserDTO> updateUser(@Valid @RequestBody UserDTO userDTO) {
137138
try {
138139
Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail());
139140
if (existingUser.isPresent() && (!existingUser.get()
140-
.getId()
141-
.equals(userDTO.getId()))) {
141+
.getId()
142+
.equals(userDTO.getId()))) {
142143
throw new EmailAlreadyUsedException();
143144
}
144145
existingUser = userRepository.findOneByLogin(userDTO.getLogin()
145-
.toLowerCase());
146+
.toLowerCase());
146147
if (existingUser.isPresent() && (!existingUser.get()
147-
.getId()
148-
.equals(userDTO.getId()))) {
148+
.getId()
149+
.equals(userDTO.getId()))) {
149150
throw new LoginAlreadyUsedException();
150151
}
152+
153+
User user = userRepository.findOneWithAuthoritiesById(userDTO.getId())
154+
.orElseThrow(() -> new NoSuchElementException(String.format("User %1$s not found", userDTO.getId().toString())));
155+
if (!userDTO.getAuthorities().contains("ROLE_ADMIN") &&
156+
user.getAuthorities().stream().anyMatch(authority -> authority.getName().equals("ROLE_ADMIN")) && userRepository.countAdmins() == 1) {
157+
throw new BadRequestAlertException(ctx, "Cannot update roles for the last remaining admin user.", UserService.class.toString());
158+
}
159+
151160
Optional<UserDTO> updatedUser = userService.updateUser(userDTO);
152161

153162
return ResponseUtil.wrapOrNotFound(updatedUser,
154-
HeaderUtil.createAlert("A user is updated with identifier " + userDTO.getLogin(),
155-
userDTO.getLogin()));
163+
HeaderUtil.createAlert("A user is updated with identifier " + userDTO.getLogin(),
164+
userDTO.getLogin()));
165+
166+
} catch (NoSuchElementException e) {
167+
String msg = ctx + ": " + e.getMessage();
168+
log.error(msg);
169+
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
170+
return ResponseEntity.status(HttpStatus.NOT_FOUND).headers(
171+
HeaderUtil.createFailureAlert("", "", msg)).body(null);
172+
} catch (BadRequestAlertException e) {
173+
String msg = ctx + ": " + e.getMessage();
174+
log.error(msg);
175+
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
176+
return ResponseEntity.status(HttpStatus.BAD_REQUEST).headers(
177+
HeaderUtil.createFailureAlert("", "", msg)).body(null);
156178
} catch (Exception e) {
157179
String msg = ctx + ": " + e.getMessage();
158180
log.error(msg);
159181
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
160182
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(
161-
HeaderUtil.createFailureAlert("", "", msg)).body(null);
183+
HeaderUtil.createFailureAlert("", "", msg)).body(null);
162184
}
163185
}
164186

@@ -239,7 +261,7 @@ public ResponseEntity<Void> deleteUser(@PathVariable String login) {
239261
return ResponseEntity.ok()
240262
.headers(HeaderUtil.createAlert("A user is deleted with identifier " + login, login))
241263
.build();
242-
} catch (NoSuchMethodException e) {
264+
} catch (NoSuchElementException e) {
243265
String msg = ctx + ": " + e.getMessage();
244266
log.error(msg);
245267
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);

frontend/src/app/admin/user/user-update/user-management-update.component.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ export class UserMgmtUpdateComponent implements OnInit {
7575

7676
private onSaveError(error, type) {
7777
this.isSaving = false;
78-
this.utmToast.showError('Problem', 'The login or email is already in use, please check');
78+
79+
if (error.status === 400) {
80+
this.utmToast.showError('Error', 'Admin role removal is prohibited for the last remaining administrator user.');
81+
} else {
82+
this.utmToast.showError('Problem', 'The login or email is already in use, please check');
83+
}
7984
}
8085
}

0 commit comments

Comments
 (0)