keycloakify 4.2.14-beta.0 → 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/README.md +13 -17
- 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/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +230 -0
- package/src/bin/build-keycloak-theme/generateFtl/generateFtl.ts +15 -32
- package/bin/build-keycloak-theme/generateFtl/Object.deepAssign.js +0 -28
- package/bin/build-keycloak-theme/generateFtl/common.ftl +0 -181
- package/src/bin/build-keycloak-theme/generateFtl/Object.deepAssign.js +0 -28
- package/src/bin/build-keycloak-theme/generateFtl/common.ftl +0 -181
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)
|
@@ -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
|
|
@@ -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]).replace("ftl_template_for_replacement", pageId)); });
|
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.14-beta.
|
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",
|
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,21 +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(
|
145
|
-
id => (ftlCode = ftlCode.replace(id, ftlPlaceholders[id]).replace("ftl_template_for_replacement", pageId)),
|
146
|
-
);
|
124
|
+
let ftlCode = $.html();
|
125
|
+
|
126
|
+
Object.entries({
|
127
|
+
...replaceValueBySearchValue,
|
128
|
+
[pageIdSearchValue]: pageId,
|
129
|
+
}).map(([searchValue, replaceValue]) => (ftlCode = ftlCode.replace(searchValue, replaceValue)));
|
147
130
|
|
148
131
|
return { ftlCode };
|
149
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,181 +0,0 @@
|
|
1
|
-
<script>const _=
|
2
|
-
<#macro objectToJson_please_ignore_errors object depth arr ftl>
|
3
|
-
<@compress>
|
4
|
-
<#local isHash = false>
|
5
|
-
<#attempt>
|
6
|
-
<#local isHash = object?is_hash || object?is_hash_ex>
|
7
|
-
<#recover>
|
8
|
-
/* can't evaluate if object is hash */
|
9
|
-
undefined
|
10
|
-
<#return>
|
11
|
-
</#attempt>
|
12
|
-
<#if isHash>
|
13
|
-
<#local keys = "">
|
14
|
-
<#attempt>
|
15
|
-
<#local keys = object?keys>
|
16
|
-
<#recover>
|
17
|
-
/* can't list keys of object */
|
18
|
-
undefined
|
19
|
-
<#return>
|
20
|
-
</#attempt>
|
21
|
-
<#if arr?sequence?size gte 1>
|
22
|
-
<#local keys = arr>
|
23
|
-
</#if>
|
24
|
-
{${'\n'}
|
25
|
-
<#list keys as key>
|
26
|
-
<#if key == "class">
|
27
|
-
/* skipping "class" property of object */
|
28
|
-
<#continue>
|
29
|
-
</#if>
|
30
|
-
<#attempt>
|
31
|
-
<#local value = object[key]!"error_data_is_undefined">
|
32
|
-
<#recover>
|
33
|
-
/* couldn't dereference ${key} of object */
|
34
|
-
<#continue>
|
35
|
-
</#attempt>
|
36
|
-
<#if depth gt 7>
|
37
|
-
/* Avoid calling recustively too many times depth: ${depth}, key: ${key} */
|
38
|
-
<#continue>
|
39
|
-
</#if>
|
40
|
-
<#local arr_keys = []>
|
41
|
-
<#if depth==0 && key=="url" && ftl=="saml-post-form.ftl" >
|
42
|
-
<#local arr_keys = ["resourcesPath", "resourcesCommonPath", "loginRestartFlowUrl", "loginUrl", "loginResetCredentialsUrl", "registrationUrl", "registrationAction", "oauth2DeviceVerificationAction", "oauthAction", "loginResetCredentialsUrl"]>
|
43
|
-
<#elseif depth==0 && key=="url">
|
44
|
-
<#local arr_keys = ["loginAction", "resourcesPath", "resourcesCommonPath", "loginRestartFlowUrl", "loginUrl", "loginResetCredentialsUrl", "registrationUrl", "registrationAction", "oauth2DeviceVerificationAction", "oauthAction", "loginResetCredentialsUrl"]>
|
45
|
-
</#if>
|
46
|
-
<#if depth==0 && key=="auth" && ftl=="login-reset-password.ftl" >
|
47
|
-
<#local arr_keys = ["showUsername", "showResetCredentials", "showTryAnotherWayLink", "attemptedUsername"]>
|
48
|
-
<#elseif depth==0 && key=="auth">
|
49
|
-
<#local arr_keys = ["showUsername", "showResetCredentials", "showTryAnotherWayLink"]>
|
50
|
-
</#if>
|
51
|
-
<#if depth==0 && key=="updateProfileCtx" ><#continue></#if>
|
52
|
-
"${key}": <@objectToJson_please_ignore_errors object=value depth=depth+1 arr=arr_keys ftl=ftl />,
|
53
|
-
</#list>
|
54
|
-
}${'\n'}
|
55
|
-
<#return>
|
56
|
-
</#if>
|
57
|
-
<#local isMethod = "">
|
58
|
-
<#attempt>
|
59
|
-
<#local isMethod = object?is_method>
|
60
|
-
<#recover>
|
61
|
-
/* can't test if object is a method */
|
62
|
-
undefined
|
63
|
-
<#return>
|
64
|
-
</#attempt>
|
65
|
-
<#if isMethod>
|
66
|
-
undefined
|
67
|
-
<#return>
|
68
|
-
</#if>
|
69
|
-
<#local isBoolean = "">
|
70
|
-
<#attempt>
|
71
|
-
<#local isBoolean = object?is_boolean>
|
72
|
-
<#recover>
|
73
|
-
/* can't test if object is a boolean */
|
74
|
-
undefined
|
75
|
-
<#return>
|
76
|
-
</#attempt>
|
77
|
-
<#if isBoolean>
|
78
|
-
${object?c}
|
79
|
-
<#return>
|
80
|
-
</#if>
|
81
|
-
<#local isEnumerable = "">
|
82
|
-
<#attempt>
|
83
|
-
<#local isEnumerable = object?is_enumerable>
|
84
|
-
<#recover>
|
85
|
-
/* can't test if object is enumerable */
|
86
|
-
undefined
|
87
|
-
<#return>
|
88
|
-
</#attempt>
|
89
|
-
<#if isEnumerable>
|
90
|
-
[${'\n'}
|
91
|
-
<#list object as item>
|
92
|
-
<@objectToJson_please_ignore_errors object=item depth=depth+1 arr=[] ftl=ftl/>,
|
93
|
-
</#list>
|
94
|
-
]${'\n'}
|
95
|
-
<#return>
|
96
|
-
</#if>
|
97
|
-
<#attempt>
|
98
|
-
"${object?replace('"', '\\"')?no_esc}"
|
99
|
-
<#recover>
|
100
|
-
/* couldn't convert into string non hash, non method, non boolean, non enumerable object */
|
101
|
-
undefined;
|
102
|
-
<#return>
|
103
|
-
</#attempt>
|
104
|
-
</@compress>
|
105
|
-
</#macro>
|
106
|
-
(()=>{
|
107
|
-
const nonAutomaticallyConvertible = {
|
108
|
-
"messagesPerField": {
|
109
|
-
<#assign fieldNames = ["global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm", "totp", "totpSecret", "SAMLRequest", "SAMLResponse", "relayState", "device_user_code", "code", "password-new", "rememberMe", "login", "authenticationExecution", "cancel-aia", "clientDataJSON", "authenticatorData", "signature", "credentialId", "userHandle", "error", "authn_use_chk", "authenticationExecution", "isSetRetry", "try-again", "attestationObject", "publicKeyCredentialId", "authenticatorLabel"]>
|
110
|
-
<#assign attributes = (profile.attributes)![]>
|
111
|
-
<#attempt>
|
112
|
-
<#list attributes as attribute>
|
113
|
-
<#if (attribute.name)??>
|
114
|
-
<#assign fieldNames += [attribute.name]>
|
115
|
-
</#if>
|
116
|
-
</#list>
|
117
|
-
<#recover>
|
118
|
-
</#attempt>
|
119
|
-
"printIfExists": function (fieldName, x) {
|
120
|
-
<#list fieldNames as fieldName>
|
121
|
-
if(fieldName === "${fieldName}" ){
|
122
|
-
<#attempt>
|
123
|
-
return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined;
|
124
|
-
<#recover>
|
125
|
-
</#attempt>
|
126
|
-
}
|
127
|
-
</#list>
|
128
|
-
throw new Error("There is no " + fieldName + " field");
|
129
|
-
},
|
130
|
-
"existsError": function (fieldName) {
|
131
|
-
<#list fieldNames as fieldName>
|
132
|
-
if(fieldName === "${fieldName}" ){
|
133
|
-
<#attempt>
|
134
|
-
return <#if messagesPerField.existsError('${fieldName}')>true<#else>false</#if>;
|
135
|
-
<#recover>
|
136
|
-
</#attempt>
|
137
|
-
}
|
138
|
-
</#list>
|
139
|
-
throw new Error("There is no " + fieldName + " field");
|
140
|
-
},
|
141
|
-
"get": function (fieldName) {
|
142
|
-
<#list fieldNames as fieldName>
|
143
|
-
if(fieldName === "${fieldName}" ){
|
144
|
-
<#attempt>
|
145
|
-
<#if messagesPerField.existsError('${fieldName}')>
|
146
|
-
return "${messagesPerField.get('${fieldName}')?no_esc}";
|
147
|
-
</#if>
|
148
|
-
<#recover>
|
149
|
-
</#attempt>
|
150
|
-
}
|
151
|
-
</#list>
|
152
|
-
throw new Error("There is no " + fieldName + " field");
|
153
|
-
},
|
154
|
-
"exists": function (fieldName) {
|
155
|
-
<#list fieldNames as fieldName>
|
156
|
-
if(fieldName === "${fieldName}" ){
|
157
|
-
<#attempt>
|
158
|
-
return <#if messagesPerField.exists('${fieldName}')>true<#else>false</#if>;
|
159
|
-
<#recover>
|
160
|
-
</#attempt>
|
161
|
-
}
|
162
|
-
</#list>
|
163
|
-
throw new Error("There is no " + fieldName + " field");
|
164
|
-
}
|
165
|
-
},
|
166
|
-
"msg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); },
|
167
|
-
"advancedMsg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); }
|
168
|
-
};
|
169
|
-
const out = {};
|
170
|
-
Object.deepAssign(
|
171
|
-
out,
|
172
|
-
//Removing all the undefined
|
173
|
-
JSON.parse(JSON.stringify(<@objectToJson_please_ignore_errors object=.data_model depth=0 arr=[] ftl="ftl_template_for_replacement" />), (key, value) => value === "error_data_is_undefined" ? undefined : value)
|
174
|
-
);
|
175
|
-
Object.deepAssign(
|
176
|
-
out,
|
177
|
-
nonAutomaticallyConvertible
|
178
|
-
);
|
179
|
-
return out;
|
180
|
-
})()
|
181
|
-
</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,181 +0,0 @@
|
|
1
|
-
<script>const _=
|
2
|
-
<#macro objectToJson_please_ignore_errors object depth arr ftl>
|
3
|
-
<@compress>
|
4
|
-
<#local isHash = false>
|
5
|
-
<#attempt>
|
6
|
-
<#local isHash = object?is_hash || object?is_hash_ex>
|
7
|
-
<#recover>
|
8
|
-
/* can't evaluate if object is hash */
|
9
|
-
undefined
|
10
|
-
<#return>
|
11
|
-
</#attempt>
|
12
|
-
<#if isHash>
|
13
|
-
<#local keys = "">
|
14
|
-
<#attempt>
|
15
|
-
<#local keys = object?keys>
|
16
|
-
<#recover>
|
17
|
-
/* can't list keys of object */
|
18
|
-
undefined
|
19
|
-
<#return>
|
20
|
-
</#attempt>
|
21
|
-
<#if arr?sequence?size gte 1>
|
22
|
-
<#local keys = arr>
|
23
|
-
</#if>
|
24
|
-
{${'\n'}
|
25
|
-
<#list keys as key>
|
26
|
-
<#if key == "class">
|
27
|
-
/* skipping "class" property of object */
|
28
|
-
<#continue>
|
29
|
-
</#if>
|
30
|
-
<#attempt>
|
31
|
-
<#local value = object[key]!"error_data_is_undefined">
|
32
|
-
<#recover>
|
33
|
-
/* couldn't dereference ${key} of object */
|
34
|
-
<#continue>
|
35
|
-
</#attempt>
|
36
|
-
<#if depth gt 7>
|
37
|
-
/* Avoid calling recustively too many times depth: ${depth}, key: ${key} */
|
38
|
-
<#continue>
|
39
|
-
</#if>
|
40
|
-
<#local arr_keys = []>
|
41
|
-
<#if depth==0 && key=="url" && ftl=="saml-post-form.ftl" >
|
42
|
-
<#local arr_keys = ["resourcesPath", "resourcesCommonPath", "loginRestartFlowUrl", "loginUrl", "loginResetCredentialsUrl", "registrationUrl", "registrationAction", "oauth2DeviceVerificationAction", "oauthAction", "loginResetCredentialsUrl"]>
|
43
|
-
<#elseif depth==0 && key=="url">
|
44
|
-
<#local arr_keys = ["loginAction", "resourcesPath", "resourcesCommonPath", "loginRestartFlowUrl", "loginUrl", "loginResetCredentialsUrl", "registrationUrl", "registrationAction", "oauth2DeviceVerificationAction", "oauthAction", "loginResetCredentialsUrl"]>
|
45
|
-
</#if>
|
46
|
-
<#if depth==0 && key=="auth" && ftl=="login-reset-password.ftl" >
|
47
|
-
<#local arr_keys = ["showUsername", "showResetCredentials", "showTryAnotherWayLink", "attemptedUsername"]>
|
48
|
-
<#elseif depth==0 && key=="auth">
|
49
|
-
<#local arr_keys = ["showUsername", "showResetCredentials", "showTryAnotherWayLink"]>
|
50
|
-
</#if>
|
51
|
-
<#if depth==0 && key=="updateProfileCtx" ><#continue></#if>
|
52
|
-
"${key}": <@objectToJson_please_ignore_errors object=value depth=depth+1 arr=arr_keys ftl=ftl />,
|
53
|
-
</#list>
|
54
|
-
}${'\n'}
|
55
|
-
<#return>
|
56
|
-
</#if>
|
57
|
-
<#local isMethod = "">
|
58
|
-
<#attempt>
|
59
|
-
<#local isMethod = object?is_method>
|
60
|
-
<#recover>
|
61
|
-
/* can't test if object is a method */
|
62
|
-
undefined
|
63
|
-
<#return>
|
64
|
-
</#attempt>
|
65
|
-
<#if isMethod>
|
66
|
-
undefined
|
67
|
-
<#return>
|
68
|
-
</#if>
|
69
|
-
<#local isBoolean = "">
|
70
|
-
<#attempt>
|
71
|
-
<#local isBoolean = object?is_boolean>
|
72
|
-
<#recover>
|
73
|
-
/* can't test if object is a boolean */
|
74
|
-
undefined
|
75
|
-
<#return>
|
76
|
-
</#attempt>
|
77
|
-
<#if isBoolean>
|
78
|
-
${object?c}
|
79
|
-
<#return>
|
80
|
-
</#if>
|
81
|
-
<#local isEnumerable = "">
|
82
|
-
<#attempt>
|
83
|
-
<#local isEnumerable = object?is_enumerable>
|
84
|
-
<#recover>
|
85
|
-
/* can't test if object is enumerable */
|
86
|
-
undefined
|
87
|
-
<#return>
|
88
|
-
</#attempt>
|
89
|
-
<#if isEnumerable>
|
90
|
-
[${'\n'}
|
91
|
-
<#list object as item>
|
92
|
-
<@objectToJson_please_ignore_errors object=item depth=depth+1 arr=[] ftl=ftl/>,
|
93
|
-
</#list>
|
94
|
-
]${'\n'}
|
95
|
-
<#return>
|
96
|
-
</#if>
|
97
|
-
<#attempt>
|
98
|
-
"${object?replace('"', '\\"')?no_esc}"
|
99
|
-
<#recover>
|
100
|
-
/* couldn't convert into string non hash, non method, non boolean, non enumerable object */
|
101
|
-
undefined;
|
102
|
-
<#return>
|
103
|
-
</#attempt>
|
104
|
-
</@compress>
|
105
|
-
</#macro>
|
106
|
-
(()=>{
|
107
|
-
const nonAutomaticallyConvertible = {
|
108
|
-
"messagesPerField": {
|
109
|
-
<#assign fieldNames = ["global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm", "totp", "totpSecret", "SAMLRequest", "SAMLResponse", "relayState", "device_user_code", "code", "password-new", "rememberMe", "login", "authenticationExecution", "cancel-aia", "clientDataJSON", "authenticatorData", "signature", "credentialId", "userHandle", "error", "authn_use_chk", "authenticationExecution", "isSetRetry", "try-again", "attestationObject", "publicKeyCredentialId", "authenticatorLabel"]>
|
110
|
-
<#assign attributes = (profile.attributes)![]>
|
111
|
-
<#attempt>
|
112
|
-
<#list attributes as attribute>
|
113
|
-
<#if (attribute.name)??>
|
114
|
-
<#assign fieldNames += [attribute.name]>
|
115
|
-
</#if>
|
116
|
-
</#list>
|
117
|
-
<#recover>
|
118
|
-
</#attempt>
|
119
|
-
"printIfExists": function (fieldName, x) {
|
120
|
-
<#list fieldNames as fieldName>
|
121
|
-
if(fieldName === "${fieldName}" ){
|
122
|
-
<#attempt>
|
123
|
-
return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined;
|
124
|
-
<#recover>
|
125
|
-
</#attempt>
|
126
|
-
}
|
127
|
-
</#list>
|
128
|
-
throw new Error("There is no " + fieldName + " field");
|
129
|
-
},
|
130
|
-
"existsError": function (fieldName) {
|
131
|
-
<#list fieldNames as fieldName>
|
132
|
-
if(fieldName === "${fieldName}" ){
|
133
|
-
<#attempt>
|
134
|
-
return <#if messagesPerField.existsError('${fieldName}')>true<#else>false</#if>;
|
135
|
-
<#recover>
|
136
|
-
</#attempt>
|
137
|
-
}
|
138
|
-
</#list>
|
139
|
-
throw new Error("There is no " + fieldName + " field");
|
140
|
-
},
|
141
|
-
"get": function (fieldName) {
|
142
|
-
<#list fieldNames as fieldName>
|
143
|
-
if(fieldName === "${fieldName}" ){
|
144
|
-
<#attempt>
|
145
|
-
<#if messagesPerField.existsError('${fieldName}')>
|
146
|
-
return "${messagesPerField.get('${fieldName}')?no_esc}";
|
147
|
-
</#if>
|
148
|
-
<#recover>
|
149
|
-
</#attempt>
|
150
|
-
}
|
151
|
-
</#list>
|
152
|
-
throw new Error("There is no " + fieldName + " field");
|
153
|
-
},
|
154
|
-
"exists": function (fieldName) {
|
155
|
-
<#list fieldNames as fieldName>
|
156
|
-
if(fieldName === "${fieldName}" ){
|
157
|
-
<#attempt>
|
158
|
-
return <#if messagesPerField.exists('${fieldName}')>true<#else>false</#if>;
|
159
|
-
<#recover>
|
160
|
-
</#attempt>
|
161
|
-
}
|
162
|
-
</#list>
|
163
|
-
throw new Error("There is no " + fieldName + " field");
|
164
|
-
}
|
165
|
-
},
|
166
|
-
"msg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); },
|
167
|
-
"advancedMsg": function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); }
|
168
|
-
};
|
169
|
-
const out = {};
|
170
|
-
Object.deepAssign(
|
171
|
-
out,
|
172
|
-
//Removing all the undefined
|
173
|
-
JSON.parse(JSON.stringify(<@objectToJson_please_ignore_errors object=.data_model depth=0 arr=[] ftl="ftl_template_for_replacement" />), (key, value) => value === "error_data_is_undefined" ? undefined : value)
|
174
|
-
);
|
175
|
-
Object.deepAssign(
|
176
|
-
out,
|
177
|
-
nonAutomaticallyConvertible
|
178
|
-
);
|
179
|
-
return out;
|
180
|
-
})()
|
181
|
-
</script>
|