mirror of
https://github.com/imgfloat/server.git
synced 2026-02-05 03:39:26 +00:00
Temo commit
This commit is contained in:
@@ -11,6 +11,7 @@ import dev.kruhlmann.imgfloat.service.ChannelDirectoryService;
|
|||||||
import dev.kruhlmann.imgfloat.service.GitInfoService;
|
import dev.kruhlmann.imgfloat.service.GitInfoService;
|
||||||
import dev.kruhlmann.imgfloat.service.GithubReleaseService;
|
import dev.kruhlmann.imgfloat.service.GithubReleaseService;
|
||||||
import dev.kruhlmann.imgfloat.service.SettingsService;
|
import dev.kruhlmann.imgfloat.service.SettingsService;
|
||||||
|
import dev.kruhlmann.imgfloat.service.SystemAdministratorService;
|
||||||
import dev.kruhlmann.imgfloat.service.VersionService;
|
import dev.kruhlmann.imgfloat.service.VersionService;
|
||||||
import dev.kruhlmann.imgfloat.util.LogSanitizer;
|
import dev.kruhlmann.imgfloat.util.LogSanitizer;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -31,6 +32,7 @@ public class ViewController {
|
|||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final AuthorizationService authorizationService;
|
private final AuthorizationService authorizationService;
|
||||||
private final GithubReleaseService githubReleaseService;
|
private final GithubReleaseService githubReleaseService;
|
||||||
|
private final SystemAdministratorService systemAdministratorService;
|
||||||
private final long uploadLimitBytes;
|
private final long uploadLimitBytes;
|
||||||
|
|
||||||
public ViewController(
|
public ViewController(
|
||||||
@@ -41,6 +43,7 @@ public class ViewController {
|
|||||||
ObjectMapper objectMapper,
|
ObjectMapper objectMapper,
|
||||||
AuthorizationService authorizationService,
|
AuthorizationService authorizationService,
|
||||||
GithubReleaseService githubReleaseService,
|
GithubReleaseService githubReleaseService,
|
||||||
|
SystemAdministratorService systemAdministratorService,
|
||||||
long uploadLimitBytes
|
long uploadLimitBytes
|
||||||
) {
|
) {
|
||||||
this.channelDirectoryService = channelDirectoryService;
|
this.channelDirectoryService = channelDirectoryService;
|
||||||
@@ -50,6 +53,7 @@ public class ViewController {
|
|||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
this.authorizationService = authorizationService;
|
this.authorizationService = authorizationService;
|
||||||
this.githubReleaseService = githubReleaseService;
|
this.githubReleaseService = githubReleaseService;
|
||||||
|
this.systemAdministratorService = systemAdministratorService;
|
||||||
this.uploadLimitBytes = uploadLimitBytes;
|
this.uploadLimitBytes = uploadLimitBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +115,7 @@ public class ViewController {
|
|||||||
LOG.error("Failed to serialize settings for settings view", e);
|
LOG.error("Failed to serialize settings for settings view", e);
|
||||||
throw new ResponseStatusException(INTERNAL_SERVER_ERROR, "Failed to serialize settings");
|
throw new ResponseStatusException(INTERNAL_SERVER_ERROR, "Failed to serialize settings");
|
||||||
}
|
}
|
||||||
|
model.addAttribute("initialSysadmin", systemAdministratorService.getInitialSysadmin());
|
||||||
return "settings";
|
return "settings";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import java.util.Locale;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -18,25 +17,18 @@ public class SystemAdministratorService {
|
|||||||
private static final Logger logger = LoggerFactory.getLogger(SystemAdministratorService.class);
|
private static final Logger logger = LoggerFactory.getLogger(SystemAdministratorService.class);
|
||||||
|
|
||||||
private final SystemAdministratorRepository repo;
|
private final SystemAdministratorRepository repo;
|
||||||
private final String initialSysadmin;
|
|
||||||
private final Environment environment;
|
private final Environment environment;
|
||||||
|
|
||||||
public SystemAdministratorService(
|
public SystemAdministratorService(
|
||||||
SystemAdministratorRepository repo,
|
SystemAdministratorRepository repo,
|
||||||
@Value("${IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN:#{null}}") String initialSysadmin,
|
|
||||||
Environment environment
|
Environment environment
|
||||||
) {
|
) {
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
this.initialSysadmin = initialSysadmin;
|
|
||||||
this.environment = environment;
|
this.environment = environment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void initDefaults() {
|
public void initDefaults() {
|
||||||
if (repo.count() > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
Boolean.parseBoolean(
|
Boolean.parseBoolean(
|
||||||
environment.getProperty("org.springframework.boot.test.context.SpringBootTestContextBootstrapper")
|
environment.getProperty("org.springframework.boot.test.context.SpringBootTestContextBootstrapper")
|
||||||
@@ -46,18 +38,34 @@ public class SystemAdministratorService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String initialSysadmin = getInitialSysadmin();
|
||||||
|
if (initialSysadmin != null) {
|
||||||
|
long deleted = repo.deleteByTwitchUsername(initialSysadmin);
|
||||||
|
if (deleted > 0) {
|
||||||
|
logger.info("Removed persisted initial system administrator '{}' to use environment value", initialSysadmin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repo.count() > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (initialSysadmin == null || initialSysadmin.isBlank()) {
|
if (initialSysadmin == null || initialSysadmin.isBlank()) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"No system administrators exist and IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN is not set"
|
"No system administrators exist and IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN is not set"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
addSysadmin(initialSysadmin);
|
logger.info("Using initial system administrator '{}' from environment", initialSysadmin);
|
||||||
logger.info("Created initial system administrator '{}'", initialSysadmin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addSysadmin(String twitchUsername) {
|
public void addSysadmin(String twitchUsername) {
|
||||||
String normalized = normalize(twitchUsername);
|
String normalized = normalize(twitchUsername);
|
||||||
|
String initialSysadmin = getInitialSysadmin();
|
||||||
|
|
||||||
|
if (initialSysadmin != null && initialSysadmin.equals(normalized)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (repo.existsByTwitchUsername(normalized)) {
|
if (repo.existsByTwitchUsername(normalized)) {
|
||||||
return;
|
return;
|
||||||
@@ -67,11 +75,18 @@ public class SystemAdministratorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeSysadmin(String twitchUsername) {
|
public void removeSysadmin(String twitchUsername) {
|
||||||
if (repo.count() <= 1) {
|
String normalized = normalize(twitchUsername);
|
||||||
|
String initialSysadmin = getInitialSysadmin();
|
||||||
|
|
||||||
|
if (initialSysadmin != null && initialSysadmin.equals(normalized)) {
|
||||||
|
throw new IllegalStateException("Cannot remove the initial system administrator");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialSysadmin == null && repo.count() <= 1) {
|
||||||
throw new IllegalStateException("Cannot remove the last system administrator");
|
throw new IllegalStateException("Cannot remove the last system administrator");
|
||||||
}
|
}
|
||||||
|
|
||||||
long deleted = repo.deleteByTwitchUsername(normalize(twitchUsername));
|
long deleted = repo.deleteByTwitchUsername(normalized);
|
||||||
|
|
||||||
if (deleted == 0) {
|
if (deleted == 0) {
|
||||||
throw new IllegalArgumentException("System administrator does not exist");
|
throw new IllegalArgumentException("System administrator does not exist");
|
||||||
@@ -79,7 +94,20 @@ public class SystemAdministratorService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSysadmin(String twitchUsername) {
|
public boolean isSysadmin(String twitchUsername) {
|
||||||
return repo.existsByTwitchUsername(normalize(twitchUsername));
|
String normalized = normalize(twitchUsername);
|
||||||
|
String initialSysadmin = getInitialSysadmin();
|
||||||
|
if (initialSysadmin != null && initialSysadmin.equals(normalized)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return repo.existsByTwitchUsername(normalized);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInitialSysadmin() {
|
||||||
|
String value = environment.getProperty("IMGFLOAT_INITIAL_TWITCH_USERNAME_SYSADMIN");
|
||||||
|
if (value == null || value.isBlank()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return normalize(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> listSysadmins() {
|
public List<String> listSysadmins() {
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ const sysadminInputElement = document.getElementById("new-sysadmin");
|
|||||||
const addSysadminButtonElement = document.getElementById("add-sysadmin-button");
|
const addSysadminButtonElement = document.getElementById("add-sysadmin-button");
|
||||||
|
|
||||||
let currentSettings = JSON.parse(serverRenderedSettings);
|
let currentSettings = JSON.parse(serverRenderedSettings);
|
||||||
|
const initialSysadmin =
|
||||||
|
typeof serverRenderedInitialSysadmin === "string" && serverRenderedInitialSysadmin.trim() !== ""
|
||||||
|
? serverRenderedInitialSysadmin.trim().toLowerCase()
|
||||||
|
: null;
|
||||||
let userSettings = { ...currentSettings };
|
let userSettings = { ...currentSettings };
|
||||||
|
|
||||||
function jsonEquals(a, b) {
|
function jsonEquals(a, b) {
|
||||||
@@ -165,7 +169,7 @@ function renderSystemAdministrators(admins) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadSystemAdministrators() {
|
async function loadSystemAdministrators() {
|
||||||
return fetch("/api/system-administrators")
|
return fetch("/api/system-administrators")
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
if (!r.ok) {
|
if (!r.ok) {
|
||||||
@@ -254,3 +258,13 @@ setFormSettings(currentSettings);
|
|||||||
updateStatCards(currentSettings);
|
updateStatCards(currentSettings);
|
||||||
updateSubmitButtonDisabledState();
|
updateSubmitButtonDisabledState();
|
||||||
loadSystemAdministrators();
|
loadSystemAdministrators();
|
||||||
|
|
||||||
|
if (initialSysadmin) {
|
||||||
|
document.querySelectorAll("[data-sysadmin-remove]").forEach((button) => {
|
||||||
|
const username = button.getAttribute("data-sysadmin-username");
|
||||||
|
if (username && username.trim().toLowerCase() === initialSysadmin) {
|
||||||
|
button.disabled = true;
|
||||||
|
button.title = "The initial system administrator cannot be removed.";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -285,6 +285,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<script th:inline="javascript">
|
<script th:inline="javascript">
|
||||||
const serverRenderedSettings = /*[[${settingsJson}]]*/;
|
const serverRenderedSettings = /*[[${settingsJson}]]*/;
|
||||||
|
const serverRenderedInitialSysadmin = /*[[${initialSysadmin}]]*/;
|
||||||
</script>
|
</script>
|
||||||
<script src="/js/cookie-consent.js"></script>
|
<script src="/js/cookie-consent.js"></script>
|
||||||
<script src="/js/settings.js"></script>
|
<script src="/js/settings.js"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user