@keycloakify/angular 0.0.4 → 0.0.6

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 (177) hide show
  1. package/account/DefaultPage/DefaultPage.d.ts +2 -30
  2. package/esm2022/account/containers/template/template.component.mjs +6 -6
  3. package/esm2022/account/directives/kc-class/kc-class.directive.mjs +3 -3
  4. package/esm2022/account/pages/account/account.component.mjs +3 -3
  5. package/esm2022/account/pages/applications/applications.component.mjs +3 -3
  6. package/esm2022/account/pages/federatedIdentity/federatedIdentity.component.mjs +3 -3
  7. package/esm2022/account/pages/log/log.component.mjs +3 -3
  8. package/esm2022/account/pages/password/password.component.mjs +3 -3
  9. package/esm2022/account/pages/sessions/sessions.component.mjs +3 -3
  10. package/esm2022/account/pages/totp/totp.component.mjs +3 -3
  11. package/esm2022/account/services/account-resource-injector/account-resource-injector.service.mjs +3 -3
  12. package/esm2022/account/services/i18n/i18n.service.mjs +3 -3
  13. package/esm2022/lib/directives/attributes/attributes.directive.mjs +3 -3
  14. package/esm2022/lib/pipes/input-type/input-type.pipe.mjs +3 -3
  15. package/esm2022/lib/pipes/is-array-with-empty-object/is-array-with-empty-object.pipe.mjs +3 -3
  16. package/esm2022/lib/pipes/kc-sanitize/kc-sanitize.pipe.mjs +3 -3
  17. package/esm2022/lib/pipes/to-array/to-array.pipe.mjs +3 -3
  18. package/esm2022/lib/pipes/to-number/to-number.pipe.mjs +3 -3
  19. package/esm2022/lib/services/resource-injector/resource-injector.service.mjs +3 -3
  20. package/esm2022/login/components/add-remove-buttons-multi-valued-attribute/add-remove-buttons-multi-valued-attribute.component.mjs +7 -53
  21. package/esm2022/login/components/field-errors/field-errors.component.mjs +3 -3
  22. package/esm2022/login/components/group-label/group-label.component.mjs +3 -3
  23. package/esm2022/login/components/input-field-by-type/input-field-by-type.component.mjs +3 -3
  24. package/esm2022/login/components/input-tag/input-tag.component.mjs +3 -3
  25. package/esm2022/login/components/input-tag-selects/input-tag-selects.component.mjs +3 -3
  26. package/esm2022/login/components/logout-other-sessions/logout-other-sessions.component.mjs +3 -3
  27. package/esm2022/login/components/password-wrapper/password-wrapper.component.mjs +3 -3
  28. package/esm2022/login/components/select-tag/select-tag.component.mjs +3 -3
  29. package/esm2022/login/components/textarea-tag/textarea-tag.component.mjs +3 -3
  30. package/esm2022/login/components/user-profile-form-fields/user-profile-form-fields.component.mjs +15 -22
  31. package/esm2022/login/containers/template/template.component.mjs +6 -6
  32. package/esm2022/login/directives/kc-class/kc-class.directive.mjs +3 -3
  33. package/esm2022/login/pages/code/code.component.mjs +3 -3
  34. package/esm2022/login/pages/delete-account-confirm/delete-account-confirm.component.mjs +3 -3
  35. package/esm2022/login/pages/delete-credential/delete-credential.component.mjs +3 -3
  36. package/esm2022/login/pages/error/error.component.mjs +3 -3
  37. package/esm2022/login/pages/frontchannel-logout/frontchannel-logout.component.mjs +3 -3
  38. package/esm2022/login/pages/idp-review-user-profile/idp-review-user-profile.component.mjs +13 -15
  39. package/esm2022/login/pages/info/info.component.mjs +3 -3
  40. package/esm2022/login/pages/login/login.component.mjs +3 -3
  41. package/esm2022/login/pages/login-config-totp/login-config-totp.component.mjs +3 -3
  42. package/esm2022/login/pages/login-idp-link-confirm/login-idp-link-confirm.component.mjs +3 -3
  43. package/esm2022/login/pages/login-idp-link-confirm-override/login-idp-link-confirm-override.component.mjs +3 -3
  44. package/esm2022/login/pages/login-idp-link-email/login-idp-link-email.component.mjs +3 -3
  45. package/esm2022/login/pages/login-oauth-grant/login-oauth-grant.component.mjs +3 -3
  46. package/esm2022/login/pages/login-oauth2-device-verify-user-code/login-oauth2-device-verify-user-code.component.mjs +3 -3
  47. package/esm2022/login/pages/login-otp/login-otp.component.mjs +3 -3
  48. package/esm2022/login/pages/login-page-expired/login-page-expired.component.mjs +3 -3
  49. package/esm2022/login/pages/login-passkeys-conditional-authenticate/login-passkeys-conditional-authenticate.component.mjs +3 -3
  50. package/esm2022/login/pages/login-password/login-password.component.mjs +3 -3
  51. package/esm2022/login/pages/login-recovery-authn-code-config/login-recovery-authn-code-config.component.mjs +125 -6
  52. package/esm2022/login/pages/login-recovery-authn-code-input/login-recovery-authn-code-input.component.mjs +3 -3
  53. package/esm2022/login/pages/login-reset-otp/login-reset-otp.component.mjs +3 -3
  54. package/esm2022/login/pages/login-reset-password/login-reset-password.component.mjs +3 -3
  55. package/esm2022/login/pages/login-update-password/login-update-password.component.mjs +3 -3
  56. package/esm2022/login/pages/login-update-profile/login-update-profile.component.mjs +13 -15
  57. package/esm2022/login/pages/login-username/login-username.component.mjs +3 -3
  58. package/esm2022/login/pages/login-verify-email/login-verify-email.component.mjs +3 -3
  59. package/esm2022/login/pages/login-x509-info/login-x509-info.component.mjs +3 -3
  60. package/esm2022/login/pages/logout-confirm/logout-confirm.component.mjs +3 -3
  61. package/esm2022/login/pages/register/register.component.mjs +12 -14
  62. package/esm2022/login/pages/saml-post-form/saml-post-form.component.mjs +3 -3
  63. package/esm2022/login/pages/select-authenticator/select-authenticator.component.mjs +3 -3
  64. package/esm2022/login/pages/terms/terms.component.mjs +3 -3
  65. package/esm2022/login/pages/update-email/update-email.component.mjs +13 -15
  66. package/esm2022/login/pages/webauthn-authenticate/webauthn-authenticate.component.mjs +3 -3
  67. package/esm2022/login/pages/webauthn-error/webauthn-error.component.mjs +3 -3
  68. package/esm2022/login/pages/webauthn-register/webauthn-register.component.mjs +3 -3
  69. package/esm2022/login/services/i18n/i18n.service.mjs +3 -3
  70. package/esm2022/login/services/login-resource-injector/login-resource-injector.service.mjs +3 -3
  71. package/esm2022/login/services/user-profile-form/user-profile-form.service.mjs +56 -1004
  72. package/fesm2022/keycloakify-angular-account-containers-template.mjs +6 -6
  73. package/fesm2022/keycloakify-angular-account-directives-kc-class.mjs +3 -3
  74. package/fesm2022/keycloakify-angular-account-pages-account.mjs +3 -3
  75. package/fesm2022/keycloakify-angular-account-pages-applications.mjs +3 -3
  76. package/fesm2022/keycloakify-angular-account-pages-federatedIdentity.mjs +3 -3
  77. package/fesm2022/keycloakify-angular-account-pages-log.mjs +3 -3
  78. package/fesm2022/keycloakify-angular-account-pages-password.mjs +3 -3
  79. package/fesm2022/keycloakify-angular-account-pages-sessions.mjs +3 -3
  80. package/fesm2022/keycloakify-angular-account-pages-totp.mjs +3 -3
  81. package/fesm2022/keycloakify-angular-account-services-account-resource-injector.mjs +3 -3
  82. package/fesm2022/keycloakify-angular-account-services-i18n.mjs +3 -3
  83. package/fesm2022/keycloakify-angular-lib-directives-attributes.mjs +3 -3
  84. package/fesm2022/keycloakify-angular-lib-pipes-input-type.mjs +3 -3
  85. package/fesm2022/keycloakify-angular-lib-pipes-is-array-with-empty-object.mjs +3 -3
  86. package/fesm2022/keycloakify-angular-lib-pipes-kc-sanitize.mjs +3 -3
  87. package/fesm2022/keycloakify-angular-lib-pipes-to-array.mjs +3 -3
  88. package/fesm2022/keycloakify-angular-lib-pipes-to-number.mjs +3 -3
  89. package/fesm2022/keycloakify-angular-lib-services-resource-injector.mjs +3 -3
  90. package/fesm2022/keycloakify-angular-login-components-add-remove-buttons-multi-valued-attribute.mjs +6 -52
  91. package/fesm2022/keycloakify-angular-login-components-add-remove-buttons-multi-valued-attribute.mjs.map +1 -1
  92. package/fesm2022/keycloakify-angular-login-components-field-errors.mjs +3 -3
  93. package/fesm2022/keycloakify-angular-login-components-group-label.mjs +3 -3
  94. package/fesm2022/keycloakify-angular-login-components-input-field-by-type.mjs +3 -3
  95. package/fesm2022/keycloakify-angular-login-components-input-tag-selects.mjs +3 -3
  96. package/fesm2022/keycloakify-angular-login-components-input-tag.mjs +3 -3
  97. package/fesm2022/keycloakify-angular-login-components-logout-other-sessions.mjs +3 -3
  98. package/fesm2022/keycloakify-angular-login-components-password-wrapper.mjs +3 -3
  99. package/fesm2022/keycloakify-angular-login-components-select-tag.mjs +3 -3
  100. package/fesm2022/keycloakify-angular-login-components-textarea-tag.mjs +3 -3
  101. package/fesm2022/keycloakify-angular-login-components-user-profile-form-fields.mjs +14 -21
  102. package/fesm2022/keycloakify-angular-login-components-user-profile-form-fields.mjs.map +1 -1
  103. package/fesm2022/keycloakify-angular-login-containers-template.mjs +6 -6
  104. package/fesm2022/keycloakify-angular-login-directives-kc-class.mjs +3 -3
  105. package/fesm2022/keycloakify-angular-login-pages-code.mjs +3 -3
  106. package/fesm2022/keycloakify-angular-login-pages-delete-account-confirm.mjs +3 -3
  107. package/fesm2022/keycloakify-angular-login-pages-delete-credential.mjs +3 -3
  108. package/fesm2022/keycloakify-angular-login-pages-error.mjs +3 -3
  109. package/fesm2022/keycloakify-angular-login-pages-frontchannel-logout.mjs +3 -3
  110. package/fesm2022/keycloakify-angular-login-pages-idp-review-user-profile.mjs +12 -14
  111. package/fesm2022/keycloakify-angular-login-pages-idp-review-user-profile.mjs.map +1 -1
  112. package/fesm2022/keycloakify-angular-login-pages-info.mjs +3 -3
  113. package/fesm2022/keycloakify-angular-login-pages-login-config-totp.mjs +3 -3
  114. package/fesm2022/keycloakify-angular-login-pages-login-idp-link-confirm-override.mjs +3 -3
  115. package/fesm2022/keycloakify-angular-login-pages-login-idp-link-confirm.mjs +3 -3
  116. package/fesm2022/keycloakify-angular-login-pages-login-idp-link-email.mjs +3 -3
  117. package/fesm2022/keycloakify-angular-login-pages-login-oauth-grant.mjs +3 -3
  118. package/fesm2022/keycloakify-angular-login-pages-login-oauth2-device-verify-user-code.mjs +3 -3
  119. package/fesm2022/keycloakify-angular-login-pages-login-otp.mjs +3 -3
  120. package/fesm2022/keycloakify-angular-login-pages-login-page-expired.mjs +3 -3
  121. package/fesm2022/keycloakify-angular-login-pages-login-passkeys-conditional-authenticate.mjs +3 -3
  122. package/fesm2022/keycloakify-angular-login-pages-login-password.mjs +3 -3
  123. package/fesm2022/keycloakify-angular-login-pages-login-recovery-authn-code-config.mjs +124 -5
  124. package/fesm2022/keycloakify-angular-login-pages-login-recovery-authn-code-config.mjs.map +1 -1
  125. package/fesm2022/keycloakify-angular-login-pages-login-recovery-authn-code-input.mjs +3 -3
  126. package/fesm2022/keycloakify-angular-login-pages-login-reset-otp.mjs +3 -3
  127. package/fesm2022/keycloakify-angular-login-pages-login-reset-password.mjs +3 -3
  128. package/fesm2022/keycloakify-angular-login-pages-login-update-password.mjs +3 -3
  129. package/fesm2022/keycloakify-angular-login-pages-login-update-profile.mjs +12 -14
  130. package/fesm2022/keycloakify-angular-login-pages-login-update-profile.mjs.map +1 -1
  131. package/fesm2022/keycloakify-angular-login-pages-login-username.mjs +3 -3
  132. package/fesm2022/keycloakify-angular-login-pages-login-verify-email.mjs +3 -3
  133. package/fesm2022/keycloakify-angular-login-pages-login-x509-info.mjs +3 -3
  134. package/fesm2022/keycloakify-angular-login-pages-login.mjs +3 -3
  135. package/fesm2022/keycloakify-angular-login-pages-logout-confirm.mjs +3 -3
  136. package/fesm2022/keycloakify-angular-login-pages-register.mjs +11 -13
  137. package/fesm2022/keycloakify-angular-login-pages-register.mjs.map +1 -1
  138. package/fesm2022/keycloakify-angular-login-pages-saml-post-form.mjs +3 -3
  139. package/fesm2022/keycloakify-angular-login-pages-select-authenticator.mjs +3 -3
  140. package/fesm2022/keycloakify-angular-login-pages-terms.mjs +3 -3
  141. package/fesm2022/keycloakify-angular-login-pages-update-email.mjs +12 -14
  142. package/fesm2022/keycloakify-angular-login-pages-update-email.mjs.map +1 -1
  143. package/fesm2022/keycloakify-angular-login-pages-webauthn-authenticate.mjs +3 -3
  144. package/fesm2022/keycloakify-angular-login-pages-webauthn-error.mjs +3 -3
  145. package/fesm2022/keycloakify-angular-login-pages-webauthn-register.mjs +3 -3
  146. package/fesm2022/keycloakify-angular-login-services-i18n.mjs +3 -3
  147. package/fesm2022/keycloakify-angular-login-services-login-resource-injector.mjs +3 -3
  148. package/fesm2022/keycloakify-angular-login-services-user-profile-form.mjs +55 -1003
  149. package/fesm2022/keycloakify-angular-login-services-user-profile-form.mjs.map +1 -1
  150. package/login/components/add-remove-buttons-multi-valued-attribute/add-remove-buttons-multi-valued-attribute.component.d.ts +0 -1
  151. package/login/components/user-profile-form-fields/user-profile-form-fields.component.d.ts +3 -13
  152. package/login/pages/idp-review-user-profile/idp-review-user-profile.component.d.ts +1 -2
  153. package/login/pages/login-recovery-authn-code-config/login-recovery-authn-code-config.component.d.ts +3 -0
  154. package/login/pages/login-update-profile/login-update-profile.component.d.ts +1 -2
  155. package/login/pages/register/register.component.d.ts +1 -2
  156. package/login/pages/update-email/update-email.component.d.ts +1 -2
  157. package/login/services/user-profile-form/user-profile-form.service.d.ts +20 -41
  158. package/package.json +8 -14
  159. package/src/login/components/add-remove-buttons-multi-valued-attribute/add-remove-buttons-multi-valued-attribute.component.ts +3 -69
  160. package/src/login/components/user-profile-form-fields/user-profile-form-fields.component.html +71 -68
  161. package/src/login/components/user-profile-form-fields/user-profile-form-fields.component.ts +6 -21
  162. package/src/login/pages/idp-review-user-profile/idp-review-user-profile.component.ts +6 -13
  163. package/src/login/pages/login-recovery-authn-code-config/login-recovery-authn-code-config.component.ts +123 -0
  164. package/src/login/pages/login-update-profile/login-update-profile.component.ts +6 -12
  165. package/src/login/pages/register/register.component.ts +5 -10
  166. package/src/login/pages/update-email/update-email.component.ts +6 -12
  167. package/src/login/services/user-profile-form/user-profile-form.service.ts +103 -1433
  168. package/esm2022/login/services/submit/keycloakify-angular-login-services-submit.mjs +0 -5
  169. package/esm2022/login/services/submit/public-api.mjs +0 -2
  170. package/esm2022/login/services/submit/submit.service.mjs +0 -20
  171. package/fesm2022/keycloakify-angular-login-services-submit.mjs +0 -27
  172. package/fesm2022/keycloakify-angular-login-services-submit.mjs.map +0 -1
  173. package/login/services/submit/index.d.ts +0 -5
  174. package/login/services/submit/public-api.d.ts +0 -1
  175. package/login/services/submit/submit.service.d.ts +0 -9
  176. package/src/login/services/submit/index.ts +0 -1
  177. package/src/login/services/submit/submit.service.ts +0 -12
