add configurable club login domains in RMS software
This commit is contained in:
@@ -4,6 +4,7 @@ const SWR_DETAIL_REFRESH_MS = 20000;
|
||||
const DEFAULT_UI_LANGUAGE = "de";
|
||||
const SUPPORTED_UI_LANGUAGES = ["de", "en"];
|
||||
const LANGUAGE_STORAGE_KEY = "rms-lang";
|
||||
const DEFAULT_ALLOWED_LOGIN_DOMAINS = ["arcg.at", "oevsv.at"];
|
||||
|
||||
let activationWatchTimer = null;
|
||||
let activationWatchInFlight = false;
|
||||
@@ -21,7 +22,8 @@ const state = {
|
||||
branding: {
|
||||
logoLightUrl: null,
|
||||
logoDarkUrl: null
|
||||
}
|
||||
},
|
||||
allowedLoginDomains: DEFAULT_ALLOWED_LOGIN_DOMAINS.slice()
|
||||
},
|
||||
accessToken: localStorage.getItem("rms-access-token") || "",
|
||||
refreshToken: localStorage.getItem("rms-refresh-token") || "",
|
||||
@@ -251,6 +253,8 @@ const els = {
|
||||
maintenanceMessageInput: document.getElementById("maintenanceMessageInput"),
|
||||
maintenanceEnableBtn: document.getElementById("maintenanceEnableBtn"),
|
||||
maintenanceDisableBtn: document.getElementById("maintenanceDisableBtn"),
|
||||
loginDomainsInput: document.getElementById("loginDomainsInput"),
|
||||
saveLoginDomainsBtn: document.getElementById("saveLoginDomainsBtn"),
|
||||
logoLightFile: document.getElementById("logoLightFile"),
|
||||
logoDarkFile: document.getElementById("logoDarkFile"),
|
||||
uploadLogoLightBtn: document.getElementById("uploadLogoLightBtn"),
|
||||
@@ -817,6 +821,11 @@ function bindEvents() {
|
||||
await setMaintenanceMode(false);
|
||||
});
|
||||
}
|
||||
if (els.saveLoginDomainsBtn) {
|
||||
els.saveLoginDomainsBtn.addEventListener("click", async () => {
|
||||
await saveLoginDomains();
|
||||
});
|
||||
}
|
||||
if (els.uploadLogoLightBtn) {
|
||||
els.uploadLogoLightBtn.addEventListener("click", async () => {
|
||||
await uploadBrandLogo("light", els.logoLightFile);
|
||||
@@ -902,6 +911,10 @@ async function refreshFrontendOnResume() {
|
||||
async function requestAccess() {
|
||||
clearMessages("auth");
|
||||
const email = els.email.value.trim();
|
||||
if (!isLoginEmailAllowed(email)) {
|
||||
renderMessage(els.authMessage, `Nur Club-Mailadressen (${formatAllowedDomainsHint()}) sind zum Anmelden moeglich.`, true);
|
||||
return;
|
||||
}
|
||||
const method = els.authMethodSelect.value;
|
||||
try {
|
||||
const result = await api("/v1/auth/request-access", {
|
||||
@@ -971,6 +984,30 @@ async function verifyOtpCode() {
|
||||
}
|
||||
}
|
||||
|
||||
function isLoginEmailAllowed(email) {
|
||||
const normalized = String(email || "").trim().toLowerCase();
|
||||
if (!normalized || !normalized.includes("@")) {
|
||||
return false;
|
||||
}
|
||||
const atIndex = normalized.lastIndexOf("@");
|
||||
if (atIndex < 0) {
|
||||
return false;
|
||||
}
|
||||
const domain = normalized.slice(atIndex + 1);
|
||||
return getAllowedLoginDomains().includes(domain);
|
||||
}
|
||||
|
||||
function getAllowedLoginDomains() {
|
||||
const list = state && state.system && Array.isArray(state.system.allowedLoginDomains)
|
||||
? state.system.allowedLoginDomains
|
||||
: [];
|
||||
return list.length > 0 ? list : DEFAULT_ALLOWED_LOGIN_DOMAINS.slice();
|
||||
}
|
||||
|
||||
function formatAllowedDomainsHint() {
|
||||
return getAllowedLoginDomains().map((domain) => `@${domain}`).join(" oder ");
|
||||
}
|
||||
|
||||
async function handleEmailTokenFromUrl() {
|
||||
const url = new URL(window.location.href);
|
||||
if (url.searchParams.get("requestApproval") === "1") {
|
||||
@@ -1036,14 +1073,16 @@ async function refreshPublicSystemStatus() {
|
||||
maintenanceMode: Boolean(result.maintenanceMode),
|
||||
maintenanceMessage: result.maintenanceMessage || "",
|
||||
updatedAt: result.updatedAt || null,
|
||||
branding: normalizeBranding(result.branding)
|
||||
branding: normalizeBranding(result.branding),
|
||||
allowedLoginDomains: normalizeLoginDomainList(result.allowedLoginDomains)
|
||||
};
|
||||
} catch {
|
||||
state.system = {
|
||||
maintenanceMode: false,
|
||||
maintenanceMessage: "",
|
||||
updatedAt: null,
|
||||
branding: normalizeBranding(null)
|
||||
branding: normalizeBranding(null),
|
||||
allowedLoginDomains: DEFAULT_ALLOWED_LOGIN_DOMAINS.slice()
|
||||
};
|
||||
}
|
||||
renderMaintenanceBanner();
|
||||
@@ -1165,6 +1204,43 @@ function renderMaintenanceBanner() {
|
||||
if (els.maintenanceMessageInput && !els.maintenanceMessageInput.value) {
|
||||
els.maintenanceMessageInput.value = state.system.maintenanceMessage || "";
|
||||
}
|
||||
if (els.loginDomainsInput && document.activeElement !== els.loginDomainsInput) {
|
||||
els.loginDomainsInput.value = getAllowedLoginDomains().join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeLoginDomainList(value) {
|
||||
const list = Array.isArray(value)
|
||||
? value
|
||||
: String(value || "").split(/[\n,;\s]+/);
|
||||
const unique = [];
|
||||
const seen = new Set();
|
||||
for (const entry of list) {
|
||||
const domain = String(entry || "").trim().toLowerCase();
|
||||
if (!domain) continue;
|
||||
if (!/^[a-z0-9.-]+$/.test(domain)) continue;
|
||||
if (!domain.includes(".")) continue;
|
||||
if (seen.has(domain)) continue;
|
||||
seen.add(domain);
|
||||
unique.push(domain);
|
||||
}
|
||||
return unique.length > 0 ? unique : DEFAULT_ALLOWED_LOGIN_DOMAINS.slice();
|
||||
}
|
||||
|
||||
async function saveLoginDomains() {
|
||||
clearMessages("admin");
|
||||
const domains = normalizeLoginDomainList(els.loginDomainsInput ? els.loginDomainsInput.value : "");
|
||||
try {
|
||||
const result = await api("/v1/admin/login-domains", {
|
||||
method: "PUT",
|
||||
body: { domains }
|
||||
});
|
||||
state.system.allowedLoginDomains = normalizeLoginDomainList(result && result.domains ? result.domains : domains);
|
||||
renderMaintenanceBanner();
|
||||
renderMessage(els.adminMessage, `Login-Domains gespeichert (${formatAllowedDomainsHint()}).`, false, true);
|
||||
} catch (error) {
|
||||
renderMessage(els.adminMessage, error.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
function renderBranding() {
|
||||
|
||||
Reference in New Issue
Block a user