useConfigurationTwoFactor.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/
  2. import { storeToRefs } from 'pinia'
  3. import { computed, watch } from 'vue'
  4. import { useApplicationConfigTwoFactor } from '#shared/composables/authentication/useApplicationConfigTwoFactor.ts'
  5. import type {
  6. EnumTwoFactorAuthenticationMethod,
  7. TwoFactorEnabledAuthenticationMethod,
  8. } from '#shared/graphql/types.ts'
  9. import SubscriptionHandler from '#shared/server/apollo/handler/SubscriptionHandler.ts'
  10. import { useSessionStore } from '#shared/stores/session.ts'
  11. import { useUserCurrentTwoFactorUpdatesSubscription } from '#desktop/entities/user/current/graphql/subscriptions/userCurrentTwoFactorUpdates.api.ts'
  12. import type { TwoFactorConfigurationMethod } from '../types.ts'
  13. export const useConfigurationTwoFactor = () => {
  14. const {
  15. twoFactorEnabledMethods,
  16. hasEnabledMethods,
  17. hasEnabledRecoveryCodes,
  18. } = useApplicationConfigTwoFactor()
  19. const session = useSessionStore()
  20. const { user } = storeToRefs(session)
  21. const defaultTwoFactorMethod = computed<EnumTwoFactorAuthenticationMethod>(
  22. () => {
  23. return user.value?.preferences?.two_factor_authentication?.default
  24. },
  25. )
  26. const userCurrentTwoFactorSubscription = new SubscriptionHandler(
  27. useUserCurrentTwoFactorUpdatesSubscription({ userId: session.userId }),
  28. )
  29. const userCurrentTwoFactorResult = userCurrentTwoFactorSubscription.result()
  30. const twoFactorConfigurationResult = computed(
  31. () =>
  32. userCurrentTwoFactorResult.value?.userCurrentTwoFactorUpdates
  33. .configuration,
  34. )
  35. const enabledAuthenticationMethodLookup = computed(() => {
  36. return twoFactorConfigurationResult.value?.enabledAuthenticationMethods.reduce(
  37. (methodLookup, enabledAuthenticationMethod) => {
  38. methodLookup[enabledAuthenticationMethod.authenticationMethod] = {
  39. ...enabledAuthenticationMethod,
  40. default:
  41. enabledAuthenticationMethod.authenticationMethod ===
  42. defaultTwoFactorMethod.value,
  43. }
  44. return methodLookup
  45. },
  46. {} as Record<string, TwoFactorEnabledAuthenticationMethod>,
  47. )
  48. })
  49. const twoFactorConfigurationMethods = computed(() => {
  50. const mappedMethods: TwoFactorConfigurationMethod[] = []
  51. twoFactorEnabledMethods.value.forEach((enabledAuthenticationMethod) => {
  52. const configurationMethod =
  53. enabledAuthenticationMethodLookup.value?.[
  54. enabledAuthenticationMethod.name
  55. ]
  56. mappedMethods.push({
  57. ...enabledAuthenticationMethod,
  58. configured: Boolean(configurationMethod?.configured),
  59. default: Boolean(configurationMethod?.default),
  60. })
  61. })
  62. return mappedMethods
  63. })
  64. const hasConfiguredMethods = computed(() =>
  65. Object.values(enabledAuthenticationMethodLookup.value || {}).some(
  66. (enabledAuthenticationMethod) => enabledAuthenticationMethod.configured,
  67. ),
  68. )
  69. const hasRecoveryCodes = computed(() => {
  70. return Boolean(twoFactorConfigurationResult.value?.recoveryCodesExist)
  71. })
  72. // We need to restart the subscription when enabled two factor method list changed.
  73. watch(twoFactorEnabledMethods, () =>
  74. userCurrentTwoFactorSubscription.operationResult.restart(),
  75. )
  76. return {
  77. twoFactorConfigurationMethods,
  78. hasEnabledMethods,
  79. hasEnabledRecoveryCodes,
  80. hasConfiguredMethods,
  81. hasRecoveryCodes,
  82. }
  83. }