feat: add auth and dual-stack tls management
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
export function getCurrentRelativeUrl() {
|
||||
return `${window.location.pathname}${window.location.search}${window.location.hash}`;
|
||||
}
|
||||
|
||||
export function buildLoginUrl(nextPath = getCurrentRelativeUrl()) {
|
||||
const loginUrl = new URL('/login.html', window.location.origin);
|
||||
if (nextPath) {
|
||||
loginUrl.searchParams.set('next', nextPath);
|
||||
}
|
||||
|
||||
return `${loginUrl.pathname}${loginUrl.search}`;
|
||||
}
|
||||
|
||||
export function redirectToLogin(nextPath = getCurrentRelativeUrl()) {
|
||||
window.location.assign(buildLoginUrl(nextPath));
|
||||
}
|
||||
|
||||
export function readNextPath(fallback = '/') {
|
||||
const nextPath = new URLSearchParams(window.location.search).get('next');
|
||||
if (!nextPath || !nextPath.startsWith('/') || nextPath.startsWith('//')) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return nextPath;
|
||||
}
|
||||
|
||||
export function redirectToNextPath(fallback = '/') {
|
||||
window.location.assign(readNextPath(fallback));
|
||||
}
|
||||
|
||||
export async function loadAuthState() {
|
||||
const response = await fetch('/api/auth/state');
|
||||
const payload = await response.json().catch(() => ({}));
|
||||
if (!response.ok) {
|
||||
throw new Error(`${payload.error?.code ?? 'AUTH_STATE_FAILED'}: ${payload.error?.message ?? 'Failed to load auth state.'}`);
|
||||
}
|
||||
|
||||
return payload.auth;
|
||||
}
|
||||
|
||||
export async function logoutCurrentSession() {
|
||||
const response = await fetch('/api/auth/logout', {
|
||||
method: 'POST'
|
||||
});
|
||||
const payload = await response.json().catch(() => ({ ok: false }));
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`${payload.error?.code ?? 'LOGOUT_FAILED'}: ${payload.error?.message ?? 'Logout failed.'}`);
|
||||
}
|
||||
|
||||
return payload;
|
||||
}
|
||||
|
||||
export function bindLogoutButton(button, labelElement, fallbackLabel = 'Signed in') {
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.addEventListener('click', async () => {
|
||||
button.disabled = true;
|
||||
if (labelElement) {
|
||||
labelElement.textContent = 'Signing out...';
|
||||
}
|
||||
|
||||
try {
|
||||
await logoutCurrentSession();
|
||||
} finally {
|
||||
redirectToLogin('/');
|
||||
}
|
||||
});
|
||||
|
||||
if (labelElement && !labelElement.textContent.trim()) {
|
||||
labelElement.textContent = fallbackLabel;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user