@@ -1,1019 +1,71 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, signal, computed, Injectable } from '@angular/core';
2
+ import { inject, Injectable } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
4
  import { DomSanitizer } from '@angular/platform-browser';
4
- import { LoginResourceInjectorService } from '@keycloakify/angular/login/services/login-resource-injector';
5
5
  import { LOGIN_I18N } from '@keycloakify/angular/login/tokens/i18n';
6
6
  import { KC_LOGIN_CONTEXT } from '@keycloakify/angular/login/tokens/kc-context';
7
7
  import { DO_MAKE_USER_CONFIRM_PASSWORD } from '@keycloakify/angular/login/tokens/make-user-confirm-password';
8
- import { emailRegexp } from 'keycloakify/tools/emailRegExp';
9
- import { formatNumber } from 'keycloakify/tools/formatNumber';
10
- import { structuredCloneButFunctions } from 'keycloakify/tools/structuredCloneButFunctions';
11
- import { id, assert } from 'tsafe';
8
+ import * as reactlessApi from 'keycloakify/login/lib/getUserProfileApi';
9
+ export { getButtonToDisplayForMultivaluedAttributeField } from 'keycloakify/login/lib/getUserProfileApi';
10
+ import { BehaviorSubject, map } from 'rxjs';
11
+ import { assert } from 'tsafe/assert';
12
12
 
