Fix sysadmin delete

This commit is contained in:
2026-01-22 22:19:39 +01:00
parent 14339bc018
commit 54bb2e6c49
3 changed files with 27 additions and 6 deletions

View File

@@ -57,7 +57,11 @@ public class SystemAdministratorApiController {
throw new ResponseStatusException(BAD_REQUEST, "Username is required"); throw new ResponseStatusException(BAD_REQUEST, "Username is required");
} }
String username = request.twitchUsername().trim(); String username = request.twitchUsername().trim();
try {
systemAdministratorService.addSysadmin(username); systemAdministratorService.addSysadmin(username);
} catch (IllegalStateException e) {
throw new ResponseStatusException(BAD_REQUEST, e.getMessage(), e);
}
LOG.info("System administrator added: {} (requested by {})", username, sessionUsername); LOG.info("System administrator added: {} (requested by {})", username, sessionUsername);
return ResponseEntity.ok().body(systemAdministratorService.listSysadmins()); return ResponseEntity.ok().body(systemAdministratorService.listSysadmins());
} }

View File

@@ -71,7 +71,7 @@ public class SystemAdministratorService {
String initialSysadmin = getInitialSysadmin(); String initialSysadmin = getInitialSysadmin();
if (initialSysadmin != null && initialSysadmin.equals(normalized)) { if (initialSysadmin != null && initialSysadmin.equals(normalized)) {
return; throw new IllegalStateException("Cannot add the initial system administrator");
} }
if (repo.existsByTwitchUsername(normalized)) { if (repo.existsByTwitchUsername(normalized)) {
@@ -81,6 +81,7 @@ public class SystemAdministratorService {
repo.save(new SystemAdministrator(normalized)); repo.save(new SystemAdministrator(normalized));
} }
@Transactional
public void removeSysadmin(String twitchUsername) { public void removeSysadmin(String twitchUsername) {
String normalized = normalize(twitchUsername); String normalized = normalize(twitchUsername);
String initialSysadmin = getInitialSysadmin(); String initialSysadmin = getInitialSysadmin();
@@ -118,11 +119,21 @@ public class SystemAdministratorService {
} }
public List<String> listSysadmins() { public List<String> listSysadmins() {
return repo String initialSysadmin = getInitialSysadmin();
List<String> persistedAdmins = repo
.findAllByOrderByTwitchUsernameAsc() .findAllByOrderByTwitchUsernameAsc()
.stream() .stream()
.map(SystemAdministrator::getTwitchUsername) .map(SystemAdministrator::getTwitchUsername)
.collect(Collectors.toList()); .collect(Collectors.toList());
if (initialSysadmin == null) {
return persistedAdmins;
}
return java.util.stream.Stream
.concat(persistedAdmins.stream(), java.util.stream.Stream.of(initialSysadmin))
.map(this::normalize)
.distinct()
.sorted()
.collect(Collectors.toList());
} }
private String normalize(String username) { private String normalize(String username) {

View File

@@ -187,14 +187,16 @@ function renderSystemAdministrators(admins) {
const button = document.createElement("button"); const button = document.createElement("button");
button.classList.add("button", "secondary"); button.classList.add("button", "secondary");
button.type = "button"; button.type = "button";
button.textContent = "Remove";
button.addEventListener("click", () => removeSystemAdministrator(admin));
button.setAttribute("data-sysadmin-remove", "true"); button.setAttribute("data-sysadmin-remove", "true");
button.setAttribute("data-sysadmin-username", admin); button.setAttribute("data-sysadmin-username", admin);
if (isInitialSysadmin) { if (isInitialSysadmin) {
button.disabled = true; button.disabled = true;
button.title = "The initial system administrator cannot be removed."; button.textContent = "System default";
button.title = "The system default administrator cannot be removed.";
} else {
button.textContent = "Remove";
button.addEventListener("click", () => removeSystemAdministrator(admin));
} }
listItem.appendChild(text); listItem.appendChild(text);
@@ -226,6 +228,10 @@ function addSystemAdministrator() {
showToast("Enter a Twitch username", "warning"); showToast("Enter a Twitch username", "warning");
return; return;
} }
if (initialSysadmin && username.toLowerCase() === initialSysadmin) {
showToast("That user is already the system default administrator.", "warning");
return;
}
fetch("/api/system-administrators", { fetch("/api/system-administrators", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },