Everything ive seen on password resets with react is at least two years out of date what am i doing wrong. the following code is everything associated with the password reset and the error im getting is at the bottom
PasswrodResetReq.jsx
import React, { useState } from 'react';
import { useMutation, gql } from '@apollo/client';
import { useNavigate } from 'react-router-dom';
const PASSWORD_RESET_REQUEST = gql`
mutation PasswordResetRequest($email: String!) {
passwordResetRequest(email: $email){
message
}
}
`;
function PasswordResetRequest() {
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const [passwordResetRequest, { data, loading, error }] = useMutation(PASSWORD_RESET_REQUEST, {
onCompleted: (data) => {
setMessage(data.passwordResetRequest);
},
onError: (error) => {
setMessage('An error occurred while trying to send the password reset request');
},
});
const handleInputChange = (event) => {
setEmail(event.target.value);
};
const navigate = useNavigate();
const handleSubmit = (event) => {
event.preventDefault();
passwordResetRequest({ variables: { email } });
navigate('/password-reset'); // Navigate to password reset page
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="email"
name="email"
placeholder="Email"
value={email}
onChange={handleInputChange}
required
/>
<button type="submit">Send Password Reset Request</button>
</form>
{message && <p>{message}</p>}
</div>
);
}
export default PasswordResetRequest;
PasswordReset.jsx
import React, { useState } from 'react';
import { useMutation, gql } from '@apollo/client';
const PASSWORD_RESET = gql`
mutation PasswordReset($token: String!, $password: String!) {
passwordReset(token: $token, password: $password)
}
`;
function PasswordReset() {
const [token, setToken] = useState('');
const [password, setPassword] = useState('');
const [message, setMessage] = useState('');
const [passwordReset, { data, loading, error }] = useMutation(PASSWORD_RESET, {
onCompleted: (data) => {
setMessage(data.passwordReset);
},
onError: (error) => {
setMessage('An error occurred while trying to reset the password');
},
});
const handleTokenChange = (event) => {
console.log(token);
setToken(event.target.value);
};
const handlePasswordChange = (event) => {
setPassword(event.target.value);
};
const handleSubmit = (event) => {
event.preventDefault();
console.log(token, password);
passwordReset({ variables: { token, password } });
};
return (
<div>
<form onSubmit={handleSubmit}>
<input
type="text"
name="token"
placeholder="Token"
value={token}
onChange={handleTokenChange}
required
/>
<input
type="password"
name="password"
placeholder="New Password"
value={password}
onChange={handlePasswordChange}
required
/>
<button type="submit">Reset Password</button>
</form>
{message && <p>{message}</p>}
</div>
);
}
export default PasswordReset;
resolvers.js
Mutation:{
requestPasswordReset: async (_, { email }, context) => {
const user = await User.findOne({ email });
if (!user) {
throw new UserInputError('User not found', {
extensions: { code: 'USER_NOT_FOUND' },
});
}
const resetToken = user.createPasswordResetToken();
console.log(resetToken);
await user.save();
const resetURL = `http://localhost:3000/resetPassword/${resetToken}`;
try {
await sendEmail({
to: user.email,
subject: 'Password Reset',
text: `Reset your password by visiting the following link: ${resetURL}`,
});
// Assuming email sending was successful
return { message: 'Password reset email sent' };
} catch (error) {
// Handle email sending failure
console.error(error);
throw new ApolloError('Failed to send email', 'EMAIL_SEND_FAILED');
}
},
resetPassword: async (_, { token, newPassword }) => {
const hashedToken = crypto.createHash('sha256').update(token).digest('hex');
const user = await User.findOne({
passwordResetToken: hashedToken,
passwordResetExpires: { $gt: Date.now() },
});
if (!user) {
throw new UserInputError('Token is invalid or has expired', {
extensions: { code: 'TOKEN_INVALID_OR_EXPIRED' },
});
}
user.password = newPassword;
user.passwordResetToken = undefined;
user.passwordResetExpires = undefined;
await user.save();
return { message: 'Password has been reset' };
},
},
};
module.exports = resolvers;
typeDefs.js
const typeDefs = `
type User {
_id: ID
firstName: String
lastName: String
email: String
profilePictureURL: String
profileBio: String
friends: [User]
}
type Auth {
token: ID
user: User
}
type Query {
users: [User]
user(_id: ID!): User
}
type Mutation {
addFriend(friendId: ID!): User
unFriend(friendId: ID!): User
addUser(firstName: String!, lastName: String!, email: String!, password: String!): Auth
updateUser(firstName: String, lastName: String, email: String, password: String): User
login(email: String!, password: String!): Auth
requestPasswordReset(email: String!): Message
resetPassword(token: String!, newPassword: String!): Message
}
type Message {
message: String
}
`;
module.exports = typeDefs;
sendEmails.js
const nodemailer = require('nodemailer');
require('dotenv').config();
const sendEmail = async ({ from, to, subject, text }) => {
const transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: '[email protected]',
pass: process.env.PASS
}
});
const emailObject = {
from:'"iQuest" <[email protected]>',
to: user.email,
subject: 'Password Reset',
text: `Reset your password by visiting the following link: ${resetURL}`,}
const info = await transporter.sendMail(emailObject);
console.log('sent email:', info)
}
module.exports = sendEmail;
server.js
const express = require('express');
const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');
const path = require('path');
const { authMiddleware } = require('./utils/auth');
const { typeDefs, resolvers } = require('./schemas');
const db = require('./config/connection');
const { User } = require('./models');
const crypto = require('crypto');
const sendEmail = require('./utils/sendEmail');
require('dotenv').config();
const PORT = process.env.PORT || 3001;
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({
token: req.headers.authorization || '',
}),
});
// Create a new instance of an Apollo server with the GraphQL schema
const startApolloServer = async () => {
await server.start();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
// Serve static assets
app.use('/images', express.static(path.join(__dirname, '../client/images')));
// Password reset endpoints
app.post('/request-password-reset', async (req, res) => {
const { email } = req.body;
try {
const user = await User.findOne({ email });
if (!user) {
return res.status(404).json({ message: 'User not found' });
}
const resetToken = user.createPasswordResetToken();
await user.save();
const resetURL = `${req.protocol}://${req.get('host')}/resetPassword/${resetToken}`;
await sendEmail({
to: user.email,
subject: 'Password Reset',
text: `Reset your password by visiting the following link: ${resetURL}`,
});
res.status(200).json({ message: 'Password reset email sent' });
} catch (error) {
res.status(500).json({ message: 'Error sending email', error });
}
});
app.post('/reset-password/:token', async (req, res) => {
const { token } = req.params;
const { newPassword } = req.body;
try {
const hashedToken = crypto.createHash('sha256').update(token).digest('hex');
const user = await User.findOne({
passwordResetToken: hashedToken,
passwordResetExpires: { $gt: Date.now() },
});
if (!user) {
return res.status(400).json({ message: 'Token is invalid or has expired' });
}
user.password = newPassword;
user.passwordResetToken = undefined;
user.passwordResetExpires = undefined;
await user.save();
res.status(200).json({ message: 'Password has been reset' });
} catch (error) {
res.status(500).json({ message: 'Error resetting password', error });
}
});
app.use('/graphql', expressMiddleware(server, {
context: authMiddleware
}));
if (process.env.NODE_ENV === 'production') {
app.use(express.static(path.join(__dirname, '../client/dist')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../client/dist/index.html'));
});
}
db.once('open', () => {
app.listen(PORT, () => {
console.log(`API server running on port ${PORT}!`);
console.log(`Use GraphQL at http://localhost:${PORT}/graphql`);
});
});
};
// Call the async function to start the server
startApolloServer();
im getting this error
(anonymous) @ @apollo_client.js?v=5558fece:744
Subscription2 @ chunk-37R5SEUF.js?v=5558fece:1984
subscribe2 @ chunk-37R5SEUF.js?v=5558fece:2045
(anonymous) @ @apollo_client_link_context.js?v=5558fece:20
Promise.then (async)
(anonymous) @ @apollo_client_link_context.js?v=5558fece:17
Subscription2 @ chunk-37R5SEUF.js?v=5558fece:1984
subscribe2 @ chunk-37R5SEUF.js?v=5558fece:2045
complete @ chunk-37R5SEUF.js?v=5558fece:11089
Concast2.start @ chunk-37R5SEUF.js?v=5558fece:11118
Concast2 @ chunk-37R5SEUF.js?v=5558fece:11110
QueryManager2.getObservableFromLink @ @apollo_client.js?v=5558fece:5464
(anonymous) @ @apollo_client.js?v=5558fece:4917
(anonymous) @ @apollo_client.js?v=5558fece:4916
step @ chunk-37R5SEUF.js?v=5558fece:136
(anonymous) @ chunk-37R5SEUF.js?v=5558fece:83
(anonymous) @ chunk-37R5SEUF.js?v=5558fece:69
__awaiter @ chunk-37R5SEUF.js?v=5558fece:51
QueryManager2.mutate @ @apollo_client.js?v=5558fece:4877
ApolloClient2.mutate @ @apollo_client.js?v=5558fece:5941
(anonymous) @ @apollo_client.js?v=5558fece:6864
handleSubmit @ PasswordResetReq.jsx:34
callCallback2 @ chunk-HZHRDQM6.js?v=5558fece:3674
invokeGuardedCallbackDev @ chunk-HZHRDQM6.js?v=5558fece:3699
invokeGuardedCallback @ chunk-HZHRDQM6.js?v=5558fece:3733
invokeGuardedCallbackAndCatchFirstError @ chunk-HZHRDQM6.js?v=5558fece:3736
executeDispatch @ chunk-HZHRDQM6.js?v=5558fece:7016
processDispatchQueueItemsInOrder @ chunk-HZHRDQM6.js?v=5558fece:7036
processDispatchQueue @ chunk-HZHRDQM6.js?v=5558fece:7045
dispatchEventsForPlugins @ chunk-HZHRDQM6.js?v=5558fece:7053
(anonymous) @ chunk-HZHRDQM6.js?v=5558fece:7177
batchedUpdates$1 @ chunk-HZHRDQM6.js?v=5558fece:18941
batchedUpdates @ chunk-HZHRDQM6.js?v=5558fece:3579
dispatchEventForPluginEventSystem @ chunk-HZHRDQM6.js?v=5558fece:7176
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ chunk-HZHRDQM6.js?v=5558fece:5478
dispatchEvent @ chunk-HZHRDQM6.js?v=5558fece:5472
dispatchDiscreteEvent @ chunk-HZHRDQM6.js?v=5558fece:5449
Show 35 more frames
Show less```
New contributor
Gavin Todd is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.