Compare commits
	
		
			4 Commits
		
	
	
		
			version/20
			...
			workspace-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 783b1b0a79 | |||
| 7c69add264 | |||
| 248fcd5d7f | |||
| 2c64e3f9ba | 
| @ -3,13 +3,11 @@ | ||||
|  * @import { StorybookConfig } from "@storybook/web-components-vite"; | ||||
|  * @import { InlineConfig, Plugin } from "vite"; | ||||
|  */ | ||||
| import { cwd } from "process"; | ||||
| import { createBundleDefinitions } from "@goauthentik/web/scripts/esbuild/environment"; | ||||
| import postcssLit from "rollup-plugin-postcss-lit"; | ||||
| import tsconfigPaths from "vite-tsconfig-paths"; | ||||
|  | ||||
| const NODE_ENV = process.env.NODE_ENV || "development"; | ||||
|  | ||||
| const CSSImportPattern = /import [\w\$]+ from .+\.(css)/g; | ||||
| const CSSImportPattern = /import [\w$]+ from .+\.(css)/g; | ||||
| const JavaScriptFilePattern = /\.m?(js|ts|tsx)$/; | ||||
|  | ||||
| /** | ||||
| @ -54,11 +52,7 @@ const config = { | ||||
|          */ | ||||
|         const mergedConfig = { | ||||
|             ...config, | ||||
|             define: { | ||||
|                 "process.env.NODE_ENV": JSON.stringify(NODE_ENV), | ||||
|                 "process.env.CWD": JSON.stringify(cwd()), | ||||
|                 "process.env.AK_API_BASE_PATH": JSON.stringify(process.env.AK_API_BASE_PATH || ""), | ||||
|             }, | ||||
|             define: createBundleDefinitions(), | ||||
|             plugins: [inlineCSSPlugin, ...plugins, postcssLit(), tsconfigPaths()], | ||||
|         }; | ||||
|  | ||||
|  | ||||
| @ -21,7 +21,7 @@ const log = console.debug.bind(console, logPrefix); | ||||
|  * ESBuild may tree-shake it out of production builds. | ||||
|  * | ||||
|  * ```ts | ||||
|  * if (process.env.NODE_ENV === "development") { | ||||
|  * if (import.meta.env.NODE_ENV=== "development") { | ||||
|  *   await import("@goauthentik/esbuild-plugin-live-reload/client") | ||||
|  *     .catch(() => console.warn("Failed to import watcher")) | ||||
|  * } | ||||
|  | ||||
| @ -4,15 +4,20 @@ | ||||
|  | ||||
| export {}; | ||||
| declare global { | ||||
|     /** | ||||
|      * Environment variables injected by ESBuild. | ||||
|      */ | ||||
|     interface ImportMetaEnv { | ||||
|         /** | ||||
|          * The injected watcher URL for ESBuild. | ||||
|          * This is used for live reloading in development mode. | ||||
|          * | ||||
|          * @format url | ||||
|          */ | ||||
|         readonly ESBUILD_WATCHER_URL?: string; | ||||
|     } | ||||
|  | ||||
|     interface ImportMeta { | ||||
|         readonly env: { | ||||
|             /** | ||||
|              * The injected watcher URL for ESBuild. | ||||
|              * This is used for live reloading in development mode. | ||||
|              * | ||||
|              * @format url | ||||
|              */ | ||||
|             ESBUILD_WATCHER_URL: string; | ||||
|         }; | ||||
|         readonly env: ImportMetaEnv; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,16 +0,0 @@ | ||||
| /** | ||||
|  * @file Constants for JavaScript and TypeScript files. | ||||
|  */ | ||||
|  | ||||
| /// <reference types="../../types/global.js" /> | ||||
|  | ||||
| /** | ||||
|  * The current Node.js environment, defaulting to "development" when not set. | ||||
|  * | ||||
|  * Note, this should only be used during the build process. | ||||
|  * | ||||
|  * If you need to check the environment at runtime, use `process.env.NODE_ENV` to | ||||
|  * ensure that module tree-shaking works correctly. | ||||
|  * | ||||
|  */ | ||||
| export const NodeEnvironment = process.env.NODE_ENV || "development"; | ||||
| @ -1,6 +1,20 @@ | ||||
| /** | ||||
|  * @file Utility functions for building and copying files. | ||||
|  * @file Utility functions for working with environment variables. | ||||
|  */ | ||||
| /// <reference types="./types/global.js" />
 | ||||
| 
 | ||||
| //#region Constants
 | ||||
| 
 | ||||
| /** | ||||
|  * The current Node.js environment, defaulting to "development" when not set. | ||||
|  * | ||||
|  * Note, this should only be used during the build process. | ||||
|  * | ||||
|  * If you need to check the environment at runtime, use `process.env.NODE_ENV` to | ||||
|  * ensure that module tree-shaking works correctly. | ||||
|  * | ||||
|  */ | ||||
| export const NodeEnvironment = process.env.NODE_ENV || "development"; | ||||
| 
 | ||||
| /** | ||||
|  * A source environment variable, which can be a string, number, boolean, null, or undefined. | ||||
| @ -14,19 +28,26 @@ | ||||
|  * @typedef {T extends string ? `"${T}"` : T} JSONify | ||||
|  */ | ||||
| 
 | ||||
| //#endregion
 | ||||
| 
 | ||||
| //#region Utilities
 | ||||
| 
 | ||||
| /** | ||||
|  * Given an object of environment variables, returns a new object with the same keys and values, but | ||||
|  * with the values serialized as strings. | ||||
|  * | ||||
|  * @template {Record<string, EnvironmentVariable>} EnvRecord | ||||
|  * @template {string} [Prefix='process.env.'] | ||||
|  * @template {string} [Prefix='import.meta.env.'] | ||||
|  * | ||||
|  * @param {EnvRecord} input | ||||
|  * @param {Prefix} [prefix='process.env.'] | ||||
|  * @param {Prefix} [prefix='import.meta.env.'] | ||||
|  * | ||||
|  * @returns {{[K in keyof EnvRecord as `${Prefix}${K}`]: JSONify<EnvRecord[K]>}} | ||||
|  */ | ||||
| export function serializeEnvironmentVars(input, prefix = /** @type {Prefix} */ ("process.env.")) { | ||||
| export function serializeEnvironmentVars( | ||||
|     input, | ||||
|     prefix = /** @type {Prefix} */ ("import.meta.env."), | ||||
| ) { | ||||
|     /** | ||||
|      * @type {Record<string, string>} | ||||
|      */ | ||||
| @ -40,3 +61,5 @@ export function serializeEnvironmentVars(input, prefix = /** @type {Prefix} */ ( | ||||
| 
 | ||||
|     return /** @type {any} */ (env); | ||||
| } | ||||
| 
 | ||||
| //#endregion
 | ||||
| @ -1,7 +1,6 @@ | ||||
| /// <reference types="./types/global.js" /> | ||||
|  | ||||
| export * from "./paths.js"; | ||||
| export * from "./constants.js"; | ||||
| export * from "./build.js"; | ||||
| export * from "./environment.js"; | ||||
| export * from "./version.js"; | ||||
| export * from "./scripting.js"; | ||||
|  | ||||
| @ -1,17 +1,32 @@ | ||||
| import { spawnSync } from "child_process"; | ||||
| import fs from "fs"; | ||||
| import path from "path"; | ||||
| import process from "process"; | ||||
| /** | ||||
|  * @file Lit Localize build script. | ||||
|  * | ||||
|  * @remarks | ||||
|  * Determines if all the Xliff translation source files are present and if the Typescript source files generated from those sources are up-to-date. | ||||
|  * | ||||
|  * If they are not, it runs the locale building script, | ||||
|  * intercepting the long spew of "this string is not translated" and replacing it with a | ||||
|  * summary of how many strings are missing with respect to the source locale. | ||||
|  * | ||||
|  * @import { ConfigFile } from "@lit/localize-tools/lib/types/config" | ||||
|  */ | ||||
| import { PackageRoot } from "@goauthentik/web/paths"; | ||||
| import { spawnSync } from "node:child_process"; | ||||
| import { readFileSync, statSync } from "node:fs"; | ||||
| import path from "node:path"; | ||||
|  | ||||
| /** | ||||
|  * Determines if all the Xliff translation source files are present and if the Typescript source | ||||
|  * files generated from those sources are up-to-date. If they are not, it runs the locale building | ||||
|  * script, intercepting the long spew of "this string is not translated" and replacing it with a | ||||
|  * summary of how many strings are missing with respect to the source locale. | ||||
|  * @type {ConfigFile} | ||||
|  */ | ||||
| const localizeRules = JSON.parse( | ||||
|     readFileSync(path.join(PackageRoot, "lit-localize.json"), "utf-8"), | ||||
| ); | ||||
|  | ||||
| const localizeRules = JSON.parse(fs.readFileSync("./lit-localize.json", "utf-8")); | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param {string} loc | ||||
|  * @returns {boolean} | ||||
|  */ | ||||
| function generatedFileIsUpToDateWithXliffSource(loc) { | ||||
|     const xliff = path.join("./xliff", `${loc}.xlf`); | ||||
|     const gened = path.join("./src/locales", `${loc}.ts`); | ||||
| @ -22,7 +37,7 @@ function generatedFileIsUpToDateWithXliffSource(loc) { | ||||
|     // generates a unique error message and halts the build. | ||||
|  | ||||
|     try { | ||||
|         var xlfStat = fs.statSync(xliff); | ||||
|         var xlfStat = statSync(xliff); | ||||
|     } catch (_error) { | ||||
|         console.error(`lit-localize expected '${loc}.xlf', but XLF file is not present`); | ||||
|         process.exit(1); | ||||
| @ -30,7 +45,7 @@ function generatedFileIsUpToDateWithXliffSource(loc) { | ||||
|  | ||||
|     // If the generated file doesn't exist, of course it's not up to date. | ||||
|     try { | ||||
|         var genedStat = fs.statSync(gened); | ||||
|         var genedStat = statSync(gened); | ||||
|     } catch (_error) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| /// <reference types="../types/esbuild.js" /> | ||||
| /** | ||||
|  * @file ESBuild script for building the authentik web UI. | ||||
|  * | ||||
| @ -9,7 +10,6 @@ import { | ||||
|     NodeEnvironment, | ||||
|     readBuildIdentifier, | ||||
|     resolvePackage, | ||||
|     serializeEnvironmentVars, | ||||
| } from "@goauthentik/monorepo"; | ||||
| import { DistDirectory, DistDirectoryName, EntryPoint, PackageRoot } from "@goauthentik/web/paths"; | ||||
| import { deepmerge } from "deepmerge-ts"; | ||||
| @ -20,15 +20,10 @@ import * as fs from "node:fs/promises"; | ||||
| import * as path from "node:path"; | ||||
|  | ||||
| import { mdxPlugin } from "./esbuild/build-mdx-plugin.mjs"; | ||||
| import { createBundleDefinitions } from "./esbuild/environment.mjs"; | ||||
|  | ||||
| const logPrefix = "[Build]"; | ||||
|  | ||||
| const definitions = serializeEnvironmentVars({ | ||||
|     NODE_ENV: NodeEnvironment, | ||||
|     CWD: process.cwd(), | ||||
|     AK_API_BASE_PATH: process.env.AK_API_BASE_PATH, | ||||
| }); | ||||
|  | ||||
| const patternflyPath = resolvePackage("@patternfly/patternfly"); | ||||
|  | ||||
| /** | ||||
| @ -86,7 +81,7 @@ const BASE_ESBUILD_OPTIONS = { | ||||
|             root: MonoRepoRoot, | ||||
|         }), | ||||
|     ], | ||||
|     define: definitions, | ||||
|     define: createBundleDefinitions(), | ||||
|     format: "esm", | ||||
|     logOverride: { | ||||
|         /** | ||||
|  | ||||
							
								
								
									
										29
									
								
								web/scripts/esbuild/environment.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								web/scripts/esbuild/environment.mjs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| /** | ||||
|  * @file ESBuild environment utilities. | ||||
|  */ | ||||
| import { AuthentikVersion, NodeEnvironment, serializeEnvironmentVars } from "@goauthentik/monorepo"; | ||||
|  | ||||
| /** | ||||
|  * Creates a mapping of environment variables to their respective runtime constants. | ||||
|  */ | ||||
| export function createBundleDefinitions() { | ||||
|     const SerializedNodeEnvironment = /** @type {`"development"` | `"production"`} */ ( | ||||
|         JSON.stringify(NodeEnvironment) | ||||
|     ); | ||||
|  | ||||
|     /** | ||||
|      * @satisfies {Record<ESBuildImportEnvKey, string>} | ||||
|      */ | ||||
|     const envRecord = { | ||||
|         AK_VERSION: AuthentikVersion, | ||||
|         AK_API_BASE_PATH: process.env.AK_API_BASE_PATH ?? "", | ||||
|     }; | ||||
|  | ||||
|     return { | ||||
|         ...serializeEnvironmentVars(envRecord), | ||||
|         // We need to explicitly set this for NPM packages that use `process` | ||||
|         // to determine their environment. | ||||
|         "process.env.NODE_ENV": SerializedNodeEnvironment, | ||||
|         "import.meta.env.NODE_ENV": SerializedNodeEnvironment, | ||||
|     }; | ||||
| } | ||||
| @ -35,6 +35,11 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url)); | ||||
| const projectRoot = path.join(__dirname, ".."); | ||||
| process.chdir(projectRoot); | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param {string[]} flags | ||||
|  * @returns | ||||
|  */ | ||||
| const hasFlag = (flags) => process.argv.length > 1 && flags.includes(process.argv[2]); | ||||
|  | ||||
| const [configFile, files] = hasFlag(["-n", "--nightmare"]) | ||||
|  | ||||
| @ -1,22 +1,36 @@ | ||||
| import { readFileSync } from "fs"; | ||||
| import path from "path"; | ||||
| /** | ||||
|  * @file Pseudo-localization script. | ||||
|  * | ||||
|  * @import { ConfigFile } from "@lit/localize-tools/lib/types/config.js" | ||||
|  * @import { Config } from '@lit/localize-tools/lib/types/config.js'; | ||||
|  * @import { ProgramMessage } from "@lit/localize-tools/src/messages.js" | ||||
|  * @import { Locale } from "@lit/localize-tools/src/types/locale.js" | ||||
|  */ | ||||
| import { PackageRoot } from "@goauthentik/web/paths"; | ||||
| import { readFileSync } from "node:fs"; | ||||
| import path from "node:path"; | ||||
| import pseudolocale from "pseudolocale"; | ||||
| import { fileURLToPath } from "url"; | ||||
|  | ||||
| import { makeFormatter } from "@lit/localize-tools/lib/formatters/index.js"; | ||||
| import { sortProgramMessages } from "@lit/localize-tools/lib/messages.js"; | ||||
| import { TransformLitLocalizer } from "@lit/localize-tools/lib/modes/transform.js"; | ||||
|  | ||||
| const __dirname = fileURLToPath(new URL(".", import.meta.url)); | ||||
| const pseudoLocale = "pseudo-LOCALE"; | ||||
| const pseudoLocale = /** @type {Locale} */ ("pseudo-LOCALE"); | ||||
| const targetLocales = [pseudoLocale]; | ||||
| const baseConfig = JSON.parse(readFileSync(path.join(__dirname, "../lit-localize.json"), "utf-8")); | ||||
|  | ||||
| /** | ||||
|  * @type {ConfigFile} | ||||
|  */ | ||||
| const baseConfig = JSON.parse(readFileSync(path.join(PackageRoot, "lit-localize.json"), "utf-8")); | ||||
|  | ||||
| // Need to make some internal specifications to satisfy the transformer. It doesn't actually matter | ||||
| // which Localizer we use (transformer or runtime), because all of the functionality we care about | ||||
| // is in their common parent class, but I had to pick one.  Everything else here is just pure | ||||
| // exploitation of the lit/localize-tools internals. | ||||
|  | ||||
| /** | ||||
|  * @satisfies {Config} | ||||
|  */ | ||||
| const config = { | ||||
|     ...baseConfig, | ||||
|     baseDir: path.join(__dirname, ".."), | ||||
| @ -28,6 +42,11 @@ const config = { | ||||
|     resolve: (path) => path, | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * @param {ProgramMessage} message | ||||
|  * @returns | ||||
|  */ | ||||
| const pseudoMessagify = (message) => ({ | ||||
|     name: message.name, | ||||
|     contents: message.contents.map((content) => | ||||
| @ -36,7 +55,7 @@ const pseudoMessagify = (message) => ({ | ||||
| }); | ||||
|  | ||||
| const localizer = new TransformLitLocalizer(config); | ||||
| const messages = localizer.extractSourceMessages().messages; | ||||
| const { messages } = localizer.extractSourceMessages(); | ||||
| const translations = messages.map(pseudoMessagify); | ||||
| const sorted = sortProgramMessages([...messages]); | ||||
| const formatter = makeFormatter(config); | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; | ||||
| import { VERSION } from "@goauthentik/common/constants"; | ||||
| import { globalAK } from "@goauthentik/common/global"; | ||||
| import { DefaultBrand } from "@goauthentik/common/ui/config"; | ||||
| import "@goauthentik/elements/EmptyState"; | ||||
| @ -45,7 +44,7 @@ export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton)) | ||||
|         } | ||||
|         return [ | ||||
|             [msg("Version"), version.versionCurrent], | ||||
|             [msg("UI Version"), VERSION], | ||||
|             [msg("UI Version"), import.meta.env.AK_VERSION], | ||||
|             [msg("Build"), build], | ||||
|             [msg("Python version"), status.runtime.pythonVersion], | ||||
|             [msg("Platform"), status.runtime.platform], | ||||
|  | ||||
| @ -43,7 +43,7 @@ import { | ||||
|     renderSidebarItems, | ||||
| } from "./AdminSidebar.js"; | ||||
|  | ||||
| if (process.env.NODE_ENV === "development") { | ||||
| if (import.meta.env.NODE_ENV === "development") { | ||||
|     await import("@goauthentik/esbuild-plugin-live-reload/client"); | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -8,7 +8,6 @@ import "@goauthentik/admin/admin-overview/cards/WorkerStatusCard"; | ||||
| import "@goauthentik/admin/admin-overview/charts/AdminLoginAuthorizeChart"; | ||||
| import "@goauthentik/admin/admin-overview/charts/OutpostStatusChart"; | ||||
| import "@goauthentik/admin/admin-overview/charts/SyncStatusChart"; | ||||
| import { VERSION } from "@goauthentik/common/constants"; | ||||
| import { me } from "@goauthentik/common/users"; | ||||
| import { AKElement } from "@goauthentik/elements/Base"; | ||||
| import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider.js"; | ||||
| @ -22,8 +21,6 @@ import { msg, str } from "@lit/localize"; | ||||
| import { CSSResult, TemplateResult, css, html, nothing } from "lit"; | ||||
| import { customElement, state } from "lit/decorators.js"; | ||||
| import { classMap } from "lit/directives/class-map.js"; | ||||
| import { map } from "lit/directives/map.js"; | ||||
| import { when } from "lit/directives/when.js"; | ||||
|  | ||||
| import PFContent from "@patternfly/patternfly/components/Content/content.css"; | ||||
| import PFDivider from "@patternfly/patternfly/components/Divider/divider.css"; | ||||
| @ -33,21 +30,17 @@ import PFBase from "@patternfly/patternfly/patternfly-base.css"; | ||||
|  | ||||
| import { SessionUser } from "@goauthentik/api"; | ||||
|  | ||||
| export function versionFamily(): string { | ||||
|     const parts = VERSION.split("."); | ||||
|     parts.pop(); | ||||
|     return parts.join("."); | ||||
| function createReleaseNotesURL(semver: string): URL { | ||||
|     const segments = semver.split("."); | ||||
|     const versionFamily = segments.slice(0, -1).join("."); | ||||
|  | ||||
|     const release = `${versionFamily}#fixed-in-${segments.join("")}`; | ||||
|  | ||||
|     return new URL(`/docs/releases/${release}`, "https://goauthentik.io"); | ||||
| } | ||||
|  | ||||
| const RELEASE = `${VERSION.split(".").slice(0, -1).join(".")}#fixed-in-${VERSION.replaceAll( | ||||
|     ".", | ||||
|     "", | ||||
| )}`; | ||||
|  | ||||
| const AdminOverviewBase = WithLicenseSummary(AKElement); | ||||
|  | ||||
| type Renderer = () => TemplateResult | typeof nothing; | ||||
|  | ||||
| @customElement("ak-admin-overview") | ||||
| export class AdminOverviewPage extends AdminOverviewBase { | ||||
|     static get styles(): CSSResult[] { | ||||
| @ -83,7 +76,11 @@ export class AdminOverviewPage extends AdminOverviewBase { | ||||
|         [msg("Check the logs"), paramURL("/events/log")], | ||||
|         [msg("Explore integrations"), "https://goauthentik.io/integrations/", true], | ||||
|         [msg("Manage users"), paramURL("/identity/users")], | ||||
|         [msg("Check the release notes"), `https://goauthentik.io/docs/releases/${RELEASE}`, true], | ||||
|         [ | ||||
|             msg("Check the release notes"), | ||||
|             createReleaseNotesURL(import.meta.env.AK_VERSION).href, | ||||
|             true, | ||||
|         ], | ||||
|     ]; | ||||
|  | ||||
|     @state() | ||||
| @ -193,45 +190,6 @@ export class AdminOverviewPage extends AdminOverviewBase { | ||||
|                   </div>` | ||||
|                 : nothing} `; | ||||
|     } | ||||
|  | ||||
|     renderActions() { | ||||
|         const release = `${versionFamily()}#fixed-in-${VERSION.replaceAll(".", "")}`; | ||||
|  | ||||
|         const quickActions: [string, string][] = [ | ||||
|             [msg("Create a new application"), paramURL("/core/applications", { createForm: true })], | ||||
|             [msg("Check the logs"), paramURL("/events/log")], | ||||
|             [msg("Explore integrations"), "https://goauthentik.io/integrations/"], | ||||
|             [msg("Manage users"), paramURL("/identity/users")], | ||||
|             [msg("Check the release notes"), `https://goauthentik.io/docs/releases/${release}`], | ||||
|         ]; | ||||
|  | ||||
|         const action = ([label, url]: [string, string]) => { | ||||
|             const isExternal = url.startsWith("https://"); | ||||
|             const ex = (truecase: Renderer, falsecase: Renderer) => | ||||
|                 when(isExternal, truecase, falsecase); | ||||
|  | ||||
|             const content = html`${label}${ex( | ||||
|                 () => html`<i class="fas fa-external-link-alt ak-external-link"></i>`, | ||||
|                 () => nothing, | ||||
|             )}`; | ||||
|  | ||||
|             return html`<li> | ||||
|                 ${ex( | ||||
|                     () => | ||||
|                         html`<a | ||||
|                             href="${url}" | ||||
|                             class="pf-u-mb-xl" | ||||
|                             rel="noopener noreferrer" | ||||
|                             target="_blank" | ||||
|                             >${content}</a | ||||
|                         >`, | ||||
|                     () => html`<a href="${url}" class="pf-u-mb-xl" )>${content}</a>`, | ||||
|                 )} | ||||
|             </li>`; | ||||
|         }; | ||||
|  | ||||
|         return html`${map(quickActions, action)}`; | ||||
|     } | ||||
| } | ||||
|  | ||||
| declare global { | ||||
|  | ||||
| @ -3,7 +3,7 @@ import { | ||||
|     EventMiddleware, | ||||
|     LoggingMiddleware, | ||||
| } from "@goauthentik/common/api/middleware.js"; | ||||
| import { EVENT_LOCALE_REQUEST, VERSION } from "@goauthentik/common/constants.js"; | ||||
| import { EVENT_LOCALE_REQUEST } from "@goauthentik/common/constants.js"; | ||||
| import { globalAK } from "@goauthentik/common/global.js"; | ||||
| import { SentryMiddleware } from "@goauthentik/common/sentry"; | ||||
|  | ||||
| @ -79,4 +79,6 @@ export function AndNext(url: string): string { | ||||
|     return `?next=${encodeURIComponent(url)}`; | ||||
| } | ||||
|  | ||||
| console.debug(`authentik(early): version ${VERSION}, apiBase ${DEFAULT_CONFIG.basePath}`); | ||||
| console.debug( | ||||
|     `authentik(early): version ${import.meta.env.AK_VERSION}, apiBase ${DEFAULT_CONFIG.basePath}`, | ||||
| ); | ||||
|  | ||||
| @ -1,12 +1,35 @@ | ||||
| /** | ||||
|  * @file Global constants used throughout the application. | ||||
|  * | ||||
|  * @todo Much of this content can be moved to a specific file, element, or component. | ||||
|  */ | ||||
|  | ||||
| /// <reference types="../../types/esbuild.js" /> | ||||
|  | ||||
| //#region Patternfly | ||||
|  | ||||
| export const SECONDARY_CLASS = "pf-m-secondary"; | ||||
| export const SUCCESS_CLASS = "pf-m-success"; | ||||
| export const ERROR_CLASS = "pf-m-danger"; | ||||
| export const PROGRESS_CLASS = "pf-m-in-progress"; | ||||
| export const CURRENT_CLASS = "pf-m-current"; | ||||
| export const VERSION = "2025.4.1"; | ||||
|  | ||||
| //#endregion | ||||
|  | ||||
| //#region Application | ||||
|  | ||||
| export const TITLE_DEFAULT = "authentik"; | ||||
| /** | ||||
|  * The delimiter used to parse the URL for the current route. | ||||
|  * | ||||
|  * @todo Move this to the ak-router. | ||||
|  */ | ||||
| export const ROUTE_SEPARATOR = ";"; | ||||
|  | ||||
| //#endregion | ||||
|  | ||||
| //#region Events | ||||
|  | ||||
| export const EVENT_REFRESH = "ak-refresh"; | ||||
| export const EVENT_NOTIFICATION_DRAWER_TOGGLE = "ak-notification-toggle"; | ||||
| export const EVENT_API_DRAWER_TOGGLE = "ak-api-drawer-toggle"; | ||||
| @ -20,7 +43,17 @@ export const EVENT_MESSAGE = "ak-message"; | ||||
| export const EVENT_THEME_CHANGE = "ak-theme-change"; | ||||
| export const EVENT_REFRESH_ENTERPRISE = "ak-refresh-enterprise"; | ||||
|  | ||||
| //#endregion | ||||
|  | ||||
| //#region WebSocket | ||||
|  | ||||
| export const WS_MSG_TYPE_MESSAGE = "message"; | ||||
| export const WS_MSG_TYPE_REFRESH = "refresh"; | ||||
|  | ||||
| //#endregion | ||||
|  | ||||
| //#region LocalStorage | ||||
|  | ||||
| export const LOCALSTORAGE_AUTHENTIK_KEY = "authentik-local-settings"; | ||||
|  | ||||
| //#endregion | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import { VERSION } from "@goauthentik/common/constants"; | ||||
| import { SentryIgnoredError } from "@goauthentik/common/sentry"; | ||||
|  | ||||
| export interface PlexPinResponse { | ||||
| @ -19,7 +18,7 @@ export const DEFAULT_HEADERS = { | ||||
|     "Accept": "application/json", | ||||
|     "Content-Type": "application/json", | ||||
|     "X-Plex-Product": "authentik", | ||||
|     "X-Plex-Version": VERSION, | ||||
|     "X-Plex-Version": import.meta.env.AK_VERSION, | ||||
|     "X-Plex-Device-Vendor": "goauthentik.io", | ||||
| }; | ||||
|  | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import { VERSION } from "@goauthentik/common/constants"; | ||||
| import { globalAK } from "@goauthentik/common/global"; | ||||
| import { me } from "@goauthentik/common/users"; | ||||
| import { readInterfaceRouteParam } from "@goauthentik/elements/router/utils"; | ||||
| @ -50,7 +49,7 @@ export function configureSentry(canDoPpi = false) { | ||||
|             /MutationObserver.observe/gi, | ||||
|             /NS_ERROR_FAILURE/gi, | ||||
|         ], | ||||
|         release: `authentik@${VERSION}`, | ||||
|         release: `authentik@${import.meta.env.AK_VERSION}`, | ||||
|         integrations: [ | ||||
|             browserTracingIntegration({ | ||||
|                 // https://docs.sentry.io/platforms/javascript/tracing/instrumentation/automatic-instrumentation/#custom-routing | ||||
|  | ||||
| @ -223,7 +223,7 @@ export function inspectStyleSheetTree(element: ReactiveElement): InspectedStyleS | ||||
|     }; | ||||
| } | ||||
|  | ||||
| if (process.env.NODE_ENV === "development") { | ||||
| if (import.meta.env.NODE_ENV === "development") { | ||||
|     Object.assign(window, { | ||||
|         inspectStyleSheetTree, | ||||
|         serializeStyleSheet, | ||||
|  | ||||
| @ -5,11 +5,11 @@ import { | ||||
|     type StyleRoot, | ||||
|     createStyleSheetUnsafe, | ||||
|     setAdoptedStyleSheets, | ||||
| } from "@goauthentik/common/stylesheets.js"; | ||||
| import { UIConfig } from "@goauthentik/common/ui/config.js"; | ||||
| } from "@goauthentik/web/common/stylesheets.js"; | ||||
| import { UIConfig } from "@goauthentik/web/common/ui/config.js"; | ||||
|  | ||||
| import AKBase from "@goauthentik/common/styles/authentik.css"; | ||||
| import AKBaseDark from "@goauthentik/common/styles/theme-dark.css"; | ||||
| import AKBase from "@goauthentik/web/common/styles/authentik.css"; | ||||
| import AKBaseDark from "@goauthentik/web/common/styles/theme-dark.css"; | ||||
| import PFBase from "@patternfly/patternfly/patternfly-base.css"; | ||||
|  | ||||
| import { Config, CurrentBrand, UiThemeEnum } from "@goauthentik/api"; | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; | ||||
| import { VERSION } from "@goauthentik/common/constants"; | ||||
| import { PFSize } from "@goauthentik/common/enums.js"; | ||||
| import { | ||||
|     EventContext, | ||||
| @ -76,7 +75,7 @@ ${context.message as string} | ||||
|  | ||||
|  | ||||
| **Version and Deployment (please complete the following information):** | ||||
| - authentik version: ${VERSION} | ||||
| - authentik version: ${import.meta.env.AK_VERSION} | ||||
| - Deployment: [e.g. docker-compose, helm] | ||||
|  | ||||
| **Additional context** | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| import { VERSION } from "@goauthentik/common/constants"; | ||||
| import { AKElement } from "@goauthentik/elements/Base"; | ||||
| import { WithVersion } from "@goauthentik/elements/Interface/versionProvider"; | ||||
|  | ||||
| @ -10,20 +9,19 @@ import PFBanner from "@patternfly/patternfly/components/Banner/banner.css"; | ||||
|  | ||||
| @customElement("ak-version-banner") | ||||
| export class VersionBanner extends WithVersion(AKElement) { | ||||
|     static get styles() { | ||||
|         return [PFBanner]; | ||||
|     } | ||||
|     static styles = [PFBanner]; | ||||
|  | ||||
|     render() { | ||||
|         return this.version && this.version.versionCurrent !== VERSION | ||||
|             ? html` | ||||
|                   <div class="pf-c-banner pf-m-sticky pf-m-gold"> | ||||
|                       ${msg( | ||||
|                           str`A newer version (${this.version.versionCurrent}) of the UI is available.`, | ||||
|                       )} | ||||
|                   </div> | ||||
|               ` | ||||
|             : nothing; | ||||
|         if (!this.version?.versionCurrent) return nothing; | ||||
|         if (this.version.versionCurrent === import.meta.env.AK_VERSION) return nothing; | ||||
|  | ||||
|         return html` | ||||
|             <div class="pf-c-banner pf-m-sticky pf-m-gold"> | ||||
|                 ${msg( | ||||
|                     str`A newer version (${this.version.versionCurrent}) of the UI is available.`, | ||||
|                 )} | ||||
|             </div> | ||||
|         `; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -14,6 +14,6 @@ import "@goauthentik/flow/stages/password/PasswordStage"; | ||||
|  | ||||
| // end of stage import | ||||
|  | ||||
| if (process.env.NODE_ENV === "development") { | ||||
| if (import.meta.env.NODE_ENV === "development") { | ||||
|     await import("@goauthentik/esbuild-plugin-live-reload/client"); | ||||
| } | ||||
|  | ||||
| @ -43,7 +43,7 @@ import PFDisplay from "@patternfly/patternfly/utilities/Display/display.css"; | ||||
|  | ||||
| import { CurrentBrand, EventsApi, SessionUser } from "@goauthentik/api"; | ||||
|  | ||||
| if (process.env.NODE_ENV === "development") { | ||||
| if (import.meta.env.NODE_ENV === "development") { | ||||
|     await import("@goauthentik/esbuild-plugin-live-reload/client"); | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -2,6 +2,9 @@ | ||||
| { | ||||
|     "extends": "@goauthentik/tsconfig", | ||||
|     "compilerOptions": { | ||||
|         "checkJs": true, | ||||
|         "allowJs": true, | ||||
|         "resolveJsonModule": true, | ||||
|         "allowSyntheticDefaultImports": true, | ||||
|         "emitDeclarationOnly": true, | ||||
|         "experimentalDecorators": true, | ||||
|  | ||||
							
								
								
									
										39
									
								
								web/types/esbuild.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								web/types/esbuild.d.ts
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| /** | ||||
|  * @file Import meta environment variables available via ESBuild. | ||||
|  */ | ||||
|  | ||||
| export {}; | ||||
| declare global { | ||||
|     interface ESBuildImportEnv { | ||||
|         /** | ||||
|          * The authentik version injected by ESBuild during build time. | ||||
|          * | ||||
|          * @format semver | ||||
|          */ | ||||
|         readonly AK_VERSION: string; | ||||
|  | ||||
|         /** | ||||
|          * @todo Determine where this is used and if it is needed, | ||||
|          * give it a better name. | ||||
|          * @deprecated | ||||
|          */ | ||||
|         readonly AK_API_BASE_PATH: string; | ||||
|     } | ||||
|  | ||||
|     type ESBuildImportEnvKey = keyof ESBuildImportEnv; | ||||
|  | ||||
|     /** | ||||
|      * Environment variables injected by ESBuild. | ||||
|      */ | ||||
|     interface ImportMetaEnv extends ESBuildImportEnv { | ||||
|         /** | ||||
|          * An environment variable used to determine | ||||
|          * whether Node.js is running in production mode. | ||||
|          */ | ||||
|         readonly NODE_ENV: "development" | "production"; | ||||
|     } | ||||
|  | ||||
|     interface ImportMeta { | ||||
|         readonly env: ImportMetaEnv; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										13
									
								
								web/types/global.d.ts → web/types/node.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								web/types/global.d.ts → web/types/node.d.ts
									
									
									
									
										vendored
									
									
								
							| @ -1,5 +1,5 @@ | ||||
| /** | ||||
|  * @file Environment variables available via ESBuild. | ||||
|  * @file Global variables provided by Node.js | ||||
|  */ | ||||
| 
 | ||||
| declare module "module" { | ||||
| @ -14,8 +14,8 @@ declare module "module" { | ||||
|          * const relativeDirname = dirname(fileURLToPath(import.meta.url)); | ||||
|          * ``` | ||||
|          */ | ||||
|         // eslint-disable-next-line no-var
 | ||||
|         var __dirname: string; | ||||
| 
 | ||||
|         const __dirname: string; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -23,13 +23,16 @@ declare module "process" { | ||||
|     global { | ||||
|         namespace NodeJS { | ||||
|             interface ProcessEnv { | ||||
|                 CWD: string; | ||||
|                 /** | ||||
|                  * Node environment, if any. | ||||
|                  */ | ||||
|                 readonly NODE_ENV?: "development" | "production"; | ||||
|                 /** | ||||
|                  * @todo Determine where this is used and if it is needed, | ||||
|                  * give it a better name. | ||||
|                  * @deprecated | ||||
|                  */ | ||||
|                 AK_API_BASE_PATH: string; | ||||
|                 readonly AK_API_BASE_PATH?: string; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @ -1,17 +1,15 @@ | ||||
| import replace from "@rollup/plugin-replace"; | ||||
| /// <reference types="@wdio/browser-runner" /> | ||||
| import { browser } from "@wdio/globals"; | ||||
| import type { Options } from "@wdio/types"; | ||||
| import path from "path"; | ||||
| import { cwd } from "process"; | ||||
| import { fileURLToPath } from "url"; | ||||
| import type { UserConfig } from "vite"; | ||||
| import litCss from "vite-plugin-lit-css"; | ||||
| import path from "node:path"; | ||||
| import { fileURLToPath } from "node:url"; | ||||
| import { createBundleDefinitions } from "scripts/esbuild/environment.mjs"; | ||||
| import type { InlineConfig } from "vite"; | ||||
| import litCSS from "vite-plugin-lit-css"; | ||||
| import tsconfigPaths from "vite-tsconfig-paths"; | ||||
|  | ||||
| const __dirname = fileURLToPath(new URL(".", import.meta.url)); | ||||
|  | ||||
| const isProdBuild = process.env.NODE_ENV === "production"; | ||||
| const apiBasePath = process.env.AK_API_BASE_PATH || ""; | ||||
| const runHeadless = process.env.CI !== undefined; | ||||
|  | ||||
| const testSafari = process.env.WDIO_TEST_SAFARI !== undefined; | ||||
| @ -72,21 +70,9 @@ export const config: Options.Testrunner = { | ||||
|     runner: [ | ||||
|         "browser", | ||||
|         { | ||||
|             viteConfig: (userConfig: UserConfig = { plugins: [] }) => ({ | ||||
|                 ...userConfig, | ||||
|                 plugins: [ | ||||
|                     litCss(), | ||||
|                     replace({ | ||||
|                         "process.env.NODE_ENV": JSON.stringify( | ||||
|                             isProdBuild ? "production" : "development", | ||||
|                         ), | ||||
|                         "process.env.CWD": JSON.stringify(cwd()), | ||||
|                         "process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath), | ||||
|                         "preventAssignment": true, | ||||
|                     }), | ||||
|                     ...(userConfig?.plugins ?? []), | ||||
|                     tsconfigPaths(), | ||||
|                 ], | ||||
|             viteConfig: { | ||||
|                 define: createBundleDefinitions(), | ||||
|                 plugins: [litCSS(), tsconfigPaths()], | ||||
|                 resolve: { | ||||
|                     alias: { | ||||
|                         "@goauthentik/admin": path.resolve(__dirname, "src/admin"), | ||||
| @ -101,7 +87,7 @@ export const config: Options.Testrunner = { | ||||
|                         "@goauthentik/user": path.resolve(__dirname, "src/user"), | ||||
|                     }, | ||||
|                 }, | ||||
|             }), | ||||
|             } satisfies InlineConfig, | ||||
|         }, | ||||
|     ], | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	