keycloakify 4.2.12 → 4.2.14

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.
@@ -0,0 +1,290 @@
1
+ <script>const _=
2
+ <#assign pageId="PAGE_ID_xIgLsPgGId9D8e">
3
+ (()=>{
4
+
5
+ const out =
6
+ ${ftl_object_to_js_code_declaring_an_object(.data_model, [])?no_esc};
7
+
8
+ out["msg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
9
+ out["advancedMsg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
10
+
11
+ out["messagesPerField"]= {
12
+ <#assign fieldNames = [
13
+ "global", "userLabel", "username", "email", "firstName", "lastName", "password", "password-confirm",
14
+ "totp", "totpSecret", "SAMLRequest", "SAMLResponse", "relayState", "device_user_code", "code",
15
+ "password-new", "rememberMe", "login", "authenticationExecution", "cancel-aia", "clientDataJSON",
16
+ "authenticatorData", "signature", "credentialId", "userHandle", "error", "authn_use_chk", "authenticationExecution",
17
+ "isSetRetry", "try-again", "attestationObject", "publicKeyCredentialId", "authenticatorLabel"
18
+ ]>
19
+
20
+ <#attempt>
21
+ <#if profile?? && profile.attributes?? && profile.attributes?is_enumerable>
22
+ <#list profile.attributes as attribute>
23
+ <#if fieldNames?seq_contains(attribute.name)>
24
+ <#continue>
25
+ </#if>
26
+ <#assign fieldNames += [attribute.name]>
27
+ </#list>
28
+ </#if>
29
+ <#recover>
30
+ </#attempt>
31
+
32
+ "printIfExists": function (fieldName, x) {
33
+ <#list fieldNames as fieldName>
34
+ if(fieldName === "${fieldName}" ){
35
+ <#attempt>
36
+ return "${messagesPerField.printIfExists(fieldName,'1')}" ? x : undefined;
37
+ <#recover>
38
+ </#attempt>
39
+ }
40
+ </#list>
41
+ throw new Error("There is no " + fieldName + " field");
42
+ },
43
+ "existsError": function (fieldName) {
44
+ <#list fieldNames as fieldName>
45
+ if(fieldName === "${fieldName}" ){
46
+ <#attempt>
47
+ return <#if messagesPerField.existsError('${fieldName}')>true<#else>false</#if>;
48
+ <#recover>
49
+ </#attempt>
50
+ }
51
+ </#list>
52
+ throw new Error("There is no " + fieldName + " field");
53
+ },
54
+ "get": function (fieldName) {
55
+ <#list fieldNames as fieldName>
56
+ if(fieldName === "${fieldName}" ){
57
+ <#attempt>
58
+ <#if messagesPerField.existsError('${fieldName}')>
59
+ return "${messagesPerField.get('${fieldName}')?no_esc}";
60
+ </#if>
61
+ <#recover>
62
+ </#attempt>
63
+ }
64
+ </#list>
65
+ throw new Error("There is no " + fieldName + " field");
66
+ },
67
+ "exists": function (fieldName) {
68
+ <#list fieldNames as fieldName>
69
+ if(fieldName === "${fieldName}" ){
70
+ <#attempt>
71
+ return <#if messagesPerField.exists('${fieldName}')>true<#else>false</#if>;
72
+ <#recover>
73
+ </#attempt>
74
+ }
75
+ </#list>
76
+ throw new Error("There is no " + fieldName + " field");
77
+ }
78
+ };
79
+
80
+ out["pageId"] = "${pageId}";
81
+
82
+ return out;
83
+
84
+ })()
85
+ <#function ftl_object_to_js_code_declaring_an_object object path>
86
+
87
+ <#local isHash = "">
88
+ <#attempt>
89
+ <#local isHash = object?is_hash || object?is_hash_ex>
90
+ <#recover>
91
+ <#return "ABORT: Can't evaluate if " + path?join(".") + " is hash">
92
+ </#attempt>
93
+
94
+ <#if isHash>
95
+
96
+ <#if path?size gt 10>
97
+ <#return "ABORT: Too many recursive calls">
98
+ </#if>
99
+
100
+ <#local keys = "">
101
+
102
+ <#attempt>
103
+ <#local keys = object?keys>
104
+ <#recover>
105
+ <#return "ABORT: We can't list keys on this object">
106
+ </#attempt>
107
+
108
+
109
+ <#local out_seq = []>
110
+
111
+ <#list keys as key>
112
+
113
+ <#if ["class","declaredConstructors","superclass","declaringClass" ]?seq_contains(key) >
114
+ <#continue>
115
+ </#if>
116
+
117
+ <#if
118
+ (
119
+ ["loginUpdatePasswordUrl", "loginUpdateProfileUrl", "loginUsernameReminderUrl", "loginUpdateTotpUrl"]?seq_contains(key) &&
120
+ are_same_path(path, ["url"])
121
+ ) || (
122
+ key == "updateProfileCtx" &&
123
+ are_same_path(path, [])
124
+ ) || (
125
+ <#-- https://github.com/InseeFrLab/keycloakify/pull/65#issuecomment-991896344 -->
126
+ key == "loginAction" &&
127
+ are_same_path(path, ["url"]) &&
128
+ pageId == "saml-post-form.ftl"
129
+ )
130
+ >
131
+ <#local out_seq += ["/*If you need '" + key + "' on " + pageId + ", please submit an issue to the Keycloakify repo*/"]>
132
+ <#continue>
133
+ </#if>
134
+
135
+ <#if key == "attemptedUsername" && are_same_path(path, ["auth"])>
136
+
137
+ <#attempt>
138
+ <#-- https://github.com/keycloak/keycloak/blob/3a2bf0c04bcde185e497aaa32d0bb7ab7520cf4a/themes/src/main/resources/theme/base/login/template.ftl#L63 -->
139
+ <#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())>
140
+ <#continue>
141
+ </#if>
142
+ <#recover>
143
+ </#attempt>
144
+
145
+ </#if>
146
+
147
+ <#attempt>
148
+ <#if !object[key]??>
149
+ <#continue>
150
+ </#if>
151
+ <#recover>
152
+ <#local out_seq += ["/*Couldn't test if '" + key + "' is available on this object*/"]>
153
+ <#continue>
154
+ </#attempt>
155
+
156
+ <#local propertyValue = "">
157
+
158
+ <#attempt>
159
+ <#local propertyValue = object[key]>
160
+ <#recover>
161
+ <#local out_seq += ["/*Couldn't dereference '" + key + "' on this object*/"]>
162
+ <#continue>
163
+ </#attempt>
164
+
165
+ <#local rec_out = ftl_object_to_js_code_declaring_an_object(propertyValue, path + [ key ])>
166
+
167
+ <#if rec_out?starts_with("ABORT:")>
168
+
169
+ <#local errorMessage = rec_out?remove_beginning("ABORT:")>
170
+
171
+ <#if errorMessage != " It's a method" >
172
+ <#local out_seq += ["/*" + key + ": " + errorMessage + "*/"]>
173
+ </#if>
174
+
175
+ <#continue>
176
+ </#if>
177
+
178
+ <#local out_seq += ['"' + key + '": ' + rec_out + ","]>
179
+
180
+ </#list>
181
+
182
+ <#return (["{"] + out_seq?map(str -> ""?right_pad(4 * (path?size + 1)) + str) + [ ""?right_pad(4 * path?size) + "}"])?join("\n")>
183
+
184
+ </#if>
185
+
186
+ <#local isMethod = "">
187
+ <#attempt>
188
+ <#local isMethod = object?is_method>
189
+ <#recover>
190
+ <#return "ABORT: Can't test if it'sa method.">
191
+ </#attempt>
192
+
193
+ <#if isMethod>
194
+ <#return "ABORT: It's a method">
195
+ </#if>
196
+
197
+ <#local isBoolean = "">
198
+ <#attempt>
199
+ <#local isBoolean = object?is_boolean>
200
+ <#recover>
201
+ <#return "ABORT: Can't test if it's a boolean">
202
+ </#attempt>
203
+
204
+ <#if isBoolean>
205
+ <#return object?c>
206
+ </#if>
207
+
208
+ <#local isEnumerable = "">
209
+ <#attempt>
210
+ <#local isEnumerable = object?is_enumerable>
211
+ <#recover>
212
+ <#return "ABORT: Can't test if it's an enumerable">
213
+ </#attempt>
214
+
215
+
216
+ <#if isEnumerable>
217
+
218
+ <#local out_seq = []>
219
+
220
+ <#local i = 0>
221
+
222
+ <#list object as array_item>
223
+
224
+ <#local rec_out = ftl_object_to_js_code_declaring_an_object(array_item, path + [ i ])>
225
+
226
+ <#local i = i + 1>
227
+
228
+ <#if rec_out?starts_with("ABORT:")>
229
+
230
+ <#local errorMessage = rec_out?remove_beginning("ABORT:")>
231
+
232
+ <#if errorMessage != " It's a method" >
233
+ <#local out_seq += ["/*" + i?string + ": " + errorMessage + "*/"]>
234
+ </#if>
235
+
236
+ <#continue>
237
+ </#if>
238
+
239
+ <#local out_seq += [rec_out + ","]>
240
+
241
+ </#list>
242
+
243
+ <#return (["["] + out_seq?map(str -> ""?right_pad(4 * (path?size + 1)) + str) + [ ""?right_pad(4 * path?size) + "]"])?join("\n")>
244
+
245
+ </#if>
246
+
247
+ <#attempt>
248
+ <#return '"' + object?js_string + '"'>;
249
+ <#recover>
250
+ </#attempt>
251
+
252
+ <#return "ABORT: Couldn't convert into string non hash, non method, non boolean, non enumerable object">
253
+
254
+ </#function>
255
+ <#function are_same_path path searchedPath>
256
+
257
+ <#if path?size != path?size>
258
+ <#return false>
259
+ </#if>
260
+
261
+ <#local i=0>
262
+
263
+ <#list path as property>
264
+
265
+ <#local searchedProperty=searchedPath[i]>
266
+
267
+ <#if searchedProperty?is_string && searchedProperty == "*">
268
+ <#continue>
269
+ </#if>
270
+
271
+ <#if searchedProperty?is_string && !property?is_string>
272
+ <#return false>
273
+ </#if>
274
+
275
+ <#if searchedProperty?is_number && !property?is_number>
276
+ <#return false>
277
+ </#if>
278
+
279
+ <#if searchedProperty?string != property?string>
280
+ <#return false>
281
+ </#if>
282
+
283
+ <#local i+= 1>
284
+
285
+ </#list>
286
+
287
+ <#return true>
288
+
289
+ </#function>
290
+ </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 ftlPlaceholders = {
81
- '{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }': loadAdjacentFile("common.ftl").match(/^<script>const _=((?:.|\n)+)<\/script>[\n]?$/)![1],
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,8 +87,6 @@ export function generateFtlFilesCodeFactory(params: {
88
87
  ].join("\n"),
89
88
  };
90
89
 
91
- const pageSpecificCodePlaceholder = "<!-- dIddLqMeOedErIdLsPdNdI9dSl42sw -->";
92
-
93
90
  $("head").prepend(
94
91
  [
95
92
  ...(Object.keys(cssGlobalsToDefine).length === 0
@@ -105,18 +102,10 @@ export function generateFtlFilesCodeFactory(params: {
105
102
  "",
106
103
  ]),
107
104
  "<script>",
108
- loadAdjacentFile("Object.deepAssign.js"),
105
+ ` window.${ftlValuesGlobalName}= ${objectKeys(replaceValueBySearchValue)[0]};`,
109
106
  "</script>",
110
- "<script>",
111
- ` window.${ftlValuesGlobalName}= Object.assign(`,
112
- ` {},`,
113
- ` ${objectKeys(ftlPlaceholders)[0]}`,
114
- " );",
115
- "</script>",
116
- "",
117
- pageSpecificCodePlaceholder,
118
107
  "",
119
- objectKeys(ftlPlaceholders)[1],
108
+ objectKeys(replaceValueBySearchValue)[1],
120
109
  ].join("\n"),
121
110
  );
122
111
 
@@ -129,19 +118,13 @@ export function generateFtlFilesCodeFactory(params: {
129
118
 
130
119
  const $ = cheerio.load(partiallyFixedIndexHtmlCode);
131
120
 
132
- let ftlCode = $.html().replace(
133
- pageSpecificCodePlaceholder,
134
- [
135
- "<script>",
136
- ` Object.deepAssign(`,
137
- ` window.${ftlValuesGlobalName},`,
138
- ` { "pageId": "${pageId}" }`,
139
- " );",
140
- "</script>",
141
- ].join("\n"),
142
- );
143
-
144
- objectKeys(ftlPlaceholders).forEach(id => (ftlCode = ftlCode.replace(id, ftlPlaceholders[id])));
121
+ let ftlCode = $.html();
122
+
123
+ Object.entries({
124
+ ...replaceValueBySearchValue,
125
+ //If updated, don't forget to change in the ftl script as well.
126
+ "PAGE_ID_xIgLsPgGId9D8e": pageId,
127
+ }).map(([searchValue, replaceValue]) => (ftlCode = ftlCode.replace(searchValue, replaceValue)));
145
128
 
146
129
  return { ftlCode };
147
130
  }
@@ -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
- );