TwoFactorConfigurationWizard.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { ref, computed } from 'vue'
  4. import { useTwoFactorPlugins } from '#shared/entities/two-factor/composables/useTwoFactorPlugins.ts'
  5. import type { ObjectLike } from '#shared/types/utils.ts'
  6. import TwoFactorConfigurationMethodList from './TwoFactorConfiguration/TwoFactorConfigurationMethodList.vue'
  7. import TwoFactorConfigurationRecoveryCodes from './TwoFactorConfiguration/TwoFactorConfigurationRecoveryCodes.vue'
  8. import TwoFactorConfigurationWizardFooterActions from './TwoFactorConfigurationWizard/TwoFactorConfigurationWizardFooterActions.vue'
  9. import type {
  10. TwoFactorConfigurationActionPayload,
  11. TwoFactorConfigurationComponentInstance,
  12. TwoFactorConfigurationType,
  13. } from './types.ts'
  14. const activeComponentInstance = ref<TwoFactorConfigurationComponentInstance>()
  15. const emit = defineEmits<{
  16. redirect: [url: string]
  17. }>()
  18. const state = ref<TwoFactorConfigurationType>('method_list')
  19. const componentOptions = ref<ObjectLike>()
  20. const { twoFactorMethodLookup } = useTwoFactorPlugins()
  21. const activeComponent = computed(() => {
  22. switch (state.value) {
  23. case 'recovery_codes':
  24. return TwoFactorConfigurationRecoveryCodes
  25. case 'method_list':
  26. return TwoFactorConfigurationMethodList
  27. default:
  28. return twoFactorMethodLookup[state.value].configurationOptions?.component
  29. }
  30. })
  31. const footerActionOptions = computed(() => ({
  32. hideActionButton:
  33. activeComponentInstance.value?.footerActionOptions?.hideActionButton,
  34. actionLabel: activeComponentInstance.value?.footerActionOptions?.actionLabel,
  35. actionButton:
  36. activeComponentInstance.value?.footerActionOptions?.actionButton,
  37. hideCancelButton:
  38. activeComponentInstance.value?.footerActionOptions?.hideCancelButton,
  39. cancelLabel:
  40. activeComponentInstance.value?.footerActionOptions?.cancelLabel ||
  41. __('Go Back'),
  42. cancelButton:
  43. activeComponentInstance.value?.footerActionOptions?.cancelButton,
  44. form: activeComponentInstance.value?.footerActionOptions?.form,
  45. }))
  46. const handleActionPayload = (payload: TwoFactorConfigurationActionPayload) => {
  47. if (!payload?.nextState) {
  48. emit('redirect', '/')
  49. return
  50. }
  51. state.value = payload.nextState
  52. componentOptions.value = payload.options
  53. }
  54. const onFooterButtonAction = () => {
  55. if (activeComponentInstance.value?.footerActionOptions?.form) return
  56. activeComponentInstance.value
  57. ?.executeAction?.()
  58. .then((payload) => handleActionPayload(payload))
  59. .catch(() => {})
  60. }
  61. const successCallback = () => {
  62. console.debug('successCallback')
  63. }
  64. const cancel = () => {
  65. if (state.value === 'method_list') {
  66. emit('redirect', '/logout')
  67. return
  68. }
  69. state.value = 'method_list'
  70. }
  71. </script>
  72. <template>
  73. <div class="mb-8">
  74. <component
  75. :is="activeComponent"
  76. ref="activeComponentInstance"
  77. :type="state"
  78. :options="componentOptions"
  79. :form-submit-callback="handleActionPayload"
  80. :success-callback="successCallback"
  81. />
  82. </div>
  83. <div class="flex flex-col gap-3">
  84. <TwoFactorConfigurationWizardFooterActions
  85. v-bind="footerActionOptions"
  86. @action="onFooterButtonAction()"
  87. @cancel="cancel()"
  88. />
  89. </div>
  90. </template>