const statusEl = document.getElementById("status"); const loginPanelEl = document.getElementById("loginPanel"); const appPanelEl = document.getElementById("appPanel"); const loginFormEl = document.getElementById("loginForm"); const passwordInputEl = document.getElementById("passwordInput"); const postfixInfoEl = document.getElementById("postfixInfo"); const postfixFileSelectEl = document.getElementById("postfixFileSelect"); const postfixConfigInputEl = document.getElementById("postfixConfigInput"); const logInfoEl = document.getElementById("logInfo"); const logOutputEl = document.getElementById("logOutput"); const reloadLogButton = document.getElementById("reloadLog"); const reloadPostfixConfigButton = document.getElementById("reloadPostfixConfig"); const savePostfixConfigButton = document.getElementById("savePostfixConfig"); const logoutButton = document.getElementById("logoutButton"); let postfixSettings = []; function setStatus(message, isError = false) { statusEl.textContent = message; statusEl.classList.toggle("error", isError); } function setAuthenticatedView(isAuthenticated) { loginPanelEl.classList.toggle("app-hidden", isAuthenticated); appPanelEl.classList.toggle("app-hidden", !isAuthenticated); } async function checkAuthStatus() { const response = await fetch("/api/auth/status"); const data = await response.json(); return Boolean(data.authenticated); } async function login(password) { const response = await fetch("/api/auth/login", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ password }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || "ログインに失敗しました。"); } } async function logout() { const response = await fetch("/api/auth/logout", { method: "POST", }); await response.json(); } async function loadPostfixSettingList() { const response = await fetch("/api/postfix-settings"); const data = await response.json(); if (!response.ok) { throw new Error(data.message || "Postfix設定一覧の取得に失敗しました。"); } postfixSettings = data.items; postfixFileSelectEl.innerHTML = ""; for (const item of postfixSettings) { const option = document.createElement("option"); option.value = item.id; const state = item.readError ? " (読込不可)" : (item.exists ? "" : " (未作成)"); option.textContent = `${item.label}${state}`; postfixFileSelectEl.appendChild(option); } if (postfixSettings.length > 0) { const preferred = postfixSettings.find((item) => !item.readError) || postfixSettings[0]; postfixFileSelectEl.value = preferred.id; } postfixInfoEl.textContent = `設定ディレクトリ: ${data.baseDir} / 管理対象: ${postfixSettings.length}件`; } async function loadPostfixSettingContent() { const id = postfixFileSelectEl.value; if (!id) { postfixConfigInputEl.value = ""; return; } const selected = postfixSettings.find((item) => item.id === id); if (selected?.readError) { throw new Error(`${selected.label}: ${selected.readError.message} (code: ${selected.readError.code})`); } const response = await fetch(`/api/postfix-settings/${encodeURIComponent(id)}`); const data = await response.json(); if (!response.ok) { throw new Error(data.message || "設定ファイルの読み込みに失敗しました。"); } postfixConfigInputEl.value = data.content; postfixInfoEl.textContent = `編集中: ${data.label} / ファイル: ${data.filePath} / 行数: ${data.lines}`; } async function savePostfixSettingContent() { const id = postfixFileSelectEl.value; if (!id) { throw new Error("保存対象の設定ファイルが未選択です。"); } const response = await fetch(`/api/postfix-settings/${encodeURIComponent(id)}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content: postfixConfigInputEl.value }), }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || "設定ファイルの保存に失敗しました。"); } setStatus(`保存しました: ${data.filePath}`); await loadPostfixSettingList(); postfixFileSelectEl.value = id; await loadPostfixSettingContent(); } async function loadMaillog() { try { const response = await fetch("/api/maillog?lines=100"); const data = await response.json(); if (!response.ok) { throw new Error(data.message || "maillog読込に失敗しました。"); } logInfoEl.textContent = `ファイル: ${data.maillogPath} / 表示行数: ${data.count}`; logOutputEl.textContent = data.lines.join("\n"); setStatus("maillogを更新しました。"); } catch (error) { logInfoEl.textContent = "maillogを読み込めませんでした。"; logOutputEl.textContent = ""; setStatus(error.message, true); } } reloadLogButton.addEventListener("click", loadMaillog); reloadPostfixConfigButton.addEventListener("click", async () => { try { await loadPostfixSettingContent(); setStatus("Postfix設定を再読込しました。"); } catch (error) { setStatus(error.message, true); } }); savePostfixConfigButton.addEventListener("click", async () => { try { await savePostfixSettingContent(); } catch (error) { setStatus(error.message, true); } }); postfixFileSelectEl.addEventListener("change", async () => { try { await loadPostfixSettingContent(); } catch (error) { setStatus(error.message, true); } }); loginFormEl.addEventListener("submit", async (event) => { event.preventDefault(); try { await login(passwordInputEl.value); passwordInputEl.value = ""; setAuthenticatedView(true); await loadPostfixSettingList(); try { await loadPostfixSettingContent(); } catch (error) { setStatus(error.message, true); } await loadMaillog(); setStatus("認証に成功しました。"); } catch (error) { setStatus(error.message, true); } }); logoutButton.addEventListener("click", async () => { await logout(); setAuthenticatedView(false); setStatus("ログアウトしました。"); }); async function bootstrap() { try { const authenticated = await checkAuthStatus(); setAuthenticatedView(authenticated); if (authenticated) { await loadPostfixSettingList(); try { await loadPostfixSettingContent(); } catch (error) { setStatus(error.message, true); } await loadMaillog(); } else { setStatus("パスワードを入力してください。"); } } catch (error) { setStatus("初期化に失敗しました。", true); } } bootstrap();