@acorex-platform/module-auth-client 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/fesm2022/{acorex-platform-module-auth-client-acorex-platform-module-auth-client-Dgo6MzxI.mjs → acorex-platform-module-auth-client-acorex-platform-module-auth-client-CBRlR1xT.mjs} +106 -80
  2. package/fesm2022/acorex-platform-module-auth-client-acorex-platform-module-auth-client-CBRlR1xT.mjs.map +1 -0
  3. package/fesm2022/{acorex-platform-module-auth-client-app-chooser.component-nSUtqF_D.mjs → acorex-platform-module-auth-client-app-chooser.component-DpGdObrH.mjs} +2 -2
  4. package/fesm2022/{acorex-platform-module-auth-client-app-chooser.component-nSUtqF_D.mjs.map → acorex-platform-module-auth-client-app-chooser.component-DpGdObrH.mjs.map} +1 -1
  5. package/fesm2022/{acorex-platform-module-auth-client-change-password.command-Bman8avz.mjs → acorex-platform-module-auth-client-change-password.command-Bt4yOMMt.mjs} +2 -2
  6. package/fesm2022/{acorex-platform-module-auth-client-change-password.command-Bman8avz.mjs.map → acorex-platform-module-auth-client-change-password.command-Bt4yOMMt.mjs.map} +1 -1
  7. package/fesm2022/{acorex-platform-module-auth-client-change-photo.command-DFS8TE__.mjs → acorex-platform-module-auth-client-change-photo.command-tZ3TnzBz.mjs} +2 -2
  8. package/fesm2022/{acorex-platform-module-auth-client-change-photo.command-DFS8TE__.mjs.map → acorex-platform-module-auth-client-change-photo.command-tZ3TnzBz.mjs.map} +1 -1
  9. package/fesm2022/{acorex-platform-module-auth-client-get-user-activity.query-ZTJMfhir.mjs → acorex-platform-module-auth-client-get-user-activity.query-BxoUkan6.mjs} +2 -2
  10. package/fesm2022/{acorex-platform-module-auth-client-get-user-activity.query-ZTJMfhir.mjs.map → acorex-platform-module-auth-client-get-user-activity.query-BxoUkan6.mjs.map} +1 -1
  11. package/fesm2022/{acorex-platform-module-auth-client-lock-screen.command-CUs7Q6yh.mjs → acorex-platform-module-auth-client-lock-screen.command-QXW3UCik.mjs} +2 -2
  12. package/fesm2022/{acorex-platform-module-auth-client-lock-screen.command-CUs7Q6yh.mjs.map → acorex-platform-module-auth-client-lock-screen.command-QXW3UCik.mjs.map} +1 -1
  13. package/fesm2022/{acorex-platform-module-auth-client-login.module-DFWtA7S3.mjs → acorex-platform-module-auth-client-login.module-dy4_aiwN.mjs} +3 -3
  14. package/fesm2022/{acorex-platform-module-auth-client-login.module-DFWtA7S3.mjs.map → acorex-platform-module-auth-client-login.module-dy4_aiwN.mjs.map} +1 -1
  15. package/fesm2022/{acorex-platform-module-auth-client-manage-two-factor.command-BXK7Lvpw.mjs → acorex-platform-module-auth-client-manage-two-factor.command-Cal6EJe0.mjs} +2 -2
  16. package/fesm2022/{acorex-platform-module-auth-client-manage-two-factor.command-BXK7Lvpw.mjs.map → acorex-platform-module-auth-client-manage-two-factor.command-Cal6EJe0.mjs.map} +1 -1
  17. package/fesm2022/{acorex-platform-module-auth-client-open-sessions.command-DToDT9eb.mjs → acorex-platform-module-auth-client-open-sessions.command-ZG33hlfh.mjs} +3 -3
  18. package/fesm2022/{acorex-platform-module-auth-client-open-sessions.command-DToDT9eb.mjs.map → acorex-platform-module-auth-client-open-sessions.command-ZG33hlfh.mjs.map} +1 -1
  19. package/fesm2022/{acorex-platform-module-auth-client-password.component-DAp_-zko.mjs → acorex-platform-module-auth-client-password.component-D0pwQEaB.mjs} +2 -2
  20. package/fesm2022/{acorex-platform-module-auth-client-password.component-DAp_-zko.mjs.map → acorex-platform-module-auth-client-password.component-D0pwQEaB.mjs.map} +1 -1
  21. package/fesm2022/{acorex-platform-module-auth-client-profile-activity-chart.component-CLW52NUu.mjs → acorex-platform-module-auth-client-profile-activity-chart.component-DJKJdwUC.mjs} +2 -2
  22. package/fesm2022/{acorex-platform-module-auth-client-profile-activity-chart.component-CLW52NUu.mjs.map → acorex-platform-module-auth-client-profile-activity-chart.component-DJKJdwUC.mjs.map} +1 -1
  23. package/fesm2022/{acorex-platform-module-auth-client-profile-page-component.provider-D5xhGDPH.mjs → acorex-platform-module-auth-client-profile-page-component.provider-CSNCpJTo.mjs} +3 -3
  24. package/fesm2022/{acorex-platform-module-auth-client-profile-page-component.provider-D5xhGDPH.mjs.map → acorex-platform-module-auth-client-profile-page-component.provider-CSNCpJTo.mjs.map} +1 -1
  25. package/fesm2022/{acorex-platform-module-auth-client-profile-page.component-Dc7gRTQD.mjs → acorex-platform-module-auth-client-profile-page.component-BM6a4K1A.mjs} +2 -2
  26. package/fesm2022/{acorex-platform-module-auth-client-profile-page.component-Dc7gRTQD.mjs.map → acorex-platform-module-auth-client-profile-page.component-BM6a4K1A.mjs.map} +1 -1
  27. package/fesm2022/{acorex-platform-module-auth-client-register-password.component-C4zu5hpL.mjs → acorex-platform-module-auth-client-register-password.component-BxQNY-Nh.mjs} +2 -2
  28. package/fesm2022/{acorex-platform-module-auth-client-register-password.component-C4zu5hpL.mjs.map → acorex-platform-module-auth-client-register-password.component-BxQNY-Nh.mjs.map} +1 -1
  29. package/fesm2022/{acorex-platform-module-auth-client-register.module-Dz-SOKXN.mjs → acorex-platform-module-auth-client-register.module-BLQWaJky.mjs} +3 -3
  30. package/fesm2022/{acorex-platform-module-auth-client-register.module-Dz-SOKXN.mjs.map → acorex-platform-module-auth-client-register.module-BLQWaJky.mjs.map} +1 -1
  31. package/fesm2022/{acorex-platform-module-auth-client-remove-pin-code.command-LKjypQTk.mjs → acorex-platform-module-auth-client-remove-pin-code.command-DyO4Oj2C.mjs} +2 -2
  32. package/fesm2022/{acorex-platform-module-auth-client-remove-pin-code.command-LKjypQTk.mjs.map → acorex-platform-module-auth-client-remove-pin-code.command-DyO4Oj2C.mjs.map} +1 -1
  33. package/fesm2022/{acorex-platform-module-auth-client-routes-Dw8YhBrw.mjs → acorex-platform-module-auth-client-routes-DAwpb1Ca.mjs} +2 -2
  34. package/fesm2022/{acorex-platform-module-auth-client-routes-Dw8YhBrw.mjs.map → acorex-platform-module-auth-client-routes-DAwpb1Ca.mjs.map} +1 -1
  35. package/fesm2022/{acorex-platform-module-auth-client-session-lock-overlay.component-PQ91EQjh.mjs → acorex-platform-module-auth-client-session-lock-overlay.component-5opoeMsk.mjs} +3 -3
  36. package/fesm2022/{acorex-platform-module-auth-client-session-lock-overlay.component-PQ91EQjh.mjs.map → acorex-platform-module-auth-client-session-lock-overlay.component-5opoeMsk.mjs.map} +1 -1
  37. package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.command-BdtPwfLH.mjs → acorex-platform-module-auth-client-set-pin-code.command-CRb8NATb.mjs} +3 -3
  38. package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.command-BdtPwfLH.mjs.map → acorex-platform-module-auth-client-set-pin-code.command-CRb8NATb.mjs.map} +1 -1
  39. package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.component-L3DlTawo.mjs → acorex-platform-module-auth-client-set-pin-code.component-6NqaEKMs.mjs} +3 -3
  40. package/fesm2022/{acorex-platform-module-auth-client-set-pin-code.component-L3DlTawo.mjs.map → acorex-platform-module-auth-client-set-pin-code.component-6NqaEKMs.mjs.map} +1 -1
  41. package/fesm2022/{acorex-platform-module-auth-client-tenant-chooser.component-cRTVB-7T.mjs → acorex-platform-module-auth-client-tenant-chooser.component-C8AopfZ4.mjs} +2 -2
  42. package/fesm2022/{acorex-platform-module-auth-client-tenant-chooser.component-cRTVB-7T.mjs.map → acorex-platform-module-auth-client-tenant-chooser.component-C8AopfZ4.mjs.map} +1 -1
  43. package/fesm2022/{acorex-platform-module-auth-client-tenant-request.component-B-qx-HIi.mjs → acorex-platform-module-auth-client-tenant-request.component-CG74dqMX.mjs} +2 -2
  44. package/fesm2022/{acorex-platform-module-auth-client-tenant-request.component-B-qx-HIi.mjs.map → acorex-platform-module-auth-client-tenant-request.component-CG74dqMX.mjs.map} +1 -1
  45. package/fesm2022/{acorex-platform-module-auth-client-two-factor-code.component-DDzjCHid.mjs → acorex-platform-module-auth-client-two-factor-code.component-DAMphXPJ.mjs} +2 -2
  46. package/fesm2022/{acorex-platform-module-auth-client-two-factor-code.component-DDzjCHid.mjs.map → acorex-platform-module-auth-client-two-factor-code.component-DAMphXPJ.mjs.map} +1 -1
  47. package/fesm2022/{acorex-platform-module-auth-client-two-factor.module-BC8AJTp4.mjs → acorex-platform-module-auth-client-two-factor.module-xzAzTU4n.mjs} +2 -2
  48. package/fesm2022/{acorex-platform-module-auth-client-two-factor.module-BC8AJTp4.mjs.map → acorex-platform-module-auth-client-two-factor.module-xzAzTU4n.mjs.map} +1 -1
  49. package/fesm2022/{acorex-platform-module-auth-client-view-login-history.command-EHXTmZtV.mjs → acorex-platform-module-auth-client-view-login-history.command-CLWGDmsI.mjs} +2 -2
  50. package/fesm2022/{acorex-platform-module-auth-client-view-login-history.command-EHXTmZtV.mjs.map → acorex-platform-module-auth-client-view-login-history.command-CLWGDmsI.mjs.map} +1 -1
  51. package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding-page.component-CQUpjsZw.mjs → acorex-platform-module-auth-client-welcome-onboarding-page.component-CdgoC07Q.mjs} +2 -2
  52. package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding-page.component-CQUpjsZw.mjs.map → acorex-platform-module-auth-client-welcome-onboarding-page.component-CdgoC07Q.mjs.map} +1 -1
  53. package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding.command-D8cyXb5q.mjs → acorex-platform-module-auth-client-welcome-onboarding.command-BNOEiB5l.mjs} +2 -2
  54. package/fesm2022/{acorex-platform-module-auth-client-welcome-onboarding.command-D8cyXb5q.mjs.map → acorex-platform-module-auth-client-welcome-onboarding.command-BNOEiB5l.mjs.map} +1 -1
  55. package/fesm2022/acorex-platform-module-auth-client.mjs +1 -1
  56. package/i18n/en-AU/auth.json +2 -1
  57. package/i18n/en-US/auth.json +2 -1
  58. package/i18n/fa-IR/auth.json +2 -1
  59. package/package.json +3 -3
  60. package/fesm2022/acorex-platform-module-auth-client-acorex-platform-module-auth-client-Dgo6MzxI.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-auth-client-manage-two-factor.command-BXK7Lvpw.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-Cal6EJe0.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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"}
@@ -22,7 +22,7 @@ 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-Dgo6MzxI.mjs';
25
+ import { A as AXMUserDeviceSessionsService } from './acorex-platform-module-auth-client-acorex-platform-module-auth-client-CBRlR1xT.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: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i5$1.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
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", "dropdownAnchor", "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-DToDT9eb.mjs.map
274
+ //# sourceMappingURL=acorex-platform-module-auth-client-open-sessions.command-ZG33hlfh.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"acorex-platform-module-auth-client-open-sessions.command-DToDT9eb.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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"}
1
+ {"version":3,"file":"acorex-platform-module-auth-client-open-sessions.command-ZG33hlfh.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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"}
@@ -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-Dgo6MzxI.mjs';
33
+ import { F as AXPLoginExternalProvidersComponent, x as AXMAuthPlatformSettingsService, G as AXMAuthenticationTypes } from './acorex-platform-module-auth-client-acorex-platform-module-auth-client-CBRlR1xT.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 ----
@@ -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-DAp_-zko.mjs.map
605
+ //# sourceMappingURL=acorex-platform-module-auth-client-password.component-D0pwQEaB.mjs.map