From f14dc9d7838984c13e2f1fc6536e439842d66aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kr=C3=BChlmann?= Date: Fri, 9 Jan 2026 20:22:14 +0100 Subject: [PATCH] Revert "Update settings" This reverts commit fa54836578c7eac9b52db56b737054a9c1e3eec6. --- .../controller/SettingsApiController.java | 20 +++- .../SystemAdministratorApiController.java | 84 -------------- .../imgfloat/controller/ViewController.java | 1 - .../SystemAdministratorRepository.java | 2 - .../service/SystemAdministratorService.java | 10 -- src/main/resources/static/js/settings.js | 108 +----------------- src/main/resources/templates/dashboard.html | 1 - src/main/resources/templates/settings.html | 21 ---- 8 files changed, 19 insertions(+), 228 deletions(-) delete mode 100644 src/main/java/dev/kruhlmann/imgfloat/controller/SystemAdministratorApiController.java diff --git a/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java b/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java index fbd1717..87fe03d 100644 --- a/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java +++ b/src/main/java/dev/kruhlmann/imgfloat/controller/SettingsApiController.java @@ -1,19 +1,36 @@ package dev.kruhlmann.imgfloat.controller; +import static org.springframework.http.HttpStatus.BAD_REQUEST; +import static org.springframework.http.HttpStatus.FORBIDDEN; +import static org.springframework.http.HttpStatus.NOT_FOUND; + import dev.kruhlmann.imgfloat.model.OauthSessionUser; import dev.kruhlmann.imgfloat.model.Settings; import dev.kruhlmann.imgfloat.service.AuthorizationService; import dev.kruhlmann.imgfloat.service.SettingsService; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import jakarta.validation.Valid; +import java.io.IOException; +import java.util.Collection; +import java.util.Comparator; +import java.util.List; +import java.util.Optional; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.ResponseEntity; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; @RestController @RequestMapping("/api/settings") @@ -43,7 +60,6 @@ public class SettingsApiController { settingsService.logSettings("From: ", currentSettings); settingsService.logSettings("To: ", newSettings); - Settings savedSettings = settingsService.save(newSettings); - return ResponseEntity.ok().body(savedSettings); + return ResponseEntity.ok().body(newSettings); } } diff --git a/src/main/java/dev/kruhlmann/imgfloat/controller/SystemAdministratorApiController.java b/src/main/java/dev/kruhlmann/imgfloat/controller/SystemAdministratorApiController.java deleted file mode 100644 index 368efcd..0000000 --- a/src/main/java/dev/kruhlmann/imgfloat/controller/SystemAdministratorApiController.java +++ /dev/null @@ -1,84 +0,0 @@ -package dev.kruhlmann.imgfloat.controller; - -import static org.springframework.http.HttpStatus.BAD_REQUEST; -import static org.springframework.http.HttpStatus.NOT_FOUND; - -import dev.kruhlmann.imgfloat.model.OauthSessionUser; -import dev.kruhlmann.imgfloat.service.AuthorizationService; -import dev.kruhlmann.imgfloat.service.SystemAdministratorService; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import java.util.List; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.http.ResponseEntity; -import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.server.ResponseStatusException; - -@RestController -@RequestMapping("/api/system-administrators") -@SecurityRequirement(name = "administrator") -public class SystemAdministratorApiController { - - private static final Logger LOG = LoggerFactory.getLogger(SystemAdministratorApiController.class); - - private final SystemAdministratorService systemAdministratorService; - private final AuthorizationService authorizationService; - - public SystemAdministratorApiController( - SystemAdministratorService systemAdministratorService, - AuthorizationService authorizationService - ) { - this.systemAdministratorService = systemAdministratorService; - this.authorizationService = authorizationService; - } - - @GetMapping - public ResponseEntity> listSystemAdministrators(OAuth2AuthenticationToken oauthToken) { - String sessionUsername = OauthSessionUser.from(oauthToken).login(); - authorizationService.userIsSystemAdministratorOrThrowHttpError(sessionUsername); - return ResponseEntity.ok().body(systemAdministratorService.listSysadmins()); - } - - @PostMapping - public ResponseEntity> addSystemAdministrator( - @RequestBody SystemAdministratorRequest request, - OAuth2AuthenticationToken oauthToken - ) { - String sessionUsername = OauthSessionUser.from(oauthToken).login(); - authorizationService.userIsSystemAdministratorOrThrowHttpError(sessionUsername); - if (request == null || request.twitchUsername() == null || request.twitchUsername().isBlank()) { - throw new ResponseStatusException(BAD_REQUEST, "Username is required"); - } - String username = request.twitchUsername().trim(); - systemAdministratorService.addSysadmin(username); - LOG.info("System administrator added: {} (requested by {})", username, sessionUsername); - return ResponseEntity.ok().body(systemAdministratorService.listSysadmins()); - } - - @DeleteMapping("/{twitchUsername}") - public ResponseEntity> removeSystemAdministrator( - @PathVariable("twitchUsername") String twitchUsername, - OAuth2AuthenticationToken oauthToken - ) { - String sessionUsername = OauthSessionUser.from(oauthToken).login(); - authorizationService.userIsSystemAdministratorOrThrowHttpError(sessionUsername); - try { - systemAdministratorService.removeSysadmin(twitchUsername); - } catch (IllegalStateException e) { - throw new ResponseStatusException(BAD_REQUEST, e.getMessage(), e); - } catch (IllegalArgumentException e) { - throw new ResponseStatusException(NOT_FOUND, e.getMessage(), e); - } - LOG.info("System administrator removed: {} (requested by {})", twitchUsername, sessionUsername); - return ResponseEntity.ok().body(systemAdministratorService.listSysadmins()); - } - - private record SystemAdministratorRequest(String twitchUsername) {} -} diff --git a/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java b/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java index cfc3eac..396b63b 100644 --- a/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java +++ b/src/main/java/dev/kruhlmann/imgfloat/controller/ViewController.java @@ -62,7 +62,6 @@ public class ViewController { model.addAttribute("username", sessionUsername); model.addAttribute("channel", sessionUsername); model.addAttribute("adminChannels", channelDirectoryService.adminChannelsFor(sessionUsername)); - model.addAttribute("isSystemAdmin", authorizationService.userIsSystemAdministrator(sessionUsername)); addVersionAttributes(model); return "dashboard"; } diff --git a/src/main/java/dev/kruhlmann/imgfloat/repository/SystemAdministratorRepository.java b/src/main/java/dev/kruhlmann/imgfloat/repository/SystemAdministratorRepository.java index 1a0da0e..ca51d65 100644 --- a/src/main/java/dev/kruhlmann/imgfloat/repository/SystemAdministratorRepository.java +++ b/src/main/java/dev/kruhlmann/imgfloat/repository/SystemAdministratorRepository.java @@ -1,11 +1,9 @@ package dev.kruhlmann.imgfloat.repository; import dev.kruhlmann.imgfloat.model.SystemAdministrator; -import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; public interface SystemAdministratorRepository extends JpaRepository { boolean existsByTwitchUsername(String twitchUsername); long deleteByTwitchUsername(String twitchUsername); - List findAllByOrderByTwitchUsernameAsc(); } diff --git a/src/main/java/dev/kruhlmann/imgfloat/service/SystemAdministratorService.java b/src/main/java/dev/kruhlmann/imgfloat/service/SystemAdministratorService.java index c8f0ff9..74a934b 100644 --- a/src/main/java/dev/kruhlmann/imgfloat/service/SystemAdministratorService.java +++ b/src/main/java/dev/kruhlmann/imgfloat/service/SystemAdministratorService.java @@ -3,9 +3,7 @@ package dev.kruhlmann.imgfloat.service; import dev.kruhlmann.imgfloat.model.SystemAdministrator; import dev.kruhlmann.imgfloat.repository.SystemAdministratorRepository; import jakarta.annotation.PostConstruct; -import java.util.List; import java.util.Locale; -import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; @@ -82,14 +80,6 @@ public class SystemAdministratorService { return repo.existsByTwitchUsername(normalize(twitchUsername)); } - public List listSysadmins() { - return repo - .findAllByOrderByTwitchUsernameAsc() - .stream() - .map(SystemAdministrator::getTwitchUsername) - .collect(Collectors.toList()); - } - private String normalize(String username) { return username.trim().toLowerCase(Locale.ROOT); } diff --git a/src/main/resources/static/js/settings.js b/src/main/resources/static/js/settings.js index 5a3424e..361bd67 100644 --- a/src/main/resources/static/js/settings.js +++ b/src/main/resources/static/js/settings.js @@ -14,11 +14,8 @@ const statCanvasSizeElement = document.getElementById("stat-canvas-size"); const statPlaybackRangeElement = document.getElementById("stat-playback-range"); const statAudioRangeElement = document.getElementById("stat-audio-range"); const statVolumeRangeElement = document.getElementById("stat-volume-range"); -const sysadminListElement = document.getElementById("sysadmin-list"); -const sysadminInputElement = document.getElementById("new-sysadmin"); -const addSysadminButtonElement = document.getElementById("add-sysadmin-button"); -let currentSettings = JSON.parse(serverRenderedSettings); +const currentSettings = JSON.parse(serverRenderedSettings); let userSettings = { ...currentSettings }; function jsonEquals(a, b) { @@ -136,100 +133,6 @@ function submitSettingsForm() { }); } -function renderSystemAdministrators(admins) { - sysadminListElement.innerHTML = ""; - if (!admins || admins.length === 0) { - const empty = document.createElement("li"); - empty.classList.add("stacked-list-item"); - empty.innerHTML = '

No system administrators found.

'; - sysadminListElement.appendChild(empty); - return; - } - - admins.forEach((admin) => { - const listItem = document.createElement("li"); - listItem.classList.add("stacked-list-item"); - - const text = document.createElement("div"); - text.innerHTML = `

${admin}

System admin access

`; - - const button = document.createElement("button"); - button.classList.add("button", "secondary"); - button.type = "button"; - button.textContent = "Remove"; - button.addEventListener("click", () => removeSystemAdministrator(admin)); - - listItem.appendChild(text); - listItem.appendChild(button); - sysadminListElement.appendChild(listItem); - }); -} - -function loadSystemAdministrators() { - return fetch("/api/system-administrators") - .then((r) => { - if (!r.ok) { - throw new Error("Failed to load system admins"); - } - return r.json(); - }) - .then((admins) => { - renderSystemAdministrators(admins); - }) - .catch((error) => { - console.error(error); - showToast("Unable to load system admins", "error"); - }); -} - -function addSystemAdministrator() { - const username = sysadminInputElement.value.trim(); - if (!username) { - showToast("Enter a Twitch username", "warning"); - return; - } - fetch("/api/system-administrators", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ twitchUsername: username }), - }) - .then((r) => { - if (!r.ok) { - throw new Error("Failed to add system admin"); - } - return r.json(); - }) - .then((admins) => { - sysadminInputElement.value = ""; - renderSystemAdministrators(admins); - showToast("System admin added", "success"); - }) - .catch((error) => { - console.error(error); - showToast("Unable to add system admin", "error"); - }); -} - -function removeSystemAdministrator(username) { - fetch(`/api/system-administrators/${encodeURIComponent(username)}`, { method: "DELETE" }) - .then((r) => { - if (!r.ok) { - return r.text().then((text) => { - throw new Error(text || "Failed to remove system admin"); - }); - } - return r.json(); - }) - .then((admins) => { - renderSystemAdministrators(admins); - showToast("System admin removed", "success"); - }) - .catch((error) => { - console.error(error); - showToast("Unable to remove system admin", "error"); - }); -} - formElement.querySelectorAll("input").forEach((input) => { input.addEventListener("input", () => { loadUserSettingsFromDom(); @@ -237,14 +140,6 @@ formElement.querySelectorAll("input").forEach((input) => { }); }); -addSysadminButtonElement.addEventListener("click", () => addSystemAdministrator()); -sysadminInputElement.addEventListener("keydown", (event) => { - if (event.key === "Enter") { - event.preventDefault(); - addSystemAdministrator(); - } -}); - formElement.addEventListener("submit", (event) => { event.preventDefault(); submitSettingsForm(); @@ -253,4 +148,3 @@ formElement.addEventListener("submit", (event) => { setFormSettings(currentSettings); updateStatCards(currentSettings); updateSubmitButtonDisabledState(); -loadSystemAdministrators(); diff --git a/src/main/resources/templates/dashboard.html b/src/main/resources/templates/dashboard.html index 751cfa9..436e7a6 100644 --- a/src/main/resources/templates/dashboard.html +++ b/src/main/resources/templates/dashboard.html @@ -31,7 +31,6 @@
Open broadcast overlay Open admin console - Application settings Browse channels
diff --git a/src/main/resources/templates/settings.html b/src/main/resources/templates/settings.html index 7707837..77c03bc 100644 --- a/src/main/resources/templates/settings.html +++ b/src/main/resources/templates/settings.html @@ -236,27 +236,6 @@
- -
-
-

Access

-

System administrators

-

- Invite teammates who can manage global defaults and other system-wide actions. -

-
-
- - -
-
-
-

Current system admins

-

These users can access the settings page and APIs.

-
-
    -
    -