diff --git a/authentik/brands/utils.py b/authentik/brands/utils.py index e5c8380198..db6309c7ff 100644 --- a/authentik/brands/utils.py +++ b/authentik/brands/utils.py @@ -43,6 +43,6 @@ def context_processor(request: HttpRequest) -> dict[str, Any]: "brand": brand, "brand_css": brand_css, "footer_links": tenant.footer_links, - "html_meta": get_http_meta(), + "html_meta": {**get_http_meta()}, "version": get_full_version(), } diff --git a/authentik/core/templates/base/skeleton.html b/authentik/core/templates/base/skeleton.html index fc5eda491c..a9df91fdb0 100644 --- a/authentik/core/templates/base/skeleton.html +++ b/authentik/core/templates/base/skeleton.html @@ -10,7 +10,6 @@ {# Darkreader breaks the site regardless of theme as its not compatible with webcomponents, and we default to a dark theme based on preferred colour-scheme #} - {% block title %}{% trans title|default:brand.branding_title %}{% endblock %} diff --git a/internal/web/static.go b/internal/web/static.go index 4e6bdd7455..25cdcaaed5 100644 --- a/internal/web/static.go +++ b/internal/web/static.go @@ -1,9 +1,11 @@ package web import ( + "fmt" "net/http" "github.com/go-http-utils/etag" + "github.com/gorilla/mux" "goauthentik.io/internal/config" "goauthentik.io/internal/constants" @@ -40,6 +42,27 @@ func (ws *WebServer) configureStatic() { config.Get().Web.Path, )) + indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/if/flow/{flow_slug}/assets").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + pathStripper( + distFs, + "if/flow/"+vars["flow_slug"], + config.Get().Web.Path, + ).ServeHTTP(rw, r) + }) + indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/if/admin/assets").Handler(http.StripPrefix(fmt.Sprintf("%sif/admin", config.Get().Web.Path), distFs)) + indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/if/user/assets").Handler(http.StripPrefix(fmt.Sprintf("%sif/user", config.Get().Web.Path), distFs)) + indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/if/rac/{app_slug}/assets").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + pathStripper( + distFs, + "if/rac/"+vars["app_slug"], + config.Get().Web.Path, + ).ServeHTTP(rw, r) + }) + // Media files, if backend is file if config.Get().Storage.Media.Backend == "file" { fsMedia := http.FileServer(http.Dir(config.Get().Storage.Media.File.Path)) diff --git a/web/bundler/css-assets-plugin/node.js b/web/bundler/css-assets-plugin/node.js deleted file mode 100644 index cafaa92a1e..0000000000 --- a/web/bundler/css-assets-plugin/node.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file CSS asset rewrite plugin for ESBuild. - * - * @import { Plugin } from "esbuild" - */ - -import * as fs from "node:fs/promises"; - -/** - * Rewrite `url()` calls in CSS files to point to the static directory. - * - * @returns {Plugin} - */ -export function cssAssetPlugin() { - return { - name: "css-text-loader", - setup: (build) => { - const URLPattern = /url\(\s*['"]?(?:[./]*)(assets\/[^)'"']*)['"]?\s*\)/g; - - build.onLoad({ filter: /\.css$/ }, async (args) => { - const contents = await fs.readFile(args.path, "utf8"); - - return { - loader: "text", - contents: contents.replaceAll(URLPattern, "url(./static/dist/$1)"), - }; - }); - }, - }; -} diff --git a/web/bundler/mdx-plugin/node.js b/web/bundler/mdx-plugin/node.js index 0a0c619a94..fe33b8f63e 100644 --- a/web/bundler/mdx-plugin/node.js +++ b/web/bundler/mdx-plugin/node.js @@ -1,3 +1,6 @@ +import * as fs from "node:fs/promises"; +import * as path from "node:path"; + /** * @file MDX plugin for ESBuild. * @@ -10,10 +13,6 @@ * PluginBuild * } from "esbuild" */ - -import * as fs from "node:fs/promises"; -import * as path from "node:path"; - import { MonoRepoRoot } from "@goauthentik/core/paths/node"; /** diff --git a/web/scripts/build-web.mjs b/web/scripts/build-web.mjs index a0c1130792..6cc153094f 100644 --- a/web/scripts/build-web.mjs +++ b/web/scripts/build-web.mjs @@ -1,13 +1,11 @@ +import * as fs from "node:fs/promises"; +import * as path from "node:path"; + /** * @file ESBuild script for building the authentik web UI. * * @import { BuildOptions } from "esbuild"; */ - -import * as fs from "node:fs/promises"; -import * as path from "node:path"; - -import { cssAssetPlugin } from "#bundler/css-assets-plugin/node"; import { mdxPlugin } from "#bundler/mdx-plugin/node"; import { createBundleDefinitions } from "#bundler/utils/node"; import { DistDirectory, EntryPoint, PackageRoot } from "#paths/node"; @@ -42,8 +40,11 @@ const BASE_ESBUILD_OPTIONS = { legalComments: "external", splitting: true, treeShaking: true, - + external: ["*.woff", "*.woff2"], tsconfig: path.resolve(PackageRoot, "tsconfig.build.json"), + loader: { + ".css": "text", + }, plugins: [ copy({ assets: [ @@ -74,7 +75,6 @@ const BASE_ESBUILD_OPTIONS = { path: true, }, }), - cssAssetPlugin(), mdxPlugin({ root: MonoRepoRoot, }), diff --git a/web/src/common/styles/authentik.css b/web/src/common/styles/authentik.css index 61f734bd12..a1ef240095 100644 --- a/web/src/common/styles/authentik.css +++ b/web/src/common/styles/authentik.css @@ -35,31 +35,6 @@ --ak-navbar--height: 7rem; } -/* #region Fonts */ - -body { - --pf-global--FontFamily--sans-serif: - RedHatVF, "RedHatText", "Overpass", overpass, helvetica, arial, sans-serif; - - --pf-global--FontFamily--heading--sans-serif: - RedHatDisplayVF, "RedHatDisplay", "Overpass", overpass, helvetica, arial, sans-serif; - - --pf-global--FontFamily--monospace: - RedHatMonoVF, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", - monospace; -} - -code, -pre { - /* - The variable weight is a bit too thin compared to the fixed weight. - So we'll use a slightly larger value here to compensate. - */ - font-weight: 500; -} - -/* #endregion */ - .pf-c-form__group { --pf-c-form--m-horizontal__group-label--md--GridColumnWidth: minmax(max-content, 9.375rem); column-gap: var(--pf-global--spacer--md); diff --git a/web/src/elements/router/RouteMatch.ts b/web/src/elements/router/RouteMatch.ts index 9a81bfc0a2..07c20d4a56 100644 --- a/web/src/elements/router/RouteMatch.ts +++ b/web/src/elements/router/RouteMatch.ts @@ -41,14 +41,6 @@ export class RouteMatch { } } -export function createPathnameHash( - hashRoute?: string | null, - basePath = location.pathname, -): string { - if (!hashRoute) return basePath; - return `${basePath}#${hashRoute}`; -} - export function getURLParam(key: string, fallback: T): T { const params = getURLParams(); if (key in params) { @@ -72,18 +64,13 @@ export function getURLParams(): { [key: string]: unknown } { } export function setURLParams(params: { [key: string]: unknown }, replace = true): void { - const serializedParams = JSON.stringify(params); - - const [currentRoute] = window.location.hash.slice(1).split(ROUTE_SEPARATOR); - - const nextPathname = createPathnameHash( - `${currentRoute};${encodeURIComponent(serializedParams)}`, - ); - + const paramsString = JSON.stringify(params); + const currentUrl = window.location.hash.slice(1, Infinity).split(ROUTE_SEPARATOR)[0]; + const newUrl = `#${currentUrl};${encodeURIComponent(paramsString)}`; if (replace) { - history.replaceState(undefined, "", nextPathname); + history.replaceState(undefined, "", newUrl); } else { - history.pushState(undefined, "", nextPathname); + history.pushState(undefined, "", newUrl); } } @@ -92,6 +79,5 @@ export function updateURLParams(params: { [key: string]: unknown }, replace = tr for (const key in params) { currentParams[key] = params[key] as string; } - setURLParams(currentParams, replace); } diff --git a/web/src/elements/sidebar/SidebarItem.ts b/web/src/elements/sidebar/SidebarItem.ts index 0138786be5..4ff9e1dd20 100644 --- a/web/src/elements/sidebar/SidebarItem.ts +++ b/web/src/elements/sidebar/SidebarItem.ts @@ -1,7 +1,6 @@ import { ROUTE_SEPARATOR } from "#common/constants"; import { AKElement } from "#elements/Base"; -import { createPathnameHash } from "#elements/router/RouteMatch"; import { msg, str } from "@lit/localize"; import { css, CSSResult, html, nothing, TemplateResult } from "lit"; @@ -90,7 +89,10 @@ export class SidebarItem extends AKElement { public current?: boolean; @property({ type: Boolean }) - public highlight = false; + public isAbsoluteLink = false; + + @property({ type: Boolean }) + public highlight?: boolean; public parent?: SidebarItem; @@ -215,8 +217,8 @@ export class SidebarItem extends AKElement { renderWithPath() { return html`