Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Password Recovery Feature #151 #158

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 20 additions & 33 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
if(process.env.NODE_ENV != "production"){
if (process.env.NODE_ENV != "production") {
require('dotenv').config();
}
const express = require("express");
Expand All @@ -16,43 +16,42 @@ const passport = require("passport");
const LocalStrategy = require("passport-local");
const User = require("./models/user.js");
const userRouter = require("./routes/user.js");
/* if you want to run the project and do not have .env files configured , please uncomment the next
two commented codes and comment down this code await mongoose.connect(dbUrl); You project will run succesfully*/

const MONGO_URL = "mongodb://mongo:27017/wanderlust"; // used with docker
// const MONGO_URL = "mongodb://127.0.0.1:27017/wanderlust"; // use for local db
const dbUrl =process.env.ATLASDB_URL;
const dbUrl = process.env.ATLASDB_URL;

main()
.then(() => {
console.log("connected to DB");
}).catch((err) => {
console.log(err);
});
async function main(){

async function main() {
await mongoose.connect(MONGO_URL);
// await mongoose.connect(dbUrl);
}
app.set("view engine","ejs");

app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "views"));

app.use(express.urlencoded({extended:true}));
app.use(express.urlencoded({ extended: true }));
app.use(methodOverride("_method"));
app.engine('ejs', ejsMate);
app.use(express.static(path.join(__dirname,"/public")));
app.use(express.static(path.join(__dirname, "/public")));

const sessionOptions = {
secret: "mysupersecretcode",
resave: false,
saveUninitialized: true,
cookie: {
expires: Date.now()+7*24*60*60*1000,
maxAge: 7*24*60*60*1000,
expires: Date.now() + 7 * 24 * 60 * 60 * 1000,
maxAge: 7 * 24 * 60 * 60 * 1000,
httpOnly: true,
},
};
/*app.get("/", (req,res) => {
res.send("Hi,I am root");
});*/

app.use(session(sessionOptions));
app.use(flash());
app.use(passport.initialize());
Expand All @@ -61,44 +60,32 @@ passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());

