Skip to content

Commit

Permalink
Merge pull request #198 from SCCapstone/hobbs-jack-forgot-pw
Browse files Browse the repository at this point in the history
Hobbs jack forgot pw
  • Loading branch information
wihobbs authored Apr 3, 2023
2 parents 3b43665 + a4f138e commit 1eedde6
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 1 deletion.
18 changes: 18 additions & 0 deletions backend/routes/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ router.get("/", async (req, res) => {
}
});

router.get("/email/:email", async (req, res) => {
try {
const { email } = req.params;
const user = await User.findOne({ email: email });
if (!user) {
return res.status(404).send({ message: "User not found" });
}

res.send(user);
} catch (error) {
console.log(error);
}
});

router.get("/:id", async (req, res) => {
try {
const { id } = req.params;
Expand Down Expand Up @@ -98,6 +112,10 @@ router.put("/:id", async (req, res) => {
user.emailVerified = req.body.emailVerified;
}

if (req.body.updatePasswordToken) {
user.updatePasswordToken = req.body.updatePasswordToken;
}

await user.save();
res.send({ message: "User role updated" });
} catch (error) {
Expand Down
7 changes: 7 additions & 0 deletions client/src/components/NavBar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Favorites from "../../views/Favorites";
import Orders from "../../views/Orders";
import EditBlogpage from "../../views/EditBlogPage";
import VerifyEmail from "../../views/VerifyEmail";
import ChangePassword from "../../views/ChangePassword";

const CompleteNavbar = () => {
const user = localStorage.getItem("token");
Expand Down Expand Up @@ -156,6 +157,12 @@ const CompleteNavbar = () => {
<Route path = {`/validate/${user.verifyEmailToken}`}
element={<VerifyEmail user={user}/>} />
))}

{/* Mapped Route for Changing Passwords */}
{users.map((user) => (
<Route path = {`/forgot/${user.updatePasswordToken}`}
element={<ChangePassword user={user}/>} />
))}

</Routes>
</BrowserRouter>
Expand Down
116 changes: 116 additions & 0 deletions client/src/views/ChangePassword.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import axios from "axios";
import React from "react";
import swal from 'sweetalert2';

export default class verifyEmail extends React.Component {
constructor(props) {
super(props);
this.state = {
newPassword: "",
newPassword2: ""
};
}

handleChange = (e) => {
const { name, value } = e.target;
this.setState((state) => ({
[name]: value
}));
};

handleSubmit = e => {
e.preventDefault();
try {
// temporary for right now but later redo this to use put commands instead of post
const url = "/api/users/" + this.props.user._id;

// hash the new password here
let tempUser = { password: this.state.newPassword };
if (tempUser.password.trim().length < 6) {
swal.fire({
icon: 'error',
title: 'Password too short'
});
return;
}

if (this.state.newPassword !== this.state.newPassword2) {
swal.fire({
icon: 'error',
title: 'Passwords do not match'
});
return;
}

// axios call to update user
axios.put(url, tempUser).then(res => {
if (res.status === 200) {
swal.fire({
icon: 'success',
title: 'Successfully Updated User'
});
}
});

} catch (error) {
// show error
console.log(error);
swal.fire({
icon: 'error',
title: 'Try Again Later',
text: error.text,
});
}
}

render() {
return (
<div class="py-4">
<div class="grid bg-polished_pine text-center text-white border-black border-2 text-3xl rounded py-3 max-w-[1300px]">
Update Password
</div>

<form class="w-full max-w-lg" onSubmit={this.handleSubmit}>
<div class="flex flex-wrap -mx-3 mb-6">
<div class="w-full px-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-password">
New Password
</label>
<input
type="password"
name="newPassword"
class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
value={this.state.newPassword}
placeholder="Change Your Password"
onChange={this.handleChange}
/>
</div>
</div>
<div class="flex flex-wrap -mx-3 mb-6">
<div class="w-full px-3">
<label class="block uppercase tracking-wide text-gray-700 text-xs font-bold mb-2" for="grid-password">
Confirm New Password
</label>
<input
type="password"
name="newPassword2"
class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 mb-3 leading-tight focus:outline-none focus:bg-white focus:border-gray-500"
value={this.state.newPassword2}
placeholder="Confirm Your New Password"
onChange={this.handleChange}
/>
</div>
</div>

<div href="/updateProfile" class="text-center lg:text-left grid pb-6">
<button type="submit" class="inline-block px-10 py-3 bg-persian_plum font-semibold text-white font-medium leading-snug uppercase rounded">
Update
</button>
</div>
</form>
</div>
)
}

}

67 changes: 66 additions & 1 deletion client/src/views/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import Button from '@mui/material/Button';
import { TextField } from "@mui/material";
import Snackbar from '@mui/material/Snackbar';
import MuiAlert from '@mui/material/Alert';
import swal from "sweetalert2";
import emailjs from "@emailjs/browser";
import { v4 as uuidv4 } from 'uuid';

const Alert = React.forwardRef(function Alert(props, ref) {
return <MuiAlert elevation={6} ref={ref} variant="filled" {...props} />;
Expand Down Expand Up @@ -44,6 +47,68 @@ const Login = () => {
}
};

const openForgotPassword = async () => {
swal.fire({
title: "Send email to retrieve your password?",
input: 'email',
inputLabel: 'Your email address',
inputPlaceholder: 'Enter your email address',
confirmButtonText: "Send Email",
showCancelButton: true,
}).then((result) => {
console.log(result);
if (!result.isConfirmed || result.value?.length <= 0) {
swal.fire(
'Email failure!',
`Failed to send email`,
'error'
);
return;
}
const email = result.value;
try {
const url = `/api/users/email/${email}`;
console.log(url);
axios.get(url).then((res) => {
res.data.updatePasswordToken = uuidv4();
const putURL = '/api/users/' + res.data._id;
axios.put(putURL, res.data).then(
emailjs.send(
"service_trb6232",
"template_jetptvm",
{
pw_link: "http://bookstore-app.herokuapp.com/forgot/" + res.data.updatePasswordToken,
to_email: email,
to_name: res.data.firstName,
},
"0v71YVpIY79kGX06h"
).then(
swal.fire(
'Email successfully sent',
"Check your email for the link to reset your password",
'success'
)
)
).catch((error) => {
console.log(error);
})
}).catch((error) => {
if (error.response.status === 404) {
swal.fire(
'Email failure!',
"There is no user with that email address.",
'error'
);
}
console.log(error);
});
} catch (error) {
console.log(error);
}

})
};

const handleClose = (event, reason) => {
if (reason === 'clickaway') {
return;
Expand Down Expand Up @@ -108,8 +173,8 @@ const Login = () => {
</Button>

<Button
href="/forgot-password"
class="text-slate-800 h-13 font-semibold hover:text-black bg-polished_pine rounded p-3 border-2"
onClick={(openForgotPassword)}
>
Forgot Password?
</Button>
Expand Down

0 comments on commit 1eedde6

Please sign in to comment.