keycloakify 4.2.11 → 4.2.14-beta.1
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/CHANGELOG.md +9 -0
- package/README.md +22 -20
- package/bin/build-keycloak-theme/build-keycloak-theme.js +7 -4
- package/bin/build-keycloak-theme/build-keycloak-theme.js.map +1 -1
- package/bin/build-keycloak-theme/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +230 -0
- package/bin/build-keycloak-theme/generateFtl/generateFtl.js +26 -25
- package/bin/build-keycloak-theme/generateFtl/generateFtl.js.map +1 -1
- package/package.json +3 -5
- package/src/bin/build-keycloak-theme/build-keycloak-theme.ts +7 -4
- package/src/bin/build-keycloak-theme/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +230 -0
- package/src/bin/build-keycloak-theme/generateFtl/generateFtl.ts +15 -30
- package/bin/build-keycloak-theme/generateFtl/Object.deepAssign.js +0 -28
- package/bin/build-keycloak-theme/generateFtl/common.ftl +0 -208
- package/src/bin/build-keycloak-theme/generateFtl/Object.deepAssign.js +0 -28
- package/src/bin/build-keycloak-theme/generateFtl/common.ftl +0 -208
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
@@ -76,8 +76,8 @@ If you already have a Keycloak custom theme, it can be easily ported to Keycloak
|
|
76
76
|
- [Possible workarounds](#possible-workarounds)
|
77
77
|
- [Implement context persistence (optional)](#implement-context-persistence-optional)
|
78
78
|
- [Kickstart video](#kickstart-video)
|
79
|
-
- [About the errors related to `objectToJson` in Keycloak logs.](#about-the-errors-related-to-objecttojson-in-keycloak-logs)
|
80
|
-
- [The pages take too long to load ?](#the-pages-take-too-long-to-load-)
|
79
|
+
- [About the errors related to `objectToJson` in Keycloak logs. (problem soon to be fixed)](#about-the-errors-related-to-objecttojson-in-keycloak-logs)
|
80
|
+
- [The pages take too long to load ? (soon to be fixed too)](#the-pages-take-too-long-to-load-)
|
81
81
|
- [Adding custom message (to `i18n/useKcMessage.tsx`)](#adding-custom-message-to-i18nusekcmessagetsx)
|
82
82
|
- [Email domain whitelist](#email-domain-whitelist)
|
83
83
|
- [Changelog highlights](#changelog-highlights)
|
@@ -88,6 +88,8 @@ If you already have a Keycloak custom theme, it can be easily ported to Keycloak
|
|
88
88
|
|
89
89
|
# Requirements
|
90
90
|
|
91
|
+
On Windows OS you'll have to use [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10). More info [here](https://github.com/InseeFrLab/keycloakify/issues/54%23issuecomment-984834217)
|
92
|
+
|
91
93
|
Tested with the following Keycloak versions:
|
92
94
|
|
93
95
|
- [11.0.3](https://hub.docker.com/layers/jboss/keycloak/11.0.3/images/sha256-4438f1e51c1369371cb807dffa526e1208086b3ebb9cab009830a178de949782?context=explore)
|
@@ -107,8 +109,6 @@ For more information see [this issue](https://github.com/InseeFrLab/keycloakify/
|
|
107
109
|
- `mvn` ([Maven](https://maven.apache.org/)), `rm`, `mkdir`, `curl`, `unzip` are assumed to be available.
|
108
110
|
- `docker` must be up and running when running `yarn keycloak`.
|
109
111
|
|
110
|
-
On Windows you'll have to use [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10).
|
111
|
-
|
112
112
|
## My framework doesn’t seem to be supported, what can I do?
|
113
113
|
|
114
114
|
Currently Keycloakify is only compatible with `create-react-app` apps.
|
@@ -152,27 +152,23 @@ your index should look something like:
|
|
152
152
|
`src/index.tsx`
|
153
153
|
|
154
154
|
```tsx
|
155
|
-
import {
|
156
|
-
import {
|
157
|
-
|
158
|
-
defaultKcProps,
|
159
|
-
getKcContext
|
160
|
-
} from "keycloakify";
|
161
|
-
import { css } from "tss-react/@emotion/css";
|
155
|
+
import { App } from "./<wherever>/App";
|
156
|
+
import { KcApp, defaultKcProps, getKcContext } from "keycloakify";
|
157
|
+
import { css } from "tss-react/@emotion/css";
|
162
158
|
|
163
159
|
const { kcContext } = getKcContext();
|
164
160
|
|
165
161
|
const myClassName = css({ "color": "red" });
|
166
162
|
|
167
163
|
reactDom.render(
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
document.getElementById("root")
|
164
|
+
<KcApp
|
165
|
+
kcContext={kcContext}
|
166
|
+
{...{
|
167
|
+
...defaultKcProps,
|
168
|
+
"kcHeaderWrapperClass": myClassName,
|
169
|
+
}}
|
170
|
+
/>,
|
171
|
+
document.getElementById("root"),
|
176
172
|
);
|
177
173
|
```
|
178
174
|
|
@@ -374,7 +370,8 @@ this limitation doesn't apply, you can import fonts however you see fit.
|
|
374
370
|
- If it is possible, use Google Fonts or any other font provider.
|
375
371
|
- If you want to host your font recommended approach is to move your fonts into the `public`
|
376
372
|
directory and to place your `@font-face` statements in the `public/index.html`.
|
377
|
-
Example [here](https://github.com/
|
373
|
+
Example [here](https://github.com/garronej/keycloakify-demo-app/blob/9aa2dbaec28a7786d6b2983c9a59d393dec1b2d6/public/index.html#L27-L73)
|
374
|
+
(and the font are [here](https://github.com/garronej/keycloakify-demo-app/tree/main/public/fonts/WorkSans)).
|
378
375
|
- You can also [use non relative url](https://github.com/garronej/keycloakify-demo-app/blob/2de8a9eb6f5de9c94f9cd3991faad0377e63268c/src/fonts.scss#L16) but don't forget [`Access-Control-Allow-Origin`](https://github.com/garronej/keycloakify-demo-app/blob/2de8a9eb6f5de9c94f9cd3991faad0377e63268c/nginx.conf#L17-L19).
|
379
376
|
|
380
377
|
# Implement context persistence (optional)
|
@@ -466,6 +463,11 @@ It's all-right because every statement that can fail is inside an `<#attempt><#r
|
|
466
463
|
|
467
464
|
The problem of templates taking a long time to load only happens in the test environment, when you have a console logging all the above-mentioned `.ftl` warnings in real time. Logging all those warnings is what takes time. Once in production page load is way faster.
|
468
465
|
|
466
|
+
If you run the docker container locally we acknowledge that the loading time is getting out of hand.
|
467
|
+
We are [in the process](https://github.com/InseeFrLab/keycloakify/pull/63) of resolving this issue.
|
468
|
+
|
469
|
+
In the meantime we recommend [to run the docker container as a background task](https://youtu.be/F29Z1GaH-jk).
|
470
|
+
|
469
471
|
# Adding custom message (to `i18n/useKcMessage.tsx`)
|
470
472
|
|
471
473
|
You can reproduce [this approach](https://github.com/garronej/keycloakify-demo-app/blob/main/src/kcMessagesExtension.ts)
|
@@ -127,11 +127,14 @@ function main() {
|
|
127
127
|
"",
|
128
128
|
"\uD83D\uDC49 $ ./" + (0, path_1.relative)(reactProjectDirPath, (0, path_1.join)(exports.keycloakThemeBuildingDirPath, generateDebugFiles_1.containerLaunchScriptBasename)) + " \uD83D\uDC48",
|
129
129
|
"",
|
130
|
-
|
131
|
-
"
|
132
|
-
|
130
|
+
"Once your container is up and running: ",
|
131
|
+
"- Log into the admin console 👉 http://localhost:8080 username: admin, password: admin 👈",
|
132
|
+
'- Create a realm named "myrealm"',
|
133
|
+
'- Create a client with id "myclient" and root url: "https://www.keycloak.org/app/"',
|
134
|
+
"- Select Login Theme: " + themeName + " (don't forget to save at the bottom of the page)",
|
135
|
+
"- Go to \uD83D\uDC49 https://www.keycloak.org/app/ \uD83D\uDC48 Click \"Save\" then \"Sign in\". You should see your login page",
|
133
136
|
"",
|
134
|
-
"
|
137
|
+
"Video demoing this process: https://youtu.be/N3wlBoH4hKg",
|
135
138
|
"",
|
136
139
|
].join("\n"));
|
137
140
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"build-keycloak-theme.js","sourceRoot":"","sources":["../../src/bin/build-keycloak-theme/build-keycloak-theme.ts"],"names":[],"mappings":"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
|
1
|
+
{"version":3,"file":"build-keycloak-theme.js","sourceRoot":"","sources":["../../src/bin/build-keycloak-theme/build-keycloak-theme.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,230 @@
|
|
1
|
+
<script>const _=
|
2
|
+
(()=>{
|
3
|
+
|
4
|
+
const out =
|
5
|
+
${ftl_object_to_js_code_declaring_an_object(.data_model, [])?no_esc};
|
6
|
+
|
7
|
+
out["msg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
|
8
|
+
out["advancedMsg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
|
9
|
+
|
10
|
+
out["messagesPerField"]= {
|
11
|
+
<#assign fieldNames = [
|
12
|
+
"global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm",
|
13
|
+
"totp", "totpSecret", "SAMLRequest", "SAMLResponse", "relayState", "device_user_code", "code",
|
14
|
+
"password-new", "rememberMe", "login", "authenticationExecution", "cancel-aia", "clientDataJSON",
|
15
|
+
"authenticatorData", "signature", "credentialId", "userHandle", "error", "authn_use_chk", "authenticationExecution",
|
16
|
+
"isSetRetry", "try-again", "attestationObject", "publicKeyCredentialId", "authenticatorLabel"
|
17
|
+
]>
|
18
|
+
|
19
|
+
<#attempt>
|
20
|
+
<#if profile?? && profile.attributes?? && profile.attributes?is_enumerable>
|
21
|
+
<#list profile.attributes as attribute>
|
22
|
+
<#if fieldNames?seq_contains(attribute.name)>
|
23
|
+
<#continue>
|
24
|
+
</#if>
|
25
|
+
<#assign fieldNames += [attribute.name]>
|
26
|
+
</#list>
|
27
|
+
</#if>
|
28
|
+
<#recover>
|
29
|
+
</#attempt>
|
30
|
+
|
31
|
+
"printIfExists": function (fieldName, x) {
|
32
|
+
<#list fieldNames as fieldName>
|
33
|
+
if(fieldName === "${fieldName}" ){
|
34
|
+
<#attempt>
|
35
|
+
return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined;
|
36
|
+
<#recover>
|
37
|
+
</#attempt>
|
38
|
+
}
|
39
|
+
</#list>
|
40
|
+
throw new Error("There is no " + fieldName + " field");
|
41
|
+
},
|
42
|
+
"existsError": function (fieldName) {
|
43
|
+
<#list fieldNames as fieldName>
|
44
|
+
if(fieldName === "${fieldName}" ){
|
45
|
+
<#attempt>
|
46
|
+
return <#if messagesPerField.existsError('${fieldName}')>true<#else>false</#if>;
|
47
|
+
<#recover>
|
48
|
+
</#attempt>
|
49
|
+
}
|
50
|
+
</#list>
|
51
|
+
throw new Error("There is no " + fieldName + " field");
|
52
|
+
},
|
53
|
+
"get": function (fieldName) {
|
54
|
+
<#list fieldNames as fieldName>
|
55
|
+
if(fieldName === "${fieldName}" ){
|
56
|
+
<#attempt>
|
57
|
+
<#if messagesPerField.existsError('${fieldName}')>
|
58
|
+
return "${messagesPerField.get('${fieldName}')?no_esc}";
|
59
|
+
</#if>
|
60
|
+
<#recover>
|
61
|
+
</#attempt>
|
62
|
+
}
|
63
|
+
</#list>
|
64
|
+
throw new Error("There is no " + fieldName + " field");
|
65
|
+
},
|
66
|
+
"exists": function (fieldName) {
|
67
|
+
<#list fieldNames as fieldName>
|
68
|
+
if(fieldName === "${fieldName}" ){
|
69
|
+
<#attempt>
|
70
|
+
return <#if messagesPerField.exists('${fieldName}')>true<#else>false</#if>;
|
71
|
+
<#recover>
|
72
|
+
</#attempt>
|
73
|
+
}
|
74
|
+
</#list>
|
75
|
+
throw new Error("There is no " + fieldName + " field");
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
return out;
|
80
|
+
|
81
|
+
})();
|
82
|
+
<#function ftl_object_to_js_code_declaring_an_object object path>
|
83
|
+
|
84
|
+
<#local isHash = "">
|
85
|
+
<#attempt>
|
86
|
+
<#local isHash = object?is_hash || object?is_hash_ex>
|
87
|
+
<#recover>
|
88
|
+
<#return "ABORT: Can't evaluate if " + path?join(".") + " is hash">
|
89
|
+
</#attempt>
|
90
|
+
|
91
|
+
<#if isHash>
|
92
|
+
|
93
|
+
<#if path?size gt 10>
|
94
|
+
<#return "ABORT: Too many recursive calls">
|
95
|
+
</#if>
|
96
|
+
|
97
|
+
<#local keys = "">
|
98
|
+
|
99
|
+
<#attempt>
|
100
|
+
<#local keys = object?keys>
|
101
|
+
<#recover>
|
102
|
+
<#return "ABORT: We can't list keys on this object">
|
103
|
+
</#attempt>
|
104
|
+
|
105
|
+
|
106
|
+
<#local out_seq = []>
|
107
|
+
|
108
|
+
<#list keys as key>
|
109
|
+
|
110
|
+
<#if ["class","declaredConstructors","superclass","declaringClass" ]?seq_contains(key) >
|
111
|
+
<#continue>
|
112
|
+
</#if>
|
113
|
+
|
114
|
+
<#if
|
115
|
+
["loginUpdatePasswordUrl", "loginUpdateProfileUrl", "loginUsernameReminderUrl", "loginUpdateTotpUrl"]?seq_contains(key) &&
|
116
|
+
path?map(x -> x?is_number?string("_index_",x))?join("°") == ["url"]?join("°")
|
117
|
+
>
|
118
|
+
<#local out_seq += ["/*If you need" + key + " please submit an issue to the Keycloakify repo*/"]>
|
119
|
+
<#continue>
|
120
|
+
</#if>
|
121
|
+
|
122
|
+
<#attempt>
|
123
|
+
<#if !object[key]??>
|
124
|
+
<#continue>
|
125
|
+
</#if>
|
126
|
+
<#recover>
|
127
|
+
<#local out_seq += ["/*Couldn't test if '" + key + "' is available on this object*/"]>
|
128
|
+
<#continue>
|
129
|
+
</#attempt>
|
130
|
+
|
131
|
+
<#local propertyValue = "">
|
132
|
+
|
133
|
+
<#attempt>
|
134
|
+
<#local propertyValue = object[key]>
|
135
|
+
<#recover>
|
136
|
+
<#local out_seq += ["/*Couldn't dereference '" + key + "' on this object*/"]>
|
137
|
+
<#continue>
|
138
|
+
</#attempt>
|
139
|
+
|
140
|
+
<#local rec_out = ftl_object_to_js_code_declaring_an_object(propertyValue, path + [ key ])>
|
141
|
+
|
142
|
+
<#if rec_out?starts_with("ABORT:")>
|
143
|
+
|
144
|
+
<#local errorMessage = rec_out?remove_beginning("ABORT:")>
|
145
|
+
|
146
|
+
<#if errorMessage != " It's a method" >
|
147
|
+
<#local out_seq += ["/*" + key + ": " + errorMessage + "*/"]>
|
148
|
+
</#if>
|
149
|
+
|
150
|
+
<#continue>
|
151
|
+
</#if>
|
152
|
+
|
153
|
+
<#local out_seq += ['"' + key + '": ' + rec_out + ","]>
|
154
|
+
|
155
|
+
</#list>
|
156
|
+
|
157
|
+
<#return (["{"] + out_seq?map(str -> ""?right_pad(4 * (path?size + 1)) + str) + [ ""?right_pad(4 * path?size) + "}"])?join("\n")>
|
158
|
+
|
159
|
+
</#if>
|
160
|
+
|
161
|
+
<#local isMethod = "">
|
162
|
+
<#attempt>
|
163
|
+
<#local isMethod = object?is_method>
|
164
|
+
<#recover>
|
165
|
+
<#return "ABORT: Can't test if it'sa method.">
|
166
|
+
</#attempt>
|
167
|
+
|
168
|
+
<#if isMethod>
|
169
|
+
<#return "ABORT: It's a method">
|
170
|
+
</#if>
|
171
|
+
|
172
|
+
<#local isBoolean = "">
|
173
|
+
<#attempt>
|
174
|
+
<#local isBoolean = object?is_boolean>
|
175
|
+
<#recover>
|
176
|
+
<#return "ABORT: Can't test if it's a boolean">
|
177
|
+
</#attempt>
|
178
|
+
|
179
|
+
<#if isBoolean>
|
180
|
+
<#return object?c>
|
181
|
+
</#if>
|
182
|
+
|
183
|
+
<#local isEnumerable = "">
|
184
|
+
<#attempt>
|
185
|
+
<#local isEnumerable = object?is_enumerable>
|
186
|
+
<#recover>
|
187
|
+
<#return "ABORT: Can't test if it's an enumerable">
|
188
|
+
</#attempt>
|
189
|
+
|
190
|
+
|
191
|
+
<#if isEnumerable>
|
192
|
+
|
193
|
+
<#local out_seq = []>
|
194
|
+
|
195
|
+
<#local i = 0>
|
196
|
+
|
197
|
+
<#list object as array_item>
|
198
|
+
|
199
|
+
<#local rec_out = ftl_object_to_js_code_declaring_an_object(array_item, path + [ i ])>
|
200
|
+
|
201
|
+
<#local i = i + 1>
|
202
|
+
|
203
|
+
<#if rec_out?starts_with("ABORT:")>
|
204
|
+
|
205
|
+
<#local errorMessage = rec_out?remove_beginning("ABORT:")>
|
206
|
+
|
207
|
+
<#if errorMessage != " It's a method" >
|
208
|
+
<#local out_seq += ["/*" + i?string + ": " + errorMessage + "*/"]>
|
209
|
+
</#if>
|
210
|
+
|
211
|
+
<#continue>
|
212
|
+
</#if>
|
213
|
+
|
214
|
+
<#local out_seq += [rec_out + ","]>
|
215
|
+
|
216
|
+
</#list>
|
217
|
+
|
218
|
+
<#return (["["] + out_seq?map(str -> ""?right_pad(4 * (path?size + 1)) + str) + [ ""?right_pad(4 * path?size) + "]"])?join("\n")>
|
219
|
+
|
220
|
+
</#if>
|
221
|
+
|
222
|
+
<#attempt>
|
223
|
+
<#return '"' + object?js_string + '"'>;
|
224
|
+
<#recover>
|
225
|
+
</#attempt>
|
226
|
+
|
227
|
+
<#return "ABORT: Couldn't convert into string non hash, non method, non boolean, non enumerable object">
|
228
|
+
|
229
|
+
</#function>
|
230
|
+
</script>
|
@@ -1,4 +1,15 @@
|
|
1
1
|
"use strict";
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
3
|
+
__assign = Object.assign || function(t) {
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
5
|
+
s = arguments[i];
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
7
|
+
t[p] = s[p];
|
8
|
+
}
|
9
|
+
return t;
|
10
|
+
};
|
11
|
+
return __assign.apply(this, arguments);
|
12
|
+
};
|
2
13
|
var __read = (this && this.__read) || function (o, n) {
|
3
14
|
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
4
15
|
if (!m) return o;
|
@@ -48,9 +59,6 @@ exports.pageIds = [
|
|
48
59
|
"login-update-profile.ftl",
|
49
60
|
"login-idp-link-confirm.ftl",
|
50
61
|
];
|
51
|
-
function loadAdjacentFile(fileBasename) {
|
52
|
-
return fs_1.default.readFileSync((0, path_1.join)(__dirname, fileBasename)).toString("utf8");
|
53
|
-
}
|
54
62
|
function generateFtlFilesCodeFactory(params) {
|
55
63
|
var cssGlobalsToDefine = params.cssGlobalsToDefine, indexHtmlCode = params.indexHtmlCode, urlPathname = params.urlPathname, urlOrigin = params.urlOrigin;
|
56
64
|
var $ = cheerio_1.default.load(indexHtmlCode);
|
@@ -100,8 +108,11 @@ function generateFtlFilesCodeFactory(params) {
|
|
100
108
|
});
|
101
109
|
});
|
102
110
|
//FTL is no valid html, we can't insert with cheerio, we put placeholder for injecting later.
|
103
|
-
var
|
104
|
-
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }':
|
111
|
+
var replaceValueBySearchValue = {
|
112
|
+
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }': fs_1.default
|
113
|
+
.readFileSync((0, path_1.join)(__dirname, "ftl_object_to_js_code_declaring_an_object.ftl"))
|
114
|
+
.toString("utf8")
|
115
|
+
.match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)[1],
|
105
116
|
"<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->": [
|
106
117
|
"<#if scripts??>",
|
107
118
|
" <#list scripts as script>",
|
@@ -110,7 +121,7 @@ function generateFtlFilesCodeFactory(params) {
|
|
110
121
|
"</#if>",
|
111
122
|
].join("\n"),
|
112
123
|
};
|
113
|
-
var
|
124
|
+
var pageIdSearchValue = "PAGE_ID_xIgLsPgGId9D8e";
|
114
125
|
$("head").prepend(__spreadArray(__spreadArray([], __read((Object.keys(cssGlobalsToDefine).length === 0
|
115
126
|
? []
|
116
127
|
: [
|
@@ -124,32 +135,22 @@ function generateFtlFilesCodeFactory(params) {
|
|
124
135
|
"",
|
125
136
|
])), false), [
|
126
137
|
"<script>",
|
127
|
-
|
128
|
-
"
|
129
|
-
"<script>",
|
130
|
-
" window." + ftlValuesGlobalName_1.ftlValuesGlobalName + "= Object.assign(",
|
131
|
-
" {},",
|
132
|
-
" " + (0, objectKeys_1.objectKeys)(ftlPlaceholders)[0],
|
133
|
-
" );",
|
138
|
+
" window." + ftlValuesGlobalName_1.ftlValuesGlobalName + "= " + (0, objectKeys_1.objectKeys)(replaceValueBySearchValue)[0] + ";",
|
139
|
+
" window." + ftlValuesGlobalName_1.ftlValuesGlobalName + "[\"pageId\"]= \"" + pageIdSearchValue + "\";",
|
134
140
|
"</script>",
|
135
141
|
"",
|
136
|
-
|
137
|
-
"",
|
138
|
-
(0, objectKeys_1.objectKeys)(ftlPlaceholders)[1],
|
142
|
+
(0, objectKeys_1.objectKeys)(replaceValueBySearchValue)[1],
|
139
143
|
], false).join("\n"));
|
140
144
|
var partiallyFixedIndexHtmlCode = $.html();
|
141
145
|
function generateFtlFilesCode(params) {
|
146
|
+
var _a;
|
142
147
|
var pageId = params.pageId;
|
143
148
|
var $ = cheerio_1.default.load(partiallyFixedIndexHtmlCode);
|
144
|
-
var ftlCode = $.html()
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
" );",
|
150
|
-
"</script>",
|
151
|
-
].join("\n"));
|
152
|
-
(0, objectKeys_1.objectKeys)(ftlPlaceholders).forEach(function (id) { return (ftlCode = ftlCode.replace(id, ftlPlaceholders[id])); });
|
149
|
+
var ftlCode = $.html();
|
150
|
+
Object.entries(__assign(__assign({}, replaceValueBySearchValue), (_a = {}, _a[pageIdSearchValue] = pageId, _a))).map(function (_a) {
|
151
|
+
var _b = __read(_a, 2), searchValue = _b[0], replaceValue = _b[1];
|
152
|
+
return (ftlCode = ftlCode.replace(searchValue, replaceValue));
|
153
|
+
});
|
153
154
|
return { ftlCode: ftlCode };
|
154
155
|
}
|
155
156
|
return { generateFtlFilesCode: generateFtlFilesCode };
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"generateFtl.js","sourceRoot":"","sources":["../../../src/bin/build-keycloak-theme/generateFtl/generateFtl.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"generateFtl.js","sourceRoot":"","sources":["../../../src/bin/build-keycloak-theme/generateFtl/generateFtl.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "keycloakify",
|
3
|
-
"version": "4.2.
|
3
|
+
"version": "4.2.14-beta.1",
|
4
4
|
"description": "Keycloak theme generator for Reacts app",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -32,8 +32,7 @@
|
|
32
32
|
"src/bin/build-keycloak-theme/generateDebugFiles/index.ts",
|
33
33
|
"src/bin/build-keycloak-theme/generateDebugFiles/standalone-ha_11.0.3.xml",
|
34
34
|
"src/bin/build-keycloak-theme/generateDebugFiles/standalone-ha_15.0.2.xml",
|
35
|
-
"src/bin/build-keycloak-theme/generateFtl/
|
36
|
-
"src/bin/build-keycloak-theme/generateFtl/common.ftl",
|
35
|
+
"src/bin/build-keycloak-theme/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl",
|
37
36
|
"src/bin/build-keycloak-theme/generateFtl/generateFtl.ts",
|
38
37
|
"src/bin/build-keycloak-theme/generateFtl/index.ts",
|
39
38
|
"src/bin/build-keycloak-theme/generateJavaStackFiles.ts",
|
@@ -114,8 +113,7 @@
|
|
114
113
|
"bin/build-keycloak-theme/generateDebugFiles/index.js.map",
|
115
114
|
"bin/build-keycloak-theme/generateDebugFiles/standalone-ha_11.0.3.xml",
|
116
115
|
"bin/build-keycloak-theme/generateDebugFiles/standalone-ha_15.0.2.xml",
|
117
|
-
"bin/build-keycloak-theme/generateFtl/
|
118
|
-
"bin/build-keycloak-theme/generateFtl/common.ftl",
|
116
|
+
"bin/build-keycloak-theme/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl",
|
119
117
|
"bin/build-keycloak-theme/generateFtl/generateFtl.d.ts",
|
120
118
|
"bin/build-keycloak-theme/generateFtl/generateFtl.js",
|
121
119
|
"bin/build-keycloak-theme/generateFtl/generateFtl.js.map",
|
@@ -121,11 +121,14 @@ export function main() {
|
|
121
121
|
"",
|
122
122
|
`👉 $ ./${pathRelative(reactProjectDirPath, pathJoin(keycloakThemeBuildingDirPath, containerLaunchScriptBasename))} 👈`,
|
123
123
|
"",
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
"Once your container is up and running: ",
|
125
|
+
"- Log into the admin console 👉 http://localhost:8080 username: admin, password: admin 👈",
|
126
|
+
'- Create a realm named "myrealm"',
|
127
|
+
'- Create a client with id "myclient" and root url: "https://www.keycloak.org/app/"',
|
128
|
+
`- Select Login Theme: ${themeName} (don't forget to save at the bottom of the page)`,
|
129
|
+
`- Go to 👉 https://www.keycloak.org/app/ 👈 Click "Save" then "Sign in". You should see your login page`,
|
127
130
|
"",
|
128
|
-
"
|
131
|
+
"Video demoing this process: https://youtu.be/N3wlBoH4hKg",
|
129
132
|
"",
|
130
133
|
].join("\n"),
|
131
134
|
);
|
package/src/bin/build-keycloak-theme/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
<script>const _=
|
2
|
+
(()=>{
|
3
|
+
|
4
|
+
const out =
|
5
|
+
${ftl_object_to_js_code_declaring_an_object(.data_model, [])?no_esc};
|
6
|
+
|
7
|
+
out["msg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
|
8
|
+
out["advancedMsg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
|
9
|
+
|
10
|
+
out["messagesPerField"]= {
|
11
|
+
<#assign fieldNames = [
|
12
|
+
"global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm",
|
13
|
+
"totp", "totpSecret", "SAMLRequest", "SAMLResponse", "relayState", "device_user_code", "code",
|
14
|
+
"password-new", "rememberMe", "login", "authenticationExecution", "cancel-aia", "clientDataJSON",
|
15
|
+
"authenticatorData", "signature", "credentialId", "userHandle", "error", "authn_use_chk", "authenticationExecution",
|
16
|
+
"isSetRetry", "try-again", "attestationObject", "publicKeyCredentialId", "authenticatorLabel"
|
17
|
+
]>
|
18
|
+
|
19
|
+
<#attempt>
|
20
|
+
<#if profile?? && profile.attributes?? && profile.attributes?is_enumerable>
|
21
|
+
<#list profile.attributes as attribute>
|
22
|
+
<#if fieldNames?seq_contains(attribute.name)>
|
23
|
+
<#continue>
|
24
|
+
</#if>
|
25
|
+
<#assign fieldNames += [attribute.name]>
|
26
|
+
</#list>
|
27
|
+
</#if>
|
28
|
+
<#recover>
|
29
|
+
</#attempt>
|
30
|
+
|
31
|
+
"printIfExists": function (fieldName, x) {
|
32
|
+
<#list fieldNames as fieldName>
|
33
|
+
if(fieldName === "${fieldName}" ){
|
34
|
+
<#attempt>
|
35
|
+
return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined;
|
36
|
+
<#recover>
|
37
|
+
</#attempt>
|
38
|
+
}
|
39
|
+
</#list>
|
40
|
+
throw new Error("There is no " + fieldName + " field");
|
41
|
+
},
|
42
|
+
"existsError": function (fieldName) {
|
43
|
+
<#list fieldNames as fieldName>
|
44
|
+
if(fieldName === "${fieldName}" ){
|
45
|
+
<#attempt>
|
46
|
+
return <#if messagesPerField.existsError('${fieldName}')>true<#else>false</#if>;
|
47
|
+
<#recover>
|
48
|
+
</#attempt>
|
49
|
+
}
|
50
|
+
</#list>
|
51
|
+
throw new Error("There is no " + fieldName + " field");
|
52
|
+
},
|
53
|
+
"get": function (fieldName) {
|
54
|
+
<#list fieldNames as fieldName>
|
55
|
+
if(fieldName === "${fieldName}" ){
|
56
|
+
<#attempt>
|
57
|
+
<#if messagesPerField.existsError('${fieldName}')>
|
58
|
+
return "${messagesPerField.get('${fieldName}')?no_esc}";
|
59
|
+
</#if>
|
60
|
+
<#recover>
|
61
|
+
</#attempt>
|
62
|
+
}
|
63
|
+
</#list>
|
64
|
+
throw new Error("There is no " + fieldName + " field");
|
65
|
+
},
|
66
|
+
"exists": function (fieldName) {
|
67
|
+
<#list fieldNames as fieldName>
|
68
|
+
if(fieldName === "${fieldName}" ){
|
69
|
+
<#attempt>
|
70
|
+
return <#if messagesPerField.exists('${fieldName}')>true<#else>false</#if>;
|
71
|
+
<#recover>
|
72
|
+
</#attempt>
|
73
|
+
}
|
74
|
+
</#list>
|
75
|
+
throw new Error("There is no " + fieldName + " field");
|
76
|
+
}
|
77
|
+
};
|
78
|
+
|
79
|
+
return out;
|
80
|
+
|
81
|
+
})();
|
82
|
+
<#function ftl_object_to_js_code_declaring_an_object object path>
|
83
|
+
|
84
|
+
<#local isHash = "">
|
85
|
+
<#attempt>
|
86
|
+
<#local isHash = object?is_hash || object?is_hash_ex>
|
87
|
+
<#recover>
|
88
|
+
<#return "ABORT: Can't evaluate if " + path?join(".") + " is hash">
|
89
|
+
</#attempt>
|
90
|
+
|
91
|
+
<#if isHash>
|
92
|
+
|
93
|
+
<#if path?size gt 10>
|
94
|
+
<#return "ABORT: Too many recursive calls">
|
95
|
+
</#if>
|
96
|
+
|
97
|
+
<#local keys = "">
|
98
|
+
|
99
|
+
<#attempt>
|
100
|
+
<#local keys = object?keys>
|
101
|
+
<#recover>
|
102
|
+
<#return "ABORT: We can't list keys on this object">
|
103
|
+
</#attempt>
|
104
|
+
|
105
|
+
|
106
|
+
<#local out_seq = []>
|
107
|
+
|
108
|
+
<#list keys as key>
|
109
|
+
|
110
|
+
<#if ["class","declaredConstructors","superclass","declaringClass" ]?seq_contains(key) >
|
111
|
+
<#continue>
|
112
|
+
</#if>
|
113
|
+
|
114
|
+
<#if
|
115
|
+
["loginUpdatePasswordUrl", "loginUpdateProfileUrl", "loginUsernameReminderUrl", "loginUpdateTotpUrl"]?seq_contains(key) &&
|
116
|
+
path?map(x -> x?is_number?string("_index_",x))?join("°") == ["url"]?join("°")
|
117
|
+
>
|
118
|
+
<#local out_seq += ["/*If you need" + key + " please submit an issue to the Keycloakify repo*/"]>
|
119
|
+
<#continue>
|
120
|
+
</#if>
|
121
|
+
|
122
|
+
<#attempt>
|
123
|
+
<#if !object[key]??>
|
124
|
+
<#continue>
|
125
|
+
</#if>
|
126
|
+
<#recover>
|
127
|
+
<#local out_seq += ["/*Couldn't test if '" + key + "' is available on this object*/"]>
|
128
|
+
<#continue>
|
129
|
+
</#attempt>
|
130
|
+
|
131
|
+
<#local propertyValue = "">
|
132
|
+
|
133
|
+
<#attempt>
|
134
|
+
<#local propertyValue = object[key]>
|
135
|
+
<#recover>
|
136
|
+
<#local out_seq += ["/*Couldn't dereference '" + key + "' on this object*/"]>
|
137
|
+
<#continue>
|
138
|
+
</#attempt>
|
139
|
+
|
140
|
+
<#local rec_out = ftl_object_to_js_code_declaring_an_object(propertyValue, path + [ key ])>
|
141
|
+
|
142
|
+
<#if rec_out?starts_with("ABORT:")>
|
143
|
+
|
144
|
+
<#local errorMessage = rec_out?remove_beginning("ABORT:")>
|
145
|
+
|
146
|
+
<#if errorMessage != " It's a method" >
|
147
|
+
<#local out_seq += ["/*" + key + ": " + errorMessage + "*/"]>
|
148
|
+
</#if>
|
149
|
+
|
150
|
+
<#continue>
|
151
|
+
</#if>
|
152
|
+
|
153
|
+
<#local out_seq += ['"' + key + '": ' + rec_out + ","]>
|
154
|
+
|
155
|
+
</#list>
|
156
|
+
|
157
|
+
<#return (["{"] + out_seq?map(str -> ""?right_pad(4 * (path?size + 1)) + str) + [ ""?right_pad(4 * path?size) + "}"])?join("\n")>
|
158
|
+
|
159
|
+
</#if>
|
160
|
+
|
161
|
+
<#local isMethod = "">
|
162
|
+
<#attempt>
|
163
|
+
<#local isMethod = object?is_method>
|
164
|
+
<#recover>
|
165
|
+
<#return "ABORT: Can't test if it'sa method.">
|
166
|
+
</#attempt>
|
167
|
+
|
168
|
+
<#if isMethod>
|
169
|
+
<#return "ABORT: It's a method">
|
170
|
+
</#if>
|
171
|
+
|
172
|
+
<#local isBoolean = "">
|
173
|
+
<#attempt>
|
174
|
+
<#local isBoolean = object?is_boolean>
|
175
|
+
<#recover>
|
176
|
+
<#return "ABORT: Can't test if it's a boolean">
|
177
|
+
</#attempt>
|
178
|
+
|
179
|
+
<#if isBoolean>
|
180
|
+
<#return object?c>
|
181
|
+
</#if>
|
182
|
+
|
183
|
+
<#local isEnumerable = "">
|
184
|
+
<#attempt>
|
185
|
+
<#local isEnumerable = object?is_enumerable>
|
186
|
+
<#recover>
|
187
|
+
<#return "ABORT: Can't test if it's an enumerable">
|
188
|
+
</#attempt>
|
189
|
+
|
190
|
+
|
191
|
+
<#if isEnumerable>
|
192
|
+
|
193
|
+
<#local out_seq = []>
|
194
|
+
|
195
|
+
<#local i = 0>
|
196
|
+
|
197
|
+
<#list object as array_item>
|
198
|
+
|
199
|
+
<#local rec_out = ftl_object_to_js_code_declaring_an_object(array_item, path + [ i ])>
|
200
|
+
|
201
|
+
<#local i = i + 1>
|
202
|
+
|
203
|
+
<#if rec_out?starts_with("ABORT:")>
|
204
|
+
|
205
|
+
<#local errorMessage = rec_out?remove_beginning("ABORT:")>
|
206
|
+
|
207
|
+
<#if errorMessage != " It's a method" >
|
208
|
+
<#local out_seq += ["/*" + i?string + ": " + errorMessage + "*/"]>
|
209
|
+
</#if>
|
210
|
+
|
211
|
+
<#continue>
|
212
|
+
</#if>
|
213
|
+
|
214
|
+
<#local out_seq += [rec_out + ","]>
|
215
|
+
|
216
|
+
</#list>
|
217
|
+
|
218
|
+
<#return (["["] + out_seq?map(str -> ""?right_pad(4 * (path?size + 1)) + str) + [ ""?right_pad(4 * path?size) + "]"])?join("\n")>
|
219
|
+
|
220
|
+
</#if>
|
221
|
+
|
222
|
+
<#attempt>
|
223
|
+
<#return '"' + object?js_string + '"'>;
|
224
|
+
<#recover>
|
225
|
+
</#attempt>
|
226
|
+
|
227
|
+
<#return "ABORT: Couldn't convert into string non hash, non method, non boolean, non enumerable object">
|
228
|
+
|
229
|
+
</#function>
|
230
|
+
</script>
|
@@ -21,10 +21,6 @@ export const pageIds = [
|
|
21
21
|
|
22
22
|
export type PageId = typeof pageIds[number];
|
23
23
|
|
24
|
-
function loadAdjacentFile(fileBasename: string) {
|
25
|
-
return fs.readFileSync(pathJoin(__dirname, fileBasename)).toString("utf8");
|
26
|
-
}
|
27
|
-
|
28
24
|
export function generateFtlFilesCodeFactory(params: {
|
29
25
|
cssGlobalsToDefine: Record<string, string>;
|
30
26
|
indexHtmlCode: string;
|
@@ -77,8 +73,11 @@ export function generateFtlFilesCodeFactory(params: {
|
|
77
73
|
);
|
78
74
|
|
79
75
|
//FTL is no valid html, we can't insert with cheerio, we put placeholder for injecting later.
|
80
|
-
const
|
81
|
-
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }':
|
76
|
+
const replaceValueBySearchValue = {
|
77
|
+
'{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }': fs
|
78
|
+
.readFileSync(pathJoin(__dirname, "ftl_object_to_js_code_declaring_an_object.ftl"))
|
79
|
+
.toString("utf8")
|
80
|
+
.match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)![1],
|
82
81
|
"<!-- xIdLqMeOedErIdLsPdNdI9dSlxI -->": [
|
83
82
|
"<#if scripts??>",
|
84
83
|
" <#list scripts as script>",
|
@@ -88,7 +87,7 @@ export function generateFtlFilesCodeFactory(params: {
|
|
88
87
|
].join("\n"),
|
89
88
|
};
|
90
89
|
|
91
|
-
const
|
90
|
+
const pageIdSearchValue = "PAGE_ID_xIgLsPgGId9D8e";
|
92
91
|
|
93
92
|
$("head").prepend(
|
94
93
|
[
|
@@ -105,18 +104,11 @@ export function generateFtlFilesCodeFactory(params: {
|
|
105
104
|
"",
|
106
105
|
]),
|
107
106
|
"<script>",
|
108
|
-
|
109
|
-
"
|
110
|
-
"<script>",
|
111
|
-
` window.${ftlValuesGlobalName}= Object.assign(`,
|
112
|
-
` {},`,
|
113
|
-
` ${objectKeys(ftlPlaceholders)[0]}`,
|
114
|
-
" );",
|
107
|
+
` window.${ftlValuesGlobalName}= ${objectKeys(replaceValueBySearchValue)[0]};`,
|
108
|
+
` window.${ftlValuesGlobalName}["pageId"]= "${pageIdSearchValue}";`,
|
115
109
|
"</script>",
|
116
110
|
"",
|
117
|
-
|
118
|
-
"",
|
119
|
-
objectKeys(ftlPlaceholders)[1],
|
111
|
+
objectKeys(replaceValueBySearchValue)[1],
|
120
112
|
].join("\n"),
|
121
113
|
);
|
122
114
|
|
@@ -129,19 +121,12 @@ export function generateFtlFilesCodeFactory(params: {
|
|
129
121
|
|
130
122
|
const $ = cheerio.load(partiallyFixedIndexHtmlCode);
|
131
123
|
|
132
|
-
let ftlCode = $.html()
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
` { "pageId": "${pageId}" }`,
|
139
|
-
" );",
|
140
|
-
"</script>",
|
141
|
-
].join("\n"),
|
142
|
-
);
|
143
|
-
|
144
|
-
objectKeys(ftlPlaceholders).forEach(id => (ftlCode = ftlCode.replace(id, ftlPlaceholders[id])));
|
124
|
+
let ftlCode = $.html();
|
125
|
+
|
126
|
+
Object.entries({
|
127
|
+
...replaceValueBySearchValue,
|
128
|
+
[pageIdSearchValue]: pageId,
|
129
|
+
}).map(([searchValue, replaceValue]) => (ftlCode = ftlCode.replace(searchValue, replaceValue)));
|
145
130
|
|
146
131
|
return { ftlCode };
|
147
132
|
}
|
@@ -1,28 +0,0 @@
|
|
1
|
-
|
2
|
-
Object.defineProperty(
|
3
|
-
Object,
|
4
|
-
"deepAssign",
|
5
|
-
{
|
6
|
-
"value": function callee(target, source) {
|
7
|
-
Object.keys(source).forEach(function (key) {
|
8
|
-
var value = source[key];
|
9
|
-
if (target[key] === undefined) {
|
10
|
-
target[key] = value;
|
11
|
-
return;
|
12
|
-
}
|
13
|
-
if (value instanceof Object) {
|
14
|
-
if (value instanceof Array) {
|
15
|
-
value.forEach(function (entry) {
|
16
|
-
target[key].push(entry);
|
17
|
-
});
|
18
|
-
return;
|
19
|
-
}
|
20
|
-
callee(target[key], value);
|
21
|
-
return;
|
22
|
-
}
|
23
|
-
target[key] = value;
|
24
|
-
});
|
25
|
-
return target;
|
26
|
-
}
|
27
|
-
}
|
28
|
-
);
|
@@ -1,208 +0,0 @@
|
|
1
|
-
<script>const _=
|
2
|
-
<#macro objectToJson_please_ignore_errors object depth>
|
3
|
-
<@compress>
|
4
|
-
|
5
|
-
<#local isHash = false>
|
6
|
-
<#attempt>
|
7
|
-
<#local isHash = object?is_hash || object?is_hash_ex>
|
8
|
-
<#recover>
|
9
|
-
/* can't evaluate if object is hash */
|
10
|
-
undefined
|
11
|
-
<#return>
|
12
|
-
</#attempt>
|
13
|
-
<#if isHash>
|
14
|
-
|
15
|
-
<#local keys = "">
|
16
|
-
|
17
|
-
<#attempt>
|
18
|
-
<#local keys = object?keys>
|
19
|
-
<#recover>
|
20
|
-
/* can't list keys of object */
|
21
|
-
undefined
|
22
|
-
<#return>
|
23
|
-
</#attempt>
|
24
|
-
|
25
|
-
{${'\n'}
|
26
|
-
|
27
|
-
<#list keys as key>
|
28
|
-
|
29
|
-
<#if key == "class">
|
30
|
-
/* skipping "class" property of object */
|
31
|
-
<#continue>
|
32
|
-
</#if>
|
33
|
-
|
34
|
-
<#local value = "">
|
35
|
-
|
36
|
-
<#attempt>
|
37
|
-
<#local value = object[key]>
|
38
|
-
<#recover>
|
39
|
-
/* couldn't dereference ${key} of object */
|
40
|
-
<#continue>
|
41
|
-
</#attempt>
|
42
|
-
|
43
|
-
<#if depth gt 7>
|
44
|
-
/* Avoid calling recustively too many times depth: ${depth}, key: ${key} */
|
45
|
-
<#continue>
|
46
|
-
</#if>
|
47
|
-
|
48
|
-
"${key}": <@objectToJson_please_ignore_errors object=value depth=depth+1/>,
|
49
|
-
|
50
|
-
</#list>
|
51
|
-
|
52
|
-
}${'\n'}
|
53
|
-
|
54
|
-
<#return>
|
55
|
-
|
56
|
-
</#if>
|
57
|
-
|
58
|
-
|
59
|
-
<#local isMethod = "">
|
60
|
-
<#attempt>
|
61
|
-
<#local isMethod = object?is_method>
|
62
|
-
<#recover>
|
63
|
-
/* can't test if object is a method */
|
64
|
-
undefined
|
65
|
-
<#return>
|
66
|
-
</#attempt>
|
67
|
-
|
68
|
-
<#if isMethod>
|
69
|
-
undefined
|
70
|
-
<#return>
|
71
|
-
</#if>
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
<#local isBoolean = "">
|
76
|
-
<#attempt>
|
77
|
-
<#local isBoolean = object?is_boolean>
|
78
|
-
<#recover>
|
79
|
-
/* can't test if object is a boolean */
|
80
|
-
undefined
|
81
|
-
<#return>
|
82
|
-
</#attempt>
|
83
|
-
|
84
|
-
<#if isBoolean>
|
85
|
-
${object?c}
|
86
|
-
<#return>
|
87
|
-
</#if>
|
88
|
-
|
89
|
-
|
90
|
-
<#local isEnumerable = "">
|
91
|
-
<#attempt>
|
92
|
-
<#local isEnumerable = object?is_enumerable>
|
93
|
-
<#recover>
|
94
|
-
/* can't test if object is enumerable */
|
95
|
-
undefined
|
96
|
-
<#return>
|
97
|
-
</#attempt>
|
98
|
-
|
99
|
-
<#if isEnumerable>
|
100
|
-
|
101
|
-
[${'\n'}
|
102
|
-
|
103
|
-
<#list object as item>
|
104
|
-
|
105
|
-
<@objectToJson_please_ignore_errors object=item depth=depth+1/>,
|
106
|
-
|
107
|
-
</#list>
|
108
|
-
|
109
|
-
]${'\n'}
|
110
|
-
|
111
|
-
<#return>
|
112
|
-
</#if>
|
113
|
-
|
114
|
-
|
115
|
-
<#attempt>
|
116
|
-
"${object?replace('"', '\\"')?no_esc}"
|
117
|
-
<#recover>
|
118
|
-
/* couldn't convert into string non hash, non method, non boolean, non enumerable object */
|
119
|
-
undefined;
|
120
|
-
<#return>
|
121
|
-
</#attempt>
|
122
|
-
|
123
|
-
|
124
|
-
</@compress>
|
125
|
-
</#macro>
|
126
|
-
|
127
|
-
(()=>{
|
128
|
-
|
129
|
-
const nonAutomaticallyConvertible = {
|
130
|
-
"messagesPerField": {
|
131
|
-
|
132
|
-
<#assign fieldNames = ["global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm"]>
|
133
|
-
|
134
|
-
<#attempt>
|
135
|
-
<#list profile.attributes as attribute>
|
136
|
-
<#assign fieldNames += [attribute.name]>
|
137
|
-
</#list>
|
138
|
-
<#recover>
|
139
|
-
</#attempt>
|
140
|
-
|
141
|
-
"printIfExists": function (fieldName, x) {
|
142
|
-
<#list fieldNames as fieldName>
|
143
|
-
if(fieldName === "${fieldName}" ){
|
144
|
-
<#attempt>
|
145
|
-
return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined;
|
146
|
-
<#recover>
|
147
|
-
</#attempt>
|
148
|
-
}
|
149
|
-
</#list>
|
150
|
-
throw new Error("There is no " + fieldName + " field");
|
151
|
-
},
|
152
|
-
"existsError": function (fieldName) {
|
153
|
-
<#list fieldNames as fieldName>
|
154
|
-
if(fieldName === "${fieldName}" ){
|
155
|
-
<#attempt>
|
156
|
-
return <#if messagesPerField.existsError('${fieldName}')>true<#else>false</#if>;
|
157
|
-
<#recover>
|
158
|
-
</#attempt>
|
159
|
-
}
|
160
|
-
</#list>
|
161
|
-
throw new Error("There is no " + fieldName + " field");
|
162
|
-
},
|
163
|
-
"get": function (fieldName) {
|
164
|
-
<#list fieldNames as fieldName>
|
165
|
-
if(fieldName === "${fieldName}" ){
|
166
|
-
<#attempt>
|
167
|
-
<#if messagesPerField.existsError('${fieldName}')>
|
168
|
-
return "${messagesPerField.get('${fieldName}')?no_esc}";
|
169
|
-
</#if>
|
170
|
-
<#recover>
|
171
|
-
</#attempt>
|
172
|
-
}
|
173
|
-
</#list>
|
174
|
-
throw new Error("There is no " + fieldName + " field");
|
175
|
-
},
|
176
|
-
"exists": function (fieldName) {
|
177
|
-
<#list fieldNames as fieldName>
|
178
|
-
if(fieldName === "${fieldName}" ){
|
179
|
-
<#attempt>
|
180
|
-
return <#if messagesPerField.exists('${fieldName}')>true<#else>false</#if>;
|
181
|
-
<#recover>
|
182
|
-
</#attempt>
|
183
|
-
}
|
184
|
-
</#list>
|
185
|
-
throw new Error("There is no " + fieldName + " field");
|
186
|
-
}
|
187
|
-
},
|
188
|
-
"msg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); },
|
189
|
-
"advancedMsg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); }
|
190
|
-
};
|
191
|
-
|
192
|
-
const out = {};
|
193
|
-
|
194
|
-
Object.deepAssign(
|
195
|
-
out,
|
196
|
-
//Removing all the undefined
|
197
|
-
JSON.parse(JSON.stringify(<@objectToJson_please_ignore_errors object=.data_model depth=0 />))
|
198
|
-
);
|
199
|
-
|
200
|
-
Object.deepAssign(
|
201
|
-
out,
|
202
|
-
nonAutomaticallyConvertible
|
203
|
-
);
|
204
|
-
|
205
|
-
return out;
|
206
|
-
|
207
|
-
})()
|
208
|
-
</script>
|
@@ -1,28 +0,0 @@
|
|
1
|
-
|
2
|
-
Object.defineProperty(
|
3
|
-
Object,
|
4
|
-
"deepAssign",
|
5
|
-
{
|
6
|
-
"value": function callee(target, source) {
|
7
|
-
Object.keys(source).forEach(function (key) {
|
8
|
-
var value = source[key];
|
9
|
-
if (target[key] === undefined) {
|
10
|
-
target[key] = value;
|
11
|
-
return;
|
12
|
-
}
|
13
|
-
if (value instanceof Object) {
|
14
|
-
if (value instanceof Array) {
|
15
|
-
value.forEach(function (entry) {
|
16
|
-
target[key].push(entry);
|
17
|
-
});
|
18
|
-
return;
|
19
|
-
}
|
20
|
-
callee(target[key], value);
|
21
|
-
return;
|
22
|
-
}
|
23
|
-
target[key] = value;
|
24
|
-
});
|
25
|
-
return target;
|
26
|
-
}
|
27
|
-
}
|
28
|
-
);
|
@@ -1,208 +0,0 @@
|
|
1
|
-
<script>const _=
|
2
|
-
<#macro objectToJson_please_ignore_errors object depth>
|
3
|
-
<@compress>
|
4
|
-
|
5
|
-
<#local isHash = false>
|
6
|
-
<#attempt>
|
7
|
-
<#local isHash = object?is_hash || object?is_hash_ex>
|
8
|
-
<#recover>
|
9
|
-
/* can't evaluate if object is hash */
|
10
|
-
undefined
|
11
|
-
<#return>
|
12
|
-
</#attempt>
|
13
|
-
<#if isHash>
|
14
|
-
|
15
|
-
<#local keys = "">
|
16
|
-
|
17
|
-
<#attempt>
|
18
|
-
<#local keys = object?keys>
|
19
|
-
<#recover>
|
20
|
-
/* can't list keys of object */
|
21
|
-
undefined
|
22
|
-
<#return>
|
23
|
-
</#attempt>
|
24
|
-
|
25
|
-
{${'\n'}
|
26
|
-
|
27
|
-
<#list keys as key>
|
28
|
-
|
29
|
-
<#if key == "class">
|
30
|
-
/* skipping "class" property of object */
|
31
|
-
<#continue>
|
32
|
-
</#if>
|
33
|
-
|
34
|
-
<#local value = "">
|
35
|
-
|
36
|
-
<#attempt>
|
37
|
-
<#local value = object[key]>
|
38
|
-
<#recover>
|
39
|
-
/* couldn't dereference ${key} of object */
|
40
|
-
<#continue>
|
41
|
-
</#attempt>
|
42
|
-
|
43
|
-
<#if depth gt 7>
|
44
|
-
/* Avoid calling recustively too many times depth: ${depth}, key: ${key} */
|
45
|
-
<#continue>
|
46
|
-
</#if>
|
47
|
-
|
48
|
-
"${key}": <@objectToJson_please_ignore_errors object=value depth=depth+1/>,
|
49
|
-
|
50
|
-
</#list>
|
51
|
-
|
52
|
-
}${'\n'}
|
53
|
-
|
54
|
-
<#return>
|
55
|
-
|
56
|
-
</#if>
|
57
|
-
|
58
|
-
|
59
|
-
<#local isMethod = "">
|
60
|
-
<#attempt>
|
61
|
-
<#local isMethod = object?is_method>
|
62
|
-
<#recover>
|
63
|
-
/* can't test if object is a method */
|
64
|
-
undefined
|
65
|
-
<#return>
|
66
|
-
</#attempt>
|
67
|
-
|
68
|
-
<#if isMethod>
|
69
|
-
undefined
|
70
|
-
<#return>
|
71
|
-
</#if>
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
<#local isBoolean = "">
|
76
|
-
<#attempt>
|
77
|
-
<#local isBoolean = object?is_boolean>
|
78
|
-
<#recover>
|
79
|
-
/* can't test if object is a boolean */
|
80
|
-
undefined
|
81
|
-
<#return>
|
82
|
-
</#attempt>
|
83
|
-
|
84
|
-
<#if isBoolean>
|
85
|
-
${object?c}
|
86
|
-
<#return>
|
87
|
-
</#if>
|
88
|
-
|
89
|
-
|
90
|
-
<#local isEnumerable = "">
|
91
|
-
<#attempt>
|
92
|
-
<#local isEnumerable = object?is_enumerable>
|
93
|
-
<#recover>
|
94
|
-
/* can't test if object is enumerable */
|
95
|
-
undefined
|
96
|
-
<#return>
|
97
|
-
</#attempt>
|
98
|
-
|
99
|
-
<#if isEnumerable>
|
100
|
-
|
101
|
-
[${'\n'}
|
102
|
-
|
103
|
-
<#list object as item>
|
104
|
-
|
105
|
-
<@objectToJson_please_ignore_errors object=item depth=depth+1/>,
|
106
|
-
|
107
|
-
</#list>
|
108
|
-
|
109
|
-
]${'\n'}
|
110
|
-
|
111
|
-
<#return>
|
112
|
-
</#if>
|
113
|
-
|
114
|
-
|
115
|
-
<#attempt>
|
116
|
-
"${object?replace('"', '\\"')?no_esc}"
|
117
|
-
<#recover>
|
118
|
-
/* couldn't convert into string non hash, non method, non boolean, non enumerable object */
|
119
|
-
undefined;
|
120
|
-
<#return>
|
121
|
-
</#attempt>
|
122
|
-
|
123
|
-
|
124
|
-
</@compress>
|
125
|
-
</#macro>
|
126
|
-
|
127
|
-
(()=>{
|
128
|
-
|
129
|
-
const nonAutomaticallyConvertible = {
|
130
|
-
"messagesPerField": {
|
131
|
-
|
132
|
-
<#assign fieldNames = ["global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm"]>
|
133
|
-
|
134
|
-
<#attempt>
|
135
|
-
<#list profile.attributes as attribute>
|
136
|
-
<#assign fieldNames += [attribute.name]>
|
137
|
-
</#list>
|
138
|
-
<#recover>
|
139
|
-
</#attempt>
|
140
|
-
|
141
|
-
"printIfExists": function (fieldName, x) {
|
142
|
-
<#list fieldNames as fieldName>
|
143
|
-
if(fieldName === "${fieldName}" ){
|
144
|
-
<#attempt>
|
145
|
-
return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined;
|
146
|
-
<#recover>
|
147
|
-
</#attempt>
|
148
|
-
}
|
149
|
-
</#list>
|
150
|
-
throw new Error("There is no " + fieldName + " field");
|
151
|
-
},
|
152
|
-
"existsError": function (fieldName) {
|
153
|
-
<#list fieldNames as fieldName>
|
154
|
-
if(fieldName === "${fieldName}" ){
|
155
|
-
<#attempt>
|
156
|
-
return <#if messagesPerField.existsError('${fieldName}')>true<#else>false</#if>;
|
157
|
-
<#recover>
|
158
|
-
</#attempt>
|
159
|
-
}
|
160
|
-
</#list>
|
161
|
-
throw new Error("There is no " + fieldName + " field");
|
162
|
-
},
|
163
|
-
"get": function (fieldName) {
|
164
|
-
<#list fieldNames as fieldName>
|
165
|
-
if(fieldName === "${fieldName}" ){
|
166
|
-
<#attempt>
|
167
|
-
<#if messagesPerField.existsError('${fieldName}')>
|
168
|
-
return "${messagesPerField.get('${fieldName}')?no_esc}";
|
169
|
-
</#if>
|
170
|
-
<#recover>
|
171
|
-
</#attempt>
|
172
|
-
}
|
173
|
-
</#list>
|
174
|
-
throw new Error("There is no " + fieldName + " field");
|
175
|
-
},
|
176
|
-
"exists": function (fieldName) {
|
177
|
-
<#list fieldNames as fieldName>
|
178
|
-
if(fieldName === "${fieldName}" ){
|
179
|
-
<#attempt>
|
180
|
-
return <#if messagesPerField.exists('${fieldName}')>true<#else>false</#if>;
|
181
|
-
<#recover>
|
182
|
-
</#attempt>
|
183
|
-
}
|
184
|
-
</#list>
|
185
|
-
throw new Error("There is no " + fieldName + " field");
|
186
|
-
}
|
187
|
-
},
|
188
|
-
"msg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); },
|
189
|
-
"advancedMsg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); }
|
190
|
-
};
|
191
|
-
|
192
|
-
const out = {};
|
193
|
-
|
194
|
-
Object.deepAssign(
|
195
|
-
out,
|
196
|
-
//Removing all the undefined
|
197
|
-
JSON.parse(JSON.stringify(<@objectToJson_please_ignore_errors object=.data_model depth=0 />))
|
198
|
-
);
|
199
|
-
|
200
|
-
Object.deepAssign(
|
201
|
-
out,
|
202
|
-
nonAutomaticallyConvertible
|
203
|
-
);
|
204
|
-
|
205
|
-
return out;
|
206
|
-
|
207
|
-
})()
|
208
|
-
</script>
|