keycloakify 10.0.0-rc.2 → 10.0.0-rc.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/account/Template.js +2 -2
  2. package/account/Template.js.map +1 -1
  3. package/account/i18n/i18n.d.ts +3 -4
  4. package/account/i18n/i18n.js +2 -3
  5. package/account/i18n/i18n.js.map +1 -1
  6. package/account/kcContext/KcContext.d.ts +0 -15
  7. package/account/kcContext/KcContext.js.map +1 -1
  8. package/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +160 -243
  9. package/bin/keycloakify/generateFtl/generateFtl.js +1 -1
  10. package/bin/keycloakify/generateFtl/generateFtl.js.map +1 -1
  11. package/bin/keycloakify/generateStartKeycloakTestingContainer.d.ts +2 -0
  12. package/bin/keycloakify/generateStartKeycloakTestingContainer.js +9 -12
  13. package/bin/keycloakify/generateStartKeycloakTestingContainer.js.map +1 -1
  14. package/bin/keycloakify/keycloakify.js +1 -0
  15. package/bin/keycloakify/keycloakify.js.map +1 -1
  16. package/login/Template.js +2 -2
  17. package/login/Template.js.map +1 -1
  18. package/login/UserProfileFormFields.js +2 -4
  19. package/login/UserProfileFormFields.js.map +1 -1
  20. package/login/i18n/i18n.d.ts +3 -4
  21. package/login/i18n/i18n.js +2 -3
  22. package/login/i18n/i18n.js.map +1 -1
  23. package/login/lib/useUserProfileForm.js +9 -9
  24. package/login/lib/useUserProfileForm.js.map +1 -1
  25. package/login/pages/Code.js +1 -1
  26. package/login/pages/Code.js.map +1 -1
  27. package/login/pages/IdpReviewUserProfile.js.map +1 -1
  28. package/login/pages/Login.js +1 -1
  29. package/login/pages/Login.js.map +1 -1
  30. package/login/pages/LoginUpdateProfile.js +1 -1
  31. package/login/pages/LoginUpdateProfile.js.map +1 -1
  32. package/login/pages/LoginUsername.js +1 -1
  33. package/login/pages/LoginUsername.js.map +1 -1
  34. package/login/pages/Register.js +1 -1
  35. package/login/pages/Register.js.map +1 -1
  36. package/login/pages/UpdateEmail.js.map +1 -1
  37. package/login/pages/WebauthnRegister.js +1 -1
  38. package/login/pages/WebauthnRegister.js.map +1 -1
  39. package/package.json +1 -7
  40. package/src/account/Template.tsx +2 -5
  41. package/src/account/i18n/i18n.tsx +5 -8
  42. package/src/account/kcContext/KcContext.ts +0 -15
  43. package/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl +160 -243
  44. package/src/bin/keycloakify/generateFtl/generateFtl.ts +1 -1
  45. package/src/bin/keycloakify/generateStartKeycloakTestingContainer.ts +13 -14
  46. package/src/bin/keycloakify/keycloakify.ts +1 -0
  47. package/src/login/Template.tsx +6 -22
  48. package/src/login/UserProfileFormFields.tsx +2 -5
  49. package/src/login/i18n/i18n.tsx +5 -8
  50. package/src/login/lib/useUserProfileForm.tsx +10 -10
  51. package/src/login/pages/Code.tsx +1 -1
  52. package/src/login/pages/IdpReviewUserProfile.tsx +1 -1
  53. package/src/login/pages/Login.tsx +1 -1
  54. package/src/login/pages/LoginUpdateProfile.tsx +1 -1
  55. package/src/login/pages/LoginUsername.tsx +1 -1
  56. package/src/login/pages/Register.tsx +1 -1
  57. package/src/login/pages/UpdateEmail.tsx +1 -1
  58. package/src/login/pages/WebauthnRegister.tsx +1 -1
  59. package/bin/tools/grant-exec-perms.d.ts +0 -1
  60. package/bin/tools/grant-exec-perms.js +0 -100
  61. package/bin/tools/grant-exec-perms.js.map +0 -1
  62. package/src/bin/tools/grant-exec-perms.ts +0 -19
