@acorex/modules 21.0.0-next.7 → 21.0.0-next.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/business-core/README.md +44 -1
- package/document-management/index.d.ts +1 -2
- package/fesm2022/acorex-modules-application-management.mjs +1 -0
- package/fesm2022/acorex-modules-application-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-auth-acorex-modules-auth-D5jGjm6i.mjs → acorex-modules-auth-acorex-modules-auth-8XP9xX7L.mjs} +95 -51
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-8XP9xX7L.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-app-chooser.component-BL3Fmc7y.mjs → acorex-modules-auth-app-chooser.component-BvbLYIXA.mjs} +6 -6
- package/fesm2022/acorex-modules-auth-app-chooser.component-BvbLYIXA.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-login.module-D8-GN_Hx.mjs → acorex-modules-auth-login.module-DLWlieUn.mjs} +4 -4
- package/fesm2022/{acorex-modules-auth-login.module-D8-GN_Hx.mjs.map → acorex-modules-auth-login.module-DLWlieUn.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-master.layout-CgDrAbPS.mjs → acorex-modules-auth-master.layout-BzV1eUvM.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-master.layout-CgDrAbPS.mjs.map → acorex-modules-auth-master.layout-BzV1eUvM.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-lEMWnVJL.mjs → acorex-modules-auth-oauth-callback.component-CqaXMQdp.mjs} +5 -5
- package/fesm2022/{acorex-modules-auth-oauth-callback.component-lEMWnVJL.mjs.map → acorex-modules-auth-oauth-callback.component-CqaXMQdp.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-password.component-BQII_ltO.mjs → acorex-modules-auth-password.component-BR2qrph-.mjs} +9 -9
- package/fesm2022/{acorex-modules-auth-password.component-BQII_ltO.mjs.map → acorex-modules-auth-password.component-BR2qrph-.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth-password.component-DMmRFHgO.mjs +563 -0
- package/fesm2022/acorex-modules-auth-password.component-DMmRFHgO.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-routes-BGLnoGO4.mjs → acorex-modules-auth-routes-BRQJ6Mx_.mjs} +2 -2
- package/fesm2022/{acorex-modules-auth-routes-BGLnoGO4.mjs.map → acorex-modules-auth-routes-BRQJ6Mx_.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth-tenant-chooser.component-CptZLRwB.mjs +58 -0
- package/fesm2022/acorex-modules-auth-tenant-chooser.component-CptZLRwB.mjs.map +1 -0
- package/fesm2022/{acorex-modules-auth-two-factor-code.component-BmlUjtYC.mjs → acorex-modules-auth-two-factor-code.component-CvheFTK7.mjs} +6 -6
- package/fesm2022/{acorex-modules-auth-two-factor-code.component-BmlUjtYC.mjs.map → acorex-modules-auth-two-factor-code.component-CvheFTK7.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-two-factor.module-D1UjsoB8.mjs → acorex-modules-auth-two-factor.module-TGGOwEpP.mjs} +3 -3
- package/fesm2022/{acorex-modules-auth-two-factor.module-D1UjsoB8.mjs.map → acorex-modules-auth-two-factor.module-TGGOwEpP.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-auth-user-sessions.component-CIlGFT7H.mjs → acorex-modules-auth-user-sessions.component-C_JzCXUy.mjs} +6 -6
- package/fesm2022/{acorex-modules-auth-user-sessions.component-CIlGFT7H.mjs.map → acorex-modules-auth-user-sessions.component-C_JzCXUy.mjs.map} +1 -1
- package/fesm2022/acorex-modules-auth.mjs +1 -1
- package/fesm2022/{acorex-modules-business-core-business-status.entity-DE3JJYdY.mjs → acorex-modules-business-core-business-status.entity-BYUneIcN.mjs} +2 -2
- package/fesm2022/acorex-modules-business-core-business-status.entity-BYUneIcN.mjs.map +1 -0
- package/fesm2022/{acorex-modules-business-core-business-type.entity-_IwOWQVA.mjs → acorex-modules-business-core-business-type.entity-DEy8LvEV.mjs} +2 -2
- package/fesm2022/acorex-modules-business-core-business-type.entity-DEy8LvEV.mjs.map +1 -0
- package/fesm2022/{acorex-modules-business-core-industry.entity-bwgPAZDk.mjs → acorex-modules-business-core-industry.entity-CGNfgpMs.mjs} +2 -2
- package/fesm2022/acorex-modules-business-core-industry.entity-CGNfgpMs.mjs.map +1 -0
- package/fesm2022/{acorex-modules-business-core-manufacturer.entity-CDlQlBUD.mjs → acorex-modules-business-core-manufacturer.entity-DhyMx-nJ.mjs} +2 -1
- package/fesm2022/acorex-modules-business-core-manufacturer.entity-DhyMx-nJ.mjs.map +1 -0
- package/fesm2022/acorex-modules-business-core.mjs +4 -4
- package/fesm2022/{acorex-modules-customer-management-customer-segment.entity-CUBg2GZp.mjs → acorex-modules-customer-management-customer-segment.entity-CoYAU5g3.mjs} +2 -1
- package/fesm2022/acorex-modules-customer-management-customer-segment.entity-CoYAU5g3.mjs.map +1 -0
- package/fesm2022/{acorex-modules-customer-management-customer-type.entity-rmq6BeCF.mjs → acorex-modules-customer-management-customer-type.entity-pt4gpOGq.mjs} +2 -1
- package/fesm2022/acorex-modules-customer-management-customer-type.entity-pt4gpOGq.mjs.map +1 -0
- package/fesm2022/acorex-modules-customer-management.mjs +2 -2
- package/fesm2022/acorex-modules-document-management.mjs +5 -2
- package/fesm2022/acorex-modules-document-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-financial-core.mjs +7 -5
- package/fesm2022/acorex-modules-financial-core.mjs.map +1 -1
- package/fesm2022/acorex-modules-human-capital-management-approve-leave-request.command-DN2T2hBp.mjs +59 -0
- package/fesm2022/acorex-modules-human-capital-management-approve-leave-request.command-DN2T2hBp.mjs.map +1 -0
- package/fesm2022/acorex-modules-human-capital-management-cancel-leave-request.command-CYMo0I8p.mjs +59 -0
- package/fesm2022/acorex-modules-human-capital-management-cancel-leave-request.command-CYMo0I8p.mjs.map +1 -0
- package/fesm2022/{acorex-modules-human-capital-management-leave-request.entity-BDh7IX7_.mjs → acorex-modules-human-capital-management-leave-request.entity-Dm_IKrVw.mjs} +1 -2
- package/fesm2022/acorex-modules-human-capital-management-leave-request.entity-Dm_IKrVw.mjs.map +1 -0
- package/fesm2022/{acorex-modules-human-capital-management-leave-type.entity-DlCdAtaz.mjs → acorex-modules-human-capital-management-leave-type.entity-CY81Nohl.mjs} +11 -3
- package/fesm2022/acorex-modules-human-capital-management-leave-type.entity-CY81Nohl.mjs.map +1 -0
- package/fesm2022/acorex-modules-human-capital-management-reject-leave-request.command-1Bn0gaZi.mjs +62 -0
- package/fesm2022/acorex-modules-human-capital-management-reject-leave-request.command-1Bn0gaZi.mjs.map +1 -0
- package/fesm2022/acorex-modules-human-capital-management.mjs +114 -38
- package/fesm2022/acorex-modules-human-capital-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-learning-management-certificate-definition.entity-BVvSzl2b.mjs → acorex-modules-learning-management-certificate-definition.entity-27VKYxw1.mjs} +2 -2
- package/fesm2022/acorex-modules-learning-management-certificate-definition.entity-27VKYxw1.mjs.map +1 -0
- package/fesm2022/{acorex-modules-learning-management-course.entity-BYb3Mgyi.mjs → acorex-modules-learning-management-course.entity-BN8XHAPz.mjs} +2 -2
- package/fesm2022/acorex-modules-learning-management-course.entity-BN8XHAPz.mjs.map +1 -0
- package/fesm2022/{acorex-modules-learning-management-skill.entity-CK93JIPg.mjs → acorex-modules-learning-management-skill.entity-rfMFaOAJ.mjs} +2 -1
- package/fesm2022/acorex-modules-learning-management-skill.entity-rfMFaOAJ.mjs.map +1 -0
- package/fesm2022/{acorex-modules-learning-management-training-definition.entity-C5RVLTy7.mjs → acorex-modules-learning-management-training-definition.entity-NQqJ5avw.mjs} +2 -2
- package/fesm2022/acorex-modules-learning-management-training-definition.entity-NQqJ5avw.mjs.map +1 -0
- package/fesm2022/{acorex-modules-learning-management-training.entity-KfxtUHEK.mjs → acorex-modules-learning-management-training.entity-DHGSlVR3.mjs} +2 -2
- package/fesm2022/acorex-modules-learning-management-training.entity-DHGSlVR3.mjs.map +1 -0
- package/fesm2022/acorex-modules-learning-management.mjs +5 -5
- package/fesm2022/acorex-modules-notification-management.mjs +34 -16
- package/fesm2022/acorex-modules-notification-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-order-management.mjs +4 -0
- package/fesm2022/acorex-modules-order-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-organization-management-job-definition.entity-Cki_0gIY.mjs → acorex-modules-organization-management-job-definition.entity-s-TfP412.mjs} +2 -2
- package/fesm2022/acorex-modules-organization-management-job-definition.entity-s-TfP412.mjs.map +1 -0
- package/fesm2022/{acorex-modules-organization-management-position.entity-m7QrOTgN.mjs → acorex-modules-organization-management-position.entity-vbmjSfyb.mjs} +2 -2
- package/fesm2022/acorex-modules-organization-management-position.entity-vbmjSfyb.mjs.map +1 -0
- package/fesm2022/acorex-modules-organization-management.mjs +2 -2
- package/fesm2022/{acorex-modules-person-management-person.entity-DWfnmtVe.mjs → acorex-modules-person-management-person.entity-BnliZw-K.mjs} +35 -33
- package/fesm2022/acorex-modules-person-management-person.entity-BnliZw-K.mjs.map +1 -0
- package/fesm2022/acorex-modules-person-management.mjs +1 -1
- package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-BOo-XED8.mjs → acorex-modules-platform-management-acorex-modules-platform-management-CAntNN8Z.mjs} +4 -2
- package/fesm2022/{acorex-modules-platform-management-acorex-modules-platform-management-BOo-XED8.mjs.map → acorex-modules-platform-management-acorex-modules-platform-management-CAntNN8Z.mjs.map} +1 -1
- package/fesm2022/{acorex-modules-platform-management-menu-list.component-BtQ0O4sx.mjs → acorex-modules-platform-management-menu-list.component-CWutHAb3.mjs} +2 -2
- package/fesm2022/{acorex-modules-platform-management-menu-list.component-BtQ0O4sx.mjs.map → acorex-modules-platform-management-menu-list.component-CWutHAb3.mjs.map} +1 -1
- package/fesm2022/acorex-modules-platform-management.mjs +1 -1
- package/fesm2022/{acorex-modules-product-catalog-brand.entity-DIv0bsiY.mjs → acorex-modules-product-catalog-brand.entity-C8VOfwF0.mjs} +2 -1
- package/fesm2022/acorex-modules-product-catalog-brand.entity-C8VOfwF0.mjs.map +1 -0
- package/fesm2022/{acorex-modules-product-catalog-product-sku.entity-CQw4VxjA.mjs → acorex-modules-product-catalog-product-sku.entity-Cxif--1E.mjs} +2 -1
- package/fesm2022/acorex-modules-product-catalog-product-sku.entity-Cxif--1E.mjs.map +1 -0
- package/fesm2022/{acorex-modules-product-catalog-product.entity-Cqye5OFr.mjs → acorex-modules-product-catalog-product.entity--aXivZUd.mjs} +2 -1
- package/fesm2022/acorex-modules-product-catalog-product.entity--aXivZUd.mjs.map +1 -0
- package/fesm2022/acorex-modules-product-catalog.mjs +3 -3
- package/fesm2022/acorex-modules-project-management.mjs +30 -1
- package/fesm2022/acorex-modules-project-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-report-management-report-runner-root-page.component-Cp5QCIll.mjs → acorex-modules-report-management-report-runner-root-page.component-DEX4VgHX.mjs} +9 -9
- package/fesm2022/acorex-modules-report-management-report-runner-root-page.component-DEX4VgHX.mjs.map +1 -0
- package/fesm2022/acorex-modules-report-management.mjs +1 -1
- package/fesm2022/acorex-modules-subscription-management.mjs +3 -0
- package/fesm2022/acorex-modules-subscription-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-supplier-management.mjs +1 -0
- package/fesm2022/acorex-modules-supplier-management.mjs.map +1 -1
- package/fesm2022/{acorex-modules-task-management-task-board.page-Cm8wJD-y.mjs → acorex-modules-task-management-task-board.page-6D76WpRB.mjs} +468 -42
- package/fesm2022/acorex-modules-task-management-task-board.page-6D76WpRB.mjs.map +1 -0
- package/fesm2022/acorex-modules-task-management.mjs +9 -3
- package/fesm2022/acorex-modules-task-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-tenant-management.mjs +2 -0
- package/fesm2022/acorex-modules-tenant-management.mjs.map +1 -1
- package/fesm2022/acorex-modules-workflow-management.mjs +1692 -28
- package/fesm2022/acorex-modules-workflow-management.mjs.map +1 -1
- package/human-capital-management/index.d.ts +1 -0
- package/package.json +2 -2
- package/task-management/index.d.ts +1 -1
- package/workflow-management/index.d.ts +446 -11
- package/fesm2022/acorex-modules-auth-acorex-modules-auth-D5jGjm6i.mjs.map +0 -1
- package/fesm2022/acorex-modules-auth-app-chooser.component-BL3Fmc7y.mjs.map +0 -1
- package/fesm2022/acorex-modules-auth-password.component-DKG8o8k8.mjs +0 -226
- package/fesm2022/acorex-modules-auth-password.component-DKG8o8k8.mjs.map +0 -1
- package/fesm2022/acorex-modules-auth-tenant-chooser.component-DNDhBKDp.mjs +0 -109
- package/fesm2022/acorex-modules-auth-tenant-chooser.component-DNDhBKDp.mjs.map +0 -1
- package/fesm2022/acorex-modules-business-core-business-status.entity-DE3JJYdY.mjs.map +0 -1
- package/fesm2022/acorex-modules-business-core-business-type.entity-_IwOWQVA.mjs.map +0 -1
- package/fesm2022/acorex-modules-business-core-industry.entity-bwgPAZDk.mjs.map +0 -1
- package/fesm2022/acorex-modules-business-core-manufacturer.entity-CDlQlBUD.mjs.map +0 -1
- package/fesm2022/acorex-modules-customer-management-customer-segment.entity-CUBg2GZp.mjs.map +0 -1
- package/fesm2022/acorex-modules-customer-management-customer-type.entity-rmq6BeCF.mjs.map +0 -1
- package/fesm2022/acorex-modules-human-capital-management-leave-request.entity-BDh7IX7_.mjs.map +0 -1
- package/fesm2022/acorex-modules-human-capital-management-leave-type.entity-DlCdAtaz.mjs.map +0 -1
- package/fesm2022/acorex-modules-learning-management-certificate-definition.entity-BVvSzl2b.mjs.map +0 -1
- package/fesm2022/acorex-modules-learning-management-course.entity-BYb3Mgyi.mjs.map +0 -1
- package/fesm2022/acorex-modules-learning-management-skill.entity-CK93JIPg.mjs.map +0 -1
- package/fesm2022/acorex-modules-learning-management-training-definition.entity-C5RVLTy7.mjs.map +0 -1
- package/fesm2022/acorex-modules-learning-management-training.entity-KfxtUHEK.mjs.map +0 -1
- package/fesm2022/acorex-modules-organization-management-job-definition.entity-Cki_0gIY.mjs.map +0 -1
- package/fesm2022/acorex-modules-organization-management-position.entity-m7QrOTgN.mjs.map +0 -1
- package/fesm2022/acorex-modules-person-management-person.entity-DWfnmtVe.mjs.map +0 -1
- package/fesm2022/acorex-modules-product-catalog-brand.entity-DIv0bsiY.mjs.map +0 -1
- package/fesm2022/acorex-modules-product-catalog-product-sku.entity-CQw4VxjA.mjs.map +0 -1
- package/fesm2022/acorex-modules-product-catalog-product.entity-Cqye5OFr.mjs.map +0 -1
- package/fesm2022/acorex-modules-report-management-report-runner-root-page.component-Cp5QCIll.mjs.map +0 -1
- package/fesm2022/acorex-modules-task-management-task-board.page-Cm8wJD-y.mjs.map +0 -1
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
import * as i1 from '@acorex/components/button';
|
|
2
|
+
import { AXButtonModule } from '@acorex/components/button';
|
|
3
|
+
import * as i9 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 i6 from '@acorex/components/loading';
|
|
13
|
+
import { AXLoadingModule } from '@acorex/components/loading';
|
|
14
|
+
import * as i5 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 i1$2 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/auth';
|
|
28
|
+
import { AXPHomePageService } from '@acorex/platform/common';
|
|
29
|
+
import * as i2$2 from '@angular/forms';
|
|
30
|
+
import { FormsModule } from '@angular/forms';
|
|
31
|
+
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
|
32
|
+
import { A as AXM_AUTH_CONFIG_TOKEN, a as AXMAuthenticationTypes } from './acorex-modules-auth-acorex-modules-auth-8XP9xX7L.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" }] : []));
|
|
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: "20.3.12", ngImport: i0, type: AXPDefaultChallengeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
62
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", type: AXPDefaultChallengeComponent, isStandalone: true, selector: "axp-default-challenge", usesInheritance: true, ngImport: i0, template: `
|
|
63
|
+
<div class="ax-flex ax-flex-col ax-gap-3 ax-p-4 ax-border ax-rounded-md ax-border-warning-300 ax-bg-warning-50">
|
|
64
|
+
<!-- Challenge Image -->
|
|
65
|
+
<div class="ax-flex ax-items-center ax-justify-center ax-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="ax-h-12 ax-border ax-rounded"
|
|
72
|
+
/>
|
|
73
|
+
} @else if (challenge.contentType === 'image-url') {
|
|
74
|
+
<img [src]="challenge.content" alt="Security Challenge" class="ax-h-12 ax-border ax-rounded" />
|
|
75
|
+
} @else {
|
|
76
|
+
<span class="ax-font-mono ax-text-lg ax-p-2 ax-border ax-rounded ax-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", "mask-options", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { 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: i6.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: i1$2.AsyncPipe, name: "async" }] }); }
|
|
113
|
+
}
|
|
114
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", 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="ax-flex ax-flex-col ax-gap-3 ax-p-4 ax-border ax-rounded-md ax-border-warning-300 ax-bg-warning-50">
|
|
132
|
+
<!-- Challenge Image -->
|
|
133
|
+
<div class="ax-flex ax-items-center ax-justify-center ax-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="ax-h-12 ax-border ax-rounded"
|
|
140
|
+
/>
|
|
141
|
+
} @else if (challenge.contentType === 'image-url') {
|
|
142
|
+
<img [src]="challenge.content" alt="Security Challenge" class="ax-h-12 ax-border ax-rounded" />
|
|
143
|
+
} @else {
|
|
144
|
+
<span class="ax-font-mono ax-text-lg ax-p-2 ax-border ax-rounded ax-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
|
+
];
|
|
200
|
+
//#endregion
|
|
201
|
+
class AXPLoginPasswordComponent {
|
|
202
|
+
constructor() {
|
|
203
|
+
//#region ---- Services & Dependencies ----
|
|
204
|
+
this.configs = inject(AXM_AUTH_CONFIG_TOKEN);
|
|
205
|
+
this.dialogService = inject(AXDialogService);
|
|
206
|
+
this.sessionService = inject(AXPSessionService);
|
|
207
|
+
this.activateRoute = inject(ActivatedRoute);
|
|
208
|
+
this.homePageService = inject(AXPHomePageService);
|
|
209
|
+
this.toastService = inject(AXToastService);
|
|
210
|
+
this.router = inject(Router);
|
|
211
|
+
this.injector = inject(Injector);
|
|
212
|
+
/** Optional challenge provider - injected only if configured */
|
|
213
|
+
this.challengeProvider = inject(AXP_LOGIN_CHALLENGE_PROVIDER, { optional: true });
|
|
214
|
+
/** Value of the first input field (username/email) */
|
|
215
|
+
this.v1 = '';
|
|
216
|
+
/** Value of the second input field (password) */
|
|
217
|
+
this.v2 = '';
|
|
218
|
+
/** Whether to keep the user logged in */
|
|
219
|
+
this.isKeepLogin = false;
|
|
220
|
+
/** Current challenge data from the server */
|
|
221
|
+
this.challengeData = signal(null, ...(ngDevMode ? [{ debugName: "challengeData" }] : []));
|
|
222
|
+
/** User's response to the challenge (e.g., CAPTCHA text) */
|
|
223
|
+
this.challengeResponse = signal('', ...(ngDevMode ? [{ debugName: "challengeResponse" }] : []));
|
|
224
|
+
/** Loading state for challenge refresh */
|
|
225
|
+
this.isChallengeLoading = signal(false, ...(ngDevMode ? [{ debugName: "isChallengeLoading" }] : []));
|
|
226
|
+
/**
|
|
227
|
+
* Effect to render the challenge component when challenge data changes
|
|
228
|
+
*/
|
|
229
|
+
this.challengeRenderEffect = effect(() => {
|
|
230
|
+
const data = this.challengeData();
|
|
231
|
+
const isLoading = this.isChallengeLoading();
|
|
232
|
+
// Wait for next tick to ensure ViewContainerRef is available
|
|
233
|
+
setTimeout(() => {
|
|
234
|
+
if (data && this.challengeContainerRef) {
|
|
235
|
+
this.renderChallengeComponent(data, isLoading);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
this.destroyChallengeComponent();
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}, ...(ngDevMode ? [{ debugName: "challengeRenderEffect" }] : []));
|
|
242
|
+
//#endregion
|
|
243
|
+
//#region ---- Loading & Status State ----
|
|
244
|
+
this.isLoading$ = new BehaviorSubject(false);
|
|
245
|
+
this.isExternalLoading$ = new BehaviorSubject(false);
|
|
246
|
+
this.submitText = 'signin.submit';
|
|
247
|
+
}
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region ---- Computed Properties ----
|
|
250
|
+
/** Check if external providers (Google, Apple, etc.) are configured */
|
|
251
|
+
get hasExternalProviders() {
|
|
252
|
+
return !!(this.configs?.externalProviders && Object.keys(this.configs.externalProviders).length > 0);
|
|
253
|
+
}
|
|
254
|
+
/** Check if a challenge is currently active and should be displayed */
|
|
255
|
+
get hasChallengeActive() {
|
|
256
|
+
return this.challengeData() !== null;
|
|
257
|
+
}
|
|
258
|
+
//#endregion
|
|
259
|
+
//#region ---- Lifecycle Methods ----
|
|
260
|
+
ngOnInit() {
|
|
261
|
+
this.l2 = 'password';
|
|
262
|
+
switch (this.configs.type) {
|
|
263
|
+
case AXMAuthenticationTypes.EmailPassword:
|
|
264
|
+
this.l1 = 'email';
|
|
265
|
+
break;
|
|
266
|
+
case AXMAuthenticationTypes.MobilePassword:
|
|
267
|
+
this.l1 = 'mobile';
|
|
268
|
+
break;
|
|
269
|
+
case AXMAuthenticationTypes.UsernameEmailPassword:
|
|
270
|
+
this.l1 = 'username-email';
|
|
271
|
+
break;
|
|
272
|
+
case AXMAuthenticationTypes.UsernamePassword:
|
|
273
|
+
default:
|
|
274
|
+
this.l1 = 'username';
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//#endregion
|
|
278
|
+
//#region ---- Navigation Handlers ----
|
|
279
|
+
handleForgotOnClick() {
|
|
280
|
+
this.router.navigate(['/auth/forgot']);
|
|
281
|
+
}
|
|
282
|
+
handleRegisterOnClick() {
|
|
283
|
+
this.router.navigate([this.configs.signup?.url || '/auth/register']);
|
|
284
|
+
}
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region ---- Login Handlers ----
|
|
287
|
+
handleLoginClick() {
|
|
288
|
+
this.sessionService.setStrategy(this.configs.defaultStrategyName || 'user-pass');
|
|
289
|
+
const redirectUrl = this.activateRoute.snapshot.queryParams['redirectUrl'];
|
|
290
|
+
this.form.validate().then(async (form) => {
|
|
291
|
+
if (form.result) {
|
|
292
|
+
this.isLoading$.next(true);
|
|
293
|
+
this.submitText = 'processing';
|
|
294
|
+
try {
|
|
295
|
+
const strategy = this.sessionService.getSessionData()?.strategy;
|
|
296
|
+
if (!strategy) {
|
|
297
|
+
throw new Error('Strategy not found');
|
|
298
|
+
}
|
|
299
|
+
// Build credentials object with challenge data if active
|
|
300
|
+
const currentChallenge = this.challengeData();
|
|
301
|
+
const credentials = {
|
|
302
|
+
strategy: strategy,
|
|
303
|
+
username: this.v1,
|
|
304
|
+
password: this.v2,
|
|
305
|
+
...(currentChallenge && {
|
|
306
|
+
challengeId: currentChallenge.id,
|
|
307
|
+
challengeResponse: this.challengeResponse(),
|
|
308
|
+
}),
|
|
309
|
+
};
|
|
310
|
+
await this.sessionService.signin(credentials);
|
|
311
|
+
await this.sessionService.signInComplete();
|
|
312
|
+
// Check authentication status before navigation
|
|
313
|
+
const isAuthenticated = await firstValueFrom(this.sessionService.isAuthenticated$);
|
|
314
|
+
if (!isAuthenticated) {
|
|
315
|
+
throw new Error('Authentication failed after signin');
|
|
316
|
+
}
|
|
317
|
+
// Clear challenge state on successful login
|
|
318
|
+
this.clearChallengeState();
|
|
319
|
+
const currentApplication = await firstValueFrom(this.sessionService.application$);
|
|
320
|
+
if (!currentApplication) {
|
|
321
|
+
if (this.sessionService.tenant?.id == null) {
|
|
322
|
+
this.router.navigate(['/auth/account/tenant-chooser']);
|
|
323
|
+
}
|
|
324
|
+
else if (this.sessionService.application?.id == null) {
|
|
325
|
+
this.router.navigate(['/auth/account/app-chooser']);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
else if (redirectUrl) {
|
|
329
|
+
this.router.navigate([redirectUrl]);
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
await this.homePageService.navigateTo();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
catch (error) {
|
|
336
|
+
await this.handleLoginError(error);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Handles login errors and checks if a challenge is required
|
|
343
|
+
*/
|
|
344
|
+
async handleLoginError(error) {
|
|
345
|
+
// Check if challenge provider wants to handle this error
|
|
346
|
+
if (this.challengeProvider) {
|
|
347
|
+
const checkResult = this.challengeProvider.checkResponse(error);
|
|
348
|
+
if (checkResult?.required) {
|
|
349
|
+
try {
|
|
350
|
+
// Fetch challenge from server
|
|
351
|
+
const challenge = await this.challengeProvider.getChallenge(checkResult.serverData);
|
|
352
|
+
this.challengeData.set(challenge);
|
|
353
|
+
this.challengeResponse.set('');
|
|
354
|
+
// Show challenge message if provided
|
|
355
|
+
if (checkResult.message) {
|
|
356
|
+
this.toastService.show({
|
|
357
|
+
color: 'warning',
|
|
358
|
+
content: checkResult.message,
|
|
359
|
+
timeOut: 5000,
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
this.submitText = 'signin.submit';
|
|
363
|
+
this.isLoading$.next(false);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
catch (challengeError) {
|
|
367
|
+
console.error('Failed to fetch challenge:', challengeError);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// Default error handling
|
|
372
|
+
this.showLoginError(error);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Displays the login error message to the user
|
|
376
|
+
*/
|
|
377
|
+
showLoginError(error) {
|
|
378
|
+
let errorMsg = 'An error occurred during sign in.';
|
|
379
|
+
if (error && typeof error === 'object') {
|
|
380
|
+
const err = error;
|
|
381
|
+
const errObj = err['error'];
|
|
382
|
+
errorMsg =
|
|
383
|
+
errObj?.['error_description'] ||
|
|
384
|
+
errObj?.['error'] ||
|
|
385
|
+
err['message'] ||
|
|
386
|
+
errorMsg;
|
|
387
|
+
if (typeof errorMsg === 'object') {
|
|
388
|
+
const msgObj = errorMsg;
|
|
389
|
+
errorMsg = msgObj['message'] || msgObj['error_description'] || JSON.stringify(errorMsg);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
this.toastService.show({
|
|
393
|
+
color: 'danger',
|
|
394
|
+
content: errorMsg,
|
|
395
|
+
timeOut: 5000,
|
|
396
|
+
});
|
|
397
|
+
console.error('Login error:', error);
|
|
398
|
+
this.submitText = 'signin.submit';
|
|
399
|
+
this.v2 = null;
|
|
400
|
+
this.isLoading$.next(false);
|
|
401
|
+
}
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region ---- Challenge Handlers ----
|
|
404
|
+
/**
|
|
405
|
+
* Gets the challenge component type from provider or uses default
|
|
406
|
+
*/
|
|
407
|
+
getChallengeComponentType() {
|
|
408
|
+
return this.challengeProvider?.getChallengeComponent() ?? AXPDefaultChallengeComponent;
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Renders the challenge component dynamically
|
|
412
|
+
*/
|
|
413
|
+
renderChallengeComponent(data, isLoading) {
|
|
414
|
+
if (!this.challengeContainerRef)
|
|
415
|
+
return;
|
|
416
|
+
// If component already exists, just update inputs
|
|
417
|
+
if (this.challengeComponentRef) {
|
|
418
|
+
this.updateChallengeComponentInputs(data, isLoading);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
// Clear container and create new component
|
|
422
|
+
this.challengeContainerRef.clear();
|
|
423
|
+
const componentType = this.getChallengeComponentType();
|
|
424
|
+
this.challengeComponentRef = this.challengeContainerRef.createComponent(componentType);
|
|
425
|
+
// Set inputs
|
|
426
|
+
this.updateChallengeComponentInputs(data, isLoading);
|
|
427
|
+
// Subscribe to outputs
|
|
428
|
+
const instance = this.challengeComponentRef.instance;
|
|
429
|
+
instance.responseChange.subscribe((response) => {
|
|
430
|
+
this.challengeResponse.set(response);
|
|
431
|
+
});
|
|
432
|
+
instance.refreshRequest.subscribe(() => {
|
|
433
|
+
this.handleRefreshChallenge();
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Updates the inputs of the challenge component
|
|
438
|
+
*/
|
|
439
|
+
updateChallengeComponentInputs(data, isLoading) {
|
|
440
|
+
if (!this.challengeComponentRef)
|
|
441
|
+
return;
|
|
442
|
+
this.challengeComponentRef.setInput('challengeData', data);
|
|
443
|
+
this.challengeComponentRef.setInput('isLoading', isLoading);
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Destroys the challenge component
|
|
447
|
+
*/
|
|
448
|
+
destroyChallengeComponent() {
|
|
449
|
+
if (this.challengeComponentRef) {
|
|
450
|
+
this.challengeComponentRef.destroy();
|
|
451
|
+
this.challengeComponentRef = undefined;
|
|
452
|
+
}
|
|
453
|
+
if (this.challengeContainerRef) {
|
|
454
|
+
this.challengeContainerRef.clear();
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Refreshes the challenge (e.g., user clicks "new image" button)
|
|
459
|
+
*/
|
|
460
|
+
async handleRefreshChallenge() {
|
|
461
|
+
if (!this.challengeProvider)
|
|
462
|
+
return;
|
|
463
|
+
this.isChallengeLoading.set(true);
|
|
464
|
+
try {
|
|
465
|
+
const newChallenge = await this.challengeProvider.refreshChallenge();
|
|
466
|
+
this.challengeData.set(newChallenge);
|
|
467
|
+
this.challengeResponse.set('');
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
console.error('Failed to refresh challenge:', error);
|
|
471
|
+
this.toastService.show({
|
|
472
|
+
color: 'danger',
|
|
473
|
+
content: 'Failed to load new challenge. Please try again.',
|
|
474
|
+
timeOut: 3000,
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
finally {
|
|
478
|
+
this.isChallengeLoading.set(false);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Clears the challenge state (after successful login or manual clear)
|
|
483
|
+
*/
|
|
484
|
+
clearChallengeState() {
|
|
485
|
+
this.challengeData.set(null);
|
|
486
|
+
this.challengeResponse.set('');
|
|
487
|
+
this.destroyChallengeComponent();
|
|
488
|
+
}
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region ---- External Sign-In Handlers ----
|
|
491
|
+
async handleExternalSignIn(provider) {
|
|
492
|
+
this.sessionService.setStrategy(provider);
|
|
493
|
+
try {
|
|
494
|
+
this.isExternalLoading$.next(true);
|
|
495
|
+
// Get provider configuration (optional, for validation)
|
|
496
|
+
const providerConfig = this.configs?.externalProviders?.[provider];
|
|
497
|
+
if (!providerConfig) {
|
|
498
|
+
throw new Error(`Provider '${provider}' is not configured`);
|
|
499
|
+
}
|
|
500
|
+
await this.sessionService.signin({ strategy: provider });
|
|
501
|
+
}
|
|
502
|
+
catch (error) {
|
|
503
|
+
console.error(`${provider} sign-in error:`, error);
|
|
504
|
+
}
|
|
505
|
+
finally {
|
|
506
|
+
this.isExternalLoading$.next(false);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
//#endregion
|
|
510
|
+
//#region ---- PKCE Utilities ----
|
|
511
|
+
/**
|
|
512
|
+
* Generates a code challenge for PKCE (Proof Key for Code Exchange)
|
|
513
|
+
*/
|
|
514
|
+
async generateCodeChallenge(codeVerifier) {
|
|
515
|
+
const hash = await this.sha256(codeVerifier);
|
|
516
|
+
return this.base64UrlEncode(hash);
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Generates a random string for code verifier
|
|
520
|
+
*/
|
|
521
|
+
generateRandomString(length) {
|
|
522
|
+
const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~';
|
|
523
|
+
let text = '';
|
|
524
|
+
for (let i = 0; i < length; i++) {
|
|
525
|
+
text += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
526
|
+
}
|
|
527
|
+
return text;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Creates SHA256 hash of the input string using Web Crypto API
|
|
531
|
+
*/
|
|
532
|
+
async sha256(str) {
|
|
533
|
+
const encoder = new TextEncoder();
|
|
534
|
+
const data = encoder.encode(str);
|
|
535
|
+
return await crypto.subtle.digest('SHA-256', data);
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Base64url encodes an ArrayBuffer
|
|
539
|
+
*/
|
|
540
|
+
base64UrlEncode(buffer) {
|
|
541
|
+
const bytes = new Uint8Array(buffer);
|
|
542
|
+
let binary = '';
|
|
543
|
+
for (let i = 0; i < bytes.byteLength; i++) {
|
|
544
|
+
binary += String.fromCharCode(bytes[i]);
|
|
545
|
+
}
|
|
546
|
+
return btoa(binary).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
|
|
547
|
+
}
|
|
548
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLoginPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
549
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.12", 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=\"ax-text-center ax-mb-4\">\n <h1 class=\"ax-font-bold ax-text-xl ax-mb-2\">\n {{ '@auth:signin.title' | translate | async }}\n </h1>\n <p class=\"ax-text-base ax-text-neutral-600\">\n {{ '@auth:signin.hint' | translate | async }}\n </p>\n </div>\n <div class=\"ax-w-80 lg:ax-w-96\">\n <ax-form>\n <div class=\"ax-flex ax-flex-col ax-gap-6\">\n <ax-form-field>\n <ax-label>{{ '@auth:username-email' | translate | async }}</ax-label>\n <ax-text-box [name]=\"'username'\" id=\"username\" [autoComplete]=\"'username'\" [(value)]=\"v1\">\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 [name]=\"'password'\" id=\"password\" [autoComplete]=\"'current-password'\" [(value)]=\"v2\">\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=\"ax-flex ax-justify-between ax-items-center\">\n <ax-check-box [(ngModel)]=\"isKeepLogin\">\n <ax-label class=\"ax-mb-0\">{{ '@auth:signin.remember' | translate | async }}</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=\"ax-mt-6 ax-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 (hasExternalProviders || configs.signup?.enable) {\n <div class=\"ax-heading ax-heading-center !ax-my-8\">\n <span>{{ '@auth:signin.or' | translate | async }}</span>\n </div>\n }\n <div class=\"ax-flex ax-flex-col ax-gap-2 lg:ax-flex-row ax-justify-between ax-mt-6\">\n @if (configs.externalProviders?.['google']) {\n <ax-button\n class=\"ax-w-full ax-mt-2\"\n text=\"{{ '@auth:authentication.with-google' | translate | async }}\"\n [color]=\"'default'\"\n id=\"google\"\n (onClick)=\"handleExternalSignIn('google')\"\n [disabled]=\"isExternalLoading$ | async\"\n >\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-brands fa-google fa-lg ax-text-danger-500\"></i>\n </ax-icon>\n </ax-prefix>\n <ax-loading *ngIf=\"isExternalLoading$ | async\"></ax-loading>\n </ax-button>\n }\n @if (configs.externalProviders?.['apple']) {\n <ax-button\n text=\"{{ '@auth:authentication.with-apple' | translate | async }}\"\n [color]=\"'default'\"\n id=\"apple\"\n (onClick)=\"handleExternalSignIn('apple')\"\n [disabled]=\"isExternalLoading$ | async\"\n >\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-brands fa-apple fa-xl\"></i>\n </ax-icon>\n </ax-prefix>\n <ax-loading *ngIf=\"isExternalLoading$ | async\"></ax-loading>\n </ax-button>\n }\n @if (configs.externalProviders?.['microsoft']) {\n <ax-button\n text=\"{{ '@auth:authentication.with-microsoft' | translate | async }}\"\n [color]=\"'default'\"\n id=\"microsoft\"\n (onClick)=\"handleExternalSignIn('microsoft')\"\n [disabled]=\"isExternalLoading$ | async\"\n >\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-brands fa-microsoft fa-lg text-blue-500\"></i>\n </ax-icon>\n </ax-prefix>\n <ax-loading *ngIf=\"isExternalLoading$ | async\"></ax-loading>\n </ax-button>\n }\n </div>\n </ax-form>\n @if (configs.signup?.enable) {\n <ax-button\n class=\"ax-w-full ax-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: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$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"], 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", "mask-options", "class"], outputs: ["onBlur", "onFocus", "valueChange", "stateChange", "onValueChanged", "readonlyChange", "disabledChange", "onKeyDown", "onKeyUp", "onKeyPress"] }, { kind: "ngmodule", type: AXPasswordBoxModule }, { kind: "component", type: i5.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: "component", type: i3$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXCheckBoxModule }, { kind: "component", type: i9.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: i6.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: RouterModule }, { kind: "ngmodule", type: AXValidationModule }, { kind: "pipe", type: i1$2.AsyncPipe, name: "async" }, { kind: "pipe", type: i2$1.AXTranslatorPipe, name: "translate" }] }); }
|
|
550
|
+
}
|
|
551
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.12", ngImport: i0, type: AXPLoginPasswordComponent, decorators: [{
|
|
552
|
+
type: Component,
|
|
553
|
+
args: [{ imports: [...MODULES], template: "<ng-container *translate=\"let t\">\n <div class=\"ax-text-center ax-mb-4\">\n <h1 class=\"ax-font-bold ax-text-xl ax-mb-2\">\n {{ '@auth:signin.title' | translate | async }}\n </h1>\n <p class=\"ax-text-base ax-text-neutral-600\">\n {{ '@auth:signin.hint' | translate | async }}\n </p>\n </div>\n <div class=\"ax-w-80 lg:ax-w-96\">\n <ax-form>\n <div class=\"ax-flex ax-flex-col ax-gap-6\">\n <ax-form-field>\n <ax-label>{{ '@auth:username-email' | translate | async }}</ax-label>\n <ax-text-box [name]=\"'username'\" id=\"username\" [autoComplete]=\"'username'\" [(value)]=\"v1\">\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 [name]=\"'password'\" id=\"password\" [autoComplete]=\"'current-password'\" [(value)]=\"v2\">\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=\"ax-flex ax-justify-between ax-items-center\">\n <ax-check-box [(ngModel)]=\"isKeepLogin\">\n <ax-label class=\"ax-mb-0\">{{ '@auth:signin.remember' | translate | async }}</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=\"ax-mt-6 ax-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 (hasExternalProviders || configs.signup?.enable) {\n <div class=\"ax-heading ax-heading-center !ax-my-8\">\n <span>{{ '@auth:signin.or' | translate | async }}</span>\n </div>\n }\n <div class=\"ax-flex ax-flex-col ax-gap-2 lg:ax-flex-row ax-justify-between ax-mt-6\">\n @if (configs.externalProviders?.['google']) {\n <ax-button\n class=\"ax-w-full ax-mt-2\"\n text=\"{{ '@auth:authentication.with-google' | translate | async }}\"\n [color]=\"'default'\"\n id=\"google\"\n (onClick)=\"handleExternalSignIn('google')\"\n [disabled]=\"isExternalLoading$ | async\"\n >\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-brands fa-google fa-lg ax-text-danger-500\"></i>\n </ax-icon>\n </ax-prefix>\n <ax-loading *ngIf=\"isExternalLoading$ | async\"></ax-loading>\n </ax-button>\n }\n @if (configs.externalProviders?.['apple']) {\n <ax-button\n text=\"{{ '@auth:authentication.with-apple' | translate | async }}\"\n [color]=\"'default'\"\n id=\"apple\"\n (onClick)=\"handleExternalSignIn('apple')\"\n [disabled]=\"isExternalLoading$ | async\"\n >\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-brands fa-apple fa-xl\"></i>\n </ax-icon>\n </ax-prefix>\n <ax-loading *ngIf=\"isExternalLoading$ | async\"></ax-loading>\n </ax-button>\n }\n @if (configs.externalProviders?.['microsoft']) {\n <ax-button\n text=\"{{ '@auth:authentication.with-microsoft' | translate | async }}\"\n [color]=\"'default'\"\n id=\"microsoft\"\n (onClick)=\"handleExternalSignIn('microsoft')\"\n [disabled]=\"isExternalLoading$ | async\"\n >\n <ax-prefix>\n <ax-icon>\n <i class=\"fa-brands fa-microsoft fa-lg text-blue-500\"></i>\n </ax-icon>\n </ax-prefix>\n <ax-loading *ngIf=\"isExternalLoading$ | async\"></ax-loading>\n </ax-button>\n }\n </div>\n </ax-form>\n @if (configs.signup?.enable) {\n <ax-button\n class=\"ax-w-full ax-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" }]
|
|
554
|
+
}], propDecorators: { form: [{
|
|
555
|
+
type: ViewChild,
|
|
556
|
+
args: [AXFormComponent]
|
|
557
|
+
}], challengeContainerRef: [{
|
|
558
|
+
type: ViewChild,
|
|
559
|
+
args: ['challengeContainer', { read: ViewContainerRef }]
|
|
560
|
+
}] } });
|
|
561
|
+
|
|
562
|
+
export { AXPLoginPasswordComponent };
|
|
563
|
+
//# sourceMappingURL=acorex-modules-auth-password.component-DMmRFHgO.mjs.map
|