PasswordResetVerify.vue 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <!-- Copyright (C) 2012-2024 Zammad Foundation, https://zammad-foundation.org/ -->
  2. <script setup lang="ts">
  3. import { ref, onBeforeMount } from 'vue'
  4. import { useRouter } from 'vue-router'
  5. import { useForm } from '#shared/components/Form/useForm.ts'
  6. import type {
  7. FormSchemaNode,
  8. FormSubmitData,
  9. } from '#shared/components/Form/types.ts'
  10. import Form from '#shared/components/Form/Form.vue'
  11. import { useApplicationStore } from '#shared/stores/application.ts'
  12. import { EnumPublicLinksScreen } from '#shared/graphql/types.ts'
  13. import { useNotifications } from '#shared/components/CommonNotifications/useNotifications.ts'
  14. import { NotificationTypes } from '#shared/components/CommonNotifications/types.ts'
  15. import CommonButton from '#desktop/components/CommonButton/CommonButton.vue'
  16. import LayoutPublicPage from '#desktop/components/layout/LayoutPublicPage/LayoutPublicPage.vue'
  17. import CommonPublicLinks from '#desktop/components/CommonPublicLinks/CommonPublicLinks.vue'
  18. import MutationHandler from '#shared/server/apollo/handler/MutationHandler.ts'
  19. import CommonLoader from '#desktop/components/CommonLoader/CommonLoader.vue'
  20. import { useUserPasswordResetVerifyMutation } from '../graphql/mutations/userPasswordResetVerify.api.ts'
  21. import { useUserPasswordResetUpdateMutation } from '../graphql/mutations/userPasswordResetUpdate.api.ts'
  22. defineOptions({
  23. beforeRouteEnter(to) {
  24. const application = useApplicationStore()
  25. if (!application.config.user_lost_password) {
  26. return to.redirectedFrom ? false : '/'
  27. }
  28. return true
  29. },
  30. })
  31. interface Props {
  32. token?: string
  33. }
  34. const props = defineProps<Props>()
  35. interface FormValues {
  36. password: string
  37. confirmPassword: string
  38. }
  39. const formSchema: FormSchemaNode[] = [
  40. {
  41. type: 'password',
  42. label: __('Password'),
  43. name: 'password',
  44. outerClass: 'col-span-1',
  45. required: true,
  46. props: {
  47. maxLength: 1001,
  48. },
  49. },
  50. {
  51. type: 'password',
  52. label: __('Confirm password'),
  53. name: 'password_confirm',
  54. outerClass: 'col-span-1',
  55. validation: 'confirm',
  56. props: {
  57. maxLength: 1001,
  58. },
  59. required: true,
  60. },
  61. ]
  62. const { form, isDisabled } = useForm()
  63. const errorMessage = ref('')
  64. const loading = ref(true)
  65. const canResetPassword = ref(false)
  66. const { notify } = useNotifications()
  67. const router = useRouter()
  68. onBeforeMount(() => {
  69. if (!props.token) {
  70. loading.value = false
  71. canResetPassword.value = false
  72. errorMessage.value = __(
  73. 'The token could not be verified. Please contact your administrator.',
  74. )
  75. return
  76. }
  77. const userSignupVerify = new MutationHandler(
  78. useUserPasswordResetVerifyMutation({
  79. variables: { token: props.token },
  80. }),
  81. {
  82. errorShowNotification: false,
  83. },
  84. )
  85. userSignupVerify
  86. .send()
  87. .then(() => {
  88. canResetPassword.value = true
  89. errorMessage.value = ''
  90. })
  91. .catch(() => {
  92. canResetPassword.value = false
  93. errorMessage.value = __('The provided token is invalid.')
  94. })
  95. .finally(() => {
  96. loading.value = false
  97. })
  98. })
  99. const resetPasswordHandler = new MutationHandler(
  100. useUserPasswordResetUpdateMutation(),
  101. { errorShowNotification: false },
  102. )
  103. const updatePassword = async (form: FormSubmitData<FormValues>) => {
  104. await resetPasswordHandler.send({
  105. token: props.token!,
  106. password: form.password,
  107. })
  108. notify({
  109. type: NotificationTypes.Success,
  110. message: __('Woo hoo! Your password has been changed!'),
  111. })
  112. router.replace('/login')
  113. }
  114. const goToLogin = () => {
  115. router.replace('/login')
  116. }
  117. </script>
  118. <template>
  119. <LayoutPublicPage box-size="medium" :title="__('Choose your new password')">
  120. <CommonLoader :loading="loading" :error="errorMessage" />
  121. <Form
  122. v-if="canResetPassword"
  123. id="password-reset-verify"
  124. ref="form"
  125. form-class="mb-2.5 grid grid-cols-2 gap-y-2.5 gap-x-3"
  126. :schema="formSchema"
  127. @submit="updatePassword($event as FormSubmitData<FormValues>)"
  128. />
  129. <template #boxActions>
  130. <CommonButton
  131. variant="secondary"
  132. size="medium"
  133. :disabled="isDisabled"
  134. @click="goToLogin()"
  135. >
  136. {{ $t('Cancel & Go Back') }}
  137. </CommonButton>
  138. <CommonButton
  139. v-if="canResetPassword"
  140. type="submit"
  141. variant="submit"
  142. size="medium"
  143. form="password-reset-verify"
  144. :disabled="isDisabled"
  145. >
  146. {{ $t('Submit') }}
  147. </CommonButton>
  148. </template>
  149. <template #bottomContent>
  150. <CommonPublicLinks :screen="EnumPublicLinksScreen.PasswordReset" />
  151. </template>
  152. </LayoutPublicPage>
  153. </template>