TwoFactorConfigurationWizard.vue 3.2 KB

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