Merge pull request #1972 from automatisch/AUT-1107

feat: refactor forgot password mutation with the REST API endpoint
This commit is contained in:
Ali BARIN
2024-07-17 15:32:37 +02:00
committed by GitHub
8 changed files with 39 additions and 70 deletions

View File

@@ -32,7 +32,6 @@ import verifyConnection from './mutations/verify-connection.js';
// Converted mutations
import deleteUser from './mutations/delete-user.ee.js';
import login from './mutations/login.js';
import forgotPassword from './mutations/forgot-password.ee.js';
import resetPassword from './mutations/reset-password.ee.js';
const mutationResolvers = {
@@ -51,7 +50,6 @@ const mutationResolvers = {
deleteUser,
duplicateFlow,
executeFlow,
forgotPassword,
generateAuthUrl,
login,
registerUser,

View File

@@ -1,43 +0,0 @@
import appConfig from '../../config/app.js';
import User from '../../models/user.js';
import emailQueue from '../../queues/email.js';
import {
REMOVE_AFTER_30_DAYS_OR_150_JOBS,
REMOVE_AFTER_7_DAYS_OR_50_JOBS,
} from '../../helpers/remove-job-configuration.js';
const forgotPassword = async (_parent, params) => {
const { email } = params.input;
const user = await User.query().findOne({ email: email.toLowerCase() });
if (!user) {
throw new Error('Email address not found!');
}
await user.generateResetPasswordToken();
const jobName = `Reset Password Email - ${user.id}`;
const jobPayload = {
email: user.email,
subject: 'Reset Password',
template: 'reset-password-instructions.ee',
params: {
token: user.resetPasswordToken,
webAppUrl: appConfig.webAppUrl,
fullName: user.fullName,
},
};
const jobOptions = {
removeOnComplete: REMOVE_AFTER_7_DAYS_OR_50_JOBS,
removeOnFail: REMOVE_AFTER_30_DAYS_OR_150_JOBS,
};
await emailQueue.add(jobName, jobPayload, jobOptions);
return true;
};
export default forgotPassword;

View File

@@ -17,7 +17,6 @@ type Mutation {
deleteUser(input: DeleteUserInput): Boolean
duplicateFlow(input: DuplicateFlowInput): Flow
executeFlow(input: ExecuteFlowInput): executeFlowType
forgotPassword(input: ForgotPasswordInput): Boolean
generateAuthUrl(input: GenerateAuthUrlInput): AuthLink
login(input: LoginInput): Auth
registerUser(input: RegisterUserInput): User
@@ -405,10 +404,6 @@ input UpdateCurrentUserInput {
fullName: String
}
input ForgotPasswordInput {
email: String!
}
input ResetPasswordInput {
token: String!
password: String!

View File

@@ -53,7 +53,6 @@ const isAuthenticatedRule = rule()(isAuthenticated);
export const authenticationRules = {
Mutation: {
'*': isAuthenticatedRule,
forgotPassword: allow,
login: allow,
registerUser: allow,
resetPassword: allow,

View File

@@ -1,23 +1,36 @@
import * as React from 'react';
import { useMutation } from '@apollo/client';
import Paper from '@mui/material/Paper';
import Typography from '@mui/material/Typography';
import LoadingButton from '@mui/lab/LoadingButton';
import { FORGOT_PASSWORD } from 'graphql/mutations/forgot-password.ee';
import { enqueueSnackbar } from 'notistack';
import useForgotPassword from 'hooks/useForgotPassword';
import Form from 'components/Form';
import TextField from 'components/TextField';
import useFormatMessage from 'hooks/useFormatMessage';
export default function ForgotPasswordForm() {
const formatMessage = useFormatMessage();
const [forgotPassword, { data, loading }] = useMutation(FORGOT_PASSWORD);
const {
mutateAsync: forgotPassword,
isPending: loading,
isSuccess,
} = useForgotPassword();
const handleSubmit = async (values) => {
const { email } = values;
try {
await forgotPassword({
variables: {
input: values,
},
email,
});
} catch (error) {
enqueueSnackbar(
error?.message || formatMessage('forgotPasswordForm.error'),
{
variant: 'error',
},
);
}
};
return (
@@ -35,7 +48,6 @@ export default function ForgotPasswordForm() {
>
{formatMessage('forgotPasswordForm.title')}
</Typography>
<Form onSubmit={handleSubmit}>
<TextField
label={formatMessage('forgotPasswordForm.emailFieldLabel')}
@@ -45,20 +57,18 @@ export default function ForgotPasswordForm() {
margin="dense"
autoComplete="username"
/>
<LoadingButton
type="submit"
variant="contained"
color="primary"
sx={{ boxShadow: 2, my: 3 }}
loading={loading}
disabled={data}
disabled={isSuccess}
fullWidth
>
{formatMessage('forgotPasswordForm.submit')}
</LoadingButton>
{data && (
{isSuccess && (
<Typography
variant="body1"
sx={{ color: (theme) => theme.palette.success.main }}

View File

@@ -1,6 +0,0 @@
import { gql } from '@apollo/client';
export const FORGOT_PASSWORD = gql`
mutation ForgotPassword($input: ForgotPasswordInput) {
forgotPassword(input: $input)
}
`;

View File

@@ -0,0 +1,15 @@
import { useMutation } from '@tanstack/react-query';
import api from 'helpers/api';
export default function useForgotPassword() {
const mutation = useMutation({
mutationFn: async (payload) => {
const { data } = await api.post('/v1/users/forgot-password', payload);
return data;
},
});
return mutation;
}

View File

@@ -157,6 +157,7 @@
"forgotPasswordForm.submit": "Send reset instructions",
"forgotPasswordForm.instructionsSent": "The instructions have been sent!",
"forgotPasswordForm.emailFieldLabel": "Email",
"forgotPasswordForm.error": "Something went wrong. Please try again.",
"resetPasswordForm.passwordsMustMatch": "Passwords must match.",
"resetPasswordForm.mandatoryInput": "{inputName} is required.",
"resetPasswordForm.title": "Reset password",