@acorex-platform/module-auth-client 0.0.15

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 (79) hide show
  1. package/fesm2022/acorex-platform-module-auth-client-acorex-platform-module-auth-client-B7tIKOw6.mjs +3174 -0
  2. package/fesm2022/acorex-platform-module-auth-client-acorex-platform-module-auth-client-B7tIKOw6.mjs.map +1 -0
  3. package/fesm2022/acorex-platform-module-auth-client-app-chooser.component-Cm2ZagaI.mjs +67 -0
  4. package/fesm2022/acorex-platform-module-auth-client-app-chooser.component-Cm2ZagaI.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-module-auth-client-blank.layout-BRGgntib.mjs +18 -0
  6. package/fesm2022/acorex-platform-module-auth-client-blank.layout-BRGgntib.mjs.map +1 -0
  7. package/fesm2022/acorex-platform-module-auth-client-change-password.command-ZyXAjUKw.mjs +168 -0
  8. package/fesm2022/acorex-platform-module-auth-client-change-password.command-ZyXAjUKw.mjs.map +1 -0
  9. package/fesm2022/acorex-platform-module-auth-client-change-photo.command-BC8lw--F.mjs +192 -0
  10. package/fesm2022/acorex-platform-module-auth-client-change-photo.command-BC8lw--F.mjs.map +1 -0
  11. package/fesm2022/acorex-platform-module-auth-client-contracts.mjs +80 -0
  12. package/fesm2022/acorex-platform-module-auth-client-contracts.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-module-auth-client-edit-account-info.command-B-mVlXxg.mjs +129 -0
  14. package/fesm2022/acorex-platform-module-auth-client-edit-account-info.command-B-mVlXxg.mjs.map +1 -0
  15. package/fesm2022/acorex-platform-module-auth-client-edit-signature.command-CcTJJwAX.mjs +32 -0
  16. package/fesm2022/acorex-platform-module-auth-client-edit-signature.command-CcTJJwAX.mjs.map +1 -0
  17. package/fesm2022/acorex-platform-module-auth-client-lock-screen.command-41QnG1TQ.mjs +30 -0
  18. package/fesm2022/acorex-platform-module-auth-client-lock-screen.command-41QnG1TQ.mjs.map +1 -0
  19. package/fesm2022/acorex-platform-module-auth-client-login.module-DYtNYzF6.mjs +57 -0
  20. package/fesm2022/acorex-platform-module-auth-client-login.module-DYtNYzF6.mjs.map +1 -0
  21. package/fesm2022/acorex-platform-module-auth-client-master.layout-DpdD9kgk.mjs +24 -0
  22. package/fesm2022/acorex-platform-module-auth-client-master.layout-DpdD9kgk.mjs.map +1 -0
  23. package/fesm2022/acorex-platform-module-auth-client-menu.provider-Bz-kRip4.mjs +19 -0
  24. package/fesm2022/acorex-platform-module-auth-client-menu.provider-Bz-kRip4.mjs.map +1 -0
  25. package/fesm2022/acorex-platform-module-auth-client-oauth-callback.component-BspBH4Ul.mjs +105 -0
  26. package/fesm2022/acorex-platform-module-auth-client-oauth-callback.component-BspBH4Ul.mjs.map +1 -0
  27. package/fesm2022/acorex-platform-module-auth-client-open-sessions.command-CXSGuqYp.mjs +196 -0
  28. package/fesm2022/acorex-platform-module-auth-client-open-sessions.command-CXSGuqYp.mjs.map +1 -0
  29. package/fesm2022/acorex-platform-module-auth-client-password.component-BuqUhET7.mjs +59 -0
  30. package/fesm2022/acorex-platform-module-auth-client-password.component-BuqUhET7.mjs.map +1 -0
  31. package/fesm2022/acorex-platform-module-auth-client-password.component-Cihg82vM.mjs +529 -0
  32. package/fesm2022/acorex-platform-module-auth-client-password.component-Cihg82vM.mjs.map +1 -0
  33. package/fesm2022/acorex-platform-module-auth-client-pin-code.constants-CRsFG7fg.mjs +7 -0
  34. package/fesm2022/acorex-platform-module-auth-client-pin-code.constants-CRsFG7fg.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-module-auth-client-profile-activity-chart.component-B8lBvZsA.mjs +158 -0
  36. package/fesm2022/acorex-platform-module-auth-client-profile-activity-chart.component-B8lBvZsA.mjs.map +1 -0
  37. package/fesm2022/acorex-platform-module-auth-client-profile-coming-soon.command-DBbFbzAx.mjs +31 -0
  38. package/fesm2022/acorex-platform-module-auth-client-profile-coming-soon.command-DBbFbzAx.mjs.map +1 -0
  39. package/fesm2022/acorex-platform-module-auth-client-profile-delete-account-danger-zone.component-CtJho4ab.mjs +79 -0
  40. package/fesm2022/acorex-platform-module-auth-client-profile-delete-account-danger-zone.component-CtJho4ab.mjs.map +1 -0
  41. package/fesm2022/acorex-platform-module-auth-client-profile-page-component.provider-B-Qtd4_j.mjs +27 -0
  42. package/fesm2022/acorex-platform-module-auth-client-profile-page-component.provider-B-Qtd4_j.mjs.map +1 -0
  43. package/fesm2022/acorex-platform-module-auth-client-profile-page.component-tbhf7K0V.mjs +446 -0
  44. package/fesm2022/acorex-platform-module-auth-client-profile-page.component-tbhf7K0V.mjs.map +1 -0
  45. package/fesm2022/acorex-platform-module-auth-client-register-password.component-hSJyEA6Q.mjs +145 -0
  46. package/fesm2022/acorex-platform-module-auth-client-register-password.component-hSJyEA6Q.mjs.map +1 -0
  47. package/fesm2022/acorex-platform-module-auth-client-register.module-DXm6AQpo.mjs +62 -0
  48. package/fesm2022/acorex-platform-module-auth-client-register.module-DXm6AQpo.mjs.map +1 -0
  49. package/fesm2022/acorex-platform-module-auth-client-remove-pin-code.command-zUZooOtv.mjs +91 -0
  50. package/fesm2022/acorex-platform-module-auth-client-remove-pin-code.command-zUZooOtv.mjs.map +1 -0
  51. package/fesm2022/acorex-platform-module-auth-client-result.component-DYJaB-FD.mjs +36 -0
  52. package/fesm2022/acorex-platform-module-auth-client-result.component-DYJaB-FD.mjs.map +1 -0
  53. package/fesm2022/acorex-platform-module-auth-client-routes-REjaWcqY.mjs +9 -0
  54. package/fesm2022/acorex-platform-module-auth-client-routes-REjaWcqY.mjs.map +1 -0
  55. package/fesm2022/acorex-platform-module-auth-client-session-lock-overlay.component-DqXGuIgN.mjs +346 -0
  56. package/fesm2022/acorex-platform-module-auth-client-session-lock-overlay.component-DqXGuIgN.mjs.map +1 -0
  57. package/fesm2022/acorex-platform-module-auth-client-set-pin-code.command-DXTVbrS0.mjs +33 -0
  58. package/fesm2022/acorex-platform-module-auth-client-set-pin-code.command-DXTVbrS0.mjs.map +1 -0
  59. package/fesm2022/acorex-platform-module-auth-client-set-pin-code.component-5TxB6aFi.mjs +188 -0
  60. package/fesm2022/acorex-platform-module-auth-client-set-pin-code.component-5TxB6aFi.mjs.map +1 -0
  61. package/fesm2022/acorex-platform-module-auth-client-settings.provider-n1qbs6e1.mjs +177 -0
  62. package/fesm2022/acorex-platform-module-auth-client-settings.provider-n1qbs6e1.mjs.map +1 -0
  63. package/fesm2022/acorex-platform-module-auth-client-show-profile-command-CxMz1yy-.mjs +70 -0
  64. package/fesm2022/acorex-platform-module-auth-client-show-profile-command-CxMz1yy-.mjs.map +1 -0
  65. package/fesm2022/acorex-platform-module-auth-client-signout-command-DqqrP5pk.mjs +24 -0
  66. package/fesm2022/acorex-platform-module-auth-client-signout-command-DqqrP5pk.mjs.map +1 -0
  67. package/fesm2022/acorex-platform-module-auth-client-tenant-chooser.component-ihsqCJKN.mjs +59 -0
  68. package/fesm2022/acorex-platform-module-auth-client-tenant-chooser.component-ihsqCJKN.mjs.map +1 -0
  69. package/fesm2022/acorex-platform-module-auth-client-two-factor-code.component-CiENsIEh.mjs +40 -0
  70. package/fesm2022/acorex-platform-module-auth-client-two-factor-code.component-CiENsIEh.mjs.map +1 -0
  71. package/fesm2022/acorex-platform-module-auth-client-two-factor.module-BJqdeuAz.mjs +45 -0
  72. package/fesm2022/acorex-platform-module-auth-client-two-factor.module-BJqdeuAz.mjs.map +1 -0
  73. package/fesm2022/acorex-platform-module-auth-client-view-login-history.command-Dl0os5lD.mjs +108 -0
  74. package/fesm2022/acorex-platform-module-auth-client-view-login-history.command-Dl0os5lD.mjs.map +1 -0
  75. package/fesm2022/acorex-platform-module-auth-client.mjs +2 -0
  76. package/fesm2022/acorex-platform-module-auth-client.mjs.map +1 -0
  77. package/package.json +28 -0
  78. package/types/acorex-platform-module-auth-client-contracts.d.ts +67 -0
  79. package/types/acorex-platform-module-auth-client.d.ts +390 -0
