web: Update Deprecated NPM Packages (#18335)

* core: Bump packages.

* Bump Live Reload dependencies.

* Bump tsconfig.

* Bum ESLint config deps. Fix formatting.

* Bump Prettier deps. Fix ESlint config.

* Bump live reload deps. Fix linter.

* Bump website deps.

* web: Update dependencies. Fix Playwright issues.

* Fix deprecations.

* Fix linter warnings.

* Fix override, run audit.

* Fix import path.

* Tidy types.

* Format.

* Update ignore patterns.

* Fix import path.

* Update deps. Clean up workspace linting.

* Update deps, options.

* Hide icons in navbar.

* Format.

* Remove deprecated option.

* Use relative packages.

* Add scripts. Tidy.

* Bump engines.

* Clarify order.

* Clarify order. Install base deps.

* Format.

* Fix stale user during tests.

* Fix runtime errors.

* Fix redirect during tests, UI change.

* web: Fix danger button hover background color.

* web: Adjust colors, padding.

* web: Fix sidebar colors, padding.

* Fix alignment.

* Fix background contrast.
This commit is contained in:
Teffen Ellis
2025-11-24 19:31:42 +01:00
committed by GitHub
parent e002243a8a
commit a8e765257e
71 changed files with 14563 additions and 9604 deletions

View File

@@ -5,10 +5,10 @@ on:
push:
branches: [main]
paths:
- packages/docusaurus-config/**
- packages/tsconfig/**
- packages/eslint-config/**
- packages/prettier-config/**
- packages/tsconfig/**
- packages/docusaurus-config/**
- packages/esbuild-plugin-live-reload/**
workflow_dispatch:
@@ -24,10 +24,11 @@ jobs:
fail-fast: false
matrix:
package:
- packages/docusaurus-config
# The order of the `*config` packages should not be changed, as they depend on each other.
- packages/tsconfig
- packages/eslint-config
- packages/prettier-config
- packages/tsconfig
- packages/docusaurus-config
- packages/esbuild-plugin-live-reload
steps:
- uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v5
@@ -43,6 +44,8 @@ jobs:
with:
files: |
${{ matrix.package }}/package.json
- name: Install Dependencies
run: npm ci
- name: Publish package
if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ${{ matrix.package }}

View File

@@ -26,6 +26,10 @@ website/api/reference
node_modules
coverage
## Vendored files
vendored
*.min.js
## Configs
*.log
*.yaml

View File

@@ -1,16 +1,17 @@
{
"name": "@goauthentik/lifecycle-aws",
"version": "0.0.0",
"private": true,
"license": "MIT",
"private": true,
"scripts": {
"aws-cfn": "cross-env CI=false cdk synth --version-reporting=false > template.yaml"
},
"engines": {
"node": ">=20"
},
"devDependencies": {
"aws-cdk": "^2.1032.0",
"cross-env": "^10.1.0"
},
"engines": {
"node": ">=20",
"npm": ">=11.6.2"
}
}

3986
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -4,17 +4,24 @@
"private": true,
"type": "module",
"dependencies": {
"@eslint/js": "^9.31.0",
"@typescript-eslint/eslint-plugin": "^8.38.0",
"@typescript-eslint/parser": "^8.38.0",
"eslint": "^9.31.0",
"@eslint/js": "^9.39.1",
"@goauthentik/eslint-config": "./packages/eslint-config",
"@goauthentik/prettier-config": "./packages/prettier-config",
"@goauthentik/tsconfig": "./packages/tsconfig",
"@typescript-eslint/eslint-plugin": "^8.47.0",
"@typescript-eslint/parser": "^8.47.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19",
"typescript": "^5.8.3",
"typescript-eslint": "^8.38.0"
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"engines": {
"node": ">=24",
"npm": ">=11.6.2"
},
"workspaces": [],
"prettier": "./packages/prettier-config/index.js",
"prettier": "@goauthentik/prettier-config",
"overrides": {
"format-imports": {
"eslint": "$eslint"

View File

@@ -23,16 +23,8 @@ a[data-icon]::after {
content: attr(aria-label);
}
@media (max-width: 1300px) {
.navbar--fixed-top .navbar__items a[data-icon]::after {
display: none;
}
}
@media (max-width: 998px) {
.navbar--fixed-top .navbar__items a[data-icon] {
display: none;
}
.navbar--fixed-top .navbar__items a[data-icon]::after {
display: none;
}
a[data-icon="github"]::before {

View File

@@ -0,0 +1,24 @@
/**
* @file ESLint Configuration
*
* @import { Config } from "eslint/config";
*/
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
import { defineConfig } from "eslint/config";
// @ts-check
/**
* @type {Config[]}
*/
const eslintConfig = defineConfig(
createESLintPackageConfig({
parserOptions: {
tsconfigRootDir: import.meta.dirname,
},
}),
);
export default eslintConfig;

View File

@@ -1,13 +1,14 @@
/**
* @file Common Docusaurus configuration utilities.
*
* @import { Config, DocusaurusConfig } from "@docusaurus/types"
* @import { Config } from "@docusaurus/types"
* @import { UserThemeConfig, UserThemeConfigExtra } from "./theme.js"
*/
import { deepmerge } from "deepmerge-ts";
import { createThemeConfig } from "./theme.js";
import { deepmerge } from "deepmerge-ts";
//#region Types
/**
@@ -66,19 +67,23 @@ export function createDefaultDocusaurusConfig() {
rspackPersistentCache: production,
},
},
title: "authentik",
tagline: "Bring all of your authentication into a unified platform.",
url: "https://docs.goauthentik.io",
baseUrl: "/",
onBrokenLinks: "throw",
onBrokenAnchors: "throw",
onBrokenMarkdownLinks: "throw",
onDuplicateRoutes: "throw",
favicon: "img/icon.png",
organizationName: "Authentik Security Inc.",
projectName: "authentik",
markdown: {
mermaid: true,
hooks: {
onBrokenMarkdownLinks: "throw",
onBrokenMarkdownImages: "throw",
},
},
});
@@ -98,7 +103,7 @@ export function createDocusaurusConfig({ themeConfig, ...overrides }) {
themeConfig: createThemeConfig(themeConfig),
};
// @ts-ignore
// @ts-expect-error JSDoc types cannot infer that `overrides` is of the correct type.
return deepmerge(config, overrides);
}

View File

@@ -3,6 +3,7 @@
*
* @import { NavbarItem } from "@docusaurus/theme-common";
*/
import { DocusaurusURL, SocialURL } from "./routing.js";
/**

View File

@@ -5,11 +5,12 @@
* @import { UserThemeConfig as UserThemeConfigAlgolia } from "@docusaurus/theme-search-algolia";
* @import { NavbarItemOverrides } from "./navbar.js"
*/
import { deepmerge } from "deepmerge-ts";
import { themes as prismThemes } from "prism-react-renderer";
import { createNavbarItems } from "./navbar.js";
import { deepmerge } from "deepmerge-ts";
import { themes as prismThemes } from "prism-react-renderer";
//#region Types
/**
@@ -85,6 +86,7 @@ export function createThemeConfig({ prism, navbarReplacements, ...overrides } =
respectPrefersColorScheme: true,
},
algolia: {
indexName: "goauthentik",
appId: "36ROD0O0FV",
apiKey: "727db511300ca9aec5425645bbbddfb5",
},

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,14 @@
{
"name": "@goauthentik/docusaurus-config",
"version": "2.1.2",
"version": "2.2.0",
"description": "authentik's Docusaurus config",
"license": "MIT",
"scripts": {
"build": "tsc -p .",
"prettier": "prettier --write .",
"prettier-check": "prettier --check ."
"lint": "eslint --fix .",
"lint-check": "eslint --max-warnings 0 .",
"prettier": "prettier --cache --write -u .",
"prettier-check": "prettier --cache --check -u ."
},
"type": "module",
"exports": {
@@ -22,20 +24,29 @@
"prism-react-renderer": "^2.4.1"
},
"devDependencies": {
"@docusaurus/theme-common": "^3.8.1",
"@docusaurus/theme-search-algolia": "^3.8.1",
"@docusaurus/types": "^3.8.1",
"@goauthentik/prettier-config": "^3.1.0",
"@goauthentik/tsconfig": "^1.0.4",
"@types/react": "^19.1.6",
"@types/react-dom": "^19.1.5",
"prettier": "^3.5.3",
"typescript": "^5.8.3"
"@docusaurus/theme-common": "3.9.2",
"@docusaurus/theme-search-algolia": "^3.9.2",
"@docusaurus/types": "^3.9.2",
"@eslint/js": "^9.39.1",
"@goauthentik/eslint-config": "../eslint-config",
"@goauthentik/prettier-config": "../prettier-config",
"@goauthentik/tsconfig": "../tsconfig",
"@types/node": "^24.10.1",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^8.47.0",
"@typescript-eslint/parser": "^8.47.0",
"eslint": "^9.39.1",
"pino": "^10.1.0",
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19",
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"peerDependencies": {
"@docusaurus/theme-common": "^3.8.1",
"@docusaurus/theme-search-algolia": "^3.8.1",
"@docusaurus/types": "^3.8.0",
"@docusaurus/theme-common": "^3.9.2",
"@docusaurus/theme-search-algolia": "^3.9.2",
"@docusaurus/types": "^3.9.2",
"react": ">=18",
"react-dom": ">=18"
},
@@ -44,7 +55,13 @@
"react-dom": ">=18"
},
"engines": {
"node": ">=22"
"node": ">=24",
"npm": ">=11.6.2"
},
"repository": {
"type": "git",
"url": "git+https://github.com/goauthentik/authentik.git",
"directory": "packages/docusaurus-config"
},
"types": "./out/index.d.ts",
"files": [

View File

@@ -1,3 +1,13 @@
# Prettier Ignorefile
## Node
node_modules
## Static Files
**/LICENSE
./README.md
## Build asset directories
coverage
dist
out

View File

@@ -0,0 +1,30 @@
/**
* @file ESLint Configuration
*
* @import { Config } from "eslint/config";
*/
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
import { defineConfig } from "eslint/config";
// @ts-check
/**
* @type {Config[]}
*/
const eslintConfig = defineConfig(
createESLintPackageConfig({
parserOptions: {
tsconfigRootDir: import.meta.dirname,
},
}),
{
rules: {
"no-console": "off",
},
files: ["shared/**"],
},
);
export default eslintConfig;

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,14 @@
{
"name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.2.2",
"version": "1.3.0",
"description": "ESBuild + browser refresh. Build completes, page reloads.",
"license": "MIT",
"scripts": {
"build": "npm run build:types && npm run build:docs",
"build:docs": "typedoc",
"build:types": "tsc -p .",
"lint": "eslint --fix .",
"lint-check": "eslint --max-warnings 0 .",
"prettier": "prettier --cache --write -u .",
"prettier-check": "prettier --cache --check -u ."
},
@@ -35,22 +37,29 @@
"find-free-ports": "^3.1.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^3.1.0",
"@goauthentik/tsconfig": "^1.0.4",
"@types/node": "^24.3.1",
"esbuild": "^0.25.9",
"pino": "^10.0.0",
"@eslint/js": "^9.39.1",
"@goauthentik/eslint-config": "../eslint-config",
"@goauthentik/prettier-config": "../prettier-config",
"@goauthentik/tsconfig": "../tsconfig",
"@types/node": "^24.10.1",
"@typescript-eslint/eslint-plugin": "^8.47.0",
"@typescript-eslint/parser": "^8.47.0",
"esbuild": "^0.27.0",
"eslint": "^9.39.1",
"pino": "^10.1.0",
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19",
"typedoc": "^0.28.12",
"typedoc-plugin-markdown": "^4.8.1",
"typescript": "^5.9.2"
"typedoc": "^0.28.14",
"typedoc-plugin-markdown": "^4.9.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"peerDependencies": {
"esbuild": "^0.25.9"
"esbuild": "^0.27.0"
},
"engines": {
"node": ">=24"
"node": ">=24",
"npm": ">=11.6.2"
},
"keywords": [
"esbuild",

View File

@@ -2,8 +2,8 @@
* @file Live reload plugin for ESBuild.
*
* @import { ListenOptions } from "node:net";
* @import {Server as HTTPServer} from "node:http";
* @import {Server as HTTPSServer} from "node:https";
* @import { Server as HTTPServer } from "node:http";
* @import { Server as HTTPSServer } from "node:https";
* @import { Logger } from "@goauthentik/esbuild-plugin-live-reload/shared";
*/
@@ -31,7 +31,7 @@ export function serializeCustomEventToStream(event) {
const eventContent = [`event: ${event.type}`, `data: ${JSON.stringify(data)}`];
return eventContent.join("\n") + "\n\n";
return `${eventContent.join("\n")}\n\n`;
}
const MIN_PORT = 1025;
@@ -123,6 +123,13 @@ export function createRequestHandler({ pathname, dispatcher, logger = createLogg
dispatcher.addEventListener("esbuild:error", listener);
dispatcher.addEventListener("esbuild:end", listener);
const keepAliveInterval = setInterval(() => {
logger.debug("🏓 Keep-alive");
res.write("event: keep-alive\n\n");
res.write(serializeCustomEventToStream(new CustomEvent("esbuild:keep-alive")));
}, 15_000);
req.on("close", () => {
logger.debug("🔌 Client disconnected");
@@ -132,13 +139,6 @@ export function createRequestHandler({ pathname, dispatcher, logger = createLogg
dispatcher.removeEventListener("esbuild:error", listener);
dispatcher.removeEventListener("esbuild:end", listener);
});
const keepAliveInterval = setInterval(() => {
logger.debug("🏓 Keep-alive");
res.write("event: keep-alive\n\n");
res.write(serializeCustomEventToStream(new CustomEvent("esbuild:keep-alive")));
}, 15_000);
};
return requestHandler;

View File

@@ -0,0 +1,12 @@
# Prettier Ignorefile
## Node
node_modules
## Static Files
**/LICENSE
## Build asset directories
coverage
dist
out

View File

@@ -0,0 +1,18 @@
/**
* @file ESLint Configuration
*
* @import { Config } from "eslint/config";
*/
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
/**
* @type {Config[]}
*/
const eslintConfig = createESLintPackageConfig({
parserOptions: {
tsconfigRootDir: import.meta.dirname,
},
});
export default eslintConfig;

View File

@@ -1,17 +1,27 @@
import eslint from "@eslint/js";
import * as litconf from "eslint-plugin-lit";
import * as wcconf from "eslint-plugin-wc";
import tseslint from "typescript-eslint";
/**
* @file ESLint Configuration Entry Point
*
* @import { Config } from "eslint/config";
* @import { ParserOptions } from "@typescript-eslint/parser";
*/
import { javaScriptConfig } from "./lib/javascript-config.js";
import { reactConfig } from "./lib/react-config.js";
import { typescriptConfig } from "./lib/typescript-config.js";
import eslint from "@eslint/js";
import { defineConfig } from "eslint/config";
import tseslint from "typescript-eslint";
// @ts-check
const litconf = await import("eslint-plugin-lit").catch(() => null);
const wcconf = await import("eslint-plugin-wc").catch(() => null);
/**
* @typedef ESLintPackageConfigOptions Options for creating package ESLint configuration.
* @property {string[]} [ignorePatterns] Override ignore patterns for ESLint.
* @property {ParserOptions} [parserOptions] Override options for TypeScript ESLint's parser.
*/
/**
@@ -39,19 +49,25 @@ export const DefaultIgnorePatterns = [
*
* @param {ESLintPackageConfigOptions} options The preferred package configuration options.
*
* @returns The ESLint configuration object.
* @returns {Config[]} The ESLint configuration object.
*/
export function createESLintPackageConfig({ ignorePatterns = DefaultIgnorePatterns } = {}) {
return tseslint.config(
export function createESLintPackageConfig({
ignorePatterns = DefaultIgnorePatterns,
parserOptions = {},
} = {}) {
return defineConfig(
{
ignores: ignorePatterns,
languageOptions: {
parserOptions,
},
},
eslint.configs.recommended,
javaScriptConfig,
wcconf.configs["flat/recommended"],
litconf.configs["flat/recommended"],
wcconf?.configs["flat/recommended"] ?? {},
litconf?.configs["flat/recommended"] ?? {},
...tseslint.configs.recommended,

View File

@@ -1,5 +1,6 @@
import { defineConfig } from "eslint/config";
// @ts-check
import tseslint from "typescript-eslint";
const MAX_DEPTH = 4;
const MAX_NESTED_CALLBACKS = 4;
@@ -8,7 +9,7 @@ const MAX_PARAMS = 5;
/**
* ESLint configuration for JavaScript authentik projects.
*/
export const javaScriptConfig = tseslint.config({
export const javaScriptConfig = defineConfig({
rules: {
// TODO: Clean up before enabling.
"accessor-pairs": "off",
@@ -68,7 +69,7 @@ export const javaScriptConfig = tseslint.config({
"no-fallthrough": "error",
"no-func-assign": "error",
"no-implied-eval": "error",
"no-implicit-coercion": "error",
"no-implicit-coercion": ["error", { allow: ["!!"] }],
"no-implicit-globals": "error",
"no-inner-declarations": ["error", "functions"],
"no-invalid-regexp": "error",

View File

@@ -1,11 +1,13 @@
import reactPlugin from "eslint-plugin-react";
import hooksPlugin from "eslint-plugin-react-hooks";
import tseslint from "typescript-eslint";
import { defineConfig } from "eslint/config";
// @ts-check
/**
* ESLint configuration for React authentik projects.
*/
export const reactConfig = tseslint.config({
export const reactConfig = defineConfig({
settings: {
react: {
version: "detect",

View File

@@ -1,10 +1,11 @@
import { defineConfig } from "eslint/config";
// @ts-check
import tseslint from "typescript-eslint";
/**
* ESLint configuration for TypeScript authentik projects.
*/
export const typescriptConfig = tseslint.config({
export const typescriptConfig = defineConfig({
rules: {
"@typescript-eslint/ban-ts-comment": [
"error",

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,14 @@
{
"name": "@goauthentik/eslint-config",
"version": "1.0.5",
"version": "1.1.0",
"description": "authentik's ESLint config",
"license": "MIT",
"scripts": {
"build": "tsc -p ."
"build": "tsc -p .",
"lint": "eslint --fix .",
"lint-check": "eslint --max-warnings 0 .",
"prettier": "prettier --cache --write -u .",
"prettier-check": "prettier --cache --check -u ."
},
"type": "module",
"exports": {
@@ -27,28 +31,35 @@
}
},
"dependencies": {
"eslint": "^9.27.0",
"eslint-plugin-import": "^2.31.0",
"eslint": "^9.39.1",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-lit": "^2.1.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.0",
"eslint-plugin-wc": "^3.0.1"
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-wc": "^3.0.2"
},
"devDependencies": {
"@goauthentik/prettier-config": "^3.1.0",
"@goauthentik/tsconfig": "^1.0.1",
"@goauthentik/prettier-config": "../prettier-config",
"@goauthentik/tsconfig": "../tsconfig",
"@types/eslint": "^9.6.1",
"typescript": "^5.8.3",
"typescript-eslint": "^8.32.1"
"@types/node": "^24.10.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.32.1"
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"engines": {
"node": ">=20.11"
"node": ">=24",
"npm": ">=11.6.2"
},
"repository": {
"type": "git",
"url": "git+https://github.com/goauthentik/authentik.git",
"directory": "packages/eslint-config"
},
"types": "./out/index.d.ts",
"files": [

View File

@@ -1,5 +1,8 @@
# Prettier Ignorefile
## Node
node_modules
## Static Files
**/LICENSE

View File

@@ -0,0 +1,30 @@
/**
* @file ESLint Configuration
*
* @import { Config } from "eslint/config";
*/
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
import { defineConfig } from "eslint/config";
// @ts-check
/**
* @type {Config[]}
*/
const eslintConfig = defineConfig(
createESLintPackageConfig({
parserOptions: {
tsconfigRootDir: import.meta.dirname,
},
}),
{
rules: {
"no-console": "off",
},
files: ["shared/**"],
},
);
export default eslintConfig;

View File

@@ -10,7 +10,7 @@ import { formatSourceFromFile } from "format-imports";
import { parsers as babelParsers } from "prettier/plugins/babel";
import { parsers as typescriptParsers } from "prettier/plugins/typescript";
const require = createRequire(process.cwd() + "/");
const require = createRequire(`${process.cwd()}/`);
const AK_KEEP_UNUSED_IMPORTS = !!process.env.AK_KEEP_UNUSED_IMPORTS;
/**
@@ -20,7 +20,7 @@ const AK_KEEP_UNUSED_IMPORTS = !!process.env.AK_KEEP_UNUSED_IMPORTS;
function resolveModule(name) {
try {
return require.resolve(name);
} catch (error) {
} catch (_error) {
return null;
}
}
@@ -61,12 +61,12 @@ function normalizeImports(filepath, input) {
[
// ---
`(?:import|from)`,
`\\\(?\\n?\\s*`,
`"(?<suffix>@goauthentik\/${submodule}\/)`,
`\\(?\\n?\\s*`,
`"(?<suffix>@goauthentik/${submodule}/)`,
`(?<path>[^"'.]+)`,
`(?:.[^"']+)?["']`,
`\\n?\\s*\\\)?;`,
`\\n?\\s*\\)?;`,
].join(""),
"gm",
);

View File

@@ -12,20 +12,77 @@
"format-imports": "^4.0.8"
},
"devDependencies": {
"@goauthentik/tsconfig": "^1.0.4",
"@eslint/js": "^9.39.1",
"@goauthentik/eslint-config": "../eslint-config",
"@goauthentik/tsconfig": "../tsconfig",
"@types/node": "^24.10.1",
"@typescript-eslint/eslint-plugin": "^8.47.0",
"@typescript-eslint/parser": "^8.47.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19",
"typescript": "^5.9.3"
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"engines": {
"node": ">=22"
"node": ">=24",
"npm": ">=11.6.2"
},
"peerDependencies": {
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19"
}
},
"../eslint-config": {
"name": "@goauthentik/eslint-config",
"version": "1.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
"eslint": "^9.39.1",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-lit": "^2.1.1",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-wc": "^3.0.2"
},
"devDependencies": {
"@goauthentik/prettier-config": "../prettier-config",
"@goauthentik/tsconfig": "../tsconfig",
"@types/eslint": "^9.6.1",
"@types/node": "^24.10.1",
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"engines": {
"node": ">=24",
"npm": ">=11.6.2"
},
"peerDependencies": {
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0",
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
}
},
"../tsconfig": {
"name": "@goauthentik/tsconfig",
"version": "1.0.5",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=24",
"npm": ">=11.6.2"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
@@ -276,15 +333,13 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@goauthentik/eslint-config": {
"resolved": "../eslint-config",
"link": true
},
"node_modules/@goauthentik/tsconfig": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.4.tgz",
"integrity": "sha512-BTGVpGh8SbCRHTULBf+2WTcw6OHJ8Ws9VtVfAMUUgcq8whbH/A7Q/n8WbkDaEeihzHUFkLk3JBenHKzEKAZWlw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20.11"
}
"resolved": "../tsconfig",
"link": true
},
"node_modules/@humanfs/core": {
"version": "0.19.1",
@@ -361,6 +416,44 @@
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"license": "MIT"
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.stat": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.walk": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@pkgr/core": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
@@ -396,6 +489,278 @@
"undici-types": "~7.16.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.47.0.tgz",
"integrity": "sha512-fe0rz9WJQ5t2iaLfdbDc9T80GJy0AeO453q8C3YCilnGozvOyCG5t+EZtg7j7D88+c3FipfP/x+wzGnh1xp8ZA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.47.0",
"@typescript-eslint/type-utils": "8.47.0",
"@typescript-eslint/utils": "8.47.0",
"@typescript-eslint/visitor-keys": "8.47.0",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.47.0",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.47.0.tgz",
"integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.47.0",
"@typescript-eslint/types": "8.47.0",
"@typescript-eslint/typescript-estree": "8.47.0",
"@typescript-eslint/visitor-keys": "8.47.0",
"debug": "^4.3.4"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.47.0.tgz",
"integrity": "sha512-2X4BX8hUeB5JcA1TQJ7GjcgulXQ+5UkNb0DL8gHsHUHdFoiCTJoYLTpib3LtSDPZsRET5ygN4qqIWrHyYIKERA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.47.0",
"@typescript-eslint/types": "^8.47.0",
"debug": "^4.3.4"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.47.0.tgz",
"integrity": "sha512-a0TTJk4HXMkfpFkL9/WaGTNuv7JWfFTQFJd6zS9dVAjKsojmv9HT55xzbEpnZoY+VUb+YXLMp+ihMLz/UlZfDg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.47.0",
"@typescript-eslint/visitor-keys": "8.47.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.47.0.tgz",
"integrity": "sha512-ybUAvjy4ZCL11uryalkKxuT3w3sXJAuWhOoGS3T/Wu+iUu1tGJmk5ytSY8gbdACNARmcYEB0COksD2j6hfGK2g==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.47.0.tgz",
"integrity": "sha512-QC9RiCmZ2HmIdCEvhd1aJELBlD93ErziOXXlHEZyuBo3tBiAZieya0HLIxp+DoDWlsQqDawyKuNEhORyku+P8A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.47.0",
"@typescript-eslint/typescript-estree": "8.47.0",
"@typescript-eslint/utils": "8.47.0",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.47.0.tgz",
"integrity": "sha512-nHAE6bMKsizhA2uuYZbEbmp5z2UpffNrPEqiKIeN7VsV6UY/roxanWfoRrf6x/k9+Obf+GQdkm0nPU+vnMXo9A==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.47.0.tgz",
"integrity": "sha512-k6ti9UepJf5NpzCjH31hQNLHQWupTRPhZ+KFF8WtTuTpy7uHPfeg2NM7cP27aCGajoEplxJDFVCEm9TGPYyiVg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.47.0",
"@typescript-eslint/tsconfig-utils": "8.47.0",
"@typescript-eslint/types": "8.47.0",
"@typescript-eslint/visitor-keys": "8.47.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.47.0.tgz",
"integrity": "sha512-g7XrNf25iL4TJOiPqatNuaChyqt49a/onq5YsJ9+hXeugK+41LVg7AxikMfM02PC6jbNtZLCJj6AUcQXJS/jGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.47.0",
"@typescript-eslint/types": "8.47.0",
"@typescript-eslint/typescript-estree": "8.47.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.47.0.tgz",
"integrity": "sha512-SIV3/6eftCy1bNzCQoPmbWsRLujS8t5iDIZ4spZOBHqrM+yfX2ogg8Tt3PDTAVKw3sSCiUgg30uOAvK2r9zGjQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.47.0",
"eslint-visitor-keys": "^4.2.1"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
"integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@vue/compiler-core": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.11.tgz",
@@ -470,6 +835,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -539,6 +905,19 @@
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
"license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/builtin-modules": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
@@ -698,6 +1077,7 @@
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz",
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1",
@@ -863,6 +1243,36 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.8"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/fast-glob/node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
"license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -875,6 +1285,16 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"license": "MIT"
},
"node_modules/fastq": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
"dev": true,
"license": "ISC",
"dependencies": {
"reusify": "^1.0.4"
}
},
"node_modules/fdir": {
"version": "6.5.0",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
@@ -905,6 +1325,19 @@
"node": ">=16.0.0"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
"license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -1029,6 +1462,13 @@
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"license": "ISC"
},
"node_modules/graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true,
"license": "MIT"
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -1114,6 +1554,16 @@
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-plain-obj": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
@@ -1243,6 +1693,43 @@
"@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"license": "MIT",
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/micromatch/node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/minimatch": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
@@ -1389,6 +1876,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -1476,6 +1964,27 @@
"node": ">=6"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT"
},
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
@@ -1485,12 +1994,47 @@
"node": ">=4"
}
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"license": "MIT",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
"node_modules/rfdc": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
"license": "MIT"
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"license": "MIT",
"dependencies": {
"queue-microtask": "^1.2.2"
}
},
"node_modules/segment-sort": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/segment-sort/-/segment-sort-1.0.9.tgz",
@@ -1681,6 +2225,32 @@
"node": ">=14.14"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/ts-api-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
"integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18.12"
},
"peerDependencies": {
"typescript": ">=4.8.4"
}
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -1698,6 +2268,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -1706,6 +2277,30 @@
"node": ">=14.17"
}
},
"node_modules/typescript-eslint": {
"version": "8.47.0",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.47.0.tgz",
"integrity": "sha512-Lwe8i2XQ3WoMjua/r1PHrCTpkubPYJCAfOurtn+mtTzqB6jNd+14n9UN1bJ4s3F49x9ixAm0FLflB/JzQ57M8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/eslint-plugin": "8.47.0",
"@typescript-eslint/parser": "8.47.0",
"@typescript-eslint/typescript-estree": "8.47.0",
"@typescript-eslint/utils": "8.47.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/undici-types": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",

View File

@@ -5,6 +5,8 @@
"license": "MIT",
"scripts": {
"build": "tsc -p .",
"lint": "eslint --fix .",
"lint-check": "eslint --max-warnings 0 .",
"prettier": "prettier --write .",
"prettier-check": "prettier --check ."
},
@@ -28,18 +30,30 @@
"format-imports": "^4.0.8"
},
"devDependencies": {
"@goauthentik/tsconfig": "^1.0.4",
"@eslint/js": "^9.39.1",
"@goauthentik/eslint-config": "../eslint-config",
"@goauthentik/tsconfig": "../tsconfig",
"@types/node": "^24.10.1",
"@typescript-eslint/eslint-plugin": "^8.47.0",
"@typescript-eslint/parser": "^8.47.0",
"eslint": "^9.39.1",
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19",
"typescript": "^5.9.3"
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0"
},
"peerDependencies": {
"prettier": "^3.6.2",
"prettier-plugin-packagejson": "^2.5.19"
},
"engines": {
"node": ">=22"
"node": ">=24",
"npm": ">=11.6.2"
},
"repository": {
"type": "git",
"url": "git+https://github.com/goauthentik/authentik.git",
"directory": "packages/prettier-config"
},
"types": "./out/index.d.ts",
"files": [

View File

@@ -1,15 +1,16 @@
{
"name": "@goauthentik/tsconfig",
"version": "1.0.4",
"version": "1.0.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@goauthentik/tsconfig",
"version": "1.0.4",
"version": "1.0.5",
"license": "MIT",
"engines": {
"node": ">=20.11"
"node": ">=24",
"npm": ">=11.6.2"
}
}
}

View File

@@ -1,19 +1,25 @@
{
"name": "@goauthentik/tsconfig",
"version": "1.0.4",
"version": "1.0.5",
"description": "authentik's base TypeScript configuration.",
"keywords": [
"tsconfig",
"typescript"
],
"license": "MIT",
"scripts": {
"build": ""
},
"type": "module",
"main": "tsconfig.json",
"type": "module",
"engines": {
"node": ">=20.11"
"node": ">=24",
"npm": ">=11.6.2"
},
"keywords": [
"tsconfig",
"typescript"
],
"repository": {
"type": "git",
"url": "git+https://github.com/goauthentik/authentik.git",
"directory": "packages/tsconfig"
},
"publishConfig": {
"access": "public"

View File

@@ -1,6 +1,6 @@
// TypeScript Project Configuration
{
"extends": "./packages/tsconfig/tsconfig.json",
"extends": "@goauthentik/tsconfig",
"compilerOptions": {
"baseUrl": "."
},

View File

@@ -1,12 +1,23 @@
# don't ever lint node_modules
# Prettier Ignorefile
## Node
node_modules
# don't lint build output (make sure it's set to your correct build folder name)
## Static Files
**/LICENSE
## Build asset directories
coverage
dist
out
# don't lint nyc coverage output
coverage
# Import order matters
src/locale-codes.ts
src/locales/
## Storybook
storybook-static/
.storybook/css-import-maps*
## Locales
src/locale-codes.ts
src/locales/
## Vendored files
*.min.js

View File

@@ -11,6 +11,7 @@ const ESLintConfig = createESLintPackageConfig({
ignorePatterns: [
"**/dist/**",
"**/out/**",
"**/vendored/**",
"**/.wireit/**",
"**/node_modules/",
"**/.storybook/*",
@@ -18,6 +19,7 @@ const ESLintConfig = createESLintPackageConfig({
"src/locale-codes.ts",
"storybook-static/",
"src/locales/",
"**/*.min.js",
],
});

6869
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -92,7 +92,7 @@
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/legacy-modes": "^6.5.2",
"@codemirror/theme-one-dark": "^6.1.3",
"@eslint/js": "^9.31.0",
"@eslint/js": "^9.39.1",
"@floating-ui/dom": "^1.7.4",
"@formatjs/intl-listformat": "^7.7.13",
"@fortawesome/fontawesome-free": "^7.1.0",
@@ -116,7 +116,7 @@
"@patternfly/elements": "^4.2.0",
"@patternfly/patternfly": "^4.224.2",
"@playwright/test": "^1.56.1",
"@sentry/browser": "^10.25.0",
"@sentry/browser": "^10.26.0",
"@storybook/addon-docs": "^10.0.8",
"@storybook/addon-links": "^10.0.8",
"@storybook/web-components": "^10.0.8",
@@ -124,26 +124,25 @@
"@types/codemirror": "^5.60.17",
"@types/grecaptcha": "^3.0.9",
"@types/guacamole-common-js": "^1.5.4",
"@types/mocha": "^10.0.10",
"@types/node": "^24.10.1",
"@types/react": "^19.2.6",
"@types/react": "^19.2.7",
"@types/react-dom": "^19.2.3",
"@typescript-eslint/eslint-plugin": "^8.38.0",
"@typescript-eslint/parser": "^8.38.0",
"@vitest/browser": "^4.0.10",
"@vitest/browser-playwright": "^4.0.10",
"@typescript-eslint/eslint-plugin": "^8.47.0",
"@typescript-eslint/parser": "^8.47.0",
"@vitest/browser": "^4.0.13",
"@vitest/browser-playwright": "^4.0.13",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"change-case": "^5.4.4",
"chart.js": "^4.5.1",
"chartjs-adapter-date-fns": "^3.0.0",
"codemirror": "^6.0.2",
"core-js": "^3.46.0",
"country-flag-icons": "^1.6.1",
"core-js": "^3.47.0",
"country-flag-icons": "^1.6.4",
"date-fns": "^4.1.0",
"deepmerge-ts": "^7.1.5",
"dompurify": "^3.3.0",
"esbuild": "^0.25.11",
"esbuild": "^0.27.0",
"esbuild-plugin-copy": "^2.1.1",
"eslint": "^9.39.1",
"eslint-plugin-lit": "^2.1.1",
@@ -152,17 +151,19 @@
"globals": "^16.5.0",
"guacamole-common-js": "^1.5.0",
"hastscript": "^9.0.1",
"knip": "^5.70.0",
"knip": "^5.70.1",
"lex": "^2025.11.0",
"lit": "^3.3.1",
"lit-analyzer": "^2.0.3",
"md-front-matter": "^1.0.4",
"mermaid": "^11.12.0",
"mermaid": "^11.12.1",
"node-domexception": "^2025.11.0",
"npm-run-all": "^4.1.5",
"pino": "^10.1.0",
"pino-pretty": "^13.1.2",
"playwright": "^1.55.1",
"prettier": "^3.6.2",
"pseudolocale": "^2.1.0",
"pseudolocale": "^2.2.0",
"rapidoc": "^9.3.8",
"react": "^19.2.0",
"react-dom": "^19.2.0",
@@ -174,7 +175,7 @@
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1",
"remark-mdx-frontmatter": "^5.2.0",
"storybook": "^10.0.3",
"storybook": "^10.0.8",
"style-mod": "^4.1.3",
"trusted-types": "^2.0.0",
"ts-pattern": "^5.9.0",
@@ -183,21 +184,20 @@
"typescript": "^5.9.3",
"typescript-eslint": "^8.47.0",
"unist-util-visit": "^5.0.0",
"vite": "^7.2.2",
"vitest": "^4.0.10",
"vite": "^7.2.4",
"vitest": "^4.0.13",
"webcomponent-qr-code": "^1.3.0",
"wireit": "^0.14.12",
"yaml": "^2.8.1"
},
"optionalDependencies": {
"@esbuild/darwin-arm64": "^0.25.4",
"@esbuild/linux-arm64": "^0.25.4",
"@esbuild/linux-x64": "^0.25.4",
"@esbuild/darwin-arm64": "^0.27.0",
"@esbuild/linux-arm64": "^0.27.0",
"@esbuild/linux-x64": "^0.27.0",
"@rollup/rollup-darwin-arm64": "^4.53.3",
"@rollup/rollup-linux-arm64-gnu": "^4.53.3",
"@rollup/rollup-linux-x64-gnu": "^4.53.3",
"chromedriver": "^141.0.4",
"p-iteration": "^1.1.8"
"chromedriver": "^142.0.3"
},
"wireit": {
"build": {
@@ -229,8 +229,7 @@
"./dist/styles/**"
],
"dependencies": [
"build-locales",
"build:sfe"
"build-locales"
],
"env": {
"NODE_RUNNER": {
@@ -294,21 +293,28 @@
}
},
"engines": {
"node": ">=24"
"node": ">=24",
"npm": ">=11.6.2"
},
"workspaces": [
"./packages/*"
],
"prettier": "@goauthentik/prettier-config",
"overrides": {
"chromedriver": {
"axios": "^1.8.4"
"@goauthentik/esbuild-plugin-live-reload": {
"esbuild": "$esbuild"
},
"@mrmarble/djangoql-completion": {
"lex": "$lex"
},
"format-imports": {
"eslint": "$eslint"
},
"node-fetch-commonjs": {
"node-domexception": "$node-domexception"
},
"rapidoc": {
"@apitools/openapi-parser@": "0.0.37"
"@apitools/openapi-parser": "0.0.37"
}
}
}

View File

@@ -1,10 +1,12 @@
/**
* @file Load the contents of an environment file into `process.env`.
*/
import { MonoRepoRoot } from "#paths/node";
import { existsSync } from "node:fs";
import { join } from "node:path";
import { MonoRepoRoot } from "#paths/node";
const envFilePath = join(MonoRepoRoot, ".env");
if (existsSync(envFilePath)) {

View File

@@ -5,9 +5,7 @@
"license": "MIT",
"private": true,
"scripts": {
"build": "tsc -p .",
"prettier": "prettier --write .",
"prettier-check": "prettier --check ."
"build": "tsc -p ."
},
"main": "index.js",
"type": "module",
@@ -45,17 +43,15 @@
}
},
"dependencies": {
"@goauthentik/prettier-config": "^3.1.0",
"@goauthentik/tsconfig": "^1.0.4",
"@types/node": "^24.10.1",
"@types/semver": "^7.7.1",
"prettier": "^3.6.2",
"semver": "^7.7.3",
"typescript": "^5.9.3"
},
"engines": {
"node": ">=24"
"node": ">=24",
"npm": ">=11.6.2"
},
"types": "./out/index.d.ts",
"prettier": "@goauthentik/prettier-config"
"types": "./out/index.d.ts"
}

View File

@@ -0,0 +1,31 @@
/**
* @file Vendored FormData polyfill.
*
* @license MIT
* @author Jimmy Warting
*
* @see https://github.com/jimmywarting/FormData/
*/
// @ts-nocheck
;(function(){var h;function l(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}}var m="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};
function n(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");}var q=n(this);function r(a,b){if(b)a:{var c=q;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&m(c,a,{configurable:!0,writable:!0,value:b})}}
r("Symbol",function(a){function b(f){if(this instanceof b)throw new TypeError("Symbol is not a constructor");return new c(d+(f||"")+"_"+e++,f)}function c(f,g){this.A=f;m(this,"description",{configurable:!0,writable:!0,value:g})}if(a)return a;c.prototype.toString=function(){return this.A};var d="jscomp_symbol_"+(1E9*Math.random()>>>0)+"_",e=0;return b});
r("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");for(var b="Array Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array".split(" "),c=0;c<b.length;c++){var d=q[b[c]];"function"===typeof d&&"function"!=typeof d.prototype[a]&&m(d.prototype,a,{configurable:!0,writable:!0,value:function(){return u(l(this))}})}return a});function u(a){a={next:a};a[Symbol.iterator]=function(){return this};return a}
function v(a){var b="undefined"!=typeof Symbol&&Symbol.iterator&&a[Symbol.iterator];return b?b.call(a):{next:l(a)}}var w;if("function"==typeof Object.setPrototypeOf)w=Object.setPrototypeOf;else{var y;a:{var z={a:!0},A={};try{A.__proto__=z;y=A.a;break a}catch(a){}y=!1}w=y?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}var B=w;function C(){this.m=!1;this.j=null;this.v=void 0;this.h=1;this.u=this.C=0;this.l=null}
function D(a){if(a.m)throw new TypeError("Generator is already running");a.m=!0}C.prototype.o=function(a){this.v=a};C.prototype.s=function(a){this.l={D:a,F:!0};this.h=this.C||this.u};C.prototype.return=function(a){this.l={return:a};this.h=this.u};function E(a,b){a.h=3;return{value:b}}function F(a){this.g=new C;this.G=a}F.prototype.o=function(a){D(this.g);if(this.g.j)return G(this,this.g.j.next,a,this.g.o);this.g.o(a);return H(this)};
function I(a,b){D(a.g);var c=a.g.j;if(c)return G(a,"return"in c?c["return"]:function(d){return{value:d,done:!0}},b,a.g.return);a.g.return(b);return H(a)}F.prototype.s=function(a){D(this.g);if(this.g.j)return G(this,this.g.j["throw"],a,this.g.o);this.g.s(a);return H(this)};
function G(a,b,c,d){try{var e=b.call(a.g.j,c);if(!(e instanceof Object))throw new TypeError("Iterator result "+e+" is not an object");if(!e.done)return a.g.m=!1,e;var f=e.value}catch(g){return a.g.j=null,a.g.s(g),H(a)}a.g.j=null;d.call(a.g,f);return H(a)}function H(a){for(;a.g.h;)try{var b=a.G(a.g);if(b)return a.g.m=!1,{value:b.value,done:!1}}catch(c){a.g.v=void 0,a.g.s(c)}a.g.m=!1;if(a.g.l){b=a.g.l;a.g.l=null;if(b.F)throw b.D;return{value:b.return,done:!0}}return{value:void 0,done:!0}}
function J(a){this.next=function(b){return a.o(b)};this.throw=function(b){return a.s(b)};this.return=function(b){return I(a,b)};this[Symbol.iterator]=function(){return this}}function K(a,b){b=new J(new F(b));B&&a.prototype&&B(b,a.prototype);return b}function L(a,b){a instanceof String&&(a+="");var c=0,d=!1,e={next:function(){if(!d&&c<a.length){var f=c++;return{value:b(f,a[f]),done:!1}}d=!0;return{done:!0,value:void 0}}};e[Symbol.iterator]=function(){return e};return e}
r("Array.prototype.entries",function(a){return a?a:function(){return L(this,function(b,c){return[b,c]})}});
if("undefined"!==typeof Blob&&("undefined"===typeof FormData||!FormData.prototype.keys)){var M=function(a,b){for(var c=0;c<a.length;c++)b(a[c])},N=function(a){return a.replace(/\r?\n|\r/g,"\r\n")},O=function(a,b,c){if(b instanceof Blob){c=void 0!==c?String(c+""):"string"===typeof b.name?b.name:"blob";if(b.name!==c||"[object Blob]"===Object.prototype.toString.call(b))b=new File([b],c);return[String(a),b]}return[String(a),String(b)]},P=function(a,b){if(a.length<b)throw new TypeError(b+" argument required, but only "+
a.length+" present.");},Q="object"===typeof globalThis?globalThis:"object"===typeof window?window:"object"===typeof self?self:this,R=Q.FormData,S=Q.XMLHttpRequest&&Q.XMLHttpRequest.prototype.send,T=Q.Request&&Q.fetch,U=Q.navigator&&Q.navigator.sendBeacon,V=Q.Element&&Q.Element.prototype,W=Q.Symbol&&Symbol.toStringTag;W&&(Blob.prototype[W]||(Blob.prototype[W]="Blob"),"File"in Q&&!File.prototype[W]&&(File.prototype[W]="File"));try{new File([],"")}catch(a){Q.File=function(b,c,d){b=new Blob(b,d||{});
Object.defineProperties(b,{name:{value:c},lastModified:{value:+(d&&void 0!==d.lastModified?new Date(d.lastModified):new Date)},toString:{value:function(){return"[object File]"}}});W&&Object.defineProperty(b,W,{value:"File"});return b}}var escape=function(a){return a.replace(/\n/g,"%0A").replace(/\r/g,"%0D").replace(/"/g,"%22")},X=function(a){this.i=[];var b=this;a&&M(a.elements,function(c){if(c.name&&!c.disabled&&"submit"!==c.type&&"button"!==c.type&&!c.matches("form fieldset[disabled] *"))if("file"===
c.type){var d=c.files&&c.files.length?c.files:[new File([],"",{type:"application/octet-stream"})];M(d,function(e){b.append(c.name,e)})}else"select-multiple"===c.type||"select-one"===c.type?M(c.options,function(e){!e.disabled&&e.selected&&b.append(c.name,e.value)}):"checkbox"===c.type||"radio"===c.type?c.checked&&b.append(c.name,c.value):(d="textarea"===c.type?N(c.value):c.value,b.append(c.name,d))})};h=X.prototype;h.append=function(a,b,c){P(arguments,2);this.i.push(O(a,b,c))};h.delete=function(a){P(arguments,
1);var b=[];a=String(a);M(this.i,function(c){c[0]!==a&&b.push(c)});this.i=b};h.entries=function b(){var c,d=this;return K(b,function(e){1==e.h&&(c=0);if(3!=e.h)return c<d.i.length?e=E(e,d.i[c]):(e.h=0,e=void 0),e;c++;e.h=2})};h.forEach=function(b,c){P(arguments,1);for(var d=v(this),e=d.next();!e.done;e=d.next()){var f=v(e.value);e=f.next().value;f=f.next().value;b.call(c,f,e,this)}};h.get=function(b){P(arguments,1);var c=this.i;b=String(b);for(var d=0;d<c.length;d++)if(c[d][0]===b)return c[d][1];
return null};h.getAll=function(b){P(arguments,1);var c=[];b=String(b);M(this.i,function(d){d[0]===b&&c.push(d[1])});return c};h.has=function(b){P(arguments,1);b=String(b);for(var c=0;c<this.i.length;c++)if(this.i[c][0]===b)return!0;return!1};h.keys=function c(){var d=this,e,f,g,k,p;return K(c,function(t){1==t.h&&(e=v(d),f=e.next());if(3!=t.h){if(f.done){t.h=0;return}g=f.value;k=v(g);p=k.next().value;return E(t,p)}f=e.next();t.h=2})};h.set=function(c,d,e){P(arguments,2);c=String(c);var f=[],g=O(c,
d,e),k=!0;M(this.i,function(p){p[0]===c?k&&(k=!f.push(g)):f.push(p)});k&&f.push(g);this.i=f};h.values=function d(){var e=this,f,g,k,p,t;return K(d,function(x){1==x.h&&(f=v(e),g=f.next());if(3!=x.h){if(g.done){x.h=0;return}k=g.value;p=v(k);p.next();t=p.next().value;return E(x,t)}g=f.next();x.h=2})};X.prototype._asNative=function(){for(var d=new R,e=v(this),f=e.next();!f.done;f=e.next()){var g=v(f.value);f=g.next().value;g=g.next().value;d.append(f,g)}return d};X.prototype._blob=function(){var d="----formdata-polyfill-"+
Math.random(),e=[],f="--"+d+'\r\nContent-Disposition: form-data; name="';this.forEach(function(g,k){return"string"==typeof g?e.push(f+escape(N(k))+('"\r\n\r\n'+N(g)+"\r\n")):e.push(f+escape(N(k))+('"; filename="'+escape(g.name)+'"\r\nContent-Type: '+(g.type||"application/octet-stream")+"\r\n\r\n"),g,"\r\n")});e.push("--"+d+"--");return new Blob(e,{type:"multipart/form-data; boundary="+d})};X.prototype[Symbol.iterator]=function(){return this.entries()};X.prototype.toString=function(){return"[object FormData]"};
V&&!V.matches&&(V.matches=V.matchesSelector||V.mozMatchesSelector||V.msMatchesSelector||V.oMatchesSelector||V.webkitMatchesSelector||function(d){d=(this.document||this.ownerDocument).querySelectorAll(d);for(var e=d.length;0<=--e&&d.item(e)!==this;);return-1<e});W&&(X.prototype[W]="FormData");if(S){var Y=Q.XMLHttpRequest.prototype.setRequestHeader;Q.XMLHttpRequest.prototype.setRequestHeader=function(d,e){Y.call(this,d,e);"content-type"===d.toLowerCase()&&(this.B=!0)};Q.XMLHttpRequest.prototype.send=
function(d){d instanceof X?(d=d._blob(),this.B||this.setRequestHeader("Content-Type",d.type),S.call(this,d)):S.call(this,d)}}T&&(Q.fetch=function(d,e){e&&e.body&&e.body instanceof X&&(e.body=e.body._blob());return T.call(this,d,e)});U&&(Q.navigator.sendBeacon=function(d,e){e instanceof X&&(e=e._asNative());return U.call(this,d,e)});Q.FormData=X};})();

View File

@@ -0,0 +1,9 @@
{
"name": "formdata-polyfill",
"version": "2025.11.0",
"description": "Vendored FormData polyfill.",
"license": "MIT",
"private": true,
"main": "index.min.js",
"type": "commonjs"
}

237
web/packages/lex/index.js Normal file
View File

@@ -0,0 +1,237 @@
/**
* @file Vendored Lexer Implementation
*
* @license MIT
* @author Aadit M Shah <aaditmshah@fastmail.fm>
* @see https://github.com/aaditmshah/lexer/tree/master
*/
/**
* @typedef {(this: Lexer, chr: string) => any} DefunctFunction
*/
/**
* @typedef {(this: Lexer, ...args: RegExpExecArray) => string | string[] | undefined} RuleAction
*/
/**
* @typedef {Object} Rule
* @property {RegExp} pattern
* @property {boolean} global
* @property {RuleAction} action
* @property {number[]} start
*/
/**
* @typedef {Object} Match
* @property {RegExpExecArray} result
* @property {RuleAction} action
* @property {number} length
*/
/**
* Lexer class for tokenizing input strings.
*/
export class Lexer {
/**
* @type {string[]}
*/
tokens = [];
/**
* @type {Rule[]}
*/
rules = [];
/**
* @type {number}
*/
remove = 0;
/**
* @type {number}
*/
state = 0;
/**
* @type {number}
*/
index = 0;
/**
* @type {string}
*/
input = "";
/**
* @param {DefunctFunction} [defunct]
*/
constructor(defunct) {
defunct ||= function (chr) {
throw new Error("Unexpected character at index " + (this.index - 1) + ": " + chr);
};
this.defunct = defunct;
}
/**
* Add a lexing rule.
*
* @param {RegExp} pattern
* @param {RuleAction} action
* @param {number[]} [start]
* @returns {Lexer}
*/
addRule = (pattern, action, start) => {
const global = pattern.global;
if (!global || !pattern.sticky) {
let flags = "gy";
if (pattern.multiline) flags += "m";
if (pattern.ignoreCase) flags += "i";
if (pattern.unicode) flags += "u";
pattern = new RegExp(pattern.source, flags);
}
if (!Array.isArray(start)) start = [0];
this.rules.push({
pattern: pattern,
global: global,
action: action,
start: start,
});
return this;
};
/**
* Set the input string for lexing.
*
* @param {string} input
* @returns {Lexer}
*/
setInput = (input) => {
this.remove = 0;
this.state = 0;
this.index = 0;
this.tokens.length = 0;
this.input = input;
return this;
};
/**
* Lex the next token from the input.
*
* @returns {string | string[] | undefined}
*/
lex = () => {
if (this.tokens.length) return this.tokens.shift();
this.reject = true;
while (this.index <= this.input.length) {
const matches = this.scan().splice(this.remove);
const index = this.index;
while (matches.length) {
if (!this.reject) {
break;
}
const match = matches.shift();
if (!match) break;
const result = match.result;
const length = match.length;
this.index += length;
this.reject = false;
this.remove++;
let token = match.action.apply(this, result);
if (this.reject) {
this.index = result.index;
} else if (Array.isArray(token)) {
this.tokens = token.slice(1);
token = token[0];
} else {
if (length) this.remove = 0;
return token;
}
}
const input = this.input;
if (index < input.length) {
if (this.reject) {
this.remove = 0;
const token = this.defunct(input.charAt(this.index++));
if (typeof token !== "undefined") {
if (Array.isArray(token)) {
this.tokens = token.slice(1);
return token[0];
} else return token;
}
} else {
if (this.index !== index) this.remove = 0;
this.reject = true;
}
} else if (matches.length) this.reject = true;
else break;
}
};
/**
* Scan the input for matches.
*
* @returns {Match[]}
*/
scan = () => {
/**
* @type {Match[]}
*/
const matches = [];
let index = 0;
const state = this.state;
const lastIndex = this.index;
const input = this.input;
for (let i = 0, length = this.rules.length; i < length; i++) {
const rule = this.rules[i];
const start = rule.start;
const states = start.length;
if (!states || start.indexOf(state) >= 0 || (state % 2 && states === 1 && !start[0])) {
const pattern = rule.pattern;
pattern.lastIndex = lastIndex;
const result = pattern.exec(input);
if (!result || result.index !== lastIndex) {
continue;
}
let j = matches.push({
result: result,
action: rule.action,
length: result[0].length,
});
if (rule.global) {
index = j;
}
while (--j > index) {
const k = j - 1;
if (matches[j].length > matches[k].length) {
const temple = matches[j];
matches[j] = matches[k];
matches[k] = temple;
}
}
}
}
return matches;
};
}
export default Lexer;

View File

@@ -0,0 +1,13 @@
{
"name": "lex",
"version": "2025.11.0",
"description": "Vendored Lexer",
"license": "MIT",
"private": true,
"type": "module",
"exports": {
".": {
"import": "./index.js"
}
}
}

View File

@@ -0,0 +1,17 @@
/**
* @file Vendored DOMException for Node.js environments.
*
* @author Jimmy Wärting
* @license MIT
* @see https://github.com/jimmywarting/node-domexception
*/
globalThis.DOMException ??= (() => {
try {
// @ts-expect-error Trigger a DOMException to get its constructor.
atob(0);
} catch (err) {
// @ts-expect-error unknown type
return err.constructor;
}
})();

View File

@@ -0,0 +1,9 @@
{
"name": "node-domexception",
"version": "2025.11.0",
"description": "Vendored DOMException implementation for Node.js",
"license": "MIT",
"private": true,
"main": "index.cjs",
"type": "commonjs"
}

View File

@@ -9,6 +9,10 @@
"prettier-check": "prettier --cache --check -u .",
"watch": "rollup -w -c rollup.config.mjs --bundleConfigAsCjs"
},
"type": "module",
"exports": {
"./package.json": "./package.json"
},
"dependencies": {
"@goauthentik/api": "^2025.10.0-rc1-1760106928",
"@goauthentik/core": "^1.0.0",
@@ -17,26 +21,25 @@
"@rollup/plugin-swc": "^0.4.0",
"@swc/cli": "^0.7.9",
"@swc/core": "^1.15.3",
"@trivago/prettier-plugin-sort-imports": "^6.0.0",
"base64-js": "^1.5.1",
"bootstrap": "^4.6.2",
"formdata-polyfill": "^4.0.10",
"bootstrap": "^5.3.8",
"formdata-polyfill": "^2025.11.0",
"globby": "16.0.0",
"jquery": "^3.7.1",
"prettier": "^3.5.3",
"rollup": "^4.53.3",
"rollup-plugin-copy": "^3.5.0",
"weakmap-polyfill": "^2.0.4"
},
"optionalDependencies": {
"@swc/core-darwin-arm64": "^1.6.13",
"@swc/core-darwin-x64": "^1.6.13",
"@swc/core-linux-arm-gnueabihf": "^1.6.13",
"@swc/core-linux-arm64-gnu": "^1.6.13",
"@swc/core-linux-arm64-musl": "^1.6.13",
"@swc/core-linux-x64-gnu": "^1.6.13",
"@swc/core-linux-x64-musl": "^1.6.13",
"@swc/core-win32-arm64-msvc": "^1.6.13",
"@swc/core-win32-ia32-msvc": "^1.6.13",
"@swc/core-win32-x64-msvc": "^1.6.13"
"@swc/core-darwin-arm64": "^1.15.3",
"@swc/core-darwin-x64": "^1.15.3",
"@swc/core-linux-arm-gnueabihf": "^1.15.3",
"@swc/core-linux-arm64-gnu": "^1.15.3",
"@swc/core-linux-arm64-musl": "^1.15.3",
"@swc/core-linux-x64-gnu": "^1.15.3",
"@swc/core-linux-x64-musl": "^1.15.3",
"@swc/core-win32-arm64-msvc": "^1.15.3",
"@swc/core-win32-ia32-msvc": "^1.15.3",
"@swc/core-win32-x64-msvc": "^1.15.3"
}
}

View File

@@ -1,20 +1,46 @@
import { resolve as resolvePath } from "node:path";
/**
* @file Rollup configuration for the SFE package.
* @import { Plugin, RollupOptions } from "rollup";
*/
import * as fs from "node:fs/promises";
import { join } from "node:path";
import commonjs from "@rollup/plugin-commonjs";
import resolve from "@rollup/plugin-node-resolve";
import swc from "@rollup/plugin-swc";
import copy from "rollup-plugin-copy";
export async function createConfig() {
// TODO: Move this to a synchronous import once the repo root has NPM Workspaces.
// Rollup's CJS to ESM conversion doesn't work well with sub-dependencies.
// We use an async import to fix the issue.
const { resolvePackage, MonoRepoRoot } = await import("@goauthentik/core/paths/node");
const distDirectory = resolvePath(MonoRepoRoot, "web", "dist", "sfe");
const distDirectory = join(MonoRepoRoot, "web", "dist", "sfe");
const bootstrapDirectory = resolvePackage("bootstrap", import.meta);
/**
* @type {Plugin} A plugin to copy static assets.
*/
const copyPlugin = {
name: "copy-static-assets",
buildEnd: async () => {
console.log("Copying static assets...");
const bootstrapCSSFilePath = join(
bootstrapDirectory,
"dist",
"css",
"bootstrap.min.css",
);
await fs.mkdir(distDirectory, { recursive: true });
await fs.copyFile(bootstrapCSSFilePath, join(distDirectory, "bootstrap.min.css"));
},
};
/**
* @type {RollupOptions}
*/
const config = {
input: "src/index.ts",
output: {
@@ -23,14 +49,7 @@ export async function createConfig() {
},
context: "window",
plugins: [
copy({
targets: [
{
src: resolvePath(bootstrapDirectory, "dist", "css", "bootstrap.min.css"),
dest: distDirectory,
},
],
}),
copyPlugin,
resolve({ browser: true }),
commonjs(),
swc({

View File

@@ -1,5 +1,8 @@
{
"compilerOptions": {
"rootDir": ".",
"moduleResolution": "bundler",
"module": "preserve",
"noEmit": true,
"baseUrl": ".",
"outDir": "out",

View File

@@ -33,9 +33,6 @@ ak-sidebar::part(about-dialog-trigger) {
--pf-c-button--m-plain--hover--Color: var(--pf-c-nav__link--Color);
}
ak-sidebar-item::part(list-item) {
}
ak-sidebar-item:active ak-sidebar-item::part(list-item),
ak-sidebar-item:hover ak-sidebar-item::part(list-item) {
--pf-c-nav__link--after--BorderColor: var(--pf-global--BorderColor--200);

View File

@@ -18,6 +18,7 @@ import {
import { isAPIResultReady } from "#common/api/responses";
import { EVENT_API_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE } from "#common/constants";
import { configureSentry } from "#common/sentry/index";
import { isGuest } from "#common/users";
import { WebsocketClient } from "#common/ws";
import { AuthenticatedInterface } from "#elements/AuthenticatedInterface";
@@ -136,8 +137,8 @@ export class AdminInterface extends WithCapabilitiesConfig(WithSession(Authentic
public override updated(changedProperties: PropertyValues<this>): void {
super.updated(changedProperties);
if (changedProperties.has("session")) {
if (isAPIResultReady(this.session) && !canAccessAdmin(this.session.user)) {
if (changedProperties.has("session") && isAPIResultReady(this.session)) {
if (!isGuest(this.session.user) && !canAccessAdmin(this.session.user)) {
window.location.assign("/if/user/");
}
}

View File

@@ -11,20 +11,19 @@ import "#admin/admin-overview/charts/SyncStatusChart";
import "#elements/cards/AggregatePromiseCard";
import "#elements/cards/QuickActionsCard";
import { me } from "#common/users";
import { formatUserDisplayName } from "#common/users";
import { AKElement } from "#elements/Base";
import type { QuickAction } from "#elements/cards/QuickActionsCard";
import { WithLicenseSummary } from "#elements/mixins/license";
import { WithSession } from "#elements/mixins/session";
import { paramURL } from "#elements/router/RouterOutlet";
import { setPageDetails } from "#components/ak-page-navbar";
import { SessionUser } from "@goauthentik/api";
import { msg, str } from "@lit/localize";
import { css, CSSResult, html, nothing, PropertyValues, TemplateResult } from "lit";
import { customElement, state } from "lit/decorators.js";
import { customElement } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import PFContent from "@patternfly/patternfly/components/Content/content.css";
@@ -33,7 +32,7 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
const AdminOverviewBase = WithLicenseSummary(AKElement);
const AdminOverviewBase = WithLicenseSummary(WithSession(AKElement));
@customElement("ak-admin-overview")
export class AdminOverviewPage extends AdminOverviewBase {
@@ -71,13 +70,6 @@ export class AdminOverviewPage extends AdminOverviewBase {
[msg("Check the release notes"), import.meta.env.AK_DOCS_RELEASE_NOTES_URL, true],
];
@state()
user?: SessionUser;
async firstUpdated(): Promise<void> {
this.user = await me();
}
render(): TemplateResult {
return html` <main class="pf-c-page__main-section" aria-label=${msg("Overview")}>
<div class="pf-l-grid pf-m-gutter">
@@ -169,9 +161,10 @@ export class AdminOverviewPage extends AdminOverviewBase {
updated(changed: PropertyValues<this>) {
super.updated(changed);
const username = this.user?.user.name || this.user?.user.username;
const displayName = formatUserDisplayName(this.currentUser);
setPageDetails({
header: username ? msg(str`Welcome, ${username}`) : msg("Welcome"),
header: displayName ? msg(str`Welcome, ${displayName}`) : msg("Welcome"),
description: msg("General system status"),
});
}

View File

@@ -35,6 +35,7 @@ import PFContent from "@patternfly/patternfly/components/Content/content.css";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import PFList from "@patternfly/patternfly/components/List/list.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
@@ -49,6 +50,7 @@ export class ApplicationViewPage extends AKElement {
PFButton,
PFDescriptionList,
PFGrid,
PFFlex,
PFCard,
];
@@ -129,9 +131,25 @@ export class ApplicationViewPage extends AKElement {
return html`<main>
<ak-tabs>
${this.missingOutpost
? html`<div slot="header" class="pf-c-banner pf-m-warning">
${msg("Warning: Application is not used by any Outpost.")}
</div>`
? html`
<div
slot="header"
class="pf-c-banner pf-m-warning"
role="status"
aria-live="polite"
>
<div class="pf-l-flex pf-m-space-items-sm">
<div class="pf-l-flex__item">
<i class="fas fa-exclamation-triangle" aria-hidden="true"></i>
</div>
<div class="pf-l-flex__item">
${msg("Warning: Application is not used by any Outpost.", {
id: "application.outpost.missing.warning",
})}
</div>
</div>
</div>
`
: nothing}
<section
role="tabpanel"
@@ -326,11 +344,29 @@ export class ApplicationViewPage extends AKElement {
id="page-app-entitlements"
aria-label="${msg("Application entitlements")}"
>
<div slot="header" class="pf-c-banner pf-m-info">
${msg("Application entitlements are in preview.")}
<a href="mailto:hello+feature/app-ent@goauthentik.io"
>${msg("Send us feedback!")}</a
>
<div
slot="header"
class="pf-c-banner pf-m-info"
role="status"
aria-live="polite"
>
<div class="pf-l-flex pf-m-space-items-sm">
<div class="pf-l-flex__item">
<i class="fas fa-info-circle" aria-hidden="true"></i>
</div>
<div class="pf-l-flex__item">
${msg("Application entitlements are in preview.", {
id: "application.entitlements.preview.info",
})}
</div>
<div class="pf-l-flex__item">
<a href="mailto:hello+feature/app-ent@goauthentik.io"
>${msg("Send us feedback!", {
id: "preview.send-us-feedback",
})}</a
>
</div>
</div>
</div>
<div class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card">

View File

@@ -16,7 +16,6 @@ import { DEFAULT_CONFIG } from "#common/api/config";
import { PFSize } from "#common/enums";
import { parseAPIResponseError, pluckErrorDetail } from "#common/errors/network";
import { MessageLevel } from "#common/messages";
import { me } from "#common/users";
import { Form } from "#elements/forms/Form";
import { showMessage } from "#elements/messages/MessageContainer";
@@ -29,7 +28,7 @@ import { UserOption } from "#elements/user/utils";
import { AKLabel } from "#components/ak-label";
import { CoreApi, CoreUsersListTypeEnum, Group, SessionUser, User } from "@goauthentik/api";
import { CoreApi, CoreUsersListTypeEnum, Group, User } from "@goauthentik/api";
import { msg, str } from "@lit/localize";
import { CSSResult, html, nothing, TemplateResult } from "lit";
@@ -142,9 +141,6 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl
@property({ type: Boolean })
hideServiceAccounts = getURLParam<boolean>("hideServiceAccounts", true);
@state()
me?: SessionUser;
static styles: CSSResult[] = [...Table.styles, PFDescriptionList, PFAlert, PFBanner];
async apiEndpoint(): Promise<PaginatedResponse<User>> {
@@ -156,7 +152,7 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl
: undefined,
includeGroups: false,
});
this.me = await me();
return users;
}
@@ -205,7 +201,7 @@ export class RelatedUserList extends WithBrandConfig(WithCapabilitiesConfig(Tabl
row(item: User): SlottedTemplateResult[] {
const canImpersonate =
this.can(CapabilitiesEnum.CanImpersonate) && item.pk !== this.me?.user.pk;
this.can(CapabilitiesEnum.CanImpersonate) && item.pk !== this.currentUser?.pk;
return [
html`<a href="#/identity/users/${item.pk}">
<div>${item.username}</div>

View File

@@ -29,10 +29,10 @@ import { DEFAULT_CONFIG } from "#common/api/config";
import { EVENT_REFRESH } from "#common/constants";
import { PFSize } from "#common/enums";
import { userTypeToLabel } from "#common/labels";
import { me } from "#common/users";
import { AKElement } from "#elements/Base";
import { WithCapabilitiesConfig } from "#elements/mixins/capabilities";
import { WithSession } from "#elements/mixins/session";
import { Timestamp } from "#elements/table/shared";
import { setPageDetails } from "#components/ak-page-navbar";
@@ -44,7 +44,6 @@ import {
CapabilitiesEnum,
CoreApi,
RbacPermissionsAssignedByUsersListModelEnum,
SessionUser,
User,
} from "@goauthentik/api";
@@ -65,26 +64,20 @@ import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css";
import PFSizing from "@patternfly/patternfly/utilities/Sizing/sizing.css";
@customElement("ak-user-view")
export class UserViewPage extends WithCapabilitiesConfig(AKElement) {
export class UserViewPage extends WithCapabilitiesConfig(WithSession(AKElement)) {
@property({ type: Number })
set userId(id: number) {
me().then((me) => {
this.me = me;
new CoreApi(DEFAULT_CONFIG)
.coreUsersRetrieve({
id: id,
})
.then((user) => {
this.user = user;
});
});
new CoreApi(DEFAULT_CONFIG)
.coreUsersRetrieve({
id: id,
})
.then((user) => {
this.user = user;
});
}
@property({ attribute: false })
user?: User;
@state()
me?: SessionUser;
protected user: User | null = null;
static styles = [
PFBase,
@@ -159,7 +152,7 @@ export class UserViewPage extends WithCapabilitiesConfig(AKElement) {
renderActionButtons(user: User) {
const canImpersonate =
this.can(CapabilitiesEnum.CanImpersonate) && user.pk !== this.me?.user.pk;
this.can(CapabilitiesEnum.CanImpersonate) && user.pk !== this.currentUser?.pk;
return html`<div class="ak-button-collection">
<ak-forms-modal>

View File

@@ -15,15 +15,15 @@ export interface ClientSessionPermissions {
/**
* The display name of the current user, according to their UI config settings.
*/
export function formatUserDisplayName(user: UserSelf | null, uiConfig: UIConfig): string {
export function formatUserDisplayName(user: UserSelf | null, uiConfig?: UIConfig): string {
if (!user) return "";
const label = match(uiConfig.navbar.userDisplay)
const label = match(uiConfig?.navbar.userDisplay)
.with(UserDisplay.username, () => user.username)
.with(UserDisplay.name, () => user.name)
.with(UserDisplay.email, () => user.email)
.with(UserDisplay.none, () => null)
.otherwise(() => user.username);
.otherwise(() => user.name || user.username);
return label || "";
}
@@ -63,6 +63,8 @@ let memoizedSession: SessionUser | null = null;
/**
* Refresh the current user session.
*
* @deprecated This should be moved to the WithSession mixin.
*/
export function refreshMe(): Promise<SessionUser> {
memoizedSession = null;
@@ -75,6 +77,8 @@ export function refreshMe(): Promise<SessionUser> {
* This is a memoized function, so it will only make one request per page load.
*
* @see {@linkcode refreshMe} to force a refresh.
*
* @category Session
*/
export async function me(requestInit?: RequestInit): Promise<SessionUser> {
if (memoizedSession) return memoizedSession;
@@ -103,16 +107,7 @@ export async function me(requestInit?: RequestInit): Promise<SessionUser> {
const { response } = error;
if (response.status === 401 || response.status === 403) {
const { pathname, search, hash } = window.location;
const authFlowRedirectURL = new URL(
`/flows/-/default/authentication/`,
window.location.origin,
);
authFlowRedirectURL.searchParams.set("next", `${pathname}${search}${hash}`);
window.location.assign(authFlowRedirectURL);
redirectToAuthFlow();
}
}
@@ -125,3 +120,31 @@ export async function me(requestInit?: RequestInit): Promise<SessionUser> {
return nextSession;
});
}
let pendingRedirect = false;
/**
* Redirect to the default authentication flow, preserving the current URL as "next" parameter.
*
* @category Session
*/
export function redirectToAuthFlow(nextPathname = "/flows/-/default/authentication/"): void {
if (pendingRedirect) {
console.debug("authentik/users: Redirect already pending, ");
return;
}
const { pathname, search, hash } = window.location;
const authFlowRedirectURL = new URL(nextPathname, window.location.origin);
authFlowRedirectURL.searchParams.set("next", `${pathname}${search}${hash}`);
pendingRedirect = true;
console.debug(
`authentik/users: Redirecting to authentication flow at ${authFlowRedirectURL.href}`,
);
window.location.assign(authFlowRedirectURL);
}

View File

@@ -218,6 +218,28 @@ export class QLSearch extends FormAssociatedElement<string> implements FormAssoc
//#region Completions
#selectCompletion(index: number) {
if (!this.#ql) {
console.debug(`authentik/ql: Skipping selection of index ${index}, QL not initialized`);
return;
}
try {
this.#ql.selectCompletion(index);
} catch (error) {
if (error instanceof TypeError && error.message.includes("convert")) {
console.warn(
`authentik/ql: Failed to select invalid completion at index ${index}`,
error.message,
);
return;
}
console.warn(`authentik/ql: Failed to select completion at index ${index}:`, error);
}
}
#refreshCompletions = () => {
if (this.anchor) {
this.value = this.anchor.value;
@@ -350,7 +372,7 @@ export class QLSearch extends FormAssociatedElement<string> implements FormAssoc
case "Tab":
if (this.selectionIndex) {
this.#ql?.selectCompletion(this.selectionIndex);
this.#selectCompletion(this.selectionIndex);
event.preventDefault();
}
@@ -361,7 +383,7 @@ export class QLSearch extends FormAssociatedElement<string> implements FormAssoc
// So expected behavior when pressing Enter is to submit the form,
// not to add a new line.
if (this.selectionIndex !== -1) {
this.#ql?.selectCompletion(this.selectionIndex);
this.#selectCompletion(this.selectionIndex);
this.selectionIndex = 0;
}
@@ -426,7 +448,7 @@ export class QLSearch extends FormAssociatedElement<string> implements FormAssoc
type="button"
aria-label=${label}
@click=${() => {
this.#ql?.selectCompletion(idx);
this.#selectCompletion(idx);
this.#refreshCompletions();
}}
>

View File

@@ -3,12 +3,11 @@ import type { SlottedTemplateResult, Spread } from "#elements/types";
import { spread } from "@open-wc/lit-helpers";
import { css, html, nothing } from "lit";
import { html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import PFLabel from "@patternfly/patternfly/components/Label/label.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
export enum PFColor {
Green = "pf-m-green",
@@ -47,18 +46,7 @@ export class Label extends AKElement implements ILabel {
@property({ type: Boolean })
compact = false;
static styles = [
PFBase,
PFLabel,
css`
:host([theme="dark"]) {
.pf-m-grey {
--pf-c-label__icon--Color: var(--ak-dark-background);
--pf-c-label__content--Color: var(--ak-dark-background);
}
}
`,
];
static styles = [PFLabel];
get classesAndIcon() {
const chrome = chromeList.find(

View File

@@ -15,6 +15,10 @@
.pf-c-tabs .pf-c-tabs__list::before {
border-color: transparent;
}
.pf-c-tabs__link {
--pf-c-tabs__link--before--BorderRightWidth: 0;
}
}
.pf-c-tabs {
@@ -59,8 +63,4 @@ ak-tabs[vertical] {
.pf-c-tabs__link {
--pf-c-tabs__link--Color: var(--pf-global--Color--100);
&::before {
border-color: transparent;
}
}

View File

@@ -7,21 +7,25 @@
--ak-c-nav__item--BorderColor: var(--pf-global--BorderColor--100);
--pf-c-nav__subnav__link--hover--after--BorderColor: var(--pf-global--palette--orange-400);
--pf-c-nav__link--xl--PaddingLeft: var(--pf-global--spacer--md);
--pf-c-nav__link--hover--before--BorderBottomWidth: 1px;
--pf-c-nav__link--before--BorderColor: transparent;
--pf-c-nav__link--PaddingTop: 0.5rem;
--pf-c-nav__link--PaddingRight: 0.5rem;
--pf-c-nav__link--PaddingBottom: 0.5rem;
--pf-c-nav__subnav__link--PaddingLeft: var(--pf-global--spacer--md);
--pf-c-nav__link--PaddingTop: var(--pf-global--spacer--sm);
--pf-c-nav__link--PaddingRight: var(--pf-global--spacer--sm);
--pf-c-nav__link--PaddingBottom: var(--pf-global--spacer--sm);
--pf-c-nav__subnav__link--PaddingLeft: var(--pf-global--spacer--md);
--pf-c-nav__subnav--PaddingBottom: var(--pf-global--spacer--sm);
--pf-c-nav__item--before--BorderColor: transparent;
--pf-c-nav__link--after--BorderColor: var(--pf-global--BorderColor--300);
--pf-c-nav__link--m-current--Color: var(--ak-accent);
display: flex;
flex-direction: column;
height: 100%;
overflow-y: hidden;
padding-block-start: var(--pf-global--spacer--sm);
}
.pf-c-nav__section + .pf-c-nav__section {

View File

@@ -3,6 +3,10 @@
box-shadow: none !important;
}
button.pf-c-nav__link {
margin-block-end: var(--pf-global--spacer--xs);
}
:host([highlight]) .pf-c-nav__item {
background-color: var(--ak-accent);
margin: 16px;
@@ -32,6 +36,7 @@
user-select: none;
--pf-c-nav__item--MarginTop: 0;
--pf-c-nav__link--m-current--after--BorderLeftWidth: 1px;
margin-inline-start: 0.2rem;
}
.pf-c-nav__link::after {

View File

@@ -2,20 +2,20 @@ import { ROUTE_SEPARATOR } from "#common/constants";
import { AKElement } from "#elements/Base";
import Styles from "#elements/sidebar/SidebarItem.css";
import { ifPresent } from "#elements/utils/attributes";
import { msg, str } from "@lit/localize";
import { CSSResult, html, nothing, PropertyValues, TemplateResult } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { createRef, ref } from "lit/directives/ref.js";
import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css";
export interface SidebarItemProperties {
path?: string;
path?: string | null;
activeWhen?: string[];
expanded?: boolean;
expanded?: boolean | null;
}
@customElement("ak-sidebar-item")
@@ -27,25 +27,25 @@ export class SidebarItem extends AKElement {
Styles,
];
@property()
public path?: string;
@property({ type: String })
public path: string | null = null;
@property({ type: String })
public label?: string;
public label: string | null = null;
activeMatchers: RegExp[] = [];
@property({ type: Boolean })
@property({ type: Boolean, useDefault: false })
public expanded = false;
@property({ type: Boolean })
public current?: boolean;
@property({ type: Boolean, useDefault: false })
public current = false;
@property({ type: Boolean })
@property({ type: Boolean, attribute: "absolute-link", useDefault: false })
public isAbsoluteLink = false;
@property({ type: Boolean })
public highlight?: boolean;
@property({ type: Boolean, useDefault: false })
public highlight = false;
public parent?: SidebarItem;
@@ -126,12 +126,13 @@ export class SidebarItem extends AKElement {
renderWithChildren() {
return html`<li
part="list-item-expandable"
aria-label=${ifDefined(this.label)}
aria-label=${ifPresent(this.label)}
role="heading"
${ref(this.#listRef)}
class="pf-c-nav__item pf-m-expandable ${this.expanded ? "pf-m-expanded" : ""}"
>
<button
part="button button-with-children"
class="pf-c-nav__link"
aria-label=${this.expanded
? msg(str`Collapse ${this.label}`)
@@ -168,7 +169,7 @@ export class SidebarItem extends AKElement {
return html`<li
part="list-item"
role="presentation"
aria-label=${ifDefined(this.label)}
aria-label=${ifPresent(this.label)}
class="pf-c-nav__item pf-m-expandable ${this.expanded ? "pf-m-expanded" : ""}"
>
${this.label}
@@ -176,6 +177,7 @@ export class SidebarItem extends AKElement {
aria-label=${this.expanded
? msg(str`Collapse ${this.label}`)
: msg(str`Expand ${this.label}`)}
part="button button-with-path-and-children"
class="pf-c-nav__link"
aria-expanded=${this.expanded ? "true" : "false"}
type="button"
@@ -200,11 +202,11 @@ export class SidebarItem extends AKElement {
renderWithPath() {
return html`
<a
part="link"
part="link ${this.current ? "current" : ""}"
id="sidebar-nav-link-${this.path}"
href="${this.isAbsoluteLink ? "" : "#"}${this.path}"
class="pf-c-nav__link ${this.current ? "pf-m-current" : ""}"
aria-current=${ifDefined(this.current ? "page" : undefined)}
aria-current=${ifPresent(this.current ? "page" : undefined)}
>
${this.label}
</a>
@@ -223,7 +225,7 @@ export class SidebarItem extends AKElement {
return html`<li
part="list-item"
role="presentation"
aria-label=${ifDefined(this.label)}
aria-label=${ifPresent(this.label)}
class="pf-c-nav__item"
>
${this.path ? this.renderWithPath() : this.renderWithLabel()}

View File

@@ -67,8 +67,8 @@ html[data-theme="dark"] {
html[data-theme="dark"] {
--pf-global--BorderColor--100: #444548;
--pf-global--BorderColor--200: #444548;
--pf-global--BorderColor--300: #57585a;
--pf-global--BorderColor--200: #57585a;
--pf-global--BorderColor--300: #444548;
--pf-global--BorderColor--400: #aaabac;
}

View File

@@ -1,3 +1,18 @@
.pf-c-banner {
--pf-c-banner--PaddingTop: var(--pf-global--spacer--sm);
--pf-c-banner--PaddingBottom: var(--pf-global--spacer--sm);
--pf-c-banner--link--hover--FontWeight: var(--pf-global--FontWeight--normal);
font-family: var(--pf-global--FontFamily--heading--sans-serif);
a {
text-decoration-color: color-mix(in srgb, currentColor 30%, transparent 70%);
}
a:hover {
text-decoration-color: currentColor;
}
}
:host([theme="dark"]) .pf-c-banner {
&.pf-m-info,
&.pf-m-blue,
@@ -7,6 +22,8 @@
&.pf-m-green,
&.pf-m-warning,
&.pf-m-gold {
--pf-c-banner--Color: var(--pf-global--palette--black-900);
--pf-c-banner--link--Color: var(--pf-global--palette--black-900);
color: var(--pf-global--palette--black-900);
}
}

View File

@@ -7,6 +7,7 @@
--pf-global--disabled-color--100: var(--pf-global--danger-color--50);
--pf-global--disabled-color--200: transparent;
--pf-global--disabled-color--300: var(--pf-global--danger-color--100);
--pf-global--danger-color--200: var(--pf-global--palette--red-200);
}
}

View File

@@ -89,6 +89,10 @@
}
}
.ak-c-placeholder {
grid-area: main;
}
[data-theme="dark"] .pf-c-login,
:host([theme="dark"]) .pf-c-login {
--pf-c-login__main--BackgroundColor: var(--pf-global--BackgroundColor--100);

View File

@@ -42,7 +42,7 @@ ak-tabs::part(row) {
[data-theme="dark"] .pf-c-page,
:host([theme="dark"]) .pf-c-page {
--pf-c-page--BackgroundColor: var(--pf-global--BackgroundColor--200) !important;
--pf-c-page--BackgroundColor: var(--pf-global--BackgroundColor--200);
/**
* Lighten the main section background to contrast page content.

View File

@@ -112,7 +112,6 @@ test.describe("Provider Wizard", () => {
).toBeVisible,
],
[selectSearchValue, "Signing Key", /authentik Self-signed Certificate/],
[selectSearchValue, "Encryption Key", /authentik Self-signed Certificate/],
[setFormGroup, "Advanced flow settings", true],
[selectSearchValue, "Authentication flow", /default-source-authentication/],
[selectSearchValue, "Invalidation flow", /default-invalidation-flow/],
@@ -120,6 +119,7 @@ test.describe("Provider Wizard", () => {
[fill, "Access code validity", "minutes=2"],
[fill, "Access token validity", "minutes=10"],
[fill, "Refresh token validity", "days=40"],
[selectSearchValue, "Encryption Key", /authentik Self-signed Certificate/],
[setInputCheck, "Include claims in id_token", false],
[setRadio, "Subject mode", "Based on the User's username"],
[setRadio, "Issuer mode", "Same identifier is used for all providers"],

View File

@@ -32,6 +32,7 @@
"unist-util-visit": "^5.0.0"
},
"engines": {
"node": ">=24"
"node": ">=24",
"npm": ">=11.6.2"
}
}

View File

@@ -29,6 +29,7 @@
"react-dom": "^19.2.0"
},
"engines": {
"node": ">=24"
"node": ">=24",
"npm": ">=11.6.2"
}
}

3396
website/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -49,7 +49,8 @@
"lightningcss-linux-x64-gnu": "1.30.2"
},
"engines": {
"node": ">=24"
"node": ">=24",
"npm": ">=11.6.2"
},
"workspaces": [
"docusaurus-theme",