@@ -1,291 +1,189 @@
1
1
  <script>const _=
2
- <#assign pageId="PAGE_ID_xIgLsPgGId9D8e">
3
2
  (()=>{
4
-
5
- const out = ${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 = [ FIELD_NAMES_eKsIY4ZsZ4xeM ]>
12
-
13
- <#attempt>
14
- <#if profile?? && profile.attributes?? && profile.attributes?is_enumerable>
15
- <#list profile.attributes as attribute>
16
- <#if fieldNames?seq_contains(attribute.name)>
17
- <#continue>
18
- </#if>
19
- <#assign fieldNames += [attribute.name]>
20
- </#list>
21
- </#if>
22
- <#recover>
23
- </#attempt>
24
-
25
- "printIfExists": function (fieldName, text) {
26
-
27
- <#if !messagesPerField?? || !(messagesPerField?is_hash)>
28
- throw new Error("You're not supposed to use messagesPerField.printIfExists in this page");
29
- <#else>
30
- <#list fieldNames as fieldName>
31
- if(fieldName === "${fieldName}" ){
32
-
33
- <#-- https://github.com/keycloakify/keycloakify/pull/218 -->
34
- <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'>
35
-
36
- <#assign doExistErrorOnUsernameOrPassword = "">
37
-
38
- <#attempt>
39
- <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')>
40
- <#recover>
41
- <#assign doExistErrorOnUsernameOrPassword = true>
42
- </#attempt>
43
-
44
- <#if doExistErrorOnUsernameOrPassword>
45
- return text;
46
- <#else>
47
-
48
- <#assign doExistMessageForField = "">
49
-
50
- <#attempt>
51
- <#assign doExistMessageForField = messagesPerField.exists('${fieldName}')>
52
- <#recover>
53
- <#assign doExistMessageForField = true>
54
- </#attempt>
55
-
56
- return <#if doExistMessageForField>text<#else>undefined</#if>;
57
-
58
- </#if>
59
-
3
+ <#assign pageId="PAGE_ID_xIgLsPgGId9D8e">
4
+ const out = ${ftl_object_to_js_code_declaring_an_object(.data_model, [])?no_esc};
5
+ out["msg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
6
+ out["advancedMsg"]= function(){ throw new Error("use import { useKcMessage } from 'keycloakify'"); };
7
+ out["messagesPerField"]= {
8
+ <#assign fieldNames = [ FIELD_NAMES_eKsIY4ZsZ4xeM ]>
9
+ <#attempt>
10
+ <#if profile?? && profile.attributes?? && profile.attributes?is_enumerable>
11
+ <#list profile.attributes as attribute>
12
+ <#if fieldNames?seq_contains(attribute.name)>
13
+ <#continue>
14
+ </#if>
15
+ <#assign fieldNames += [attribute.name]>
16
+ </#list>
17
+ </#if>
18
+ <#recover>
19
+ </#attempt>
20
+ "printIfExists": function (fieldName, text) {
21
+ <#if !messagesPerField?? || !(messagesPerField?is_hash)>
22
+ throw new Error("You're not supposed to use messagesPerField.printIfExists in this page");
23
+ <#else>
24
+ <#list fieldNames as fieldName>
25
+ if(fieldName === "${fieldName}" ){
26
+ <#-- https://github.com/keycloakify/keycloakify/pull/218 -->
27
+ <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'>
28
+ <#assign doExistErrorOnUsernameOrPassword = "">
29
+ <#attempt>
30
+ <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')>
31
+ <#recover>
32
+ <#assign doExistErrorOnUsernameOrPassword = true>
33
+ </#attempt>
34
+ <#if doExistErrorOnUsernameOrPassword>
35
+ return text;
60
36
  <#else>
61
-
62
37
  <#assign doExistMessageForField = "">
63
-
64
38
  <#attempt>
65
39
  <#assign doExistMessageForField = messagesPerField.exists('${fieldName}')>
66
40
  <#recover>
67
41
  <#assign doExistMessageForField = true>
68
42
  </#attempt>
69
-
70
43
  return <#if doExistMessageForField>text<#else>undefined</#if>;
71
-
72
44
  </#if>
73
-
74
-
75
- }
76
- </#list>
77
-
78
- throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated");
79
- </#if>
80
-
81
- },
82
- "existsError": function (){
83
-
84
- function existsError_singleFieldName(fieldName) {
85
-
86
- <#if !messagesPerField?? || !(messagesPerField?is_hash)>
87
- throw new Error("You're not supposed to use messagesPerField.printIfExists in this page");
88
- <#else>
89
- <#list fieldNames as fieldName>
90
- if(fieldName === "${fieldName}" ){
91
-
92
- <#-- https://github.com/keycloakify/keycloakify/pull/218 -->
93
- <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'>
94
-
95
- <#assign doExistErrorOnUsernameOrPassword = "">
96
-
97
- <#attempt>
98
- <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')>
99
- <#recover>
100
- <#assign doExistErrorOnUsernameOrPassword = true>
101
- </#attempt>
102
-
103
- return <#if doExistErrorOnUsernameOrPassword>true<#else>false</#if>;
104
-
105
- <#else>
106
-
107
- <#assign doExistErrorMessageForField = "">
108
-
109
- <#attempt>
110
- <#assign doExistErrorMessageForField = messagesPerField.existsError('${fieldName}')>
111
- <#recover>
112
- <#assign doExistErrorMessageForField = true>
113
- </#attempt>
114
-
115
- return <#if doExistErrorMessageForField>true<#else>false</#if>;
116
-
117
- </#if>
118
-
119
- }
120
- </#list>
121
-
122
- throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated");
123
-
124
- </#if>
125
-
126
- }
127
-
128
- for( let i = 0; i < arguments.length; i++ ){
129
-
130
- if( existsError_singleFieldName(arguments[i]) ){
131
- return true;
45
+ <#else>
46
+ <#assign doExistMessageForField = "">
47
+ <#attempt>
48
+ <#assign doExistMessageForField = messagesPerField.exists('${fieldName}')>
49
+ <#recover>
50
+ <#assign doExistMessageForField = true>
51
+ </#attempt>
52
+ return <#if doExistMessageForField>text<#else>undefined</#if>;
53
+ </#if>
132
54
  }
133
-
134
- }
135
-
136
- return false;
137
-
138
- },
139
- "get": function (fieldName) {
140
-
141
-
55
+ </#list>
56
+ throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated");
57
+ </#if>
58
+ },
59
+ "existsError": function (){
60
+ function existsError_singleFieldName(fieldName) {
142
61
  <#if !messagesPerField?? || !(messagesPerField?is_hash)>
143
- throw new Error("You're not supposed to use messagesPerField.get in this page");
62
+ throw new Error("You're not supposed to use messagesPerField.printIfExists in this page");
144
63
  <#else>
145
64
  <#list fieldNames as fieldName>
146
65
  if(fieldName === "${fieldName}" ){
147
-
148
66
  <#-- https://github.com/keycloakify/keycloakify/pull/218 -->
149
67
  <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'>
150
-
151
68
  <#assign doExistErrorOnUsernameOrPassword = "">
152
-
153
69
  <#attempt>
154
70
  <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')>
155
71
  <#recover>
156
72
  <#assign doExistErrorOnUsernameOrPassword = true>
157
73
  </#attempt>
158
-
159
- <#if doExistErrorOnUsernameOrPassword>
160
-
161
- <#attempt>
162
- return "${kcSanitize(msg('invalidUserMessage'))?no_esc}";
163
- <#recover>
164
- return "Invalid username or password.";
165
- </#attempt>
166
-
167
- <#else>
168
-
169
- <#attempt>
170
- return "${messagesPerField.get('${fieldName}')?no_esc}";
171
- <#recover>
172
- return "";
173
- </#attempt>
174
-
175
- </#if>
176
-
74
+ return <#if doExistErrorOnUsernameOrPassword>true<#else>false</#if>;
177
75
  <#else>
178
-
76
+ <#assign doExistErrorMessageForField = "">
179
77
  <#attempt>
180
- return "${messagesPerField.get('${fieldName}')?no_esc}";
78
+ <#assign doExistErrorMessageForField = messagesPerField.existsError('${fieldName}')>
181
79
  <#recover>
182
- return "invalid field";
80
+ <#assign doExistErrorMessageForField = true>
183
81
  </#attempt>
184
-
82
+ return <#if doExistErrorMessageForField>true<#else>false</#if>;
185
83
  </#if>
186
-
187
84
  }
188
85
  </#list>
189
-
190
86
  throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated");
191
-
192
87
  </#if>
193
-
194
- },
195
- "exists": function (fieldName) {
196
-
197
- <#if !messagesPerField?? || !(messagesPerField?is_hash)>
198
- throw new Error("You're not supposed to use messagesPerField.exists in this page");
199
- <#else>
200
- <#list fieldNames as fieldName>
201
- if(fieldName === "${fieldName}" ){
202
-
203
- <#-- https://github.com/keycloakify/keycloakify/pull/218 -->
204
- <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'>
205
-
206
- <#assign doExistErrorOnUsernameOrPassword = "">
207
-
88
+ }
89
+ for( let i = 0; i < arguments.length; i++ ){
90
+ if( existsError_singleFieldName(arguments[i]) ){
91
+ return true;
92
+ }
93
+ }
94
+ return false;
95
+ },
96
+ "get": function (fieldName) {
97
+ <#if !messagesPerField?? || !(messagesPerField?is_hash)>
98
+ throw new Error("You're not supposed to use messagesPerField.get in this page");
99
+ <#else>
100
+ <#list fieldNames as fieldName>
101
+ if(fieldName === "${fieldName}" ){
102
+ <#-- https://github.com/keycloakify/keycloakify/pull/218 -->
103
+ <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'>
104
+ <#assign doExistErrorOnUsernameOrPassword = "">
105
+ <#attempt>
106
+ <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')>
107
+ <#recover>
108
+ <#assign doExistErrorOnUsernameOrPassword = true>
109
+ </#attempt>
110
+ <#if doExistErrorOnUsernameOrPassword>
208
111
  <#attempt>
209
- <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')>
112
+ return "${kcSanitize(msg('invalidUserMessage'))?no_esc}";
210
113
  <#recover>
211
- <#assign doExistErrorOnUsernameOrPassword = true>
114
+ return "Invalid username or password.";
212
115
  </#attempt>
213
-
214
- return <#if doExistErrorOnUsernameOrPassword>true<#else>false</#if>;
215
-
216
116
  <#else>
217
-
218
- <#assign doExistErrorMessageForField = "">
219
-
220
117
  <#attempt>
221
- <#assign doExistErrorMessageForField = messagesPerField.exists('${fieldName}')>
118
+ return "${messagesPerField.get('${fieldName}')?no_esc}";
222
119
  <#recover>
223
- <#assign doExistErrorMessageForField = true>
120
+ return "";
224
121
  </#attempt>
225
-
226
- return <#if doExistErrorMessageForField>true<#else>false</#if>;
227
-
228
122
  </#if>
229
-
230
- }
231
- </#list>
232
-
233
- throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated");
234
- </#if>
235
-
236
- },
237
- "getFirstError": function () {
238
-
239
- for( let i = 0; i < arguments.length; i++ ){
240
-
241
- const fieldName = arguments[i];
242
-
243
- if( out.messagesPerField.existsError(fieldName) ){
244
- return out.messagesPerField.get(fieldName);
123
+ <#else>
124
+ <#attempt>
125
+ return "${messagesPerField.get('${fieldName}')?no_esc}";
126
+ <#recover>
127
+ return "invalid field";
128
+ </#attempt>
129
+ </#if>
245
130
  }
246
-
131
+ </#list>
132
+ throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated");
133
+ </#if>
134
+ },
135
+ "exists": function (fieldName) {
136
+ <#if !messagesPerField?? || !(messagesPerField?is_hash)>
137
+ throw new Error("You're not supposed to use messagesPerField.exists in this page");
138
+ <#else>
139
+ <#list fieldNames as fieldName>
140
+ if(fieldName === "${fieldName}" ){
141
+ <#-- https://github.com/keycloakify/keycloakify/pull/218 -->
142
+ <#if ('${fieldName}' == 'username' || '${fieldName}' == 'password') && pageId != 'register.ftl' && pageId != 'register-user-profile.ftl'>
143
+ <#assign doExistErrorOnUsernameOrPassword = "">
144
+ <#attempt>
145
+ <#assign doExistErrorOnUsernameOrPassword = messagesPerField.existsError('username', 'password')>
146
+ <#recover>
147
+ <#assign doExistErrorOnUsernameOrPassword = true>
148
+ </#attempt>
149
+ return <#if doExistErrorOnUsernameOrPassword>true<#else>false</#if>;
150
+ <#else>
151
+ <#assign doExistErrorMessageForField = "">
152
+ <#attempt>
153
+ <#assign doExistErrorMessageForField = messagesPerField.exists('${fieldName}')>
154
+ <#recover>
155
+ <#assign doExistErrorMessageForField = true>
156
+ </#attempt>
157
+ return <#if doExistErrorMessageForField>true<#else>false</#if>;
158
+ </#if>
159
+ }
160
+ </#list>
161
+ throw new Error(fieldName + "is probably runtime generated, see: https://docs.keycloakify.dev/limitations#field-names-cant-be-runtime-generated");
162
+ </#if>
163
+ },
164
+ "getFirstError": function () {
165
+ for( let i = 0; i < arguments.length; i++ ){
166
+ const fieldName = arguments[i];
167
+ if( out.messagesPerField.existsError(fieldName) ){
168
+ return out.messagesPerField.get(fieldName);
247
169
  }
248
-
249
170
  }
250
- };
251
-
252
- <#if account??>
253
- out["url"]["getLogoutUrl"] = function () {
254
- <#attempt>
255
- return "${url.getLogoutUrl()}";
256
- <#recover>
257
- throw new Error("Failed to invoke url.getLogoutUrl() in the FreeMarker template");
258
- </#attempt>
259
- };
260
- </#if>
261
-
262
- <#if pageId === "login-config-totp.ftl">
263
- out["totp"]["policy"]["getAlgorithmKey"] = function () {
264
- <#attempt>
265
- return "${totp.policy.getAlgorithmKey()}";
266
- <#recover>
267
- throw new Error("Failed to invoke totp.policy.getAlgorithmKey() in the FreeMarker template");
268
- </#attempt>
269
- };
270
- </#if>
271
-
272
- out["keycloakifyVersion"] = "KEYCLOAKIFY_VERSION_xEdKd3xEdr";
273
- out["themeVersion"] = "KEYCLOAKIFY_THEME_VERSION_sIgKd3xEdr3dx";
274
- out["themeType"] = "KEYCLOAKIFY_THEME_TYPE_dExKd3xEdr";
275
- out["themeName"] = "KEYCLOAKIFY_THEME_NAME_cXxKd3xEer";
276
- out["pageId"] = "${pageId}";
277
-
278
- try {
171
+ }
172
+ };
279
173
 
280
- out["url"]["resourcesCommonPath"] = out["url"]["resourcesPath"] + "/" + "RESOURCES_COMMON_cLsLsMrtDkpVv";
174
+ out["keycloakifyVersion"] = "KEYCLOAKIFY_VERSION_xEdKd3xEdr";
175
+ out["themeVersion"] = "KEYCLOAKIFY_THEME_VERSION_sIgKd3xEdr3dx";
176
+ out["themeType"] = "KEYCLOAKIFY_THEME_TYPE_dExKd3xEdr";
177
+ out["themeName"] = "KEYCLOAKIFY_THEME_NAME_cXxKd3xEer";
178
+ out["pageId"] = "${pageId}";
281
179
 
282
- } catch(error) {
180
+ try {
181
+ out["url"]["resourcesCommonPath"] = out["url"]["resourcesPath"] + "/" + "RESOURCES_COMMON_cLsLsMrtDkpVv";
182
+ } catch(error) { }
283
183
 
284
- }
184
+ return out;
285
185
 
286
- return out;
287
-
288
- })()
186
+ })();
289
187
  <#function ftl_object_to_js_code_declaring_an_object object path>
290
188
 
291
189
  <#local isHash = "">
@@ -309,7 +207,6 @@
309
207
  <#return "ABORT: We can't list keys on this object">
310
208
  </#attempt>
311
209
 
312
-
313
210
  <#local out_seq = []>
314
211
 
315
212
  <#list keys as key>
@@ -378,7 +275,7 @@
378
275
  key == "realmAttributes"
379
276
  )
380
277
  >
381
- <#local out_seq += ["/*If you need '" + path?join(".") + "." + key + "' on " + pageId + ", please submit an issue to the Keycloakify repo*/"]>
278
+ <#local out_seq += ["/*" + path?join(".") + "." + key + " excluded*/"]>
382
279
  <#continue>
383
280
  </#if>
384
281
 
@@ -390,7 +287,7 @@
390
287
  <#attempt>
391
288
  <#-- https://github.com/keycloak/keycloak/blob/3a2bf0c04bcde185e497aaa32d0bb7ab7520cf4a/themes/src/main/resources/theme/base/login/template.ftl#L63 -->
392
289
  <#if !(auth?has_content && auth.showUsername() && !auth.showResetCredentials())>
393
- <#local out_seq += ["/*If you need '" + key + "' on " + pageId + ", please submit an issue to the Keycloakify repo*/"]>
290
+ <#local out_seq += ["/*" + path?join(".") + "." + key + " excluded*/"]>
394
291
  <#continue>
395
292
  </#if>
396
293
  <#recover>
@@ -470,6 +367,26 @@
470
367
  </#attempt>
471
368
  </#if>
472
369
 
370
+ <#if are_same_path(path, ["url", "getLogoutUrl"])>
371
+ <#local returnValue = "">
372
+ <#attempt>
373
+ <#local returnValue = url.getLogoutUrl()>
374
+ <#recover>
375
+ <#return "ABORT: Couldn't evaluate url.getLogoutUrl()">
376
+ </#attempt>
377
+ <#return 'function(){ return "' + returnValue + '"; }'>
378
+ </#if>
379
+
380
+ <#if are_same_path(path, ["totp", "policy", "getAlgorithmKey"])>
381
+ <#local returnValue = "">
382
+ <#attempt>
383
+ <#local returnValue = totp.policy.getAlgorithmKey()>
384
+ <#recover>
385
+ <#return "ABORT: Couldn't evaluate totp.policy.getAlgorithmKey()">
386
+ </#attempt>
387
+ <#return 'function(){ return "' + returnValue + '"; }'>
388
+ </#if>
389
+
473
390
  <#return "ABORT: It's a method">
474
391
  </#if>
475
392
 
@@ -108,7 +108,7 @@ export function generateFtlFilesCodeFactory(params: {
108
108
 
109
109
  const ftlObjectToJsCodeDeclaringAnObjectPlaceholder = '{ "x": "vIdLqMeOed9sdLdIdOxdK0d" }';
110
110
 
111
- $("head").prepend(["<script>", ` window.${nameOfTheGlobal}= ${ftlObjectToJsCodeDeclaringAnObjectPlaceholder};`, "</script>"].join("\n"));
111
+ $("head").prepend(`<script>\nwindow.${nameOfTheGlobal}=${ftlObjectToJsCodeDeclaringAnObjectPlaceholder}</script>`);
112
112
 
113
113
  // Remove part of the document marked as ignored.
114
114
  {
@@ -2,9 +2,11 @@ import * as fs from "fs";
2
2
  import { join as pathJoin, relative as pathRelative, basename as pathBasename } from "path";
3
3
  import { assert } from "tsafe/assert";
4
4
  import type { BuildOptions } from "./buildOptions";
5
+ import { accountV1ThemeName } from "../constants";
5
6
 
6
7
  export type BuildOptionsLike = {
7
8
  keycloakifyBuildDirPath: string;
9
+ themeNames: string[];
8
10
  };
9
11
 
10
12
  assert<BuildOptions extends BuildOptionsLike ? true : false>();
@@ -15,11 +17,14 @@ const containerName = "keycloak-testing-container";
15
17
  const keycloakVersion = "24.0.4";
16
18
 
17
19
  /** Files for being able to run a hot reload keycloak container */
18
- export function generateStartKeycloakTestingContainer(params: { jarFilePath: string; buildOptions: BuildOptionsLike }) {
19
- const { jarFilePath, buildOptions } = params;
20
+ export function generateStartKeycloakTestingContainer(params: {
21
+ jarFilePath: string;
22
+ doesImplementAccountTheme: boolean;
23
+ buildOptions: BuildOptionsLike;
24
+ }) {
25
+ const { jarFilePath, doesImplementAccountTheme, buildOptions } = params;
20
26
 
21
27
  const themeRelativeDirPath = pathJoin("src", "main", "resources", "theme");
22
- const themeDirPath = pathJoin(buildOptions.keycloakifyBuildDirPath, themeRelativeDirPath);
23
28
 
24
29
  fs.writeFileSync(
25
30
  pathJoin(buildOptions.keycloakifyBuildDirPath, generateStartKeycloakTestingContainer.basename),
@@ -40,18 +45,12 @@ export function generateStartKeycloakTestingContainer(params: { jarFilePath: str
40
45
  "$(pwd)",
41
46
  pathRelative(buildOptions.keycloakifyBuildDirPath, jarFilePath)
42
47
  )}":"/opt/keycloak/providers/${pathBasename(jarFilePath)}" \\`,
43
- ...fs
44
- .readdirSync(themeDirPath)
45
- .filter(name => fs.lstatSync(pathJoin(themeDirPath, name)).isDirectory())
46
- .map(
47
- themeName =>
48
- ` -v "${pathJoin("$(pwd)", themeRelativeDirPath, themeName).replace(
49
- /\\/g,
50
- "/"
51
- )}":"/opt/keycloak/themes/${themeName}":rw \\`
52
- ),
48
+ [...(doesImplementAccountTheme ? [accountV1ThemeName] : []), ...buildOptions.themeNames].map(
49
+ themeName =>
50
+ ` -v "${pathJoin("$(pwd)", themeRelativeDirPath, themeName).replace(/\\/g, "/")}":"/opt/keycloak/themes/${themeName}":rw \\`
51
+ ),
53
52
  ` -it quay.io/keycloak/keycloak:${keycloakVersion} \\`,
54
- ` start-dev --features=declarative-user-profile`,
53
+ ` start-dev`,
55
54
  ""
56
55
  ].join("\n"),
57
56
  "utf8"
@@ -57,6 +57,7 @@ export async function main() {
57
57
 
58
58
  generateStartKeycloakTestingContainer({
59
59
  "jarFilePath": pathJoin(buildOptions.keycloakifyBuildDirPath, lastJarFileBasename),
60
+ doesImplementAccountTheme,
60
61
  buildOptions
61
62
  });
62
63
 
@@ -32,7 +32,7 @@ export default function Template(props: TemplateProps<KcContext, I18n>) {
32
32
 
33
33
  const { getClassName } = useGetClassName({ doUseDefaultCss, classes });
34
34
 
35
- const { msg, msgStr, changeLocale, labelBySupportedLanguageTag, currentLanguageTag } = i18n;
35
+ const { msg, msgStr, getChangeLocalUrl, labelBySupportedLanguageTag, currentLanguageTag } = i18n;
36
36
 
37
37
  const { realm, locale, auth, url, message, isAppInitiatedAction, authenticationSession, scripts } = kcContext;
38
38
 
@@ -126,31 +126,17 @@ export default function Template(props: TemplateProps<KcContext, I18n>) {
126
126
 
127
127
  <div className={getClassName("kcFormCardClass")}>
128
128
  <header className={getClassName("kcFormHeaderClass")}>
129
- {realm.internationalizationEnabled && (assert(locale !== undefined), true) && locale.supported.length > 1 && (
129
+ {realm.internationalizationEnabled && (assert(locale !== undefined), locale.supported.length > 1) && (
130
130
  <div className={getClassName("kcLocaleMainClass")} id="kc-locale">
131
131
  <div id="kc-locale-wrapper" className={getClassName("kcLocaleWrapperClass")}>
132
132
  <div id="kc-locale-dropdown" className={clsx("menu-button-links", getClassName("kcLocaleDropDownClass"))}>
133
133
  {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
134
- <a href="#" id="kc-current-locale-link">
135
- {labelBySupportedLanguageTag[currentLanguageTag]}
136
- </a>
137
- <ul>
138
- {locale.supported.map(({ languageTag }) => (
139
- <li key={languageTag} className="kc-dropdown-item">
140
- {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
141
- <a href="#" onClick={() => changeLocale(languageTag)}>
142
- {labelBySupportedLanguageTag[languageTag]}
143
- </a>
144
- </li>
145
- ))}
146
- </ul>
147
-
148
134
  <button
149
135
  tabIndex={1}
150
136
  id="kc-current-locale-link"
151
137
  aria-label={msgStr("languages" as any)}
152
- aria-haspopup={true}
153
- aria-expanded={false}
138
+ aria-haspopup="true"
139
+ aria-expanded="false"
154
140
  aria-controls="language-switch1"
155
141
  >
156
142
  {labelBySupportedLanguageTag[currentLanguageTag]}
@@ -165,13 +151,11 @@ export default function Template(props: TemplateProps<KcContext, I18n>) {
165
151
  >
166
152
  {locale.supported.map(({ languageTag }, i) => (
167
153
  <li key={languageTag} className={getClassName("kcLocaleListItemClass")} role="none">
168
- {/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
169
154
  <a
170
155
  role="menuitem"
171
- id={`language-${i}`}
156
+ id={`language-${i + 1}`}
172
157
  className={getClassName("kcLocaleItemClass")}
173
- href="#"
174
- onClick={() => changeLocale(languageTag)}
158
+ href={getChangeLocalUrl(languageTag)}
175
159
  >
176
160
  {labelBySupportedLanguageTag[languageTag]}
177
161
  </a>
@@ -201,18 +201,15 @@ function FieldErrors(props: {
201
201
  <span
202
202
  id={`input-error-${attribute.name}${fieldIndex === undefined ? "" : `-${fieldIndex}`}`}
203
203
  className={getClassName("kcInputErrorMessageClass")}
204
- style={{
205
- "position": displayableErrors.length === 1 ? "absolute" : undefined
206
- }}
207
204
  aria-live="polite"
208
205
  >
209
206
  {displayableErrors
210
207
  .filter(error => error.fieldIndex === fieldIndex)
211
208
  .map(({ errorMessage }, i, arr) => (
212
- <>
209
+ <Fragment key={i}>
213
210
  <span key={i}>{errorMessage}</span>
214
211
  {arr.length - 1 !== i && <br />}
215
- </>
212
+ </Fragment>
216
213
  ))}
217
214
  </span>
218
215
  );