@@ -0,0 +1,529 @@
1
+ import * as i1 from '@acorex/components/button';
2
+ import { AXButtonModule } from '@acorex/components/button';
3
+ import * as i7 from '@acorex/components/check-box';
4
+ import { AXCheckBoxModule } from '@acorex/components/check-box';
5
+ import * as i3$1 from '@acorex/components/decorators';
6
+ import { AXDecoratorModule } from '@acorex/components/decorators';
7
+ import { AXDialogService } from '@acorex/components/dialog';
8
+ import * as i1$1 from '@acorex/components/form';
9
+ import { AXFormModule, AXFormComponent } from '@acorex/components/form';
10
+ import * as i3 from '@acorex/components/label';
11
+ import { AXLabelModule } from '@acorex/components/label';
12
+ import * as i5 from '@acorex/components/loading';
13
+ import { AXLoadingModule } from '@acorex/components/loading';
14
+ import * as i4$1 from '@acorex/components/password-box';
15
+ import { AXPasswordBoxModule } from '@acorex/components/password-box';
16
+ import * as i2 from '@acorex/components/text-box';
17
+ import { AXTextBoxModule } from '@acorex/components/text-box';
18
+ import * as i2$1 from '@acorex/core/translation';
19
+ import { AXTranslationModule } from '@acorex/core/translation';
20
+ import * as i4 from '@angular/common';
21
+ import { CommonModule } from '@angular/common';
22
+ import * as i0 from '@angular/core';
23
+ import { signal, Component, inject, Injector, effect, ViewContainerRef, ViewChild } from '@angular/core';
24
+ import { RouterModule, ActivatedRoute, Router } from '@angular/router';
25
+ import { AXToastService } from '@acorex/components/toast';
26
+ import { AXValidationModule } from '@acorex/core/validation';
27
+ import { AXPLoginChallengeComponentBase, AXPSessionService, AXP_LOGIN_CHALLENGE_PROVIDER } from '@acorex-platform/framework-client/auth';
28
+ import { AXPHomePageService } from '@acorex-platform/framework-client/common';
29
+ import * as i1$2 from '@angular/forms';
30
+ import { FormsModule } from '@angular/forms';
31
+ import { BehaviorSubject, firstValueFrom } from 'rxjs';
32
+ import { x as AXPLoginExternalProvidersComponent, n as AXM_AUTH_CONFIG_TOKEN, p as AXMAuthenticationTypes } from './acorex-platform-module-auth-client-acorex-platform-module-auth-client-B7tIKOw6.mjs';
33
+
34
+ //#region ---- Default Challenge Component ----
35
+ /**
36
+ * Default built-in challenge component for login
37
+ * Shows challenge image/content with an input field and refresh button
38
+ */
39
+ class AXPDefaultChallengeComponent extends AXPLoginChallengeComponentBase {
40
+ constructor() {
41
+ super(...arguments);
42
+ //#region ---- Local State ----
43
+ /** Local state for the response input */
44
+ this.response = signal('', ...(ngDevMode ? [{ debugName: "response" }] : /* istanbul ignore next */ []));
45
+ }
46
+ //#endregion
47
+ //#region ---- Event Handlers ----
48
+ /**
49
+ * Handles response input change
50
+ */
51
+ onResponseChange(value) {
52
+ this.response.set(value);
53
+ this.responseChange.emit(value);
54
+ }
55
+ /**
56
+ * Handles refresh button click
57
+ */
58
+ onRefreshClick() {
59
+ this.refreshRequest.emit();
60
+ }
61
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultChallengeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
62
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPDefaultChallengeComponent, isStandalone: true, selector: "axp-default-challenge", usesInheritance: true, ngImport: i0, template: `
63
+ <div class="flex flex-col gap-3 p-4 border rounded-md border-warning-300 bg-warning-50">
64
+ <!-- Challenge Image -->
65
+ <div class="flex items-center justify-center gap-2">
66
+ @if (challengeData(); as challenge) {
67
+ @if (challenge.contentType === 'image-base64') {
68
+ <img
69
+ [src]="'data:image/png;base64,' + challenge.content"
70
+ alt="Security Challenge"
71
+ class="h-12 border rounded"
72
+ />
73
+ } @else if (challenge.contentType === 'image-url') {
74
+ <img [src]="challenge.content" alt="Security Challenge" class="h-12 border rounded" />
75
+ } @else {
76
+ <span class="font-mono text-lg p-2 border rounded bg-white">
77
+ {{ challenge.content }}
78
+ </span>
79
+ }
80
+ }
81
+ <!-- Refresh Challenge Button -->
82
+ <ax-button
83
+ look="blank"
84
+ color="primary"
85
+ class="ax-sm"
86
+ id="refresh-challenge"
87
+ (onClick)="onRefreshClick()"
88
+ [disabled]="isLoading()"
89
+ >
90
+ @if (isLoading()) {
91
+ <ax-loading></ax-loading>
92
+ } @else {
93
+ <ax-icon><i class="fa-solid fa-rotate"></i></ax-icon>
94
+ }
95
+ </ax-button>
96
+ </div>
97
+
98
+ <!-- Challenge Response Input -->
99
+ <ax-form-field>
100
+ <ax-label>{{ '@auth:challenge.enter-code' | translate | async }}</ax-label>
101
+ <ax-text-box
102
+ [name]="'challengeResponse'"
103
+ id="challenge-response"
104
+ [placeholder]="'@auth:challenge.placeholder' | translate | async"
105
+ [value]="response()"
106
+ (valueChange)="onResponseChange($event)"
107
+ >
108
+ <ax-validation-rule rule="required"></ax-validation-rule>
109
+ </ax-text-box>
110
+ </ax-form-field>
111
+ </div>
112
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i2.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "maskPattern", "customTokens", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onMaskChanged"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i1$1.AXFormFieldComponent, selector: "ax-form-field", inputs: ["labelMode"] }, { kind: "directive", type: i1$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i5.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXValidationModule }, { kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i2$1.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }] }); }
113
+ }
114
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDefaultChallengeComponent, decorators: [{
115
+ type: Component,
116
+ args: [{
117
+ selector: 'axp-default-challenge',
118
+ standalone: true,
119
+ imports: [
120
+ AXButtonModule,
121
+ AXTextBoxModule,
122
+ AXLabelModule,
123
+ AXFormModule,
124
+ AXDecoratorModule,
125
+ AXLoadingModule,
126
+ AXTranslationModule,
127
+ AXValidationModule,
128
+ CommonModule,
129
+ ],
130
+ template: `
131
+ <div class="flex flex-col gap-3 p-4 border rounded-md border-warning-300 bg-warning-50">
132
+ <!-- Challenge Image -->
133
+ <div class="flex items-center justify-center gap-2">
134
+ @if (challengeData(); as challenge) {
135
+ @if (challenge.contentType === 'image-base64') {
136
+ <img
137
+ [src]="'data:image/png;base64,' + challenge.content"
138
+ alt="Security Challenge"
139
+ class="h-12 border rounded"
140
+ />
141
+ } @else if (challenge.contentType === 'image-url') {
142
+ <img [src]="challenge.content" alt="Security Challenge" class="h-12 border rounded" />
143
+ } @else {
144
+ <span class="font-mono text-lg p-2 border rounded bg-white">
145
+ {{ challenge.content }}
146
+ </span>
147
+ }
148
+ }
149
+ <!-- Refresh Challenge Button -->
150
+ <ax-button
151
+ look="blank"
152
+ color="primary"
153
+ class="ax-sm"
154
+ id="refresh-challenge"
155
+ (onClick)="onRefreshClick()"
156
+ [disabled]="isLoading()"
157
+ >
158
+ @if (isLoading()) {
159
+ <ax-loading></ax-loading>
160
+ } @else {
161
+ <ax-icon><i class="fa-solid fa-rotate"></i></ax-icon>
162
+ }
163
+ </ax-button>
164
+ </div>
165
+
166
+ <!-- Challenge Response Input -->
167
+ <ax-form-field>
168
+ <ax-label>{{ '@auth:challenge.enter-code' | translate | async }}</ax-label>
169
+ <ax-text-box
170
+ [name]="'challengeResponse'"
171
+ id="challenge-response"
172
+ [placeholder]="'@auth:challenge.placeholder' | translate | async"
173
+ [value]="response()"
174
+ (valueChange)="onResponseChange($event)"
175
+ >
176
+ <ax-validation-rule rule="required"></ax-validation-rule>
177
+ </ax-text-box>
178
+ </ax-form-field>
179
+ </div>
180
+ `,
181
+ }]
182
+ }] });
183
+
184
+ //#region ---- Module Imports ----
185
+ const MODULES = [
186
+ CommonModule,
187
+ FormsModule,
188
+ AXFormModule,
189
+ AXTextBoxModule,
190
+ AXPasswordBoxModule,
191
+ AXButtonModule,
192
+ AXLabelModule,
193
+ AXDecoratorModule,
194
+ AXCheckBoxModule,
195
+ AXTranslationModule,
196
+ AXLoadingModule,
197
+ RouterModule,
198
+ AXValidationModule,
199
+ AXPLoginExternalProvidersComponent,
200
+ ];
201
+ //#endregion
202
+ class AXPLoginPasswordComponent {
203
+ constructor() {
204
+ //#region ---- Services & Dependencies ----
205
+ this.configs = inject(AXM_AUTH_CONFIG_TOKEN);
206
+ this.dialogService = inject(AXDialogService);
207
+ this.sessionService = inject(AXPSessionService);
208
+ this.activateRoute = inject(ActivatedRoute);
209
+ this.homePageService = inject(AXPHomePageService);
210
+ this.toastService = inject(AXToastService);
211
+ this.router = inject(Router);
212
+ this.injector = inject(Injector);
213
+ /** Optional challenge provider - injected only if configured */
214
+ this.challengeProvider = inject(AXP_LOGIN_CHALLENGE_PROVIDER, { optional: true });
215
+ /** Value of the first input field (username/email) */
216
+ this.v1 = '';
217
+ /** Value of the second input field (password) */
218
+ this.v2 = '';
219
+ /** Whether to keep the user logged in */
220
+ this.isKeepLogin = false;
221
+ /** Current challenge data from the server */
222
+ this.challengeData = signal(null, ...(ngDevMode ? [{ debugName: "challengeData" }] : /* istanbul ignore next */ []));
223
+ /** User's response to the challenge (e.g., CAPTCHA text) */
224
+ this.challengeResponse = signal('', ...(ngDevMode ? [{ debugName: "challengeResponse" }] : /* istanbul ignore next */ []));
225
+ /** Loading state for challenge refresh */
226
+ this.isChallengeLoading = signal(false, ...(ngDevMode ? [{ debugName: "isChallengeLoading" }] : /* istanbul ignore next */ []));
227
+ /**
228
+ * Effect to render the challenge component when challenge data changes
229
+ */
230
+ this.challengeRenderEffect = effect(() => {
231
+ const data = this.challengeData();
232
+ const isLoading = this.isChallengeLoading();
233
+ // Wait for next tick to ensure ViewContainerRef is available
234
+ setTimeout(() => {
235
+ if (data && this.challengeContainerRef) {
236
+ this.renderChallengeComponent(data, isLoading);
237
+ }
238
+ else {
239
+ this.destroyChallengeComponent();
240
+ }
241
+ });
242
+ }, ...(ngDevMode ? [{ debugName: "challengeRenderEffect" }] : /* istanbul ignore next */ []));
243
+ //#endregion
244
+ //#region ---- Loading & Status State ----
245
+ this.isLoading$ = new BehaviorSubject(false);
246
+ this.submitText = 'signin.submit';
247
+ }
248
+ //#endregion
249
+ //#region ---- Computed Properties ----
250
+ /** Check if a challenge is currently active and should be displayed */
251
+ get hasChallengeActive() {
252
+ return this.challengeData() !== null;
253
+ }
254
+ //#endregion
255
+ //#region ---- Lifecycle Methods ----
256
+ ngOnInit() {
257
+ this.l2 = 'password';
258
+ switch (this.configs.type) {
259
+ case AXMAuthenticationTypes.EmailPassword:
260
+ this.l1 = 'email';
261
+ break;
262
+ case AXMAuthenticationTypes.MobilePassword:
263
+ this.l1 = 'mobile';
264
+ break;
265
+ case AXMAuthenticationTypes.UsernameEmailPassword:
266
+ this.l1 = 'username-email';
267
+ break;
268
+ case AXMAuthenticationTypes.UsernamePassword:
269
+ default:
270
+ this.l1 = 'username';
271
+ }
272
+ }
273
+ //#endregion
274
+ //#region ---- Navigation Handlers ----
275
+ handleForgotOnClick() {
276
+ this.router.navigate(['/auth/forgot']);
277
+ }
278
+ handleRegisterOnClick() {
279
+ this.router.navigate([this.configs.signup?.url || '/auth/register']);
280
+ }
281
+ //#endregion
282
+ //#region ---- Login Handlers ----
283
+ handleLoginClick() {
284
+ this.sessionService.setStrategy(this.configs.defaultStrategyName || 'user-pass');
285
+ const redirectUrl = this.activateRoute.snapshot.queryParams['redirectUrl'];
286
+ this.form.validate().then(async (form) => {
287
+ if (form.result) {
288
+ this.isLoading$.next(true);
289
+ this.submitText = 'processing';
290
+ try {
291
+ const strategy = this.sessionService.getSessionData()?.strategy;
292
+ if (!strategy) {
293
+ throw new Error('Strategy not found');
294
+ }
295
+ // Build credentials object with challenge data if active
296
+ const currentChallenge = this.challengeData();
297
+ const credentials = {
298
+ strategy: strategy,
299
+ username: this.v1,
300
+ password: this.v2,
301
+ ...(currentChallenge && {
302
+ challengeId: currentChallenge.id,
303
+ challengeResponse: this.challengeResponse(),
304
+ }),
305
+ };
306
+ await this.sessionService.signin(credentials);
307
+ // Check authentication status before navigation
308
+ const isAuthenticated = await firstValueFrom(this.sessionService.isAuthenticated$);
309
+ if (!isAuthenticated) {
310
+ throw new Error('Authentication failed after signin');
311
+ }
312
+ // Clear challenge state on successful login
313
+ this.clearChallengeState();
314
+ await this.navigateAfterAuth(redirectUrl);
315
+ }
316
+ catch (error) {
317
+ await this.handleLoginError(error);
318
+ }
319
+ }
320
+ });
321
+ }
322
+ async navigateAfterAuth(redirectUrl) {
323
+ if (this.sessionService.tenant?.id == null) {
324
+ await this.router.navigate(['/auth/account/tenant-chooser']);
325
+ return;
326
+ }
327
+ if (this.sessionService.application?.id == null) {
328
+ await this.router.navigate(['/auth/account/app-chooser']);
329
+ return;
330
+ }
331
+ if (redirectUrl) {
332
+ await this.router.navigate([redirectUrl]);
333
+ return;
334
+ }
335
+ await this.homePageService.navigateTo();
336
+ }
337
+ /**
338
+ * Handles login errors and checks if a challenge is required
339
+ */
340
+ async handleLoginError(error) {
341
+ const apiError = this.extractApiError(error);
342
+ // Check if challenge provider wants to handle this error
343
+ if (this.challengeProvider) {
344
+ const checkResult = this.challengeProvider.checkResponse(error);
345
+ if (checkResult?.required) {
346
+ try {
347
+ // Fetch challenge from server
348
+ const challenge = await this.challengeProvider.getChallenge(checkResult.serverData);
349
+ this.challengeData.set(challenge);
350
+ this.challengeResponse.set('');
351
+ // Show challenge message if provided
352
+ if (checkResult.message) {
353
+ this.toastService.show({
354
+ color: 'warning',
355
+ content: checkResult.message,
356
+ timeOut: 5000,
357
+ });
358
+ }
359
+ this.submitText = 'signin.submit';
360
+ this.isLoading$.next(false);
361
+ return;
362
+ }
363
+ catch (challengeError) {
364
+ console.error('Failed to fetch challenge:', challengeError);
365
+ }
366
+ }
367
+ }
368
+ else if (apiError?.['requiresCaptcha'] === true) {
369
+ this.toastService.show({
370
+ color: 'warning',
371
+ content: 'Too many failed attempts. Additional verification may be required on your next try.',
372
+ timeOut: 5000,
373
+ });
374
+ }
375
+ // Default error handling
376
+ this.showLoginError(error, apiError);
377
+ }
378
+ /**
379
+ * Displays the login error message to the user
380
+ */
381
+ showLoginError(error, apiError) {
382
+ let errorMsg = 'An error occurred during sign in.';
383
+ const resolvedApiError = apiError ?? this.extractApiError(error);
384
+ if (resolvedApiError?.['message'] && typeof resolvedApiError['message'] === 'string') {
385
+ errorMsg = resolvedApiError['message'];
386
+ }
387
+ else if (error && typeof error === 'object') {
388
+ const err = error;
389
+ const errObj = err['error'];
390
+ errorMsg =
391
+ errObj?.['error_description'] ||
392
+ errObj?.['error'] ||
393
+ err['message'] ||
394
+ errorMsg;
395
+ if (typeof errorMsg === 'object') {
396
+ const msgObj = errorMsg;
397
+ errorMsg = msgObj['message'] || msgObj['error_description'] || JSON.stringify(errorMsg);
398
+ }
399
+ }
400
+ const remainingAttempts = resolvedApiError?.['remainingAttempts'];
401
+ if (typeof remainingAttempts === 'number' && remainingAttempts >= 0 && resolvedApiError?.['error'] !== 'AccountLocked') {
402
+ errorMsg = `${errorMsg} (${remainingAttempts} attempt${remainingAttempts === 1 ? '' : 's'} remaining)`;
403
+ }
404
+ this.toastService.show({
405
+ color: 'danger',
406
+ content: errorMsg,
407
+ timeOut: 5000,
408
+ });
409
+ console.error('Login error:', error);
410
+ this.submitText = 'signin.submit';
411
+ this.v2 = null;
412
+ this.isLoading$.next(false);
413
+ }
414
+ extractApiError(error) {
415
+ if (!error || typeof error !== 'object') {
416
+ return null;
417
+ }
418
+ const err = error;
419
+ if (err['apiError'] && typeof err['apiError'] === 'object') {
420
+ return err['apiError'];
421
+ }
422
+ if (err['error'] && typeof err['error'] === 'object') {
423
+ return err['error'];
424
+ }
425
+ return null;
426
+ }
427
+ //#endregion
428
+ //#region ---- Challenge Handlers ----
429
+ /**
430
+ * Gets the challenge component type from provider or uses default
431
+ */
432
+ getChallengeComponentType() {
433
+ return this.challengeProvider?.getChallengeComponent() ?? AXPDefaultChallengeComponent;
434
+ }
435
+ /**
436
+ * Renders the challenge component dynamically
437
+ */
438
+ renderChallengeComponent(data, isLoading) {
439
+ if (!this.challengeContainerRef)
440
+ return;
441
+ // If component already exists, just update inputs
442
+ if (this.challengeComponentRef) {
443
+ this.updateChallengeComponentInputs(data, isLoading);
444
+ return;
445
+ }
446
+ // Clear container and create new component
447
+ this.challengeContainerRef.clear();
448
+ const componentType = this.getChallengeComponentType();
449
+ this.challengeComponentRef = this.challengeContainerRef.createComponent(componentType);
450
+ // Set inputs
451
+ this.updateChallengeComponentInputs(data, isLoading);
452
+ // Subscribe to outputs
453
+ const instance = this.challengeComponentRef.instance;
454
+ instance.responseChange.subscribe((response) => {
455
+ this.challengeResponse.set(response);
456
+ });
457
+ instance.refreshRequest.subscribe(() => {
458
+ this.handleRefreshChallenge();
459
+ });
460
+ }
461
+ /**
462
+ * Updates the inputs of the challenge component
463
+ */
464
+ updateChallengeComponentInputs(data, isLoading) {
465
+ if (!this.challengeComponentRef)
466
+ return;
467
+ this.challengeComponentRef.setInput('challengeData', data);
468
+ this.challengeComponentRef.setInput('isLoading', isLoading);
469
+ }
470
+ /**
471
+ * Destroys the challenge component
472
+ */
473
+ destroyChallengeComponent() {
474
+ if (this.challengeComponentRef) {
475
+ this.challengeComponentRef.destroy();
476
+ this.challengeComponentRef = undefined;
477
+ }
478
+ if (this.challengeContainerRef) {
479
+ this.challengeContainerRef.clear();
480
+ }
481
+ }
482
+ /**
483
+ * Refreshes the challenge (e.g., user clicks "new image" button)
484
+ */
485
+ async handleRefreshChallenge() {
486
+ if (!this.challengeProvider)
487
+ return;
488
+ this.isChallengeLoading.set(true);
489
+ try {
490
+ const newChallenge = await this.challengeProvider.refreshChallenge();
491
+ this.challengeData.set(newChallenge);
492
+ this.challengeResponse.set('');
493
+ }
494
+ catch (error) {
495
+ console.error('Failed to refresh challenge:', error);
496
+ this.toastService.show({
497
+ color: 'danger',
498
+ content: 'Failed to load new challenge. Please try again.',
499
+ timeOut: 3000,
500
+ });
501
+ }
502
+ finally {
503
+ this.isChallengeLoading.set(false);
504
+ }
505
+ }
506
+ /**
507
+ * Clears the challenge state (after successful login or manual clear)
508
+ */
509
+ clearChallengeState() {
510
+ this.challengeData.set(null);
511
+ this.challengeResponse.set('');
512
+ this.destroyChallengeComponent();
513
+ }
514
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLoginPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
515
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLoginPasswordComponent, isStandalone: true, selector: "ng-component", viewQueries: [{ propertyName: "form", first: true, predicate: AXFormComponent, descendants: true }, { propertyName: "challengeContainerRef", first: true, predicate: ["challengeContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0, template: "<ng-container *translate=\"let t\">\n <div class=\"text-center mb-4\">\n <h1 class=\"font-bold text-xl mb-2\">\n {{ '@auth:signin.title' | translate | async }}\n </h1>\n <p class=\"text-base text-neutral-600\">\n {{ '@auth:signin.hint' | translate | async }}\n </p>\n </div>\n <div class=\"w-80 lg:w-96\">\n <ax-form>\n <div class=\"flex flex-col gap-6\">\n <ax-form-field>\n <ax-label>{{ '@auth:username-email' | translate | async }}</ax-label>\n <ax-text-box\n [name]=\"'username'\"\n id=\"username\"\n [autoComplete]=\"'username'\"\n [(value)]=\"v1\"\n >\n <ax-validation-rule rule=\"required\"></ax-validation-rule>\n </ax-text-box>\n </ax-form-field>\n <ax-form-field>\n <ax-label>{{ '@auth:password' | translate | async }}</ax-label>\n <ax-password-box\n [name]=\"'password'\"\n id=\"password\"\n [autoComplete]=\"'current-password'\"\n [(value)]=\"v2\"\n >\n <ax-validation-rule rule=\"required\"></ax-validation-rule>\n </ax-password-box>\n </ax-form-field>\n\n <!-- Challenge Section (CAPTCHA) - rendered via ViewContainerRef -->\n @if (hasChallengeActive) {\n <ng-container #challengeContainer></ng-container>\n }\n\n <div class=\"flex justify-between items-center\">\n <ax-check-box [(ngModel)]=\"isKeepLogin\">\n <ax-label class=\"mb-0\">{{\n '@auth:signin.remember' | translate | async\n }}</ax-label>\n </ax-check-box>\n <ax-button\n color=\"primary\"\n class=\"ax-sm\"\n id=\"forgot-password\"\n [text]=\"'@auth:forgot.password' | translate | async\"\n look=\"blank\"\n (onClick)=\"handleForgotOnClick()\"\n >\n </ax-button>\n </div>\n </div>\n <ax-button\n color=\"primary\"\n class=\"mt-6 w-full\"\n id=\"submit-login\"\n [text]=\"'@auth:signin.submit' | translate | async\"\n (onClick)=\"handleLoginClick()\"\n [disabled]=\"isLoading$ | async\"\n [type]=\"'submit'\"\n >\n @if (isLoading$ | async) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n @if (externalProviders.hasContent() || configs.signup?.enable) {\n <div class=\"heading heading-center !my-8\">\n <span>{{ '@auth:signin.or' | translate | async }}</span>\n </div>\n }\n <axm-login-external-providers\n #externalProviders\n ></axm-login-external-providers>\n </ax-form>\n @if (configs.signup?.enable) {\n <ax-button\n class=\"w-full mt-2\"\n id=\"register\"\n (onClick)=\"handleRegisterOnClick()\"\n text=\"{{ '@auth:register' | translate | async }}\"\n [color]=\"'default'\"\n >\n </ax-button>\n }\n </div>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXFormModule }, { kind: "component", type: i1$1.AXFormFieldComponent, selector: "ax-form-field", inputs: ["labelMode"] }, { kind: "component", type: i1$1.AXFormComponent, selector: "ax-form", inputs: ["disabled", "readonly", "labelMode", "look", "messageStyle", "updateOn", "inUserInteractionActive"], outputs: ["onValidate", "updateOnChange"] }, { kind: "directive", type: i1$1.AXValidationRuleDirective, selector: "ax-validation-rule", inputs: ["rule", "options", "message", "disabled"] }, { kind: "ngmodule", type: AXTextBoxModule }, { kind: "component", type: i2.AXTextBoxComponent, selector: "ax-text-box", inputs: ["disabled", "tabIndex", "readonly", "value", "state", "name", "id", "placeholder", "maxLength", "allowNull", "type", "autoComplete", "look", "maskPattern", "customTokens", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress", "onMaskChanged"] }, { kind: "ngmodule", type: AXPasswordBoxModule }, { kind: "component", type: i4$1.AXPasswordBoxComponent, selector: "ax-password-box", inputs: ["readonly", "disabled", "tabIndex", "placeholder", "value", "state", "name", "id", "look", "autoComplete", "showToggleButton", "class"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXLabelModule }, { kind: "component", type: i3.AXLabelComponent, selector: "ax-label", inputs: ["required", "for"], outputs: ["requiredChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i7.AXCheckBoxComponent, selector: "ax-check-box", inputs: ["disabled", "tabIndex", "readonly", "color", "value", "name", "id", "isLoading", "indeterminate"], outputs: ["onBlur", "onFocus", "valueChange", "onValueChanged"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i2$1.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i5.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: AXValidationModule }, { kind: "component", type: AXPLoginExternalProvidersComponent, selector: "axm-login-external-providers" }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i2$1.AXTranslatorPipe, name: "translate" }] }); }
516
+ }
517
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLoginPasswordComponent, decorators: [{
518
+ type: Component,
519
+ args: [{ imports: [...MODULES], template: "<ng-container *translate=\"let t\">\n <div class=\"text-center mb-4\">\n <h1 class=\"font-bold text-xl mb-2\">\n {{ '@auth:signin.title' | translate | async }}\n </h1>\n <p class=\"text-base text-neutral-600\">\n {{ '@auth:signin.hint' | translate | async }}\n </p>\n </div>\n <div class=\"w-80 lg:w-96\">\n <ax-form>\n <div class=\"flex flex-col gap-6\">\n <ax-form-field>\n <ax-label>{{ '@auth:username-email' | translate | async }}</ax-label>\n <ax-text-box\n [name]=\"'username'\"\n id=\"username\"\n [autoComplete]=\"'username'\"\n [(value)]=\"v1\"\n >\n <ax-validation-rule rule=\"required\"></ax-validation-rule>\n </ax-text-box>\n </ax-form-field>\n <ax-form-field>\n <ax-label>{{ '@auth:password' | translate | async }}</ax-label>\n <ax-password-box\n [name]=\"'password'\"\n id=\"password\"\n [autoComplete]=\"'current-password'\"\n [(value)]=\"v2\"\n >\n <ax-validation-rule rule=\"required\"></ax-validation-rule>\n </ax-password-box>\n </ax-form-field>\n\n <!-- Challenge Section (CAPTCHA) - rendered via ViewContainerRef -->\n @if (hasChallengeActive) {\n <ng-container #challengeContainer></ng-container>\n }\n\n <div class=\"flex justify-between items-center\">\n <ax-check-box [(ngModel)]=\"isKeepLogin\">\n <ax-label class=\"mb-0\">{{\n '@auth:signin.remember' | translate | async\n }}</ax-label>\n </ax-check-box>\n <ax-button\n color=\"primary\"\n class=\"ax-sm\"\n id=\"forgot-password\"\n [text]=\"'@auth:forgot.password' | translate | async\"\n look=\"blank\"\n (onClick)=\"handleForgotOnClick()\"\n >\n </ax-button>\n </div>\n </div>\n <ax-button\n color=\"primary\"\n class=\"mt-6 w-full\"\n id=\"submit-login\"\n [text]=\"'@auth:signin.submit' | translate | async\"\n (onClick)=\"handleLoginClick()\"\n [disabled]=\"isLoading$ | async\"\n [type]=\"'submit'\"\n >\n @if (isLoading$ | async) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n @if (externalProviders.hasContent() || configs.signup?.enable) {\n <div class=\"heading heading-center !my-8\">\n <span>{{ '@auth:signin.or' | translate | async }}</span>\n </div>\n }\n <axm-login-external-providers\n #externalProviders\n ></axm-login-external-providers>\n </ax-form>\n @if (configs.signup?.enable) {\n <ax-button\n class=\"w-full mt-2\"\n id=\"register\"\n (onClick)=\"handleRegisterOnClick()\"\n text=\"{{ '@auth:register' | translate | async }}\"\n [color]=\"'default'\"\n >\n </ax-button>\n }\n </div>\n</ng-container>\n" }]
520
+ }], propDecorators: { form: [{
521
+ type: ViewChild,
522
+ args: [AXFormComponent]
523
+ }], challengeContainerRef: [{
524
+ type: ViewChild,
525
+ args: ['challengeContainer', { read: ViewContainerRef }]
526
+ }] } });
527
+
528
+ export { AXPLoginPasswordComponent };
529
+ //# sourceMappingURL=acorex-platform-module-auth-client-password.component-Cihg82vM.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acorex-platform-module-auth-client-password.component-Cihg82vM.mjs","sources":["../../../../libs/modules/auth/client/src/lib/pages/login/password/default-challenge.component.ts","../../../../libs/modules/auth/client/src/lib/pages/login/password/password.component.ts","../../../../libs/modules/auth/client/src/lib/pages/login/password/password.component.html"],"sourcesContent":["import { AXButtonModule } from '@acorex/components/button';\nimport { AXDecoratorModule } from '@acorex/components/decorators';\nimport { AXFormModule } from '@acorex/components/form';\nimport { AXLabelModule } from '@acorex/components/label';\nimport { AXLoadingModule } from '@acorex/components/loading';\nimport { AXTextBoxModule } from '@acorex/components/text-box';\nimport { AXTranslationModule } from '@acorex/core/translation';\nimport { AXValidationModule } from '@acorex/core/validation';\nimport { AXPLoginChallengeComponentBase } from '@acorex-platform/framework-client/auth';\nimport { CommonModule } from '@angular/common';\nimport { Component, signal } from '@angular/core';\n\n//#region ---- Default Challenge Component ----\n\n/**\n * Default built-in challenge component for login\n * Shows challenge image/content with an input field and refresh button\n */\n@Component({\n selector: 'axp-default-challenge',\n standalone: true,\n imports: [\n AXButtonModule,\n AXTextBoxModule,\n AXLabelModule,\n AXFormModule,\n AXDecoratorModule,\n AXLoadingModule,\n AXTranslationModule,\n AXValidationModule,\n CommonModule,\n ],\n template: `\n <div class=\"flex flex-col gap-3 p-4 border rounded-md border-warning-300 bg-warning-50\">\n <!-- Challenge Image -->\n <div class=\"flex items-center justify-center gap-2\">\n @if (challengeData(); as challenge) {\n @if (challenge.contentType === 'image-base64') {\n <img\n [src]=\"'data:image/png;base64,' + challenge.content\"\n alt=\"Security Challenge\"\n class=\"h-12 border rounded\"\n />\n } @else if (challenge.contentType === 'image-url') {\n <img [src]=\"challenge.content\" alt=\"Security Challenge\" class=\"h-12 border rounded\" />\n } @else {\n <span class=\"font-mono text-lg p-2 border rounded bg-white\">\n {{ challenge.content }}\n </span>\n }\n }\n <!-- Refresh Challenge Button -->\n <ax-button\n look=\"blank\"\n color=\"primary\"\n class=\"ax-sm\"\n id=\"refresh-challenge\"\n (onClick)=\"onRefreshClick()\"\n [disabled]=\"isLoading()\"\n >\n @if (isLoading()) {\n <ax-loading></ax-loading>\n } @else {\n <ax-icon><i class=\"fa-solid fa-rotate\"></i></ax-icon>\n }\n </ax-button>\n </div>\n\n <!-- Challenge Response Input -->\n <ax-form-field>\n <ax-label>{{ '@auth:challenge.enter-code' | translate | async }}</ax-label>\n <ax-text-box\n [name]=\"'challengeResponse'\"\n id=\"challenge-response\"\n [placeholder]=\"'@auth:challenge.placeholder' | translate | async\"\n [value]=\"response()\"\n (valueChange)=\"onResponseChange($event)\"\n >\n <ax-validation-rule rule=\"required\"></ax-validation-rule>\n </ax-text-box>\n </ax-form-field>\n </div>\n `,\n})\nexport class AXPDefaultChallengeComponent extends AXPLoginChallengeComponentBase {\n //#region ---- Local State ----\n\n /** Local state for the response input */\n protected response = signal<string>('');\n\n //#endregion\n\n //#region ---- Event Handlers ----\n\n /**\n * Handles response input change\n */\n protected onResponseChange(value: string): void {\n this.response.set(value);\n this.responseChange.emit(value);\n }\n\n /**\n * Handles refresh button click\n */\n protected onRefreshClick(): void {\n this.refreshRequest.emit();\n }\n\n //#endregion\n}\n\n//#endregion\n","import { AXButtonModule } from '@acorex/components/button';\nimport { AXCheckBoxModule } from '@acorex/components/check-box';\nimport { AXDecoratorModule } from '@acorex/components/decorators';\nimport { AXDialogService } from '@acorex/components/dialog';\nimport { AXFormComponent, AXFormModule } from '@acorex/components/form';\nimport { AXLabelModule } from '@acorex/components/label';\nimport { AXLoadingModule } from '@acorex/components/loading';\nimport { AXPasswordBoxModule } from '@acorex/components/password-box';\nimport { AXTextBoxModule } from '@acorex/components/text-box';\nimport { AXTranslationModule } from '@acorex/core/translation';\nimport { CommonModule } from '@angular/common';\nimport {\n Component,\n ComponentRef,\n Injector,\n OnInit,\n Type,\n ViewChild,\n ViewContainerRef,\n effect,\n inject,\n signal,\n} from '@angular/core';\nimport { ActivatedRoute, Router, RouterModule } from '@angular/router';\n\nimport { AXToastService } from '@acorex/components/toast';\nimport { AXValidationModule } from '@acorex/core/validation';\nimport {\n AXPLoginChallengeComponentBase,\n AXPLoginChallengeData,\n AXPSessionService,\n AXP_LOGIN_CHALLENGE_PROVIDER,\n} from '@acorex-platform/framework-client/auth';\nimport { AXPHomePageService } from '@acorex-platform/framework-client/common';\nimport { FormsModule } from '@angular/forms';\nimport { BehaviorSubject, firstValueFrom } from 'rxjs';\nimport { AXMAuthConfigs, AXMAuthenticationTypes, AXM_AUTH_CONFIG_TOKEN } from '../../../auth.config';\nimport { AXPLoginExternalProvidersComponent } from '../login-external-providers.component';\nimport { AXPDefaultChallengeComponent } from './default-challenge.component';\n\n//#region ---- Module Imports ----\n\nconst MODULES = [\n CommonModule,\n FormsModule,\n AXFormModule,\n AXTextBoxModule,\n AXPasswordBoxModule,\n AXButtonModule,\n AXLabelModule,\n AXDecoratorModule,\n AXCheckBoxModule,\n AXTranslationModule,\n AXLoadingModule,\n RouterModule,\n AXValidationModule,\n AXPLoginExternalProvidersComponent,\n];\n\n//#endregion\n\n@Component({\n templateUrl: './password.component.html',\n imports: [...MODULES],\n})\nexport class AXPLoginPasswordComponent implements OnInit {\n //#region ---- Services & Dependencies ----\n\n protected configs: AXMAuthConfigs = inject<AXMAuthConfigs>(AXM_AUTH_CONFIG_TOKEN);\n private dialogService = inject(AXDialogService);\n private sessionService = inject(AXPSessionService);\n private activateRoute = inject(ActivatedRoute);\n private homePageService = inject(AXPHomePageService);\n private toastService = inject(AXToastService);\n private router = inject(Router);\n protected injector = inject(Injector);\n\n /** Optional challenge provider - injected only if configured */\n private challengeProvider = inject(AXP_LOGIN_CHALLENGE_PROVIDER, { optional: true });\n\n //#endregion\n\n //#region ---- Form References ----\n\n @ViewChild(AXFormComponent)\n private form!: AXFormComponent;\n\n //#endregion\n\n //#region ---- Form Fields ----\n\n /** Label key for the first input field (username/email/mobile) */\n protected l1!: string;\n\n /** Label key for the second input field (password) */\n protected l2!: string;\n\n /** Value of the first input field (username/email) */\n protected v1 = '';\n\n /** Value of the second input field (password) */\n protected v2: string | null = '';\n\n /** Whether to keep the user logged in */\n protected isKeepLogin = false;\n\n //#endregion\n\n //#region ---- Challenge State ----\n\n /** ViewContainerRef for rendering the challenge component */\n @ViewChild('challengeContainer', { read: ViewContainerRef })\n private challengeContainerRef?: ViewContainerRef;\n\n /** Reference to the currently rendered challenge component */\n private challengeComponentRef?: ComponentRef<AXPLoginChallengeComponentBase>;\n\n /** Current challenge data from the server */\n protected challengeData = signal<AXPLoginChallengeData | null>(null);\n\n /** User's response to the challenge (e.g., CAPTCHA text) */\n protected challengeResponse = signal<string>('');\n\n /** Loading state for challenge refresh */\n protected isChallengeLoading = signal<boolean>(false);\n\n /**\n * Effect to render the challenge component when challenge data changes\n */\n private challengeRenderEffect = effect(() => {\n const data = this.challengeData();\n const isLoading = this.isChallengeLoading();\n\n // Wait for next tick to ensure ViewContainerRef is available\n setTimeout(() => {\n if (data && this.challengeContainerRef) {\n this.renderChallengeComponent(data, isLoading);\n } else {\n this.destroyChallengeComponent();\n }\n });\n });\n\n //#endregion\n\n //#region ---- Loading & Status State ----\n\n protected isLoading$: BehaviorSubject<boolean> = new BehaviorSubject(false);\n protected submitText = 'signin.submit';\n\n //#endregion\n\n //#region ---- Computed Properties ----\n\n /** Check if a challenge is currently active and should be displayed */\n protected get hasChallengeActive(): boolean {\n return this.challengeData() !== null;\n }\n\n //#endregion\n\n //#region ---- Lifecycle Methods ----\n\n ngOnInit(): void {\n this.l2 = 'password';\n switch (this.configs.type) {\n case AXMAuthenticationTypes.EmailPassword:\n this.l1 = 'email';\n break;\n case AXMAuthenticationTypes.MobilePassword:\n this.l1 = 'mobile';\n break;\n case AXMAuthenticationTypes.UsernameEmailPassword:\n this.l1 = 'username-email';\n break;\n case AXMAuthenticationTypes.UsernamePassword:\n default:\n this.l1 = 'username';\n }\n }\n\n //#endregion\n\n //#region ---- Navigation Handlers ----\n\n protected handleForgotOnClick(): void {\n this.router.navigate(['/auth/forgot']);\n }\n\n protected handleRegisterOnClick(): void {\n this.router.navigate([this.configs.signup?.url || '/auth/register']);\n }\n\n //#endregion\n\n //#region ---- Login Handlers ----\n\n protected handleLoginClick(): void {\n this.sessionService.setStrategy(this.configs.defaultStrategyName || 'user-pass');\n const redirectUrl = this.activateRoute.snapshot.queryParams['redirectUrl'];\n\n this.form.validate().then(async (form) => {\n if (form.result) {\n this.isLoading$.next(true);\n this.submitText = 'processing';\n\n try {\n const strategy = this.sessionService.getSessionData()?.strategy;\n if (!strategy) {\n throw new Error('Strategy not found');\n }\n\n // Build credentials object with challenge data if active\n const currentChallenge = this.challengeData();\n const credentials = {\n strategy: strategy,\n username: this.v1,\n password: this.v2!,\n ...(currentChallenge && {\n challengeId: currentChallenge.id,\n challengeResponse: this.challengeResponse(),\n }),\n };\n\n await this.sessionService.signin(credentials);\n\n // Check authentication status before navigation\n const isAuthenticated = await firstValueFrom(this.sessionService.isAuthenticated$);\n\n if (!isAuthenticated) {\n throw new Error('Authentication failed after signin');\n }\n\n // Clear challenge state on successful login\n this.clearChallengeState();\n\n await this.navigateAfterAuth(redirectUrl);\n } catch (error: unknown) {\n await this.handleLoginError(error);\n }\n }\n });\n }\n\n private async navigateAfterAuth(redirectUrl?: string): Promise<void> {\n if (this.sessionService.tenant?.id == null) {\n await this.router.navigate(['/auth/account/tenant-chooser']);\n return;\n }\n\n if (this.sessionService.application?.id == null) {\n await this.router.navigate(['/auth/account/app-chooser']);\n return;\n }\n\n if (redirectUrl) {\n await this.router.navigate([redirectUrl]);\n return;\n }\n\n await this.homePageService.navigateTo();\n }\n\n /**\n * Handles login errors and checks if a challenge is required\n */\n private async handleLoginError(error: unknown): Promise<void> {\n const apiError = this.extractApiError(error);\n\n // Check if challenge provider wants to handle this error\n if (this.challengeProvider) {\n const checkResult = this.challengeProvider.checkResponse(error);\n\n if (checkResult?.required) {\n try {\n // Fetch challenge from server\n const challenge = await this.challengeProvider.getChallenge(checkResult.serverData);\n this.challengeData.set(challenge);\n this.challengeResponse.set('');\n\n // Show challenge message if provided\n if (checkResult.message) {\n this.toastService.show({\n color: 'warning',\n content: checkResult.message,\n timeOut: 5000,\n });\n }\n\n this.submitText = 'signin.submit';\n this.isLoading$.next(false);\n return;\n } catch (challengeError) {\n console.error('Failed to fetch challenge:', challengeError);\n }\n }\n } else if (apiError?.['requiresCaptcha'] === true) {\n this.toastService.show({\n color: 'warning',\n content: 'Too many failed attempts. Additional verification may be required on your next try.',\n timeOut: 5000,\n });\n }\n\n // Default error handling\n this.showLoginError(error, apiError);\n }\n\n /**\n * Displays the login error message to the user\n */\n private showLoginError(error: unknown, apiError?: Record<string, unknown> | null): void {\n let errorMsg = 'An error occurred during sign in.';\n const resolvedApiError = apiError ?? this.extractApiError(error);\n\n if (resolvedApiError?.['message'] && typeof resolvedApiError['message'] === 'string') {\n errorMsg = resolvedApiError['message'];\n } else if (error && typeof error === 'object') {\n const err = error as Record<string, unknown>;\n const errObj = err['error'] as Record<string, unknown> | undefined;\n\n errorMsg =\n (errObj?.['error_description'] as string) ||\n (errObj?.['error'] as string) ||\n (err['message'] as string) ||\n errorMsg;\n\n if (typeof errorMsg === 'object') {\n const msgObj = errorMsg as unknown as Record<string, unknown>;\n errorMsg = (msgObj['message'] as string) || (msgObj['error_description'] as string) || JSON.stringify(errorMsg);\n }\n }\n\n const remainingAttempts = resolvedApiError?.['remainingAttempts'];\n if (typeof remainingAttempts === 'number' && remainingAttempts >= 0 && resolvedApiError?.['error'] !== 'AccountLocked') {\n errorMsg = `${errorMsg} (${remainingAttempts} attempt${remainingAttempts === 1 ? '' : 's'} remaining)`;\n }\n\n this.toastService.show({\n color: 'danger',\n content: errorMsg,\n timeOut: 5000,\n });\n\n console.error('Login error:', error);\n this.submitText = 'signin.submit';\n this.v2 = null;\n this.isLoading$.next(false);\n }\n\n private extractApiError(error: unknown): Record<string, unknown> | null {\n if (!error || typeof error !== 'object') {\n return null;\n }\n\n const err = error as Record<string, unknown>;\n if (err['apiError'] && typeof err['apiError'] === 'object') {\n return err['apiError'] as Record<string, unknown>;\n }\n\n if (err['error'] && typeof err['error'] === 'object') {\n return err['error'] as Record<string, unknown>;\n }\n\n return null;\n }\n\n //#endregion\n\n //#region ---- Challenge Handlers ----\n\n /**\n * Gets the challenge component type from provider or uses default\n */\n private getChallengeComponentType(): Type<AXPLoginChallengeComponentBase> {\n return this.challengeProvider?.getChallengeComponent() ?? AXPDefaultChallengeComponent;\n }\n\n /**\n * Renders the challenge component dynamically\n */\n private renderChallengeComponent(data: AXPLoginChallengeData, isLoading: boolean): void {\n if (!this.challengeContainerRef) return;\n\n // If component already exists, just update inputs\n if (this.challengeComponentRef) {\n this.updateChallengeComponentInputs(data, isLoading);\n return;\n }\n\n // Clear container and create new component\n this.challengeContainerRef.clear();\n const componentType = this.getChallengeComponentType();\n this.challengeComponentRef = this.challengeContainerRef.createComponent(componentType);\n\n // Set inputs\n this.updateChallengeComponentInputs(data, isLoading);\n\n // Subscribe to outputs\n const instance = this.challengeComponentRef.instance;\n instance.responseChange.subscribe((response: string) => {\n this.challengeResponse.set(response);\n });\n instance.refreshRequest.subscribe(() => {\n this.handleRefreshChallenge();\n });\n }\n\n /**\n * Updates the inputs of the challenge component\n */\n private updateChallengeComponentInputs(data: AXPLoginChallengeData, isLoading: boolean): void {\n if (!this.challengeComponentRef) return;\n\n this.challengeComponentRef.setInput('challengeData', data);\n this.challengeComponentRef.setInput('isLoading', isLoading);\n }\n\n /**\n * Destroys the challenge component\n */\n private destroyChallengeComponent(): void {\n if (this.challengeComponentRef) {\n this.challengeComponentRef.destroy();\n this.challengeComponentRef = undefined;\n }\n if (this.challengeContainerRef) {\n this.challengeContainerRef.clear();\n }\n }\n\n /**\n * Refreshes the challenge (e.g., user clicks \"new image\" button)\n */\n protected async handleRefreshChallenge(): Promise<void> {\n if (!this.challengeProvider) return;\n\n this.isChallengeLoading.set(true);\n try {\n const newChallenge = await this.challengeProvider.refreshChallenge();\n this.challengeData.set(newChallenge);\n this.challengeResponse.set('');\n } catch (error) {\n console.error('Failed to refresh challenge:', error);\n this.toastService.show({\n color: 'danger',\n content: 'Failed to load new challenge. Please try again.',\n timeOut: 3000,\n });\n } finally {\n this.isChallengeLoading.set(false);\n }\n }\n\n /**\n * Clears the challenge state (after successful login or manual clear)\n */\n private clearChallengeState(): void {\n this.challengeData.set(null);\n this.challengeResponse.set('');\n this.destroyChallengeComponent();\n }\n\n //#endregion\n}\n","<ng-container *translate=\"let t\">\n <div class=\"text-center mb-4\">\n <h1 class=\"font-bold text-xl mb-2\">\n {{ '@auth:signin.title' | translate | async }}\n </h1>\n <p class=\"text-base text-neutral-600\">\n {{ '@auth:signin.hint' | translate | async }}\n </p>\n </div>\n <div class=\"w-80 lg:w-96\">\n <ax-form>\n <div class=\"flex flex-col gap-6\">\n <ax-form-field>\n <ax-label>{{ '@auth:username-email' | translate | async }}</ax-label>\n <ax-text-box\n [name]=\"'username'\"\n id=\"username\"\n [autoComplete]=\"'username'\"\n [(value)]=\"v1\"\n >\n <ax-validation-rule rule=\"required\"></ax-validation-rule>\n </ax-text-box>\n </ax-form-field>\n <ax-form-field>\n <ax-label>{{ '@auth:password' | translate | async }}</ax-label>\n <ax-password-box\n [name]=\"'password'\"\n id=\"password\"\n [autoComplete]=\"'current-password'\"\n [(value)]=\"v2\"\n >\n <ax-validation-rule rule=\"required\"></ax-validation-rule>\n </ax-password-box>\n </ax-form-field>\n\n <!-- Challenge Section (CAPTCHA) - rendered via ViewContainerRef -->\n @if (hasChallengeActive) {\n <ng-container #challengeContainer></ng-container>\n }\n\n <div class=\"flex justify-between items-center\">\n <ax-check-box [(ngModel)]=\"isKeepLogin\">\n <ax-label class=\"mb-0\">{{\n '@auth:signin.remember' | translate | async\n }}</ax-label>\n </ax-check-box>\n <ax-button\n color=\"primary\"\n class=\"ax-sm\"\n id=\"forgot-password\"\n [text]=\"'@auth:forgot.password' | translate | async\"\n look=\"blank\"\n (onClick)=\"handleForgotOnClick()\"\n >\n </ax-button>\n </div>\n </div>\n <ax-button\n color=\"primary\"\n class=\"mt-6 w-full\"\n id=\"submit-login\"\n [text]=\"'@auth:signin.submit' | translate | async\"\n (onClick)=\"handleLoginClick()\"\n [disabled]=\"isLoading$ | async\"\n [type]=\"'submit'\"\n >\n @if (isLoading$ | async) {\n <ax-loading></ax-loading>\n }\n </ax-button>\n @if (externalProviders.hasContent() || configs.signup?.enable) {\n <div class=\"heading heading-center !my-8\">\n <span>{{ '@auth:signin.or' | translate | async }}</span>\n </div>\n }\n <axm-login-external-providers\n #externalProviders\n ></axm-login-external-providers>\n </ax-form>\n @if (configs.signup?.enable) {\n <ax-button\n class=\"w-full mt-2\"\n id=\"register\"\n (onClick)=\"handleRegisterOnClick()\"\n text=\"{{ '@auth:register' | translate | async }}\"\n [color]=\"'default'\"\n >\n </ax-button>\n }\n </div>\n</ng-container>\n"],"names":["i4","i5","i6","i7","i8","i1","i2","i3","i9","i10"],"mappings":"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"}