keycloakify 7.6.2 → 7.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/account/kcContext/KcContext.d.ts +1 -0
- package/account/kcContext/KcContext.js.map +1 -1
- package/account/kcContext/getKcContext.js +3 -1
- package/account/kcContext/getKcContext.js.map +1 -1
- package/account/kcContext/kcContextMocks.js +1 -0
- package/account/kcContext/kcContextMocks.js.map +1 -1
- package/bin/eject-keycloak-page.js +7 -7
- package/bin/eject-keycloak-page.js.map +1 -1
- package/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +2 -2
- package/bin/keycloakify/generateFtl/generateFtl.d.ts +1 -4
- package/bin/keycloakify/generateFtl/generateFtl.js +5 -32
- package/bin/keycloakify/generateFtl/generateFtl.js.map +1 -1
- package/bin/keycloakify/generateFtl/index.d.ts +1 -0
- package/bin/keycloakify/generateFtl/index.js +1 -0
- package/bin/keycloakify/generateFtl/index.js.map +1 -1
- package/bin/keycloakify/generateFtl/pageId.d.ts +4 -0
- package/bin/keycloakify/generateFtl/pageId.js +30 -0
- package/bin/keycloakify/generateFtl/pageId.js.map +1 -0
- package/bin/keycloakify/generateKeycloakThemeResources.d.ts +1 -0
- package/bin/keycloakify/generateKeycloakThemeResources.js +4 -3
- package/bin/keycloakify/generateKeycloakThemeResources.js.map +1 -1
- package/bin/keycloakify/keycloakify.js +7 -1
- package/bin/keycloakify/keycloakify.js.map +1 -1
- package/bin/tools/jar.d.ts +19 -3
- package/bin/tools/jar.js +151 -58
- package/bin/tools/jar.js.map +1 -1
- package/bin/tools/walk.d.ts +1 -1
- package/login/kcContext/KcContext.d.ts +1 -0
- package/login/kcContext/KcContext.js.map +1 -1
- package/login/kcContext/getKcContext.js +2 -1
- package/login/kcContext/getKcContext.js.map +1 -1
- package/login/kcContext/kcContextMocks.js +1 -0
- package/login/kcContext/kcContextMocks.js.map +1 -1
- package/login/lib/useDownloadTerms.d.ts +1 -2
- package/login/pages/Terms.js +3 -2
- package/login/pages/Terms.js.map +1 -1
- package/package.json +7 -5
- package/src/account/kcContext/KcContext.ts +1 -0
- package/src/account/kcContext/getKcContext.ts +3 -1
- package/src/account/kcContext/kcContextMocks.ts +1 -0
- package/src/bin/eject-keycloak-page.ts +3 -5
- package/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +2 -2
- package/src/bin/keycloakify/generateFtl/generateFtl.ts +4 -34
- package/src/bin/keycloakify/generateFtl/index.ts +1 -0
- package/src/bin/keycloakify/generateFtl/pageId.ts +30 -0
- package/src/bin/keycloakify/generateKeycloakThemeResources.ts +4 -2
- package/src/bin/keycloakify/keycloakify.ts +9 -1
- package/src/bin/tools/jar.ts +58 -65
- package/src/bin/tools/walk.ts +1 -1
- package/src/login/kcContext/KcContext.ts +1 -0
- package/src/login/kcContext/getKcContext.ts +2 -1
- package/src/login/kcContext/kcContextMocks.ts +1 -0
- package/src/login/lib/useDownloadTerms.ts +1 -1
- package/src/login/pages/Terms.tsx +6 -2
- package/bin/tools/zip.d.ts +0 -29
- package/bin/tools/zip.js +0 -330
- package/bin/tools/zip.js.map +0 -1
- package/src/bin/tools/zip.ts +0 -246
@@ -13,37 +13,6 @@ export const themeTypes = ["login", "account"] as const;
|
|
13
13
|
|
14
14
|
export type ThemeType = (typeof themeTypes)[number];
|
15
15
|
|
16
|
-
export const loginThemePageIds = [
|
17
|
-
"login.ftl",
|
18
|
-
"login-username.ftl",
|
19
|
-
"login-password.ftl",
|
20
|
-
"webauthn-authenticate.ftl",
|
21
|
-
"register.ftl",
|
22
|
-
"register-user-profile.ftl",
|
23
|
-
"info.ftl",
|
24
|
-
"error.ftl",
|
25
|
-
"login-reset-password.ftl",
|
26
|
-
"login-verify-email.ftl",
|
27
|
-
"terms.ftl",
|
28
|
-
"login-otp.ftl",
|
29
|
-
"login-update-profile.ftl",
|
30
|
-
"login-update-password.ftl",
|
31
|
-
"login-idp-link-confirm.ftl",
|
32
|
-
"login-idp-link-email.ftl",
|
33
|
-
"login-page-expired.ftl",
|
34
|
-
"login-config-totp.ftl",
|
35
|
-
"logout-confirm.ftl",
|
36
|
-
"update-user-profile.ftl",
|
37
|
-
"idp-review-user-profile.ftl",
|
38
|
-
"update-email.ftl",
|
39
|
-
"select-authenticator.ftl"
|
40
|
-
] as const;
|
41
|
-
|
42
|
-
export const accountThemePageIds = ["password.ftl", "account.ftl"] as const;
|
43
|
-
|
44
|
-
export type LoginThemePageId = (typeof loginThemePageIds)[number];
|
45
|
-
export type AccountThemePageId = (typeof accountThemePageIds)[number];
|
46
|
-
|
47
16
|
export type BuildOptionsLike = BuildOptionsLike.Standalone | BuildOptionsLike.ExternalAssets;
|
48
17
|
|
49
18
|
export namespace BuildOptionsLike {
|
@@ -84,8 +53,9 @@ export function generateFtlFilesCodeFactory(params: {
|
|
84
53
|
//NOTE: Expected to be an empty object if external assets mode is enabled.
|
85
54
|
cssGlobalsToDefine: Record<string, string>;
|
86
55
|
buildOptions: BuildOptionsLike;
|
56
|
+
keycloakifyVersion: string;
|
87
57
|
}) {
|
88
|
-
const { cssGlobalsToDefine, indexHtmlCode, buildOptions } = params;
|
58
|
+
const { cssGlobalsToDefine, indexHtmlCode, buildOptions, keycloakifyVersion } = params;
|
89
59
|
|
90
60
|
const $ = cheerio.load(indexHtmlCode);
|
91
61
|
|
@@ -159,7 +129,8 @@ export function generateFtlFilesCodeFactory(params: {
|
|
159
129
|
.replace(
|
160
130
|
"CUSTOM_USER_ATTRIBUTES_eKsIY4ZsZ4xeM",
|
161
131
|
buildOptions.customUserAttributes.length === 0 ? "" : ", " + buildOptions.customUserAttributes.map(name => `"${name}"`).join(", ")
|
162
|
-
)
|
132
|
+
)
|
133
|
+
.replace("KEYCLOAKIFY_VERSION_xEdKd3xEdr", keycloakifyVersion),
|
163
134
|
"<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->": [
|
164
135
|
"<#if scripts??>",
|
165
136
|
" <#list scripts as script>",
|
@@ -192,7 +163,6 @@ export function generateFtlFilesCodeFactory(params: {
|
|
192
163
|
|
193
164
|
Object.entries({
|
194
165
|
...replaceValueBySearchValue,
|
195
|
-
//If updated, don't forget to change in the ftl script as well.
|
196
166
|
"PAGE_ID_xIgLsPgGId9D8e": pageId
|
197
167
|
}).map(([searchValue, replaceValue]) => (ftlCode = ftlCode.replace(searchValue, replaceValue)));
|
198
168
|
|
@@ -0,0 +1,30 @@
|
|
1
|
+
export const loginThemePageIds = [
|
2
|
+
"login.ftl",
|
3
|
+
"login-username.ftl",
|
4
|
+
"login-password.ftl",
|
5
|
+
"webauthn-authenticate.ftl",
|
6
|
+
"register.ftl",
|
7
|
+
"register-user-profile.ftl",
|
8
|
+
"info.ftl",
|
9
|
+
"error.ftl",
|
10
|
+
"login-reset-password.ftl",
|
11
|
+
"login-verify-email.ftl",
|
12
|
+
"terms.ftl",
|
13
|
+
"login-otp.ftl",
|
14
|
+
"login-update-profile.ftl",
|
15
|
+
"login-update-password.ftl",
|
16
|
+
"login-idp-link-confirm.ftl",
|
17
|
+
"login-idp-link-email.ftl",
|
18
|
+
"login-page-expired.ftl",
|
19
|
+
"login-config-totp.ftl",
|
20
|
+
"logout-confirm.ftl",
|
21
|
+
"update-user-profile.ftl",
|
22
|
+
"idp-review-user-profile.ftl",
|
23
|
+
"update-email.ftl",
|
24
|
+
"select-authenticator.ftl"
|
25
|
+
] as const;
|
26
|
+
|
27
|
+
export const accountThemePageIds = ["password.ftl", "account.ftl"] as const;
|
28
|
+
|
29
|
+
export type LoginThemePageId = (typeof loginThemePageIds)[number];
|
30
|
+
export type AccountThemePageId = (typeof accountThemePageIds)[number];
|
@@ -54,8 +54,9 @@ export async function generateKeycloakThemeResources(params: {
|
|
54
54
|
emailThemeSrcDirPath: string | undefined;
|
55
55
|
keycloakVersion: string;
|
56
56
|
buildOptions: BuildOptionsLike;
|
57
|
+
keycloakifyVersion: string;
|
57
58
|
}): Promise<{ doBundlesEmailTemplate: boolean }> {
|
58
|
-
const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, emailThemeSrcDirPath, keycloakVersion, buildOptions } = params;
|
59
|
+
const { reactAppBuildDirPath, keycloakThemeBuildingDirPath, emailThemeSrcDirPath, keycloakVersion, buildOptions, keycloakifyVersion } = params;
|
59
60
|
|
60
61
|
const getThemeDirPath = (themeType: ThemeType | "email") =>
|
61
62
|
pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme", buildOptions.themeName, themeType);
|
@@ -138,7 +139,8 @@ export async function generateKeycloakThemeResources(params: {
|
|
138
139
|
const { generateFtlFilesCode } = generateFtlFilesCodeFactory({
|
139
140
|
"indexHtmlCode": fs.readFileSync(pathJoin(reactAppBuildDirPath, "index.html")).toString("utf8"),
|
140
141
|
"cssGlobalsToDefine": allCssGlobalsToDefine,
|
141
|
-
buildOptions
|
142
|
+
buildOptions,
|
143
|
+
keycloakifyVersion
|
142
144
|
});
|
143
145
|
|
144
146
|
return generateFtlFilesCode;
|
@@ -11,6 +11,7 @@ import jar from "../tools/jar";
|
|
11
11
|
import { assert } from "tsafe/assert";
|
12
12
|
import { Equals } from "tsafe";
|
13
13
|
import { getEmailThemeSrcDirPath } from "../getSrcDirPath";
|
14
|
+
import { getProjectRoot } from "../tools/getProjectRoot";
|
14
15
|
|
15
16
|
export async function main() {
|
16
17
|
const { isSilent, hasExternalAssets } = getCliOptions(process.argv.slice(2));
|
@@ -38,7 +39,14 @@ export async function main() {
|
|
38
39
|
})(),
|
39
40
|
"reactAppBuildDirPath": buildOptions.reactAppBuildDirPath,
|
40
41
|
buildOptions,
|
41
|
-
"keycloakVersion": buildOptions.keycloakVersionDefaultAssets
|
42
|
+
"keycloakVersion": buildOptions.keycloakVersionDefaultAssets,
|
43
|
+
"keycloakifyVersion": (() => {
|
44
|
+
const version = JSON.parse(fs.readFileSync(pathJoin(getProjectRoot(), "package.json")).toString("utf8"))["version"];
|
45
|
+
|
46
|
+
assert(typeof version === "string");
|
47
|
+
|
48
|
+
return version;
|
49
|
+
})()
|
42
50
|
});
|
43
51
|
|
44
52
|
const { jarFilePath } = generateJavaStackFiles({
|
package/src/bin/tools/jar.ts
CHANGED
@@ -1,94 +1,87 @@
|
|
1
|
-
import { Readable, Transform } from "stream";
|
2
1
|
import { dirname, relative, sep } from "path";
|
3
2
|
import { createWriteStream } from "fs";
|
4
3
|
|
5
4
|
import walk from "./walk";
|
6
|
-
import
|
5
|
+
import { ZipFile } from "yazl";
|
7
6
|
import { mkdir } from "fs/promises";
|
8
7
|
import trimIndent from "./trimIndent";
|
9
8
|
|
10
|
-
type
|
11
|
-
|
12
|
-
|
9
|
+
export type ZipEntry = { zipPath: string } & ({ fsPath: string } | { buffer: Buffer });
|
10
|
+
export type ZipEntryGenerator = AsyncGenerator<ZipEntry, void, unknown>;
|
11
|
+
|
12
|
+
type CommonJarArgs = {
|
13
13
|
groupId: string;
|
14
14
|
artifactId: string;
|
15
15
|
version: string;
|
16
16
|
};
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
export type JarStreamArgs = CommonJarArgs & {
|
19
|
+
asyncPathGeneratorFn(): ZipEntryGenerator;
|
20
|
+
};
|
21
|
+
|
22
|
+
export type JarArgs = CommonJarArgs & {
|
23
|
+
targetPath: string;
|
24
|
+
rootPath: string;
|
25
|
+
};
|
26
|
+
|
27
|
+
export async function jarStream({ groupId, artifactId, version, asyncPathGeneratorFn }: JarStreamArgs) {
|
28
|
+
const manifestPath = "META-INF/MANIFEST.MF";
|
29
|
+
const manifestData = Buffer.from(trimIndent`
|
27
30
|
Manifest-Version: 1.0
|
28
31
|
Archiver-Version: Plexus Archiver
|
29
32
|
Created-By: Keycloakify
|
30
33
|
Built-By: unknown
|
31
34
|
Build-Jdk: 19.0.0
|
32
|
-
`)
|
33
|
-
};
|
35
|
+
`);
|
34
36
|
|
35
|
-
const
|
36
|
-
|
37
|
-
|
38
|
-
# ${new Date()
|
37
|
+
const pomPropsPath = `META-INF/maven/${groupId}/${artifactId}/pom.properties`;
|
38
|
+
const pomPropsData = Buffer.from(trimIndent`
|
39
|
+
# Generated by keycloakify
|
40
|
+
# ${new Date()}
|
39
41
|
artifactId=${artifactId}
|
40
42
|
groupId=${groupId}
|
41
43
|
version=${version}
|
42
|
-
`)
|
43
|
-
};
|
44
|
+
`);
|
44
45
|
|
45
|
-
|
46
|
-
* Convert every path entry to a ZipSource record, and when all records are
|
47
|
-
* processed, append records for MANIFEST.mf and pom.properties
|
48
|
-
*/
|
49
|
-
const pathToRecord = () =>
|
50
|
-
new Transform({
|
51
|
-
objectMode: true,
|
52
|
-
transform: function (fsPath, _, cb) {
|
53
|
-
const path = relative(rootPath, fsPath).split(sep).join("/");
|
54
|
-
this.push({ path, fsPath });
|
55
|
-
cb();
|
56
|
-
},
|
57
|
-
final: function () {
|
58
|
-
this.push(manifest);
|
59
|
-
this.push(pomProps);
|
60
|
-
this.push(null);
|
61
|
-
}
|
62
|
-
});
|
46
|
+
const zipFile = new ZipFile();
|
63
47
|
|
64
|
-
await
|
48
|
+
for await (const entry of asyncPathGeneratorFn()) {
|
49
|
+
if ("buffer" in entry) {
|
50
|
+
zipFile.addBuffer(entry.buffer, entry.zipPath);
|
51
|
+
} else if ("fsPath" in entry && entry.fsPath.endsWith(sep)) {
|
52
|
+
zipFile.addFile(entry.fsPath, entry.zipPath);
|
53
|
+
}
|
54
|
+
}
|
65
55
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
// let the zip lib convert all ZipSource objects into a byte stream
|
73
|
-
.pipe(zip())
|
74
|
-
// write that byte stream to targetPath
|
75
|
-
.pipe(createWriteStream(targetPath, { encoding: "binary" }))
|
76
|
-
.on("finish", () => resolve())
|
77
|
-
.on("error", e => reject(e));
|
78
|
-
});
|
56
|
+
zipFile.addBuffer(manifestData, manifestPath);
|
57
|
+
zipFile.addBuffer(pomPropsData, pomPropsPath);
|
58
|
+
|
59
|
+
zipFile.end();
|
60
|
+
|
61
|
+
return zipFile;
|
79
62
|
}
|
80
63
|
|
81
64
|
/**
|
82
|
-
*
|
65
|
+
* Create a jar archive, using the resources found at `rootPath` (a directory) and write the
|
66
|
+
* archive to `targetPath` (a file). Use `groupId`, `artifactId` and `version` to define
|
67
|
+
* the contents of the pom.properties file which is going to be added to the archive.
|
83
68
|
*/
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
69
|
+
export default async function jar({ groupId, artifactId, version, rootPath, targetPath }: JarArgs) {
|
70
|
+
await mkdir(dirname(targetPath), { recursive: true });
|
71
|
+
|
72
|
+
const asyncPathGeneratorFn = async function* (): ZipEntryGenerator {
|
73
|
+
for await (const fsPath of walk(rootPath)) {
|
74
|
+
const zipPath = relative(rootPath, fsPath).split(sep).join("/");
|
75
|
+
yield { fsPath, zipPath };
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
const zipFile = await jarStream({ groupId, artifactId, version, asyncPathGeneratorFn });
|
80
|
+
|
81
|
+
await new Promise<void>(async (resolve, reject) => {
|
82
|
+
zipFile.outputStream
|
83
|
+
.pipe(createWriteStream(targetPath, { encoding: "binary" }))
|
84
|
+
.on("close", () => resolve())
|
85
|
+
.on("error", e => reject(e));
|
86
|
+
});
|
94
87
|
}
|
package/src/bin/tools/walk.ts
CHANGED
@@ -8,7 +8,7 @@ import { resolve } from "path";
|
|
8
8
|
* @param root the starting directory
|
9
9
|
* @returns AsyncGenerator
|
10
10
|
*/
|
11
|
-
export default async function* walk(root: string): AsyncGenerator<string, void,
|
11
|
+
export default async function* walk(root: string): AsyncGenerator<string, void, unknown> {
|
12
12
|
for (const entry of await readdir(root, { withFileTypes: true })) {
|
13
13
|
const absolutePath = resolve(root, entry.name);
|
14
14
|
if (entry.isDirectory()) {
|
@@ -11,6 +11,7 @@ import { pathJoin } from "keycloakify/bin/tools/pathJoin";
|
|
11
11
|
import { pathBasename } from "keycloakify/tools/pathBasename";
|
12
12
|
import { mockTestingResourcesCommonPath } from "keycloakify/bin/mockTestingResourcesPath";
|
13
13
|
import { symToStr } from "tsafe/symToStr";
|
14
|
+
import { loginThemePageIds } from "keycloakify/bin/keycloakify/generateFtl/pageId";
|
14
15
|
|
15
16
|
export function getKcContext<KcContextExtension extends { pageId: string } = never>(params?: {
|
16
17
|
mockPageId?: ExtendKcContext<KcContextExtension>["pageId"];
|
@@ -121,7 +122,7 @@ export function getKcContext<KcContextExtension extends { pageId: string } = nev
|
|
121
122
|
return { "kcContext": undefined };
|
122
123
|
}
|
123
124
|
|
124
|
-
if (!("login" in realKcContext)) {
|
125
|
+
if (id<readonly string[]>(loginThemePageIds).indexOf(realKcContext.pageId) < 0 && !("login" in realKcContext)) {
|
125
126
|
return { "kcContext": undefined };
|
126
127
|
}
|
127
128
|
|
@@ -101,6 +101,7 @@ const attributes: Attribute[] = [
|
|
101
101
|
const attributesByName = Object.fromEntries(attributes.map(attribute => [attribute.name, attribute])) as any;
|
102
102
|
|
103
103
|
export const kcContextCommonMock: KcContext.Common = {
|
104
|
+
"keycloakifyVersion": "0.0.0",
|
104
105
|
"url": {
|
105
106
|
"loginAction": "#",
|
106
107
|
"resourcesPath": pathJoin(PUBLIC_URL, mockTestingResourcesPath),
|
@@ -21,13 +21,17 @@ export default function Terms(props: PageProps<Extract<KcContext, { pageId: "ter
|
|
21
21
|
|
22
22
|
const { url } = kcContext;
|
23
23
|
|
24
|
-
|
24
|
+
const termMarkdown = evtTermMarkdown.state;
|
25
|
+
|
26
|
+
if (termMarkdown === undefined) {
|
25
27
|
return null;
|
26
28
|
}
|
27
29
|
|
28
30
|
return (
|
29
31
|
<Template {...{ kcContext, i18n, doUseDefaultCss, classes }} displayMessage={false} headerNode={msg("termsTitle")}>
|
30
|
-
<div id="kc-terms-text">
|
32
|
+
<div id="kc-terms-text">
|
33
|
+
<Markdown>{termMarkdown}</Markdown>
|
34
|
+
</div>
|
31
35
|
<form className="form-actions" action={url.loginAction} method="POST">
|
32
36
|
<input
|
33
37
|
className={clsx(
|
package/bin/tools/zip.d.ts
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
/// <reference types="node" />
|
2
|
-
/// <reference types="node" />
|
3
|
-
import { Transform } from "stream";
|
4
|
-
/**
|
5
|
-
* Zip source
|
6
|
-
* @property filename the name of the entry in the archie
|
7
|
-
* @property path of the source file, if the source is an actual file
|
8
|
-
* @property data the actual data buffer, if the source is constructed in-memory
|
9
|
-
*/
|
10
|
-
export type ZipSource = {
|
11
|
-
path: string;
|
12
|
-
} & ({
|
13
|
-
fsPath: string;
|
14
|
-
} | {
|
15
|
-
data: Buffer;
|
16
|
-
});
|
17
|
-
export type ZipRecord = {
|
18
|
-
path: string;
|
19
|
-
compression: "deflate" | undefined;
|
20
|
-
uncompressedSize: number;
|
21
|
-
compressedSize?: number;
|
22
|
-
crc32?: number;
|
23
|
-
offset?: number;
|
24
|
-
};
|
25
|
-
/**
|
26
|
-
* @returns a stream Transform, which reads a stream of ZipRecords and
|
27
|
-
* writes a bytestream
|
28
|
-
*/
|
29
|
-
export default function zip(): Transform;
|