Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
227fa6c
creating the storage for items
Prajituric May 3, 2023
f6faad3
creating different paths and stucturating the code for better underst…
Prajituric May 3, 2023
d7dd2ef
distributing content for the specific files
Prajituric May 3, 2023
c83b732
adding the routes for specific files
Prajituric May 3, 2023
e21ce18
adding characteristics for products
Prajituric May 3, 2023
b22458c
adding dynamic content on forms
Prajituric May 3, 2023
60c7589
stabilizing the form with routes
Prajituric May 3, 2023
fd6e6dc
creating the mobile version
Prajituric May 4, 2023
131d48d
configurating the media queries
Prajituric May 4, 2023
5e73569
adding the details functionality
Prajituric May 4, 2023
304c256
creating the add to cart pages
Prajituric May 4, 2023
244dfe3
restore the merge mistake 1/?
Prajituric May 8, 2023
e2bd2f2
solving the merge mistake 2/3
Prajituric May 8, 2023
2586502
solving the merge mistake 3/3
Prajituric May 8, 2023
77b9a9c
connecting the project to database
Prajituric May 11, 2023
8c8fe8f
customize the code to work with mysql
Prajituric May 11, 2023
941fe36
fixing the style
Prajituric May 11, 2023
f675519
updating the project to use sequelize
Prajituric May 11, 2023
db2f0ff
creating the cart database
Prajituric May 11, 2023
5c67edc
finishing the db connections
Prajituric May 13, 2023
5315a29
changing the database to mongoDB
Prajituric May 13, 2023
6acbeb8
editing items using mongodb
Prajituric May 22, 2023
7df5687
deleting products using mongodb
Prajituric May 22, 2023
67ad007
solving add product issue
Prajituric May 22, 2023
a869632
creating the cart functionality with database and fixing the redirect…
Prajituric May 22, 2023
569226e
maintaining the clean code and config
Prajituric Sep 18, 2023
47b0cb6
clearing junk data
Prajituric Sep 18, 2023
cdd9bde
stabilize
Prajituric Nov 13, 2023
de74c49
creating reset pwbutton and page
Prajituric Nov 20, 2023
9115364
update
Prajituric Dec 5, 2023
d8cfef4
cart update
Prajituric Dec 5, 2023
21568c7
updating orders
Prajituric Dec 6, 2023
20351ba
console modifiers
Prajituric Dec 6, 2023
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
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# EditorConfig is awesome: https://EditorConfig.org

# Top-most EditorConfig file
root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
62 changes: 58 additions & 4 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,75 @@
const path = require("path");

const express = require("express");
const bodyParser = require("body-parser");
const path = require("path");
const mongoose = require("mongoose");
const session = require("express-session");
const MongoDBStore = require("connect-mongodb-session")(session);
const csrf = require("csurf");
const flash = require("connect-flash");

const errorController = require("./controllers/error");
const User = require("./models/user");

const MONGODB_URI =
"mongodb+srv://userDB:rgkBQLIEPZYCWBFS@cluster0.oopvnro.mongodb.net/shop?retryWrites=true";

const app = express();
const store = new MongoDBStore({
uri: MONGODB_URI,
collection: "sessions",
});
const csrfProtection = csrf();

app.set("view engine", "pug");
app.set("views");
app.set("views", "views");

const adminRoutes = require("./routes/admin");
const shopRoutes = require("./routes/shop");
const authRoutes = require("./routes/auth");

app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, "public")));
app.use(
session({
secret: "my secret",
resave: false,
saveUninitialized: false,
store: store,
})
);
app.use(csrfProtection);
app.use(flash());

app.use((req, res, next) => {
if (!req.session.user) {
return next();
}
User.findById(req.session.user._id)
.then((user) => {
req.user = user;
next();
})
.catch((err) => console.log(err));
});

app.use((req, res, next) => {
res.locals.isAuth = req.session.isLoggedIn;
res.locals.csrfToken = req.csrfToken();
next();
});

app.use("/admin", adminRoutes);
app.use(shopRoutes);
app.use(authRoutes);

app.use(errorController.get404Page);
app.use(errorController.get404);

app.listen(3000);
mongoose
.connect(MONGODB_URI, { useNewUrlParser: true })
.then((result) => {
app.listen(3000);
})
.catch((err) => {
console.log(err);
});
105 changes: 105 additions & 0 deletions controllers/admin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const Product = require("../models/product");

exports.getAddProduct = (req, res, next) => {
res.render("admin/edit-product", {
pageTitle: "Add Product",
path: "/admin/add-product",
editing: false,
});
};

exports.postAddProduct = (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
const product = new Product({
title: title,
price: price,
description: description,
imageUrl: imageUrl,
userId: req.user,
});
product
.save()
.then((result) => {
console.log("Created Product");
res.redirect("/admin/products");
})
.catch((err) => {
console.log(err);
});
};

