/* Auth guard for the Work Package Suite. Included in the of every protected page (before other scripts). It confirms there is a valid session by calling /api/auth/me; if not, it sends the user to the login page. The real protection is server-side (the API refuses data requests without a session) — this guard is for UX so people land on the login screen instead of an empty app. It also exposes: window.WP_USER the logged-in user object (set once verified) window.wpLogout() clears the session and returns to the login page and dispatches a 'wp-auth-ready' event on document once WP_USER is set. */ (function () { 'use strict'; var inIframe = (function () { try { return window.top !== window.self; } catch (e) { return true; } })(); // Hide the page until we know the user is allowed, to avoid a flash of the app // before a redirect. A safety timer reveals it even if the check hangs. var root = document.documentElement; var style = document.createElement('style'); style.textContent = '.wp-auth-pending body{visibility:hidden!important}'; (document.head || root).appendChild(style); root.className += ' wp-auth-pending'; function reveal() { root.className = root.className.replace(/\bwp-auth-pending\b/, ''); } var safety = setTimeout(reveal, 4000); function goToLogin() { clearTimeout(safety); var next = encodeURIComponent(location.pathname + location.search); var url = 'login.html?next=' + next; // If we're inside the WP-creator iframe, redirect the whole window. var w = inIframe ? window.top : window; try { w.location.replace(url); } catch (e) { window.location.replace(url); } } window.wpLogout = function () { fetch('/api/auth/logout', { method: 'POST' }) .catch(function () {}) .then(function () { window.location.replace('login.html'); }); }; function addLogoutPill(user) { if (inIframe) return; // the parent page already shows it if (document.getElementById('wp-logout-pill')) return; var pill = document.createElement('div'); pill.id = 'wp-logout-pill'; pill.style.cssText = 'position:fixed;top:12px;right:12px;z-index:10001;' + 'display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #e0e0e0;' + 'box-shadow:0 1px 4px rgba(0,0,0,.16);border-radius:16px;padding:5px 12px;' + 'font:500 12px/1.2 -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;color:#525252;'; function sep() { var s = document.createElement('span'); s.textContent = '·'; s.style.color = '#a8a8a8'; return s; } var who = document.createElement('span'); who.textContent = user.full_name || user.username; pill.appendChild(who); // Admins get a link to the Admin Console (hidden when already on it). var onAdmin = /(^|\/)admin\.html$/.test(location.pathname); if (user.role === 'admin' && !onAdmin) { var adm = document.createElement('a'); adm.href = 'admin.html'; adm.textContent = 'Admin'; adm.style.cssText = 'color:#0f62fe;text-decoration:none;font-weight:600;'; pill.appendChild(sep()); pill.appendChild(adm); } var out = document.createElement('a'); out.href = '#'; out.textContent = 'Sign out'; out.style.cssText = 'color:#0f62fe;text-decoration:none;font-weight:600;'; out.addEventListener('click', function (e) { e.preventDefault(); window.wpLogout(); }); pill.appendChild(sep()); pill.appendChild(out); document.body.appendChild(pill); } fetch('/api/auth/me', { headers: { 'Accept': 'application/json' } }) .then(function (r) { if (r.status === 401 || r.status === 403) { goToLogin(); return; } if (!r.ok) { reveal(); clearTimeout(safety); return; } // unexpected; show page rather than trap return r.json().then(function (data) { clearTimeout(safety); window.WP_USER = data && data.user; reveal(); if (window.WP_USER) { try { document.dispatchEvent(new CustomEvent('wp-auth-ready', { detail: window.WP_USER })); } catch (e) {} if (document.body) addLogoutPill(window.WP_USER); else document.addEventListener('DOMContentLoaded', function () { addLogoutPill(window.WP_USER); }); } }); }) .catch(function () { goToLogin(); }); // API unreachable → send to login })();