diff --git a/src/bin/keycloakify/buildJars/buildJar.ts b/src/bin/keycloakify/buildJars/buildJar.ts index 9ae7ae9f..a077dedf 100644 --- a/src/bin/keycloakify/buildJars/buildJar.ts +++ b/src/bin/keycloakify/buildJars/buildJar.ts @@ -1,12 +1,12 @@ -import { assert } from "tsafe/assert"; +import { assert, type Equals } from "tsafe/assert"; import type { KeycloakAccountV1Version, KeycloakThemeAdditionalInfoExtensionVersion } from "./extensionVersions"; -import { join as pathJoin } from "path"; +import { join as pathJoin, dirname as pathDirname } from "path"; import { transformCodebase } from "../../tools/transformCodebase"; import type { BuildOptions } from "../buildOptions"; import * as fs from "fs/promises"; import { accountV1ThemeName } from "../../constants"; import { generatePom, BuildOptionsLike as BuildOptionsLike_generatePom } from "./generatePom"; -import { existsSync } from "fs"; +import { existsSync, readFileSync } from "fs"; import { isInside } from "../../tools/isInside"; import child_process from "child_process"; @@ -37,9 +37,9 @@ export async function buildJar(params: { await fs.writeFile(pathJoin(buildOptions.keycloakifyBuildDirPath, ".gitignore"), Buffer.from("*", "utf8")); } - { - const srcMainResourcesRelativeDirPath = pathJoin("src", "main", "resources"); + const srcMainResourcesRelativeDirPath = pathJoin("src", "main", "resources"); + { const keycloakThemesJsonFilePath = pathJoin(srcMainResourcesRelativeDirPath, "META-INF", "keycloak-themes.json"); const themePropertiesFilePathSet = new Set( @@ -87,6 +87,53 @@ export async function buildJar(params: { }); } + route_legacy_pages: { + // NOTE: If there's no account theme there is no special target for keycloak 24 and up so we create + // the pages anyway. If there is an account pages, since we know that account-v1 is only support keycloak + // 24 in version 0.4 and up, we can safely break the route for legacy pages. + const doBreak: boolean = (() => { + switch (keycloakAccountV1Version) { + case null: + return false; + case "0.3": + return false; + default: + return true; + } + })(); + + if (doBreak) { + break route_legacy_pages; + } + + (["register.ftl", "login-update-profile.ftl"] as const).forEach(pageId => + buildOptions.themeNames.map(themeName => { + const ftlFilePath = pathJoin(srcMainResourcesRelativeDirPath, "themes", themeName, "login", pageId); + + const ftlFileContent = readFileSync(ftlFilePath).toString("utf8"); + + const realPageId = (() => { + switch (pageId) { + case "register.ftl": + return "register-user-profile.ftl"; + case "login-update-profile.ftl": + return "update-user-profile.ftl"; + } + assert>(false); + })(); + + const modifiedFtlFileContent = ftlFileContent.replace( + `out["pageId"] = "${pageId}";`, + `out["pageId"] = "${pageId}"; out["realPageId"] = "${realPageId}";` + ); + + assert(modifiedFtlFileContent !== ftlFileContent); + + fs.writeFile(pathJoin(pathDirname(ftlFilePath), realPageId), Buffer.from(modifiedFtlFileContent, "utf8")); + }) + ); + } + { const { pomFileCode } = generatePom({ buildOptions, diff --git a/src/bin/keycloakify/generateFtl/pageId.ts b/src/bin/keycloakify/generateFtl/pageId.ts index e9c4b1e3..fe83f196 100644 --- a/src/bin/keycloakify/generateFtl/pageId.ts +++ b/src/bin/keycloakify/generateFtl/pageId.ts @@ -5,7 +5,6 @@ export const loginThemePageIds = [ "webauthn-authenticate.ftl", "webauthn-register.ftl", "register.ftl", - "register-user-profile.ftl", "info.ftl", "error.ftl", "login-reset-password.ftl", @@ -21,7 +20,6 @@ export const loginThemePageIds = [ "login-page-expired.ftl", "login-config-totp.ftl", "logout-confirm.ftl", - "update-user-profile.ftl", "idp-review-user-profile.ftl", "update-email.ftl", "select-authenticator.ftl", diff --git a/src/login/Fallback.tsx b/src/login/Fallback.tsx index d08cd78e..90d4a266 100644 --- a/src/login/Fallback.tsx +++ b/src/login/Fallback.tsx @@ -55,7 +55,6 @@ export default function Fallback(props: FallbackProps) { case "login.ftl": return ; case "register.ftl": - case "register-user-profile.ftl": return ; case "info.ftl": return ; @@ -84,7 +83,6 @@ export default function Fallback(props: FallbackProps) { case "login-update-password.ftl": return ; case "login-update-profile.ftl": - case "update-user-profile.ftl": return ; case "login-idp-link-confirm.ftl": return ; diff --git a/src/login/kcContext/KcContext.ts b/src/login/kcContext/KcContext.ts index 3f404d28..88c759b8 100644 --- a/src/login/kcContext/KcContext.ts +++ b/src/login/kcContext/KcContext.ts @@ -183,7 +183,7 @@ export declare namespace KcContext { }; export type Register = Common & { - pageId: "register.ftl" | "register-user-profile.ftl"; + pageId: "register.ftl"; profile: UserProfile; url: { registrationAction: string; @@ -452,7 +452,7 @@ export declare namespace KcContext { }; export type LoginUpdateProfile = Common & { - pageId: "login-update-profile.ftl" | "update-user-profile.ftl"; + pageId: "login-update-profile.ftl"; profile: UserProfile; }; diff --git a/src/login/pages/LoginUpdateProfile.tsx b/src/login/pages/LoginUpdateProfile.tsx index 4309fe42..d224c5f6 100644 --- a/src/login/pages/LoginUpdateProfile.tsx +++ b/src/login/pages/LoginUpdateProfile.tsx @@ -7,7 +7,7 @@ import type { I18n } from "../i18n"; import type { LazyOrNot } from "keycloakify/tools/LazyOrNot"; import type { UserProfileFormFieldsProps } from "keycloakify/login/UserProfileFormFields"; -type LoginUpdateProfileProps = PageProps, I18n> & { +type LoginUpdateProfileProps = PageProps, I18n> & { UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>; }; diff --git a/src/login/pages/Register.tsx b/src/login/pages/Register.tsx index d1e65d9d..8d036119 100644 --- a/src/login/pages/Register.tsx +++ b/src/login/pages/Register.tsx @@ -9,7 +9,7 @@ import { Markdown } from "keycloakify/tools/Markdown"; import type { KcContext } from "../kcContext"; import type { I18n } from "../i18n"; -type RegisterProps = PageProps, I18n> & { +type RegisterProps = PageProps, I18n> & { UserProfileFormFields: LazyOrNot<(props: UserProfileFormFieldsProps) => JSX.Element>; };