mirror of
https://github.com/DerTyp7/shop-ejs-expressjs.git
synced 2025-10-29 12:32:11 +01:00
400 lines
15 KiB
JavaScript
400 lines
15 KiB
JavaScript
// Import Packages
|
||
const express = require('express');
|
||
const bcrypt = require("bcryptjs");
|
||
const cookieParser = require("cookie-parser");
|
||
const jwt = require("jsonwebtoken");
|
||
const bodyParser = require("body-parser");
|
||
const uuid = require("uuid");
|
||
|
||
// Import Modules
|
||
const mysql_handler = require("./mysql_handler");
|
||
|
||
// Global Variables
|
||
const app = express();
|
||
const port = 3000;
|
||
const SECRET_KEY = "KEY";
|
||
|
||
// Express App Setup
|
||
app.set("view engine", "ejs");
|
||
app.use(express.json());
|
||
app.use(express.urlencoded({ extended: true}));
|
||
app.use(cookieParser());
|
||
app.use(bodyParser.json());
|
||
app.use(express.static(__dirname + "/static"));
|
||
|
||
// Authentication Handlers
|
||
|
||
// Check if user is authenticated and NO redirect
|
||
function authNoRedirectHandler(req, res, next){
|
||
const authcookie = req.cookies.authcookie; // Get authcookie from cookie
|
||
|
||
jwt.verify(authcookie, SECRET_KEY, (err, data) =>{ // Verify authcookie
|
||
if(err){ // If authcookie is invalid
|
||
console.log(err);
|
||
next();
|
||
} else if(data.user){ // If authcookie is valid
|
||
req.user = data.user; // Set user to data.user
|
||
mysql_handler.con.query(`SELECT * FROM users WHERE id = "${req.user}"`, (err, result) => { // Get user from database
|
||
if(err) console.log(err);
|
||
let user = JSON.parse(JSON.stringify(result))[0]; // Parse user from database
|
||
if(user.id){
|
||
// Set user to req.user
|
||
req.isAdmin = user.isAdmin;
|
||
req.username = user.username;
|
||
req.firstname = user.firstname;
|
||
req.lastname = user.lastname;
|
||
req.email = user.email;
|
||
}
|
||
|
||
next(); // Continue to next handler
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
|
||
// Check if user is authenticated and redirect to login if not
|
||
function authenticatedHandler(req, res, next){
|
||
const authcookie = req.cookies.authcookie; // Get authcookie from cookie
|
||
|
||
jwt.verify(authcookie, SECRET_KEY, (err, data) =>{ // Verify authcookie
|
||
if(err){ // If authcookie is invalid
|
||
console.log(err);
|
||
res.redirect("/login");
|
||
} else if(data.user){ // If authcookie is valid
|
||
req.user = data.user; // Set user to data.user
|
||
mysql_handler.con.query(`SELECT * FROM users LEFT JOIN userinfos ON users.id=userinfos.userId WHERE users.id = "${req.user}"`, (err, result) => { // Get user from database
|
||
if(err) console.log(err);
|
||
let user = JSON.parse(JSON.stringify(result))[0]; // Parse user from database
|
||
// Set user to req.user
|
||
req.isAdmin = user.isAdmin;
|
||
req.username = user.username;
|
||
req.firstname = user.firstname;
|
||
req.lastname = user.lastname;
|
||
req.email = user.email;
|
||
next(); // Continue to next handler
|
||
});
|
||
}
|
||
});
|
||
}
|
||
|
||
// Check if user is not authenticated and redirect to home if so
|
||
function notAuthenticatedHandler(req, res, next){
|
||
const authcookie = req.cookies.authcookie; // Get authcookie from cookie
|
||
|
||
jwt.verify(authcookie, SECRET_KEY, (err, data) =>{ // Verify authcookie
|
||
if(err){ // If authcookie is invalid
|
||
console.log(err);
|
||
next(); // Continue to next handler
|
||
} else if(data.user){ // If authcookie is valid
|
||
res.redirect("/");
|
||
}
|
||
});
|
||
}
|
||
|
||
// Homepage
|
||
app.get("/", authNoRedirectHandler, (req, res) => {
|
||
mysql_handler.con.query("SELECT * FROM products", function(err, result){
|
||
if(err) throw err;
|
||
|
||
let dict = {
|
||
title: "Startseite",
|
||
user: req.user,
|
||
products: JSON.parse(JSON.stringify(result))
|
||
}
|
||
res.render('index', dict)
|
||
});
|
||
});
|
||
|
||
// Account
|
||
app.get("/account", authenticatedHandler, (req, res) => {
|
||
mysql_handler.con.query(`SELECT orders.id, products.name, order_products.quantity, order_products.price
|
||
FROM orders LEFT JOIN order_products ON orders.id=order_products.orderId
|
||
LEFT JOIN products ON order_products.productId=products.id WHERE orders.userId = '${req.user}' ORDER BY orders.id DESC`, (err, result) => {
|
||
if(err) console.log(err);
|
||
let dict = {
|
||
title: "Account",
|
||
user: req.user,
|
||
isAdmin: req.isAdmin,
|
||
username: req.username,
|
||
firstname: req.firstname,
|
||
lastname: req.lastname,
|
||
email: req.email,
|
||
orders: JSON.parse(JSON.stringify(result))
|
||
}
|
||
res.render('account', dict)
|
||
})
|
||
});
|
||
|
||
|
||
// Product Page
|
||
app.get("/product/:productId", authNoRedirectHandler, (req, res) => {
|
||
let productId = req.params.productId;
|
||
|
||
mysql_handler.con.query(`SELECT s.name AS sellerName, p.name AS productName, p.description AS productDescription, p.id AS id, price,quantity, delivery_time, p.categoryId
|
||
FROM products AS p LEFT JOIN sellers AS s ON p.sellerId= s.id WHERE p.id=${productId}` , function(err, result){
|
||
if(err) throw err;
|
||
|
||
let product = JSON.parse(JSON.stringify(result))[0];
|
||
|
||
mysql_handler.con.query(`SELECT title, content ,rating, u.username AS name FROM reviews AS r LEFT JOIN users AS u ON r.userId = u.id WHERE productId=${productId}`,function(err,result){
|
||
if(err) throw err;
|
||
let reviews = JSON.parse(JSON.stringify(result));
|
||
console.log(product)
|
||
mysql_handler.con.query(`SELECT * FROM categories WHERE id='${product.categoryId}'`,function(err,result){
|
||
if(err) throw err;
|
||
let category = JSON.parse(JSON.stringify(result))[0];
|
||
|
||
let dict = {
|
||
title: product.productName,
|
||
product: product,
|
||
shippingDays: 3,
|
||
stockAmount: 50,
|
||
productDescription: "ez",
|
||
loggedIn: true,
|
||
reviews: reviews,
|
||
category: category,
|
||
user: req.user,
|
||
}
|
||
res.render('product', dict)
|
||
});
|
||
});
|
||
|
||
});
|
||
});
|
||
|
||
// Reviews
|
||
app.post("/review/create/:productId", authenticatedHandler,(req, res) => {
|
||
let productId = req.params.productId;
|
||
let rating = req.body.rating;
|
||
let title = req.body.title;
|
||
let content = req.body.content;
|
||
|
||
|
||
mysql_handler.con.query(`INSERT INTO reviews(title, content, rating, userId, productId)
|
||
VALUES('${title}', '${content}', '${rating}', (SELECT id FROM users WHERE id = ${req.user}), (SELECT id FROM products WHERE id = ${productId}))`, (err, result) => {
|
||
if(err) throw err;
|
||
res.redirect("/product/" + productId);
|
||
});
|
||
|
||
});
|
||
|
||
// Search Page
|
||
app.get("/search", authNoRedirectHandler,(req, res) => {
|
||
var products = [
|
||
{
|
||
title: "Panasonic LUMIX DC-GH5M2ME",
|
||
price: 1699.99,
|
||
img: "https://m.media-amazon.com/images/I/815eDw--FQS._AC_SL1500_.jpg",
|
||
desc: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
|
||
},
|
||
{
|
||
title: "Sony α 7 IV",
|
||
price: 2999.00,
|
||
img: "https://m.media-amazon.com/images/I/819+EOCsREL._AC_SL1500_.jpg",
|
||
desc: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
|
||
},
|
||
{
|
||
title: "Canon PowerShot G3 X",
|
||
price: 876.34,
|
||
img: "https://m.media-amazon.com/images/I/91bODLikNBL._AC_SL1500_.jpg",
|
||
desc: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
|
||
},
|
||
{
|
||
title: "Canon PowerShot SX710",
|
||
price: 495.00,
|
||
img: "https://m.media-amazon.com/images/I/91w6iw3JtiL._AC_SL1500_.jpg",
|
||
desc: "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.",
|
||
},
|
||
]
|
||
|
||
let dict = {
|
||
title: "Suche",
|
||
products: products,
|
||
user: req.user,
|
||
}
|
||
|
||
mysql_handler.con.query("SELECT * FROM products", function(err, result){
|
||
if(err) throw err;
|
||
|
||
dict.products = JSON.parse(JSON.stringify(result));
|
||
|
||
res.render('search', dict)
|
||
});
|
||
});
|
||
|
||
// Order Page
|
||
app.get("/order/:productId/:quantity/", authenticatedHandler, (req, res) => {
|
||
|
||
let error = "";
|
||
mysql_handler.con.query(`SELECT * FROM products WHERE id=${req.params.productId}`, function(err, result){ // Get product from database
|
||
if(err) throw err;
|
||
|
||
result = JSON.parse(JSON.stringify(result))[0]; // Parse result from database
|
||
|
||
if(req.params.quantity > result.quantity){ // If quantity is higher than available quantity
|
||
error = "Nicht genug Produkte vorhanden";
|
||
}
|
||
|
||
let dict = {
|
||
title: "Bestellung",
|
||
error: error,
|
||
product: result,
|
||
quantity: req.params.quantity,
|
||
user: req.user,
|
||
}
|
||
|
||
res.render('order', dict);
|
||
});
|
||
});
|
||
|
||
// Order Success Page
|
||
app.get("/order_success/:trackingnumber", authenticatedHandler, (req, res) => {
|
||
let dict = {
|
||
title: "Bestellung erfolgreich",
|
||
trackingnumber: req.params.trackingnumber
|
||
}
|
||
|
||
res.render('order_success', dict);
|
||
});
|
||
|
||
// Order POST Request
|
||
app.post("/order", authenticatedHandler, (req, res) => {
|
||
let productId = req.body.productId;
|
||
let quantity = req.body.quantity;
|
||
let userId = req.user;
|
||
|
||
mysql_handler.con.query(`SELECT * FROM products WHERE id=${productId}`, function(err, result){
|
||
if(err) throw err;
|
||
result = JSON.parse(JSON.stringify(result))[0];
|
||
|
||
if(quantity > result.quantity){
|
||
res.redirect(`/order/${productId}/${quantity}/`);
|
||
}else{
|
||
order_trackingnumber = uuid.v4();
|
||
mysql_handler.createOrder(userId, order_trackingnumber, 0, productId, quantity) ;
|
||
|
||
res.redirect("/order_success/" + order_trackingnumber);
|
||
}
|
||
});
|
||
});
|
||
|
||
|
||
// Admin
|
||
app.get("/admin/product/delete/:productId", authenticatedHandler, (req, res) => {
|
||
if(req.isAdmin){
|
||
productId = req.params.productId;
|
||
mysql_handler.con.query(`DELETE FROM products WHERE id=${productId}`, function(err, result){
|
||
if(err) console.log(err);
|
||
});
|
||
}
|
||
});
|
||
|
||
// Authentication
|
||
// Logout
|
||
app.get("/logout/", authenticatedHandler, (req, res) => {
|
||
res.clearCookie("authcookie"); // Clear cookie
|
||
res.redirect("/");
|
||
});
|
||
|
||
// Register Page
|
||
app.get("/register/:error?", notAuthenticatedHandler, (req, res) => {
|
||
let dict = {
|
||
title: "Register",
|
||
error: req.params.error
|
||
}
|
||
res.render('register', dict);
|
||
});
|
||
|
||
// Login Page
|
||
app.get("/login/:error?", notAuthenticatedHandler, (req, res) => {
|
||
let dict = {
|
||
title: "Login",
|
||
error: req.params.error
|
||
}
|
||
|
||
res.render('login', dict);
|
||
});
|
||
|
||
// Register POST Request
|
||
app.post("/auth/register", notAuthenticatedHandler,(req, res) =>{
|
||
// Get data from POST request
|
||
let username = req.body.username;
|
||
let email = req.body.email;
|
||
let password1 = req.body.password1;
|
||
let password2 = req.body.password2;
|
||
let firstname = req.body.firstname;
|
||
let lastname = req.body.lastname;
|
||
let gender = req.body.gender;
|
||
let street = req.body.street;
|
||
let housenumber = req.body.housenumber;
|
||
let postcode = req.body.postcode;
|
||
let cityName = req.body.cityName;
|
||
let country = req.body.country;
|
||
|
||
let error = ""; // Error message
|
||
|
||
if(password1 != password2){ // If passwords don't match
|
||
error += "Passwörter sind unterschiedlich!";
|
||
}else if(password1.length < 8){ // If password is too short
|
||
error += "Passwort muss mindestens 8 Zeichen lang sein!";
|
||
}
|
||
if(username.length < 3){ // If username is too short
|
||
error += "<br> Der Benutzername muss mindestens 3 Zeichen lang sein!";
|
||
}else if(username.length > 30){ // If username is too long
|
||
error += "<br> Der Benutzername darf maximal 30 Zeichen lang sein!";
|
||
}
|
||
|
||
if(error != ""){ // If there is an error
|
||
res.redirect(`/register/${error}`); // Redirect to register page with error message
|
||
}else{
|
||
bcrypt.genSalt(10, function(err, salt) { // Generate salt
|
||
bcrypt.hash(password1, salt, function(err, hash){ // Hash password
|
||
mysql_handler.createUser(username, email, hash, firstname, lastname, gender, street, housenumber, postcode, cityName, country);
|
||
res.redirect(`/login/`);
|
||
});
|
||
});
|
||
}
|
||
});
|
||
|
||
// Login POST Request
|
||
app.post("/auth/login", notAuthenticatedHandler, (req, res) =>{
|
||
// Get data from POST request
|
||
let username = req.body.username;
|
||
let password = req.body.password;
|
||
|
||
error = "" // Error message
|
||
|
||
mysql_handler.con.query(`SELECT * FROM users WHERE username = "${username}"`, function(err, result){ // Get user from database
|
||
if(err){ // If there is an error
|
||
error = "Login-Daten falsch!"
|
||
}else{ // If there is no error
|
||
result = JSON.parse(JSON.stringify(result))[0]; // Parse result from database
|
||
if(result){ // If there is a user
|
||
user = result; // Set user
|
||
dbPassword = user.password; // Get password from database
|
||
|
||
bcrypt.compare(password, dbPassword, function(err, matched){ // Compare password
|
||
if(err) console.log(err);
|
||
if(matched){ // If password matches
|
||
// Set cookie
|
||
const token = jwt.sign({user:user.id}, SECRET_KEY)
|
||
res.cookie('authcookie', token, {maxAge: 90000000, httpOnly: true})
|
||
res.redirect(`/`)
|
||
}else{
|
||
error = "Login-Daten falsch!"
|
||
}
|
||
})
|
||
}else{
|
||
error = "Login-Daten falsch!"
|
||
}
|
||
}
|
||
if(error != ""){ // If there is an error
|
||
res.redirect(`/login/${error}`)
|
||
}
|
||
});
|
||
})
|
||
|
||
app.listen(port, () =>{ // Start server
|
||
console.log("Listining to " + port)
|
||
}); |