@acorex-platform/module-auth-client 0.0.59 → 0.0.61
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/fesm2022/{acorex-platform-module-auth-client-accept-invitation.component-Ct28GG3a.mjs → acorex-platform-module-auth-client-accept-invitation.component-Bq49K_8F.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-accept-invitation.component-Ct28GG3a.mjs.map → acorex-platform-module-auth-client-accept-invitation.component-Bq49K_8F.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-acorex-platform-module-auth-client-CQEt9bXJ.mjs → acorex-platform-module-auth-client-acorex-platform-module-auth-client-DINrCCAx.mjs} +75 -51
- package/fesm2022/acorex-platform-module-auth-client-acorex-platform-module-auth-client-DINrCCAx.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-auth-client-app-chooser.component-SUwPTueG.mjs → acorex-platform-module-auth-client-app-chooser.component-C1fUi_Mp.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-app-chooser.component-SUwPTueG.mjs.map → acorex-platform-module-auth-client-app-chooser.component-C1fUi_Mp.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-change-password.command-DRwzhNlO.mjs → acorex-platform-module-auth-client-change-password.command-UvBqwF9V.mjs} +48 -23
- package/fesm2022/acorex-platform-module-auth-client-change-password.command-UvBqwF9V.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-auth-client-change-photo.command-C1Fm_MdA.mjs → acorex-platform-module-auth-client-change-photo.command-2e7ZjiEf.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-change-photo.command-C1Fm_MdA.mjs.map → acorex-platform-module-auth-client-change-photo.command-2e7ZjiEf.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-get-user-activity.query-CLdmidQb.mjs → acorex-platform-module-auth-client-get-user-activity.query-BGOYJ4FC.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-get-user-activity.query-CLdmidQb.mjs.map → acorex-platform-module-auth-client-get-user-activity.query-BGOYJ4FC.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-lock-screen.command-CHbe_N-Z.mjs → acorex-platform-module-auth-client-lock-screen.command-BOKKr6WW.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-lock-screen.command-CHbe_N-Z.mjs.map → acorex-platform-module-auth-client-lock-screen.command-BOKKr6WW.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-login.module-BM3L_d8i.mjs → acorex-platform-module-auth-client-login.module-gi6wea8m.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-login.module-BM3L_d8i.mjs.map → acorex-platform-module-auth-client-login.module-gi6wea8m.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-manage-two-factor.command-BOM6_896.mjs → acorex-platform-module-auth-client-manage-two-factor.command-DRsNZWZF.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-manage-two-factor.command-BOM6_896.mjs.map → acorex-platform-module-auth-client-manage-two-factor.command-DRsNZWZF.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-oauth-callback.component-BgUSFibH.mjs → acorex-platform-module-auth-client-oauth-callback.component-DLrIDQXn.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-oauth-callback.component-BgUSFibH.mjs.map → acorex-platform-module-auth-client-oauth-callback.component-DLrIDQXn.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-open-sessions.command-Dq9eJ-bY.mjs → acorex-platform-module-auth-client-open-sessions.command-CwWtPiTG.mjs} +5 -5
- package/fesm2022/{acorex-platform-module-auth-client-open-sessions.command-Dq9eJ-bY.mjs.map → acorex-platform-module-auth-client-open-sessions.command-CwWtPiTG.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-password.component-SpEVRPaE.mjs → acorex-platform-module-auth-client-password.component-CAZ3tVPG.mjs} +5 -5
- package/fesm2022/{acorex-platform-module-auth-client-password.component-SpEVRPaE.mjs.map → acorex-platform-module-auth-client-password.component-CAZ3tVPG.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-password.component-Ci5Wy3rO.mjs → acorex-platform-module-auth-client-password.component-CE2nXYCz.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-password.component-Ci5Wy3rO.mjs.map → acorex-platform-module-auth-client-password.component-CE2nXYCz.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-platform-settings-unavailable.component-LwuokJiZ.mjs → acorex-platform-module-auth-client-platform-settings-unavailable.component-BJMtsa99.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-platform-settings-unavailable.component-LwuokJiZ.mjs.map → acorex-platform-module-auth-client-platform-settings-unavailable.component-BJMtsa99.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-profile-activity-chart.component-DcMdz44P.mjs → acorex-platform-module-auth-client-profile-activity-chart.component-BcbVLmZo.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-profile-activity-chart.component-DcMdz44P.mjs.map → acorex-platform-module-auth-client-profile-activity-chart.component-BcbVLmZo.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-profile-delete-account-danger-zone.component-DTujROAP.mjs → acorex-platform-module-auth-client-profile-delete-account-danger-zone.component-Dx2-o9XL.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-profile-delete-account-danger-zone.component-DTujROAP.mjs.map → acorex-platform-module-auth-client-profile-delete-account-danger-zone.component-Dx2-o9XL.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-profile-page-component.provider-CelasDrw.mjs → acorex-platform-module-auth-client-profile-page-component.provider-DEVBmVKd.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-profile-page-component.provider-CelasDrw.mjs.map → acorex-platform-module-auth-client-profile-page-component.provider-DEVBmVKd.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-profile-page.component-iGdfjv6g.mjs → acorex-platform-module-auth-client-profile-page.component-BNYoh2IL.mjs} +7 -7
- package/fesm2022/{acorex-platform-module-auth-client-profile-page.component-iGdfjv6g.mjs.map → acorex-platform-module-auth-client-profile-page.component-BNYoh2IL.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-register-password.component-CaztyyPx.mjs → acorex-platform-module-auth-client-register-password.component-DArLfswX.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-register-password.component-CaztyyPx.mjs.map → acorex-platform-module-auth-client-register-password.component-DArLfswX.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-register.module-R-yxS0EI.mjs → acorex-platform-module-auth-client-register.module-BXMV9tp3.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-register.module-R-yxS0EI.mjs.map → acorex-platform-module-auth-client-register.module-BXMV9tp3.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-remove-pin-code.command-DHY46WWD.mjs → acorex-platform-module-auth-client-remove-pin-code.command-D9uLV6je.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-remove-pin-code.command-DHY46WWD.mjs.map → acorex-platform-module-auth-client-remove-pin-code.command-D9uLV6je.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-reset-password.component-BQfKSqpW.mjs → acorex-platform-module-auth-client-reset-password.component-Cz4UePgF.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-reset-password.component-BQfKSqpW.mjs.map → acorex-platform-module-auth-client-reset-password.component-Cz4UePgF.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-result.component-DuMch6Ge.mjs → acorex-platform-module-auth-client-result.component-BS5uizi6.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-result.component-DuMch6Ge.mjs.map → acorex-platform-module-auth-client-result.component-BS5uizi6.mjs.map} +1 -1
- package/fesm2022/acorex-platform-module-auth-client-routes-Dw8YhBrw.mjs +21 -0
- package/fesm2022/acorex-platform-module-auth-client-routes-Dw8YhBrw.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-auth-client-session-limit.component-Dc6TIn-2.mjs → acorex-platform-module-auth-client-session-limit.component-DH58dRba.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-session-limit.component-Dc6TIn-2.mjs.map → acorex-platform-module-auth-client-session-limit.component-DH58dRba.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-session-lock-overlay.component-DBJjSIOq.mjs → acorex-platform-module-auth-client-session-lock-overlay.component-D_IKdJl8.mjs} +5 -5
- package/fesm2022/{acorex-platform-module-auth-client-session-lock-overlay.component-DBJjSIOq.mjs.map → acorex-platform-module-auth-client-session-lock-overlay.component-D_IKdJl8.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.command-CheMeghC.mjs → acorex-platform-module-auth-client-set-pin-code.command-DRLTGXEF.mjs} +3 -3
- package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.command-CheMeghC.mjs.map → acorex-platform-module-auth-client-set-pin-code.command-DRLTGXEF.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.component-BWl3vLOO.mjs → acorex-platform-module-auth-client-set-pin-code.component-m7SwyaZH.mjs} +5 -5
- package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.component-BWl3vLOO.mjs.map → acorex-platform-module-auth-client-set-pin-code.component-m7SwyaZH.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-tenant-chooser.component-BEtlhGUb.mjs → acorex-platform-module-auth-client-tenant-chooser.component-CdqBeKVw.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-tenant-chooser.component-BEtlhGUb.mjs.map → acorex-platform-module-auth-client-tenant-chooser.component-CdqBeKVw.mjs.map} +1 -1
- package/fesm2022/acorex-platform-module-auth-client-tenant-request.component-B-qx-HIi.mjs +256 -0
- package/fesm2022/acorex-platform-module-auth-client-tenant-request.component-B-qx-HIi.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-auth-client-two-factor-code.component-4XVRgh6H.mjs → acorex-platform-module-auth-client-two-factor-code.component-B1334bPg.mjs} +4 -4
- package/fesm2022/{acorex-platform-module-auth-client-two-factor-code.component-4XVRgh6H.mjs.map → acorex-platform-module-auth-client-two-factor-code.component-B1334bPg.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-two-factor.module-CrLPxje1.mjs → acorex-platform-module-auth-client-two-factor.module-C0mkbR4X.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-two-factor.module-CrLPxje1.mjs.map → acorex-platform-module-auth-client-two-factor.module-C0mkbR4X.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-view-login-history.command-qrd0bNM9.mjs → acorex-platform-module-auth-client-view-login-history.command-CerhsvHF.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-view-login-history.command-qrd0bNM9.mjs.map → acorex-platform-module-auth-client-view-login-history.command-CerhsvHF.mjs.map} +1 -1
- package/fesm2022/acorex-platform-module-auth-client-waiting-room.component-Wu8iPiTm.mjs +327 -0
- package/fesm2022/acorex-platform-module-auth-client-waiting-room.component-Wu8iPiTm.mjs.map +1 -0
- package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding-page.component-3yva-FyV.mjs → acorex-platform-module-auth-client-welcome-onboarding-page.component-BKqHYkv2.mjs} +5 -5
- package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding-page.component-3yva-FyV.mjs.map → acorex-platform-module-auth-client-welcome-onboarding-page.component-BKqHYkv2.mjs.map} +1 -1
- package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding.command-CFpMZAwC.mjs → acorex-platform-module-auth-client-welcome-onboarding.command--Rr0duJS.mjs} +2 -2
- package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding.command-CFpMZAwC.mjs.map → acorex-platform-module-auth-client-welcome-onboarding.command--Rr0duJS.mjs.map} +1 -1
- package/fesm2022/acorex-platform-module-auth-client.mjs +1 -1
- package/i18n/en-AU/auth.json +70 -5
- package/i18n/en-US/auth.json +70 -5
- package/i18n/fa-IR/auth.json +70 -5
- package/package.json +3 -2
- package/fesm2022/acorex-platform-module-auth-client-acorex-platform-module-auth-client-CQEt9bXJ.mjs.map +0 -1
- package/fesm2022/acorex-platform-module-auth-client-change-password.command-DRwzhNlO.mjs.map +0 -1
- package/fesm2022/acorex-platform-module-auth-client-routes-90eFjxx8.mjs +0 -17
- package/fesm2022/acorex-platform-module-auth-client-routes-90eFjxx8.mjs.map +0 -1
- package/fesm2022/acorex-platform-module-auth-client-waiting-room.component-IAVIt1fY.mjs +0 -165
- package/fesm2022/acorex-platform-module-auth-client-waiting-room.component-IAVIt1fY.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-module-auth-client-manage-two-factor.command-BOM6_896.mjs","sources":["../../../../libs/modules/auth/client/src/lib/commands/manage-two-factor.command.ts"],"sourcesContent":["import { AXDialogService } from '@acorex/components/dialog';\nimport { AXToastService } from '@acorex/components/toast';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXPSessionService } from '@acorex-platform/framework-client/auth';\nimport {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n} from '@acorex-platform/framework-client/layout/builder';\nimport { AXPCommandService } from '@acorex-platform/framework-client/runtime';\nimport { AXPRuntimeCommandResult, runtimeCommandPayloadData } from '@acorex-platform/framework-shared/core';\nimport { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n AXM_TWO_FACTOR_ERROR_CODES,\n AXMSecurityManagementServerCommands,\n type AXMConfirmTwoFactorEnrollmentResult,\n type AXMGenerateTwoFactorRecoveryCodesResult,\n type AXMGetTwoFactorStatusResult,\n type AXMStartTwoFactorEnrollmentResult,\n} from '@acorex-platform/module-security-management-client/contracts';\nimport { inject, Injectable } from '@angular/core';\n\nimport {\n PROFILE_SECTION_INSIGHTS_PATCH_METADATA_KEY,\n} from '../pages/account/profile-page/profile-password-insight.util';\nimport {\n TWO_FACTOR_SECTION_ID,\n buildTwoFactorStatusInsights,\n} from '../pages/account/profile-page/profile-two-factor-insight.util';\n\n//#region ----- Constants -----\n\nconst I18N = '@auth:profile-page.commands.manage-two-factor';\n\nconst TWO_FACTOR_ERROR_I18N: Record<string, string> = {\n [AXM_TWO_FACTOR_ERROR_CODES.NotSignedIn]: `${I18N}.messages.not-signed-in`,\n [AXM_TWO_FACTOR_ERROR_CODES.InvalidInput]: `${I18N}.messages.invalid-input`,\n [AXM_TWO_FACTOR_ERROR_CODES.IncorrectPassword]: `${I18N}.messages.incorrect-password`,\n [AXM_TWO_FACTOR_ERROR_CODES.IncorrectCode]: `${I18N}.messages.incorrect-code`,\n [AXM_TWO_FACTOR_ERROR_CODES.AlreadyEnabled]: `${I18N}.messages.already-enabled`,\n [AXM_TWO_FACTOR_ERROR_CODES.NotEnabled]: `${I18N}.messages.not-enabled`,\n [AXM_TWO_FACTOR_ERROR_CODES.EnrollmentExpired]: `${I18N}.messages.enrollment-expired`,\n [AXM_TWO_FACTOR_ERROR_CODES.RateLimited]: `${I18N}.messages.rate-limited`,\n [AXM_TWO_FACTOR_ERROR_CODES.InvalidConfiguration]: `${I18N}.messages.invalid-configuration`,\n [AXM_TWO_FACTOR_ERROR_CODES.ProofRequired]: `${I18N}.messages.proof-required`,\n};\n\n//#endregion\n\n//#region ----- Types -----\n\ntype TwoFactorProofForm = {\n password?: string;\n totpCode?: string;\n};\n\n//#endregion\n\n//#region ----- Helpers -----\n\n/** Groups Base32 secret in fours for Authenticator manual-entry UX (apps ignore spaces). */\nfunction formatTotpManualSecret(secretBase32: string): string {\n const cleaned = String(secretBase32 ?? '')\n .replace(/\\s+/g, '')\n .toUpperCase();\n return cleaned.replace(/(.{4})(?=.)/g, '$1 ');\n}\n\n//#endregion\n\n//#region ----- Manage two-factor command -----\n\n/** Opens profile dialogs to enroll, disable, or regenerate recovery codes for 2FA. */\n@Injectable({ providedIn: 'root' })\nexport class AXPManageTwoFactorCommand implements AXPCommand {\n //#region ----- Services & Dependencies -----\n\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly commandService = inject(AXPCommandService);\n private readonly sessionService = inject(AXPSessionService);\n private readonly dialogService = inject(AXDialogService);\n private readonly toastService = inject(AXToastService);\n private readonly translateService = inject(AXTranslationService);\n\n //#endregion\n\n //#region ----- Command -----\n\n async execute(): AXPCommandExecuteResultPromise<void> {\n if (!this.sessionService.user?.id) {\n await this.showErrorToast(`${I18N}.messages.not-signed-in`);\n return { success: false };\n }\n\n const status = await this.loadStatus();\n if (!status) {\n return { success: false };\n }\n\n // Prefer manage/disable whenever enrollment exists (even if setting briefly drifted).\n if (status.enabled || status.enrolled) {\n return this.runEnabledFlow(status);\n }\n\n return this.runEnrollmentFlow();\n }\n\n //#endregion\n\n //#region ----- Enrollment -----\n\n private async runEnrollmentFlow(): AXPCommandExecuteResultPromise<void> {\n const enrollment = await this.promptStartEnrollment();\n if (!enrollment) {\n return { success: false };\n }\n\n // Let the password dialog finish teardown before opening the QR dialog\n // (avoids RxJS ObjectUnsubscribedError on overlapping popup subjects).\n await this.waitForDialogTeardown();\n\n const confirmed = await this.promptConfirmEnrollment(enrollment);\n if (!confirmed) {\n return { success: false };\n }\n\n // Success feedback comes from the realtime security alert (avoid duplicate toasts).\n\n await this.waitForDialogTeardown();\n\n const generateCodes = await this.dialogService.confirm(\n await this.translateService.translateAsync(`${I18N}.recovery.offer-title`),\n await this.translateService.translateAsync(`${I18N}.recovery.offer-message`),\n 'primary',\n 'horizontal',\n );\n\n if (generateCodes.result) {\n await this.generateAndShowRecoveryCodes({ password: enrollment.password });\n }\n\n return this.successWithStatusInsights(true);\n }\n\n /**\n * Password re-auth + start enrollment in one dialog (same pattern as change-password).\n * Returns enrollment payload plus the password for optional recovery generation.\n */\n private async promptStartEnrollment(): Promise<\n (AXMStartTwoFactorEnrollmentResult & { password: string }) | null\n > {\n const result = await this.layoutBuilder\n .create()\n .dialog<(AXMStartTwoFactorEnrollmentResult & { password: string }) | null>((dialog) => {\n dialog\n .setTitle(`${I18N}.enable.password-dialog.title`)\n .setSize('sm')\n .setCloseButton(true)\n .setContext({ password: '' })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('1rem')\n .formField(`${I18N}.fields.password.title`, (field) => {\n field.setOptions({\n hint: `${I18N}.fields.password.hint`,\n hintDisplayMode: 'note',\n });\n field.path('password');\n field.passwordBox({\n revealToggle: true,\n placeholder: `${I18N}.fields.password.placeholder`,\n validations: [{ rule: 'required' }],\n });\n });\n });\n })\n .setActions((actions) => {\n actions.cancel('@general:actions.cancel.title');\n actions.submit(`${I18N}.actions.continue`);\n })\n .onAction(async (dialogRef) => {\n if (dialogRef.action() === 'cancel') {\n return null;\n }\n\n const form = dialogRef.context() as { password?: string };\n const password = String(form.password ?? '');\n if (!password) {\n throw new Error(`${I18N}.messages.incorrect-password`);\n }\n\n dialogRef.setLoading(true);\n try {\n const startResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.StartTwoFactorEnrollment,\n { password },\n );\n if (!startResult?.success) {\n throw new Error(this.resolveServerErrorKey(startResult?.message?.code));\n }\n\n const enrollment = runtimeCommandPayloadData(startResult) as\n | AXMStartTwoFactorEnrollmentResult\n | undefined;\n if (!enrollment?.enrollmentId || !enrollment.otpauthUri) {\n throw new Error(`${I18N}.messages.save-failed`);\n }\n\n // Do not call dialogRef.close() here — the layout-builder closes after onAction returns.\n // A second close throws ObjectUnsubscribedError and surfaces as \"object unsubscribed\".\n return { ...enrollment, password };\n } catch (error) {\n dialogRef.setLoading(false);\n throw error;\n }\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<AXMStartTwoFactorEnrollmentResult & { password: string }>(\n result,\n );\n }\n\n private async promptConfirmEnrollment(\n enrollment: AXMStartTwoFactorEnrollmentResult,\n ): Promise<boolean> {\n const result = await this.layoutBuilder\n .create()\n .dialog<boolean | null>((dialog) => {\n dialog\n .setTitle(`${I18N}.enable.confirm-dialog.title`)\n .setSize('md')\n .setCloseButton(true)\n .setContext({\n otpauthUri: enrollment.otpauthUri,\n // Authenticator apps expect Base32; spaced groups are easier to enter and widely accepted.\n secretBase32: formatTotpManualSecret(enrollment.secretBase32),\n code: '',\n })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('0.75rem')\n .setAlignItems('center')\n .customWidget('text-block-layout', {\n content: `${I18N}.enable.confirm-dialog.instructions`,\n })\n .customWidget('qrcode', {\n path: 'otpauthUri',\n size: 160,\n readonly: true,\n showContent: false,\n })\n .formField(`${I18N}.enable.confirm-dialog.fields.manual-secret.title`, (field) => {\n field.path('secretBase32');\n field.readonly(true);\n field.textBox({});\n })\n .formField(`${I18N}.enable.confirm-dialog.fields.code.title`, (field) => {\n field.path('code');\n field.textBox({\n placeholder: `${I18N}.enable.confirm-dialog.fields.code.placeholder`,\n validations: [{ rule: 'required' }],\n });\n });\n });\n })\n .setActions((actions) => {\n actions.cancel('@general:actions.cancel.title');\n actions.submit(`${I18N}.enable.confirm-dialog.actions.confirm`);\n })\n .onAction(async (dialogRef) => {\n if (dialogRef.action() === 'cancel') {\n return null;\n }\n\n const form = dialogRef.context() as { code?: string };\n const code = String(form.code ?? '').trim();\n if (!code) {\n throw new Error(`${I18N}.messages.incorrect-code`);\n }\n\n dialogRef.setLoading(true);\n try {\n const confirmResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.ConfirmTwoFactorEnrollment,\n { enrollmentId: enrollment.enrollmentId, code },\n );\n if (!confirmResult?.success) {\n throw new Error(this.resolveServerErrorKey(confirmResult?.message?.code));\n }\n\n const payload = runtimeCommandPayloadData(confirmResult) as\n | AXMConfirmTwoFactorEnrollmentResult\n | undefined;\n if (!payload?.enabled) {\n throw new Error(`${I18N}.messages.save-failed`);\n }\n\n return true;\n } catch (error) {\n dialogRef.setLoading(false);\n throw error;\n }\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<boolean>(result) === true;\n }\n\n //#endregion\n\n //#region ----- Enabled management -----\n\n private async runEnabledFlow(\n status: AXMGetTwoFactorStatusResult,\n ): AXPCommandExecuteResultPromise<void> {\n const choice = await this.dialogService.show({\n title: `${I18N}.manage.dialog.title`,\n content: await this.translateService.translateAsync(`${I18N}.manage.dialog.description`, {\n params: {\n recoveryCount: status.unusedRecoveryCodeCount ?? 0,\n },\n }),\n type: 'primary',\n orientation: 'vertical',\n buttons: [\n {\n name: 'regenerate',\n text: `${I18N}.manage.actions.regenerate-recovery`,\n color: 'primary',\n autofocus: true,\n },\n {\n name: 'disable',\n text: `${I18N}.manage.actions.disable`,\n color: 'danger',\n },\n {\n name: 'cancel',\n text: '@general:actions.cancel.title',\n color: 'default',\n },\n ],\n });\n\n if (choice?.name === 'disable') {\n const proof = await this.promptProof(`${I18N}.disable.dialog.title`);\n if (!proof) {\n return { success: false };\n }\n\n const disableResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.DisableTwoFactor,\n proof,\n );\n if (!disableResult?.success) {\n await this.showErrorToast(this.resolveServerErrorKey(disableResult?.message?.code));\n return { success: false };\n }\n\n // Success feedback comes from the realtime security alert (avoid duplicate toasts).\n return this.successWithStatusInsights(false);\n }\n\n if (choice?.name === 'regenerate') {\n const proof = await this.promptProof(`${I18N}.recovery.regenerate-dialog.title`);\n if (!proof) {\n return { success: false };\n }\n\n const shown = await this.generateAndShowRecoveryCodes(proof);\n if (!shown) {\n return { success: false };\n }\n\n return this.successWithStatusInsights(true);\n }\n\n return { success: false };\n }\n\n //#endregion\n\n //#region ----- Shared dialogs -----\n\n /** Yields so popup teardown can finish before opening another dialog. */\n private async waitForDialogTeardown(): Promise<void> {\n await new Promise<void>((resolve) => setTimeout(resolve, 50));\n }\n\n private async promptProof(titleKey: string): Promise<TwoFactorProofForm | null> {\n const result = await this.layoutBuilder\n .create()\n .dialog<TwoFactorProofForm | null>((dialog) => {\n dialog\n .setTitle(titleKey)\n .setSize('sm')\n .setCloseButton(true)\n .setContext({ password: '', totpCode: '' })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('1rem')\n .customWidget('text-block-layout', {\n content: `${I18N}.fields.proof.hint`,\n })\n .formField(`${I18N}.fields.password.title`, (field) => {\n field.path('password');\n field.passwordBox({\n revealToggle: true,\n placeholder: `${I18N}.fields.password.placeholder`,\n });\n })\n .formField(`${I18N}.fields.totp-code.title`, (field) => {\n field.path('totpCode');\n field.textBox({\n placeholder: `${I18N}.fields.totp-code.placeholder`,\n });\n });\n });\n })\n .setActions((actions) => {\n actions.cancel('@general:actions.cancel.title');\n actions.submit(`${I18N}.actions.continue`);\n })\n .onAction(async (dialogRef) => {\n if (dialogRef.action() === 'cancel') {\n return null;\n }\n\n const form = dialogRef.context() as TwoFactorProofForm;\n const password = String(form.password ?? '').trim();\n const totpCode = String(form.totpCode ?? '').trim();\n if (!password && !totpCode) {\n throw new Error(`${I18N}.messages.proof-required`);\n }\n\n return {\n ...(password ? { password } : {}),\n ...(totpCode ? { totpCode } : {}),\n };\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<TwoFactorProofForm>(result) ?? null;\n }\n\n private async generateAndShowRecoveryCodes(proof: TwoFactorProofForm): Promise<boolean> {\n const generateResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.GenerateTwoFactorRecoveryCodes,\n proof,\n );\n if (!generateResult?.success) {\n await this.showErrorToast(this.resolveServerErrorKey(generateResult?.message?.code));\n return false;\n }\n\n const payload = runtimeCommandPayloadData(generateResult) as\n | AXMGenerateTwoFactorRecoveryCodesResult\n | undefined;\n const codes = payload?.codes ?? [];\n if (!codes.length) {\n await this.showErrorToast(`${I18N}.messages.save-failed`);\n return false;\n }\n\n const codesText = codes.join('\\n');\n await this.layoutBuilder\n .create()\n .dialog<null>((dialog) => {\n dialog\n .setTitle(`${I18N}.recovery.codes-dialog.title`)\n .setSize('md')\n .setCloseButton(true)\n .setContext({ codesText })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('1rem')\n .customWidget('text-block-layout', {\n content: `${I18N}.recovery.codes-dialog.warning`,\n })\n .formField(`${I18N}.recovery.codes-dialog.fields.codes.title`, (field) => {\n field.path('codesText');\n field.readonly(true);\n field.largeTextBox({\n rows: Math.min(codes.length + 1, 12),\n });\n });\n });\n })\n .setActions((actions) => {\n actions.submit(`${I18N}.recovery.codes-dialog.actions.done`);\n })\n .onAction(async () => null);\n })\n .show();\n\n return true;\n }\n\n //#endregion\n\n //#region ----- Status & messaging -----\n\n private async loadStatus(): Promise<AXMGetTwoFactorStatusResult | null> {\n const result = await this.commandService.execute(\n AXMSecurityManagementServerCommands.GetTwoFactorStatus,\n {},\n );\n if (!result?.success) {\n await this.showErrorToast(this.resolveServerErrorKey(result?.message?.code));\n return null;\n }\n\n return (runtimeCommandPayloadData(result) as AXMGetTwoFactorStatusResult | undefined) ?? {\n enabled: false,\n enrolled: false,\n hasRecoveryCodes: false,\n unusedRecoveryCodeCount: 0,\n };\n }\n\n private successWithStatusInsights(enabled: boolean): AXPRuntimeCommandResult<void> {\n return {\n success: true,\n kind: 'object',\n data: undefined,\n metadata: {\n refresh: false,\n [PROFILE_SECTION_INSIGHTS_PATCH_METADATA_KEY]: {\n sectionId: TWO_FACTOR_SECTION_ID,\n insights: buildTwoFactorStatusInsights(enabled),\n },\n },\n };\n }\n\n private resolveServerErrorKey(code: string | undefined): string {\n if (code && TWO_FACTOR_ERROR_I18N[code]) {\n return TWO_FACTOR_ERROR_I18N[code];\n }\n\n return `${I18N}.messages.save-failed`;\n }\n\n private async showErrorToast(key: string): Promise<void> {\n const content = await this.translateService.translateAsync(key);\n this.toastService.show({ color: 'danger', content, timeOut: 4000 });\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"acorex-platform-module-auth-client-manage-two-factor.command-DRsNZWZF.mjs","sources":["../../../../libs/modules/auth/client/src/lib/commands/manage-two-factor.command.ts"],"sourcesContent":["import { AXDialogService } from '@acorex/components/dialog';\nimport { AXToastService } from '@acorex/components/toast';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXPSessionService } from '@acorex-platform/framework-client/auth';\nimport {\n AXPLayoutBuilderService,\n resolveLayoutBuilderDialogResult,\n} from '@acorex-platform/framework-client/layout/builder';\nimport { AXPCommandService } from '@acorex-platform/framework-client/runtime';\nimport { AXPRuntimeCommandResult, runtimeCommandPayloadData } from '@acorex-platform/framework-shared/core';\nimport { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport {\n AXM_TWO_FACTOR_ERROR_CODES,\n AXMSecurityManagementServerCommands,\n type AXMConfirmTwoFactorEnrollmentResult,\n type AXMGenerateTwoFactorRecoveryCodesResult,\n type AXMGetTwoFactorStatusResult,\n type AXMStartTwoFactorEnrollmentResult,\n} from '@acorex-platform/module-security-management-client/contracts';\nimport { inject, Injectable } from '@angular/core';\n\nimport {\n PROFILE_SECTION_INSIGHTS_PATCH_METADATA_KEY,\n} from '../pages/account/profile-page/profile-password-insight.util';\nimport {\n TWO_FACTOR_SECTION_ID,\n buildTwoFactorStatusInsights,\n} from '../pages/account/profile-page/profile-two-factor-insight.util';\n\n//#region ----- Constants -----\n\nconst I18N = '@auth:profile-page.commands.manage-two-factor';\n\nconst TWO_FACTOR_ERROR_I18N: Record<string, string> = {\n [AXM_TWO_FACTOR_ERROR_CODES.NotSignedIn]: `${I18N}.messages.not-signed-in`,\n [AXM_TWO_FACTOR_ERROR_CODES.InvalidInput]: `${I18N}.messages.invalid-input`,\n [AXM_TWO_FACTOR_ERROR_CODES.IncorrectPassword]: `${I18N}.messages.incorrect-password`,\n [AXM_TWO_FACTOR_ERROR_CODES.IncorrectCode]: `${I18N}.messages.incorrect-code`,\n [AXM_TWO_FACTOR_ERROR_CODES.AlreadyEnabled]: `${I18N}.messages.already-enabled`,\n [AXM_TWO_FACTOR_ERROR_CODES.NotEnabled]: `${I18N}.messages.not-enabled`,\n [AXM_TWO_FACTOR_ERROR_CODES.EnrollmentExpired]: `${I18N}.messages.enrollment-expired`,\n [AXM_TWO_FACTOR_ERROR_CODES.RateLimited]: `${I18N}.messages.rate-limited`,\n [AXM_TWO_FACTOR_ERROR_CODES.InvalidConfiguration]: `${I18N}.messages.invalid-configuration`,\n [AXM_TWO_FACTOR_ERROR_CODES.ProofRequired]: `${I18N}.messages.proof-required`,\n};\n\n//#endregion\n\n//#region ----- Types -----\n\ntype TwoFactorProofForm = {\n password?: string;\n totpCode?: string;\n};\n\n//#endregion\n\n//#region ----- Helpers -----\n\n/** Groups Base32 secret in fours for Authenticator manual-entry UX (apps ignore spaces). */\nfunction formatTotpManualSecret(secretBase32: string): string {\n const cleaned = String(secretBase32 ?? '')\n .replace(/\\s+/g, '')\n .toUpperCase();\n return cleaned.replace(/(.{4})(?=.)/g, '$1 ');\n}\n\n//#endregion\n\n//#region ----- Manage two-factor command -----\n\n/** Opens profile dialogs to enroll, disable, or regenerate recovery codes for 2FA. */\n@Injectable({ providedIn: 'root' })\nexport class AXPManageTwoFactorCommand implements AXPCommand {\n //#region ----- Services & Dependencies -----\n\n private readonly layoutBuilder = inject(AXPLayoutBuilderService);\n private readonly commandService = inject(AXPCommandService);\n private readonly sessionService = inject(AXPSessionService);\n private readonly dialogService = inject(AXDialogService);\n private readonly toastService = inject(AXToastService);\n private readonly translateService = inject(AXTranslationService);\n\n //#endregion\n\n //#region ----- Command -----\n\n async execute(): AXPCommandExecuteResultPromise<void> {\n if (!this.sessionService.user?.id) {\n await this.showErrorToast(`${I18N}.messages.not-signed-in`);\n return { success: false };\n }\n\n const status = await this.loadStatus();\n if (!status) {\n return { success: false };\n }\n\n // Prefer manage/disable whenever enrollment exists (even if setting briefly drifted).\n if (status.enabled || status.enrolled) {\n return this.runEnabledFlow(status);\n }\n\n return this.runEnrollmentFlow();\n }\n\n //#endregion\n\n //#region ----- Enrollment -----\n\n private async runEnrollmentFlow(): AXPCommandExecuteResultPromise<void> {\n const enrollment = await this.promptStartEnrollment();\n if (!enrollment) {\n return { success: false };\n }\n\n // Let the password dialog finish teardown before opening the QR dialog\n // (avoids RxJS ObjectUnsubscribedError on overlapping popup subjects).\n await this.waitForDialogTeardown();\n\n const confirmed = await this.promptConfirmEnrollment(enrollment);\n if (!confirmed) {\n return { success: false };\n }\n\n // Success feedback comes from the realtime security alert (avoid duplicate toasts).\n\n await this.waitForDialogTeardown();\n\n const generateCodes = await this.dialogService.confirm(\n await this.translateService.translateAsync(`${I18N}.recovery.offer-title`),\n await this.translateService.translateAsync(`${I18N}.recovery.offer-message`),\n 'primary',\n 'horizontal',\n );\n\n if (generateCodes.result) {\n await this.generateAndShowRecoveryCodes({ password: enrollment.password });\n }\n\n return this.successWithStatusInsights(true);\n }\n\n /**\n * Password re-auth + start enrollment in one dialog (same pattern as change-password).\n * Returns enrollment payload plus the password for optional recovery generation.\n */\n private async promptStartEnrollment(): Promise<\n (AXMStartTwoFactorEnrollmentResult & { password: string }) | null\n > {\n const result = await this.layoutBuilder\n .create()\n .dialog<(AXMStartTwoFactorEnrollmentResult & { password: string }) | null>((dialog) => {\n dialog\n .setTitle(`${I18N}.enable.password-dialog.title`)\n .setSize('sm')\n .setCloseButton(true)\n .setContext({ password: '' })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('1rem')\n .formField(`${I18N}.fields.password.title`, (field) => {\n field.setOptions({\n hint: `${I18N}.fields.password.hint`,\n hintDisplayMode: 'note',\n });\n field.path('password');\n field.passwordBox({\n revealToggle: true,\n placeholder: `${I18N}.fields.password.placeholder`,\n validations: [{ rule: 'required' }],\n });\n });\n });\n })\n .setActions((actions) => {\n actions.cancel('@general:actions.cancel.title');\n actions.submit(`${I18N}.actions.continue`);\n })\n .onAction(async (dialogRef) => {\n if (dialogRef.action() === 'cancel') {\n return null;\n }\n\n const form = dialogRef.context() as { password?: string };\n const password = String(form.password ?? '');\n if (!password) {\n throw new Error(`${I18N}.messages.incorrect-password`);\n }\n\n dialogRef.setLoading(true);\n try {\n const startResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.StartTwoFactorEnrollment,\n { password },\n );\n if (!startResult?.success) {\n throw new Error(this.resolveServerErrorKey(startResult?.message?.code));\n }\n\n const enrollment = runtimeCommandPayloadData(startResult) as\n | AXMStartTwoFactorEnrollmentResult\n | undefined;\n if (!enrollment?.enrollmentId || !enrollment.otpauthUri) {\n throw new Error(`${I18N}.messages.save-failed`);\n }\n\n // Do not call dialogRef.close() here — the layout-builder closes after onAction returns.\n // A second close throws ObjectUnsubscribedError and surfaces as \"object unsubscribed\".\n return { ...enrollment, password };\n } catch (error) {\n dialogRef.setLoading(false);\n throw error;\n }\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<AXMStartTwoFactorEnrollmentResult & { password: string }>(\n result,\n );\n }\n\n private async promptConfirmEnrollment(\n enrollment: AXMStartTwoFactorEnrollmentResult,\n ): Promise<boolean> {\n const result = await this.layoutBuilder\n .create()\n .dialog<boolean | null>((dialog) => {\n dialog\n .setTitle(`${I18N}.enable.confirm-dialog.title`)\n .setSize('md')\n .setCloseButton(true)\n .setContext({\n otpauthUri: enrollment.otpauthUri,\n // Authenticator apps expect Base32; spaced groups are easier to enter and widely accepted.\n secretBase32: formatTotpManualSecret(enrollment.secretBase32),\n code: '',\n })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('0.75rem')\n .setAlignItems('center')\n .customWidget('text-block-layout', {\n content: `${I18N}.enable.confirm-dialog.instructions`,\n })\n .customWidget('qrcode', {\n path: 'otpauthUri',\n size: 160,\n readonly: true,\n showContent: false,\n })\n .formField(`${I18N}.enable.confirm-dialog.fields.manual-secret.title`, (field) => {\n field.path('secretBase32');\n field.readonly(true);\n field.textBox({});\n })\n .formField(`${I18N}.enable.confirm-dialog.fields.code.title`, (field) => {\n field.path('code');\n field.textBox({\n placeholder: `${I18N}.enable.confirm-dialog.fields.code.placeholder`,\n validations: [{ rule: 'required' }],\n });\n });\n });\n })\n .setActions((actions) => {\n actions.cancel('@general:actions.cancel.title');\n actions.submit(`${I18N}.enable.confirm-dialog.actions.confirm`);\n })\n .onAction(async (dialogRef) => {\n if (dialogRef.action() === 'cancel') {\n return null;\n }\n\n const form = dialogRef.context() as { code?: string };\n const code = String(form.code ?? '').trim();\n if (!code) {\n throw new Error(`${I18N}.messages.incorrect-code`);\n }\n\n dialogRef.setLoading(true);\n try {\n const confirmResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.ConfirmTwoFactorEnrollment,\n { enrollmentId: enrollment.enrollmentId, code },\n );\n if (!confirmResult?.success) {\n throw new Error(this.resolveServerErrorKey(confirmResult?.message?.code));\n }\n\n const payload = runtimeCommandPayloadData(confirmResult) as\n | AXMConfirmTwoFactorEnrollmentResult\n | undefined;\n if (!payload?.enabled) {\n throw new Error(`${I18N}.messages.save-failed`);\n }\n\n return true;\n } catch (error) {\n dialogRef.setLoading(false);\n throw error;\n }\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<boolean>(result) === true;\n }\n\n //#endregion\n\n //#region ----- Enabled management -----\n\n private async runEnabledFlow(\n status: AXMGetTwoFactorStatusResult,\n ): AXPCommandExecuteResultPromise<void> {\n const choice = await this.dialogService.show({\n title: `${I18N}.manage.dialog.title`,\n content: await this.translateService.translateAsync(`${I18N}.manage.dialog.description`, {\n params: {\n recoveryCount: status.unusedRecoveryCodeCount ?? 0,\n },\n }),\n type: 'primary',\n orientation: 'vertical',\n buttons: [\n {\n name: 'regenerate',\n text: `${I18N}.manage.actions.regenerate-recovery`,\n color: 'primary',\n autofocus: true,\n },\n {\n name: 'disable',\n text: `${I18N}.manage.actions.disable`,\n color: 'danger',\n },\n {\n name: 'cancel',\n text: '@general:actions.cancel.title',\n color: 'default',\n },\n ],\n });\n\n if (choice?.name === 'disable') {\n const proof = await this.promptProof(`${I18N}.disable.dialog.title`);\n if (!proof) {\n return { success: false };\n }\n\n const disableResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.DisableTwoFactor,\n proof,\n );\n if (!disableResult?.success) {\n await this.showErrorToast(this.resolveServerErrorKey(disableResult?.message?.code));\n return { success: false };\n }\n\n // Success feedback comes from the realtime security alert (avoid duplicate toasts).\n return this.successWithStatusInsights(false);\n }\n\n if (choice?.name === 'regenerate') {\n const proof = await this.promptProof(`${I18N}.recovery.regenerate-dialog.title`);\n if (!proof) {\n return { success: false };\n }\n\n const shown = await this.generateAndShowRecoveryCodes(proof);\n if (!shown) {\n return { success: false };\n }\n\n return this.successWithStatusInsights(true);\n }\n\n return { success: false };\n }\n\n //#endregion\n\n //#region ----- Shared dialogs -----\n\n /** Yields so popup teardown can finish before opening another dialog. */\n private async waitForDialogTeardown(): Promise<void> {\n await new Promise<void>((resolve) => setTimeout(resolve, 50));\n }\n\n private async promptProof(titleKey: string): Promise<TwoFactorProofForm | null> {\n const result = await this.layoutBuilder\n .create()\n .dialog<TwoFactorProofForm | null>((dialog) => {\n dialog\n .setTitle(titleKey)\n .setSize('sm')\n .setCloseButton(true)\n .setContext({ password: '', totpCode: '' })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('1rem')\n .customWidget('text-block-layout', {\n content: `${I18N}.fields.proof.hint`,\n })\n .formField(`${I18N}.fields.password.title`, (field) => {\n field.path('password');\n field.passwordBox({\n revealToggle: true,\n placeholder: `${I18N}.fields.password.placeholder`,\n });\n })\n .formField(`${I18N}.fields.totp-code.title`, (field) => {\n field.path('totpCode');\n field.textBox({\n placeholder: `${I18N}.fields.totp-code.placeholder`,\n });\n });\n });\n })\n .setActions((actions) => {\n actions.cancel('@general:actions.cancel.title');\n actions.submit(`${I18N}.actions.continue`);\n })\n .onAction(async (dialogRef) => {\n if (dialogRef.action() === 'cancel') {\n return null;\n }\n\n const form = dialogRef.context() as TwoFactorProofForm;\n const password = String(form.password ?? '').trim();\n const totpCode = String(form.totpCode ?? '').trim();\n if (!password && !totpCode) {\n throw new Error(`${I18N}.messages.proof-required`);\n }\n\n return {\n ...(password ? { password } : {}),\n ...(totpCode ? { totpCode } : {}),\n };\n });\n })\n .show();\n\n return resolveLayoutBuilderDialogResult<TwoFactorProofForm>(result) ?? null;\n }\n\n private async generateAndShowRecoveryCodes(proof: TwoFactorProofForm): Promise<boolean> {\n const generateResult = await this.commandService.execute(\n AXMSecurityManagementServerCommands.GenerateTwoFactorRecoveryCodes,\n proof,\n );\n if (!generateResult?.success) {\n await this.showErrorToast(this.resolveServerErrorKey(generateResult?.message?.code));\n return false;\n }\n\n const payload = runtimeCommandPayloadData(generateResult) as\n | AXMGenerateTwoFactorRecoveryCodesResult\n | undefined;\n const codes = payload?.codes ?? [];\n if (!codes.length) {\n await this.showErrorToast(`${I18N}.messages.save-failed`);\n return false;\n }\n\n const codesText = codes.join('\\n');\n await this.layoutBuilder\n .create()\n .dialog<null>((dialog) => {\n dialog\n .setTitle(`${I18N}.recovery.codes-dialog.title`)\n .setSize('md')\n .setCloseButton(true)\n .setContext({ codesText })\n .content((layout) => {\n layout.flex((flex) => {\n flex\n .setDirection('column')\n .setGap('1rem')\n .customWidget('text-block-layout', {\n content: `${I18N}.recovery.codes-dialog.warning`,\n })\n .formField(`${I18N}.recovery.codes-dialog.fields.codes.title`, (field) => {\n field.path('codesText');\n field.readonly(true);\n field.largeTextBox({\n rows: Math.min(codes.length + 1, 12),\n });\n });\n });\n })\n .setActions((actions) => {\n actions.submit(`${I18N}.recovery.codes-dialog.actions.done`);\n })\n .onAction(async () => null);\n })\n .show();\n\n return true;\n }\n\n //#endregion\n\n //#region ----- Status & messaging -----\n\n private async loadStatus(): Promise<AXMGetTwoFactorStatusResult | null> {\n const result = await this.commandService.execute(\n AXMSecurityManagementServerCommands.GetTwoFactorStatus,\n {},\n );\n if (!result?.success) {\n await this.showErrorToast(this.resolveServerErrorKey(result?.message?.code));\n return null;\n }\n\n return (runtimeCommandPayloadData(result) as AXMGetTwoFactorStatusResult | undefined) ?? {\n enabled: false,\n enrolled: false,\n hasRecoveryCodes: false,\n unusedRecoveryCodeCount: 0,\n };\n }\n\n private successWithStatusInsights(enabled: boolean): AXPRuntimeCommandResult<void> {\n return {\n success: true,\n kind: 'object',\n data: undefined,\n metadata: {\n refresh: false,\n [PROFILE_SECTION_INSIGHTS_PATCH_METADATA_KEY]: {\n sectionId: TWO_FACTOR_SECTION_ID,\n insights: buildTwoFactorStatusInsights(enabled),\n },\n },\n };\n }\n\n private resolveServerErrorKey(code: string | undefined): string {\n if (code && TWO_FACTOR_ERROR_I18N[code]) {\n return TWO_FACTOR_ERROR_I18N[code];\n }\n\n return `${I18N}.messages.save-failed`;\n }\n\n private async showErrorToast(key: string): Promise<void> {\n const content = await this.translateService.translateAsync(key);\n this.toastService.show({ color: 'danger', content, timeOut: 4000 });\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,7 @@ import { AXTranslationModule } from '@acorex/core/translation';
|
|
|
6
6
|
import { AXPSessionService, resolvePlatformOAuthRedirectUri } from '@acorex-platform/framework-client/auth';
|
|
7
7
|
import { AXPHomePageService } from '@acorex-platform/framework-client/common';
|
|
8
8
|
import { AXPStateMessageComponent } from '@acorex-platform/framework-client/layout/components';
|
|
9
|
-
import * as
|
|
9
|
+
import * as i5$1 from '@angular/common';
|
|
10
10
|
import { CommonModule } from '@angular/common';
|
|
11
11
|
import * as i0 from '@angular/core';
|
|
12
12
|
import { inject, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
@@ -90,7 +90,7 @@ class AXPOAuthCallbackComponent {
|
|
|
90
90
|
this.router.navigate(['/']);
|
|
91
91
|
}
|
|
92
92
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPOAuthCallbackComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
93
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPOAuthCallbackComponent, isStandalone: true, selector: "axp-oauth-callback", ngImport: i0, template: "<ng-container *translate=\"let t\">\n <div class=\"h-full flex flex-col items-center justify-center p-8\">\n <div class=\"w-96 text-center\">\n <!-- Loading State -->\n @if (isLoading$ | async) {\n <axp-state-message\n mode=\"loading\"\n icon=\"fa-solid fa-spinner fa-spin\"\n [title]=\"(status$ | async) || '@auth:state-message.loading.title'\"\n [description]=\"'@auth:state-message.loading.description'\"\n >\n </axp-state-message>\n }\n\n <!-- Error State -->\n @if ((error$ | async) && !(isLoading$ | async)) {\n <axp-state-message\n mode=\"error\"\n icon=\"fa-solid fa-exclamation-triangle\"\n [title]=\"'@auth:state-message.error.title'\"\n [description]=\"(error$ | async) || '@auth:state-message.error.description'\"\n >\n <div slot=\"actions\" class=\"flex flex-col gap-2 sm:flex-row sm:justify-center\">\n <ax-button\n color=\"primary\"\n [text]=\"('@auth:startup-error.retry' | translate | async) ?? ''\"\n (onClick)=\"handleRetry()\"\n class=\"w-full sm:w-auto\"\n >\n </ax-button>\n <ax-button\n color=\"default\"\n [text]=\"('@general:errors.404.actions.go-home.title' | translate | async) ?? ''\"\n (onClick)=\"handleGoHome()\"\n class=\"w-full sm:w-auto\"\n >\n </ax-button>\n </div>\n </axp-state-message>\n }\n\n <!-- Success State (briefly shown before redirect) -->\n @if (!(isLoading$ | async) && !(error$ | async)) {\n <axp-state-message\n mode=\"success\"\n icon=\"fa-solid fa-check\"\n [title]=\"'@auth:state-message.success.title'\"\n [description]=\"'@auth:state-message.success.description'\"\n >\n </axp-state-message>\n }\n </div>\n </div>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i5.AXTranslatorDirective, selector: "[translate]" }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "pipe", type:
|
|
93
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXPOAuthCallbackComponent, isStandalone: true, selector: "axp-oauth-callback", ngImport: i0, template: "<ng-container *translate=\"let t\">\n <div class=\"h-full flex flex-col items-center justify-center p-8\">\n <div class=\"w-96 text-center\">\n <!-- Loading State -->\n @if (isLoading$ | async) {\n <axp-state-message\n mode=\"loading\"\n icon=\"fa-solid fa-spinner fa-spin\"\n [title]=\"(status$ | async) || '@auth:state-message.loading.title'\"\n [description]=\"'@auth:state-message.loading.description'\"\n >\n </axp-state-message>\n }\n\n <!-- Error State -->\n @if ((error$ | async) && !(isLoading$ | async)) {\n <axp-state-message\n mode=\"error\"\n icon=\"fa-solid fa-exclamation-triangle\"\n [title]=\"'@auth:state-message.error.title'\"\n [description]=\"(error$ | async) || '@auth:state-message.error.description'\"\n >\n <div slot=\"actions\" class=\"flex flex-col gap-2 sm:flex-row sm:justify-center\">\n <ax-button\n color=\"primary\"\n [text]=\"('@auth:startup-error.retry' | translate | async) ?? ''\"\n (onClick)=\"handleRetry()\"\n class=\"w-full sm:w-auto\"\n >\n </ax-button>\n <ax-button\n color=\"default\"\n [text]=\"('@general:errors.404.actions.go-home.title' | translate | async) ?? ''\"\n (onClick)=\"handleGoHome()\"\n class=\"w-full sm:w-auto\"\n >\n </ax-button>\n </div>\n </axp-state-message>\n }\n\n <!-- Success State (briefly shown before redirect) -->\n @if (!(isLoading$ | async) && !(error$ | async)) {\n <axp-state-message\n mode=\"success\"\n icon=\"fa-solid fa-check\"\n [title]=\"'@auth:state-message.success.title'\"\n [description]=\"'@auth:state-message.success.description'\"\n >\n </axp-state-message>\n }\n </div>\n </div>\n</ng-container>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "directive", type: i5.AXTranslatorDirective, selector: "[translate]" }, { kind: "component", type: AXPStateMessageComponent, selector: "axp-state-message", inputs: ["mode", "icon", "title", "description", "titleParams", "descriptionParams", "look"] }, { kind: "pipe", type: i5$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
94
94
|
}
|
|
95
95
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPOAuthCallbackComponent, decorators: [{
|
|
96
96
|
type: Component,
|
|
@@ -98,4 +98,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
98
98
|
}] });
|
|
99
99
|
|
|
100
100
|
export { AXPOAuthCallbackComponent };
|
|
101
|
-
//# sourceMappingURL=acorex-platform-module-auth-client-oauth-callback.component-
|
|
101
|
+
//# sourceMappingURL=acorex-platform-module-auth-client-oauth-callback.component-DLrIDQXn.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-module-auth-client-oauth-callback.component-
|
|
1
|
+
{"version":3,"file":"acorex-platform-module-auth-client-oauth-callback.component-DLrIDQXn.mjs","sources":["../../../../libs/modules/auth/client/src/lib/pages/callback/oauth-callback.component.ts","../../../../libs/modules/auth/client/src/lib/pages/callback/oauth-callback.component.html"],"sourcesContent":["import { AXButtonModule } from '@acorex/components/button';\nimport { AXLoadingModule } from '@acorex/components/loading';\nimport { AXTranslationModule } from '@acorex/core/translation';\nimport { AXPSessionService, resolvePlatformOAuthRedirectUri } from '@acorex-platform/framework-client/auth';\nimport { AXPHomePageService } from '@acorex-platform/framework-client/common';\nimport { AXPStateMessageComponent } from '@acorex-platform/framework-client/layout/components';\nimport { CommonModule } from '@angular/common';\nimport { Component, OnInit, inject, ChangeDetectionStrategy } from '@angular/core';\nimport { ActivatedRoute, Router } from '@angular/router';\nimport { BehaviorSubject } from 'rxjs';\n@Component({\n selector: 'axp-oauth-callback',\n templateUrl: './oauth-callback.component.html',\n imports: [CommonModule, AXButtonModule, AXLoadingModule, AXTranslationModule, AXPStateMessageComponent],\n changeDetection: ChangeDetectionStrategy.Eager,\n standalone: true,\n})\nexport class AXPOAuthCallbackComponent implements OnInit {\n //#region ---- Services & Dependencies ----\n\n private sessionService = inject(AXPSessionService);\n private router = inject(Router);\n private route = inject(ActivatedRoute);\n private homePageService = inject(AXPHomePageService);\n\n //#endregion\n\n //#region ---- Properties ----\n\n protected isLoading$ = new BehaviorSubject<boolean>(true);\n protected error$ = new BehaviorSubject<string | null>(null);\n protected status$ = new BehaviorSubject<string>('Processing authorization...');\n private exchangeStarted = false;\n // Removed: @Input() flow\n\n //#endregion\n\n //#region ---- Lifecycle Methods ----\n\n async ngOnInit(): Promise<void> {\n if (this.exchangeStarted) {\n return;\n }\n this.exchangeStarted = true;\n\n try {\n const queryParams = this.route.snapshot.queryParams;\n const code = queryParams['code'];\n const error = queryParams['error'];\n // Removed: flowParam and its assignment\n if (error) {\n throw new Error(`OAuth error: ${error} - ${queryParams['error_description'] || 'Unknown error'}`);\n }\n if (!code) {\n throw new Error('No authorization code received from OAuth provider');\n }\n this.status$.next('Exchanging authorization code for tokens...');\n\n const redirectUri = resolvePlatformOAuthRedirectUri();\n // Strategy is resolved inside updateToken (session + pending OAuth key).\n await this.sessionService.updateToken({ code, redirectUri });\n this.status$.next('Authentication successful! Redirecting...');\n await this.navigateAfterSuccess();\n } catch (error) {\n console.error('OAuth callback error:', error);\n const message =\n error instanceof Error && error.message.trim()\n ? error.message\n : 'Authentication failed. Please try again.';\n this.error$.next(message);\n await this.sessionService.signout();\n this.isLoading$.next(false);\n } finally {\n this.isLoading$.next(false);\n }\n }\n\n //#endregion\n\n //#region ---- Navigation ----\n\n private async navigateAfterSuccess(): Promise<void> {\n // Use await with router.navigate to ensure navigation completes\n if (this.sessionService.tenant?.id == null) {\n await this.router.navigate(['/auth/account/tenant-chooser']);\n return;\n }\n if (this.sessionService.application?.id == null) {\n await this.router.navigate(['/auth/account/app-chooser']);\n return;\n }\n // Navigate to home page\n await this.homePageService.navigateTo();\n }\n\n //#endregion\n\n //#region ---- UI Handlers ----\n\n protected handleRetry(): void {\n this.router.navigate(['/auth/login']);\n }\n\n protected handleGoHome(): void {\n this.router.navigate(['/']);\n }\n\n //#endregion\n}\n","<ng-container *translate=\"let t\">\n <div class=\"h-full flex flex-col items-center justify-center p-8\">\n <div class=\"w-96 text-center\">\n <!-- Loading State -->\n @if (isLoading$ | async) {\n <axp-state-message\n mode=\"loading\"\n icon=\"fa-solid fa-spinner fa-spin\"\n [title]=\"(status$ | async) || '@auth:state-message.loading.title'\"\n [description]=\"'@auth:state-message.loading.description'\"\n >\n </axp-state-message>\n }\n\n <!-- Error State -->\n @if ((error$ | async) && !(isLoading$ | async)) {\n <axp-state-message\n mode=\"error\"\n icon=\"fa-solid fa-exclamation-triangle\"\n [title]=\"'@auth:state-message.error.title'\"\n [description]=\"(error$ | async) || '@auth:state-message.error.description'\"\n >\n <div slot=\"actions\" class=\"flex flex-col gap-2 sm:flex-row sm:justify-center\">\n <ax-button\n color=\"primary\"\n [text]=\"('@auth:startup-error.retry' | translate | async) ?? ''\"\n (onClick)=\"handleRetry()\"\n class=\"w-full sm:w-auto\"\n >\n </ax-button>\n <ax-button\n color=\"default\"\n [text]=\"('@general:errors.404.actions.go-home.title' | translate | async) ?? ''\"\n (onClick)=\"handleGoHome()\"\n class=\"w-full sm:w-auto\"\n >\n </ax-button>\n </div>\n </axp-state-message>\n }\n\n <!-- Success State (briefly shown before redirect) -->\n @if (!(isLoading$ | async) && !(error$ | async)) {\n <axp-state-message\n mode=\"success\"\n icon=\"fa-solid fa-check\"\n [title]=\"'@auth:state-message.success.title'\"\n [description]=\"'@auth:state-message.success.description'\"\n >\n </axp-state-message>\n }\n </div>\n </div>\n</ng-container>\n"],"names":["i2","i3"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AXPopupService } from '@acorex/components/popup';
|
|
2
2
|
import { AXPDialogOpener } from '@acorex-platform/framework-client/core';
|
|
3
|
-
import * as i5 from '@acorex/core/translation';
|
|
3
|
+
import * as i5$1 from '@acorex/core/translation';
|
|
4
4
|
import { AXTranslationService, AXTranslationModule } from '@acorex/core/translation';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
6
6
|
import { signal, inject, ChangeDetectorRef, ViewEncapsulation, ChangeDetectionStrategy, Component, Injectable } from '@angular/core';
|
|
@@ -17,12 +17,12 @@ import { AXBasePageComponent } from '@acorex/components/page';
|
|
|
17
17
|
import { AXFormatService, AXFormatModule } from '@acorex/core/format';
|
|
18
18
|
import { AXPSettingsService } from '@acorex-platform/framework-client/common';
|
|
19
19
|
import { AXPRegionalSetting } from '@acorex-platform/framework-shared/core';
|
|
20
|
-
import * as
|
|
20
|
+
import * as i5 from '@angular/common';
|
|
21
21
|
import { CommonModule } from '@angular/common';
|
|
22
22
|
import * as i1$1 from '@angular/forms';
|
|
23
23
|
import { FormsModule } from '@angular/forms';
|
|
24
24
|
import { AXP_AUTH_INACTIVE_SESSION_TERMINATION_OPTION_DEFINITIONS, AXPAuthSettings, isAuthInactiveSessionTerminationValue } from '@acorex-platform/module-auth-client/contracts';
|
|
25
|
-
import { A as AXMUserDeviceSessionsService } from './acorex-platform-module-auth-client-acorex-platform-module-auth-client-
|
|
25
|
+
import { A as AXMUserDeviceSessionsService } from './acorex-platform-module-auth-client-acorex-platform-module-auth-client-DINrCCAx.mjs';
|
|
26
26
|
|
|
27
27
|
//#endregion
|
|
28
28
|
//#region ----- Constants -----
|
|
@@ -220,7 +220,7 @@ class AXMUserSessionsComponent extends AXBasePageComponent {
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMUserSessionsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
223
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMUserSessionsComponent, isStandalone: true, selector: "axm-user-sessions", host: { classAttribute: "axm-user-sessions" }, usesInheritance: true, ngImport: i0, template: "<ax-content>\n <div class=\"axm-user-sessions__content flex flex-col gap-4 p-6 w-full min-w-0\">\n <!-- ----- This device (current session) ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.this-device.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--primary\">\n <i class=\"{{ getSessionIcon(activeSessionView()?.session) }}\"></i>\n </div>\n <!--->\n <!-- ----- Current session details when available ----- -->\n @if (activeSessionView(); as current) {\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ current.title }}</div>\n @if (current.subtitle) {\n <div class=\"font-normal text-sm\">{{ current.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ current.metaLabel }}</p>\n </div>\n }\n </div>\n\n <!--->\n <!-- ----- Other sessions: terminate-all + device list ----- -->\n @if (items().length > 0) {\n <!-- ----- Terminate all other sessions (never current) ----- -->\n <div\n class=\"axm-user-sessions__row cursor-pointer\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onTerminateAll()\"\n (keydown.enter)=\"onTerminateAll()\"\n >\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--danger\">\n <i class=\"ax-icon ax-icon-clear\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">\n {{ '@auth:sessions.terminate-all.title' | translate | async }}\n </div>\n <p class=\"axm-user-sessions__meta m-0 font-normal text-sm\">\n {{ '@auth:sessions.terminate-all.description' | translate | async }}\n </p>\n </div>\n </div>\n\n <!-- ----- Other active devices ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.active-devices.title' | translate | async }}\n </p>\n @for (item of items(); track item.id) {\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon\">\n <i class=\"{{ item.icon }}\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ item.title }}</div>\n @if (item.subtitle) {\n <div class=\"font-normal text-sm\">{{ item.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ item.metaLabel }}</p>\n </div>\n <ax-button\n class=\"axm-user-sessions__action\"\n look=\"blank\"\n color=\"danger\"\n [attr.aria-label]=\"('@general:actions.remove.title' | translate | async) ?? ''\"\n (onClick)=\"onTerminate(item.id)\"\n >\n <ax-icon icon=\"fa-light fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n }\n }\n </div>\n</ax-content>\n<ax-footer>\n <ax-suffix>\n <div class=\"axm-user-sessions__footer flex w-full min-w-0 flex-col gap-1 px-4 py-2\">\n <p class=\"m-0 text-start font-medium text-base text-danger-500\">\n {{ '@auth:sessions.terminate-old.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__footer-setting\">\n <div class=\"axm-user-sessions__footer-label font-normal text-base text-on-lightest text-start\">\n {{ '@auth:sessions.terminate-old.inactive-for' | translate | async }}\n </div>\n <div class=\"axm-user-sessions__footer-select\">\n <ax-select-box\n [ngModel]=\"expireTime()\"\n (onValueChanged)=\"onChangeSessionExpireTime($event)\"\n [dataSource]=\"dataSource\"\n textField=\"name\"\n valueField=\"id\"\n [placeholder]=\"('@auth:sessions.terminate-old.placeholder' | translate | async) ?? ''\"\n >\n </ax-select-box>\n </div>\n </div>\n </div>\n </ax-suffix>\n</ax-footer>\n", styles: ["@layer properties;.axm-user-sessions__content,.axm-user-sessions__footer{box-sizing:border-box}.axm-user-sessions__row{display:flex;width:100%;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-lightest-surface));background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 3);color:rgba(var(--ax-sys-color-on-lightest-surface))}.axm-user-sessions__icon{display:grid;width:calc(var(--spacing, .25rem) * 12);height:calc(var(--spacing, .25rem) * 12);flex-shrink:0;place-items:center;border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px}.axm-user-sessions__icon--primary{border-color:rgba(var(--ax-sys-color-primary-200));background-color:rgba(var(--ax-sys-color-primary-50));color:rgba(var(--ax-sys-color-primary-500))}.axm-user-sessions__icon--danger{border-color:rgba(var(--ax-sys-color-danger-200));background-color:rgba(var(--ax-sys-color-danger-50));color:rgba(var(--ax-sys-color-danger-500))}.axm-user-sessions__icon i{margin:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));--tw-leading: 1;line-height:1}.axm-user-sessions__meta{color:rgb(var(--ax-sys-color-on-lighter-surface))}.axm-user-sessions__action{pointer-events:auto;position:relative;z-index:10;flex-shrink:0;cursor:pointer}.axm-user-sessions__footer-setting{display:flex;width:100%;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.axm-user-sessions__footer-label{flex-shrink:0}.axm-user-sessions__footer-select{margin-inline-start:auto;min-width:calc(var(--spacing, .25rem) * 48);flex:0 1 18rem}@media(max-width:640px){.axm-user-sessions__footer-setting{flex-wrap:wrap}.axm-user-sessions__footer-select{margin-inline-start:0px;max-width:none;flex:1 1 100%}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.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: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i4.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type:
|
|
223
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", type: AXMUserSessionsComponent, isStandalone: true, selector: "axm-user-sessions", host: { classAttribute: "axm-user-sessions" }, usesInheritance: true, ngImport: i0, template: "<ax-content>\n <div class=\"axm-user-sessions__content flex flex-col gap-4 p-6 w-full min-w-0\">\n <!-- ----- This device (current session) ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.this-device.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--primary\">\n <i class=\"{{ getSessionIcon(activeSessionView()?.session) }}\"></i>\n </div>\n <!--->\n <!-- ----- Current session details when available ----- -->\n @if (activeSessionView(); as current) {\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ current.title }}</div>\n @if (current.subtitle) {\n <div class=\"font-normal text-sm\">{{ current.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ current.metaLabel }}</p>\n </div>\n }\n </div>\n\n <!--->\n <!-- ----- Other sessions: terminate-all + device list ----- -->\n @if (items().length > 0) {\n <!-- ----- Terminate all other sessions (never current) ----- -->\n <div\n class=\"axm-user-sessions__row cursor-pointer\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onTerminateAll()\"\n (keydown.enter)=\"onTerminateAll()\"\n >\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--danger\">\n <i class=\"ax-icon ax-icon-clear\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">\n {{ '@auth:sessions.terminate-all.title' | translate | async }}\n </div>\n <p class=\"axm-user-sessions__meta m-0 font-normal text-sm\">\n {{ '@auth:sessions.terminate-all.description' | translate | async }}\n </p>\n </div>\n </div>\n\n <!-- ----- Other active devices ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.active-devices.title' | translate | async }}\n </p>\n @for (item of items(); track item.id) {\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon\">\n <i class=\"{{ item.icon }}\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ item.title }}</div>\n @if (item.subtitle) {\n <div class=\"font-normal text-sm\">{{ item.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ item.metaLabel }}</p>\n </div>\n <ax-button\n class=\"axm-user-sessions__action\"\n look=\"blank\"\n color=\"danger\"\n [attr.aria-label]=\"('@general:actions.remove.title' | translate | async) ?? ''\"\n (onClick)=\"onTerminate(item.id)\"\n >\n <ax-icon icon=\"fa-light fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n }\n }\n </div>\n</ax-content>\n<ax-footer>\n <ax-suffix>\n <div class=\"axm-user-sessions__footer flex w-full min-w-0 flex-col gap-1 px-4 py-2\">\n <p class=\"m-0 text-start font-medium text-base text-danger-500\">\n {{ '@auth:sessions.terminate-old.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__footer-setting\">\n <div class=\"axm-user-sessions__footer-label font-normal text-base text-on-lightest text-start\">\n {{ '@auth:sessions.terminate-old.inactive-for' | translate | async }}\n </div>\n <div class=\"axm-user-sessions__footer-select\">\n <ax-select-box\n [ngModel]=\"expireTime()\"\n (onValueChanged)=\"onChangeSessionExpireTime($event)\"\n [dataSource]=\"dataSource\"\n textField=\"name\"\n valueField=\"id\"\n [placeholder]=\"('@auth:sessions.terminate-old.placeholder' | translate | async) ?? ''\"\n >\n </ax-select-box>\n </div>\n </div>\n </div>\n </ax-suffix>\n</ax-footer>\n", styles: ["@layer properties;.axm-user-sessions__content,.axm-user-sessions__footer{box-sizing:border-box}.axm-user-sessions__row{display:flex;width:100%;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 3);border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px;border-color:rgba(var(--ax-sys-color-lightest-surface));background-color:rgba(var(--ax-sys-color-lightest-surface));padding:calc(var(--spacing, .25rem) * 3);color:rgba(var(--ax-sys-color-on-lightest-surface))}.axm-user-sessions__icon{display:grid;width:calc(var(--spacing, .25rem) * 12);height:calc(var(--spacing, .25rem) * 12);flex-shrink:0;place-items:center;border-radius:var(--radius-lg, .5rem);border-style:var(--tw-border-style);border-width:1px}.axm-user-sessions__icon--primary{border-color:rgba(var(--ax-sys-color-primary-200));background-color:rgba(var(--ax-sys-color-primary-50));color:rgba(var(--ax-sys-color-primary-500))}.axm-user-sessions__icon--danger{border-color:rgba(var(--ax-sys-color-danger-200));background-color:rgba(var(--ax-sys-color-danger-50));color:rgba(var(--ax-sys-color-danger-500))}.axm-user-sessions__icon i{margin:0;font-size:var(--text-xl, 1.25rem);line-height:var(--tw-leading, var(--text-xl--line-height, calc(1.75 / 1.25)));--tw-leading: 1;line-height:1}.axm-user-sessions__meta{color:rgb(var(--ax-sys-color-on-lighter-surface))}.axm-user-sessions__action{pointer-events:auto;position:relative;z-index:10;flex-shrink:0;cursor:pointer}.axm-user-sessions__footer-setting{display:flex;width:100%;min-width:0px;align-items:center;gap:calc(var(--spacing, .25rem) * 3)}.axm-user-sessions__footer-label{flex-shrink:0}.axm-user-sessions__footer-select{margin-inline-start:auto;min-width:calc(var(--spacing, .25rem) * 48);flex:0 1 18rem}@media(max-width:640px){.axm-user-sessions__footer-setting{flex-wrap:wrap}.axm-user-sessions__footer-select{margin-inline-start:0px;max-width:none;flex:1 1 100%}}@property --tw-border-style{syntax: \"*\"; inherits: false; initial-value: solid;}@property --tw-leading{syntax: \"*\"; inherits: false;}@layer properties{@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style: solid;--tw-leading: initial}}}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n"], dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.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: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: AXFormatModule }, { kind: "ngmodule", type: AXSelectBoxModule }, { kind: "component", type: i4.AXSelectBoxComponent, selector: "ax-select-box", inputs: ["disabled", "readonly", "tabIndex", "placeholder", "minValue", "maxValue", "value", "state", "name", "id", "type", "look", "multiple", "valueField", "textField", "disabledField", "textTemplate", "selectedItems", "isItemTruncated", "showItemTooltip", "itemHeight", "maxVisibleItems", "dataSource", "minRecordsForSearch", "caption", "itemTemplate", "selectedTemplate", "emptyTemplate", "loadingTemplate", "dropdownWidth", "searchBoxAutoFocus"], outputs: ["valueChange", "stateChange", "onValueChanged", "onBlur", "onFocus", "readonlyChange", "disabledChange", "onOpened", "onClosed", "onItemSelected", "onItemClick"] }, { kind: "ngmodule", type: AXDropdownModule }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
224
224
|
}
|
|
225
225
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXMUserSessionsComponent, decorators: [{
|
|
226
226
|
type: Component,
|
|
@@ -271,4 +271,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
271
271
|
}] });
|
|
272
272
|
|
|
273
273
|
export { AXPOpenSessionsCommand };
|
|
274
|
-
//# sourceMappingURL=acorex-platform-module-auth-client-open-sessions.command-
|
|
274
|
+
//# sourceMappingURL=acorex-platform-module-auth-client-open-sessions.command-CwWtPiTG.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"acorex-platform-module-auth-client-open-sessions.command-Dq9eJ-bY.mjs","sources":["../../../../libs/modules/auth/client/src/lib/pages/account/user-sessions/user-sessions.component.ts","../../../../libs/modules/auth/client/src/lib/pages/account/user-sessions/user-sessions.component.html","../../../../libs/modules/auth/client/src/lib/commands/open-sessions.command.ts"],"sourcesContent":["import { AXButtonModule } from '@acorex/components/button';\nimport { AXDataSource, AXValueChangedEvent } from '@acorex/cdk/common';\nimport { AXDecoratorModule } from '@acorex/components/decorators';\nimport { AXDropdownModule } from '@acorex/components/dropdown';\nimport { AXPopoverModule } from '@acorex/components/popover';\nimport { AXSelectBoxModule } from '@acorex/components/select-box';\nimport { AXBasePageComponent } from '@acorex/components/page';\nimport { AXFormatModule, AXFormatService } from '@acorex/core/format';\nimport { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';\nimport { AXPSettingsService } from '@acorex-platform/framework-client/common';\nimport { AXPRegionalSetting } from '@acorex-platform/framework-shared/core';\nimport { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n inject,\n signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n AXPAuthInactiveSessionTerminationValue,\n AXPAuthSettings,\n AXP_AUTH_INACTIVE_SESSION_TERMINATION_OPTION_DEFINITIONS,\n isAuthInactiveSessionTerminationValue,\n} from '@acorex-platform/module-auth-client/contracts';\nimport { AXMSecurityManagementDeviceSessionsEntityModel } from '@acorex-platform/module-security-management-client/contracts';\nimport { AXMUserDeviceSessionsService } from './user-sessions.service';\n\n//#region ----- Types -----\n\ninterface TranslatedInactiveSessionTerminationOption {\n id: AXPAuthInactiveSessionTerminationValue;\n name: string;\n}\n\ninterface SessionListItem extends AXMSecurityManagementDeviceSessionsEntityModel {\n icon: string;\n title: string;\n subtitle: string;\n metaLabel: string;\n}\n\ninterface ActiveSessionView {\n session: AXMSecurityManagementDeviceSessionsEntityModel;\n title: string;\n subtitle: string;\n metaLabel: string;\n}\n\n//#endregion\n\n//#region ----- Constants -----\n\nconst ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000;\n\n//#endregion\n\n//#region ----- Helpers -----\n\nfunction parseSessionDate(value: Date | string | number | null | undefined): Date | undefined {\n if (value instanceof Date) {\n return Number.isNaN(value.getTime()) ? undefined : value;\n }\n if (typeof value === 'string' || typeof value === 'number') {\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? undefined : parsed;\n }\n return undefined;\n}\n\n/** Drops year tokens from a regional date pattern (keeps day/month + separators). */\nfunction omitYearFromDateFormat(format: string): string {\n let result = format.replace(/Y{2,4}/gi, '').replace(/y{2,4}/g, '');\n result = result.replace(/^[/\\-.\\s]+|[/\\-.\\s]+$/g, '');\n result = result.replace(/[/\\-.\\s]{2,}/g, (match) => match.charAt(0));\n return result.trim() || format;\n}\n\n//#endregion\n\n@Component({\n selector: 'axm-user-sessions',\n templateUrl: './user-sessions.component.html',\n styleUrl: './user-sessions.component.css',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'axm-user-sessions' },\n imports: [\n AXButtonModule,\n AXDecoratorModule,\n CommonModule,\n FormsModule,\n AXFormatModule,\n AXSelectBoxModule,\n AXDropdownModule,\n AXPopoverModule,\n AXTranslationModule,\n ],\n})\nexport class AXMUserSessionsComponent extends AXBasePageComponent {\n //#region ----- State -----\n\n items = signal<SessionListItem[]>([]);\n activeSessionView = signal<ActiveSessionView | undefined>(undefined);\n expireTime = signal<AXPAuthInactiveSessionTerminationValue | null>(null);\n\n //#endregion\n\n //#region ----- Services & Dependencies -----\n\n private readonly userDeviceSessionsService = inject(AXMUserDeviceSessionsService);\n private readonly settingsService = inject(AXPSettingsService);\n private readonly translateService = inject(AXTranslationService);\n private readonly formatService = inject(AXFormatService);\n private readonly cdRef = inject(ChangeDetectorRef);\n\n //#endregion\n\n //#region ----- Data Sources -----\n\n protected expirationItems: TranslatedInactiveSessionTerminationOption[] = [];\n\n protected dataSource = new AXDataSource<TranslatedInactiveSessionTerminationOption>({\n pageSize: 10,\n key: 'id',\n load: async () => ({\n items: this.expirationItems,\n total: this.expirationItems.length,\n }),\n });\n\n //#endregion\n\n //#region ----- Lifecycle -----\n\n constructor() {\n super();\n void this.loadUserSessions();\n }\n\n //#endregion\n\n //#region ----- UI Handlers -----\n\n getSessionIcon(session: AXMSecurityManagementDeviceSessionsEntityModel | undefined): string {\n if (!session) {\n return 'fa-solid fa-question';\n }\n\n const haystack = [session.browser, session.operatingSystem, session.deviceName]\n .map((part) => (part ?? '').toLowerCase())\n .join(' ');\n\n if (haystack.includes('firefox')) {\n return 'fa-brands fa-firefox';\n }\n if (haystack.includes('chrome') || haystack.includes('chromium')) {\n return 'fa-brands fa-chrome';\n }\n if (haystack.includes('edge')) {\n return 'fa-brands fa-edge';\n }\n if (haystack.includes('safari')) {\n return 'fa-brands fa-safari';\n }\n if (haystack.includes('opera')) {\n return 'fa-brands fa-opera';\n }\n if (haystack.includes('windows')) {\n return 'fa-brands fa-windows';\n }\n if (haystack.includes('mac') || haystack.includes('iphone') || haystack.includes('ipad') || haystack.includes('ios')) {\n return 'fa-brands fa-apple';\n }\n if (haystack.includes('android')) {\n return 'fa-brands fa-android';\n }\n if (haystack.includes('linux')) {\n return 'fa-brands fa-linux';\n }\n\n return 'fa-solid fa-desktop';\n }\n\n protected onChangeSessionExpireTime(e: AXValueChangedEvent): void {\n const selectedId = e.component.selectedItems[0]?.id as AXPAuthInactiveSessionTerminationValue | undefined;\n if (!selectedId) {\n return;\n }\n\n this.expireTime.set(selectedId);\n void this.userDeviceSessionsService.setInactiveSessionTermination(selectedId);\n }\n\n async onTerminate(sessionId: string | undefined): Promise<void> {\n if (!sessionId) {\n console.error('No item to terminate');\n return;\n }\n\n // Never terminate the current browser session from a row action.\n if (sessionId === this.activeSessionView()?.session.id) {\n return;\n }\n\n await this.userDeviceSessionsService.terminateSession(sessionId);\n await this.loadUserSessions();\n }\n\n async onTerminateAll(): Promise<void> {\n await this.userDeviceSessionsService.terminateAllSession();\n await this.loadUserSessions();\n }\n\n //#endregion\n\n //#region ----- Private Methods -----\n\n private async resolveSessionMeta(\n session: AXMSecurityManagementDeviceSessionsEntityModel,\n ): Promise<string> {\n const place =\n (session.location ?? '').trim() ||\n (await this.translateService.translateAsync('@auth:sessions.meta.unknown-location'));\n const detailParts = [place, (session.ipAddress ?? '').trim()].filter(Boolean);\n const placeAndIp = detailParts.join(' · ');\n const lastSeen = await this.resolveLastSeenLabel(session.lastLoginDate);\n if (!lastSeen) {\n return placeAndIp;\n }\n return `${placeAndIp}, ${lastSeen}`;\n }\n\n private formatSessionTitle(session: AXMSecurityManagementDeviceSessionsEntityModel): string {\n return [session.deviceName, session.browser]\n .map((part) => (part ?? '').trim())\n .filter(Boolean)\n .join(' · ');\n }\n\n private formatSessionSubtitle(session: AXMSecurityManagementDeviceSessionsEntityModel): string {\n return (session.operatingSystem ?? '').trim();\n }\n\n private async resolveLastSeenLabel(\n lastLoginDate: Date | string | number | null | undefined,\n ): Promise<string> {\n const date = parseSessionDate(lastLoginDate);\n if (!date) {\n return '';\n }\n\n const ageMs = Date.now() - date.getTime();\n if (ageMs >= 0 && ageMs < ONE_WEEK_MS) {\n return this.formatService.format(date, 'timeleft');\n }\n\n const dateFormat = await this.settingsService.get<string>(AXPRegionalSetting.ShortDate);\n const timeFormat = await this.settingsService.get<string>(AXPRegionalSetting.ShortTime);\n const sameYear = date.getFullYear() === new Date().getFullYear();\n const datePart = sameYear ? omitYearFromDateFormat(dateFormat ?? '') : (dateFormat ?? '');\n const format = `${datePart} ${timeFormat ?? ''}`.trim();\n return this.formatService.format(date, 'datetime', { format });\n }\n\n private async loadUserSessions(): Promise<void> {\n try {\n // Options come from the auth settings definition (shared contracts catalog).\n this.expirationItems = await Promise.all(\n AXP_AUTH_INACTIVE_SESSION_TERMINATION_OPTION_DEFINITIONS.map(async (option) => ({\n id: option.id,\n name: await this.translateService.translateAsync(option.titleKey),\n })),\n );\n\n const sessions = await this.userDeviceSessionsService.getSessions();\n const items = await Promise.all(\n sessions.map(async (item) => ({\n ...item,\n icon: this.getSessionIcon(item),\n title: this.formatSessionTitle(item),\n subtitle: this.formatSessionSubtitle(item),\n metaLabel: await this.resolveSessionMeta(item),\n })),\n );\n this.items.set(items);\n\n try {\n const activeSession = await this.userDeviceSessionsService.getCurrentActiveSessions();\n this.activeSessionView.set({\n session: activeSession,\n title: this.formatSessionTitle(activeSession),\n subtitle: this.formatSessionSubtitle(activeSession),\n metaLabel: await this.resolveSessionMeta(activeSession),\n });\n } catch (error) {\n console.warn('No active session found:', error);\n this.activeSessionView.set(undefined);\n }\n\n const inactiveSessionTermination = await this.settingsService.get(\n AXPAuthSettings.InactiveSessionTermination,\n );\n\n if (isAuthInactiveSessionTerminationValue(inactiveSessionTermination)) {\n this.expireTime.set(inactiveSessionTermination);\n }\n\n await this.dataSource.refresh();\n this.cdRef.markForCheck();\n } catch (error) {\n console.error('Error loading user sessions', error);\n }\n }\n\n //#endregion\n}\n","<ax-content>\n <div class=\"axm-user-sessions__content flex flex-col gap-4 p-6 w-full min-w-0\">\n <!-- ----- This device (current session) ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.this-device.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--primary\">\n <i class=\"{{ getSessionIcon(activeSessionView()?.session) }}\"></i>\n </div>\n <!--->\n <!-- ----- Current session details when available ----- -->\n @if (activeSessionView(); as current) {\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ current.title }}</div>\n @if (current.subtitle) {\n <div class=\"font-normal text-sm\">{{ current.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ current.metaLabel }}</p>\n </div>\n }\n </div>\n\n <!--->\n <!-- ----- Other sessions: terminate-all + device list ----- -->\n @if (items().length > 0) {\n <!-- ----- Terminate all other sessions (never current) ----- -->\n <div\n class=\"axm-user-sessions__row cursor-pointer\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onTerminateAll()\"\n (keydown.enter)=\"onTerminateAll()\"\n >\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--danger\">\n <i class=\"ax-icon ax-icon-clear\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">\n {{ '@auth:sessions.terminate-all.title' | translate | async }}\n </div>\n <p class=\"axm-user-sessions__meta m-0 font-normal text-sm\">\n {{ '@auth:sessions.terminate-all.description' | translate | async }}\n </p>\n </div>\n </div>\n\n <!-- ----- Other active devices ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.active-devices.title' | translate | async }}\n </p>\n @for (item of items(); track item.id) {\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon\">\n <i class=\"{{ item.icon }}\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ item.title }}</div>\n @if (item.subtitle) {\n <div class=\"font-normal text-sm\">{{ item.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ item.metaLabel }}</p>\n </div>\n <ax-button\n class=\"axm-user-sessions__action\"\n look=\"blank\"\n color=\"danger\"\n [attr.aria-label]=\"('@general:actions.remove.title' | translate | async) ?? ''\"\n (onClick)=\"onTerminate(item.id)\"\n >\n <ax-icon icon=\"fa-light fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n }\n }\n </div>\n</ax-content>\n<ax-footer>\n <ax-suffix>\n <div class=\"axm-user-sessions__footer flex w-full min-w-0 flex-col gap-1 px-4 py-2\">\n <p class=\"m-0 text-start font-medium text-base text-danger-500\">\n {{ '@auth:sessions.terminate-old.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__footer-setting\">\n <div class=\"axm-user-sessions__footer-label font-normal text-base text-on-lightest text-start\">\n {{ '@auth:sessions.terminate-old.inactive-for' | translate | async }}\n </div>\n <div class=\"axm-user-sessions__footer-select\">\n <ax-select-box\n [ngModel]=\"expireTime()\"\n (onValueChanged)=\"onChangeSessionExpireTime($event)\"\n [dataSource]=\"dataSource\"\n textField=\"name\"\n valueField=\"id\"\n [placeholder]=\"('@auth:sessions.terminate-old.placeholder' | translate | async) ?? ''\"\n >\n </ax-select-box>\n </div>\n </div>\n </div>\n </ax-suffix>\n</ax-footer>\n","import { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { AXPopupService } from '@acorex/components/popup';\nimport { AXPDialogOpener } from '@acorex-platform/framework-client/core';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXPRuntimeCommandResult } from '@acorex-platform/framework-shared/core';\n\nimport { inject, Injectable } from '@angular/core';\nimport { AXMUserSessionsComponent } from '../pages/account/user-sessions/user-sessions.component';\n\n//#region ---- Open sessions command ----\n\n/** Opens the active sessions popup for the current user. */\n@Injectable({ providedIn: 'root' })\nexport class AXPOpenSessionsCommand implements AXPCommand {\n //#region ---- Services & Dependencies ----\n\n private readonly popupService = inject(AXPopupService);\n private readonly dialogOpener = inject(AXPDialogOpener);\n private readonly translateService = inject(AXTranslationService);\n\n //#endregion\n\n //#region ---- Command ----\n\n async execute(): AXPCommandExecuteResultPromise<void> {\n let title = '';\n await this.dialogOpener.openPopup({\n load: () => Promise.resolve(AXMUserSessionsComponent),\n prepare: async () => {\n title = await this.translateService.translateAsync('@auth:profile.sessions');\n },\n show: (component) =>\n this.popupService.open(component, {\n title,\n size: 'md',\n }),\n });\n\n return { success: true, kind: 'object', data: undefined };\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":["i3","i5","i6"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"acorex-platform-module-auth-client-open-sessions.command-CwWtPiTG.mjs","sources":["../../../../libs/modules/auth/client/src/lib/pages/account/user-sessions/user-sessions.component.ts","../../../../libs/modules/auth/client/src/lib/pages/account/user-sessions/user-sessions.component.html","../../../../libs/modules/auth/client/src/lib/commands/open-sessions.command.ts"],"sourcesContent":["import { AXButtonModule } from '@acorex/components/button';\nimport { AXDataSource, AXValueChangedEvent } from '@acorex/cdk/common';\nimport { AXDecoratorModule } from '@acorex/components/decorators';\nimport { AXDropdownModule } from '@acorex/components/dropdown';\nimport { AXPopoverModule } from '@acorex/components/popover';\nimport { AXSelectBoxModule } from '@acorex/components/select-box';\nimport { AXBasePageComponent } from '@acorex/components/page';\nimport { AXFormatModule, AXFormatService } from '@acorex/core/format';\nimport { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';\nimport { AXPSettingsService } from '@acorex-platform/framework-client/common';\nimport { AXPRegionalSetting } from '@acorex-platform/framework-shared/core';\nimport { CommonModule } from '@angular/common';\nimport {\n ChangeDetectionStrategy,\n ChangeDetectorRef,\n Component,\n inject,\n signal,\n ViewEncapsulation,\n} from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport {\n AXPAuthInactiveSessionTerminationValue,\n AXPAuthSettings,\n AXP_AUTH_INACTIVE_SESSION_TERMINATION_OPTION_DEFINITIONS,\n isAuthInactiveSessionTerminationValue,\n} from '@acorex-platform/module-auth-client/contracts';\nimport { AXMSecurityManagementDeviceSessionsEntityModel } from '@acorex-platform/module-security-management-client/contracts';\nimport { AXMUserDeviceSessionsService } from './user-sessions.service';\n\n//#region ----- Types -----\n\ninterface TranslatedInactiveSessionTerminationOption {\n id: AXPAuthInactiveSessionTerminationValue;\n name: string;\n}\n\ninterface SessionListItem extends AXMSecurityManagementDeviceSessionsEntityModel {\n icon: string;\n title: string;\n subtitle: string;\n metaLabel: string;\n}\n\ninterface ActiveSessionView {\n session: AXMSecurityManagementDeviceSessionsEntityModel;\n title: string;\n subtitle: string;\n metaLabel: string;\n}\n\n//#endregion\n\n//#region ----- Constants -----\n\nconst ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000;\n\n//#endregion\n\n//#region ----- Helpers -----\n\nfunction parseSessionDate(value: Date | string | number | null | undefined): Date | undefined {\n if (value instanceof Date) {\n return Number.isNaN(value.getTime()) ? undefined : value;\n }\n if (typeof value === 'string' || typeof value === 'number') {\n const parsed = new Date(value);\n return Number.isNaN(parsed.getTime()) ? undefined : parsed;\n }\n return undefined;\n}\n\n/** Drops year tokens from a regional date pattern (keeps day/month + separators). */\nfunction omitYearFromDateFormat(format: string): string {\n let result = format.replace(/Y{2,4}/gi, '').replace(/y{2,4}/g, '');\n result = result.replace(/^[/\\-.\\s]+|[/\\-.\\s]+$/g, '');\n result = result.replace(/[/\\-.\\s]{2,}/g, (match) => match.charAt(0));\n return result.trim() || format;\n}\n\n//#endregion\n\n@Component({\n selector: 'axm-user-sessions',\n templateUrl: './user-sessions.component.html',\n styleUrl: './user-sessions.component.css',\n changeDetection: ChangeDetectionStrategy.OnPush,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'axm-user-sessions' },\n imports: [\n AXButtonModule,\n AXDecoratorModule,\n CommonModule,\n FormsModule,\n AXFormatModule,\n AXSelectBoxModule,\n AXDropdownModule,\n AXPopoverModule,\n AXTranslationModule,\n ],\n})\nexport class AXMUserSessionsComponent extends AXBasePageComponent {\n //#region ----- State -----\n\n items = signal<SessionListItem[]>([]);\n activeSessionView = signal<ActiveSessionView | undefined>(undefined);\n expireTime = signal<AXPAuthInactiveSessionTerminationValue | null>(null);\n\n //#endregion\n\n //#region ----- Services & Dependencies -----\n\n private readonly userDeviceSessionsService = inject(AXMUserDeviceSessionsService);\n private readonly settingsService = inject(AXPSettingsService);\n private readonly translateService = inject(AXTranslationService);\n private readonly formatService = inject(AXFormatService);\n private readonly cdRef = inject(ChangeDetectorRef);\n\n //#endregion\n\n //#region ----- Data Sources -----\n\n protected expirationItems: TranslatedInactiveSessionTerminationOption[] = [];\n\n protected dataSource = new AXDataSource<TranslatedInactiveSessionTerminationOption>({\n pageSize: 10,\n key: 'id',\n load: async () => ({\n items: this.expirationItems,\n total: this.expirationItems.length,\n }),\n });\n\n //#endregion\n\n //#region ----- Lifecycle -----\n\n constructor() {\n super();\n void this.loadUserSessions();\n }\n\n //#endregion\n\n //#region ----- UI Handlers -----\n\n getSessionIcon(session: AXMSecurityManagementDeviceSessionsEntityModel | undefined): string {\n if (!session) {\n return 'fa-solid fa-question';\n }\n\n const haystack = [session.browser, session.operatingSystem, session.deviceName]\n .map((part) => (part ?? '').toLowerCase())\n .join(' ');\n\n if (haystack.includes('firefox')) {\n return 'fa-brands fa-firefox';\n }\n if (haystack.includes('chrome') || haystack.includes('chromium')) {\n return 'fa-brands fa-chrome';\n }\n if (haystack.includes('edge')) {\n return 'fa-brands fa-edge';\n }\n if (haystack.includes('safari')) {\n return 'fa-brands fa-safari';\n }\n if (haystack.includes('opera')) {\n return 'fa-brands fa-opera';\n }\n if (haystack.includes('windows')) {\n return 'fa-brands fa-windows';\n }\n if (haystack.includes('mac') || haystack.includes('iphone') || haystack.includes('ipad') || haystack.includes('ios')) {\n return 'fa-brands fa-apple';\n }\n if (haystack.includes('android')) {\n return 'fa-brands fa-android';\n }\n if (haystack.includes('linux')) {\n return 'fa-brands fa-linux';\n }\n\n return 'fa-solid fa-desktop';\n }\n\n protected onChangeSessionExpireTime(e: AXValueChangedEvent): void {\n const selectedId = e.component.selectedItems[0]?.id as AXPAuthInactiveSessionTerminationValue | undefined;\n if (!selectedId) {\n return;\n }\n\n this.expireTime.set(selectedId);\n void this.userDeviceSessionsService.setInactiveSessionTermination(selectedId);\n }\n\n async onTerminate(sessionId: string | undefined): Promise<void> {\n if (!sessionId) {\n console.error('No item to terminate');\n return;\n }\n\n // Never terminate the current browser session from a row action.\n if (sessionId === this.activeSessionView()?.session.id) {\n return;\n }\n\n await this.userDeviceSessionsService.terminateSession(sessionId);\n await this.loadUserSessions();\n }\n\n async onTerminateAll(): Promise<void> {\n await this.userDeviceSessionsService.terminateAllSession();\n await this.loadUserSessions();\n }\n\n //#endregion\n\n //#region ----- Private Methods -----\n\n private async resolveSessionMeta(\n session: AXMSecurityManagementDeviceSessionsEntityModel,\n ): Promise<string> {\n const place =\n (session.location ?? '').trim() ||\n (await this.translateService.translateAsync('@auth:sessions.meta.unknown-location'));\n const detailParts = [place, (session.ipAddress ?? '').trim()].filter(Boolean);\n const placeAndIp = detailParts.join(' · ');\n const lastSeen = await this.resolveLastSeenLabel(session.lastLoginDate);\n if (!lastSeen) {\n return placeAndIp;\n }\n return `${placeAndIp}, ${lastSeen}`;\n }\n\n private formatSessionTitle(session: AXMSecurityManagementDeviceSessionsEntityModel): string {\n return [session.deviceName, session.browser]\n .map((part) => (part ?? '').trim())\n .filter(Boolean)\n .join(' · ');\n }\n\n private formatSessionSubtitle(session: AXMSecurityManagementDeviceSessionsEntityModel): string {\n return (session.operatingSystem ?? '').trim();\n }\n\n private async resolveLastSeenLabel(\n lastLoginDate: Date | string | number | null | undefined,\n ): Promise<string> {\n const date = parseSessionDate(lastLoginDate);\n if (!date) {\n return '';\n }\n\n const ageMs = Date.now() - date.getTime();\n if (ageMs >= 0 && ageMs < ONE_WEEK_MS) {\n return this.formatService.format(date, 'timeleft');\n }\n\n const dateFormat = await this.settingsService.get<string>(AXPRegionalSetting.ShortDate);\n const timeFormat = await this.settingsService.get<string>(AXPRegionalSetting.ShortTime);\n const sameYear = date.getFullYear() === new Date().getFullYear();\n const datePart = sameYear ? omitYearFromDateFormat(dateFormat ?? '') : (dateFormat ?? '');\n const format = `${datePart} ${timeFormat ?? ''}`.trim();\n return this.formatService.format(date, 'datetime', { format });\n }\n\n private async loadUserSessions(): Promise<void> {\n try {\n // Options come from the auth settings definition (shared contracts catalog).\n this.expirationItems = await Promise.all(\n AXP_AUTH_INACTIVE_SESSION_TERMINATION_OPTION_DEFINITIONS.map(async (option) => ({\n id: option.id,\n name: await this.translateService.translateAsync(option.titleKey),\n })),\n );\n\n const sessions = await this.userDeviceSessionsService.getSessions();\n const items = await Promise.all(\n sessions.map(async (item) => ({\n ...item,\n icon: this.getSessionIcon(item),\n title: this.formatSessionTitle(item),\n subtitle: this.formatSessionSubtitle(item),\n metaLabel: await this.resolveSessionMeta(item),\n })),\n );\n this.items.set(items);\n\n try {\n const activeSession = await this.userDeviceSessionsService.getCurrentActiveSessions();\n this.activeSessionView.set({\n session: activeSession,\n title: this.formatSessionTitle(activeSession),\n subtitle: this.formatSessionSubtitle(activeSession),\n metaLabel: await this.resolveSessionMeta(activeSession),\n });\n } catch (error) {\n console.warn('No active session found:', error);\n this.activeSessionView.set(undefined);\n }\n\n const inactiveSessionTermination = await this.settingsService.get(\n AXPAuthSettings.InactiveSessionTermination,\n );\n\n if (isAuthInactiveSessionTerminationValue(inactiveSessionTermination)) {\n this.expireTime.set(inactiveSessionTermination);\n }\n\n await this.dataSource.refresh();\n this.cdRef.markForCheck();\n } catch (error) {\n console.error('Error loading user sessions', error);\n }\n }\n\n //#endregion\n}\n","<ax-content>\n <div class=\"axm-user-sessions__content flex flex-col gap-4 p-6 w-full min-w-0\">\n <!-- ----- This device (current session) ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.this-device.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--primary\">\n <i class=\"{{ getSessionIcon(activeSessionView()?.session) }}\"></i>\n </div>\n <!--->\n <!-- ----- Current session details when available ----- -->\n @if (activeSessionView(); as current) {\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ current.title }}</div>\n @if (current.subtitle) {\n <div class=\"font-normal text-sm\">{{ current.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ current.metaLabel }}</p>\n </div>\n }\n </div>\n\n <!--->\n <!-- ----- Other sessions: terminate-all + device list ----- -->\n @if (items().length > 0) {\n <!-- ----- Terminate all other sessions (never current) ----- -->\n <div\n class=\"axm-user-sessions__row cursor-pointer\"\n role=\"button\"\n tabindex=\"0\"\n (click)=\"onTerminateAll()\"\n (keydown.enter)=\"onTerminateAll()\"\n >\n <div class=\"axm-user-sessions__icon axm-user-sessions__icon--danger\">\n <i class=\"ax-icon ax-icon-clear\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">\n {{ '@auth:sessions.terminate-all.title' | translate | async }}\n </div>\n <p class=\"axm-user-sessions__meta m-0 font-normal text-sm\">\n {{ '@auth:sessions.terminate-all.description' | translate | async }}\n </p>\n </div>\n </div>\n\n <!-- ----- Other active devices ----- -->\n <p class=\"font-semibold text-base text-on-lightest text-start m-0\">\n {{ '@auth:sessions.active-devices.title' | translate | async }}\n </p>\n @for (item of items(); track item.id) {\n <div class=\"axm-user-sessions__row\">\n <div class=\"axm-user-sessions__icon\">\n <i class=\"{{ item.icon }}\"></i>\n </div>\n <div class=\"flex min-w-0 flex-1 flex-col text-start\">\n <div class=\"font-medium text-base\">{{ item.title }}</div>\n @if (item.subtitle) {\n <div class=\"font-normal text-sm\">{{ item.subtitle }}</div>\n }\n <p class=\"axm-user-sessions__meta m-0 font-normal text-xs\">{{ item.metaLabel }}</p>\n </div>\n <ax-button\n class=\"axm-user-sessions__action\"\n look=\"blank\"\n color=\"danger\"\n [attr.aria-label]=\"('@general:actions.remove.title' | translate | async) ?? ''\"\n (onClick)=\"onTerminate(item.id)\"\n >\n <ax-icon icon=\"fa-light fa-xmark\"></ax-icon>\n </ax-button>\n </div>\n }\n }\n </div>\n</ax-content>\n<ax-footer>\n <ax-suffix>\n <div class=\"axm-user-sessions__footer flex w-full min-w-0 flex-col gap-1 px-4 py-2\">\n <p class=\"m-0 text-start font-medium text-base text-danger-500\">\n {{ '@auth:sessions.terminate-old.title' | translate | async }}\n </p>\n <div class=\"axm-user-sessions__footer-setting\">\n <div class=\"axm-user-sessions__footer-label font-normal text-base text-on-lightest text-start\">\n {{ '@auth:sessions.terminate-old.inactive-for' | translate | async }}\n </div>\n <div class=\"axm-user-sessions__footer-select\">\n <ax-select-box\n [ngModel]=\"expireTime()\"\n (onValueChanged)=\"onChangeSessionExpireTime($event)\"\n [dataSource]=\"dataSource\"\n textField=\"name\"\n valueField=\"id\"\n [placeholder]=\"('@auth:sessions.terminate-old.placeholder' | translate | async) ?? ''\"\n >\n </ax-select-box>\n </div>\n </div>\n </div>\n </ax-suffix>\n</ax-footer>\n","import { AXPCommand, type AXPCommandExecuteResultPromise } from '@acorex-platform/framework-shared/runtime';\nimport { AXPopupService } from '@acorex/components/popup';\nimport { AXPDialogOpener } from '@acorex-platform/framework-client/core';\nimport { AXTranslationService } from '@acorex/core/translation';\nimport { AXPRuntimeCommandResult } from '@acorex-platform/framework-shared/core';\n\nimport { inject, Injectable } from '@angular/core';\nimport { AXMUserSessionsComponent } from '../pages/account/user-sessions/user-sessions.component';\n\n//#region ---- Open sessions command ----\n\n/** Opens the active sessions popup for the current user. */\n@Injectable({ providedIn: 'root' })\nexport class AXPOpenSessionsCommand implements AXPCommand {\n //#region ---- Services & Dependencies ----\n\n private readonly popupService = inject(AXPopupService);\n private readonly dialogOpener = inject(AXPDialogOpener);\n private readonly translateService = inject(AXTranslationService);\n\n //#endregion\n\n //#region ---- Command ----\n\n async execute(): AXPCommandExecuteResultPromise<void> {\n let title = '';\n await this.dialogOpener.openPopup({\n load: () => Promise.resolve(AXMUserSessionsComponent),\n prepare: async () => {\n title = await this.translateService.translateAsync('@auth:profile.sessions');\n },\n show: (component) =>\n this.popupService.open(component, {\n title,\n size: 'md',\n }),\n });\n\n return { success: true, kind: 'object', data: undefined };\n }\n\n //#endregion\n}\n\n//#endregion\n"],"names":["i3","i6"],"mappings":"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"}
|
|
@@ -16,7 +16,7 @@ import * as i2 from '@acorex/components/text-box';
|
|
|
16
16
|
import { AXTextBoxModule } from '@acorex/components/text-box';
|
|
17
17
|
import * as i5 from '@acorex/core/translation';
|
|
18
18
|
import { AXTranslationModule, AXTranslationService } from '@acorex/core/translation';
|
|
19
|
-
import * as
|
|
19
|
+
import * as i5$1 from '@angular/common';
|
|
20
20
|
import { CommonModule } from '@angular/common';
|
|
21
21
|
import * as i0 from '@angular/core';
|
|
22
22
|
import { signal, ChangeDetectionStrategy, Component, inject, Injector, effect, ViewContainerRef, ViewChild } from '@angular/core';
|
|
@@ -30,7 +30,7 @@ import { AXPRegionalSetting } from '@acorex-platform/framework-shared/core';
|
|
|
30
30
|
import * as i1$2 from '@angular/forms';
|
|
31
31
|
import { FormsModule } from '@angular/forms';
|
|
32
32
|
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
|
33
|
-
import { F as AXPLoginExternalProvidersComponent, x as AXMAuthPlatformSettingsService, G as AXMAuthenticationTypes } from './acorex-platform-module-auth-client-acorex-platform-module-auth-client-
|
|
33
|
+
import { F as AXPLoginExternalProvidersComponent, x as AXMAuthPlatformSettingsService, G as AXMAuthenticationTypes } from './acorex-platform-module-auth-client-acorex-platform-module-auth-client-DINrCCAx.mjs';
|
|
34
34
|
import { w as writeTwoFactorChallenge } from './acorex-platform-module-auth-client-two-factor-challenge.storage-mi0UD7Sc.mjs';
|
|
35
35
|
|
|
36
36
|
//#region ---- Default Challenge Component ----
|
|
@@ -112,7 +112,7 @@ class AXPDefaultChallengeComponent extends AXPLoginChallengeComponentBase {
|
|
|
112
112
|
</ax-text-box>
|
|
113
113
|
</ax-form-field>
|
|
114
114
|
</div>
|
|
115
|
-
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "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: i4.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.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$1.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: i5.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type:
|
|
115
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "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: i4.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.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$1.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: i5.AXTranslatorPipe, name: "translate" }, { kind: "pipe", type: i5$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
116
116
|
}
|
|
117
117
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPDefaultChallengeComponent, decorators: [{
|
|
118
118
|
type: Component,
|
|
@@ -588,7 +588,7 @@ class AXPLoginPasswordComponent {
|
|
|
588
588
|
this.destroyChallengeComponent();
|
|
589
589
|
}
|
|
590
590
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPLoginPasswordComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
591
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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=\"axp-auth-form\">\n <div class=\"text-center mb-3 lg:mb-5\">\n <h1 class=\"font-bold text-xl mb-1 lg: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 <ax-form>\n <div class=\"flex flex-col gap-4 lg:gap-6\">\n <ax-form-field>\n <ax-label>{{ ('@auth:' + l1) | 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-4 lg: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() || signupEnabled) {\n <div class=\"my-5 lg:my-8 flex w-full items-center\">\n <div class=\"h-px flex-1 bg-border-lighter\"></div>\n <span class=\"px-3 text-xs font-medium tracking-wide text-neutral-400\">\n {{ '@auth:signin.or' | translate | async }}\n </span>\n <div class=\"h-px flex-1 bg-border-lighter\"></div>\n </div>\n }\n <axm-login-external-providers\n #externalProviders\n ></axm-login-external-providers>\n </ax-form>\n @if (signupEnabled) {\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", styles: [":host{display:block;width:100%}.axp-auth-form{width:100%;margin-inline:auto}@media(min-width:768px){.axp-auth-form{width:24rem;max-width:100%}}.axp-auth-form ax-form,.axp-auth-form ax-form-field,.axp-auth-form ax-text-box,.axp-auth-form ax-password-box{display:block;width:100%}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\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: i2$2.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", "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: i4.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: i5.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$1.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:
|
|
591
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.8", 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=\"axp-auth-form\">\n <div class=\"text-center mb-3 lg:mb-5\">\n <h1 class=\"font-bold text-xl mb-1 lg: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 <ax-form>\n <div class=\"flex flex-col gap-4 lg:gap-6\">\n <ax-form-field>\n <ax-label>{{ ('@auth:' + l1) | 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-4 lg: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() || signupEnabled) {\n <div class=\"my-5 lg:my-8 flex w-full items-center\">\n <div class=\"h-px flex-1 bg-border-lighter\"></div>\n <span class=\"px-3 text-xs font-medium tracking-wide text-neutral-400\">\n {{ '@auth:signin.or' | translate | async }}\n </span>\n <div class=\"h-px flex-1 bg-border-lighter\"></div>\n </div>\n }\n <axm-login-external-providers\n #externalProviders\n ></axm-login-external-providers>\n </ax-form>\n @if (signupEnabled) {\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", styles: [":host{display:block;width:100%}.axp-auth-form{width:100%;margin-inline:auto}@media(min-width:768px){.axp-auth-form{width:24rem;max-width:100%}}.axp-auth-form ax-form,.axp-auth-form ax-form-field,.axp-auth-form ax-text-box,.axp-auth-form ax-password-box{display:block;width:100%}\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\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: i2$2.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", "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: i4.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: i5.AXTranslatorDirective, selector: "[translate]" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i2$1.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: i5$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
|
|
592
592
|
}
|
|
593
593
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImport: i0, type: AXPLoginPasswordComponent, decorators: [{
|
|
594
594
|
type: Component,
|
|
@@ -602,4 +602,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.8", ngImpor
|
|
|
602
602
|
}] } });
|
|
603
603
|
|
|
604
604
|
export { AXPLoginPasswordComponent };
|
|
605
|
-
//# sourceMappingURL=acorex-platform-module-auth-client-password.component-
|
|
605
|
+
//# sourceMappingURL=acorex-platform-module-auth-client-password.component-CAZ3tVPG.mjs.map
|