app.use((req,res,next) =>{
app.use((req, res, next) => {
res.locals.success = req.flash("success");
res.locals.error = req.flash("error");
res.locals.currUser = req.user;
//console.log(success);
next();
});

app.use("/listings",listingRouter);
app.use("/listings/:id/reviews",reviewRouter);
app.use("/",userRouter);
app.use("/listings", listingRouter);
app.use("/listings/:id/reviews", reviewRouter);
app.use("/", userRouter);

app.get('/privacy', (req, res) => {
res.render('privacy'); // This should be placed before the app.all("*") block
res.render('privacy');
});

// Catch-all route for undefined paths
app.all("*", (req, res, next) => {
next(new ExpressError(404, "Page Not Found!"));
});


//if any of the incomming request does not match then throw this error
app.all("*",(req,res,next) =>{
next(new ExpressError(404,"Page Not Found!"));
});
//error handling is done by middleware
app.use((err,req,res,next) =>{
let {statusCode=500,message="Something went wrong!"}=err;
res.status(statusCode).render("error.ejs",{message});
//res.status(statusCode).send(message);
});

// Error handling middleware
app.use((err, req, res, next) => {
console.log(err); // Log the full error to see what’s causing the issue
let { statusCode = 500, message = "Something went wrong!" } = err;
res.status(statusCode).render("error.ejs", { message });
});

app.listen(8080,()=>{
app.listen(8080, () => {
console.log("Server is listening to port 8080");
});
19 changes: 16 additions & 3 deletions controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const renderSignupForm = (req, res) => {
res.render("users/signup.ejs");
};

const signup = async (req, res) => {
const signup = async (req, res, next) => {
try {
// Check for validation errors
const errors = validationResult(req);
Expand Down Expand Up @@ -53,10 +53,23 @@ const logout = (req, res, next) => {
});
};

// Render the password recovery form
const renderForgotPasswordForm = (req, res) => {
res.render('users/forgot.ejs');
};

// Handle the password recovery form submission
const forgotPassword = (req, res) => {
req.flash('info', 'If an account with that email exists, you will receive an email with instructions to reset your password.');
res.redirect('/forgot');
};

module.exports = {
renderSignupForm,
signup,
renderLoginForm,
login,
logout
};
logout,
renderForgotPasswordForm,
forgotPassword
};
21 changes: 20 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,26 @@ We ❤️ contributions! Here’s how you can join the effort:

6. **Open a pull request**.

---

<!--line-->
<img src="https://www.animatedimages.org/data/media/562/animated-line-image-0184.gif" width="1920" />



## This project is now OFFICIALLY accepted for

<div align="center">
<img src="https://github.com/amiya-cyber/banner/blob/main/329829127-e79eb6de-81b1-4ffb-b6ed-f018bb977e88.png" alt="GSSoC 2024 Extd" width="60%">
</div>

<div align="center">
<img src="https://github.com/amiya-cyber/banner/blob/main/hacktober.png" alt="Hacktober fest 2024" width="60%">
</div>


<!--line-->
<img src="https://www.animatedimages.org/data/media/562/animated-line-image-0184.gif" width="1920" />


## 📝 License

Expand Down
7 changes: 6 additions & 1 deletion routes/user.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const express = require("express");
const router = express.Router();
const User = require("../models/user.js");
const wrapAsync = require("../utils/wrapAsync.js");
const passport = require("passport");
const { saveRedirectUrl } = require("../middleware.js");
Expand Down Expand Up @@ -30,4 +29,10 @@ router

router.get("/logout", saveRedirectUrl, userController.logout);

// Add routes for forgot password
router
.route("/forgot")
.get(userController.renderForgotPasswordForm)
.post(wrapAsync(userController.forgotPassword));

module.exports = router;
51 changes: 51 additions & 0 deletions views/users/forgot.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<% layout("/layouts/boilerplate") -%>
<div class="row justify-content-center my-5">
<div class="col-md-6 col-lg-5">
<div class="card shadow-lg border-0 rounded">
<div class="card-body p-4">
<h1 class="text-center mb-4 display-6" style="color: black; font-weight: bold;">Forgot Password</h1>
<form action="/forgot" method="POST" class="needs-validation" novalidate>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input name="email" id="email" placeholder="Enter your email" type="email"
class="form-control form-control-lg rounded-pill" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Please enter a valid email.
</div>
</div>

<button type="submit" class="btn btn-success w-100 btn-lg rounded-pill mt-3">Reset
Password</button>
</form>
<div class="text-center mt-3">
<a href="/login" class="text-decoration-none" style="color: black; font-weight: bold;">Back to
Login</a>
</div>
<p class="text-center mt-4">
Don't have an account? <a href="/signup" class="text-decoration-none">Sign Up</a>
</p>
</div>
</div>
</div>
</div>

<!-- Bootstrap form validation -->
<script>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function () {
'use strict'
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms).forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
99 changes: 52 additions & 47 deletions views/users/login.ejs
Original file line number Diff line number Diff line change
@@ -1,56 +1,61 @@
<% layout("/layouts/boilerplate") -%>
<div class="row justify-content-center my-5">
<div class="col-md-6 col-lg-5">
<div class="card shadow-lg border-0 rounded">
<div class="card-body p-4">
<h1 class="text-center mb-4 display-6" style="color: black; font-weight: bold;">Log In</h1>
<form action="/login" method="POST" class="needs-validation" novalidate>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input name="email" id="email" placeholder="Enter your email" type="email" class="form-control form-control-lg rounded-pill" required>
<div class="valid-feedback">
Looks good!
<div class="row justify-content-center my-5">
<div class="col-md-6 col-lg-5">
<div class="card shadow-lg border-0 rounded">
<div class="card-body p-4">
<h1 class="text-center mb-4 display-6" style="color: black; font-weight: bold;">Log In</h1>
<form action="/login" method="POST" class="needs-validation" novalidate>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input name="email" id="email" placeholder="Enter your email" type="email"
class="form-control form-control-lg rounded-pill" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Please enter a valid email.
</div>
</div>
<div class="invalid-feedback">
Please enter a valid email.
</div>
</div>

<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input name="password" id="password" placeholder="Enter your password" type="password" class="form-control form-control-lg rounded-pill" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Please enter a valid password.
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input name="password" id="password" placeholder="Enter your password" type="password"
class="form-control form-control-lg rounded-pill" required>
<div class="valid-feedback">
Looks good!
</div>
<div class="invalid-feedback">
Please enter a valid password.
</div>
</div>
</div>

<button type="submit" class="btn btn-success w-100 btn-lg rounded-pill mt-3">Log In</button>
</form>
<p class="text-center mt-4">
Don't have an account? <a href="/signup" class="text-decoration-none">Sign Up</a>
</p>
<button type="submit" class="btn btn-success w-100 btn-lg rounded-pill mt-3">Log In</button>
</form>
<div class="text-center mt-3">
<a href="/forgot" class="text-decoration-none" style="color: black; font-weight: bold;">Forgot Password?</a>
</div>
<p class="text-center mt-4">
Don't have an account? <a href="/signup" class="text-decoration-none">Sign Up</a>
</p>
</div>
</div>
</div>
</div>
</div>

<!-- Bootstrap form validation -->
<script>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function () {
'use strict'
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms).forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
<!-- Bootstrap form validation -->
<script>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function () {
'use strict'
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms).forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>