Reintroduce doBuildRetrocompatAccountTheme (for now) and fix multiple things in the account default theme
This commit is contained in:
parent
33b7bb6184
commit
694b4c8027
11
README.md
11
README.md
@ -125,17 +125,6 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|||||||
|
|
||||||
# Changelog highlights
|
# Changelog highlights
|
||||||
|
|
||||||
## 9.2
|
|
||||||
|
|
||||||
Remove the `<your theme name>_retrocompat` option in the account theme dropdown and the `doBuildRetrocompatAccountTheme` build option.
|
|
||||||
`<your theme name>_retrocompat` was useless because `<rout theme name>` works fine even on older Keycloak version.
|
|
||||||
|
|
||||||
What you have to remember is that:
|
|
||||||
|
|
||||||
- If you have no account theme: You can use the `retrocompat_*.jar` it will work on any Keycloak version.
|
|
||||||
- If you have an Account theme: Use `retrocompat_*.jar` only if your Keycloak is in a version prior to 23.
|
|
||||||
Keycloak 22 is not supported (Only login themes works in Keycloak 22).
|
|
||||||
|
|
||||||
## 9.0
|
## 9.0
|
||||||
|
|
||||||
Bring back support for account themes in Keycloak v23 and up! [See issue](https://github.com/keycloakify/keycloakify/issues/389).
|
Bring back support for account themes in Keycloak v23 and up! [See issue](https://github.com/keycloakify/keycloakify/issues/389).
|
||||||
|
@ -3,6 +3,7 @@ export const resources_common = "resources-common";
|
|||||||
export const lastKeycloakVersionWithAccountV1 = "21.1.2";
|
export const lastKeycloakVersionWithAccountV1 = "21.1.2";
|
||||||
|
|
||||||
export const themeTypes = ["login", "account"] as const;
|
export const themeTypes = ["login", "account"] as const;
|
||||||
|
export const retrocompatPostfix = "_retrocompat";
|
||||||
export const accountV1 = "account-v1";
|
export const accountV1 = "account-v1";
|
||||||
|
|
||||||
export type ThemeType = (typeof themeTypes)[number];
|
export type ThemeType = (typeof themeTypes)[number];
|
||||||
|
@ -27,6 +27,51 @@ export async function downloadBuiltinKeycloakTheme(params: { keycloakVersion: st
|
|||||||
"preCacheTransform": {
|
"preCacheTransform": {
|
||||||
"actionCacheId": "npm install and build",
|
"actionCacheId": "npm install and build",
|
||||||
"action": async ({ destDirPath }) => {
|
"action": async ({ destDirPath }) => {
|
||||||
|
fix_account_css: {
|
||||||
|
const accountCssFilePath = pathJoin(destDirPath, "keycloak", "account", "resources", "css", "account.css");
|
||||||
|
|
||||||
|
if (!fs.existsSync(accountCssFilePath)) {
|
||||||
|
break fix_account_css;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
accountCssFilePath,
|
||||||
|
Buffer.from(fs.readFileSync(accountCssFilePath).toString("utf8").replace("top: -34px;", "top: -34px !important;"), "utf8")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fix_account_topt: {
|
||||||
|
const totpFtlFilePath = pathJoin(destDirPath, "base", "account", "totp.ftl");
|
||||||
|
|
||||||
|
if (!fs.existsSync(totpFtlFilePath)) {
|
||||||
|
break fix_account_topt;
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.writeFileSync(
|
||||||
|
totpFtlFilePath,
|
||||||
|
Buffer.from(
|
||||||
|
fs
|
||||||
|
.readFileSync(totpFtlFilePath)
|
||||||
|
.toString("utf8")
|
||||||
|
.replace(
|
||||||
|
[
|
||||||
|
" <#list totp.policy.supportedApplications as app>",
|
||||||
|
" <li>${app}</li>",
|
||||||
|
" </#list>"
|
||||||
|
].join("\n"),
|
||||||
|
[
|
||||||
|
" <#if totp.policy.supportedApplications?has_content>",
|
||||||
|
" <#list totp.policy.supportedApplications as app>",
|
||||||
|
" <li>${app}</li>",
|
||||||
|
" </#list>",
|
||||||
|
" </#if>"
|
||||||
|
].join("\n")
|
||||||
|
),
|
||||||
|
"utf8"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
install_common_node_modules: {
|
install_common_node_modules: {
|
||||||
const commonResourcesDirPath = pathJoin(destDirPath, "keycloak", "common", "resources");
|
const commonResourcesDirPath = pathJoin(destDirPath, "keycloak", "common", "resources");
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ export type BuildOptions = {
|
|||||||
/** If your app is hosted under a subpath, it's the case in CRA if you have "homepage": "https://example.com/my-app" in your package.json
|
/** If your app is hosted under a subpath, it's the case in CRA if you have "homepage": "https://example.com/my-app" in your package.json
|
||||||
* In this case the urlPathname will be "/my-app/" */
|
* In this case the urlPathname will be "/my-app/" */
|
||||||
urlPathname: string | undefined;
|
urlPathname: string | undefined;
|
||||||
|
doBuildRetrocompatAccountTheme: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function readBuildOptions(params: { reactAppRootDirPath: string; processArgv: string[] }): BuildOptions {
|
export function readBuildOptions(params: { reactAppRootDirPath: string; processArgv: string[] }): BuildOptions {
|
||||||
@ -150,6 +151,7 @@ export function readBuildOptions(params: { reactAppRootDirPath: string; processA
|
|||||||
|
|
||||||
const out = url.pathname.replace(/([^/])$/, "$1/");
|
const out = url.pathname.replace(/([^/])$/, "$1/");
|
||||||
return out === "/" ? undefined : out;
|
return out === "/" ? undefined : out;
|
||||||
})()
|
})(),
|
||||||
|
"doBuildRetrocompatAccountTheme": parsedPackageJson.keycloakify?.doBuildRetrocompatAccountTheme ?? true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,21 @@ export async function bringInAccountV1(params: { buildOptions: BuildOptionsLike
|
|||||||
|
|
||||||
const commonResourceFilePaths = [
|
const commonResourceFilePaths = [
|
||||||
"node_modules/patternfly/dist/css/patternfly.min.css",
|
"node_modules/patternfly/dist/css/patternfly.min.css",
|
||||||
"node_modules/patternfly/dist/css/patternfly-additions.min.css"
|
"node_modules/patternfly/dist/css/patternfly-additions.min.css",
|
||||||
|
...[
|
||||||
|
"OpenSans-Light-webfont.woff2",
|
||||||
|
"OpenSans-Regular-webfont.woff2",
|
||||||
|
"OpenSans-Bold-webfont.woff2",
|
||||||
|
"OpenSans-Semibold-webfont.woff2",
|
||||||
|
"OpenSans-Bold-webfont.woff",
|
||||||
|
"OpenSans-Light-webfont.woff",
|
||||||
|
"OpenSans-Regular-webfont.woff",
|
||||||
|
"OpenSans-Semibold-webfont.woff",
|
||||||
|
"OpenSans-Regular-webfont.ttf",
|
||||||
|
"OpenSans-Light-webfont.ttf",
|
||||||
|
"OpenSans-Semibold-webfont.ttf",
|
||||||
|
"OpenSans-Bold-webfont.ttf"
|
||||||
|
].map(path => `node_modules/patternfly/dist/fonts/${path}`)
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const relativeFilePath of commonResourceFilePaths.map(path => pathJoin(...path.split("/")))) {
|
for (const relativeFilePath of commonResourceFilePaths.map(path => pathJoin(...path.split("/")))) {
|
||||||
@ -49,7 +63,7 @@ export async function bringInAccountV1(params: { buildOptions: BuildOptionsLike
|
|||||||
fs.cpSync(pathJoin(builtinKeycloakThemeTmpDirPath, "keycloak", "common", "resources", relativeFilePath), destFilePath);
|
fs.cpSync(pathJoin(builtinKeycloakThemeTmpDirPath, "keycloak", "common", "resources", relativeFilePath), destFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
const resourceFilePaths = ["css/account.css"];
|
const resourceFilePaths = ["css/account.css", "img/icon-sidebar-active.png", "img/logo.png"];
|
||||||
|
|
||||||
for (const relativeFilePath of resourceFilePaths.map(path => pathJoin(...path.split("/")))) {
|
for (const relativeFilePath of resourceFilePaths.map(path => pathJoin(...path.split("/")))) {
|
||||||
const destFilePath = pathJoin(accountV1DirPath, "resources", relativeFilePath);
|
const destFilePath = pathJoin(accountV1DirPath, "resources", relativeFilePath);
|
||||||
@ -69,7 +83,7 @@ export async function bringInAccountV1(params: { buildOptions: BuildOptionsLike
|
|||||||
"",
|
"",
|
||||||
"locales=ar,ca,cs,da,de,en,es,fr,fi,hu,it,ja,lt,nl,no,pl,pt-BR,ru,sk,sv,tr,zh-CN",
|
"locales=ar,ca,cs,da,de,en,es,fr,fi,hu,it,ja,lt,nl,no,pl,pt-BR,ru,sk,sv,tr,zh-CN",
|
||||||
"",
|
"",
|
||||||
"styles=" + [...resourceFilePaths, ...commonResourceFilePaths.map(path => `resources_common/${path}`)].join(" "),
|
"styles=" + [...resourceFilePaths, ...commonResourceFilePaths.map(path => `resources-common/${path}`)].join(" "),
|
||||||
"",
|
"",
|
||||||
"##### css classes for form buttons",
|
"##### css classes for form buttons",
|
||||||
"# main class used for all buttons",
|
"# main class used for all buttons",
|
||||||
|
@ -3,7 +3,7 @@ import { join as pathJoin, dirname as pathDirname } from "path";
|
|||||||
import { assert } from "tsafe/assert";
|
import { assert } from "tsafe/assert";
|
||||||
import { Reflect } from "tsafe/Reflect";
|
import { Reflect } from "tsafe/Reflect";
|
||||||
import type { BuildOptions } from "../BuildOptions";
|
import type { BuildOptions } from "../BuildOptions";
|
||||||
import { type ThemeType, accountV1 } from "../../constants";
|
import { type ThemeType, retrocompatPostfix, accountV1 } from "../../constants";
|
||||||
import { bringInAccountV1 } from "./bringInAccountV1";
|
import { bringInAccountV1 } from "./bringInAccountV1";
|
||||||
|
|
||||||
export type BuildOptionsLike = {
|
export type BuildOptionsLike = {
|
||||||
@ -13,6 +13,7 @@ export type BuildOptionsLike = {
|
|||||||
cacheDirPath: string;
|
cacheDirPath: string;
|
||||||
keycloakifyBuildDirPath: string;
|
keycloakifyBuildDirPath: string;
|
||||||
themeNames: string[];
|
themeNames: string[];
|
||||||
|
doBuildRetrocompatAccountTheme: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -113,7 +114,15 @@ export async function generateJavaStackFiles(params: {
|
|||||||
"types": Object.entries(implementedThemeTypes)
|
"types": Object.entries(implementedThemeTypes)
|
||||||
.filter(([, isImplemented]) => isImplemented)
|
.filter(([, isImplemented]) => isImplemented)
|
||||||
.map(([themeType]) => themeType)
|
.map(([themeType]) => themeType)
|
||||||
}
|
},
|
||||||
|
...(!implementedThemeTypes.account || !buildOptions.doBuildRetrocompatAccountTheme
|
||||||
|
? []
|
||||||
|
: [
|
||||||
|
{
|
||||||
|
"name": `${themeName}${retrocompatPostfix}`,
|
||||||
|
"types": ["account"]
|
||||||
|
}
|
||||||
|
])
|
||||||
])
|
])
|
||||||
.flat()
|
.flat()
|
||||||
]
|
]
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { transformCodebase } from "../../tools/transformCodebase";
|
import { transformCodebase } from "../../tools/transformCodebase";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import { join as pathJoin, resolve as pathResolve } from "path";
|
import { join as pathJoin, basename as pathBasename, resolve as pathResolve } from "path";
|
||||||
import { replaceImportsFromStaticInJsCode } from "../replacers/replaceImportsFromStaticInJsCode";
|
import { replaceImportsFromStaticInJsCode } from "../replacers/replaceImportsFromStaticInJsCode";
|
||||||
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
|
import { replaceImportsInCssCode } from "../replacers/replaceImportsInCssCode";
|
||||||
import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds } from "../generateFtl";
|
import { generateFtlFilesCodeFactory, loginThemePageIds, accountThemePageIds } from "../generateFtl";
|
||||||
import { themeTypes, type ThemeType, lastKeycloakVersionWithAccountV1, keycloak_resources, accountV1 } from "../../constants";
|
import { themeTypes, type ThemeType, lastKeycloakVersionWithAccountV1, keycloak_resources, retrocompatPostfix, accountV1 } from "../../constants";
|
||||||
import { isInside } from "../../tools/isInside";
|
import { isInside } from "../../tools/isInside";
|
||||||
import type { BuildOptions } from "../BuildOptions";
|
import type { BuildOptions } from "../BuildOptions";
|
||||||
import { assert, type Equals } from "tsafe/assert";
|
import { assert, type Equals } from "tsafe/assert";
|
||||||
@ -22,6 +22,7 @@ export type BuildOptionsLike = {
|
|||||||
keycloakifyBuildDirPath: string;
|
keycloakifyBuildDirPath: string;
|
||||||
reactAppBuildDirPath: string;
|
reactAppBuildDirPath: string;
|
||||||
cacheDirPath: string;
|
cacheDirPath: string;
|
||||||
|
doBuildRetrocompatAccountTheme: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
assert<BuildOptions extends BuildOptionsLike ? true : false>();
|
||||||
@ -35,9 +36,17 @@ export async function generateTheme(params: {
|
|||||||
}): Promise<void> {
|
}): Promise<void> {
|
||||||
const { themeName, themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion } = params;
|
const { themeName, themeSrcDirPath, keycloakifySrcDirPath, buildOptions, keycloakifyVersion } = params;
|
||||||
|
|
||||||
const getThemeTypeDirPath = (params: { themeType: ThemeType | "email" }) => {
|
const getThemeTypeDirPath = (params: { themeType: ThemeType | "email"; isRetrocompat?: true }) => {
|
||||||
const { themeType } = params;
|
const { themeType, isRetrocompat = false } = params;
|
||||||
return pathJoin(buildOptions.keycloakifyBuildDirPath, "src", "main", "resources", "theme", themeName, themeType);
|
return pathJoin(
|
||||||
|
buildOptions.keycloakifyBuildDirPath,
|
||||||
|
"src",
|
||||||
|
"main",
|
||||||
|
"resources",
|
||||||
|
"theme",
|
||||||
|
`${themeName}${isRetrocompat ? retrocompatPostfix : ""}`,
|
||||||
|
themeType
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let allCssGlobalsToDefine: Record<string, string> = {};
|
let allCssGlobalsToDefine: Record<string, string> = {};
|
||||||
@ -192,6 +201,22 @@ export async function generateTheme(params: {
|
|||||||
"utf8"
|
"utf8"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (themeType === "account" && buildOptions.doBuildRetrocompatAccountTheme) {
|
||||||
|
transformCodebase({
|
||||||
|
"srcDirPath": themeTypeDirPath,
|
||||||
|
"destDirPath": getThemeTypeDirPath({ themeType, "isRetrocompat": true }),
|
||||||
|
"transformSourceCode": ({ filePath, sourceCode }) => {
|
||||||
|
if (pathBasename(filePath) === "theme.properties") {
|
||||||
|
return {
|
||||||
|
"modifiedSourceCode": Buffer.from(sourceCode.toString("utf8").replace(`parent=${accountV1}`, "parent=keycloak"), "utf8")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return { "modifiedSourceCode": sourceCode };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
email: {
|
email: {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { getLatestsSemVersionedTagFactory } from "./tools/octokit-addons/getLatestsSemVersionedTag";
|
import { getLatestsSemVersionedTagFactory } from "./tools/octokit-addons/getLatestsSemVersionedTag";
|
||||||
import { Octokit } from "@octokit/rest";
|
import { Octokit } from "@octokit/rest";
|
||||||
import cliSelect from "cli-select";
|
import cliSelect from "cli-select";
|
||||||
|
import { lastKeycloakVersionWithAccountV1 } from "./constants";
|
||||||
|
|
||||||
export async function promptKeycloakVersion() {
|
export async function promptKeycloakVersion() {
|
||||||
const { getLatestsSemVersionedTag } = (() => {
|
const { getLatestsSemVersionedTag } = (() => {
|
||||||
@ -26,6 +27,7 @@ export async function promptKeycloakVersion() {
|
|||||||
"owner": "keycloak",
|
"owner": "keycloak",
|
||||||
"repo": "keycloak"
|
"repo": "keycloak"
|
||||||
}).then(arr => arr.map(({ tag }) => tag))),
|
}).then(arr => arr.map(({ tag }) => tag))),
|
||||||
|
lastKeycloakVersionWithAccountV1,
|
||||||
"11.0.3"
|
"11.0.3"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user