diff --git a/app.js b/app.js
index e25d7bc..126b933 100644
--- a/app.js
+++ b/app.js
@@ -315,7 +315,13 @@ MongoClient.connect(config.databaseConnectionString, {}, (err, client) => {
// select DB
const dbUriObj = mongodbUri.parse(config.databaseConnectionString);
- const db = client.db(dbUriObj.database);
+ let db;
+ // if in testing, set the testing DB
+ if(process.env.NODE_ENV === 'test'){
+ db = client.db('testingdb');
+ }else{
+ db = client.db(dbUriObj.database);
+ }
// setup the collections
db.users = db.collection('users');
@@ -326,17 +332,20 @@ MongoClient.connect(config.databaseConnectionString, {}, (err, client) => {
db.customers = db.collection('customers');
// add db to app for routes
+ app.dbClient = client;
app.db = db;
+ app.config = config;
+ app.port = app.get('port');
// run indexing
common.runIndexing(app)
- .then(common.testData(db, app))
.then(app.listen(app.get('port')))
.then(() => {
// lift the app
+ app.emit('appStarted');
console.log(colors.green('expressCart running on host: http://localhost:' + app.get('port')));
})
- .catch(() => {
+ .catch((err) => {
console.error(colors.red('Error setting up indexes:' + err));
process.exit(2);
});
diff --git a/bin/testdata.json b/bin/testdata.json
index e1fa7d0..e38574d 100644
--- a/bin/testdata.json
+++ b/bin/testdata.json
@@ -14,7 +14,7 @@
"productImage": "/uploads/duckworth-jacket/woolfill-jacket_6c39ae23-c0c8-4821-85f4-4b5d64333c62_grande.jpg"
},
{
- "productPermalink": "5-panel-cap",
+ "productPermalink": "5-panel-camp-cap",
"productTitle": "5 Panel Camp Cap",
"productPrice": "48",
"productDescription": "
A classic 5 panel hat with our United By Blue logo on the front and an adjustable strap to keep fit and secure. Made with recycled polyester and organic cotton mix.<\/p>
Made in New Jersey<\/li>
7oz Eco-Twill fabric: 35% organic cotton, 65% recycled PET (plastic water and soda bottles) <\/li>
Comfortable and practical, our chambray button down is perfect for travel or days spent on the go. The Ayres Chambray has a rich, washed out indigo color suitable to throw on for any event. Made with sustainable soft chambray featuring two chest pockets with sturdy and scratch resistant corozo buttons.
",$("#product_opt_wrapper").append(r),n[e]={optName:e,optLabel:a,optType:o,optOptions:$.grep(i.split(","),function(t){return 0===t||t})},$("#productOptJson").val(JSON.stringify(n)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$("#stripeButton").validator().on("click",function(t){(t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length)&&window.StripeCheckout.configure({key:$("#stripeButton").data("key"),image:$("#stripeButton").data("image"),locale:"auto",token:function(t){$("#shipping-form").append(''),$("#shipping-form").submit()}}).open({name:$("#stripeButton").data("name"),description:$("#stripeButton").data("description"),zipCode:$("#stripeButton").data("zipCode"),amount:$("#stripeButton").data("amount"),currency:$("#stripeButton").data("currency")})}),$("#settingsForm").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(t){showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}))}),$("#customerLogout").on("click",function(t){$.ajax({method:"POST",url:"/customer/logout",data:{}}).done(function(t){location.reload()})}),$("#createCustomerAccount").validator().on("click",function(t){t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/customer/create",data:{email:$("#shipEmail").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()}}).done(function(t){location.reload()}).fail(function(t){showNotification(t.responseJSON.err,"danger")})}),$("#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 e=t.customer;$("#shipEmail").val(e.email),$("#shipFirstname").val(e.firstName),$("#shipLastname").val(e.lastName),$("#shipAddr1").val(e.address1),$("#shipAddr2").val(e.address2),$("#shipCountry").val(e.country),$("#shipState").val(e.state),$("#shipPostcode").val(e.postcode),$("#shipPhoneNumber").val(e.phone),location.reload()}).fail(function(t){showNotification(t.responseJSON.err,"danger")})),t.preventDefault()}),$(document).on("click",".image-next",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a+1===e.length||a+1<0?0:a+1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click",".image-prev",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a-1===e.length||a-1<0?e.length-1:a-1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click","#orderStatusUpdate",function(t){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product-add-to-cart",function(t){var e=getSelectedOptions();$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productOptions:JSON.stringify(e)}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".cart-product-quantity").on("input",function(){cartUpdate()}),$(document).on("click",".pushy-link",function(t){$("body").removeClass("pushy-open-right")}),$(document).on("click",".add-to-cart",function(t){var e="/product/"+$(this).attr("data-id");$(this).attr("data-link")&&(e="/product/"+$(this).attr("data-link")),"true"===$(this).attr("data-has-options")?window.location=e:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#empty-cart",function(t){$.ajax({method:"POST",url:"/product/emptycart"}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success",!0)})}),$(".qty-btn-minus").on("click",function(){$("#product_quantity").val(parseInt($("#product_quantity").val())-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"))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#frmProductId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#frmProductId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#validate_permalink",function(t){""!==$("#frmProductPermalink").val()?$.ajax({method:"POST",url:"/admin/api/validate_permalink",data:{permalink:$("#frmProductPermalink").val(),docId:$("#frmProductId").val()}}).done(function(t){showNotification(t,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(t){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(t){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(t){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(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()}),$(document).on("click","#frm_edit_product_save",function(t){""===$("#frmProductPermalink").val()&&""!==$("#frmProductTitle").val()&&$("#frmProductPermalink").val(slugify($("#frmProductTitle").val()))}),""!==$("#input_notify_message").val()){var l=$("#input_notify_message").val(),u=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(l,u,!1)}});
\ No newline at end of file
+function deleteFromCart(t){$.ajax({method:"POST",url:"/product/removefromcart",data:{cart_index:t.attr("data-id")}}).done(function(e){$("#cart-count").text(e.totalCartItems),0===e.totalCartItems?($(t).closest(".cart-row").hide("slow",function(){$(t).closest(".cart-row").remove()}),$(".cart-contents-shipping").hide("slow",function(){$(".cart-contents-shipping").remove()}),showNotification(e.message,"success"),setTimeout(function(){window.location="/"},3700)):($(t).closest(".cart-row").hide("slow",function(){$(t).closest(".cart-row").remove()}),showNotification(e.message,"success"))}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function slugify(t){return $.trim(t).replace(/[^a-z0-9-æøå]/gi,"-").replace(/-+/g,"-").replace(/^-|-$/g,"").replace(/æ/gi,"ae").replace(/ø/gi,"oe").replace(/å/gi,"a").toLowerCase()}function cartUpdate(t){$(t).val()<1?deleteFromCart($(t)):""!==$(t).val()&&updateCart()}function updateCart(){var t=[];$(".cart-product-quantity").each(function(){var e={cartIndex:$(this).attr("id"),itemQuantity:$(this).val(),productId:$(this).attr("data-id")};$(this).val()<0?deleteFromCart($(this)):t.push(e)}),$.ajax({method:"POST",url:"/product/updatecart",data:{items:JSON.stringify(t)}}).done(function(t){updateCartDiv(),$("#cart-count").text(t.totalCartItems)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function updateCartDiv(){var t=window.location.pathname.split("/").length>0?window.location.pathname.split("/")[1]:"";$.ajax({method:"GET",url:"/cartPartial",data:{path:t}}).done(function(t){$("#cart").html(t)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}function getSelectedOptions(){var t={};return $(".product-opt").each(function(){t[$(this).attr("name")]=$(this).val()}),t}function showNotification(t,e,a){a=a||!1,$("#notify_message").removeClass(),$("#notify_message").addClass("alert-"+e),$("#notify_message").html(t),$("#notify_message").slideDown(600).delay(2500).slideUp(600,function(){!0===a&&location.reload()})}$(document).ready(function(){if("Material"===$("#cartTheme").val()&&$(".materialboxed").materialbox(),$(window).width()<768&&($(".menu-side").on("click",function(t){t.preventDefault(),$('.menu-side li:not(".active")').slideToggle()}),$('.menu-side li:not(".active")').hide(),$(".menu-side>.active").html(''),$(".menu-side>.active").addClass("menu-side-mobile"),0===$("#navbar ul li").length&&$("#navbar").hide(),$("#offcanvasClose").hide()),$(".shipping-form input").each(function(t){$(this).wrap("");var e=$(this).attr("placeholder");$(this).after('")}),$(".shipping-form input").on("focus",function(){$(this).next().addClass("floatLabel"),$(this).next().removeClass("hidden")}),$(".shipping-form input").on("blur",function(){""===$(this).val()&&($(this).next().addClass("hidden"),$(this).next().removeClass("floatLabel"))}),$(".menu-btn").on("click",function(t){t.preventDefault()}),$("#sendTestEmail").on("click",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/testEmail"}).done(function(t){showNotification(t,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$("#footerHtml").length){var t=window.CodeMirror.fromTextArea(document.getElementById("footerHtml"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1});t.setValue(t.getValue())}if($("#googleAnalytics").length&&window.CodeMirror.fromTextArea(document.getElementById("googleAnalytics"),{mode:"xml",tabMode:"indent",theme:"flatly",lineNumbers:!0,htmlMode:!0,fixedGutter:!1}),$("#customCss").length){var e=window.CodeMirror.fromTextArea(document.getElementById("customCss"),{mode:"text/css",tabMode:"indent",theme:"flatly",lineNumbers:!0}),a=window.cssbeautify(e.getValue(),{indent:" ",autosemicolon:!0});e.setValue(a)}if($("table").each(function(){$(this).addClass("table table-hover")}),$("#frmProductTags").tokenfield(),$(document).on("click",".dashboard_list",function(t){window.document.location=$(this).attr("href")}).hover(function(){$(this).toggleClass("hover")}),$(".product-title").dotdotdot({ellipsis:"..."}),$('input[class="published_state"]').change(function(){$.ajax({method:"POST",url:"/admin/product/published_state",data:{id:this.id,state:this.checked}}).done(function(t){showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".btn-qty-minus",function(t){var e=$(t.target).parent().parent().find(".cart-product-quantity");$(e).val(parseInt(e.val())-1),cartUpdate(e)}),$(document).on("click",".btn-qty-add",function(t){var e=$(t.target).parent().parent().find(".cart-product-quantity");$(e).val(parseInt(e.val())+1),cartUpdate(e)}),$(document).on("click",".orderFilterByStatus",function(t){t.preventDefault(),window.location="/admin/orders/bystatus/"+$("#orderStatusFilter").val()}),$("#pager").length){var o=$("#pageNum").val(),i=$("#productsPerPage").val(),n=$("#totalProductCount").val(),r=$("#paginateUrl").val(),s=$("#searchTerm").val();""!==s&&(s+="/");var c="/"+r+"/"+s+"{{number}}",d=Math.ceil(n/i);parseInt(n)>parseInt(i)&&$("#pager").bootpag({total:d,page:o,maxVisible:5,href:c,wrapClass:"pagination",prevClass:"waves-effect",nextClass:"waves-effect",activeClass:"pag-active waves-effect"})}if($(document).on("click","#btnPageUpdate",function(t){t.preventDefault(),$.ajax({method:"POST",url:"/admin/settings/pages/update",data:{page_id:$("#page_id").val(),pageName:$("#pageName").val(),pageSlug:$("#pageSlug").val(),pageEnabled:$("#pageEnabled").is(":checked"),pageContent:$("#pageContent").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product_opt_remove",function(t){t.preventDefault();var e=$(this).closest("li").find(".opt-name").html();$.ajax({method:"POST",url:"/admin/settings/option/remove/",data:{productId:$("#frmProductId").val(),optName:e}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#product_opt_add",function(t){t.preventDefault();var e=$("#product_optName").val(),a=$("#product_optLabel").val(),o=$("#product_optType").val(),i=$("#product_optOptions").val(),n={};""!==$("#productOptJson").val()&&(n=JSON.parse($("#productOptJson").val()));var r='
';r+='
',r+='
'+e+"
",r+='
'+a+"
",r+='
'+o+"
",r+='
'+i+"
",r+='
',r+='',r+="
",$("#product_opt_wrapper").append(r),n[e]={optName:e,optLabel:a,optType:o,optOptions:$.grep(i.split(","),function(t){return 0===t||t})},$("#productOptJson").val(JSON.stringify(n)),$("#product_optName").val(""),$("#product_optLabel").val(""),$("#product_optOptions").val("")}),$("#stripeButton").validator().on("click",function(t){(t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length)&&window.StripeCheckout.configure({key:$("#stripeButton").data("key"),image:$("#stripeButton").data("image"),locale:"auto",token:function(t){$("#shipping-form").append(''),$("#shipping-form").submit()}}).open({name:$("#stripeButton").data("name"),description:$("#stripeButton").data("description"),zipCode:$("#stripeButton").data("zipCode"),amount:$("#stripeButton").data("amount"),currency:$("#stripeButton").data("currency")})}),$("#settingsForm").validator().on("submit",function(t){t.isDefaultPrevented()||(t.preventDefault(),$("#footerHtml_input").val($(".CodeMirror")[0].CodeMirror.getValue()),$("#googleAnalytics_input").val($(".CodeMirror")[1].CodeMirror.getValue()),$("#customCss_input").val($(".CodeMirror")[2].CodeMirror.getValue()),$.ajax({method:"POST",url:"/admin/settings/update",data:$("#settingsForm").serialize()}).done(function(t){showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}))}),$("#customerLogout").on("click",function(t){$.ajax({method:"POST",url:"/customer/logout",data:{}}).done(function(t){location.reload()})}),$("#createCustomerAccount").validator().on("click",function(t){t.preventDefault(),0===$("#shipping-form").validator("validate").has(".has-error").length&&$.ajax({method:"POST",url:"/customer/create",data:{email:$("#shipEmail").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()}}).done(function(t){location.reload()}).fail(function(t){showNotification(t.responseJSON.err,"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()}),$("#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 e=t.customer;$("#shipEmail").val(e.email),$("#shipFirstname").val(e.firstName),$("#shipLastname").val(e.lastName),$("#shipAddr1").val(e.address1),$("#shipAddr2").val(e.address2),$("#shipCountry").val(e.country),$("#shipState").val(e.state),$("#shipPostcode").val(e.postcode),$("#shipPhoneNumber").val(e.phone),location.reload()}).fail(function(t){showNotification(t.responseJSON.err,"danger")})),t.preventDefault()}),$(document).on("click",".image-next",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a+1===e.length||a+1<0?0:a+1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click",".image-prev",function(t){var e=$(".thumbnail-image"),a=0,o=0;$(".thumbnail-image").each(function(){$("#product-title-image").attr("src")===$(this).attr("src")&&(o=a-1===e.length||a-1<0?e.length-1:a-1),a++}),$("#product-title-image").attr("src",$(e).eq(o).attr("src"))}),$(document).on("click","#orderStatusUpdate",function(t){$.ajax({method:"POST",url:"/admin/order/statusupdate",data:{order_id:$("#order_id").val(),status:$("#orderStatus").val()}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click",".product-add-to-cart",function(t){var e=getSelectedOptions();$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productOptions:JSON.stringify(e)}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".cart-product-quantity").on("input",function(){cartUpdate()}),$(document).on("click",".pushy-link",function(t){$("body").removeClass("pushy-open-right")}),$(document).on("click",".add-to-cart",function(t){var e="/product/"+$(this).attr("data-id");$(this).attr("data-link")&&(e="/product/"+$(this).attr("data-link")),"true"===$(this).attr("data-has-options")?window.location=e:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#empty-cart",function(t){$.ajax({method:"POST",url:"/product/emptycart"}).done(function(t){$("#cart-count").text(t.totalCartItems),updateCartDiv(),showNotification(t.message,"success",!0)})}),$(".qty-btn-minus").on("click",function(){$("#product_quantity").val(parseInt($("#product_quantity").val())-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"))}),$(".set-as-main-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/setasmainimage",data:{product_id:$("#frmProductId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(".btn-delete-image").on("click",function(){$.ajax({method:"POST",url:"/admin/product/deleteimage",data:{product_id:$("#frmProductId").val(),productImage:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success",!0)}).fail(function(t){showNotification(t.responseJSON.message,"danger")})}),$(document).on("click","#validate_permalink",function(t){""!==$("#frmProductPermalink").val()?$.ajax({method:"POST",url:"/admin/api/validate_permalink",data:{permalink:$("#frmProductPermalink").val(),docId:$("#frmProductId").val()}}).done(function(t){showNotification(t,"success")}).fail(function(t){showNotification(t.responseJSON.message,"danger")}):showNotification("Please enter a permalink to validate","danger")}),$(document).on("click","#btn_product_filter",function(t){""!==$("#product_filter").val()?window.location.href="/admin/products/filter/"+$("#product_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_order_filter",function(t){""!==$("#order_filter").val()?window.location.href="/admin/orders/filter/"+$("#order_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(document).on("click","#btn_customer_filter",function(t){""!==$("#customer_filter").val()?window.location.href="/admin/customers/filter/"+$("#customer_filter").val():showNotification("Please enter a keyword to filter","danger")}),$(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()}),$(document).on("click","#frm_edit_product_save",function(t){""===$("#frmProductPermalink").val()&&""!==$("#frmProductTitle").val()&&$("#frmProductPermalink").val(slugify($("#frmProductTitle").val()))}),""!==$("#input_notify_message").val()){var l=$("#input_notify_message").val(),u=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(l,u,!1)}});
\ No newline at end of file
diff --git a/routes/admin.js b/routes/admin.js
index ea13281..2199d8a 100644
--- a/routes/admin.js
+++ b/routes/admin.js
@@ -39,7 +39,7 @@ router.get('/admin/login', (req, res) => {
res.render('login', {
title: 'Login',
referringUrl: req.header('Referer'),
- config: common.getConfig(),
+ config: req.app.config,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
@@ -59,17 +59,13 @@ router.post('/admin/login_action', (req, res) => {
db.users.findOne({userEmail: req.body.email}, (err, user) => {
if(err){
- req.session.message = 'Cannot find user.';
- req.session.messageType = 'danger';
- res.redirect('/admin/login');
+ res.status(400).json({message: 'A user with that email does not exist.'});
return;
}
// check if user exists with that email
if(user === undefined || user === null){
- req.session.message = 'A user with that email does not exist.';
- req.session.messageType = 'danger';
- res.redirect('/admin/login');
+ res.status(400).json({message: 'A user with that email does not exist.'});
}else{
// we have a user under that email so we compare the password
bcrypt.compare(req.body.password, user.userPassword)
@@ -79,12 +75,10 @@ router.post('/admin/login_action', (req, res) => {
req.session.usersName = user.usersName;
req.session.userId = user._id.toString();
req.session.isAdmin = user.isAdmin;
- res.redirect('/admin');
+ res.status(200).json({message: 'Login successful'});
}else{
// password is not correct
- req.session.message = 'Access denied. Check password and try again.';
- req.session.messageType = 'danger';
- res.redirect('/admin/login');
+ res.status(400).json({message: 'Access denied. Check password and try again.'});
}
});
}
@@ -106,7 +100,7 @@ router.get('/admin/setup', (req, res) => {
req.session.needsSetup = true;
res.render('setup', {
title: 'Setup',
- config: common.getConfig(),
+ config: req.app.config,
helpers: req.handlebars.helpers,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
@@ -165,9 +159,9 @@ router.get('/admin/settings', common.restrict, (req, res) => {
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
- config: common.getConfig(),
- footerHtml: typeof common.getConfig().footerHtml !== 'undefined' ? escape.decode(common.getConfig().footerHtml) : null,
- googleAnalytics: typeof common.getConfig().googleAnalytics !== 'undefined' ? escape.decode(common.getConfig().googleAnalytics) : null
+ config: req.app.config,
+ footerHtml: typeof req.app.config.footerHtml !== 'undefined' ? escape.decode(req.app.config.footerHtml) : null,
+ googleAnalytics: typeof req.app.config.googleAnalytics !== 'undefined' ? escape.decode(req.app.config.googleAnalytics) : null
});
});
@@ -218,7 +212,7 @@ router.get('/admin/settings/menu', common.restrict, async (req, res) => {
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
- config: common.getConfig(),
+ config: req.app.config,
menu: common.sortMenu(await common.getMenu(db))
});
});
@@ -239,7 +233,7 @@ router.get('/admin/settings/pages', common.restrict, (req, res) => {
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
- config: common.getConfig(),
+ config: req.app.config,
menu: common.sortMenu(await common.getMenu(db))
});
});
@@ -257,7 +251,7 @@ router.get('/admin/settings/pages/new', common.restrict, common.checkAccess, asy
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
- config: common.getConfig(),
+ config: req.app.config,
menu: common.sortMenu(await common.getMenu(db))
});
});
@@ -281,14 +275,14 @@ router.get('/admin/settings/pages/edit/:page', common.restrict, common.checkAcce
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
- config: common.getConfig(),
+ config: req.app.config,
menu
});
}else{
// 404 it!
res.status(404).render('error', {
title: '404 Error - Page not found',
- config: common.getConfig(),
+ config: req.app.config,
message: '404 Error - Page not found',
helpers: req.handlebars.helpers,
showFooter: 'showFooter',
@@ -478,7 +472,7 @@ router.post('/admin/file/upload', common.restrict, common.checkAccess, upload.si
// delete a file via ajax request
router.post('/admin/testEmail', common.restrict, (req, res) => {
- let config = common.getConfig();
+ let config = req.app.config;
// TODO: Should fix this to properly handle result
common.sendEmail(config.emailAddress, 'expressCart test email', 'Your email settings are working');
res.status(200).json({message: 'Test email sent'});
diff --git a/routes/customer.js b/routes/customer.js
index bcf4bfd..a9e17d9 100644
--- a/routes/customer.js
+++ b/routes/customer.js
@@ -74,7 +74,7 @@ router.get('/admin/customer/view/:id?', common.restrict, (req, res) => {
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
- config: common.getConfig(),
+ config: req.app.config,
editor: true,
helpers: req.handlebars.helpers
});
@@ -94,7 +94,7 @@ router.get('/admin/customers', common.restrict, (req, res) => {
helpers: req.handlebars.helpers,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
- config: common.getConfig()
+ config: req.app.config
});
});
});
@@ -119,7 +119,7 @@ router.get('/admin/customers/filter/:search', common.restrict, (req, res, next)
title: 'Customer results',
customers: customers,
admin: true,
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
searchTerm: searchTerm,
message: common.clearSessionValue(req.session, 'message'),
@@ -130,7 +130,7 @@ router.get('/admin/customers/filter/:search', common.restrict, (req, res, next)
});
// login the customer and check the password
-router.post('/customer/login_action', (req, res) => {
+router.post('/customer/login_action', async (req, res) => {
let db = req.app.db;
db.customers.findOne({email: req.body.loginEmail}, (err, customer) => { // eslint-disable-line
@@ -178,7 +178,7 @@ router.get('/customer/forgotten', (req, res) => {
title: 'Forgotten',
route: 'customer',
forgotType: 'customer',
- config: common.getConfig(),
+ config: req.app.config,
helpers: req.handlebars.helpers,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
@@ -189,7 +189,7 @@ router.get('/customer/forgotten', (req, res) => {
// forgotten password
router.post('/customer/forgotten_action', (req, res) => {
const db = req.app.db;
- const config = common.getConfig();
+ const config = req.app.config;
let passwordToken = randtoken.generate(30);
// find the user
@@ -240,7 +240,7 @@ router.get('/customer/reset/:token', (req, res) => {
title: 'Reset password',
token: req.params.token,
route: 'customer',
- config: common.getConfig(),
+ config: req.app.config,
message: common.clearSessionValue(req.session, 'message'),
message_type: common.clearSessionValue(req.session, 'message_type'),
show_footer: 'show_footer',
diff --git a/routes/index.js b/routes/index.js
index 5adb7a2..e2c22be 100644
--- a/routes/index.js
+++ b/routes/index.js
@@ -6,10 +6,9 @@ const _ = require('lodash');
const common = require('../lib/common');
// These is the customer facing routes
-
router.get('/payment/:orderId', async (req, res, next) => {
let db = req.app.db;
- let config = common.getConfig();
+ let config = req.app.config;
// render the payment complete message
db.orders.findOne({_id: common.getId(req.params.orderId)}, async (err, result) => {
@@ -18,7 +17,7 @@ router.get('/payment/:orderId', async (req, res, next) => {
}
res.render(`${config.themeViews}payment_complete`, {
title: 'Payment complete',
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
pageCloseBtn: common.showCartCloseBtn('payment'),
result: result,
@@ -32,7 +31,7 @@ router.get('/payment/:orderId', async (req, res, next) => {
});
router.get('/checkout', async (req, res, next) => {
- let config = common.getConfig();
+ let config = req.app.config;
// if there is no items in the cart then render a failure
if(!req.session.cart){
@@ -45,7 +44,7 @@ router.get('/checkout', async (req, res, next) => {
// render the checkout
res.render(`${config.themeViews}checkout`, {
title: 'Checkout',
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
pageCloseBtn: common.showCartCloseBtn('checkout'),
checkout: 'hidden',
@@ -58,7 +57,7 @@ router.get('/checkout', async (req, res, next) => {
});
router.get('/pay', async (req, res, next) => {
- const config = common.getConfig();
+ const config = req.app.config;
// if there is no items in the cart then render a failure
if(!req.session.cart){
@@ -71,7 +70,7 @@ router.get('/pay', async (req, res, next) => {
// render the payment page
res.render(`${config.themeViews}pay`, {
title: 'Pay',
- config: common.getConfig(),
+ config: req.app.config,
paymentConfig: common.getPaymentConfig(),
pageCloseBtn: common.showCartCloseBtn('pay'),
session: req.session,
@@ -85,14 +84,14 @@ router.get('/pay', async (req, res, next) => {
});
router.get('/cartPartial', (req, res) => {
- const config = common.getConfig();
+ const config = req.app.config;
res.render(`${config.themeViews}cart`, {
pageCloseBtn: common.showCartCloseBtn(req.query.path),
page: req.query.path,
layout: false,
helpers: req.handlebars.helpers,
- config: common.getConfig(),
+ config: req.app.config,
session: req.session
});
});
@@ -100,7 +99,7 @@ router.get('/cartPartial', (req, res) => {
// show an individual product
router.get('/product/:id', (req, res) => {
let db = req.app.db;
- let config = common.getConfig();
+ let config = req.app.config;
db.products.findOne({$or: [{_id: common.getId(req.params.id)}, {productPermalink: req.params.id}]}, (err, result) => {
// render 404 if page is not published
@@ -115,6 +114,12 @@ router.get('/product/:id', (req, res) => {
productOptions = JSON.parse(result.productOptions);
}
+ // If JSON query param return json instead
+ if(req.query.json === 'true'){
+ res.status(200).json(result);
+ return;
+ }
+
// show the view
common.getImages(result._id, req, res, async (images) => {
res.render(`${config.themeViews}product`, {
@@ -223,58 +228,59 @@ router.post('/product/addtocart', (req, res, next) => {
db.products.findOne({_id: common.getId(req.body.productId)}, (err, product) => {
if(err){
console.error(colors.red('Error adding to cart', err));
+ return res.status(400).json({message: 'Error updating cart. Please try again.'});
}
- // We item is found, add it to the cart
- if(product){
- let productPrice = parseFloat(product.productPrice).toFixed(2);
+ // No product found
+ if(!product){
+ return res.status(400).json({message: 'Error updating cart. Please try again.'});
+ }
- // Doc used to test if existing in the cart with the options. If not found, we add new.
- let options = {};
- if(req.body.productOptions){
- options = JSON.parse(req.body.productOptions);
- }
- let findDoc = {
- productId: req.body.productId,
- options: options
- };
+ let productPrice = parseFloat(product.productPrice).toFixed(2);
- // if exists we add to the existing value
- let cartIndex = _.findIndex(req.session.cart, findDoc);
- if(cartIndex > -1){
- req.session.cart[cartIndex].quantity = parseInt(req.session.cart[cartIndex].quantity) + productQuantity;
- req.session.cart[cartIndex].totalItemPrice = productPrice * parseInt(req.session.cart[cartIndex].quantity);
- }else{
- // Doesnt exist so we add to the cart session
- req.session.cartTotalItems = req.session.cartTotalItems + productQuantity;
+ // Doc used to test if existing in the cart with the options. If not found, we add new.
+ let options = {};
+ if(req.body.productOptions){
+ options = JSON.parse(req.body.productOptions);
+ }
+ let findDoc = {
+ productId: req.body.productId,
+ options: options
+ };
- // new product deets
- let productObj = {};
- productObj.productId = req.body.productId;
- productObj.title = product.productTitle;
- productObj.quantity = productQuantity;
- productObj.totalItemPrice = productPrice * productQuantity;
- productObj.options = options;
- productObj.productImage = product.productImage;
- if(product.productPermalink){
- productObj.link = product.productPermalink;
- }else{
- productObj.link = product._id;
- }
-
- // merge into the current cart
- req.session.cart.push(productObj);
- }
-
- // update total cart amount
- common.updateTotalCartAmount(req, res);
-
- // update how many products in the shopping cart
- req.session.cartTotalItems = Object.keys(req.session.cart).length;
- res.status(200).json({message: 'Cart successfully updated', totalCartItems: Object.keys(req.session.cart).length});
+ // if exists we add to the existing value
+ let cartIndex = _.findIndex(req.session.cart, findDoc);
+ if(cartIndex > -1){
+ req.session.cart[cartIndex].quantity = parseInt(req.session.cart[cartIndex].quantity) + productQuantity;
+ req.session.cart[cartIndex].totalItemPrice = productPrice * parseInt(req.session.cart[cartIndex].quantity);
}else{
- res.status(400).json({message: 'Error updating cart. Please try again.'});
+ // Doesnt exist so we add to the cart session
+ req.session.cartTotalItems = req.session.cartTotalItems + productQuantity;
+
+ // new product deets
+ let productObj = {};
+ productObj.productId = req.body.productId;
+ productObj.title = product.productTitle;
+ productObj.quantity = productQuantity;
+ productObj.totalItemPrice = productPrice * productQuantity;
+ productObj.options = options;
+ productObj.productImage = product.productImage;
+ if(product.productPermalink){
+ productObj.link = product.productPermalink;
+ }else{
+ productObj.link = product._id;
+ }
+
+ // merge into the current cart
+ req.session.cart.push(productObj);
}
+
+ // update total cart amount
+ common.updateTotalCartAmount(req, res);
+
+ // update how many products in the shopping cart
+ req.session.cartTotalItems = Object.keys(req.session.cart).length;
+ return res.status(200).json({message: 'Cart successfully updated', totalCartItems: Object.keys(req.session.cart).length});
});
});
@@ -283,7 +289,7 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
let db = req.app.db;
let searchTerm = req.params.searchTerm;
let productsIndex = req.app.productsIndex;
- let config = common.getConfig();
+ let config = req.app.config;
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
let lunrIdArray = [];
@@ -301,12 +307,18 @@ router.get('/search/:searchTerm/:pageNum?', (req, res) => {
common.getMenu(db)
])
.then(([results, menu]) => {
+ // If JSON query param return json instead
+ if(req.query.json === 'true'){
+ res.status(200).json(results.data);
+ return;
+ }
+
res.render(`${config.themeViews}index`, {
title: 'Results',
results: results.data,
filtered: true,
session: req.session,
- metaDescription: common.getConfig().cartTitle + ' - Search term: ' + searchTerm,
+ metaDescription: req.app.config.cartTitle + ' - Search term: ' + searchTerm,
searchTerm: searchTerm,
pageCloseBtn: common.showCartCloseBtn('search'),
message: common.clearSessionValue(req.session, 'message'),
@@ -331,7 +343,7 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
let db = req.app.db;
let searchTerm = req.params.cat;
let productsIndex = req.app.productsIndex;
- let config = common.getConfig();
+ let config = req.app.config;
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
let lunrIdArray = [];
@@ -351,13 +363,19 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
.then(([results, menu]) => {
const sortedMenu = common.sortMenu(menu);
+ // If JSON query param return json instead
+ if(req.query.json === 'true'){
+ res.status(200).json(results.data);
+ return;
+ }
+
res.render(`${config.themeViews}index`, {
title: 'Category',
results: results.data,
filtered: true,
session: req.session,
searchTerm: searchTerm,
- metaDescription: common.getConfig().cartTitle + ' - Category: ' + searchTerm,
+ metaDescription: req.app.config.cartTitle + ' - Category: ' + searchTerm,
pageCloseBtn: common.showCartCloseBtn('category'),
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
@@ -380,7 +398,7 @@ router.get('/category/:cat/:pageNum?', (req, res) => {
// return sitemap
router.get('/sitemap.xml', (req, res, next) => {
let sm = require('sitemap');
- let config = common.getConfig();
+ let config = req.app.config;
common.addSitemapProducts(req, res, (err, products) => {
if(err){
@@ -412,7 +430,7 @@ router.get('/sitemap.xml', (req, res, next) => {
router.get('/page/:pageNum', (req, res, next) => {
let db = req.app.db;
- let config = common.getConfig();
+ let config = req.app.config;
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
Promise.all([
@@ -420,15 +438,21 @@ router.get('/page/:pageNum', (req, res, next) => {
common.getMenu(db)
])
.then(([results, menu]) => {
+ // If JSON query param return json instead
+ if(req.query.json === 'true'){
+ res.status(200).json(results.data);
+ return;
+ }
+
res.render(`${config.themeViews}index`, {
title: 'Shop',
results: results.data,
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
- metaDescription: common.getConfig().cartTitle + ' - Products page: ' + req.params.pageNum,
+ metaDescription: req.app.config.cartTitle + ' - Products page: ' + req.params.pageNum,
pageCloseBtn: common.showCartCloseBtn('page'),
- config: common.getConfig(),
+ config: req.app.config,
productsPerPage: numberProducts,
totalProductCount: results.totalProducts,
pageNum: req.params.pageNum,
@@ -446,7 +470,7 @@ router.get('/page/:pageNum', (req, res, next) => {
// The main entry point of the shop
router.get('/:page?', (req, res, next) => {
let db = req.app.db;
- let config = common.getConfig();
+ let config = req.app.config;
let numberProducts = config.productsPerPage ? config.productsPerPage : 6;
// if no page is specified, just render page 1 of the cart
@@ -456,6 +480,12 @@ router.get('/:page?', (req, res, next) => {
common.getMenu(db)
])
.then(([results, menu]) => {
+ // If JSON query param return json instead
+ if(req.query.json === 'true'){
+ res.status(200).json(results.data);
+ return;
+ }
+
res.render(`${config.themeViews}index`, {
title: `${config.cartTitle} - Shop`,
theme: config.theme,
@@ -464,7 +494,7 @@ router.get('/:page?', (req, res, next) => {
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
pageCloseBtn: common.showCartCloseBtn('page'),
- config: common.getConfig(),
+ config: req.app.config,
productsPerPage: numberProducts,
totalProductCount: results.totalProducts,
pageNum: 1,
@@ -497,8 +527,8 @@ router.get('/:page?', (req, res, next) => {
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
pageCloseBtn: common.showCartCloseBtn('page'),
- config: common.getConfig(),
- metaDescription: common.getConfig().cartTitle + ' - ' + page,
+ config: req.app.config,
+ metaDescription: req.app.config.cartTitle + ' - ' + page,
helpers: req.handlebars.helpers,
showFooter: 'showFooter',
menu: common.sortMenu(await common.getMenu(db))
@@ -506,7 +536,7 @@ router.get('/:page?', (req, res, next) => {
}else{
res.status(404).render('error', {
title: '404 Error - Page not found',
- config: common.getConfig(),
+ config: req.app.config,
message: '404 Error - Page not found',
helpers: req.handlebars.helpers,
showFooter: 'showFooter',
diff --git a/routes/order.js b/routes/order.js
index e25af1f..b85d540 100644
--- a/routes/order.js
+++ b/routes/order.js
@@ -15,7 +15,7 @@ router.get('/admin/orders', common.restrict, (req, res, next) => {
title: 'Cart',
orders: orders,
admin: true,
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
@@ -45,7 +45,7 @@ router.get('/admin/orders/bystatus/:orderstatus', common.restrict, (req, res, ne
admin: true,
filteredOrders: true,
filteredStatus: req.params.orderstatus,
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
@@ -69,7 +69,7 @@ router.get('/admin/order/view/:id', common.restrict, (req, res) => {
title: 'View order',
result: result,
productOptions: productOptions,
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
@@ -100,7 +100,7 @@ router.get('/admin/orders/filter/:search', common.restrict, (req, res, next) =>
title: 'Order results',
orders: orders,
admin: true,
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
searchTerm: searchTerm,
message: common.clearSessionValue(req.session, 'message'),
diff --git a/routes/payments/authorizenet.js b/routes/payments/authorizenet.js
index 16e50c1..6e785dd 100644
--- a/routes/payments/authorizenet.js
+++ b/routes/payments/authorizenet.js
@@ -7,7 +7,7 @@ const router = express.Router();
// The homepage of the site
router.post('/checkout_action', (req, res, next) => {
const db = req.app.db;
- const config = common.getConfig();
+ const config = req.app.config;
const authorizenetConfig = common.getPaymentConfig();
let authorizeUrl = 'https://api.authorize.net/xml/v1/request.api';
diff --git a/routes/payments/paypal.js b/routes/payments/paypal.js
index 58581a6..a5d3f56 100644
--- a/routes/payments/paypal.js
+++ b/routes/payments/paypal.js
@@ -10,7 +10,7 @@ router.get('/checkout_cancel', (req, res, next) => {
router.get('/checkout_return', (req, res, next) => {
let db = req.app.db;
- let config = common.getConfig();
+ let config = req.app.config;
let paymentId = req.session.paymentId;
let payerId = req.query['PayerID'];
@@ -107,7 +107,7 @@ router.get('/checkout_return', (req, res, next) => {
// The homepage of the site
router.post('/checkout_action', (req, res, next) => {
let db = req.app.db;
- let config = common.getConfig();
+ let config = req.app.config;
let paypalConfig = common.getPaymentConfig();
// setup the payment object
diff --git a/routes/payments/stripe.js b/routes/payments/stripe.js
index d01ee0e..931dc3b 100644
--- a/routes/payments/stripe.js
+++ b/routes/payments/stripe.js
@@ -7,7 +7,7 @@ let router = express.Router();
// The homepage of the site
router.post('/checkout_action', (req, res, next) => {
let db = req.app.db;
- let config = common.getConfig();
+ let config = req.app.config;
let stripeConfig = common.getPaymentConfig();
// charge via stripe
diff --git a/routes/product.js b/routes/product.js
index 11a3e08..dec0e11 100644
--- a/routes/product.js
+++ b/routes/product.js
@@ -18,7 +18,7 @@ router.get('/admin/products', common.restrict, (req, res, next) => {
top_results: topResults,
session: req.session,
admin: true,
- config: common.getConfig(),
+ config: req.app.config,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers
@@ -45,7 +45,7 @@ router.get('/admin/products/filter/:search', (req, res, next) => {
title: 'Results',
results: results,
admin: true,
- config: common.getConfig(),
+ config: req.app.config,
session: req.session,
searchTerm: searchTerm,
message: common.clearSessionValue(req.session, 'message'),
@@ -69,7 +69,7 @@ router.get('/admin/product/new', common.restrict, common.checkAccess, (req, res)
editor: true,
admin: true,
helpers: req.handlebars.helpers,
- config: common.getConfig()
+ config: req.app.config
});
});
@@ -167,7 +167,7 @@ router.get('/admin/product/edit/:id', common.restrict, common.checkAccess, (req,
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
- config: common.getConfig(),
+ config: req.app.config,
editor: true,
helpers: req.handlebars.helpers
});
diff --git a/routes/user.js b/routes/user.js
index 30eca95..9c8815b 100644
--- a/routes/user.js
+++ b/routes/user.js
@@ -15,7 +15,7 @@ router.get('/admin/users', common.restrict, (req, res) => {
title: 'Users',
users: users,
admin: true,
- config: common.getConfig(),
+ config: req.app.config,
isAdmin: req.session.isAdmin,
helpers: req.handlebars.helpers,
session: req.session,
@@ -49,7 +49,7 @@ router.get('/admin/user/edit/:id', common.restrict, (req, res) => {
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
- config: common.getConfig()
+ config: req.app.config
});
});
});
@@ -63,7 +63,7 @@ router.get('/admin/user/new', common.restrict, (req, res) => {
helpers: req.handlebars.helpers,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
- config: common.getConfig()
+ config: req.app.config
});
});
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..17c7ce9
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,147 @@
+const test = require('ava');
+const axios = require('axios');
+const fs = require('fs');
+const app = require('../app');
+const common = require('../lib/common');
+
+// Get test data to compare in tests
+const rawTestData = fs.readFileSync('./bin/testdata.json', 'utf-8');
+const testData = JSON.parse(rawTestData);
+
+let config;
+let db;
+let baseUrl;
+let products;
+let customers;
+let users;
+
+// Start up app and wait for it to be ready
+test.before.cb(t => {
+ app.on('appStarted', async () => {
+ // Set some stuff now we have the app started
+ config = app.config;
+ db = app.db;
+ baseUrl = `http://localhost:${app.port}`;
+ await common.testData(app);
+ products = await db.products.find({}).toArray();
+ customers = await db.customers.find({}).toArray();
+ users = await db.users.find({}).toArray();
+ t.end();
+ });
+});
+
+test('[Success] Get products JSON', t => {
+ return new Promise((resolve, reject) => {
+ axios.get(`${baseUrl}?json=true`)
+ .then((response) => {
+ if(response.data.length < config.productsPerPage){
+ t.is(response.data.length, testData.products.length);
+ }else{
+ t.is(response.data.length, config.productsPerPage);
+ }
+ t.pass();
+ resolve();
+ })
+ .catch((error) => {
+ reject(new Error('Should not be allowed'));
+ });
+ });
+});
+
+test('[Success] User Login', t => {
+ return new Promise((resolve, reject) => {
+ axios.post(`${baseUrl}/admin/login_action`, {
+ email: users[0].userEmail,
+ password: 'test'
+ })
+ .then((response) => {
+ t.deepEqual(response.data.message, 'Login successful');
+ resolve();
+ })
+ .catch((error) => {
+ reject(new Error('Should not be allowed'));
+ });
+ });
+});
+
+test('[Fail] Incorrect user password', t => {
+ return new Promise((resolve, reject) => {
+ axios.post(`${baseUrl}/admin/login_action`, {
+ email: users[0].userEmail,
+ password: 'test1'
+ })
+ .then((response) => {
+ reject(new Error('Should not be allowed'));
+ })
+ .catch((error) => {
+ t.deepEqual(error.response.data.message, 'Access denied. Check password and try again.');
+ resolve();
+ });
+ });
+});
+
+test('[Fail] Customer login with incorrect email', t => {
+ return new Promise((resolve, reject) => {
+ axios.post(`${baseUrl}/customer/login_action`, {
+ loginEmail: 'test1@test.com',
+ loginPassword: 'test'
+ })
+ .then((response) => {
+ reject(new Error('Should not be allowed'));
+ })
+ .catch((error) => {
+ t.deepEqual(error.response.data.err, 'A customer with that email does not exist.');
+ resolve();
+ });
+ });
+});
+
+test('[Success] Customer login with correct email', t => {
+ return new Promise((resolve, reject) => {
+ axios.post(`${baseUrl}/customer/login_action`, {
+ loginEmail: 'test@test.com',
+ loginPassword: 'test'
+ })
+ .then((response) => {
+ t.deepEqual(response.data.message, 'Successfully logged in');
+ resolve();
+ })
+ .catch((error) => {
+ reject(new Error('Should not be allowed'));
+ });
+ });
+});
+
+test('[Success] Add product to cart', t => {
+ return new Promise((resolve, reject) => {
+ axios.post(`${baseUrl}/product/addtocart`, {
+ productId: products[0]._id,
+ productQuantity: 1,
+ productOptions: JSON.stringify(products[0].productOptions)
+ })
+ .then((response) => {
+ t.deepEqual(response.data.message, 'Cart successfully updated');
+ resolve();
+ })
+ .catch((error) => {
+ reject(new Error('Should not be allowed'));
+ });
+ });
+});
+
+test('[Fail] Add incorrect product to cart', t => {
+ return new Promise((resolve, reject) => {
+ axios.post(`${baseUrl}/product/addtocart`, {
+ productId: 'someid'
+ })
+ .then((response) => {
+ t.deepEqual(response.data.message, 'Successfully logged in');
+ reject(new Error('Should not be allowed'));
+ resolve();
+ })
+ .catch((error) => {
+ t.deepEqual(error.response.data.message, 'Error updating cart. Please try again.');
+ resolve();
+ });
+ });
+});
diff --git a/views/login.hbs b/views/login.hbs
index d50f012..f834ad4 100644
--- a/views/login.hbs
+++ b/views/login.hbs
@@ -1,13 +1,13 @@