TwoFactorConfigurationFlyout.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <!-- Copyright (C) 2012-2025 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { ref, computed, useTemplateRef } from 'vue'
  4. import { useTwoFactorPlugins } from '#shared/entities/two-factor/composables/useTwoFactorPlugins.ts'
  5. import { i18n } from '#shared/i18n.ts'
  6. import type { ObjectLike } from '#shared/types/utils.ts'
  7. import CommonFlyout from '#desktop/components/CommonFlyout/CommonFlyout.vue'
  8. import { closeFlyout } from '#desktop/components/CommonFlyout/useFlyout.ts'
  9. import TwoFactorConfigurationPasswordCheck from './TwoFactorConfiguration/TwoFactorConfigurationPasswordCheck.vue'
  10. import TwoFactorConfigurationRecoveryCodes from './TwoFactorConfiguration/TwoFactorConfigurationRecoveryCodes.vue'
  11. import type {
  12. TwoFactorConfigurationActionPayload,
  13. TwoFactorConfigurationComponentInstance,
  14. TwoFactorConfigurationProps,
  15. TwoFactorConfigurationType,
  16. } from './types.ts'
  17. const props = defineProps<TwoFactorConfigurationProps>()
  18. const activeComponentInstance =
  19. useTemplateRef<TwoFactorConfigurationComponentInstance>('active-component')
  20. const flyoutName = 'two-factor-flyout'
  21. const headerTitle = computed(() => {
  22. switch (props.type) {
  23. case 'recovery_codes':
  24. return i18n.t(
  25. 'Generate Recovery Codes: %s',
  26. i18n.t(activeComponentInstance.value?.headerSubtitle),
  27. )
  28. case 'removal_confirmation':
  29. return i18n.t(
  30. 'Remove Two-factor Authentication: %s',
  31. i18n.t(activeComponentInstance.value?.headerSubtitle),
  32. )
  33. default:
  34. return i18n.t(
  35. 'Set Up Two-factor Authentication: %s',
  36. i18n.t(activeComponentInstance.value?.headerSubtitle),
  37. )
  38. }
  39. })
  40. const state = ref<TwoFactorConfigurationType>('password_check')
  41. const componentOptions = ref<ObjectLike>()
  42. const token = ref()
  43. const { twoFactorMethodLookup } = useTwoFactorPlugins()
  44. const activeComponent = computed(() => {
  45. switch (state.value) {
  46. case 'recovery_codes':
  47. return TwoFactorConfigurationRecoveryCodes
  48. case 'password_check':
  49. case 'removal_confirmation':
  50. return TwoFactorConfigurationPasswordCheck
  51. default:
  52. return twoFactorMethodLookup[state.value].configurationOptions?.component
  53. }
  54. })
  55. const handleActionPayload = (payload: TwoFactorConfigurationActionPayload) => {
  56. if (!payload?.nextState) {
  57. closeFlyout('two-factor-flyout')
  58. return
  59. }
  60. state.value = payload.nextState
  61. token.value = payload.token
  62. componentOptions.value = payload.options
  63. }
  64. const onFooterButtonAction = () => {
  65. if (activeComponentInstance.value?.footerActionOptions?.form) return
  66. activeComponentInstance.value
  67. ?.executeAction?.()
  68. .then((payload) => handleActionPayload(payload))
  69. .catch(() => {})
  70. }
  71. </script>
  72. <template>
  73. <CommonFlyout
  74. :header-title="headerTitle"
  75. :footer-action-options="activeComponentInstance?.footerActionOptions"
  76. :header-icon="activeComponentInstance?.headerIcon"
  77. :name="flyoutName"
  78. no-close-on-action
  79. @action="onFooterButtonAction"
  80. >
  81. <component
  82. :is="activeComponent"
  83. ref="active-component"
  84. :type="type"
  85. :token="token"
  86. :options="componentOptions"
  87. :form-submit-callback="handleActionPayload"
  88. :success-callback="successCallback"
  89. />
  90. </CommonFlyout>
  91. </template>