t.toUpperCase())}function emptyCart(){$.ajax({method:"POST",url:"/product/emptycart"}).done(function(t){showNotification(t.message,"success",!0),updateCartDiv()})}$(document).ready(function(){if($(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()),$("#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=$("#productsPerPage").val(),e=$("#totalProductCount").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/save",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("click",".product-add-to-cart",function(t){var a=getSelectedOptions();parseInt($("#product_quantity").val())<1&&$("#product_quantity").val(1),$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$("#productId").val(),productQuantity:$("#product_quantity").val(),productOptions:JSON.stringify(a),productComment:$("#product_comment").val()}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).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-options")?window.location=a:$.ajax({method:"POST",url:"/product/addtocart",data:{productId:$(this).attr("data-id")}}).done(function(t){showNotification(t.message,"success"),updateCartDiv()}).fail(function(t){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 s=$("#input_notify_message").val(),c=$("#input_notify_messageType").val();$("#input_notify_message").val(""),$("#input_notify_messageType").val(""),showNotification(s,c||"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 expiredClick 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
diff --git a/public/stylesheets/admin.css b/public/stylesheets/admin.css
index d17f633..981decd 100644
--- a/public/stylesheets/admin.css
+++ b/public/stylesheets/admin.css
@@ -244,8 +244,6 @@ body .popover {
[role="main"] {
padding-top: 20px;
margin-bottom: 20px;
- min-height: 100%;
- height: 100%;
}
@media (min-width: 768px) {
[role="main"] {
diff --git a/public/stylesheets/admin.min.css b/public/stylesheets/admin.min.css
index 54496ca..71dac10 100644
--- a/public/stylesheets/admin.min.css
+++ b/public/stylesheets/admin.min.css
@@ -1 +1 @@
-body,html{height:100%;background-color:#f8f9fa!important}.content-body{margin-bottom:0}.feather{width:16px;height:16px}.btn-outline-danger,.btn-outline-info,.btn-outline-primary,.btn-outline-success,.btn-outline-warning{background-color:#fff}.btn-outline-primary{color:#fff!important;background-color:#000;border-color:#000}.btn-outline-danger{color:#dc3545!important}.btn-outline-danger:hover{color:#fff!important}.has-error div,.has-error input,.has-error textarea{border-color:#cc4135}#frm_search,.search-bar-input,.search-bar-input .btn{padding-top:10px;height:45px}.footer{padding-top:20px}.admin-menu{padding-left:0}.admin-menu .list-group-item{border-bottom:none}.navbarMenuWrapper{background-color:#f5f5f5}.navbarMenu>ul>li>a:hover{color:#cc4135!important}.navbarMenu{padding-right:0;padding-left:0}.product-wrapper>a:hover{color:#cc4135!important}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{margin-bottom:0;height:100px!important}#navbar>.navbar-nav>li>a{padding-top:35px}.pagination>li>a{background-color:#cc4135!important}.admin-card{background-color:#fff!important;border-radius:5px;padding:15px;margin:10px;box-shadow:0 0 1px rgba(0,0,0,.12),0 1px 6px rgba(0,0,0,.03),0 6px 10px -8px rgba(0,0,0,.1)}.admin-card-body{padding:5px}body .popover{display:none!important}.navbar-brand{color:#cc4135!important;letter-spacing:4px;padding-left:20px!important;padding-top:0!important;height:80px!important;font-size:55px!important}.navbar-brand,.navbar-brand-image{height:80px;padding-left:10px;padding-top:10px}.navbar-default .badge{background-color:#cc4135}#empty-cart:active,#empty-cart:active:hover,#empty-cart:focus,#empty-cart:hover,.pushy-link:active,.pushy-link:active:hover,.pushy-link:focus,.pushy-link:hover{border-color:#cc4135;background-color:#cc4135}.navActive>a{margin-bottom:0;padding-top:15px;border-bottom:5px solid #cc4135}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{background-color:#fff}.navbar-default .navbar-nav>li>a{color:#838b8f;font-size:20px}.global-result-type{color:#8d8d8d}.global-result:hover{background-color:#007bff}.global-result:hover .global-result-detail,.global-result:hover .global-result-type,.global-result:hover .global-result-type .fal{color:#fff!important}.global-result a{text-decoration:none!important}.global-result:hover{cursor:pointer}.global-result:first-child{border-top-left-radius:0;border-top-right-radius:0}.global-result{border-left:0;border-right:0}.global-search-modal-content,.global-search-modal-header{background-color:transparent;border:none}#global-search-results{padding-right:0;border-bottom-left-radius:.3rem;border-bottom-right-radius:.3rem}.global-search-form{margin-bottom:0}#global-search-value{border-bottom-right-radius:0}.search-input-addon{border-bottom-left-radius:0}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:100;padding:0;background-color:#fff;box-shadow:inset -1px 0 0 rgba(0,0,0,.1)}.sidebar-sticky{position:relative;top:0;height:100vh;padding-top:15px;overflow-x:hidden;overflow-y:auto}@supports ((position:-webkit-sticky) or (position:sticky)){.sidebar-sticky{position:-webkit-sticky;position:sticky}}.sidebar .nav-link{font-weight:400;color:#333}.sidebar .nav-link .feather{margin-right:4px;color:#999}.sidebar .nav-link.active .feather,.sidebar .nav-link:hover .feather{color:inherit}.sidebar-heading{font-size:.75rem;text-transform:uppercase}.sidebar-brand{width:80%}.sidebar-search{text-align:center;width:20%}.sidebar-addon{height:40px}.sidebar-link{display:inline-block;width:80%}.sidebar-link-addon{display:inline-block;width:10%}[role=main]{padding-top:20px;margin-bottom:20px;min-height:100%;height:100%}@media (min-width:768px){[role=main]{padding-top:20px;padding-bottom:20px}}@media only screen and (max-width:768px){.navbar-default .navbar-brand{padding-top:10px}.navbar-default .navbar-nav>li>a{font-size:16px}.searchBarWrapper{padding-top:10px}.navbarMenuWrapper{padding-left:0;padding-right:0}.navbarMenuOuter{padding-left:0;padding-right:0}.navActive>a{color:#fff!important}.navbarMenu{padding-right:7.5px;padding-left:7.5px}.navActive>a{color:#fff!important;background-color:#cc4135;border-bottom:none}.footer{padding-top:10px}}
\ No newline at end of file
+body,html{height:100%;background-color:#f8f9fa!important}.content-body{margin-bottom:0}.feather{width:16px;height:16px}.btn-outline-danger,.btn-outline-info,.btn-outline-primary,.btn-outline-success,.btn-outline-warning{background-color:#fff}.btn-outline-primary{color:#fff!important;background-color:#000;border-color:#000}.btn-outline-danger{color:#dc3545!important}.btn-outline-danger:hover{color:#fff!important}.has-error div,.has-error input,.has-error textarea{border-color:#cc4135}#frm_search,.search-bar-input,.search-bar-input .btn{padding-top:10px;height:45px}.footer{padding-top:20px}.admin-menu{padding-left:0}.admin-menu .list-group-item{border-bottom:none}.navbarMenuWrapper{background-color:#f5f5f5}.navbarMenu>ul>li>a:hover{color:#cc4135!important}.navbarMenu{padding-right:0;padding-left:0}.product-wrapper>a:hover{color:#cc4135!important}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{margin-bottom:0;height:100px!important}#navbar>.navbar-nav>li>a{padding-top:35px}.pagination>li>a{background-color:#cc4135!important}.admin-card{background-color:#fff!important;border-radius:5px;padding:15px;margin:10px;box-shadow:0 0 1px rgba(0,0,0,.12),0 1px 6px rgba(0,0,0,.03),0 6px 10px -8px rgba(0,0,0,.1)}.admin-card-body{padding:5px}body .popover{display:none!important}.navbar-brand{color:#cc4135!important;letter-spacing:4px;padding-left:20px!important;padding-top:0!important;height:80px!important;font-size:55px!important}.navbar-brand,.navbar-brand-image{height:80px;padding-left:10px;padding-top:10px}.navbar-default .badge{background-color:#cc4135}#empty-cart:active,#empty-cart:active:hover,#empty-cart:focus,#empty-cart:hover,.pushy-link:active,.pushy-link:active:hover,.pushy-link:focus,.pushy-link:hover{border-color:#cc4135;background-color:#cc4135}.navActive>a{margin-bottom:0;padding-top:15px;border-bottom:5px solid #cc4135}#navbar,#navbar>.navbar-nav,#navbar>.navbar-nav>li>a,.navbar-header,.navbar-static-top{background-color:#fff}.navbar-default .navbar-nav>li>a{color:#838b8f;font-size:20px}.global-result-type{color:#8d8d8d}.global-result:hover{background-color:#007bff}.global-result:hover .global-result-detail,.global-result:hover .global-result-type,.global-result:hover .global-result-type .fal{color:#fff!important}.global-result a{text-decoration:none!important}.global-result:hover{cursor:pointer}.global-result:first-child{border-top-left-radius:0;border-top-right-radius:0}.global-result{border-left:0;border-right:0}.global-search-modal-content,.global-search-modal-header{background-color:transparent;border:none}#global-search-results{padding-right:0;border-bottom-left-radius:.3rem;border-bottom-right-radius:.3rem}.global-search-form{margin-bottom:0}#global-search-value{border-bottom-right-radius:0}.search-input-addon{border-bottom-left-radius:0}.sidebar{position:fixed;top:0;bottom:0;left:0;z-index:100;padding:0;background-color:#fff;box-shadow:inset -1px 0 0 rgba(0,0,0,.1)}.sidebar-sticky{position:relative;top:0;height:100vh;padding-top:15px;overflow-x:hidden;overflow-y:auto}@supports ((position:-webkit-sticky) or (position:sticky)){.sidebar-sticky{position:-webkit-sticky;position:sticky}}.sidebar .nav-link{font-weight:400;color:#333}.sidebar .nav-link .feather{margin-right:4px;color:#999}.sidebar .nav-link.active .feather,.sidebar .nav-link:hover .feather{color:inherit}.sidebar-heading{font-size:.75rem;text-transform:uppercase}.sidebar-brand{width:80%}.sidebar-search{text-align:center;width:20%}.sidebar-addon{height:40px}.sidebar-link{display:inline-block;width:80%}.sidebar-link-addon{display:inline-block;width:10%}[role=main]{padding-top:20px;margin-bottom:20px}@media (min-width:768px){[role=main]{padding-top:20px;padding-bottom:20px}}@media only screen and (max-width:768px){.navbar-default .navbar-brand{padding-top:10px}.navbar-default .navbar-nav>li>a{font-size:16px}.searchBarWrapper{padding-top:10px}.navbarMenuWrapper{padding-left:0;padding-right:0}.navbarMenuOuter{padding-left:0;padding-right:0}.navActive>a{color:#fff!important}.navbarMenu{padding-right:7.5px;padding-left:7.5px}.navActive>a{color:#fff!important;background-color:#cc4135;border-bottom:none}.footer{padding-top:10px}}
\ No newline at end of file
diff --git a/public/stylesheets/less/admin.less b/public/stylesheets/less/admin.less
index 247dcc2..0a985ae 100644
--- a/public/stylesheets/less/admin.less
+++ b/public/stylesheets/less/admin.less
@@ -283,8 +283,6 @@ body .popover{display:none !important; }
[role="main"] {
padding-top: 20px;
margin-bottom: 20px;
- min-height: 100%;
- height: 100%;
}
@media (min-width: 768px) {
diff --git a/routes/customer.js b/routes/customer.js
index cdb420f..131da13 100644
--- a/routes/customer.js
+++ b/routes/customer.js
@@ -3,7 +3,14 @@ const router = express.Router();
const colors = require('colors');
const randtoken = require('rand-token');
const bcrypt = require('bcryptjs');
-const common = require('../lib/common');
+const {
+ getId,
+ clearSessionValue,
+ getCountryList,
+ mongoSanitize,
+ sendEmail,
+ clearCustomer
+} = require('../lib/common');
const rateLimit = require('express-rate-limit');
const { indexCustomers } = require('../lib/indexing');
const { validateJson } = require('../lib/schema');
@@ -58,6 +65,7 @@ router.post('/customer/create', async (req, res) => {
// Set the customer into the session
req.session.customerPresent = true;
+ req.session.customerId = customerReturn._id;
req.session.customerEmail = customerReturn.email;
req.session.customerCompany = customerReturn.company;
req.session.customerFirstname = customerReturn.firstName;
@@ -118,11 +126,107 @@ router.post('/customer/save', async (req, res) => {
res.status(200).json(customerObj);
});
+// Get customer orders
+router.get('/customer/account', async (req, res) => {
+ const db = req.app.db;
+ const config = req.app.config;
+
+ if(!req.session.customerPresent){
+ res.redirect('/customer/login');
+ return;
+ }
+
+ const orders = await db.orders.find({
+ orderCustomer: getId(req.session.customerId)
+ })
+ .sort({ orderDate: -1 })
+ .toArray();
+ res.render(`${config.themeViews}customer-account`, {
+ title: 'Orders',
+ session: req.session,
+ orders,
+ message: clearSessionValue(req.session, 'message'),
+ messageType: clearSessionValue(req.session, 'messageType'),
+ countryList: getCountryList(),
+ config: req.app.config,
+ helpers: req.handlebars.helpers
+ });
+});
+
+// Update a customer
+router.post('/customer/update', async (req, res) => {
+ const db = req.app.db;
+
+ if(!req.session.customerPresent){
+ res.redirect('/customer/login');
+ return;
+ }
+
+ const customerObj = {
+ company: req.body.company,
+ email: req.body.email,
+ firstName: req.body.firstName,
+ lastName: req.body.lastName,
+ address1: req.body.address1,
+ address2: req.body.address2,
+ country: req.body.country,
+ state: req.body.state,
+ postcode: req.body.postcode,
+ phone: req.body.phone
+ };
+
+ const schemaResult = validateJson('editCustomer', customerObj);
+ if(!schemaResult.result){
+ console.log('errors', schemaResult.errors);
+ res.status(400).json(schemaResult.errors);
+ return;
+ }
+
+ // check for existing customer
+ const customer = await db.customers.findOne({ _id: getId(req.session.customerId) });
+ if(!customer){
+ res.status(400).json({
+ message: 'Customer not found'
+ });
+ return;
+ }
+ // Update customer
+ try{
+ const updatedCustomer = await db.customers.findOneAndUpdate(
+ { _id: getId(req.session.customerId) },
+ {
+ $set: customerObj
+ }, { multi: false, returnOriginal: false }
+ );
+ indexCustomers(req.app)
+ .then(() => {
+ // Set the customer into the session
+ req.session.customerEmail = customerObj.email;
+ req.session.customerCompany = customerObj.company;
+ req.session.customerFirstname = customerObj.firstName;
+ req.session.customerLastname = customerObj.lastName;
+ req.session.customerAddress1 = customerObj.address1;
+ req.session.customerAddress2 = customerObj.address2;
+ req.session.customerCountry = customerObj.country;
+ req.session.customerState = customerObj.state;
+ req.session.customerPostcode = customerObj.postcode;
+ req.session.customerPhone = customerObj.phone;
+ req.session.orderComment = req.body.orderComment;
+
+ res.status(200).json({ message: 'Customer updated', customer: updatedCustomer.value });
+ });
+ }catch(ex){
+ console.error(colors.red('Failed updating customer: ' + ex));
+ res.status(400).json({ message: 'Failed to update customer' });
+ }
+});
+
// Update a customer
router.post('/admin/customer/update', restrict, async (req, res) => {
const db = req.app.db;
const customerObj = {
+ company: req.body.company,
email: req.body.email,
firstName: req.body.firstName,
lastName: req.body.lastName,
@@ -145,7 +249,7 @@ router.post('/admin/customer/update', restrict, async (req, res) => {
}
// check for existing customer
- const customer = await db.customers.findOne({ _id: common.getId(req.body.customerId) });
+ const customer = await db.customers.findOne({ _id: getId(req.body.customerId) });
if(!customer){
res.status(400).json({
message: 'Customer not found'
@@ -155,7 +259,7 @@ router.post('/admin/customer/update', restrict, async (req, res) => {
// Update customer
try{
const updatedCustomer = await db.customers.findOneAndUpdate(
- { _id: common.getId(req.body.customerId) },
+ { _id: getId(req.body.customerId) },
{
$set: customerObj
}, { multi: false, returnOriginal: false }
@@ -177,7 +281,7 @@ router.delete('/admin/customer', restrict, async (req, res) => {
const db = req.app.db;
// check for existing customer
- const customer = await db.customers.findOne({ _id: common.getId(req.body.customerId) });
+ const customer = await db.customers.findOne({ _id: getId(req.body.customerId) });
if(!customer){
res.status(400).json({
message: 'Failed to delete customer. Customer not found'
@@ -186,7 +290,7 @@ router.delete('/admin/customer', restrict, async (req, res) => {
}
// Update customer
try{
- await db.customers.deleteOne({ _id: common.getId(req.body.customerId) });
+ await db.customers.deleteOne({ _id: getId(req.body.customerId) });
indexCustomers(req.app)
.then(() => {
res.status(200).json({ message: 'Customer deleted' });
@@ -201,7 +305,7 @@ router.delete('/admin/customer', restrict, async (req, res) => {
router.get('/admin/customer/view/:id?', restrict, async (req, res) => {
const db = req.app.db;
- const customer = await db.customers.findOne({ _id: common.getId(req.params.id) });
+ const customer = await db.customers.findOne({ _id: getId(req.params.id) });
if(!customer){
// If API request, return json
@@ -223,9 +327,9 @@ router.get('/admin/customer/view/:id?', restrict, async (req, res) => {
result: customer,
admin: true,
session: req.session,
- message: common.clearSessionValue(req.session, 'message'),
- messageType: common.clearSessionValue(req.session, 'messageType'),
- countryList: common.getCountryList(),
+ message: clearSessionValue(req.session, 'message'),
+ messageType: clearSessionValue(req.session, 'messageType'),
+ countryList: getCountryList(),
config: req.app.config,
editor: true,
helpers: req.handlebars.helpers
@@ -249,8 +353,8 @@ router.get('/admin/customers', restrict, async (req, res) => {
customers: customers,
session: req.session,
helpers: req.handlebars.helpers,
- message: common.clearSessionValue(req.session, 'message'),
- messageType: common.clearSessionValue(req.session, 'messageType'),
+ message: clearSessionValue(req.session, 'message'),
+ messageType: clearSessionValue(req.session, 'messageType'),
config: req.app.config
});
});
@@ -263,7 +367,7 @@ router.get('/admin/customers/filter/:search', restrict, async (req, res, next) =
const lunrIdArray = [];
customersIndex.search(searchTerm).forEach((id) => {
- lunrIdArray.push(common.getId(id.ref));
+ lunrIdArray.push(getId(id.ref));
});
// we search on the lunr indexes
@@ -283,8 +387,8 @@ router.get('/admin/customers/filter/:search', restrict, async (req, res, next) =
config: req.app.config,
session: req.session,
searchTerm: searchTerm,
- message: common.clearSessionValue(req.session, 'message'),
- messageType: common.clearSessionValue(req.session, 'messageType'),
+ message: clearSessionValue(req.session, 'message'),
+ messageType: clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers
});
});
@@ -298,6 +402,7 @@ router.post('/admin/customer/lookup', restrict, async (req, res, next) => {
if(customer){
req.session.customerPresent = true;
+ req.session.customerId = customer._id;
req.session.customerEmail = customer.email;
req.session.customerCompany = customer.company;
req.session.customerFirstname = customer.firstName;
@@ -319,11 +424,24 @@ router.post('/admin/customer/lookup', restrict, async (req, res, next) => {
});
});
+router.get('/customer/login', async (req, res, next) => {
+ const config = req.app.config;
+
+ res.render(`${config.themeViews}customer-login`, {
+ title: 'Customer login',
+ config: req.app.config,
+ session: req.session,
+ message: clearSessionValue(req.session, 'message'),
+ messageType: clearSessionValue(req.session, 'messageType'),
+ helpers: req.handlebars.helpers
+ });
+});
+
// login the customer and check the password
router.post('/customer/login_action', async (req, res) => {
const db = req.app.db;
- const customer = await db.customers.findOne({ email: common.mongoSanitize(req.body.loginEmail) });
+ const customer = await db.customers.findOne({ email: mongoSanitize(req.body.loginEmail) });
// check if customer exists with that email
if(customer === undefined || customer === null){
res.status(400).json({
@@ -344,6 +462,7 @@ router.post('/customer/login_action', async (req, res) => {
// Customer login successful
req.session.customerPresent = true;
+ req.session.customerId = customer._id;
req.session.customerEmail = customer.email;
req.session.customerCompany = customer.company;
req.session.customerFirstname = customer.firstName;
@@ -375,8 +494,8 @@ router.get('/customer/forgotten', (req, res) => {
forgotType: 'customer',
config: req.app.config,
helpers: req.handlebars.helpers,
- message: common.clearSessionValue(req.session, 'message'),
- messageType: common.clearSessionValue(req.session, 'messageType'),
+ message: clearSessionValue(req.session, 'message'),
+ messageType: clearSessionValue(req.session, 'messageType'),
showFooter: 'showFooter'
});
});
@@ -411,7 +530,7 @@ router.post('/customer/forgotten_action', apiLimiter, async (req, res) => {
// send the email with token to the user
// TODO: Should fix this to properly handle result
- common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body);
+ sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body);
res.status(200).json({
message: 'If your account exists, a password reset has been sent to your email'
});
@@ -441,8 +560,8 @@ router.get('/customer/reset/:token', async (req, res) => {
token: req.params.token,
route: 'customer',
config: req.app.config,
- message: common.clearSessionValue(req.session, 'message'),
- message_type: common.clearSessionValue(req.session, 'message_type'),
+ message: clearSessionValue(req.session, 'message'),
+ message_type: clearSessionValue(req.session, 'message_type'),
show_footer: 'show_footer',
helpers: req.handlebars.helpers
});
@@ -471,7 +590,7 @@ router.post('/customer/reset/:token', async (req, res) => {
};
// TODO: Should fix this to properly handle result
- common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body);
+ sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body);
req.session.message = 'Password successfully updated';
req.session.message_type = 'success';
return res.redirect('/checkout/payment');
@@ -486,8 +605,15 @@ router.post('/customer/reset/:token', async (req, res) => {
// logout the customer
router.post('/customer/logout', (req, res) => {
// Clear our session
- common.clearCustomer(req);
+ clearCustomer(req);
res.status(200).json({});
});
+// logout the customer
+router.get('/customer/logout', (req, res) => {
+ // Clear our session
+ clearCustomer(req);
+ res.redirect('/customer/login');
+});
+
module.exports = router;
diff --git a/routes/payments/adyen.js b/routes/payments/adyen.js
index a4e6b34..4b385fd 100644
--- a/routes/payments/adyen.js
+++ b/routes/payments/adyen.js
@@ -80,6 +80,7 @@ router.post('/checkout_action', async (req, res, next) => {
orderShipping: req.session.totalCartShipping,
orderItemCount: req.session.totalCartItems,
orderProductCount: req.session.totalCartProducts,
+ orderCustomer: common.getId(req.session.customerId),
orderEmail: req.session.customerEmail,
orderCompany: req.session.customerCompany,
orderFirstname: req.session.customerFirstname,
diff --git a/routes/payments/authorizenet.js b/routes/payments/authorizenet.js
index ef39907..9c150ee 100644
--- a/routes/payments/authorizenet.js
+++ b/routes/payments/authorizenet.js
@@ -63,6 +63,7 @@ router.post('/checkout_action', (req, res, next) => {
orderShipping: req.session.totalCartShipping,
orderItemCount: req.session.totalCartItems,
orderProductCount: req.session.totalCartProducts,
+ orderCustomer: common.getId(req.session.customerId),
orderEmail: req.session.customerEmail,
orderCompany: req.session.customerCompany,
orderFirstname: req.session.customerFirstname,
diff --git a/routes/payments/blockonomics.js b/routes/payments/blockonomics.js
index c889479..59b0633 100644
--- a/routes/payments/blockonomics.js
+++ b/routes/payments/blockonomics.js
@@ -94,6 +94,7 @@ router.post('/checkout_action', (req, res, next) => {
orderShipping: req.session.totalCartShipping,
orderItemCount: req.session.totalCartItems,
orderProductCount: req.session.totalCartProducts,
+ orderCustomer: common.getId(req.session.customerId),
orderEmail: req.session.customerEmail,
orderCompany: req.session.customerCompany,
orderFirstname: req.session.customerFirstname,
diff --git a/routes/payments/instore.js b/routes/payments/instore.js
index 2d767ea..b29feae 100644
--- a/routes/payments/instore.js
+++ b/routes/payments/instore.js
@@ -17,6 +17,7 @@ router.post('/checkout_action', async (req, res, next) => {
orderShipping: 0,
orderItemCount: req.session.totalCartItems,
orderProductCount: req.session.totalCartProducts,
+ orderCustomer: common.getId(req.session.customerId),
orderEmail: req.session.customerEmail,
orderCompany: req.session.customerCompany,
orderFirstname: req.session.customerFirstname,
diff --git a/routes/payments/paypal.js b/routes/payments/paypal.js
index f812cac..7f7d99c 100644
--- a/routes/payments/paypal.js
+++ b/routes/payments/paypal.js
@@ -166,6 +166,7 @@ router.post('/checkout_action', (req, res, next) => {
orderShipping: req.session.totalCartShipping,
orderItemCount: req.session.totalCartItems,
orderProductCount: req.session.totalCartProducts,
+ orderCustomer: common.getId(req.session.customerId),
orderEmail: req.session.customerEmail,
orderCompany: req.session.customerCompany,
orderFirstname: req.session.customerFirstname,
diff --git a/routes/payments/stripe.js b/routes/payments/stripe.js
index 8eb05b8..c47d16d 100644
--- a/routes/payments/stripe.js
+++ b/routes/payments/stripe.js
@@ -56,6 +56,7 @@ router.post('/checkout_action', (req, res, next) => {
orderShipping: req.session.totalCartShipping,
orderItemCount: req.session.totalCartItems,
orderProductCount: req.session.totalCartProducts,
+ orderCustomer: common.getId(req.session.customerId),
orderEmail: req.session.customerEmail,
orderCompany: req.session.customerCompany,
orderFirstname: req.session.customerFirstname,
diff --git a/test/specs/customers.js b/test/specs/customers.js
index 7763ade..8154896 100644
--- a/test/specs/customers.js
+++ b/test/specs/customers.js
@@ -78,9 +78,10 @@ test('[Fail] Create with invalid email address', async t => {
t.deepEqual(res.body[0].message, 'should match format "emailAddress"');
});
-test('[Success] Update existing customer', async t => {
+test('[Success] Update existing customer from dashboard', async t => {
const customer = {
customerId: g.customers[1]._id,
+ company: 'Acme Co',
email: 'sarah.jones@test.com',
firstName: 'Sarah',
lastName: 'Jones',
@@ -99,6 +100,47 @@ test('[Success] Update existing customer', async t => {
.expect(200);
t.deepEqual(res.body.message, 'Customer updated');
+ t.deepEqual(res.body.customer.company, customer.company);
+ t.deepEqual(res.body.customer.email, customer.email);
+ t.deepEqual(res.body.customer.firstName, customer.firstName);
+ t.deepEqual(res.body.customer.lastName, customer.lastName);
+ t.deepEqual(res.body.customer.address1, customer.address1);
+ t.deepEqual(res.body.customer.country, customer.country);
+ t.deepEqual(res.body.customer.state, customer.state);
+ t.deepEqual(res.body.customer.postcode, customer.postcode);
+ t.deepEqual(res.body.customer.phone, customer.phone);
+});
+
+test('[Success] Update existing customer from customer page', async t => {
+ const customer = {
+ customerId: g.customers[1]._id,
+ company: 'Acme Company',
+ email: 'sarah.jones@test.com',
+ firstName: 'Tina',
+ lastName: 'Smith',
+ address1: '2 Sydney Street',
+ address2: '',
+ country: 'Australia',
+ state: 'NSW',
+ postcode: '2000',
+ phone: '0444444444'
+ };
+
+ await g.request
+ .post('/customer/login_action')
+ .send({
+ loginEmail: 'sarah.jones@test.com',
+ loginPassword: 'test'
+ })
+ .expect(200);
+
+ const res = await g.request
+ .post('/customer/update')
+ .send(customer)
+ .expect(200);
+
+ t.deepEqual(res.body.message, 'Customer updated');
+ t.deepEqual(res.body.customer.company, customer.company);
t.deepEqual(res.body.customer.email, customer.email);
t.deepEqual(res.body.customer.firstName, customer.firstName);
t.deepEqual(res.body.customer.lastName, customer.lastName);
diff --git a/views/layouts/layout.hbs b/views/layouts/layout.hbs
index cd80b03..7592b5b 100644
--- a/views/layouts/layout.hbs
+++ b/views/layouts/layout.hbs
@@ -185,6 +185,19 @@