Skip to content

Commit 4c127e5

Browse files
authored
Merge pull request #857 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 d8b7904 + b0d0c87 commit 4c127e5

File tree

6 files changed

+41
-18
lines changed

6 files changed

+41
-18
lines changed

CHANGELOG.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# UTMStack 10.5.10 Release Notes
1+
# UTMStack 10.5.11 Release Notes
22
## Bugfix
3-
- Improved timezone handling for Data Source -> Last Input and Log Explorer views
4-
- Implemented a check to assign 'UNKNOWN' as the default key for buckets with empty keys to ensure data consistency.
3+
- Implemented validation checks during the user deletion process to prevent the deletion of the last admin user. This ensures that at least one admin user remains in the system, maintaining the integrity of the authentication process.

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ public interface UserRepository extends JpaRepository<User, Long> {
3232
@Query("select u from User u where upper(u.login) like concat('%', UPPER(:login) , '%') and (u.fsManager is null or u.fsManager is false)")
3333
Page<User> findAllByLoginLike(Pageable pageable, @Param("login") String login);
3434

35+
@Query(nativeQuery = true, value = "SELECT count(jhi_user.id) 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')")
36+
int countAdmins();
37+
3538
@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')")
3639
List<User> findAllAdmins();
3740

backend/src/main/java/com/park/utmstack/service/UserService.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import com.park.utmstack.service.dto.UserDTO;
1313
import com.park.utmstack.service.util.RandomUtil;
1414
import com.park.utmstack.util.exceptions.CurrentUserLoginNotFoundException;
15+
import com.park.utmstack.web.rest.errors.BadRequestAlertException;
1516
import com.park.utmstack.web.rest.errors.InvalidPasswordException;
1617
import org.slf4j.Logger;
1718
import org.slf4j.LoggerFactory;
@@ -27,10 +28,7 @@
2728

2829
import java.time.Instant;
2930
import java.time.temporal.ChronoUnit;
30-
import java.util.List;
31-
import java.util.Objects;
32-
import java.util.Optional;
33-
import java.util.Set;
31+
import java.util.*;
3432
import java.util.stream.Collectors;
3533
import java.util.stream.Stream;
3634

@@ -227,14 +225,17 @@ public User updateUserTfaSecret(String userLogin, String tfaSecret) throws Excep
227225
}
228226
}
229227

230-
public void deleteUser(String login) {
228+
public void deleteUser(String login) throws Exception {
231229
String ctx = CLASS_NAME + ".deleteUser";
232-
Optional<User> user = userRepository.findOneByLogin(login);
233-
if (user.isPresent()) {
234-
User usr = user.get();
235-
userRepository.delete(usr);
236-
log.debug("Deleted User: {}", usr);
230+
User user = userRepository.findOneByLogin(login)
231+
.orElseThrow(() -> new NoSuchElementException(String.format("User %1$s not found", login)));
232+
233+
if (user.getAuthorities().stream().anyMatch(authority -> authority.getName().equals("ROLE_ADMIN")) && userRepository.countAdmins() == 1) {
234+
throw new BadRequestAlertException(ctx, "Cannot delete the last admin user.", UserService.class.toString());
237235
}
236+
237+
userRepository.delete(user);
238+
log.debug("Deleted User: {}", user);
238239
}
239240

240241
public void changePassword(String currentClearTextPassword, String newPassword) {

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,14 +237,26 @@ public ResponseEntity<Void> deleteUser(@PathVariable String login) {
237237
try {
238238
userService.deleteUser(login);
239239
return ResponseEntity.ok()
240-
.headers(HeaderUtil.createAlert("A user is deleted with identifier " + login, login))
241-
.build();
240+
.headers(HeaderUtil.createAlert("A user is deleted with identifier " + login, login))
241+
.build();
242+
} catch (NoSuchMethodException e) {
243+
String msg = ctx + ": " + e.getMessage();
244+
log.error(msg);
245+
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
246+
return ResponseEntity.status(HttpStatus.NOT_FOUND).headers(
247+
HeaderUtil.createFailureAlert("", "", msg)).body(null);
248+
} catch (BadRequestAlertException e) {
249+
String msg = ctx + ": " + e.getMessage();
250+
log.error(msg);
251+
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
252+
return ResponseEntity.status(HttpStatus.BAD_REQUEST).headers(
253+
HeaderUtil.createFailureAlert("", "", msg)).body(null);
242254
} catch (Exception e) {
243255
String msg = ctx + ": " + e.getMessage();
244256
log.error(msg);
245257
applicationEventService.createEvent(msg, ApplicationEventType.ERROR);
246258
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(
247-
HeaderUtil.createFailureAlert("", "", msg)).body(null);
259+
HeaderUtil.createFailureAlert("", "", msg)).body(null);
248260
}
249261
}
250262

frontend/src/app/admin/user/user-delete/user-management-delete-dialog.component.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {JhiEventManager} from 'ng-jhipster';
44
import {User} from '../../../core/user/user.model';
55
import {UserService} from '../../../core/user/user.service';
66
import {UtmToastService} from '../../../shared/alert/utm-toast.service';
7+
import {HttpErrorResponse, HttpResponse} from "@angular/common/http";
78

89
@Component({
910
selector: 'app-ser-mgmt-delete-dialog',
@@ -30,6 +31,13 @@ export class UserMgmtDeleteDialogComponent {
3031
});
3132
this.utmToast.showSuccess('User deleted successfully');
3233
this.activeModal.dismiss(true);
33-
});
34+
},
35+
(error: HttpErrorResponse) => {
36+
if (error.status === 400) {
37+
this.utmToast.showError('Error', 'Cannot delete the last admin user.');
38+
}
39+
this.utmToast.showError('Error', 'An error occurred while attempting to delete the user.');
40+
this.activeModal.dismiss(true);
41+
});
3442
}
3543
}

version.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version: 10.5.10
1+
version: 10.5.11

0 commit comments

Comments
 (0)