split RMS login email into callsign and domain select
This commit is contained in:
@@ -81,7 +81,8 @@ const state = {
|
|||||||
|
|
||||||
const els = {
|
const els = {
|
||||||
authForm: document.getElementById("authForm"),
|
authForm: document.getElementById("authForm"),
|
||||||
email: document.getElementById("email"),
|
callsignInput: document.getElementById("callsignInput"),
|
||||||
|
emailDomainSelect: document.getElementById("emailDomainSelect"),
|
||||||
loginBtn: document.getElementById("loginBtn"),
|
loginBtn: document.getElementById("loginBtn"),
|
||||||
authMethodSelect: document.getElementById("authMethodSelect"),
|
authMethodSelect: document.getElementById("authMethodSelect"),
|
||||||
otpWrap: document.getElementById("otpWrap"),
|
otpWrap: document.getElementById("otpWrap"),
|
||||||
@@ -910,7 +911,7 @@ async function refreshFrontendOnResume() {
|
|||||||
|
|
||||||
async function requestAccess() {
|
async function requestAccess() {
|
||||||
clearMessages("auth");
|
clearMessages("auth");
|
||||||
const email = els.email.value.trim();
|
const email = composeLoginEmail();
|
||||||
if (!isLoginEmailAllowed(email)) {
|
if (!isLoginEmailAllowed(email)) {
|
||||||
renderMessage(els.authMessage, `Nur Club-Mailadressen (${formatAllowedDomainsHint()}) sind zum Anmelden moeglich.`, true);
|
renderMessage(els.authMessage, `Nur Club-Mailadressen (${formatAllowedDomainsHint()}) sind zum Anmelden moeglich.`, true);
|
||||||
return;
|
return;
|
||||||
@@ -950,11 +951,12 @@ async function requestAccess() {
|
|||||||
|
|
||||||
async function verifyOtpCode() {
|
async function verifyOtpCode() {
|
||||||
clearMessages("auth");
|
clearMessages("auth");
|
||||||
|
const email = composeLoginEmail();
|
||||||
try {
|
try {
|
||||||
const result = await api("/v1/auth/verify-email", {
|
const result = await api("/v1/auth/verify-email", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: {
|
body: {
|
||||||
email: els.email.value.trim(),
|
email,
|
||||||
code: els.otpCode.value.trim()
|
code: els.otpCode.value.trim()
|
||||||
},
|
},
|
||||||
authRequired: false
|
authRequired: false
|
||||||
@@ -997,6 +999,41 @@ function isLoginEmailAllowed(email) {
|
|||||||
return getAllowedLoginDomains().includes(domain);
|
return getAllowedLoginDomains().includes(domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function composeLoginEmail() {
|
||||||
|
const callsign = String(els.callsignInput && els.callsignInput.value ? els.callsignInput.value : "")
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
|
const selectedDomain = String(
|
||||||
|
els.emailDomainSelect && els.emailDomainSelect.value
|
||||||
|
? els.emailDomainSelect.value
|
||||||
|
: getAllowedLoginDomains()[0] || ""
|
||||||
|
)
|
||||||
|
.trim()
|
||||||
|
.toLowerCase();
|
||||||
|
if (!callsign || !selectedDomain) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (callsign.includes("@")) {
|
||||||
|
return callsign;
|
||||||
|
}
|
||||||
|
return `${callsign}@${selectedDomain}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitEmailParts(email) {
|
||||||
|
const normalized = String(email || "").trim().toLowerCase();
|
||||||
|
const atIndex = normalized.lastIndexOf("@");
|
||||||
|
if (atIndex < 0) {
|
||||||
|
return {
|
||||||
|
callsign: normalized,
|
||||||
|
domain: ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
callsign: normalized.slice(0, atIndex),
|
||||||
|
domain: normalized.slice(atIndex + 1)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function getAllowedLoginDomains() {
|
function getAllowedLoginDomains() {
|
||||||
const list = state && state.system && Array.isArray(state.system.allowedLoginDomains)
|
const list = state && state.system && Array.isArray(state.system.allowedLoginDomains)
|
||||||
? state.system.allowedLoginDomains
|
? state.system.allowedLoginDomains
|
||||||
@@ -1008,12 +1045,32 @@ function formatAllowedDomainsHint() {
|
|||||||
return getAllowedLoginDomains().map((domain) => `@${domain}`).join(" oder ");
|
return getAllowedLoginDomains().map((domain) => `@${domain}`).join(" oder ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderLoginDomainSelect() {
|
||||||
|
if (!els.emailDomainSelect) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const domains = getAllowedLoginDomains();
|
||||||
|
const previous = String(els.emailDomainSelect.value || "").toLowerCase();
|
||||||
|
els.emailDomainSelect.innerHTML = "";
|
||||||
|
for (const domain of domains) {
|
||||||
|
const option = document.createElement("option");
|
||||||
|
option.value = domain;
|
||||||
|
option.textContent = domain;
|
||||||
|
els.emailDomainSelect.appendChild(option);
|
||||||
|
}
|
||||||
|
if (previous && domains.includes(previous)) {
|
||||||
|
els.emailDomainSelect.value = previous;
|
||||||
|
} else if (domains.length > 0) {
|
||||||
|
els.emailDomainSelect.value = domains[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleEmailTokenFromUrl() {
|
async function handleEmailTokenFromUrl() {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(window.location.href);
|
||||||
if (url.searchParams.get("requestApproval") === "1") {
|
if (url.searchParams.get("requestApproval") === "1") {
|
||||||
const email = (url.searchParams.get("email") || "").trim();
|
const email = (url.searchParams.get("email") || "").trim();
|
||||||
if (email) {
|
if (email) {
|
||||||
els.email.value = email;
|
setLoginEmail(email);
|
||||||
try {
|
try {
|
||||||
const result = await api("/v1/auth/request-approval", {
|
const result = await api("/v1/auth/request-approval", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@@ -1066,6 +1123,19 @@ async function handleEmailTokenFromUrl() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setLoginEmail(email) {
|
||||||
|
const parts = splitEmailParts(email);
|
||||||
|
if (els.callsignInput) {
|
||||||
|
els.callsignInput.value = parts.callsign || "";
|
||||||
|
}
|
||||||
|
if (els.emailDomainSelect) {
|
||||||
|
renderLoginDomainSelect();
|
||||||
|
if (parts.domain && getAllowedLoginDomains().includes(parts.domain)) {
|
||||||
|
els.emailDomainSelect.value = parts.domain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function refreshPublicSystemStatus() {
|
async function refreshPublicSystemStatus() {
|
||||||
try {
|
try {
|
||||||
const result = await api("/v1/public/system", { authRequired: false });
|
const result = await api("/v1/public/system", { authRequired: false });
|
||||||
@@ -1085,6 +1155,7 @@ async function refreshPublicSystemStatus() {
|
|||||||
allowedLoginDomains: DEFAULT_ALLOWED_LOGIN_DOMAINS.slice()
|
allowedLoginDomains: DEFAULT_ALLOWED_LOGIN_DOMAINS.slice()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
renderLoginDomainSelect();
|
||||||
renderMaintenanceBanner();
|
renderMaintenanceBanner();
|
||||||
renderBranding();
|
renderBranding();
|
||||||
}
|
}
|
||||||
@@ -4225,7 +4296,8 @@ function updateUserUi() {
|
|||||||
setDisabled(els.logoutBtn, !loggedIn);
|
setDisabled(els.logoutBtn, !loggedIn);
|
||||||
setDisabled(els.settingsLogoutTopBtn, !loggedIn);
|
setDisabled(els.settingsLogoutTopBtn, !loggedIn);
|
||||||
setDisabled(els.userMenuButton, !loggedIn);
|
setDisabled(els.userMenuButton, !loggedIn);
|
||||||
setDisabled(els.email, loggedIn);
|
setDisabled(els.callsignInput, loggedIn);
|
||||||
|
setDisabled(els.emailDomainSelect, loggedIn);
|
||||||
if (els.userMenuButton) {
|
if (els.userMenuButton) {
|
||||||
els.userMenuButton.textContent = "☰";
|
els.userMenuButton.textContent = "☰";
|
||||||
els.userMenuButton.setAttribute("aria-label", loggedIn ? `Menue (${state.user.email})` : "Menue");
|
els.userMenuButton.setAttribute("aria-label", loggedIn ? `Menue (${state.user.email})` : "Menue");
|
||||||
|
|||||||
@@ -59,14 +59,21 @@
|
|||||||
<section class="view auth-view" id="authView">
|
<section class="view auth-view" id="authView">
|
||||||
<article class="card login-card stagger" id="authCard">
|
<article class="card login-card stagger" id="authCard">
|
||||||
<h2>Anmeldung</h2>
|
<h2>Anmeldung</h2>
|
||||||
<p class="muted">Anmeldung per ARCG E-Mail-Adresse wird automatisch freigeschalten. Andere Mailadressen brauchen eine manuelle Freischaltung. Du bekommst einen Login- oder Bestaetigungslink.</p>
|
<p class="muted">Bitte Rufzeichen und Club-Domain eingeben. Du bekommst einen Login- oder Bestaetigungslink.</p>
|
||||||
<p id="maintenanceBanner" class="message" hidden></p>
|
<p id="maintenanceBanner" class="message" hidden></p>
|
||||||
|
|
||||||
<form id="authForm" class="stack">
|
<form id="authForm" class="stack">
|
||||||
<label class="field">
|
<div class="actions" style="align-items: end; gap: 0.6rem; flex-wrap: wrap;">
|
||||||
<span>E-Mail</span>
|
<label class="field" style="flex: 2 1 220px; min-width: 180px; margin: 0;">
|
||||||
<input id="email" type="email" autocomplete="email" required />
|
<span>Rufzeichen</span>
|
||||||
|
<input id="callsignInput" type="text" autocomplete="username" placeholder="oe6abc" required />
|
||||||
</label>
|
</label>
|
||||||
|
<span class="muted" aria-hidden="true" style="padding-bottom: 0.5rem;">@</span>
|
||||||
|
<label class="field" style="flex: 1 1 180px; min-width: 160px; margin: 0;">
|
||||||
|
<span>Domain</span>
|
||||||
|
<select id="emailDomainSelect"></select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<label class="field">
|
<label class="field">
|
||||||
<span>Bestaetigungsart</span>
|
<span>Bestaetigungsart</span>
|
||||||
<select id="authMethodSelect"></select>
|
<select id="authMethodSelect"></select>
|
||||||
|
|||||||
Reference in New Issue
Block a user