stage 1 of oauth removal, switch to sanctum pat tokens

This commit is contained in:
Codex Agent
2025-11-06 20:35:58 +01:00
parent c9783bd57b
commit 776da57ca9
47 changed files with 1571 additions and 2555 deletions

View File

@@ -1,8 +1,5 @@
import { ADMIN_BASE_PATH, ADMIN_DEFAULT_AFTER_LOGIN_PATH, ADMIN_LOGIN_PATH, ADMIN_LOGIN_START_PATH } from '../constants';
const LAST_DESTINATION_KEY = 'tenant.oauth.lastDestination';
const DASHBOARD_PREFIX = '/dashboard';
function ensureLeadingSlash(target: string): string {
if (!target) {
return '/';
@@ -15,14 +12,6 @@ function ensureLeadingSlash(target: string): string {
return target.startsWith('/') ? target : `/${target}`;
}
function matchesDashboardScope(path: string): boolean {
return (
path === DASHBOARD_PREFIX ||
path.startsWith(`${DASHBOARD_PREFIX}?`) ||
path.startsWith(`${DASHBOARD_PREFIX}/`)
);
}
export function isPermittedReturnTarget(target: string): boolean {
if (!target) {
return false;
@@ -30,11 +19,20 @@ export function isPermittedReturnTarget(target: string): boolean {
const sanitized = ensureLeadingSlash(target);
if (sanitized.startsWith(ADMIN_BASE_PATH)) {
return true;
if (/^[a-z][a-z0-9+\-.]*:\/\//i.test(sanitized)) {
try {
const url = new URL(sanitized);
return url.pathname.startsWith(ADMIN_BASE_PATH);
} catch (error) {
if (import.meta.env.DEV) {
console.warn('[Auth] Failed to parse return target URL', error);
}
return false;
}
}
return matchesDashboardScope(sanitized);
return sanitized.startsWith(ADMIN_BASE_PATH);
}
function base64UrlEncode(value: string): string {
@@ -135,69 +133,3 @@ export function resolveReturnTarget(raw: string | null, fallback: string): Retur
return { finalTarget, encodedFinal };
}
export function buildAdminOAuthStartPath(targetPath: string, encodedTarget?: string): string {
const sanitizedTarget = ensureLeadingSlash(targetPath);
const encoded = encodedTarget ?? encodeReturnTo(sanitizedTarget);
const url = new URL(ADMIN_LOGIN_START_PATH, window.location.origin);
url.searchParams.set('return_to', encoded);
return `${url.pathname}${url.search}`;
}
function resolveLocale(): string {
const raw = document.documentElement.lang || 'de';
const normalized = raw.toLowerCase();
if (normalized.includes('-')) {
return normalized.split('-')[0] || 'de';
}
return normalized || 'de';
}
export function buildMarketingLoginUrl(returnPath: string): string {
const sanitizedPath = ensureLeadingSlash(returnPath);
const encoded = encodeReturnTo(sanitizedPath);
const locale = resolveLocale();
const loginPath = `/${locale}/login`;
const url = new URL(loginPath, window.location.origin);
url.searchParams.set('return_to', encoded);
return url.toString();
}
export function storeLastDestination(path: string): void {
if (typeof window === 'undefined') {
return;
}
const sanitized = ensureLeadingSlash(path.trim());
try {
window.sessionStorage.setItem(LAST_DESTINATION_KEY, sanitized);
} catch (error) {
if (import.meta.env.DEV) {
console.warn('[Auth] Failed to store last destination', error);
}
}
}
export function consumeLastDestination(): string | null {
if (typeof window === 'undefined') {
return null;
}
try {
const value = window.sessionStorage.getItem(LAST_DESTINATION_KEY);
if (value) {
window.sessionStorage.removeItem(LAST_DESTINATION_KEY);
return ensureLeadingSlash(value);
}
} catch (error) {
if (import.meta.env.DEV) {
console.warn('[Auth] Failed to read last destination', error);
}
}
return null;
}