ultisuite-client/scripts/authentik-dom-dump.mjs
R3D347HR4Y 9ea2d3325d
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(auth): enhance authentication flows with embedded support and UI improvements
- Updated login and signup components to utilize AuthCard for better user experience during redirection.
- Introduced AuthentikEmbedDialog for seamless integration of Authentik's identity portal within the application.
- Enhanced password recovery and signup flows with dynamic theme handling and improved loading states.
- Refactored existing components to streamline authentication processes and improve maintainability.
2026-06-21 00:12:45 +02:00

81 lines
2.7 KiB
JavaScript

// Headless dump of Authentik flow shadow DOM + screenshot.
// Usage: node scripts/authentik-dom-dump.mjs <url> <outName> [theme]
import { chromium } from "@playwright/test"
import { writeFileSync } from "node:fs"
const url = process.argv[2] ?? "http://localhost/auth/if/flow/default-authentication-flow/"
const outName = process.argv[3] ?? "login"
const theme = process.argv[4] ?? "light" // light | dark
const outDir = "/tmp/authentik-dom"
await import("node:fs").then((fs) => fs.mkdirSync(outDir, { recursive: true }))
const browser = await chromium.launch()
const ctx = await browser.newContext({
viewport: { width: 1280, height: 900 },
colorScheme: theme === "dark" ? "dark" : "light",
ignoreHTTPSErrors: true,
})
const page = await ctx.newPage()
// Authentik advertises api.base as https://localhost (X-Forwarded-Proto), but nginx is http-only
// here. Rewrite api.base to a same-origin relative URL before the flow bundle reads it.
await page.addInitScript(() => {
Object.defineProperty(window, "authentik", {
configurable: true,
set(v) {
try {
if (v && v.api) {
v.api.base = location.origin + "/auth/"
v.api.relBase = "/auth/"
}
} catch {}
Object.defineProperty(window, "authentik", {
value: v,
writable: true,
configurable: true,
})
},
get() {
return undefined
},
})
})
await page.goto(url, { waitUntil: "networkidle", timeout: 30000 })
// Give Lit components time to render the stage.
await page.waitForTimeout(2500)
// Recursively serialize light + shadow DOM into an indented outline.
const outline = await page.evaluate(() => {
function attrs(el) {
return [...el.attributes]
.filter((a) => !["style"].includes(a.name))
.map((a) => (a.value ? `${a.name}="${a.value}"` : a.name))
.join(" ")
}
function walk(node, depth, lines) {
const pad = " ".repeat(depth)
if (node.nodeType === Node.ELEMENT_NODE) {
const tag = node.tagName.toLowerCase()
const a = attrs(node)
lines.push(`${pad}<${tag}${a ? " " + a : ""}>`)
if (node.shadowRoot) {
lines.push(`${pad} #shadow-root`)
for (const c of node.shadowRoot.children) walk(c, depth + 2, lines)
}
for (const c of node.children) walk(c, depth + 1, lines)
}
return lines
}
const lines = []
walk(document.documentElement, 0, lines)
// Cap to keep output readable.
return lines.slice(0, 1200).join("\n")
})
writeFileSync(`${outDir}/${outName}-${theme}.dom.txt`, outline)
await page.screenshot({ path: `${outDir}/${outName}-${theme}.png`, fullPage: true })
console.log(`wrote ${outDir}/${outName}-${theme}.dom.txt (+ .png)`)
await browser.close()