exports.getEditProduct = (req, res, next) => {
const editMode = req.query.edit;
if (!editMode) {
return res.redirect("/");
}
const prodId = req.params.productId;
Product.findById(prodId)
.then((product) => {
if (!product) {
return res.redirect("/");
}
if (product.userId.toString() !== req.user._id.toString()) {
return res.redirect("/");
}
res.render("admin/edit-product", {
pageTitle: "Edit Product",
path: "/admin/edit-product",
editing: editMode,
product: product,
});
})
.catch((err) => console.log(err));
};

exports.postEditProduct = (req, res, next) => {
const prodId = req.body.productId;
const updatedTitle = req.body.title;
const updatedPrice = req.body.price;
const updatedImageUrl = req.body.imageUrl;
const updatedDesc = req.body.description;

Product.findById(prodId)
.then((product) => {
if (product.userId.toString() !== req.user._id.toString()) {
return res.redirect("/");
}

product.title = updatedTitle;
product.price = updatedPrice;
product.description = updatedDesc;
product.imageUrl = updatedImageUrl;
return product.save();
})
.then((result) => {
console.log("UPDATED PRODUCT!");
res.redirect("/admin/products");
})
.catch((err) => console.log(err));
};

exports.getProducts = (req, res, next) => {
Product.find({ userId: req.user._id })
.then((products) => {
console.log(products);
res.render("admin/products", {
prods: products,
pageTitle: "Admin Products",
path: "/admin/products",
});
})
.catch((err) => console.log(err));
};

exports.postDeleteProduct = (req, res, next) => {
const prodId = req.body.productId;
Product.findByIdAndRemove({ _id: prodId, userId: req.user._id })
.then(() => {
console.log("DESTROYED PRODUCT");
res.redirect("/admin/products");
})
.catch((err) => console.log(err));
};
150 changes: 150 additions & 0 deletions controllers/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
const bcrypt = require("bcryptjs");

const User = require("../models/user");
const crypto = require("crypto");

exports.getLogin = (req, res, next) => {
let message = req.flash("error");
if (message.length > 0) {
message = message[0];
} else {
message = null;
}
res.render("auth/login", {
path: "/login",
pageTitle: "Login",
errorMessage: message,
});
};

exports.getSignup = (req, res, next) => {
let message = req.flash("error");
if (message.length > 0) {
message = message[0];
} else {
message = null;
}
res.render("auth/signup", {
path: "/signup",
pageTitle: "Signup",
errorMessage: message,
});
};

exports.postLogin = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
User.findOne({ email: email })
.then((user) => {
if (!user) {
req.flash("error", "Invalid email or password.");
return res.redirect("/login");
}
bcrypt
.compare(password, user.password)
.then((doMatch) => {
if (doMatch) {
req.session.isLoggedIn = true;
req.session.user = user;
return req.session.save((err) => {
console.log(err);
res.redirect("/");
});
}
req.flash("error", "Invalid email or password.");
res.redirect("/login");
})
.catch((err) => {
console.log(err);
res.redirect("/login");
});
})
.catch((err) => console.log(err));
};

exports.postSignup = (req, res, next) => {
const email = req.body.email;
const password = req.body.password;
const confirmPassword = req.body.confirmPassword;

// Input validation code
if (
!password ||
!confirmPassword ||
password.length < 8 ||
confirmPassword.length < 8
) {
req.flash(
"error",
"Invalid password. Password must have at least 8 characters."
);
return res.redirect("/signup");
}

const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailPattern.test(email)) {
req.flash("error", "Invalid email format.");
return res.redirect("/signup");
}

if (password !== confirmPassword) {
req.flash("error", "Passwords do not match.");
return res.redirect("/signup");
}

User.findOne({ email: email }).then((userDoc) => {
if (userDoc) {
req.flash("error", "Your e-mail is already in use.");
return res.redirect("/signup");
}

return bcrypt
.hash(password, 12)
.then((hashedPassword) => {
const verificationToken = crypto.randomBytes(32).toString("hex");
const user = new User({
email: email,
password: hashedPassword,
cart: { items: [] },
isVerified: false,
verificationToken: verificationToken,
});
return user.save();
})
.then(() => {
const successMessage = "Sign-up successful! Please log in.";
req.flash("success", successMessage);

res.render("auth/login", {
path: "/login",
pageTitle: "Login",
errorMessage: null,
successMessage: req.flash("success")[0],
});
})
.catch((err) => {
console.log(err);
});
});
};

exports.postLogout = (req, res, next) => {
req.session.destroy((err) => {
console.log(err);
res.redirect("/");
});
};

exports.getResetPw = (req, res, next) => {
let message = req.flash("error");
if (message.length > 0) {
message = message[0];
} else {
message = null;
}
res.render("auth/resetpw", {
path: "/resetpw",
pageTitle: "Reset Password",
errorMessage: message,
});
};
8 changes: 6 additions & 2 deletions controllers/error.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
exports.get404Page = (req, res, next) => {
res.status(404).render("404", { pageTitle: "Page Not Found" });
exports.get404 = (req, res, next) => {
res.status(404).render("404", {
pageTitle: "Page Not Found",
path: "/404",
isAuth: req.session.isLoggedIn,
});
};
23 changes: 0 additions & 23 deletions controllers/products.js

This file was deleted.

Loading