web: remove a lot of duplication from the Routes
This commit extracts the highly repetitive `new Route(new RegExp(...))` syntax into a mappable function, leaving only the regular expression and the asynchronous loader behind. In the process, it creates a typed description of what kinds of routes we have, and uses type-level pattern matching to generate the route handlers and redirects. For example, it establishes that for the purposes of discriminating between redirects and loaders, the loader type is irrelevant to routing correctly. The loader type *is* still well-typed to prevent anyone from putting an incompatible loader into a route, but the two different loader types-- ones that take arguments, and ones that do not-- do not matter to the route builder. Likewise, the two different kinds of redirects *do* matter, but only because JavaScript makes a distinction between methods of one argument that can be `call`'ed and methods of more than one argument that must be `apply`'d. I suppose I could make this irrelevant by enforcing that the second argument to RawRedirect always be an Array, but that's not ergonomic, and when the `match()` function has such a lovely and simple way of distinguishing between the two forms, ergonomics always wins. This might seem like a curious bit of cleanup, but by exposing the regular expressions as strings, independent of the Routes that they ultimately represent, we get the power to associate paths to routeable objects with paths to navigable objects in the Sidebar, *and* ultimately with paths to navigable objects in a command palette. It might also lead to replacing our Routes infrastructure with an off-the-shelf router such as [Vaadin.router](https://github.com/vaadin/router) or Justin Fagnani's preferred [page.js](https://visionmedia.github.io/page.js/)
This commit is contained in:
@ -1,155 +1,266 @@
|
||||
import "@goauthentik/admin/admin-overview/AdminOverviewPage";
|
||||
import { ID_REGEX, Route, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
|
||||
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
|
||||
import { RawRoute, makeRoute } from "@goauthentik/elements/router/routeUtils";
|
||||
|
||||
import { html } from "lit";
|
||||
|
||||
export const ROUTES: Route[] = [
|
||||
export const _ROUTES: RawRoute[] = [
|
||||
// Prevent infinite Shell loops
|
||||
new Route(new RegExp("^/$")).redirect("/administration/overview"),
|
||||
new Route(new RegExp("^#.*")).redirect("/administration/overview"),
|
||||
new Route(new RegExp("^/library$")).redirect("/if/user/", true),
|
||||
["^/$", "/administration/overview"],
|
||||
["^#.*", "/administration/overview"],
|
||||
["^/library$", ["/if/user/", true]],
|
||||
// statically imported since this is the default route
|
||||
new Route(new RegExp("^/administration/overview$"), async () => {
|
||||
return html`<ak-admin-overview></ak-admin-overview>`;
|
||||
}),
|
||||
new Route(new RegExp("^/administration/dashboard/users$"), async () => {
|
||||
await import("@goauthentik/admin/admin-overview/DashboardUserPage");
|
||||
return html`<ak-admin-dashboard-users></ak-admin-dashboard-users>`;
|
||||
}),
|
||||
new Route(new RegExp("^/administration/system-tasks$"), async () => {
|
||||
await import("@goauthentik/admin/system-tasks/SystemTaskListPage");
|
||||
return html`<ak-system-task-list></ak-system-task-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/core/providers$"), async () => {
|
||||
await import("@goauthentik/admin/providers/ProviderListPage");
|
||||
return html`<ak-provider-list></ak-provider-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/core/providers/(?<id>${ID_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/providers/ProviderViewPage");
|
||||
return html`<ak-provider-view .providerID=${parseInt(args.id, 10)}></ak-provider-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/core/applications$"), async () => {
|
||||
await import("@goauthentik/admin/applications/ApplicationListPage");
|
||||
return html`<ak-application-list></ak-application-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/core/applications/(?<slug>${SLUG_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/applications/ApplicationViewPage");
|
||||
return html`<ak-application-view .applicationSlug=${args.slug}></ak-application-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/core/sources$"), async () => {
|
||||
await import("@goauthentik/admin/sources/SourceListPage");
|
||||
return html`<ak-source-list></ak-source-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/core/sources/(?<slug>${SLUG_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/sources/SourceViewPage");
|
||||
return html`<ak-source-view .sourceSlug=${args.slug}></ak-source-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/core/property-mappings$"), async () => {
|
||||
await import("@goauthentik/admin/property-mappings/PropertyMappingListPage");
|
||||
return html`<ak-property-mapping-list></ak-property-mapping-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/core/tokens$"), async () => {
|
||||
await import("@goauthentik/admin/tokens/TokenListPage");
|
||||
return html`<ak-token-list></ak-token-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/core/brands"), async () => {
|
||||
await import("@goauthentik/admin/brands/BrandListPage");
|
||||
return html`<ak-brand-list></ak-brand-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/policy/policies$"), async () => {
|
||||
await import("@goauthentik/admin/policies/PolicyListPage");
|
||||
return html`<ak-policy-list></ak-policy-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/policy/reputation$"), async () => {
|
||||
await import("@goauthentik/admin/policies/reputation/ReputationListPage");
|
||||
return html`<ak-policy-reputation-list></ak-policy-reputation-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/identity/groups$"), async () => {
|
||||
await import("@goauthentik/admin/groups/GroupListPage");
|
||||
return html`<ak-group-list></ak-group-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/identity/groups/(?<uuid>${UUID_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/groups/GroupViewPage");
|
||||
return html`<ak-group-view .groupId=${args.uuid}></ak-group-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/identity/users$"), async () => {
|
||||
await import("@goauthentik/admin/users/UserListPage");
|
||||
return html`<ak-user-list></ak-user-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/identity/users/(?<id>${ID_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/users/UserViewPage");
|
||||
return html`<ak-user-view .userId=${parseInt(args.id, 10)}></ak-user-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/identity/roles$"), async () => {
|
||||
await import("@goauthentik/admin/roles/RoleListPage");
|
||||
return html`<ak-role-list></ak-role-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/identity/roles/(?<id>${UUID_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/roles/RoleViewPage");
|
||||
return html`<ak-role-view roleId=${args.id}></ak-role-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/flow/stages/invitations$"), async () => {
|
||||
await import("@goauthentik/admin/stages/invitation/InvitationListPage");
|
||||
return html`<ak-stage-invitation-list></ak-stage-invitation-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/flow/stages/prompts$"), async () => {
|
||||
await import("@goauthentik/admin/stages/prompt/PromptListPage");
|
||||
return html`<ak-stage-prompt-list></ak-stage-prompt-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/flow/stages$"), async () => {
|
||||
await import("@goauthentik/admin/stages/StageListPage");
|
||||
return html`<ak-stage-list></ak-stage-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/flow/flows$"), async () => {
|
||||
await import("@goauthentik/admin/flows/FlowListPage");
|
||||
return html`<ak-flow-list></ak-flow-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/flow/flows/(?<slug>${SLUG_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/flows/FlowViewPage");
|
||||
return html`<ak-flow-view .flowSlug=${args.slug}></ak-flow-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/events/log$"), async () => {
|
||||
await import("@goauthentik/admin/events/EventListPage");
|
||||
return html`<ak-event-list></ak-event-list>`;
|
||||
}),
|
||||
new Route(new RegExp(`^/events/log/(?<id>${UUID_REGEX})$`), async (args) => {
|
||||
await import("@goauthentik/admin/events/EventViewPage");
|
||||
return html`<ak-event-view .eventID=${args.id}></ak-event-view>`;
|
||||
}),
|
||||
new Route(new RegExp("^/events/transports$"), async () => {
|
||||
await import("@goauthentik/admin/events/TransportListPage");
|
||||
return html`<ak-event-transport-list></ak-event-transport-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/events/rules$"), async () => {
|
||||
await import("@goauthentik/admin/events/RuleListPage");
|
||||
return html`<ak-event-rule-list></ak-event-rule-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/outpost/outposts$"), async () => {
|
||||
await import("@goauthentik/admin/outposts/OutpostListPage");
|
||||
return html`<ak-outpost-list></ak-outpost-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/outpost/integrations$"), async () => {
|
||||
await import("@goauthentik/admin/outposts/ServiceConnectionListPage");
|
||||
return html`<ak-outpost-service-connection-list></ak-outpost-service-connection-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/crypto/certificates$"), async () => {
|
||||
await import("@goauthentik/admin/crypto/CertificateKeyPairListPage");
|
||||
return html`<ak-crypto-certificate-list></ak-crypto-certificate-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/admin/settings$"), async () => {
|
||||
await import("@goauthentik/admin/admin-settings/AdminSettingsPage");
|
||||
return html`<ak-admin-settings></ak-admin-settings>`;
|
||||
}),
|
||||
new Route(new RegExp("^/blueprints/instances$"), async () => {
|
||||
await import("@goauthentik/admin/blueprints/BlueprintListPage");
|
||||
return html`<ak-blueprint-list></ak-blueprint-list>`;
|
||||
}),
|
||||
new Route(new RegExp("^/debug$"), async () => {
|
||||
await import("@goauthentik/admin/DebugPage");
|
||||
return html`<ak-admin-debug-page></ak-admin-debug-page>`;
|
||||
}),
|
||||
new Route(new RegExp("^/enterprise/licenses$"), async () => {
|
||||
await import("@goauthentik/admin/enterprise/EnterpriseLicenseListPage");
|
||||
return html`<ak-enterprise-license-list></ak-enterprise-license-list>`;
|
||||
}),
|
||||
[
|
||||
"^/administration/overview$",
|
||||
async () => {
|
||||
return html`<ak-admin-overview></ak-admin-overview>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/administration/dashboard/users$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/admin-overview/DashboardUserPage");
|
||||
return html`<ak-admin-dashboard-users></ak-admin-dashboard-users>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/administration/system-tasks$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/system-tasks/SystemTaskListPage");
|
||||
return html`<ak-system-task-list></ak-system-task-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/core/providers$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/providers/ProviderListPage");
|
||||
return html`<ak-provider-list></ak-provider-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/core/providers/(?<id>${ID_REGEX}])$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/providers/ProviderViewPage");
|
||||
return html`<ak-provider-view .providerID=${parseInt(args.id, 10)}></ak-provider-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/core/applications$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/applications/ApplicationListPage");
|
||||
return html`<ak-application-list></ak-application-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/core/applications/(?<slug>${SLUG_REGEX})$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/applications/ApplicationViewPage");
|
||||
return html`<ak-application-view .applicationSlug=${args.slug}></ak-application-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/core/sources$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/sources/SourceListPage");
|
||||
return html`<ak-source-list></ak-source-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/core/sources/(?<slug>${SLUG_REGEX})$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/sources/SourceViewPage");
|
||||
return html`<ak-source-view .sourceSlug=${args.slug}></ak-source-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/core/property-mappings$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/property-mappings/PropertyMappingListPage");
|
||||
return html`<ak-property-mapping-list></ak-property-mapping-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/core/tokens$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/tokens/TokenListPage");
|
||||
return html`<ak-token-list></ak-token-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/core/brands",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/brands/BrandListPage");
|
||||
return html`<ak-brand-list></ak-brand-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/policy/policies$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/policies/PolicyListPage");
|
||||
return html`<ak-policy-list></ak-policy-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/policy/reputation$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/policies/reputation/ReputationListPage");
|
||||
return html`<ak-policy-reputation-list></ak-policy-reputation-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/identity/groups$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/groups/GroupListPage");
|
||||
return html`<ak-group-list></ak-group-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/identity/groups/(?<uuid>${UUID_REGEX})$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/groups/GroupViewPage");
|
||||
return html`<ak-group-view .groupId=${args.uuid}></ak-group-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/identity/users$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/users/UserListPage");
|
||||
return html`<ak-user-list></ak-user-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/identity/users/(?<id>${ID_REGEX})$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/users/UserViewPage");
|
||||
return html`<ak-user-view .userId=${parseInt(args.id, 10)}></ak-user-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/identity/roles$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/roles/RoleListPage");
|
||||
return html`<ak-role-list></ak-role-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/identity/roles/(?<id>${UUID_REGEX})$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/roles/RoleViewPage");
|
||||
return html`<ak-role-view roleId=${args.id}></ak-role-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/flow/stages/invitations$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/stages/invitation/InvitationListPage");
|
||||
return html`<ak-stage-invitation-list></ak-stage-invitation-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/flow/stages/prompts$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/stages/prompt/PromptListPage");
|
||||
return html`<ak-stage-prompt-list></ak-stage-prompt-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/flow/stages$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/stages/StageListPage");
|
||||
return html`<ak-stage-list></ak-stage-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/flow/flows$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/flows/FlowListPage");
|
||||
return html`<ak-flow-list></ak-flow-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/flow/flows/(?<slug>${SLUG_REGEX})$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/flows/FlowViewPage");
|
||||
return html`<ak-flow-view .flowSlug=${args.slug}></ak-flow-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/events/log$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/events/EventListPage");
|
||||
return html`<ak-event-list></ak-event-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
`^/events/log/(?<id>${UUID_REGEX})$`,
|
||||
async (args) => {
|
||||
await import("@goauthentik/admin/events/EventViewPage");
|
||||
return html`<ak-event-view .eventID=${args.id}></ak-event-view>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/events/transports$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/events/TransportListPage");
|
||||
return html`<ak-event-transport-list></ak-event-transport-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/events/rules$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/events/RuleListPage");
|
||||
return html`<ak-event-rule-list></ak-event-rule-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/outpost/outposts$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/outposts/OutpostListPage");
|
||||
return html`<ak-outpost-list></ak-outpost-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/outpost/integrations$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/outposts/ServiceConnectionListPage");
|
||||
return html`<ak-outpost-service-connection-list></ak-outpost-service-connection-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/crypto/certificates$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/crypto/CertificateKeyPairListPage");
|
||||
return html`<ak-crypto-certificate-list></ak-crypto-certificate-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/admin/settings$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/admin-settings/AdminSettingsPage");
|
||||
return html`<ak-admin-settings></ak-admin-settings>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/blueprints/instances$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/blueprints/BlueprintListPage");
|
||||
return html`<ak-blueprint-list></ak-blueprint-list>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/debug$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/DebugPage");
|
||||
return html`<ak-admin-debug-page></ak-admin-debug-page>`;
|
||||
},
|
||||
],
|
||||
[
|
||||
"^/enterprise/licenses$",
|
||||
async () => {
|
||||
await import("@goauthentik/admin/enterprise/EnterpriseLicenseListPage");
|
||||
return html`<ak-enterprise-license-list></ak-enterprise-license-list>`;
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
export const ROUTES = _ROUTES.map(makeRoute);
|
||||
|
37
web/src/elements/router/routeUtils.ts
Normal file
37
web/src/elements/router/routeUtils.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Route, RouteArgs } from "@goauthentik/elements/router/Route";
|
||||
import { P, match } from "ts-pattern";
|
||||
|
||||
import { TemplateResult } from "lit";
|
||||
|
||||
type RouteInvoke =
|
||||
| ((_1: RouteArgs) => Promise<TemplateResult<1>>)
|
||||
| (() => Promise<TemplateResult<1>>);
|
||||
|
||||
type _RawRedirect = [string, string | [string, boolean]];
|
||||
type _RawRoute = [string, RouteInvoke];
|
||||
export type RawRoute = _RawRoute | _RawRedirect;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const isLoader = (v: any): v is RouteInvoke => typeof v === "function";
|
||||
|
||||
// When discriminating between redirects and loaders, the loader type is irrelevant to routing
|
||||
// correctly. The loader type *is* still well-typed to prevent an incompatible loader being added to
|
||||
// a route, but the two different loader types-- ones that take arguments, and ones that do not-- do
|
||||
// not matter to the route builder.
|
||||
|
||||
// On the other hand, the two different kinds of redirects *do* matter, but only because JavaScript
|
||||
// makes a distinction between methods of one argument that can be `call`'ed and methods of more
|
||||
// than one argument that must be `apply`'d. (Spread arguments are converted to call or apply as
|
||||
// needed).
|
||||
|
||||
// prettier-ignore
|
||||
export function makeRoute(route: RawRoute): Route {
|
||||
return match(route)
|
||||
.with([P.string, P.when(isLoader)],
|
||||
([path, loader]) => new Route(new RegExp(path), loader))
|
||||
.with([P.string, P.string],
|
||||
([path, redirect]) => new Route(new RegExp(path)).redirect(redirect))
|
||||
.with([P.string, [P.string, P.boolean]],
|
||||
([path, redirect]) => new Route(new RegExp(path)).redirect(...redirect))
|
||||
.exhaustive();
|
||||
}
|
@ -1,15 +1,20 @@
|
||||
import { Route } from "@goauthentik/elements/router/Route";
|
||||
import { RawRoute, makeRoute } from "@goauthentik/elements/router/routeUtils";
|
||||
import "@goauthentik/user/LibraryPage/LibraryPage";
|
||||
|
||||
import { html } from "lit";
|
||||
|
||||
export const ROUTES: Route[] = [
|
||||
export const _ROUTES: RawRoute[] = [
|
||||
// Prevent infinite Shell loops
|
||||
new Route(new RegExp("^/$")).redirect("/library"),
|
||||
new Route(new RegExp("^#.*")).redirect("/library"),
|
||||
new Route(new RegExp("^/library$"), async () => html`<ak-library></ak-library>`),
|
||||
new Route(new RegExp("^/settings$"), async () => {
|
||||
await import("@goauthentik/user/user-settings/UserSettingsPage");
|
||||
return html`<ak-user-settings></ak-user-settings>`;
|
||||
}),
|
||||
["^/$", "/library"],
|
||||
["^#.*", "/library"],
|
||||
["^/library$", async () => html`<ak-library></ak-library>`],
|
||||
[
|
||||
"^/settings$",
|
||||
async () => {
|
||||
await import("@goauthentik/user/user-settings/UserSettingsPage");
|
||||
return html`<ak-user-settings></ak-user-settings>`;
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
export const ROUTES = _ROUTES.map(makeRoute);
|
||||
|
Reference in New Issue
Block a user