13
- /* eslint-disable @typescript-eslint/no-explicit-any */
14
- /* eslint-disable @typescript-eslint/ban-ts-comment */
13
+ {
14
+ assert();
15
+ }
16
+ {
17
+ assert();
18
+ }
19
+ {
20
+ assert();
21
+ }
22
+ {
23
+ assert();
24
+ }
25
+ {
26
+ assert();
27
+ }
15
28
  class UserProfileFormService {
29
+ #kcContext = inject(KC_LOGIN_CONTEXT);
30
+ #i18n = inject(LOGIN_I18N);
31
+ #doMakeUserConfirmPassword = inject(DO_MAKE_USER_CONFIRM_PASSWORD);
32
+ #domSanitizer = inject(DomSanitizer);
33
+ #internal_formState$;
34
+ #unsubscribe;
16
35
  constructor() {
17
- this.kcContext = inject(KC_LOGIN_CONTEXT);
18
- this.i18n = inject(LOGIN_I18N);
19
- this.doMakeUserConfirmPassword = inject(DO_MAKE_USER_CONFIRM_PASSWORD);
20
- this.loginResourceInjectorService = inject(LoginResourceInjectorService);
21
- this.sanitizer = inject(DomSanitizer);
22
- this.initialState = (() => {
23
- const attributes = (() => {
24
- mock_user_profile_attributes_for_older_keycloak_versions: {
25
- if ('profile' in this.kcContext &&
26
- 'attributesByName' in this.kcContext.profile &&
27
- Object.keys(this.kcContext.profile.attributesByName).length !== 0) {
28
- break mock_user_profile_attributes_for_older_keycloak_versions;
29
- }
30
- if ('register' in this.kcContext &&
31
- this.kcContext.register instanceof Object &&
32
- 'formData' in this.kcContext.register) {
33
- //NOTE: Handle legacy register.ftl page
34
- return ['firstName', 'lastName', 'email', 'username']
35
- .filter(name => name !== 'username'
36
- ? true
37
- : !this.kcContext.realm.registrationEmailAsUsername)
38
- .map(name => id({
39
- name: name,
40
- displayName: id(`\${${name}}`),
41
- required: true,
42
- value: this.kcContext.register.formData[name] ?? '',
43
- html5DataAnnotations: {},
44
- readOnly: false,
45
- validators: {},
46
- annotations: {},
47
- autocomplete: (() => {
48
- switch (name) {
49
- case 'email':
50
- return 'email';
51
- case 'username':
52
- return 'username';
53
- default:
54
- return undefined;
55
- }
56
- })()
57
- }));
58
- }
59
- if ('user' in this.kcContext && this.kcContext.user instanceof Object) {
60
- //NOTE: Handle legacy login-update-profile.ftl
61
- return ['username', 'email', 'firstName', 'lastName']
62
- .filter(name => name !== 'username'
63
- ? true
64
- : this.kcContext.user.editUsernameAllowed)
65
- .map(name => id({
66
- name: name,
67
- displayName: id(`\${${name}}`),
68
- required: true,
69
- value: this.kcContext.user[name] ?? '',
70
- html5DataAnnotations: {},
71
- readOnly: false,
72
- validators: {},
73
- annotations: {},
74
- autocomplete: (() => {
75
- switch (name) {
76
- case 'email':
77
- return 'email';
78
- case 'username':
79
- return 'username';
80
- default:
81
- return undefined;
82
- }
83
- })()
84
- }));
85
- }
86
- if ('email' in this.kcContext && this.kcContext.email instanceof Object) {
87
- //NOTE: Handle legacy update-email.ftl
88
- return [
89
- id({
90
- name: 'email',
91
- displayName: id(`\${email}`),
92
- required: true,
93
- value: this.kcContext.email.value ?? '',
94
- html5DataAnnotations: {},
95
- readOnly: false,
96
- validators: {},
97
- annotations: {},
98
- autocomplete: 'email'
99
- })
100
- ];
101
- }
102
- assert(false, 'Unable to mock user profile from the current kcContext');
103
- }
104
- return Object.values(this.kcContext.profile.attributesByName).map(structuredCloneButFunctions);
105
- })();
106
- // Retro-compatibility and consistency patches
107
- attributes.forEach(attribute => {
108
- patch_legacy_group: {
109
- if (typeof attribute.group !== 'string') {
110
- break patch_legacy_group;
111
- }
112
- const { group, groupDisplayHeader, groupDisplayDescription, groupAnnotations } = attribute;
113
- delete attribute.group;
114
- // @ts-expect-error
115
- delete attribute.groupDisplayHeader;
116
- // @ts-expect-error
117
- delete attribute.groupDisplayDescription;
118
- // @ts-expect-error
119
- delete attribute.groupAnnotations;
120
- if (group === '') {
121
- break patch_legacy_group;
122
- }
123
- attribute.group = {
124
- name: group,
125
- displayHeader: groupDisplayHeader,
126
- displayDescription: groupDisplayDescription,
127
- annotations: groupAnnotations,
128
- html5DataAnnotations: {}
129
- };
130
- }
131
- // Attributes with options rendered by default as select inputs
132
- if (attribute.validators.options !== undefined &&
133
- attribute.annotations.inputType === undefined) {
134
- attribute.annotations.inputType = 'select';
135
- }
136
- // Consistency patch on values/value property
137
- {
138
- if (this.getIsMultivaluedSingleField({ attribute })) {
139
- attribute.multivalued = true;
140
- }
141
- if (attribute.multivalued) {
142
- attribute.values ??=
143
- attribute.value !== undefined ? [attribute.value] : [];
144
- delete attribute.value;
145
- }
146
- else {
147
- attribute.value ??= attribute.values?.[0];
148
- delete attribute.values;
149
- }
150
- }
151
- });
152
- add_password_and_password_confirm: {
153
- if (!this.kcContext.passwordRequired) {
154
- break add_password_and_password_confirm;
155
- }
156
- attributes.forEach((attribute, i) => {
157
- if (attribute.name !==
158
- (this.kcContext.realm.registrationEmailAsUsername
159
- ? 'email'
160
- : 'username')) {
161
- // NOTE: We want to add password and password-confirm after the field that identifies the user.
162
- // It's either email or username.
163
- return;
164
- }
165
- attributes.splice(i + 1, 0, {
166
- name: 'password',
167
- displayName: id('${password}'),
168
- required: true,
169
- readOnly: false,
170
- validators: {},
171
- annotations: {},
172
- autocomplete: 'new-password',
173
- html5DataAnnotations: {}
174
- }, {
175
- name: 'password-confirm',
176
- displayName: id('${passwordConfirm}'),
177
- required: true,
178
- readOnly: false,
179
- validators: {},
180
- annotations: {},
181
- html5DataAnnotations: {},
182
- autocomplete: 'new-password'
183
- });
184
- });
185
- }
186
- const initialFormFieldState = [];
187
- for (const attribute of attributes) {
188
- handle_multi_valued_attribute: {
189
- if (!attribute.multivalued) {
190
- break handle_multi_valued_attribute;
191
- }
192
- const values = attribute.values?.length ? attribute.values : [''];
193
- apply_validator_min_range: {
194
- if (this.getIsMultivaluedSingleField({ attribute })) {
195
- break apply_validator_min_range;
196
- }
197
- const validator = attribute.validators.multivalued;
198
- if (validator === undefined) {
199
- break apply_validator_min_range;
200
- }
201
- const { min: minStr } = validator;
202
- if (!minStr) {
203
- break apply_validator_min_range;
204
- }
205
- const min = parseInt(`${minStr}`);
206
- for (let index = values.length; index < min; index++) {
207
- values.push('');
208
- }
209
- }
210
- initialFormFieldState.push({
211
- attribute,
212
- valueOrValues: values
213
- });
214
- continue;
215
- }
216
- initialFormFieldState.push({
217
- attribute,
218
- valueOrValues: attribute.value ?? ''
219
- });
220
- }
221
- const initialState = {
222
- formFieldStates: initialFormFieldState.map(({ attribute, valueOrValues }) => ({
223
- attribute,
224
- errors: this.getErrors({
225
- attributeName: attribute.name,
226
- formFieldStates: initialFormFieldState
227
- }),
228
- hasLostFocusAtLeastOnce: valueOrValues instanceof Array &&
229
- !this.getIsMultivaluedSingleField({ attribute })
230
- ? valueOrValues.map(() => false)
231
- : false,
232
- valueOrValues: valueOrValues
233
- }))
234
- };
235
- return initialState;
236
- })();
237
- this.state = signal(this.initialState);
238
- this.formState = computed(() => {
239
- const state = this.state();
240
- return {
241
- formFieldStates: state.formFieldStates.map(({ errors, hasLostFocusAtLeastOnce: hasLostFocusAtLeastOnceOrArr, attribute, ...valueOrValuesWrap }) => ({
242
- displayableErrors: errors.filter(error => {
243
- const hasLostFocusAtLeastOnce = typeof hasLostFocusAtLeastOnceOrArr === 'boolean'
244
- ? hasLostFocusAtLeastOnceOrArr
245
- : error.fieldIndex !== undefined
246
- ? hasLostFocusAtLeastOnceOrArr[error.fieldIndex]
247
- : hasLostFocusAtLeastOnceOrArr[hasLostFocusAtLeastOnceOrArr.length - 1];
248
- let value = false;
249
- switch (error.source.type) {
250
- case 'server':
251
- value = true;
252
- break;
253
- case 'other':
254
- switch (error.source.rule) {
255
- case 'requiredField':
256
- value = hasLostFocusAtLeastOnce;
257
- break;
258
- case 'passwordConfirmMatchesPassword':
259
- value = hasLostFocusAtLeastOnce;
260
- break;
261
- }
262
- // assert<Equals<typeof error.source.rule, never>>(false);
263
- break;
264
- case 'passwordPolicy':
265
- switch (error.source.name) {
266
- case 'length':
267
- value = hasLostFocusAtLeastOnce;
268
- break;
269
- case 'digits':
270
- value = hasLostFocusAtLeastOnce;
271
- break;
272
- case 'lowerCase':
273
- value = hasLostFocusAtLeastOnce;
274
- break;
275
- case 'upperCase':
276
- value = hasLostFocusAtLeastOnce;
277
- break;
278
- case 'specialChars':
279
- value = hasLostFocusAtLeastOnce;
280
- break;
281
- case 'notUsername':
282
- value = true;
283
- break;
284
- case 'notEmail':
285
- value = true;
286
- break;
287
- }
288
- // assert<Equals<typeof error.source, never>>(false);
289
- break;
290
- case 'validator':
291
- switch (error.source.name) {
292
- case 'length':
293
- value = hasLostFocusAtLeastOnce;
294
- break;
295
- case 'pattern':
296
- value = hasLostFocusAtLeastOnce;
297
- break;
298
- case 'email':
299
- value = hasLostFocusAtLeastOnce;
300
- break;
301
- case 'integer':
302
- value = hasLostFocusAtLeastOnce;
303
- break;
304
- case 'multivalued':
305
- value = hasLostFocusAtLeastOnce;
306
- break;
307
- case 'options':
308
- value = hasLostFocusAtLeastOnce;
309
- break;
310
- }
311
- // assert<Equals<typeof error.source, never>>(false);
312
- break;
313
- }
314
- return value;
315
- }),
316
- attribute,
317
- ...valueOrValuesWrap
318
- })),
319
- isFormSubmittable: state.formFieldStates.every(({ errors }) => errors.length === 0)
320
- };
36
+ const api = reactlessApi.getUserProfileApi({
37
+ kcContext: this.#kcContext,
38
+ doMakeUserConfirmPassword: this.#doMakeUserConfirmPassword
321
39
  });
322
- this.loginResourceInjectorService.insertAdditionalScripts(Object.keys(this.kcContext.profile?.html5DataAnnotations ?? {})
323
- .filter(key => key !== 'kcMultivalued' && key !== 'kcNumberFormat') // NOTE: Keycloakify handles it.
324
- .map(key => ({
325
- type: 'module',
326
- src: `${this.kcContext.url.resourcesPath}/js/${key}.js`,
327
- id: `${this.kcContext.url.resourcesPath}/js/${key}.js`
40
+ this.#internal_formState$ = new BehaviorSubject(api.getFormState());
41
+ this.#unsubscribe = api.subscribeToFormState(() => {
42
+ this.#internal_formState$.next(api.getFormState());
43
+ }).unsubscribe;
44
+ this.formState$ = this.#internal_formState$.asObservable().pipe(takeUntilDestroyed(), map(formState_reactless => ({
45
+ isFormSubmittable: formState_reactless.isFormSubmittable,
46
+ formFieldStates: formState_reactless.formFieldStates.map(formFieldState_reactless => ({
47
+ attribute: formFieldState_reactless.attribute,
48
+ valueOrValues: formFieldState_reactless.valueOrValues,
49
+ displayableErrors: formFieldState_reactless.displayableErrors.map((formFieldError_reactless, i) => ({
50
+ errorMessage: this.#domSanitizer.bypassSecurityTrustHtml(this.#i18n.advancedMsgStr(...formFieldError_reactless.advancedMsgArgs)),
51
+ errorMessageStr: this.#i18n.advancedMsgStr(...formFieldError_reactless.advancedMsgArgs),
52
+ source: formFieldError_reactless.source,
53
+ fieldIndex: formFieldError_reactless.fieldIndex
54
+ }))
55
+ }))
328
56
  })));
57
+ this.dispatchFormAction = api.dispatchFormAction;
329
58
  }
330
- dispatchFormAction(formAction) {
331
- if (!formAction)
332
- return;
333
- const state = this.state();
334
- const formFieldState = state.formFieldStates.find(({ attribute }) => attribute.name === formAction.name);
335
- assert(formFieldState !== undefined);
336
- switch (formAction.action) {
337
- case 'update':
338
- formFieldState.valueOrValues = formAction.valueOrValues;
339
- apply_formatters: {
340
- const { attribute } = formFieldState;
341
- const { kcNumberFormat } = attribute.html5DataAnnotations ?? {};
342
- if (!kcNumberFormat) {
343
- break apply_formatters;
344
- }
345
- if (formFieldState.valueOrValues instanceof Array) {
346
- formFieldState.valueOrValues = formFieldState.valueOrValues.map(value => formatNumber(value, kcNumberFormat));
347
- }
348
- else {
349
- formFieldState.valueOrValues = formatNumber(formFieldState.valueOrValues, kcNumberFormat);
350
- }
351
- }
352
- formFieldState.errors = this.getErrors({
353
- attributeName: formAction.name,
354
- formFieldStates: state.formFieldStates
355
- });
356
- simulate_focus_lost: {
357
- const { displayErrorsImmediately = false } = formAction;
358
- if (!displayErrorsImmediately) {
359
- break simulate_focus_lost;
360
- }
361
- for (const fieldIndex of formAction.valueOrValues instanceof Array
362
- ? formAction.valueOrValues.map((...[, index]) => index)
363
- : [undefined]) {
364
- this.dispatchFormAction({
365
- action: 'focus lost',
366
- name: formAction.name,
367
- fieldIndex
368
- });
369
- }
370
- }
371
- update_password_confirm: {
372
- if (this.doMakeUserConfirmPassword) {
373
- break update_password_confirm;
374
- }
375
- if (formAction.name !== 'password') {
376
- break update_password_confirm;
377
- }
378
- this.dispatchFormAction({
379
- action: 'update',
380
- name: 'password-confirm',
381
- valueOrValues: formAction.valueOrValues,
382
- displayErrorsImmediately: formAction.displayErrorsImmediately
383
- });
384
- }
385
- trigger_password_confirm_validation_on_password_change: {
386
- if (!this.doMakeUserConfirmPassword) {
387
- break trigger_password_confirm_validation_on_password_change;
388
- }
389
- if (formAction.name !== 'password') {
390
- break trigger_password_confirm_validation_on_password_change;
391
- }
392
- this.dispatchFormAction({
393
- action: 'update',
394
- name: 'password-confirm',
395
- valueOrValues: (() => {
396
- const formFieldState = state.formFieldStates.find(({ attribute }) => attribute.name === 'password-confirm');
397
- assert(formFieldState !== undefined);
398
- return formFieldState.valueOrValues;
399
- })(),
400
- displayErrorsImmediately: formAction.displayErrorsImmediately
401
- });
402
- }
403
- break;
404
- case 'focus lost':
405
- if (formFieldState.hasLostFocusAtLeastOnce instanceof Array) {
406
- const { fieldIndex } = formAction;
407
- assert(fieldIndex !== undefined);
408
- formFieldState.hasLostFocusAtLeastOnce[fieldIndex] = true;
409
- break;
410
- }
411
- formFieldState.hasLostFocusAtLeastOnce = true;
412
- break;
413
- }
414
- this.state.update(state => ({
415
- ...state,
416
- formFieldStates: state.formFieldStates.map(f => {
417
- if (f.attribute === formFieldState.attribute)
418
- return formFieldState;
419
- return f;
420
- })
421
- }));
422
- }
423
- getIsMultivaluedSingleField(params) {
424
- const { attribute } = params;
425
- return attribute.annotations.inputType?.startsWith('multiselect') ?? false;
426
- }
427
- getErrors(params) {
428
- const { messagesPerField, passwordPolicies } = this.kcContext;
429
- const { msgStr, advancedMsgStr } = this.i18n;
430
- const { attributeName, formFieldStates } = params;
431
- const formFieldState = formFieldStates.find(({ attribute }) => attribute.name === attributeName);
432
- assert(formFieldState !== undefined);
433
- const { attribute } = formFieldState;
434
- const valueOrValues = (() => {
435
- let { valueOrValues } = formFieldState;
436
- unFormat_number: {
437
- const { kcNumberUnFormat } = attribute.html5DataAnnotations ?? {};
438
- if (!kcNumberUnFormat) {
439
- break unFormat_number;
440
- }
441
- if (valueOrValues instanceof Array) {
442
- valueOrValues = valueOrValues.map(value => formatNumber(value, kcNumberUnFormat));
443
- }
444
- else {
445
- valueOrValues = formatNumber(valueOrValues, kcNumberUnFormat);
446
- }
447
- }
448
- return valueOrValues;
449
- })();
450
- assert(attribute !== undefined);
451
- server_side_error: {
452
- if (attribute.multivalued) {
453
- const defaultValues = attribute.values?.length ? attribute.values : [''];
454
- assert(valueOrValues instanceof Array);
455
- const values = valueOrValues;
456
- if (JSON.stringify(defaultValues) !==
457
- JSON.stringify(values.slice(0, defaultValues.length))) {
458
- break server_side_error;
459
- }
460
- }
461
- else {
462
- const defaultValue = attribute.value ?? '';
463
- assert(typeof valueOrValues === 'string');
464
- const value = valueOrValues;
465
- if (defaultValue !== value) {
466
- break server_side_error;
467
- }
468
- }
469
- let doesErrorExist;
470
- try {
471
- doesErrorExist = messagesPerField.existsError(attributeName);
472
- }
473
- catch {
474
- break server_side_error;
475
- }
476
- if (!doesErrorExist) {
477
- break server_side_error;
478
- }
479
- const errorMessageStr = messagesPerField.get(attributeName);
480
- return [
481
- {
482
- errorMessageStr,
483
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span>${errorMessageStr}</span>`),
484
- fieldIndex: undefined,
485
- source: {
486
- type: 'server'
487
- }
488
- }
489
- ];
490
- }
491
- handle_multi_valued_multi_fields: {
492
- if (!attribute.multivalued) {
493
- break handle_multi_valued_multi_fields;
494
- }
495
- if (this.getIsMultivaluedSingleField({ attribute })) {
496
- break handle_multi_valued_multi_fields;
497
- }
498
- assert(valueOrValues instanceof Array);
499
- const values = valueOrValues;
500
- const errors = values
501
- .map((...[, index]) => {
502
- const specificValueErrors = this.getErrors({
503
- attributeName,
504
- formFieldStates: formFieldStates.map(formFieldState => {
505
- if (formFieldState.attribute.name === attributeName) {
506
- assert(formFieldState.valueOrValues instanceof Array);
507
- return {
508
- attribute: {
509
- ...attribute,
510
- annotations: {
511
- ...attribute.annotations,
512
- inputType: undefined
513
- },
514
- multivalued: false
515
- },
516
- valueOrValues: formFieldState.valueOrValues[index]
517
- };
518
- }
519
- return formFieldState;
520
- })
521
- });
522
- return specificValueErrors
523
- .filter(error => {
524
- if (error.source.type === 'other' &&
525
- error.source.rule === 'requiredField') {
526
- return false;
527
- }
528
- return true;
529
- })
530
- .map((error) => ({
531
- ...error,
532
- fieldIndex: index
533
- }));
534
- })
535
- .reduce((acc, errors) => [...acc, ...errors], []);
536
- required_field: {
537
- if (!attribute.required) {
538
- break required_field;
539
- }
540
- if (values.every(value => value !== '')) {
541
- break required_field;
542
- }
543
- const msgArgs = ['error-user-attribute-required'];
544
- errors.push({
545
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
546
- errorMessageStr: msgStr(...msgArgs),
547
- fieldIndex: undefined,
548
- source: {
549
- type: 'other',
550
- rule: 'requiredField'
551
- }
552
- });
553
- }
554
- return errors;
555
- }
556
- handle_multi_valued_single_field: {
557
- if (!attribute.multivalued) {
558
- break handle_multi_valued_single_field;
559
- }
560
- if (!this.getIsMultivaluedSingleField({ attribute })) {
561
- break handle_multi_valued_single_field;
562
- }
563
- const validatorName = 'multivalued';
564
- const validator = attribute.validators[validatorName];
565
- if (validator === undefined) {
566
- return [];
567
- }
568
- const { min: minStr } = validator;
569
- const min = minStr ? parseInt(`${minStr}`) : attribute.required ? 1 : 0;
570
- assert(!isNaN(min));
571
- const { max: maxStr } = validator;
572
- const max = !maxStr ? Infinity : parseInt(`${maxStr}`);
573
- assert(!isNaN(max));
574
- assert(valueOrValues instanceof Array);
575
- const values = valueOrValues;
576
- if (min <= values.length && values.length <= max) {
577
- return [];
578
- }
579
- const msgArgs = [
580
- 'error-invalid-multivalued-size',
581
- `${min}`,
582
- `${max}`
583
- ];
584
- return [
585
- {
586
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="0">${msgStr(...msgArgs)}</span>`),
587
- errorMessageStr: msgStr(...msgArgs),
588
- fieldIndex: undefined,
589
- source: {
590
- type: 'validator',
591
- name: validatorName
592
- }
593
- }
594
- ];
595
- }
596
- assert(typeof valueOrValues === 'string');
597
- const value = valueOrValues;
598
- const errors = [];
599
- check_password_policies: {
600
- if (attributeName !== 'password') {
601
- break check_password_policies;
602
- }
603
- if (passwordPolicies === undefined) {
604
- break check_password_policies;
605
- }
606
- check_password_policy_x: {
607
- const policyName = 'length';
608
- const policy = passwordPolicies[policyName];
609
- if (!policy) {
610
- break check_password_policy_x;
611
- }
612
- const minLength = policy;
613
- if (value.length >= minLength) {
614
- break check_password_policy_x;
615
- }
616
- const msgArgs = [
617
- 'invalidPasswordMinLengthMessage',
618
- `${minLength}`
619
- ];
620
- errors.push({
621
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
622
- errorMessageStr: msgStr(...msgArgs),
623
- fieldIndex: undefined,
624
- source: {
625
- type: 'passwordPolicy',
626
- name: policyName
627
- }
628
- });
629
- }
630
- check_password_policy_x: {
631
- const policyName = 'digits';
632
- const policy = passwordPolicies[policyName];
633
- if (!policy) {
634
- break check_password_policy_x;
635
- }
636
- const minNumberOfDigits = policy;
637
- if (value.split('').filter(char => !isNaN(parseInt(char))).length >=
638
- minNumberOfDigits) {
639
- break check_password_policy_x;
640
- }
641
- const msgArgs = [
642
- 'invalidPasswordMinDigitsMessage',
643
- `${minNumberOfDigits}`
644
- ];
645
- errors.push({
646
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
647
- errorMessageStr: msgStr(...msgArgs),
648
- fieldIndex: undefined,
649
- source: {
650
- type: 'passwordPolicy',
651
- name: policyName
652
- }
653
- });
654
- }
655
- check_password_policy_x: {
656
- const policyName = 'lowerCase';
657
- const policy = passwordPolicies[policyName];
658
- if (!policy) {
659
- break check_password_policy_x;
660
- }
661
- const minNumberOfLowerCaseChar = policy;
662
- if (value
663
- .split('')
664
- .filter(char => char === char.toLowerCase() && char !== char.toUpperCase()).length >= minNumberOfLowerCaseChar) {
665
- break check_password_policy_x;
666
- }
667
- const msgArgs = [
668
- 'invalidPasswordMinLowerCaseCharsMessage',
669
- `${minNumberOfLowerCaseChar}`
670
- ];
671
- errors.push({
672
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
673
- errorMessageStr: msgStr(...msgArgs),
674
- fieldIndex: undefined,
675
- source: {
676
- type: 'passwordPolicy',
677
- name: policyName
678
- }
679
- });
680
- }
681
- check_password_policy_x: {
682
- const policyName = 'upperCase';
683
- const policy = passwordPolicies[policyName];
684
- if (!policy) {
685
- break check_password_policy_x;
686
- }
687
- const minNumberOfUpperCaseChar = policy;
688
- if (value
689
- .split('')
690
- .filter(char => char === char.toUpperCase() && char !== char.toLowerCase()).length >= minNumberOfUpperCaseChar) {
691
- break check_password_policy_x;
692
- }
693
- const msgArgs = [
694
- 'invalidPasswordMinUpperCaseCharsMessage',
695
- `${minNumberOfUpperCaseChar}`
696
- ];
697
- errors.push({
698
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
699
- errorMessageStr: msgStr(...msgArgs),
700
- fieldIndex: undefined,
701
- source: {
702
- type: 'passwordPolicy',
703
- name: policyName
704
- }
705
- });
706
- }
707
- check_password_policy_x: {
708
- const policyName = 'specialChars';
709
- const policy = passwordPolicies[policyName];
710
- if (!policy) {
711
- break check_password_policy_x;
712
- }
713
- const minNumberOfSpecialChar = policy;
714
- if (value.split('').filter(char => !char.match(/[a-zA-Z0-9]/)).length >=
715
- minNumberOfSpecialChar) {
716
- break check_password_policy_x;
717
- }
718
- const msgArgs = [
719
- 'invalidPasswordMinSpecialCharsMessage',
720
- `${minNumberOfSpecialChar}`
721
- ];
722
- errors.push({
723
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
724
- errorMessageStr: msgStr(...msgArgs),
725
- fieldIndex: undefined,
726
- source: {
727
- type: 'passwordPolicy',
728
- name: policyName
729
- }
730
- });
731
- }
732
- check_password_policy_x: {
733
- const policyName = 'notUsername';
734
- const notUsername = passwordPolicies[policyName];
735
- if (!notUsername) {
736
- break check_password_policy_x;
737
- }
738
- const usernameFormFieldState = formFieldStates.find(formFieldState => formFieldState.attribute.name === 'username');
739
- if (!usernameFormFieldState) {
740
- break check_password_policy_x;
741
- }
742
- const usernameValue = (() => {
743
- let { valueOrValues } = usernameFormFieldState;
744
- assert(typeof valueOrValues === 'string');
745
- unFormat_number: {
746
- const { kcNumberUnFormat } = attribute.html5DataAnnotations ?? {};
747
- if (!kcNumberUnFormat) {
748
- break unFormat_number;
749
- }
750
- valueOrValues = formatNumber(valueOrValues, kcNumberUnFormat);
751
- }
752
- return valueOrValues;
753
- })();
754
- if (usernameValue === '') {
755
- break check_password_policy_x;
756
- }
757
- if (value !== usernameValue) {
758
- break check_password_policy_x;
759
- }
760
- const msgArgs = ['invalidPasswordNotUsernameMessage'];
761
- errors.push({
762
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
763
- errorMessageStr: msgStr(...msgArgs),
764
- fieldIndex: undefined,
765
- source: {
766
- type: 'passwordPolicy',
767
- name: policyName
768
- }
769
- });
770
- }
771
- check_password_policy_x: {
772
- const policyName = 'notEmail';
773
- const notEmail = passwordPolicies[policyName];
774
- if (!notEmail) {
775
- break check_password_policy_x;
776
- }
777
- const emailFormFieldState = formFieldStates.find(formFieldState => formFieldState.attribute.name === 'email');
778
- if (!emailFormFieldState) {
779
- break check_password_policy_x;
780
- }
781
- assert(typeof emailFormFieldState.valueOrValues === 'string');
782
- {
783
- const emailValue = emailFormFieldState.valueOrValues;
784
- if (emailValue === '') {
785
- break check_password_policy_x;
786
- }
787
- if (value !== emailValue) {
788
- break check_password_policy_x;
789
- }
790
- }
791
- const msgArgs = ['invalidPasswordNotEmailMessage'];
792
- errors.push({
793
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
794
- errorMessageStr: msgStr(...msgArgs),
795
- fieldIndex: undefined,
796
- source: {
797
- type: 'passwordPolicy',
798
- name: policyName
799
- }
800
- });
801
- }
802
- }
803
- password_confirm_matches_password: {
804
- if (attributeName !== 'password-confirm') {
805
- break password_confirm_matches_password;
806
- }
807
- const passwordFormFieldState = formFieldStates.find(formFieldState => formFieldState.attribute.name === 'password');
808
- assert(passwordFormFieldState !== undefined);
809
- assert(typeof passwordFormFieldState.valueOrValues === 'string');
810
- {
811
- const passwordValue = passwordFormFieldState.valueOrValues;
812
- if (value === passwordValue) {
813
- break password_confirm_matches_password;
814
- }
815
- }
816
- const msgArgs = ['invalidPasswordConfirmMessage'];
817
- errors.push({
818
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
819
- errorMessageStr: msgStr(...msgArgs),
820
- fieldIndex: undefined,
821
- source: {
822
- type: 'other',
823
- rule: 'passwordConfirmMatchesPassword'
824
- }
825
- });
826
- }
827
- const { validators } = attribute;
828
- required_field: {
829
- if (!attribute.required) {
830
- break required_field;
831
- }
832
- if (value !== '') {
833
- break required_field;
834
- }
835
- const msgArgs = ['error-user-attribute-required'];
836
- errors.push({
837
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
838
- errorMessageStr: msgStr(...msgArgs),
839
- fieldIndex: undefined,
840
- source: {
841
- type: 'other',
842
- rule: 'requiredField'
843
- }
844
- });
845
- }
846
- validator_x: {
847
- const validatorName = 'length';
848
- const validator = validators[validatorName];
849
- if (!validator) {
850
- break validator_x;
851
- }
852
- const { 'ignore.empty.value': ignoreEmptyValue = false, max, min } = validator;
853
- if (ignoreEmptyValue && value === '') {
854
- break validator_x;
855
- }
856
- const source = {
857
- type: 'validator',
858
- name: validatorName
859
- };
860
- if (max && value.length > parseInt(`${max}`)) {
861
- const msgArgs = ['error-invalid-length-too-long', `${max}`];
862
- errors.push({
863
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
864
- errorMessageStr: msgStr(...msgArgs),
865
- fieldIndex: undefined,
866
- source
867
- });
868
- }
869
- if (min && value.length < parseInt(`${min}`)) {
870
- const msgArgs = ['error-invalid-length-too-short', `${min}`];
871
- errors.push({
872
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
873
- errorMessageStr: msgStr(...msgArgs),
874
- fieldIndex: undefined,
875
- source
876
- });
877
- }
878
- }
879
- validator_x: {
880
- const validatorName = 'pattern';
881
- const validator = validators[validatorName];
882
- if (validator === undefined) {
883
- break validator_x;
884
- }
885
- const { 'ignore.empty.value': ignoreEmptyValue = false, pattern, 'error-message': errorMessageKey } = validator;
886
- if (ignoreEmptyValue && value === '') {
887
- break validator_x;
888
- }
889
- if (new RegExp(pattern).test(value)) {
890
- break validator_x;
891
- }
892
- const msgArgs = [
893
- errorMessageKey ?? id('shouldMatchPattern'),
894
- pattern
895
- ];
896
- errors.push({
897
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${advancedMsgStr(...msgArgs)}</span>`),
898
- errorMessageStr: advancedMsgStr(...msgArgs),
899
- fieldIndex: undefined,
900
- source: {
901
- type: 'validator',
902
- name: validatorName
903
- }
904
- });
905
- }
906
- validator_x: {
907
- {
908
- const lastError = errors[errors.length - 1];
909
- if (lastError !== undefined &&
910
- lastError.source.type === 'validator' &&
911
- lastError.source.name === 'pattern') {
912
- break validator_x;
913
- }
914
- }
915
- const validatorName = 'email';
916
- const validator = validators[validatorName];
917
- if (validator === undefined) {
918
- break validator_x;
919
- }
920
- const { 'ignore.empty.value': ignoreEmptyValue = false } = validator;
921
- if (ignoreEmptyValue && value === '') {
922
- break validator_x;
923
- }
924
- if (emailRegexp.test(value)) {
925
- break validator_x;
926
- }
927
- const msgArgs = [id('invalidEmailMessage')];
928
- errors.push({
929
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
930
- errorMessageStr: msgStr(...msgArgs),
931
- fieldIndex: undefined,
932
- source: {
933
- type: 'validator',
934
- name: validatorName
935
- }
936
- });
937
- }
938
- validator_x: {
939
- const validatorName = 'integer';
940
- const validator = validators[validatorName];
941
- if (validator === undefined) {
942
- break validator_x;
943
- }
944
- const { 'ignore.empty.value': ignoreEmptyValue = false, max, min } = validator;
945
- if (ignoreEmptyValue && value === '') {
946
- break validator_x;
947
- }
948
- const intValue = parseInt(value);
949
- const source = {
950
- type: 'validator',
951
- name: validatorName
952
- };
953
- if (isNaN(intValue)) {
954
- const msgArgs = ['mustBeAnInteger'];
955
- errors.push({
956
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
957
- errorMessageStr: msgStr(...msgArgs),
958
- fieldIndex: undefined,
959
- source
960
- });
961
- break validator_x;
962
- }
963
- if (max && intValue > parseInt(`${max}`)) {
964
- const msgArgs = ['error-number-out-of-range-too-big', `${max}`];
965
- errors.push({
966
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
967
- errorMessageStr: msgStr(...msgArgs),
968
- fieldIndex: undefined,
969
- source
970
- });
971
- break validator_x;
972
- }
973
- if (min && intValue < parseInt(`${min}`)) {
974
- const msgArgs = [
975
- 'error-number-out-of-range-too-small',
976
- `${min}`
977
- ];
978
- errors.push({
979
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
980
- errorMessageStr: msgStr(...msgArgs),
981
- fieldIndex: undefined,
982
- source
983
- });
984
- break validator_x;
985
- }
986
- }
987
- validator_x: {
988
- const validatorName = 'options';
989
- const validator = validators[validatorName];
990
- if (validator === undefined) {
991
- break validator_x;
992
- }
993
- if (value === '') {
994
- break validator_x;
995
- }
996
- if (validator.options.indexOf(value) >= 0) {
997
- break validator_x;
998
- }
999
- const msgArgs = [id('notAValidOption')];
1000
- errors.push({
1001
- errorMessage: this.sanitizer.bypassSecurityTrustHtml(`<span data-key="${attributeName}-${errors.length}">${msgStr(...msgArgs)}</span>`),
1002
- errorMessageStr: msgStr(...msgArgs),
1003
- fieldIndex: undefined,
1004
- source: {
1005
- type: 'validator',
1006
- name: validatorName
1007
- }
1008
- });
1009
- }
1010
- //TODO: Implement missing validators. See Validators type definition.
1011
- return errors;
59
+ ngOnDestroy() {
60
+ this.#internal_formState$.complete();
61
+ this.#internal_formState$.unsubscribe();
62
+ if (this.#unsubscribe)
63
+ this.#unsubscribe();
1012
64
  }
1013
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: UserProfileFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
1014
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: UserProfileFormService, providedIn: 'root' }); }
65
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: UserProfileFormService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
66
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: UserProfileFormService, providedIn: 'root' }); }
1015
67
  }
1016
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: UserProfileFormService, decorators: [{
68
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.8", ngImport: i0, type: UserProfileFormService, decorators: [{
1017
69
  type: Injectable,
1018
70
  args: [{ providedIn: 'root' }]
1019
71
  }], ctorParameters: () => [] });