From 76264c0400da64371161e5bd48d43633f9d34c6e Mon Sep 17 00:00:00 2001 From: shadmaankhan Date: Tue, 6 Jun 2023 12:18:29 +0530 Subject: [PATCH 1/3] =?UTF-8?q?Shadmaan=20Commit=F0=9F=8D=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/auth.js | 145 +++++----- lib/cart.js | 208 ++++++++------- lib/common.js | 490 ++++++++++++++++++---------------- lib/schemas/editProduct.json | 120 ++++----- lib/schemas/editUser.json | 35 +-- lib/schemas/editVariant.json | 66 +++-- lib/schemas/newCustomer.json | 110 ++++---- lib/schemas/newDiscount.json | 55 ++-- lib/schemas/newProduct.json | 122 ++++----- lib/schemas/newUser.json | 41 ++- lib/schemas/newVariant.json | 57 ++-- lib/schemas/saveCustomer.json | 100 +++---- 12 files changed, 774 insertions(+), 775 deletions(-) diff --git a/lib/auth.js b/lib/auth.js index a515394a..54272592 100644 --- a/lib/auth.js +++ b/lib/auth.js @@ -1,91 +1,96 @@ -const ObjectId = require('mongodb').ObjectID; -const _ = require('lodash'); +const ObjectId = require("mongodb"); +const lodash = require("lodash"); const restrictedRoutes = [ - { route: '/admin/product/new', response: 'redirect' }, - { route: '/admin/product/insert', response: 'redirect' }, - { route: '/admin/product/edit/:id', response: 'redirect' }, - { route: '/admin/product/update', response: 'redirect' }, - { route: '/admin/product/delete/:id', response: 'redirect' }, - { route: '/admin/product/publishedState', response: 'json' }, - { route: '/admin/product/setasmainimage', response: 'json' }, - { route: '/admin/product/deleteimage', response: 'json' }, - { route: '/admin/product/removeoption', response: 'json' }, - { route: '/admin/order/updateorder', response: 'json' }, - { route: '/admin/settings/update', response: 'json' }, - { route: '/admin/settings/pages/new', response: 'redirect' }, - { route: '/admin/settings/pages/edit/:page', response: 'redirect' }, - { route: '/admin/settings/pages', response: 'json' }, - { route: '/admin/settings/page/delete/:page', response: 'json' }, - { route: '/admin/settings/menu/new', response: 'json' }, - { route: '/admin/settings/menu/update', response: 'json' }, - { route: '/admin/settings/menu/delete', response: 'json' }, - { route: '/admin/settings/menu/saveOrder', response: 'json' }, - { route: '/admin/file/upload', response: 'json' } + { route: "/admin/product/new", response: "redirect" }, + { route: "/admin/product/insert", response: "redirect" }, + { route: "/admin/product/edit/:id", response: "redirect" }, + { route: "/admin/product/update", response: "redirect" }, + { route: "/admin/product/delete/:id", response: "redirect" }, + { route: "/admin/product/publishedState", response: "json" }, + { route: "/admin/product/setasmainimage", response: "json" }, + { route: "/admin/product/deleteimage", response: "json" }, + { route: "/admin/product/removeoption", response: "json" }, + { route: "/admin/order/updateorder", response: "json" }, + { route: "/admin/settings/update", response: "json" }, + { route: "/admin/settings/pages/new", response: "redirect" }, + { route: "/admin/settings/pages/edit/:page", response: "redirect" }, + { route: "/admin/settings/pages", response: "json" }, + { route: "/admin/settings/page/delete/:page", response: "json" }, + { route: "/admin/settings/menu/new", response: "json" }, + { route: "/admin/settings/menu/update", response: "json" }, + { route: "/admin/settings/menu/delete", response: "json" }, + { route: "/admin/settings/menu/saveOrder", response: "json" }, + { route: "/admin/file/upload", response: "json" }, ]; const restrict = (req, res, next) => { - checkLogin(req, res, next); + checkLogin(req, res, next); }; const checkLogin = async (req, res, next) => { - const db = req.app.db; - // if not protecting we check for public pages and don't checkLogin - if(req.session.needsSetup === true){ - res.redirect('/admin/setup'); - return; - } - - // If API key, check for a user - if(req.headers.apikey){ - try{ - const user = await db.users.findOne({ - apiKey: ObjectId(req.headers.apikey), - isAdmin: true - }); - if(!user){ - res.status(400).json({ message: 'Access denied' }); - return; - } - // Set API authenticated in the req - req.apiAuthenticated = true; - next(); - return; - }catch(ex){ - res.status(400).json({ message: 'Access denied' }); - return; - } - } + const db = req.app.db; + // if not protecting we check for public pages and don't checkLogin + if (req.session.needsSetup === true) { + res.redirect("/admin/setup"); + return; + } - if(req.session.user){ - next(); + // If API key, check for a user + if (req.headers.apikey) { + try { + const user = await db.users.findOne({ + apiKey: ObjectId(req.headers.apikey), + isAdmin: true, + }); + if (!user) { + res.status(400).json({ message: "Access denied" }); return; + } + // Set API authenticated in the req + req.apiAuthenticated = true; + next(); + return; + } catch (error) { + res.status(400).json({ + status: "Failed", + message: "Access denied", + }); + return; } - res.redirect('/admin/login'); + } + + if (req.session.user) { + next(); + return; + } + res.redirect("/admin/login"); }; // Middleware to check for admin access for certain route const checkAccess = (req, res, next) => { - const routeCheck = _.find(restrictedRoutes, { route: req.route.path }); + const routeCheck = lodash.find(restrictedRoutes, { route: req.route.path }); - // If the user is not an admin and route is restricted, show message and redirect to /admin - if(req.session.isAdmin === false && routeCheck){ - if(routeCheck.response === 'redirect'){ - req.session.message = 'Unauthorised. Please refer to administrator.'; - req.session.messageType = 'danger'; - res.redirect('/admin'); - return; - } - if(routeCheck.response === 'json'){ - res.status(400).json({ message: 'Unauthorised. Please refer to administrator.' }); - } - }else{ - next(); + // If the user is not an admin and route is restricted, show message and redirect to /admin + if (req.session.isAdmin === false && routeCheck) { + if (routeCheck.response === "redirect") { + req.session.message = "Unauthorised Please refer to administrator."; + req.session.messageType = "danger"; + res.redirect("/admin"); + return; + } + if (routeCheck.response === "json") { + res + .status(400) + .json({ message: "Unauthorised. Please refer to administrator." }); } + } else { + next(); + } }; module.exports = { - restrict, - checkLogin, - checkAccess + restrict, + checkLogin, + checkAccess, }; diff --git a/lib/cart.js b/lib/cart.js index b541d49c..62b2935f 100644 --- a/lib/cart.js +++ b/lib/cart.js @@ -1,119 +1,121 @@ -const { - getConfig -} = require('./config'); +const { getConfig } = require("./config"); const updateTotalCart = async (req, res) => { - const config = getConfig(); - const db = req.app.db; - - req.session.totalCartAmount = 0; - req.session.totalCartItems = 0; - req.session.totalCartProducts = 0; - - // If cart is empty return zero values - if(!req.session.cart){ - return; - } - - Object.keys(req.session.cart).forEach((item) => { - req.session.totalCartAmount = req.session.totalCartAmount + req.session.cart[item].totalItemPrice; - req.session.totalCartProducts = req.session.totalCartProducts + req.session.cart[item].quantity; + const config = getConfig(); + const db = req.app.db; + + req.session.totalCartAmount = 0; + req.session.totalCartItems = 0; + req.session.totalCartProducts = 0; + + // If cart is empty return zero values + if (!req.session.cart) { + return; + } + + Object.keys(req.session.cart).forEach((item) => { + req.session.totalCartAmount = + req.session.totalCartAmount + req.session.cart[item].totalItemPrice; + req.session.totalCartProducts = + req.session.totalCartProducts + req.session.cart[item].quantity; + }); + + // Update the total items in cart for the badge + req.session.totalCartItems = Object.keys(req.session.cart).length; + + // Update the total amount not including shipping/discounts + req.session.totalCartNetAmount = req.session.totalCartAmount; + + // Update checking cart for subscription + updateSubscriptionCheck(req, res); + + // Calculate shipping using the loaded module + config.modules.loaded.shipping.calculateShipping( + req.session.totalCartNetAmount, + config, + req + ); + + // If discount module enabled + if (config.modules.loaded.discount) { + // Recalculate discounts + const discount = await db.discounts.findOne({ + code: req.session.discountCode, }); - - // Update the total items in cart for the badge - req.session.totalCartItems = Object.keys(req.session.cart).length; - - // Update the total amount not including shipping/discounts - req.session.totalCartNetAmount = req.session.totalCartAmount; - - // Update checking cart for subscription - updateSubscriptionCheck(req, res); - - // Calculate shipping using the loaded module - config.modules.loaded.shipping.calculateShipping( - req.session.totalCartNetAmount, - config, - req - ); - - // If discount module enabled - if(config.modules.loaded.discount){ - // Recalculate discounts - const discount = await db.discounts.findOne({ code: req.session.discountCode }); - if(discount){ - config.modules.loaded.discount.calculateDiscount( - discount, - req - ); - }else{ - // If discount code is not found, remove it - delete req.session.discountCode; - req.session.totalCartDiscount = 0; - } + if (discount) { + config.modules.loaded.discount.calculateDiscount(discount, req); + } else { + // If discount code is not found, remove it + delete req.session.discountCode; + req.session.totalCartDiscount = 0; } + } - // Calculate our total amount removing discount and adding shipping - req.session.totalCartAmount = (req.session.totalCartNetAmount - req.session.totalCartDiscount) + req.session.totalCartShipping; + // Calculate our total amount removing discount and adding shipping + req.session.totalCartAmount = + req.session.totalCartNetAmount - + req.session.totalCartDiscount + + req.session.totalCartShipping; }; const updateSubscriptionCheck = (req, res) => { - // If cart is empty - if(!req.session.cart || req.session.cart.length === 0){ - req.session.cartSubscription = null; - return; + // If cart is empty + if (!req.session.cart || req.session.cart.length === 0) { + req.session.cartSubscription = null; + return; + } + + Object.keys(req.session.cart).forEach((item) => { + if (req.session.cart[item].productSubscription) { + req.session.cartSubscription = req.session.cart[item].productSubscription; + } else { + req.session.cartSubscription = null; } - - Object.keys(req.session.cart).forEach((item) => { - if(req.session.cart[item].productSubscription){ - req.session.cartSubscription = req.session.cart[item].productSubscription; - }else{ - req.session.cartSubscription = null; - } - }); + }); }; const emptyCart = async (req, res, type, customMessage) => { - const db = req.app.db; - - // Remove from session - delete req.session.cart; - delete req.session.shippingAmount; - delete req.session.orderId; - delete req.session.cartSubscription; - delete req.session.discountCode; - - // Remove cart from DB - await db.cart.deleteOne({ sessionId: req.session.id }); - - // update total cart - await updateTotalCart(req, res); - - // Update checking cart for subscription - updateSubscriptionCheck(req, res); - - // Set returned message - let message = 'Cart successfully emptied'; - if(customMessage){ - message = customMessage; - } - - if(type === 'function'){ - return; - } - - // If POST, return JSON else redirect nome - if(type === 'json'){ - res.status(200).json({ message: message, totalCartItems: 0 }); - return; - } - - req.session.message = message; - req.session.messageType = 'success'; - res.redirect('/'); + const db = req.app.db; + + // Remove from session + delete req.session.cart; + delete req.session.shippingAmount; + delete req.session.orderId; + delete req.session.cartSubscription; + delete req.session.discountCode; + + // Remove cart from DB + await db.cart.deleteOne({ sessionId: req.session.id }); + + // update total cart + await updateTotalCart(req, res); + + // Update checking cart for subscription + updateSubscriptionCheck(req, res); + + // Set returned message + let message = "Cart successfully emptied"; + if (customMessage) { + message = customMessage; + } + + if (type === "function") { + return; + } + + // If POST, return JSON else redirect nome + if (type === "json") { + res.status(200).json({ message: message, totalCartItems: 0 }); + return; + } + + req.session.message = message; + req.session.messageType = "success"; + res.redirect("/"); }; module.exports = { - updateTotalCart, - updateSubscriptionCheck, - emptyCart + updateTotalCart, + updateSubscriptionCheck, + emptyCart, }; diff --git a/lib/common.js b/lib/common.js index 9b138ecc..2f8c6194 100755 --- a/lib/common.js +++ b/lib/common.js @@ -1,38 +1,36 @@ -const colors = require('colors'); -const cheerio = require('cheerio'); -const axios = require('axios'); -const fs = require('fs'); -const path = require('path'); -const glob = require('glob'); -const async = require('async'); -const nodemailer = require('nodemailer'); -const sanitizeHtml = require('sanitize-html'); -const stripHtml = require('string-strip-html'); -const mkdirp = require('mkdirp'); -const ObjectId = require('mongodb').ObjectID; -const countryList = require('countries-list'); -const { - getConfig -} = require('./config'); +const colors = require("colors"); +const cheerio = require("cheerio"); +const axios = require("axios"); +const fs = require("fs"); +const path = require("path"); +const glob = require("glob"); +const async = require("async"); +const nodemailer = require("nodemailer"); +const sanitizeHtml = require("sanitize-html"); +const stripHtml = require("string-strip-html"); +const mkdirp = require("mkdirp"); +const ObjectId = require("mongodb").ObjectID; +const countryList = require("countries-list"); +const { getConfig } = require("./config"); // Parse country list once const countryArray = []; const countryCodes = {}; Object.keys(countryList.countries).forEach((country) => { - const countryName = countryList.countries[country].name; - countryArray.push(countryName); - countryCodes[countryName] = { - code: country - }; + const countryName = countryList.countries[country].name; + countryArray.push(countryName); + countryCodes[countryName] = { + code: country, + }; }); // Allowed mime types for product images const allowedMimeType = [ - 'image/jpeg', - 'image/png', - 'image/gif', - 'image/bmp', - 'image/webp' + "image/jpeg", + "image/png", + "image/gif", + "image/bmp", + "image/webp", ]; const fileSizeLimit = 10485760; @@ -41,293 +39,313 @@ const fileSizeLimit = 10485760; // Removes HTML from string const sanitize = (string) => { - return stripHtml(string); + return stripHtml(string); }; // Ensures HTML is safe const cleanHtml = (string) => { - return sanitizeHtml(string); + return sanitizeHtml(string); }; const mongoSanitize = (param) => { - if(param instanceof Object){ - for(const key in param){ - if(/^\$/.test(key)){ - delete param[key]; - } - } + if (param instanceof Object) { + for (const key in param) { + if (/^\$/.test(key)) { + delete param[key]; + } } - return param; + } + return param; }; const safeParseInt = (param) => { - if(param){ - try{ - return parseInt(param); - }catch(ex){ - return param; - } - }else{ - return param; + if (param) { + try { + return parseInt(param); + } catch (error) { + return param; } + } else { + return param; + } }; const checkboxBool = (param) => { - if(param && param === 'on'){ - return true; - } - if(param && param === 'true'){ - return true; - } - return false; + if (param && param === "on") { + return true; + } + if (param && param === "true") { + return true; + } + return false; }; const convertBool = (value) => { - if(value === 'true' || value === true){ - return true; - } - return false; + if (value === "true" || value === true) { + return true; + } + return false; }; // adds products to sitemap.xml const addSitemapProducts = (req, res, cb) => { - const db = req.app.db; + const db = req.app.db; - const config = getConfig(); - const hostname = config.baseUrl; + const config = getConfig(); + const hostname = config.baseUrl; - db.products.find({ productPublished: true }).toArray((err, products) => { - const posts = []; - if(err){ - cb(null, posts); + db.products.find({ productPublished: true }).toArray((err, products) => { + const posts = []; + if (err) { + cb(null, posts); + } + async.eachSeries( + products, + (item, callback) => { + const post = {}; + let url = item._id; + if (item.productPermalink) { + url = item.productPermalink; } - async.eachSeries(products, (item, callback) => { - const post = {}; - let url = item._id; - if(item.productPermalink){ - url = item.productPermalink; - } - post.url = `${hostname}/product/${url}`; - post.changefreq = 'weekly'; - post.priority = 0.7; - posts.push(post); - callback(null, posts); - }, () => { - cb(null, posts); - }); - }); + post.url = `${hostname}/product/${url}`; + post.changefreq = "weekly"; + post.priority = 0.7; + posts.push(post); + callback(null, posts); + }, + () => { + cb(null, posts); + } + ); + }); }; const clearSessionValue = (session, sessionVar) => { - let temp; - if(session){ - temp = session[sessionVar]; - session[sessionVar] = null; - } - return temp; + let temp; + if (session) { + temp = session[sessionVar]; + session[sessionVar] = null; + } + return temp; }; const checkDirectorySync = (directory) => { - try{ - fs.statSync(directory); - }catch(e){ - try{ - fs.mkdirSync(directory); - }catch(err){ - mkdirp.sync(directory);// error : directory & sub directories to be newly created - } + try { + fs.statSync(directory); + } catch (error) { + try { + fs.mkdirSync(directory); + } catch (error) { + mkdirp.sync(directory); // error : directory & sub directories to be newly created } + } }; const getThemes = () => { - return fs.readdirSync(path.join(__dirname, '../', 'views', 'themes')).filter(file => fs.statSync(path.join(path.join(__dirname, '../', 'views', 'themes'), file)).isDirectory()); + return fs + .readdirSync(path.join(__dirname, "../", "views", "themes")) + .filter((file) => + fs + .statSync( + path.join(path.join(__dirname, "../", "views", "themes"), file) + ) + .isDirectory() + ); }; const getImages = async (id, req, res, callback) => { - const db = req.app.db; - - const product = await db.products.findOne({ _id: getId(id) }); - if(!product){ - return []; + const db = req.app.db; + + const product = await db.products.findOne({ _id: getId(id) }); + if (!product) { + return []; + } + + // loop files in /public/uploads/ + const files = await glob.sync(`public/uploads/${product._id.toString()}/**`, { + nosort: true, + }); + + // sort array + files.sort(); + + // declare the array of objects + const fileList = []; + + // loop these files + for (let i = 0; i < files.length; i++) { + // only want files + if (fs.lstatSync(files[i]).isDirectory() === false) { + // declare the file object and set its values + const file = { + id: i, + path: files[i].substring(6), + }; + if (product.productImage === files[i].substring(6)) { + file.productImage = true; + } + // push the file object into the array + fileList.push(file); } - - // loop files in /public/uploads/ - const files = await glob.sync(`public/uploads/${product._id.toString()}/**`, { nosort: true }); - - // sort array - files.sort(); - - // declare the array of objects - const fileList = []; - - // loop these files - for(let i = 0; i < files.length; i++){ - // only want files - if(fs.lstatSync(files[i]).isDirectory() === false){ - // declare the file object and set its values - const file = { - id: i, - path: files[i].substring(6) - }; - if(product.productImage === files[i].substring(6)){ - file.productImage = true; - } - // push the file object into the array - fileList.push(file); - } + } + + // Check for URL images and add + if (product.productImages) { + for (let i = 0; i < product.productImages.length; i++) { + const file = { + id: fileList.length + 1, + path: product.productImages[i], + }; + if (product.productImage === product.productImages[i]) { + file.productImage = true; + } + fileList.push(file); } + } - // Check for URL images and add - if(product.productImages){ - for(let i = 0; i < product.productImages.length; i++){ - const file = { - id: fileList.length + 1, - path: product.productImages[i] - }; - if(product.productImage === product.productImages[i]){ - file.productImage = true; - } - fileList.push(file); - } - } - - return fileList; + return fileList; }; const getEmailTemplate = (result) => { - const config = getConfig(); - - const template = fs.readFileSync(path.join(__dirname, '../public/email_template.html'), 'utf8'); - - $ = cheerio.load(template); - $('#brand').text(config.cartTitle); - $('#paymentResult').text(result.message); - if(result.paymentApproved === true){ - $('#paymentResult').addClass('text-success'); - }else{ - $('#paymentResult').addClass('text-danger'); - } - $('#paymentMessage').text('Thanks for shopping with us. We hope you will shop with us again soon.'); - $('#paymentDetails').html(result.paymentDetails); - - return $.html(); + const config = getConfig(); + + const template = fs.readFileSync( + path.join(__dirname, "../public/email_template.html"), + "utf8" + ); + + $ = cheerio.load(template); + $("#brand").text(config.cartTitle); + $("#paymentResult").text(result.message); + if (result.paymentApproved === true) { + $("#paymentResult").addClass("text-success"); + } else { + $("#paymentResult").addClass("text-danger"); + } + $("#paymentMessage").text( + "Thanks for shopping with us. We hope you will shop with us again soon." + ); + $("#paymentDetails").html(result.paymentDetails); + + return $.html(); }; const sendEmail = (to, subject, body) => { - const config = getConfig(); - - const emailSettings = { - host: config.emailHost, - port: config.emailPort, - secure: config.emailSecure, - auth: { - user: config.emailUser, - pass: config.emailPassword - } - }; - - // outlook needs this setting - if(config.emailHost === 'smtp-mail.outlook.com'){ - emailSettings.tls = { ciphers: 'SSLv3' }; + const config = getConfig(); + + const emailSettings = { + host: config.emailHost, + port: config.emailPort, + secure: config.emailSecure, + auth: { + user: config.emailUser, + pass: config.emailPassword, + }, + }; + + // outlook needs this setting + if (config.emailHost === "smtp-mail.outlook.com") { + emailSettings.tls = { ciphers: "SSLv3" }; + } + + const transporter = nodemailer.createTransport(emailSettings); + + const mailOptions = { + from: config.emailAddress, // sender address + to: to, // list of receivers + subject: subject, // Subject line + html: body, // html body + }; + + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + return console.error(colors.red(error)); } - - const transporter = nodemailer.createTransport(emailSettings); - - const mailOptions = { - from: config.emailAddress, // sender address - to: to, // list of receivers - subject: subject, // Subject line - html: body// html body - }; - - transporter.sendMail(mailOptions, (error, info) => { - if(error){ - return console.error(colors.red(error)); - } - return true; - }); + return true; + }); }; // gets the correct type of index ID const getId = (id) => { - if(id){ - if(id.length !== 24){ - return id; - } + if (id) { + if (id.length !== 24) { + return id; } - return ObjectId(id); + } + return ObjectId(id); }; const newId = () => { - return new ObjectId(); + return new ObjectId(); }; const hooker = (order) => { - const config = getConfig(); + const config = getConfig(); - return axios.post(config.orderHook, order, { responseType: 'application/json' }) + return axios + .post(config.orderHook, order, { responseType: "application/json" }) .then((response) => { - if(response.status === 200){ - console.info('Successfully called order hook'); - } + if (response.status === 200) { + console.info("Successfully called order hook"); + } }) .catch((err) => { - console.log('Error calling hook:', err); + console.log("Error calling hook:", err); }); }; const getCountryList = () => { - return countryArray; + return countryArray; }; const getCountryNameToCode = (name) => { - return countryCodes[name]; + return countryCodes[name]; }; const cleanAmount = (amount) => { - if(amount){ - return parseInt(amount.toString().replace('.', '')); - } - return amount; + if (amount) { + return parseInt(amount.toString().replace(".", "")); + } + return amount; }; const clearCustomer = (req) => { - // Clear our session - req.session.customerCompany = null; - req.session.customerPresent = null; - req.session.customerEmail = null; - req.session.customerFirstname = null; - req.session.customerLastname = null; - req.session.customerAddress1 = null; - req.session.customerAddress2 = null; - req.session.customerCountry = null; - req.session.customerState = null; - req.session.customerPostcode = null; - req.session.customerPhone = null; - req.session.orderComment = null; + // Clear our session + req.session.customerCompany = null; + req.session.customerPresent = null; + req.session.customerEmail = null; + req.session.customerFirstname = null; + req.session.customerLastname = null; + req.session.customerAddress1 = null; + req.session.customerAddress2 = null; + req.session.customerCountry = null; + req.session.customerState = null; + req.session.customerPostcode = null; + req.session.customerPhone = null; + req.session.orderComment = null; }; module.exports = { - allowedMimeType, - fileSizeLimit, - sanitize, - cleanHtml, - mongoSanitize, - safeParseInt, - checkboxBool, - convertBool, - addSitemapProducts, - clearSessionValue, - checkDirectorySync, - getThemes, - getImages, - getEmailTemplate, - sendEmail, - getId, - newId, - hooker, - getCountryList, - cleanAmount, - clearCustomer, - getCountryNameToCode + allowedMimeType, + fileSizeLimit, + sanitize, + cleanHtml, + mongoSanitize, + safeParseInt, + checkboxBool, + convertBool, + addSitemapProducts, + clearSessionValue, + checkDirectorySync, + getThemes, + getImages, + getEmailTemplate, + sendEmail, + getId, + newId, + hooker, + getCountryList, + cleanAmount, + clearCustomer, + getCountryNameToCode, }; diff --git a/lib/schemas/editProduct.json b/lib/schemas/editProduct.json index f2d212b6..60612353 100644 --- a/lib/schemas/editProduct.json +++ b/lib/schemas/editProduct.json @@ -1,63 +1,61 @@ { - "$id": "editProduct", - "type": "object", + "$id": "editProduct", + "type": "object", + "properties": { + "productId": { + "type": "string" + }, + "productPermalink": { + "type": "string", + "isNotEmpty": true, + "minLength": 2 + }, + "productTitle": { + "type": "string", + "isNotEmpty": true, + "minLength": 5 + }, + "productPrice": { + "type": "string", + "format": "amount" + }, + "productDescription": { + "type": "string", + "isNotEmpty": true, + "minLength": 25 + }, + "productGtin": { + "type": "string", + "format": "alphanumeric", + "maxLength": 16 + }, + "productBrand": { + "type": "string", + "maxLength": 50 + }, + "productPublished": { + "type": "boolean" + }, + "productTags": { + "type": "string" + }, + "productComment": { + "type": "boolean" + }, + "productStock": { + "type": ["number", "null"] + }, + "productStockDisable": { + "type": "boolean" + } + }, + "errorMessage": { + "isNotEmpty": "This is my custom error message", "properties": { - "productId": { - "type": "string" - }, - "productPermalink": { - "type": "string", - "isNotEmpty": true, - "minLength": 2 - }, - "productTitle": { - "type": "string", - "isNotEmpty": true, - "minLength": 5 - }, - "productPrice": { - "type": "string", - "format": "amount" - }, - "productDescription": { - "type": "string", - "isNotEmpty": true, - "minLength": 25 - }, - "productGtin": { - "type": "string", - "format": "alphanumeric", - "maxLength": 16 - }, - "productBrand": { - "type": "string", - "maxLength": 50 - }, - "productPublished": { - "type": "boolean" - }, - "productTags": { - "type": "string" - }, - "productComment": { - "type": "boolean" - }, - "productStock": { - "type": ["number", "null"] - }, - "productStockDisable": { - "type": "boolean" - } - }, - "errorMessage": { - "isNotEmpty": "This is my custom error message", - "properties": { - "productPrice": "Should be a full 2 decimal value. Eg: 10.99", - "productPublished": "Should be either true or false", - "productComment": "Should be either true or false" - } - }, - "required": [ - "productId" - ] -} \ No newline at end of file + "productPrice": "Should be a full 2 decimal value. Eg: 10.99", + "productPublished": "Should be either true or false", + "productComment": "Should be either true or false" + } + }, + "required": ["productId"] +} diff --git a/lib/schemas/editUser.json b/lib/schemas/editUser.json index 0f4bfdfd..de5b046c 100644 --- a/lib/schemas/editUser.json +++ b/lib/schemas/editUser.json @@ -1,19 +1,20 @@ { - "$id": "editUser", - "type": "object", - "properties": { - "usersName": { - "type": "string" - }, - "userEmail": { - "type": "string", - "format": "emailAddress" - }, - "userPassword": { - "type": "string" - }, - "isAdmin": { - "type": "boolean" - } + "$id": "editUser", + "type": "object", + "properties": { + "usersName": { + "type": "string" + }, + "userEmail": { + "type": "string", + "format": "emailAddress" + }, + "userPassword": { + "type": "string" + }, + "isAdmin": { + "type": "boolean" } -} \ No newline at end of file + }, + "required": ["usersName", "userEmail", "userPassword","isAdmin"] +} diff --git a/lib/schemas/editVariant.json b/lib/schemas/editVariant.json index f2f2afe9..df72d258 100644 --- a/lib/schemas/editVariant.json +++ b/lib/schemas/editVariant.json @@ -1,39 +1,33 @@ { - "$id": "editVariant", - "type": "object", - "properties": { - "product": { - "type": "string", - "format": "objectid" - }, - "variant": { - "type": "string", - "format": "objectid" - }, - "title": { - "type": "string", - "isNotEmpty": true, - "minLength": 2 - }, - "price": { - "type": "string", - "format": "amount" - }, - "stock": { - "type": ["number", "null"] - } + "$id": "editVariant", + "type": "object", + "properties": { + "product": { + "type": "string", + "format": "objectid" + }, + "variant": { + "type": "string", + "format": "objectid" }, - "errorMessage": { - "isNotEmpty": "This is my custom error message", - "properties": { - "price": "Should be a full 2 decimal value. Eg: 10.99" - } + "title": { + "type": "string", + "isNotEmpty": true, + "minLength": 2 }, - "required": [ - "variant", - "product", - "title", - "price", - "stock" - ] -} \ No newline at end of file + "price": { + "type": "string", + "format": "amount" + }, + "stock": { + "type": ["number", "null"] + } + }, + "errorMessage": { + "isNotEmpty": "This is my custom error message", + "properties": { + "price": "Should be a full 2 decimal value. Eg: 10.99" + } + }, + "required": ["variant", "product", "title", "price", "stock"] +} diff --git a/lib/schemas/newCustomer.json b/lib/schemas/newCustomer.json index 2ac73380..1e03ff8c 100644 --- a/lib/schemas/newCustomer.json +++ b/lib/schemas/newCustomer.json @@ -1,56 +1,56 @@ { - "$id": "newCustomer", - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "emailAddress" - }, - "firstName": { - "type": "string", - "isNotEmpty": true - }, - "lastName": { - "type": "string", - "isNotEmpty": true - }, - "address1": { - "type": "string", - "isNotEmpty": true - }, - "address2": { - "type": "string" - }, - "country": { - "type": "string", - "isNotEmpty": true - }, - "state": { - "type": "string", - "isNotEmpty": true - }, - "postcode": { - "type": "string", - "isNotEmpty": true - }, - "phone": { - "type": "string", - "isNotEmpty": true - }, - "password": { - "type": "string", - "isNotEmpty": true - } - }, - "required": [ - "email", - "firstName", - "lastName", - "address1", - "country", - "state", - "postcode", - "phone", - "password" - ] -} \ No newline at end of file + "$id": "newCustomer", + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "emailAddress" + }, + "firstName": { + "type": "string", + "isNotEmpty": true + }, + "lastName": { + "type": "string", + "isNotEmpty": true + }, + "address1": { + "type": "string", + "isNotEmpty": true + }, + "address2": { + "type": "string" + }, + "country": { + "type": "string", + "isNotEmpty": true + }, + "state": { + "type": "string", + "isNotEmpty": true + }, + "postcode": { + "type": "string", + "isNotEmpty": true + }, + "phone": { + "type": "string", + "isNotEmpty": true + }, + "password": { + "type": "string", + "isNotEmpty": true + } + }, + "required": [ + "email", + "firstName", + "lastName", + "address1", + "country", + "state", + "postcode", + "phone", + "password" + ] +} diff --git a/lib/schemas/newDiscount.json b/lib/schemas/newDiscount.json index 0f023b0f..f6ceacb0 100644 --- a/lib/schemas/newDiscount.json +++ b/lib/schemas/newDiscount.json @@ -1,34 +1,25 @@ { - "$id": "newDiscount", - "type": "object", - "properties": { - "code": { - "type": "string" - }, - "type": { - "type": "string", - "enum": [ - "amount", - "percent" - ] - }, - "value": { - "type": "number" - }, - "start": { - "type": "object", - "format" : "datetime" - }, - "end": { - "type": "object", - "format" : "datetime" - } + "$id": "newDiscount", + "type": "object", + "properties": { + "code": { + "type": "string" }, - "required": [ - "code", - "type", - "value", - "start", - "end" - ] -} \ No newline at end of file + "type": { + "type": "string", + "enum": ["amount", "percent"] + }, + "value": { + "type": "number" + }, + "start": { + "type": "object", + "format": "datetime" + }, + "end": { + "type": "object", + "format": "datetime" + } + }, + "required": ["code", "type", "value", "start", "end"] +} diff --git a/lib/schemas/newProduct.json b/lib/schemas/newProduct.json index 3871554b..c3859838 100644 --- a/lib/schemas/newProduct.json +++ b/lib/schemas/newProduct.json @@ -1,63 +1,63 @@ { - "$id": "newProduct", - "type": "object", + "$id": "newProduct", + "type": "object", + "properties": { + "productPermalink": { + "type": "string", + "isNotEmpty": true, + "minLength": 2 + }, + "productTitle": { + "type": "string", + "isNotEmpty": true, + "minLength": 5 + }, + "productPrice": { + "type": "string", + "format": "amount" + }, + "productDescription": { + "type": "string", + "isNotEmpty": true, + "minLength": 25 + }, + "productGtin": { + "type": ["string", "null"], + "format": "alphanumeric", + "maxLength": 16 + }, + "productBrand": { + "type": "string", + "maxLength": 50 + }, + "productPublished": { + "type": "boolean" + }, + "productTags": { + "type": "string" + }, + "productComment": { + "type": "boolean" + }, + "productStock": { + "type": ["number", "null"] + }, + "productStockDisable": { + "type": "boolean" + } + }, + "errorMessage": { "properties": { - "productPermalink": { - "type": "string", - "isNotEmpty": true, - "minLength": 2 - }, - "productTitle": { - "type": "string", - "isNotEmpty": true, - "minLength": 5 - }, - "productPrice": { - "type": "string", - "format": "amount" - }, - "productDescription": { - "type": "string", - "isNotEmpty": true, - "minLength": 25 - }, - "productGtin": { - "type": ["string", "null"], - "format": "alphanumeric", - "maxLength": 16 - }, - "productBrand": { - "type": "string", - "maxLength": 50 - }, - "productPublished": { - "type": "boolean" - }, - "productTags": { - "type": "string" - }, - "productComment": { - "type": "boolean" - }, - "productStock": { - "type": ["number", "null"] - }, - "productStockDisable": { - "type": "boolean" - } - }, - "errorMessage": { - "properties": { - "productPrice": "Should be a full 2 decimal value. Eg: 10.99", - "productPublished": "Should be either true or false", - "productComment": "Should be either true or false" - } - }, - "required": [ - "productPermalink", - "productTitle", - "productPrice", - "productDescription", - "productPublished" - ] -} \ No newline at end of file + "productPrice": "Should be a full 2 decimal value. Eg: 10.99", + "productPublished": "Should be either true or false", + "productComment": "Should be either true or false" + } + }, + "required": [ + "productPermalink", + "productTitle", + "productPrice", + "productDescription", + "productPublished" + ] +} diff --git a/lib/schemas/newUser.json b/lib/schemas/newUser.json index 799d2fe1..a18c5aa5 100644 --- a/lib/schemas/newUser.json +++ b/lib/schemas/newUser.json @@ -1,25 +1,20 @@ { - "$id": "newUser", - "type": "object", - "properties": { - "usersName": { - "type": "string" - }, - "userEmail": { - "type": "string", - "format": "emailAddress" - }, - "userPassword": { - "type": "string" - }, - "isAdmin": { - "type": "boolean" - } + "$id": "newUser", + "type": "object", + "properties": { + "usersName": { + "type": "string" }, - "required": [ - "usersName", - "userEmail", - "userPassword", - "isAdmin" - ] -} \ No newline at end of file + "userEmail": { + "type": "string", + "format": "emailAddress" + }, + "userPassword": { + "type": "string" + }, + "isAdmin": { + "type": "boolean" + } + }, + "required": ["usersName", "userEmail", "userPassword", "isAdmin"] +} diff --git a/lib/schemas/newVariant.json b/lib/schemas/newVariant.json index 303aa306..4a6c5bdc 100644 --- a/lib/schemas/newVariant.json +++ b/lib/schemas/newVariant.json @@ -1,34 +1,29 @@ { - "$id": "newVariant", - "type": "object", - "properties": { - "product": { - "type": "string", - "format": "objectid" - }, - "title": { - "type": "string", - "isNotEmpty": true, - "minLength": 2 - }, - "price": { - "type": "string", - "format": "amount" - }, - "stock": { - "type": ["number", "null"] - } + "$id": "newVariant", + "type": "object", + "properties": { + "product": { + "type": "string", + "format": "objectid" + }, + "title": { + "type": "string", + "isNotEmpty": true, + "minLength": 2 }, - "errorMessage": { - "isNotEmpty": "This is my custom error message", - "properties": { - "price": "Should be a full 2 decimal value. Eg: 10.99" - } + "price": { + "type": "string", + "format": "amount" }, - "required": [ - "product", - "title", - "price", - "stock" - ] -} \ No newline at end of file + "stock": { + "type": ["number", "null"] + } + }, + "errorMessage": { + "isNotEmpty": "This is my custom error message", + "properties": { + "price": "Should be a full 2 decimal value. Eg: 10.99" + } + }, + "required": ["product", "title", "price", "stock"] +} diff --git a/lib/schemas/saveCustomer.json b/lib/schemas/saveCustomer.json index 55b41c66..ce857a73 100644 --- a/lib/schemas/saveCustomer.json +++ b/lib/schemas/saveCustomer.json @@ -1,51 +1,51 @@ { - "$id": "saveCustomer", - "type": "object", - "properties": { - "email": { - "type": "string", - "format": "emailAddress" - }, - "firstName": { - "type": "string", - "isNotEmpty": true - }, - "lastName": { - "type": "string", - "isNotEmpty": true - }, - "address1": { - "type": "string", - "isNotEmpty": true - }, - "address2": { - "type": "string" - }, - "country": { - "type": "string", - "isNotEmpty": true - }, - "state": { - "type": "string", - "isNotEmpty": true - }, - "postcode": { - "type": "string", - "isNotEmpty": true - }, - "phone": { - "type": "string", - "isNotEmpty": true - } - }, - "required": [ - "email", - "firstName", - "lastName", - "address1", - "country", - "state", - "postcode", - "phone" - ] -} \ No newline at end of file + "$id": "saveCustomer", + "type": "object", + "properties": { + "email": { + "type": "string", + "format": "emailAddress" + }, + "firstName": { + "type": "string", + "isNotEmpty": true + }, + "lastName": { + "type": "string", + "isNotEmpty": true + }, + "address1": { + "type": "string", + "isNotEmpty": true + }, + "address2": { + "type": "string" + }, + "country": { + "type": "string", + "isNotEmpty": true + }, + "state": { + "type": "string", + "isNotEmpty": true + }, + "postcode": { + "type": "string", + "isNotEmpty": true + }, + "phone": { + "type": "string", + "isNotEmpty": true + } + }, + "required": [ + "email", + "firstName", + "lastName", + "address1", + "country", + "state", + "postcode", + "phone" + ] +} From f680fe73c0b64eb03c385178a041e785634012cb Mon Sep 17 00:00:00 2001 From: shadmaankhan Date: Tue, 6 Jun 2023 12:54:08 +0530 Subject: [PATCH 2/3] Some changes in routes --- lib/config.js | 337 ++++++++++++++++++++++++++-------------------- lib/googledata.js | 4 +- routes/admin.js | 4 +- 3 files changed, 194 insertions(+), 151 deletions(-) diff --git a/lib/config.js b/lib/config.js index d80e9b1e..6864e233 100644 --- a/lib/config.js +++ b/lib/config.js @@ -1,174 +1,217 @@ -const uglifycss = require('uglifycss'); -const escape = require('html-entities').AllHtmlEntities; -const fs = require('fs'); -const path = require('path'); -const _ = require('lodash'); +const uglifycss = require("uglifycss"); +const escape = require("html-entities").AllHtmlEntities; +const fs = require("fs"); +const path = require("path"); +const _ = require("lodash"); const getConfig = () => { - let config = JSON.parse(fs.readFileSync(path.join(__dirname, '../config', 'settings.json'), 'utf8')); - const localConfigFilePath = path.join(__dirname, '../config', 'settings-local.json'); - - // Check for local config file and merge with base settings - if(fs.existsSync(localConfigFilePath)){ - const localConfigFile = JSON.parse(fs.readFileSync(localConfigFilePath, 'utf8')); - config = Object.assign(config, localConfigFile); + let config = JSON.parse( + fs.readFileSync(path.join(__dirname, "../config", "settings.json"), "utf8") + ); + const localConfigFilePath = path.join( + __dirname, + "../config", + "settings-local.json" + ); + + // Check for local config file and merge with base settings + if (fs.existsSync(localConfigFilePath)) { + const localConfigFile = JSON.parse( + fs.readFileSync(localConfigFilePath, "utf8") + ); + config = Object.assign(config, localConfigFile); + } + + // Override from env.yaml environment file + Object.keys(config).forEach((configKey) => { + if (process.env[configKey]) { + config[configKey] = process.env[configKey]; } - - // Override from env.yaml environment file - Object.keys(config).forEach((configKey) => { - if(process.env[configKey]){ - config[configKey] = process.env[configKey]; - } + }); + + config.customCss = + typeof config.customCss !== "undefined" + ? escape.decode(config.customCss) + : null; + config.footerHtml = + typeof config.footerHtml !== "undefined" + ? escape.decode(config.footerHtml) + : null; + config.googleAnalytics = + typeof config.googleAnalytics !== "undefined" + ? escape.decode(config.googleAnalytics) + : null; + + // setup theme + config.themeViews = ""; + if (typeof config.theme === "undefined" || config.theme === "") { + config.theme = "Cloth"; // Default to Cloth theme + } + + config.themeViews = `../views/themes/${config.theme}/`; + + // set the environment for files + config.env = ".min"; + if ( + process.env.NODE_ENV === "development" || + process.env.NODE_ENV === undefined + ) { + config.env = ""; + } + + // load modules + try { + config.modules.loaded = {}; + Object.keys(config.modules.enabled).forEach((mod) => { + config.modules.loaded[ + mod + ] = require(`./modules/${config.modules.enabled[mod]}`); }); + } catch (ex) { + console.log("Could not load modules, check your config.", ex); + process.exit(1); + } - config.customCss = typeof config.customCss !== 'undefined' ? escape.decode(config.customCss) : null; - config.footerHtml = typeof config.footerHtml !== 'undefined' ? escape.decode(config.footerHtml) : null; - config.googleAnalytics = typeof config.googleAnalytics !== 'undefined' ? escape.decode(config.googleAnalytics) : null; - - // setup theme - config.themeViews = ''; - if(typeof config.theme === 'undefined' || config.theme === ''){ - config.theme = 'Cloth'; // Default to Cloth theme - } - - config.themeViews = `../views/themes/${config.theme}/`; - - // set the environment for files - config.env = '.min'; - if(process.env.NODE_ENV === 'development' || process.env.NODE_ENV === undefined){ - config.env = ''; - } - - // load modules - try{ - config.modules.loaded = {}; - Object.keys(config.modules.enabled).forEach((mod) => { - config.modules.loaded[mod] = require(`./modules/${config.modules.enabled[mod]}`); - }); - }catch(ex){ - console.log('Could not load modules, check your config.', ex); - process.exit(1); - } - - return config; + return config; }; const getPaymentConfig = (gateway) => { - const siteConfig = getConfig(); - - // Read the Gateway config - const config = {}; - _.forEach(siteConfig.paymentGateway, (gateway) => { - const gateConfigFile = path.join(__dirname, '../config', 'payment', 'config', `${gateway}.json`); - if(fs.existsSync(gateConfigFile)){ - config[gateway] = JSON.parse(fs.readFileSync(gateConfigFile, 'utf8')); - } - - // Override from env.yaml environment file - Object.keys(config[gateway]).forEach((configKey) => { - if(process.env[gateway] && process.env[gateway][configKey]){ - config[gateway][configKey] = process.env[gateway][configKey]; - } - }); - }); - - // If Gateway supplied, return that Gateway config - if(gateway && config[gateway]){ - return config[gateway]; + const siteConfig = getConfig(); + + // Read the Gateway config + const config = {}; + _.forEach(siteConfig.paymentGateway, (gateway) => { + const gateConfigFile = path.join( + __dirname, + "../config", + "payment", + "config", + `${gateway}.json` + ); + if (fs.existsSync(gateConfigFile)) { + config[gateway] = JSON.parse(fs.readFileSync(gateConfigFile, "utf8")); } - return config; -}; - -const updateConfig = (fields) => { - const settingsFile = getConfig(); - - _.forEach(fields, (value, key) => { - settingsFile[key] = value; - if(key === 'customCss_input'){ - settingsFile.customCss = escape.encode(uglifycss.processString(value)); - } - if(key === 'footerHtml_input'){ - const footerHtml = typeof value !== 'undefined' || value === '' ? escape.encode(value) : ''; - settingsFile.footerHtml = footerHtml; - } - if(key === 'googleAnalytics_input'){ - const googleAnalytics = typeof value !== 'undefined' ? escape.encode(value) : ''; - settingsFile.googleAnalytics = googleAnalytics; - } + // Override from env.yaml environment file + Object.keys(config[gateway]).forEach((configKey) => { + if (process.env[gateway] && process.env[gateway][configKey]) { + config[gateway][configKey] = process.env[gateway][configKey]; + } }); + }); - // delete any settings - delete settingsFile.customCss_input; - delete settingsFile.footerHtml_input; - delete settingsFile.googleAnalytics_input; + // If Gateway supplied, return that Gateway config + if (gateway && config[gateway]) { + return config[gateway]; + } - if(fields.emailSecure === 'on'){ - settingsFile.emailSecure = true; - }else{ - settingsFile.emailSecure = false; - } + return config; +}; - if(fields.emailPort){ - settingsFile.emailPort = parseInt(fields.emailPort); - } +const updateConfig = (fields) => { + const settingsFile = getConfig(); - if(fields.productsPerRow){ - settingsFile.productsPerRow = parseInt(fields.productsPerRow); + _.forEach(fields, (value, key) => { + settingsFile[key] = value; + if (key === "customCss_input") { + settingsFile.customCss = escape.encode(uglifycss.processString(value)); } - - if(fields.productsPerPage){ - settingsFile.productsPerPage = parseInt(fields.productsPerPage); + if (key === "footerHtml_input") { + const footerHtml = + typeof value !== "undefined" || value === "" + ? escape.encode(value) + : ""; + settingsFile.footerHtml = footerHtml; } - - // If we have a local settings file (not git tracked) we loop its settings and save - // and changes made to them. All other settings get updated to the base settings file. - const localSettingsFile = path.join(__dirname, '../config', 'settings-local.json'); - if(fs.existsSync(localSettingsFile)){ - const localSettings = JSON.parse(fs.readFileSync(localSettingsFile)); - _.forEach(localSettings, (value, key) => { - if(fields[key]){ - localSettings[key] = fields[key]; - - // Exists in local so remove from main settings file - delete settingsFile[key]; - } - }); - // Save our local settings - try{ - fs.writeFileSync(localSettingsFile, JSON.stringify(localSettings, null, 4)); - }catch(exception){ - console.log('Failed to save local settings file', exception); - } + if (key === "googleAnalytics_input") { + const googleAnalytics = + typeof value !== "undefined" ? escape.encode(value) : ""; + settingsFile.googleAnalytics = googleAnalytics; } - - // write base settings file - const baseSettingsFile = path.join(__dirname, '../config', 'settings.json'); - try{ - fs.writeFileSync(baseSettingsFile, JSON.stringify(settingsFile, null, 4)); - return true; - }catch(exception){ - return false; + }); + + // delete any settings + delete settingsFile.customCss_input; + delete settingsFile.footerHtml_input; + delete settingsFile.googleAnalytics_input; + + if (fields.emailSecure === "on") { + settingsFile.emailSecure = true; + } else { + settingsFile.emailSecure = false; + } + + if (fields.emailPort) { + settingsFile.emailPort = parseInt(fields.emailPort); + } + + if (fields.productsPerRow) { + settingsFile.productsPerRow = parseInt(fields.productsPerRow); + } + + if (fields.productsPerPage) { + settingsFile.productsPerPage = parseInt(fields.productsPerPage); + } + + // If we have a local settings file (not git tracked) we loop its settings and save + // and changes made to them. All other settings get updated to the base settings file. + const localSettingsFile = path.join( + __dirname, + "../config", + "settings-local.json" + ); + if (fs.existsSync(localSettingsFile)) { + const localSettings = JSON.parse(fs.readFileSync(localSettingsFile)); + _.forEach(localSettings, (value, key) => { + if (fields[key]) { + localSettings[key] = fields[key]; + + // Exists in local so remove from main settings file + delete settingsFile[key]; + } + }); + // Save our local settings + try { + fs.writeFileSync( + localSettingsFile, + JSON.stringify(localSettings, null, 4) + ); + } catch (exception) { + console.log("Failed to save local settings file", exception); } + } + + // write base settings file + const baseSettingsFile = path.join(__dirname, "../config", "settings.json"); + try { + fs.writeFileSync(baseSettingsFile, JSON.stringify(settingsFile, null, 4)); + return true; + } catch (exception) { + return false; + } }; const updateConfigLocal = (field) => { - const localSettingsFile = path.join(__dirname, '../config', 'settings-local.json'); - try{ - let localSettings = {}; - if(fs.existsSync(localSettingsFile)){ - localSettings = JSON.parse(fs.readFileSync(localSettingsFile)); - } - Object.assign(localSettings, field); - fs.writeFileSync(localSettingsFile, JSON.stringify(localSettings, null, 4)); - }catch(exception){ - console.log('Failed to save local settings file', exception); + const localSettingsFile = path.join( + __dirname, + "../config", + "settings-local.json" + ); + try { + let localSettings = {}; + if (fs.existsSync(localSettingsFile)) { + localSettings = JSON.parse(fs.readFileSync(localSettingsFile)); } + Object.assign(localSettings, field); + fs.writeFileSync(localSettingsFile, JSON.stringify(localSettings, null, 4)); + } catch (exception) { + console.log("Failed to save local settings file", exception); + } }; module.exports = { - getConfig, - getPaymentConfig, - updateConfig, - updateConfigLocal + getConfig, + getPaymentConfig, + updateConfig, + updateConfigLocal, }; diff --git a/lib/googledata.js b/lib/googledata.js index 470427d4..c546740d 100755 --- a/lib/googledata.js +++ b/lib/googledata.js @@ -1,4 +1,4 @@ -const _ = require('lodash'); +const lodash = require('lodash'); const fs = require('fs'); const path = require('path'); const convert = require('xml-js'); @@ -37,7 +37,7 @@ const writeGoogleData = async (db) => { }; // Add products - _.forEach(products, async (product) => { + lodash.forEach(products, async (product) => { const item = { 'g:title': product.productTitle, 'g:id': product._id.toString(), diff --git a/routes/admin.js b/routes/admin.js index 0cfe9866..49a9db79 100644 --- a/routes/admin.js +++ b/routes/admin.js @@ -109,10 +109,10 @@ router.post('/admin/login_action', async (req, res) => { req.session.isAdmin = user.isAdmin; res.status(200).json({ message: 'Login successful' }); return; - } + } else { // password is not correct res.status(400).json({ message: 'Access denied. Check password and try again.' }); - }); + }}); }); // setup form is shown when there are no users setup in the DB From 108dbc54720e87f4028e5a3366cd41d3f2e99da4 Mon Sep 17 00:00:00 2001 From: shadmaankhan Date: Tue, 6 Jun 2023 13:14:22 +0530 Subject: [PATCH 3/3] =?UTF-8?q?making=20some=20changes=20in=20code=20?= =?UTF-8?q?=F0=9F=8D=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/javascripts/expressCart.min.js | 594 +++++++++++++++++++++++++- routes/index.js | 8 +- 2 files changed, 597 insertions(+), 5 deletions(-) diff --git a/public/javascripts/expressCart.min.js b/public/javascripts/expressCart.min.js index 23a703a5..dccab57c 100644 --- a/public/javascripts/expressCart.min.js +++ b/public/javascripts/expressCart.min.js @@ -1 +1,593 @@ -function checkMaxQuantity(t,a){if($("#maxQuantity").length){if(46===t.keyCode||8===t.keyCode)return;if(parseInt($(t.target).val())>parseInt($("#maxQuantity").val())){const e=a.val();t.preventDefault(),a.val(e.slice(0,-1)),showNotification(`Exceeds maximum quantity: ${$("#maxQuantity").val()}`,"warning",!1)}}}function deleteFromCart(t){$.ajax({method:"POST",url:"/product/removefromcart",data:{cartId:t.attr("data-cartid")}}).done(function(t){updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function cartUpdate(t){$(t).val()>0?""!==$(t).val()&&updateCart(t):$(t).val(1)}function updateCart(t){$.ajax({method:"POST",url:"/product/updatecart",data:{cartId:t.attr("data-cartid"),productId:t.attr("data-id"),quantity:t.val()}}).done(function(t){updateCartDiv()}).fail(function(t){showNotification(t.responseJSON.message,"danger",!0)})}function updateCartDiv(){$.ajax({method:"GET",url:"/checkout/cartdata"}).done(function(t){var a=t.cart,e=t.session,n="",o=numeral(e.totalCartAmount).format("0.00"),i=numeral(e.totalCartShipping).format("0.00"),r=`${e.shippingMessage} :${t.currencySymbol}${i}`;0===e.totalCartShipping&&(r=`${e.shippingMessage}`);var c=numeral(e.totalCartDiscount).format("0.00"),s="";e.totalCartDiscount>0&&(s=`\n
\n Discount: ${t.currencySymbol}${c}\n
`),a?($("#cart-empty").empty(),Object.keys(a).forEach(function(e){var o=a[e],i=numeral(o.totalItemPrice).format("0.00"),r="";o.variantId&&(r+=`Option: ${o.variantTitle}`);var c=`${o.title} product image`;o.productImage&&(c=`${o.title} product image`),n+=`\n
\n
\n
\n
\n ${c}\n
\n
\n
\n
\n
${o.title}
\n ${r}\n
\n
\n
\n
\n \n
\n \n
\n \n
\n
\n
\n
\n \n
\n
\n ${t.currencySymbol}${i}\n
\n
\n
\n
\n
\n
`}),$(".cartBodyWrapper").html(n)):$(".cartBodyWrapper").html(""),$("#cart-count").text(e.totalCartItems);var d=`\n
\n
\n
\n ${r}\n
\n ${s}\n
\n Total:\n ${t.currencySymbol}${o}\n
\n
\n
`;a?($(".cartTotalsWrapper").html(d),$(".cart-buttons").removeClass("d-none")):($(".cartTotalsWrapper").html('\n
\n
.active").html(''),$(".menu-side>.active").addClass("menu-side-mobile"),0===$("#navbar ul li").length&&$("#navbar").hide(),$("#offcanvasClose").hide()),$("#userSetupForm").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/setup_action",data:{usersName:$("#usersName").val(),userEmail:$("#userEmail").val(),userPassword:$("#userPassword").val()}}).done(function(t){showNotification(t.message,"success",!1,"/admin/login")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}))}),$(document).on("click",".menu-btn",function(t){t.preventDefault(),$("body").addClass("pushy-open-right")}),$("table").each(function(){$(this).addClass("table table-hover")}),$("#productTags").length&&$("#productTags").tokenfield(),$(document).on("click",".dashboard_list",function(t){window.document.location=$(this).attr("href")}).hover(function(){$(this).toggleClass("hover")}),$(document).on("click",".btn-qty-minus",function(t){t.preventDefault();var a=$(t.target).parent().parent().find(".cart-product-quantity");$(a).val(parseInt(a.val())-1),cartUpdate(a)}),$(document).on("click",".btn-qty-add",function(t){t.preventDefault();var a=$(t.target).parent().parent().find(".cart-product-quantity");$(a).val(parseInt(a.val())+1),cartUpdate(a)}),$(document).on("click",".btn-delete-from-cart",function(t){deleteFromCart($(t.target))}),$("#pager").length){var t=$("#pageNum").val(),a=$("#itemsPerPage").val(),e=$("#totalItemCount").val(),n=$("#paginateUrl").val(),o=$("#searchTerm").val();""!==o&&(o+="/");var i="/"+n+"/"+o+"{{number}}",r=Math.ceil(e/a);parseInt(e)>parseInt(a)&&($("#pager").bootpag({total:r,page:t,maxVisible:5,href:i,wrapClass:"pagination",prevClass:"page-item previous",nextClass:"page-item next",activeClass:"page-item active"}),$("#pager a").each(function(){$(this).addClass("page-link")}))}if($("#customerLogout").on("click",function(t){$.ajax({method:"POST",url:"/customer/logout",data:{}}).done(function(t){location.reload()})}),$("#customerForgotten").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/forgotten_action",data:{email:$("#email").val()}}).done(function(t){showNotification(t.message,"success")}).fail(function(t){t.message?showNotification(t.responseJSON.message,"danger"):showNotification(t.responseText,"danger")}))}),$(document).on("click","#createAccountCheckbox",function(t){$("#newCustomerPassword").prop("required",$("#createAccountCheckbox").prop("checked"))}),$("#checkoutInformation").validator().on("click",function(t){if(t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length){var a="/customer/save";$("#createAccountCheckbox").prop("checked")&&(a="/customer/create"),$.ajax({method:"POST",url:a,data:{email:$("#shipEmail").val(),company:$("#shipCompany").val(),firstName:$("#shipFirstname").val(),lastName:$("#shipLastname").val(),address1:$("#shipAddr1").val(),address2:$("#shipAddr2").val(),country:$("#shipCountry").val(),state:$("#shipState").val(),postcode:$("#shipPostcode").val(),phone:$("#shipPhoneNumber").val(),password:$("#newCustomerPassword").val(),orderComment:$("#orderComment").val()}}).done(function(){window.location="/checkout/shipping"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}}),$("#addDiscountCode").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/checkout/adddiscountcode",data:{discountCode:$("#discountCode").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#removeDiscountCode").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/checkout/removediscountcode",data:{}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#loginForm").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/admin/login_action",data:{email:$("#email").val(),password:$("#password").val()}}).done(function(t){window.location="/admin"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerloginForm").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/login_action",data:{loginEmail:$("#email").val(),loginPassword:$("#password").val()}}).done(function(t){window.location="/customer/account"}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerLogin").on("click",function(t){t.isDefaultPrevented()||(t.preventDefault(),$.ajax({method:"POST",url:"/customer/login_action",data:{loginEmail:$("#customerLoginEmail").val(),loginPassword:$("#customerLoginPassword").val()}}).done(function(t){var a=t.customer;$("#shipEmail").val(a.email),$("#shipFirstname").val(a.firstName),$("#shipLastname").val(a.lastName),$("#shipAddr1").val(a.address1),$("#shipAddr2").val(a.address2),$("#shipCountry").val(a.country),$("#shipState").val(a.state),$("#shipPostcode").val(a.postcode),$("#shipPhoneNumber").val(a.phone),location.reload()}).fail(function(t){showNotification(t.responseJSON.message,"danger")})),t.preventDefault()}),$("#customerSave").validator().on("click",function(t){t.preventDefault(),0===$("#customer-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/customer/update",data:{email:$("#shipEmail").val(),company:$("#shipCompany").val(),firstName:$("#shipFirstname").val(),lastName:$("#shipLastname").val(),address1:$("#shipAddr1").val(),address2:$("#shipAddr2").val(),country:$("#shipCountry").val(),state:$("#shipState").val(),postcode:$("#shipPostcode").val(),phone:$("#shipPhoneNumber").val(),password:$("#newCustomerPassword").val(),orderComment:$("#orderComment").val()}}).done(function(){showNotification("Customer saved","success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".image-next",function(t){var a=$(".thumbnail-image"),e=0,n=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(n=e+1===a.length||e+1<0?0:e+1),e++}),$("#product-title-image").attr("src",$(a).eq(n).attr("src"))}),$(document).on("click",".image-prev",function(t){var a=$(".thumbnail-image"),e=0,n=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(n=e-1===a.length||e-1<0?a.length-1:e-1),e++}),$("#product-title-image").attr("src",$(a).eq(n).attr("src"))}),$(document).on("change","#product_variant",function(t){var a=$(this).find(":selected").attr("data-price"),e=$("#currencySymbol").val();$("h4.product-price:first").html(e+a)}),$(document).on("click",".add-variant-to-cart",function(t){$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id"),productQuantity:"1",productVariant:$("#productVariant-"+$(this).attr("data-id")).val()}}).done(function(t){updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product-add-to-cart",function(t){parseInt($("#product_quantity").val())<1&&$("#product_quantity").val(1),$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productVariant:$("#product_variant").val(),productComment:$("#product_comment").val()}}).done(function(t){updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#product_quantity").on("keyup",function(t){checkMaxQuantity(t,$("#product_quantity"))}),$(".cart-product-quantity").on("keyup",function(t){checkMaxQuantity(t,$(".cart-product-quantity"))}),$(".cart-product-quantity").on("focusout",function(t){cartUpdate($(t.target))}),$(document).on("click",".pushy-link",function(t){$("body").removeClass("pushy-open-right")}),$(document).on("click",".add-to-cart",function(t){var a="/product/"+$(this).attr("data-id");$(this).attr("data-link")&&(a="/product/"+$(this).attr("data-link")),"true"===$(this).attr("data-has-variants")?window.location=a:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#add-review",function(t){$.ajax({method:"POST",url:"/customer/check",data:{}}).done(function(t){$("#reviewModal").modal("show")}).fail(function(){showNotification("You need to be logged in to create a review","danger",!1,"/customer/account")})}),$(document).on("click","#addReview",function(t){$.ajax({method:"POST",url:"/product/addreview",data:{product:$("#product").val(),title:$("#review-title").val(),description:$("#review-description").val(),rating:$("#review-rating").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){"You need to be logged in to create a review"===t.responseJSON.message&&showNotification(t.responseJSON.message,"danger",!1,"/customer/account"),showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#empty-cart",function(t){$("#confirmModal").modal("show"),$("#buttonConfirm").attr("data-func","emptyCart")}),$(document).on("click","#buttonConfirm",function(t){var a=$(t.target).attr("data-func");window[a](),$("#confirmModal").modal("hide")}),$(".qty-btn-minus").on("click",function(){var t=parseInt($("#product_quantity").val())-1;$("#product_quantity").val(t>0?t:1)}),$(".qty-btn-plus").on("click",function(){$("#product_quantity").val(parseInt($("#product_quantity").val())+1)}),$(".thumbnail-image").on("click",function(){$("#product-title-image").attr("src",$(this).attr("src"))}),$(document).on("click","#btn_search_reset",function(t){window.location.replace("/")}),$(document).on("click","#btn_search",function(t){t.preventDefault(),""===$("#frm_search").val().trim()?showNotification("Please enter a search value","danger"):window.location.href="/search/"+$("#frm_search").val()}),""!==$("#input_notify_message").val()){var c=$("#input_notify_message").val(),s=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(c,s||"danger",!1)}if($("#blockonomics_div").length>0){var d=$("#blockonomics_div").data("orderid")||"",l=$("#blockonomics_div").data("timestamp")||-1,u=$("#blockonomics_div").data("address")||"",m=new WebSocket("wss://www.blockonomics.co/payment/"+u+"?timestamp="+l);m.onopen=function(t){};setTimeout(function(){$("#blockonomics_waiting").html("Payment expired

Click here to try again.

If you already paid, your order will be processed automatically."),showNotification("Payment expired","danger"),m.close()},6e5);var p=$("#blockonomics_timeout"),f=new Date((new Date).getTime()+6e5),v=setInterval(function(){var t=(new Date).getTime(),a=f-t;if(a<0)clearInterval(v);else{var e=Math.floor(a%36e5/6e4),n=Math.floor(a%6e4/1e3);p.html(e+"m "+n+"s")}},1e3);m.onmessage=function(t){var a=JSON.parse(t.data);if(0===a.status||1===a.status||2===a.status){var e='
View Order';$("#blockonomics_waiting").html("Payment detected ("+a.value/1e8+" BTC)."+e),showNotification("Payment detected","success"),$("#cart-count").html("0"),m.close(),$.ajax({method:"POST",url:"/product/emptycart"}).done(function(){window.location.replace("/payment/"+d)})}}}}); \ No newline at end of file +function checkMaxQuantity(t, a) { + if ($("#maxQuantity").length) { + if (46 === t.keyCode || 8 === t.keyCode) return; + if (parseInt($(t.target).val()) > parseInt($("#maxQuantity").val())) { + const e = a.val(); + t.preventDefault(), + a.val(e.slice(0, -1)), + showNotification( + `Exceeds maximum quantity: ${$("#maxQuantity").val()}`, + "warning", + !1 + ); + } + } +} +function deleteFromCart(t) { + $.ajax({ + method: "POST", + url: "/product/removefromcart", + data: { cartId: t.attr("data-cartid") }, + }) + .done(function (t) { + updateCartDiv(), showNotification(t.message, "success"); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); +} +function cartUpdate(t) { + $(t).val() > 0 ? "" !== $(t).val() && updateCart(t) : $(t).val(1); +} +function updateCart(t) { + $.ajax({ + method: "POST", + url: "/product/updatecart", + data: { + cartId: t.attr("data-cartid"), + productId: t.attr("data-id"), + quantity: t.val(), + }, + }) + .done(function (t) { + updateCartDiv(); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger", !0); + }); +} +function updateCartDiv() { + $.ajax({ method: "GET", url: "/checkout/cartdata" }) + .done(function (t) { + var a = t.cart, + e = t.session, + n = "", + o = numeral(e.totalCartAmount).format("0.00"), + i = numeral(e.totalCartShipping).format("0.00"), + r = `${e.shippingMessage} :${t.currencySymbol}${i}`; + 0 === e.totalCartShipping && + (r = `${e.shippingMessage}`); + var c = numeral(e.totalCartDiscount).format("0.00"), + s = ""; + e.totalCartDiscount > 0 && + (s = `\n
\n Discount: ${t.currencySymbol}${c}\n
`), + a + ? ($("#cart-empty").empty(), + Object.keys(a).forEach(function (e) { + var o = a[e], + i = numeral(o.totalItemPrice).format("0.00"), + r = ""; + o.variantId && + (r += `Option: ${o.variantTitle}`); + var c = `${o.title} product image`; + o.productImage && + (c = `${o.title} product image`), + (n += `\n
\n
\n
\n
\n ${c}\n
\n
\n
\n
\n
${o.title}
\n ${r}\n
\n
\n
\n
\n \n
\n \n
\n \n
\n
\n
\n
\n \n
\n
\n ${t.currencySymbol}${i}\n
\n
\n
\n
\n
\n
`); + }), + $(".cartBodyWrapper").html(n)) + : $(".cartBodyWrapper").html(""), + $("#cart-count").text(e.totalCartItems); + var d = `\n
\n
\n
\n ${r}\n
\n ${s}\n
\n Total:\n ${t.currencySymbol}${o}\n
\n
\n
`; + a + ? ($(".cartTotalsWrapper").html(d), + $(".cart-buttons").removeClass("d-none")) + : ($(".cartTotalsWrapper").html( + '\n
\n
.active").html( + '' + ), + $(".menu-side>.active").addClass("menu-side-mobile"), + 0 === $("#navbar ul li").length && $("#navbar").hide(), + $("#offcanvasClose").hide()), + $("#userSetupForm") + .validator() + .on("submit", function (t) { + t.isDefaultPrevented() || + (t.preventDefault(), + $.ajax({ + method: "POST", + url: "/admin/setup_action", + data: { + usersName: $("#usersName").val(), + userEmail: $("#userEmail").val(), + userPassword: $("#userPassword").val(), + }, + }) + .done(function (t) { + showNotification(t.message, "success", !1, "/admin/login"); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + })); + }), + $(document).on("click", ".menu-btn", function (t) { + t.preventDefault(), $("body").addClass("pushy-open-right"); + }), + $("table").each(function () { + $(this).addClass("table table-hover"); + }), + $("#productTags").length && $("#productTags").tokenfield(), + $(document) + .on("click", ".dashboard_list", function (t) { + window.document.location = $(this).attr("href"); + }) + .hover(function () { + $(this).toggleClass("hover"); + }), + $(document).on("click", ".btn-qty-minus", function (t) { + t.preventDefault(); + var a = $(t.target).parent().parent().find(".cart-product-quantity"); + $(a).val(parseInt(a.val()) - 1), cartUpdate(a); + }), + $(document).on("click", ".btn-qty-add", function (t) { + t.preventDefault(); + var a = $(t.target).parent().parent().find(".cart-product-quantity"); + $(a).val(parseInt(a.val()) + 1), cartUpdate(a); + }), + $(document).on("click", ".btn-delete-from-cart", function (t) { + deleteFromCart($(t.target)); + }), + $("#pager").length) + ) { + var t = $("#pageNum").val(), + a = $("#itemsPerPage").val(), + e = $("#totalItemCount").val(), + n = $("#paginateUrl").val(), + o = $("#searchTerm").val(); + "" !== o && (o += "/"); + var i = "/" + n + "/" + o + "{{number}}", + r = Math.ceil(e / a); + parseInt(e) > parseInt(a) && + ($("#pager").bootpag({ + total: r, + page: t, + maxVisible: 5, + href: i, + wrapClass: "pagination", + prevClass: "page-item previous", + nextClass: "page-item next", + activeClass: "page-item active", + }), + $("#pager a").each(function () { + $(this).addClass("page-link"); + })); + } + if ( + ($("#customerLogout").on("click", function (t) { + $.ajax({ method: "POST", url: "/customer/logout", data: {} }).done( + function (t) { + location.reload(); + } + ); + }), + $("#customerForgotten") + .validator() + .on("submit", function (t) { + t.isDefaultPrevented() || + (t.preventDefault(), + $.ajax({ + method: "POST", + url: "/customer/forgotten_action", + data: { email: $("#email").val() }, + }) + .done(function (t) { + showNotification(t.message, "success"); + }) + .fail(function (t) { + t.message + ? showNotification(t.responseJSON.message, "danger") + : showNotification(t.responseText, "danger"); + })); + }), + $(document).on("click", "#createAccountCheckbox", function (t) { + $("#newCustomerPassword").prop( + "required", + $("#createAccountCheckbox").prop("checked") + ); + }), + $("#checkoutInformation") + .validator() + .on("click", function (t) { + if ( + (t.preventDefault(), + 0 === + $("#shipping-form").validator("validate").has(".has-error").length) + ) { + var a = "/customer/save"; + $("#createAccountCheckbox").prop("checked") && + (a = "/customer/create"), + $.ajax({ + method: "POST", + url: a, + data: { + email: $("#shipEmail").val(), + company: $("#shipCompany").val(), + firstName: $("#shipFirstname").val(), + lastName: $("#shipLastname").val(), + address1: $("#shipAddr1").val(), + address2: $("#shipAddr2").val(), + country: $("#shipCountry").val(), + state: $("#shipState").val(), + postcode: $("#shipPostcode").val(), + phone: $("#shipPhoneNumber").val(), + password: $("#newCustomerPassword").val(), + orderComment: $("#orderComment").val(), + }, + }) + .done(function () { + window.location = "/checkout/shipping"; + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); + } + }), + $("#addDiscountCode").on("click", function (t) { + t.preventDefault(), + $.ajax({ + method: "POST", + url: "/checkout/adddiscountcode", + data: { discountCode: $("#discountCode").val() }, + }) + .done(function (t) { + showNotification(t.message, "success", !0); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); + }), + $("#removeDiscountCode").on("click", function (t) { + t.preventDefault(), + $.ajax({ + method: "POST", + url: "/checkout/removediscountcode", + data: {}, + }) + .done(function (t) { + showNotification(t.message, "success", !0); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); + }), + $("#loginForm").on("click", function (t) { + t.isDefaultPrevented() || + (t.preventDefault(), + $.ajax({ + method: "POST", + url: "/admin/login_action", + data: { email: $("#email").val(), password: $("#password").val() }, + }) + .done(function (t) { + window.location = "/admin"; + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + })), + t.preventDefault(); + }), + $("#customerloginForm").on("click", function (t) { + t.isDefaultPrevented() || + (t.preventDefault(), + $.ajax({ + method: "POST", + url: "/customer/login_action", + data: { + loginEmail: $("#email").val(), + loginPassword: $("#password").val(), + }, + }) + .done(function (t) { + window.location = "/customer/account"; + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + })), + t.preventDefault(); + }), + $("#customerLogin").on("click", function (t) { + t.isDefaultPrevented() || + (t.preventDefault(), + $.ajax({ + method: "POST", + url: "/customer/login_action", + data: { + loginEmail: $("#customerLoginEmail").val(), + loginPassword: $("#customerLoginPassword").val(), + }, + }) + .done(function (t) { + var a = t.customer; + $("#shipEmail").val(a.email), + $("#shipFirstname").val(a.firstName), + $("#shipLastname").val(a.lastName), + $("#shipAddr1").val(a.address1), + $("#shipAddr2").val(a.address2), + $("#shipCountry").val(a.country), + $("#shipState").val(a.state), + $("#shipPostcode").val(a.postcode), + $("#shipPhoneNumber").val(a.phone), + location.reload(); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + })), + t.preventDefault(); + }), + $("#customerSave") + .validator() + .on("click", function (t) { + t.preventDefault(), + 0 === + $("#customer-form").validator("validate").has(".has-error") + .length && + $.ajax({ + method: "POST", + url: "/customer/update", + data: { + email: $("#shipEmail").val(), + company: $("#shipCompany").val(), + firstName: $("#shipFirstname").val(), + lastName: $("#shipLastname").val(), + address1: $("#shipAddr1").val(), + address2: $("#shipAddr2").val(), + country: $("#shipCountry").val(), + state: $("#shipState").val(), + postcode: $("#shipPostcode").val(), + phone: $("#shipPhoneNumber").val(), + password: $("#newCustomerPassword").val(), + orderComment: $("#orderComment").val(), + }, + }) + .done(function () { + showNotification("Customer saved", "success"); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); + }), + $(document).on("click", ".image-next", function (t) { + var a = $(".thumbnail-image"), + e = 0, + n = 0; + $(".thumbnail-image").each(function () { + $("#product-title-image").attr("src") === $(this).attr("src") && + (n = e + 1 === a.length || e + 1 < 0 ? 0 : e + 1), + e++; + }), + $("#product-title-image").attr("src", $(a).eq(n).attr("src")); + }), + $(document).on("click", ".image-prev", function (t) { + var a = $(".thumbnail-image"), + e = 0, + n = 0; + $(".thumbnail-image").each(function () { + $("#product-title-image").attr("src") === $(this).attr("src") && + (n = e - 1 === a.length || e - 1 < 0 ? a.length - 1 : e - 1), + e++; + }), + $("#product-title-image").attr("src", $(a).eq(n).attr("src")); + }), + $(document).on("change", "#product_variant", function (t) { + var a = $(this).find(":selected").attr("data-price"), + e = $("#currencySymbol").val(); + $("h4.product-price:first").html(e + a); + }), + $(document).on("click", ".add-variant-to-cart", function (t) { + $.ajax({ + method: "POST", + url: "/product/addtocart", + data: { + productId: $(this).attr("data-id"), + productQuantity: "1", + productVariant: $("#productVariant-" + $(this).attr("data-id")).val(), + }, + }) + .done(function (t) { + updateCartDiv(), showNotification(t.message, "success"); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); + }), + $(document).on("click", ".product-add-to-cart", function (t) { + parseInt($("#product_quantity").val()) < 1 && + $("#product_quantity").val(1), + $.ajax({ + method: "POST", + url: "/product/addtocart", + data: { + productId: $("#productId").val(), + productQuantity: $("#product_quantity").val(), + productVariant: $("#product_variant").val(), + productComment: $("#product_comment").val(), + }, + }) + .done(function (t) { + updateCartDiv(), showNotification(t.message, "success"); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); + }), + $("#product_quantity").on("keyup", function (t) { + checkMaxQuantity(t, $("#product_quantity")); + }), + $(".cart-product-quantity").on("keyup", function (t) { + checkMaxQuantity(t, $(".cart-product-quantity")); + }), + $(".cart-product-quantity").on("focusout", function (t) { + cartUpdate($(t.target)); + }), + $(document).on("click", ".pushy-link", function (t) { + $("body").removeClass("pushy-open-right"); + }), + $(document).on("click", ".add-to-cart", function (t) { + var a = "/product/" + $(this).attr("data-id"); + $(this).attr("data-link") && + (a = "/product/" + $(this).attr("data-link")), + "true" === $(this).attr("data-has-variants") + ? (window.location = a) + : $.ajax({ + method: "POST", + url: "/product/addtocart", + data: { productId: $(this).attr("data-id") }, + }) + .done(function (t) { + updateCartDiv(), showNotification(t.message, "success"); + }) + .fail(function (t) { + showNotification(t.responseJSON.message, "danger"); + }); + }), + $(document).on("click", "#add-review", function (t) { + $.ajax({ method: "POST", url: "/customer/check", data: {} }) + .done(function (t) { + $("#reviewModal").modal("show"); + }) + .fail(function () { + showNotification( + "You need to be logged in to create a review", + "danger", + !1, + "/customer/account" + ); + }); + }), + $(document).on("click", "#addReview", function (t) { + $.ajax({ + method: "POST", + url: "/product/addreview", + data: { + product: $("#product").val(), + title: $("#review-title").val(), + description: $("#review-description").val(), + rating: $("#review-rating").val(), + }, + }) + .done(function (t) { + showNotification(t.message, "success", !0); + }) + .fail(function (t) { + "You need to be logged in to create a review" === + t.responseJSON.message && + showNotification( + t.responseJSON.message, + "danger", + !1, + "/customer/account" + ), + showNotification(t.responseJSON.message, "danger"); + }); + }), + $(document).on("click", "#empty-cart", function (t) { + $("#confirmModal").modal("show"), + $("#buttonConfirm").attr("data-func", "emptyCart"); + }), + $(document).on("click", "#buttonConfirm", function (t) { + var a = $(t.target).attr("data-func"); + window[a](), $("#confirmModal").modal("hide"); + }), + $(".qty-btn-minus").on("click", function () { + var t = parseInt($("#product_quantity").val()) - 1; + $("#product_quantity").val(t > 0 ? t : 1); + }), + $(".qty-btn-plus").on("click", function () { + $("#product_quantity").val(parseInt($("#product_quantity").val()) + 1); + }), + $(".thumbnail-image").on("click", function () { + $("#product-title-image").attr("src", $(this).attr("src")); + }), + $(document).on("click", "#btn_search_reset", function (t) { + window.location.replace("/"); + }), + $(document).on("click", "#btn_search", function (t) { + t.preventDefault(), + "" === $("#frm_search").val().trim() + ? showNotification("Please enter a search value", "danger") + : (window.location.href = "/search/" + $("#frm_search").val()); + }), + "" !== $("#input_notify_message").val()) + ) { + var c = $("#input_notify_message").val(), + s = $("#input_notify_messageType").val(); + $("#input_notify_message").val(""), + $("#input_notify_messageType").val(""), + showNotification(c, s || "danger", !1); + } + if ($("#blockonomics_div").length > 0) { + var d = $("#blockonomics_div").data("orderid") || "", + l = $("#blockonomics_div").data("timestamp") || -1, + u = $("#blockonomics_div").data("address") || "", + m = new WebSocket( + "wss://www.blockonomics.co/payment/" + u + "?timestamp=" + l + ); + m.onopen = function (t) {}; + setTimeout(function () { + $("#blockonomics_waiting").html( + "Payment expired

Click here to try again.

If you already paid, your order will be processed automatically." + ), + showNotification("Payment expired", "danger"), + m.close(); + }, 6e5); + var p = $("#blockonomics_timeout"), + f = new Date(new Date().getTime() + 6e5), + v = setInterval(function () { + var t = new Date().getTime(), + a = f - t; + if (a < 0) clearInterval(v); + else { + var e = Math.floor((a % 36e5) / 6e4), + n = Math.floor((a % 6e4) / 1e3); + p.html(e + "m " + n + "s"); + } + }, 1e3); + m.onmessage = function (t) { + var a = JSON.parse(t.data); + if (0 === a.status || 1 === a.status || 2 === a.status) { + var e = '
View Order'; + $("#blockonomics_waiting").html( + "Payment detected (" + a.value / 1e8 + " BTC)." + e + ), + showNotification("Payment detected", "success"), + $("#cart-count").html("0"), + m.close(), + $.ajax({ method: "POST", url: "/product/emptycart" }).done( + function () { + window.location.replace("/payment/" + d); + } + ); + } + }; + } +}); diff --git a/routes/index.js b/routes/index.js index 774f4149..f0f0ec79 100644 --- a/routes/index.js +++ b/routes/index.js @@ -5,7 +5,7 @@ const stripHtml = require('string-strip-html'); const moment = require('moment'); const fs = require('fs'); const path = require('path'); -const _ = require('lodash'); +const lodash = require('lodash'); const ObjectId = require('mongodb').ObjectID; const { getId, @@ -626,7 +626,7 @@ router.post('/product/updatecart', async (req, res, next) => { // If there is stock if(stockHeld.length > 0){ - const totalHeld = _.find(stockHeld, ['_id', getId(cartItem.cartId)]).sumHeld; + const totalHeld = lodash.find(stockHeld, ['_id', getId(cartItem.cartId)]).sumHeld; const netStock = productStock - totalHeld; // Check there is sufficient stock @@ -782,7 +782,7 @@ router.post('/product/addtocart', async (req, res, next) => { // If there is stock if(stockHeld.length > 0){ - const heldProduct = _.find(stockHeld, ['_id', getId(productCartId)]); + const heldProduct = lodash.find(stockHeld, ['_id', getId(productCartId)]); if(heldProduct){ const netStock = productStock - heldProduct.sumHeld; @@ -1030,7 +1030,7 @@ router.get('/category/:cat/:pageNum?', (req, res) => { productsPerPage: numberProducts, totalProductCount: results.totalItems, pageNum: pageNum, - menuLink: _.find(sortedMenu.items, (obj) => { return obj.link === searchTerm; }), + menuLink: lodash.find(sortedMenu.items, (obj) => { return obj.link === searchTerm; }), paginateUrl: 'category', config: config, menu: sortedMenu,