Added support for returning customers
							parent
							
								
									3730f84796
								
							
						
					
					
						commit
						6076455d06
					
				
							
								
								
									
										1
									
								
								app.js
								
								
								
								
							
							
						
						
									
										1
									
								
								app.js
								
								
								
								
							|  | @ -288,6 +288,7 @@ MongoClient.connect(config.databaseConnectionString, {}, (err, client) => { | ||||||
|     db.orders = db.collection('orders'); |     db.orders = db.collection('orders'); | ||||||
|     db.pages = db.collection('pages'); |     db.pages = db.collection('pages'); | ||||||
|     db.menu = db.collection('menu'); |     db.menu = db.collection('menu'); | ||||||
|  |     db.customers = db.collection('customers'); | ||||||
| 
 | 
 | ||||||
|     // add db to app for routes
 |     // add db to app for routes
 | ||||||
|     app.db = db; |     app.db = db; | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ | ||||||
|     "nodemailer": "^4.4.1", |     "nodemailer": "^4.4.1", | ||||||
|     "numeral": "^2.0.6", |     "numeral": "^2.0.6", | ||||||
|     "paypal-rest-sdk": "^1.6.9", |     "paypal-rest-sdk": "^1.6.9", | ||||||
|  |     "rand-token": "^0.4.0", | ||||||
|     "rimraf": "^2.6.2", |     "rimraf": "^2.6.2", | ||||||
|     "sitemap": "^1.6.0", |     "sitemap": "^1.6.0", | ||||||
|     "stripe": "^5.4.0", |     "stripe": "^5.4.0", | ||||||
|  |  | ||||||
|  | @ -294,6 +294,79 @@ $(document).ready(function (){ | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     $('#customerLogout').on('click', function(e){ | ||||||
|  |         $.ajax({ | ||||||
|  |             method: 'POST', | ||||||
|  |             url: '/customer/logout', | ||||||
|  |             data: {} | ||||||
|  |         }) | ||||||
|  |         .done(function(msg){ | ||||||
|  |             location.reload(); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     $('#createCustomerAccount').validator().on('click', function(e){ | ||||||
|  |         e.preventDefault(); | ||||||
|  |         if($('#shipping-form').validator('validate').has('.has-error').length === 0){ | ||||||
|  |             $.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(msg){ | ||||||
|  |                 // Just reload to fill in the form from session
 | ||||||
|  |                 location.reload(); | ||||||
|  |             }) | ||||||
|  |             .fail(function(msg){ | ||||||
|  |                 showNotification(msg.responseJSON.err, 'danger'); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     // call update settings API
 | ||||||
|  |     $('#customerLogin').on('click', function(e){ | ||||||
|  |         if(!e.isDefaultPrevented()){ | ||||||
|  |             e.preventDefault(); | ||||||
|  |             $.ajax({ | ||||||
|  |                 method: 'POST', | ||||||
|  |                 url: '/customer/login_action', | ||||||
|  |                 data: { | ||||||
|  |                     loginEmail: $('#customerLoginEmail').val(), | ||||||
|  |                     loginPassword: $('#customerLoginPassword').val() | ||||||
|  |                 } | ||||||
|  |             }) | ||||||
|  |             .done(function(msg){ | ||||||
|  |                 var customer = msg.customer; | ||||||
|  |                 // Fill in customer form
 | ||||||
|  |                 $('#shipEmail').val(customer.email); | ||||||
|  |                 $('#shipFirstname').val(customer.firstName); | ||||||
|  |                 $('#shipLastname').val(customer.lastName); | ||||||
|  |                 $('#shipAddr1').val(customer.address1); | ||||||
|  |                 $('#shipAddr2').val(customer.address2); | ||||||
|  |                 $('#shipCountry').val(customer.country); | ||||||
|  |                 $('#shipState').val(customer.state); | ||||||
|  |                 $('#shipPostcode').val(customer.postcode); | ||||||
|  |                 $('#shipPhoneNumber').val(customer.phone); | ||||||
|  |                 location.reload(); | ||||||
|  |             }) | ||||||
|  |             .fail(function(msg){ | ||||||
|  |                 showNotification(msg.responseJSON.err, 'danger'); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         e.preventDefault(); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|     $(document).on('click', '.image-next', function(e){ |     $(document).on('click', '.image-next', function(e){ | ||||||
|         var thumbnails = $('.thumbnail-image'); |         var thumbnails = $('.thumbnail-image'); | ||||||
|         var index = 0; |         var index = 0; | ||||||
|  | @ -491,21 +564,20 @@ $(document).ready(function (){ | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|  |     // applies an product filter
 | ||||||
|  |     $(document).on('click', '#btn_customer_filter', function(e){ | ||||||
|  |         if($('#customer_filter').val() !== ''){ | ||||||
|  |             window.location.href = '/admin/customers/filter/' + $('#customer_filter').val(); | ||||||
|  |         }else{ | ||||||
|  |             showNotification('Please enter a keyword to filter', 'danger'); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|     // resets the order filter
 |     // resets the order filter
 | ||||||
|     $(document).on('click', '#btn_search_reset', function(e){ |     $(document).on('click', '#btn_search_reset', function(e){ | ||||||
|         window.location.replace('/'); |         window.location.replace('/'); | ||||||
|     }); |     }); | ||||||
| 
 | 
 | ||||||
|     // resets the product filter
 |  | ||||||
|     $(document).on('click', '#btn_product_reset', function(e){ |  | ||||||
|         window.location.href = '/admin/products'; |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
| 	// resets the order filter
 |  | ||||||
|     $(document).on('click', '#btn_order_reset', function(e){ |  | ||||||
|         window.location.href = '/admin/orders'; |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     // search button click event
 |     // search button click event
 | ||||||
|     $(document).on('click', '#btn_search', function(e){ |     $(document).on('click', '#btn_search', function(e){ | ||||||
|         e.preventDefault(); |         e.preventDefault(); | ||||||
|  |  | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -6,59 +6,93 @@ | ||||||
|         <div class="col-md-5"> |         <div class="col-md-5"> | ||||||
|             <div class="panel panel-default" style="margin-top: 30px;"> |             <div class="panel panel-default" style="margin-top: 30px;"> | ||||||
|                 <div class="panel-heading">Customer details</div> |                 <div class="panel-heading">Customer details</div> | ||||||
|  |                 {{#unless session.customer}} | ||||||
|  |                 <div class="panel-body customer-details-login"> | ||||||
|  |                     <p>Existing customer</p> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <input type="email" class="form-control" id="customerLoginEmail" name="loginEmail" minlength="5" placeholder="Email address" required> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <input type="password" class="form-control" id="customerLoginPassword" name="loginPassword" minlength="5" placeholder="Password" required> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <a href="/customer/forgotten" class="btn btn-default pull-left">Forgotten</a> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <button id="customerLogin" class="btn btn-success pull-right" type="submit">Login</button> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 {{/unless}} | ||||||
|                 <div class="panel-body customer-details"> |                 <div class="panel-body customer-details"> | ||||||
|  |                     {{#if session.customer}} | ||||||
|  |                     <div class="col-xs-12 col-md-12"> | ||||||
|  |                         <button id="customerLogout" class="btn btn-sm btn-success pull-right">Change customer</button> | ||||||
|  |                     </div> | ||||||
|  |                     {{/if}} | ||||||
|                     <form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false"> |                     <form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false"> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" required> |                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" value="{{session.customer.email}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-6"> |                         <div class="col-xs-12 col-md-6"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" required> |                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" value="{{session.customer.firstName}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-6"> |                         <div class="col-xs-12 col-md-6"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" required> |                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" value="{{session.customer.lastName}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" required> |                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" value="{{session.customer.address1}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)"> |                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)" value="{{session.customer.address1}}"> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-4"> |                         <div class="col-xs-12 col-md-4"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" required> |                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" value="{{session.customer.country}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-4"> |                         <div class="col-xs-12 col-md-4"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" required> |                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" value="{{session.customer.state}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-4"> |                         <div class="col-xs-12 col-md-4"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="number" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" required> |                                 <input type="text" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" value="{{session.customer.postcode}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number (optional)"> |                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number" value="{{session.customer.phone}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|  |                         {{#if session.customer}} | ||||||
|                         {{#ifCond config.paymentGateway '==' 'paypal'}} |                         {{#ifCond config.paymentGateway '==' 'paypal'}} | ||||||
|                         <div class="paypal_button col-xs-12 col-md-12 text-center"> |                         <div class="paypal_button col-xs-12 col-md-12 text-center"> | ||||||
|                             <button id="checkout_paypal" class="btn btn-success" type="submit"><i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i> Pay with PayPal <i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i></button> |                             <button id="checkout_paypal" class="btn btn-success" type="submit"><i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i> Pay with PayPal <i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i></button> | ||||||
|                         </div> |                         </div> | ||||||
|                         {{/ifCond}} |                         {{/ifCond}} | ||||||
|  |                         {{/if}} | ||||||
|  |                         {{#unless session.customer}} | ||||||
|  |                         <div class="col-xs-12 col-md-12"> | ||||||
|  |                             <p class="text-muted">Enter a password to create an account for next time</p> | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <input type="password" class="form-control customerDetails" id="newCustomerPassword" name="newCustomerPassword" placeholder="Password" required> | ||||||
|  |                             </div> | ||||||
|  |                             <a id="createCustomerAccount" class="btn btn-success pull-right">Create account</a> | ||||||
|  |                         </div> | ||||||
|  |                         {{/unless}} | ||||||
|                     </form> |                     </form> | ||||||
|  |                     {{#if session.customer}} | ||||||
|                     {{#ifCond config.paymentGateway '==' 'stripe'}} |                     {{#ifCond config.paymentGateway '==' 'stripe'}} | ||||||
|                     <div class="col-xs-12 col-md-12 text-center"> |                     <div class="col-xs-12 col-md-12 text-center"> | ||||||
|                         <form method="POST" id="payment-form"> |                         <form method="POST" id="payment-form"> | ||||||
|  | @ -82,6 +116,8 @@ | ||||||
|                         </form> |                         </form> | ||||||
|                     </div> |                     </div> | ||||||
|                     {{/ifCond}} |                     {{/ifCond}} | ||||||
|  |                     {{/if}} | ||||||
|  | 
 | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
							
								
								
									
										138
									
								
								routes/admin.js
								
								
								
								
							
							
						
						
									
										138
									
								
								routes/admin.js
								
								
								
								
							|  | @ -13,7 +13,7 @@ router.get('/', common.restrict, (req, res, next) => { | ||||||
| 
 | 
 | ||||||
| // Admin section
 | // Admin section
 | ||||||
| router.get('/orders', common.restrict, (req, res, next) => { | router.get('/orders', common.restrict, (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     // Top 10 products
 |     // Top 10 products
 | ||||||
|     common.dbQuery(db.orders, {}, {'orderDate': -1}, 10, (err, orders) => { |     common.dbQuery(db.orders, {}, {'orderDate': -1}, 10, (err, orders) => { | ||||||
|  | @ -35,7 +35,7 @@ router.get('/orders', common.restrict, (req, res, next) => { | ||||||
| 
 | 
 | ||||||
| // Admin section
 | // Admin section
 | ||||||
| router.get('/orders/bystatus/:orderstatus', common.restrict, (req, res, next) => { | router.get('/orders/bystatus/:orderstatus', common.restrict, (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     if(typeof req.params.orderstatus === 'undefined'){ |     if(typeof req.params.orderstatus === 'undefined'){ | ||||||
|         res.redirect('/admin/orders'); |         res.redirect('/admin/orders'); | ||||||
|  | @ -65,7 +65,7 @@ router.get('/orders/bystatus/:orderstatus', common.restrict, (req, res, next) => | ||||||
| 
 | 
 | ||||||
| // render the editor
 | // render the editor
 | ||||||
| router.get('/order/view/:id', common.restrict, (req, res) => { | router.get('/order/view/:id', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     db.orders.findOne({_id: common.getId(req.params.id)}, (err, result) => { |     db.orders.findOne({_id: common.getId(req.params.id)}, (err, result) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             console.info(err.stack); |             console.info(err.stack); | ||||||
|  | @ -91,7 +91,7 @@ router.get('/order/view/:id', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // Admin section
 | // Admin section
 | ||||||
| router.get('/orders/filter/:search', common.restrict, (req, res, next) => { | router.get('/orders/filter/:search', common.restrict, (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let searchTerm = req.params.search; |     let searchTerm = req.params.search; | ||||||
|     let ordersIndex = req.app.ordersIndex; |     let ordersIndex = req.app.ordersIndex; | ||||||
| 
 | 
 | ||||||
|  | @ -121,7 +121,7 @@ router.get('/orders/filter/:search', common.restrict, (req, res, next) => { | ||||||
| 
 | 
 | ||||||
| // order product
 | // order product
 | ||||||
| router.get('/order/delete/:id', common.restrict, (req, res) => { | router.get('/order/delete/:id', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     // remove the article
 |     // remove the article
 | ||||||
|     db.orders.remove({_id: common.getId(req.params.id)}, {}, (err, numRemoved) => { |     db.orders.remove({_id: common.getId(req.params.id)}, {}, (err, numRemoved) => { | ||||||
|  | @ -141,7 +141,7 @@ router.get('/order/delete/:id', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // update order status
 | // update order status
 | ||||||
| router.post('/order/statusupdate', common.restrict, (req, res) => { | router.post('/order/statusupdate', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     db.orders.update({_id: common.getId(req.body.order_id)}, {$set: {orderStatus: req.body.status}}, {multi: false}, (err, numReplaced) => { |     db.orders.update({_id: common.getId(req.body.order_id)}, {$set: {orderStatus: req.body.status}}, {multi: false}, (err, numReplaced) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             console.info(err.stack); |             console.info(err.stack); | ||||||
|  | @ -152,7 +152,7 @@ router.post('/order/statusupdate', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // Admin section
 | // Admin section
 | ||||||
| router.get('/products', common.restrict, (req, res, next) => { | router.get('/products', common.restrict, (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     // get the top results
 |     // get the top results
 | ||||||
|     common.dbQuery(db.products, {}, {'productAddedDate': -1}, 10, (err, topResults) => { |     common.dbQuery(db.products, {}, {'productAddedDate': -1}, 10, (err, topResults) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|  | @ -173,7 +173,7 @@ router.get('/products', common.restrict, (req, res, next) => { | ||||||
| 
 | 
 | ||||||
| // Admin section
 | // Admin section
 | ||||||
| router.post('/product/addtocart', (req, res, next) => { | router.post('/product/addtocart', (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let productQuantity = req.body.productQuantity ? parseInt(req.body.productQuantity) : 1; |     let productQuantity = req.body.productQuantity ? parseInt(req.body.productQuantity) : 1; | ||||||
| 
 | 
 | ||||||
|     // setup cart object if it doesn't exist
 |     // setup cart object if it doesn't exist
 | ||||||
|  | @ -240,7 +240,7 @@ router.post('/product/addtocart', (req, res, next) => { | ||||||
| 
 | 
 | ||||||
| // Updates a single product quantity
 | // Updates a single product quantity
 | ||||||
| router.post('/product/updatecart', (req, res, next) => { | router.post('/product/updatecart', (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let cartItems = JSON.parse(req.body.items); |     let cartItems = JSON.parse(req.body.items); | ||||||
|     let hasError = false; |     let hasError = false; | ||||||
| 
 | 
 | ||||||
|  | @ -310,7 +310,7 @@ router.post('/product/emptycart', (req, res, next) => { | ||||||
| 
 | 
 | ||||||
| // Admin section
 | // Admin section
 | ||||||
| router.get('/products/filter/:search', common.restrict, (req, res, next) => { | router.get('/products/filter/:search', common.restrict, (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let searchTerm = req.params.search; |     let searchTerm = req.params.search; | ||||||
|     let productsIndex = req.app.productsIndex; |     let productsIndex = req.app.productsIndex; | ||||||
| 
 | 
 | ||||||
|  | @ -358,7 +358,7 @@ router.get('/product/new', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // insert new product form action
 | // insert new product form action
 | ||||||
| router.post('/product/insert', common.restrict, (req, res) => { | router.post('/product/insert', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     let doc = { |     let doc = { | ||||||
|         productPermalink: req.body.frmProductPermalink, |         productPermalink: req.body.frmProductPermalink, | ||||||
|  | @ -429,7 +429,7 @@ router.post('/product/insert', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // render the editor
 | // render the editor
 | ||||||
| router.get('/product/edit/:id', common.restrict, (req, res) => { | router.get('/product/edit/:id', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     common.getImages(req.params.id, req, res, (images) => { |     common.getImages(req.params.id, req, res, (images) => { | ||||||
|         db.products.findOne({_id: common.getId(req.params.id)}, (err, result) => { |         db.products.findOne({_id: common.getId(req.params.id)}, (err, result) => { | ||||||
|  | @ -460,7 +460,7 @@ router.get('/product/edit/:id', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // Update an existing product form action
 | // Update an existing product form action
 | ||||||
| router.post('/product/update', common.restrict, (req, res) => { | router.post('/product/update', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     db.products.findOne({_id: common.getId(req.body.frmProductId)}, (err, product) => { |     db.products.findOne({_id: common.getId(req.body.frmProductId)}, (err, product) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|  | @ -540,7 +540,7 @@ router.post('/product/update', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // delete product
 | // delete product
 | ||||||
| router.get('/product/delete/:id', common.restrict, (req, res) => { | router.get('/product/delete/:id', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let rimraf = require('rimraf'); |     let rimraf = require('rimraf'); | ||||||
| 
 | 
 | ||||||
|     // remove the article
 |     // remove the article
 | ||||||
|  | @ -568,7 +568,7 @@ router.get('/product/delete/:id', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // users
 | // users
 | ||||||
| router.get('/users', common.restrict, (req, res) => { | router.get('/users', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     db.users.find({}).toArray((err, users) => { |     db.users.find({}).toArray((err, users) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             console.info(err.stack); |             console.info(err.stack); | ||||||
|  | @ -589,7 +589,7 @@ router.get('/users', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // edit user
 | // edit user
 | ||||||
| router.get('/user/edit/:id', common.restrict, (req, res) => { | router.get('/user/edit/:id', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     db.users.findOne({_id: common.getId(req.params.id)}, (err, user) => { |     db.users.findOne({_id: common.getId(req.params.id)}, (err, user) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             console.info(err.stack); |             console.info(err.stack); | ||||||
|  | @ -618,7 +618,7 @@ router.get('/user/edit/:id', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // update a user
 | // update a user
 | ||||||
| router.post('/user/update', common.restrict, (req, res) => { | router.post('/user/update', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let bcrypt = req.bcrypt; |     let bcrypt = req.bcrypt; | ||||||
| 
 | 
 | ||||||
|     let isAdmin = req.body.user_admin === 'on' ? 'true' : 'false'; |     let isAdmin = req.body.user_admin === 'on' ? 'true' : 'false'; | ||||||
|  | @ -666,7 +666,7 @@ router.post('/user/update', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // insert a user
 | // insert a user
 | ||||||
| router.post('/setup_action', (req, res) => { | router.post('/setup_action', (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let bcrypt = req.bcrypt; |     let bcrypt = req.bcrypt; | ||||||
| 
 | 
 | ||||||
|     let doc = { |     let doc = { | ||||||
|  | @ -704,7 +704,7 @@ router.post('/setup_action', (req, res) => { | ||||||
| 
 | 
 | ||||||
| // insert a user
 | // insert a user
 | ||||||
| router.post('/user/insert', common.restrict, (req, res) => { | router.post('/user/insert', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let bcrypt = req.bcrypt; |     let bcrypt = req.bcrypt; | ||||||
|     let url = require('url'); |     let url = require('url'); | ||||||
| 
 | 
 | ||||||
|  | @ -765,6 +765,79 @@ router.post('/user/insert', common.restrict, (req, res) => { | ||||||
|     }); |     }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | // render the customer view
 | ||||||
|  | router.get('/customer/view/:id?', common.restrict, (req, res) => { | ||||||
|  |     const db = req.app.db; | ||||||
|  | 
 | ||||||
|  |     console.log('here'); | ||||||
|  | 
 | ||||||
|  |     db.customers.findOne({_id: common.getId(req.params.id)}, (err, result) => { | ||||||
|  |         if(err){ | ||||||
|  |             console.info(err.stack); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         res.render('customer', { | ||||||
|  |             title: 'View customer', | ||||||
|  |             result: result, | ||||||
|  |             admin: true, | ||||||
|  |             session: req.session, | ||||||
|  |             message: common.clearSessionValue(req.session, 'message'), | ||||||
|  |             messageType: common.clearSessionValue(req.session, 'messageType'), | ||||||
|  |             config: common.getConfig(), | ||||||
|  |             editor: true, | ||||||
|  |             helpers: req.handlebars.helpers | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // customers list
 | ||||||
|  | router.get('/customers', common.restrict, (req, res) => { | ||||||
|  |     const db = req.app.db; | ||||||
|  | 
 | ||||||
|  |     db.customers.find({}).limit(20).sort({created: -1}).toArray((err, customers) => { | ||||||
|  |         res.render('customers', { | ||||||
|  |             title: 'Customers - List', | ||||||
|  |             admin: true, | ||||||
|  |             customers: customers, | ||||||
|  |             session: req.session, | ||||||
|  |             helpers: req.handlebars.helpers, | ||||||
|  |             message: common.clearSessionValue(req.session, 'message'), | ||||||
|  |             messageType: common.clearSessionValue(req.session, 'messageType'), | ||||||
|  |             config: common.getConfig() | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // Filtered customers list
 | ||||||
|  | router.get('/customers/filter/:search', common.restrict, (req, res, next) => { | ||||||
|  |     const db = req.app.db; | ||||||
|  |     let searchTerm = req.params.search; | ||||||
|  |     let customersIndex = req.app.customersIndex; | ||||||
|  | 
 | ||||||
|  |     let lunrIdArray = []; | ||||||
|  |     customersIndex.search(searchTerm).forEach((id) => { | ||||||
|  |         lunrIdArray.push(common.getId(id.ref)); | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     // we search on the lunr indexes
 | ||||||
|  |     db.customers.find({_id: {$in: lunrIdArray}}).sort({created: -1}).toArray((err, customers) => { | ||||||
|  |         if(err){ | ||||||
|  |             console.error(colors.red('Error searching', err)); | ||||||
|  |         } | ||||||
|  |         res.render('customers', { | ||||||
|  |             title: 'Customer results', | ||||||
|  |             customers: customers, | ||||||
|  |             admin: true, | ||||||
|  |             config: common.getConfig(), | ||||||
|  |             session: req.session, | ||||||
|  |             searchTerm: searchTerm, | ||||||
|  |             message: common.clearSessionValue(req.session, 'message'), | ||||||
|  |             messageType: common.clearSessionValue(req.session, 'messageType'), | ||||||
|  |             helpers: req.handlebars.helpers | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| // users new
 | // users new
 | ||||||
| router.get('/user/new', common.restrict, (req, res) => { | router.get('/user/new', common.restrict, (req, res) => { | ||||||
|     res.render('user_new', { |     res.render('user_new', { | ||||||
|  | @ -780,7 +853,7 @@ router.get('/user/new', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // delete user
 | // delete user
 | ||||||
| router.get('/user/delete/:id', common.restrict, (req, res) => { | router.get('/user/delete/:id', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     if(req.session.isAdmin === 'true'){ |     if(req.session.isAdmin === 'true'){ | ||||||
|         db.users.remove({_id: common.getId(req.params.id)}, {}, (err, numRemoved) => { |         db.users.remove({_id: common.getId(req.params.id)}, {}, (err, numRemoved) => { | ||||||
|             if(err){ |             if(err){ | ||||||
|  | @ -825,7 +898,7 @@ router.post('/settings/update', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // settings update
 | // settings update
 | ||||||
| router.post('/settings/option/remove', common.restrict, (req, res) => { | router.post('/settings/option/remove', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     db.products.findOne({_id: common.getId(req.body.productId)}, (err, product) => { |     db.products.findOne({_id: common.getId(req.body.productId)}, (err, product) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             console.info(err.stack); |             console.info(err.stack); | ||||||
|  | @ -852,7 +925,7 @@ router.post('/settings/option/remove', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // settings update
 | // settings update
 | ||||||
| router.get('/settings/menu', common.restrict, async (req, res) => { | router.get('/settings/menu', common.restrict, async (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     res.render('settings_menu', { |     res.render('settings_menu', { | ||||||
|         title: 'Cart menu', |         title: 'Cart menu', | ||||||
|         session: req.session, |         session: req.session, | ||||||
|  | @ -867,7 +940,7 @@ router.get('/settings/menu', common.restrict, async (req, res) => { | ||||||
| 
 | 
 | ||||||
| // settings page list
 | // settings page list
 | ||||||
| router.get('/settings/pages', common.restrict, (req, res) => { | router.get('/settings/pages', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     common.dbQuery(db.pages, {}, null, null, async (err, pages) => { |     common.dbQuery(db.pages, {}, null, null, async (err, pages) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             console.info(err.stack); |             console.info(err.stack); | ||||||
|  | @ -889,7 +962,7 @@ router.get('/settings/pages', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // settings pages new
 | // settings pages new
 | ||||||
| router.get('/settings/pages/new', common.restrict, async (req, res) => { | router.get('/settings/pages/new', common.restrict, async (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     res.render('settings_page_edit', { |     res.render('settings_page_edit', { | ||||||
|         title: 'Static pages', |         title: 'Static pages', | ||||||
|  | @ -906,7 +979,7 @@ router.get('/settings/pages/new', common.restrict, async (req, res) => { | ||||||
| 
 | 
 | ||||||
| // settings pages editor
 | // settings pages editor
 | ||||||
| router.get('/settings/pages/edit/:page', common.restrict, (req, res) => { | router.get('/settings/pages/edit/:page', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     db.pages.findOne({_id: common.getId(req.params.page)}, async (err, page) => { |     db.pages.findOne({_id: common.getId(req.params.page)}, async (err, page) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             console.info(err.stack); |             console.info(err.stack); | ||||||
|  | @ -942,7 +1015,7 @@ router.get('/settings/pages/edit/:page', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // settings update page
 | // settings update page
 | ||||||
| router.post('/settings/pages/update', common.restrict, (req, res) => { | router.post('/settings/pages/update', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     let doc = { |     let doc = { | ||||||
|         pageName: req.body.pageName, |         pageName: req.body.pageName, | ||||||
|  | @ -982,7 +1055,7 @@ router.post('/settings/pages/update', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // settings delete page
 | // settings delete page
 | ||||||
| router.get('/settings/pages/delete/:page', common.restrict, (req, res) => { | router.get('/settings/pages/delete/:page', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     db.pages.remove({_id: common.getId(req.params.page)}, {}, (err, numRemoved) => { |     db.pages.remove({_id: common.getId(req.params.page)}, {}, (err, numRemoved) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|             req.session.message = 'Error deleting page. Please try again.'; |             req.session.message = 'Error deleting page. Please try again.'; | ||||||
|  | @ -1040,7 +1113,7 @@ router.post('/settings/menu/save_order', common.restrict, (req, res) => { | ||||||
| router.post('/api/validate_permalink', (req, res) => { | router.post('/api/validate_permalink', (req, res) => { | ||||||
|     // if doc id is provided it checks for permalink in any products other that one provided,
 |     // if doc id is provided it checks for permalink in any products other that one provided,
 | ||||||
|     // else it just checks for any products with that permalink
 |     // else it just checks for any products with that permalink
 | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     let query = {}; |     let query = {}; | ||||||
|     if(typeof req.body.docId === 'undefined' || req.body.docId === ''){ |     if(typeof req.body.docId === 'undefined' || req.body.docId === ''){ | ||||||
|  | @ -1065,7 +1138,7 @@ router.post('/api/validate_permalink', (req, res) => { | ||||||
| 
 | 
 | ||||||
| // update the published state based on an ajax call from the frontend
 | // update the published state based on an ajax call from the frontend
 | ||||||
| router.post('/product/published_state', common.restrict, (req, res) => { | router.post('/product/published_state', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     db.products.update({_id: common.getId(req.body.id)}, {$set: {productPublished: req.body.state}}, {multi: false}, (err, numReplaced) => { |     db.products.update({_id: common.getId(req.body.id)}, {$set: {productPublished: req.body.state}}, {multi: false}, (err, numReplaced) => { | ||||||
|         if(err){ |         if(err){ | ||||||
|  | @ -1081,7 +1154,7 @@ router.post('/product/published_state', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // set as main product image
 | // set as main product image
 | ||||||
| router.post('/product/setasmainimage', common.restrict, (req, res) => { | router.post('/product/setasmainimage', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
| 
 | 
 | ||||||
|     // update the productImage to the db
 |     // update the productImage to the db
 | ||||||
|     db.products.update({_id: common.getId(req.body.product_id)}, {$set: {productImage: req.body.productImage}}, {multi: false}, (err, numReplaced) => { |     db.products.update({_id: common.getId(req.body.product_id)}, {$set: {productImage: req.body.productImage}}, {multi: false}, (err, numReplaced) => { | ||||||
|  | @ -1095,7 +1168,7 @@ router.post('/product/setasmainimage', common.restrict, (req, res) => { | ||||||
| 
 | 
 | ||||||
| // deletes a product image
 | // deletes a product image
 | ||||||
| router.post('/product/deleteimage', common.restrict, (req, res) => { | router.post('/product/deleteimage', common.restrict, (req, res) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let fs = require('fs'); |     let fs = require('fs'); | ||||||
|     let path = require('path'); |     let path = require('path'); | ||||||
| 
 | 
 | ||||||
|  | @ -1136,7 +1209,7 @@ router.post('/product/deleteimage', common.restrict, (req, res) => { | ||||||
| let multer = require('multer'); | let multer = require('multer'); | ||||||
| let upload = multer({dest: 'public/uploads/'}); | let upload = multer({dest: 'public/uploads/'}); | ||||||
| router.post('/file/upload', common.restrict, upload.single('upload_file'), (req, res, next) => { | router.post('/file/upload', common.restrict, upload.single('upload_file'), (req, res, next) => { | ||||||
|     let db = req.app.db; |     const db = req.app.db; | ||||||
|     let fs = require('fs'); |     let fs = require('fs'); | ||||||
|     let path = require('path'); |     let path = require('path'); | ||||||
| 
 | 
 | ||||||
|  | @ -1195,6 +1268,7 @@ router.post('/file/upload', common.restrict, upload.single('upload_file'), (req, | ||||||
| // delete a file via ajax request
 | // delete a file via ajax request
 | ||||||
| router.post('/testEmail', common.restrict, (req, res) => { | router.post('/testEmail', common.restrict, (req, res) => { | ||||||
|     let config = common.getConfig(); |     let config = common.getConfig(); | ||||||
|  |     // TODO: Should fix this to properly handle result
 | ||||||
|     common.sendEmail(config.emailAddress, 'expressCart test email', 'Your email settings are working'); |     common.sendEmail(config.emailAddress, 'expressCart test email', 'Your email settings are working'); | ||||||
|     res.status(200).json('Test email sent'); |     res.status(200).json('Test email sent'); | ||||||
| }); | }); | ||||||
|  |  | ||||||
							
								
								
									
										206
									
								
								routes/index.js
								
								
								
								
							
							
						
						
									
										206
									
								
								routes/index.js
								
								
								
								
							|  | @ -2,6 +2,7 @@ const express = require('express'); | ||||||
| const router = express.Router(); | const router = express.Router(); | ||||||
| const colors = require('colors'); | const colors = require('colors'); | ||||||
| const _ = require('lodash'); | const _ = require('lodash'); | ||||||
|  | const randtoken = require('rand-token'); | ||||||
| const common = require('./common'); | const common = require('./common'); | ||||||
| 
 | 
 | ||||||
| router.get('/payment/:orderId', async (req, res, next) => { | router.get('/payment/:orderId', async (req, res, next) => { | ||||||
|  | @ -236,6 +237,211 @@ router.post('/login_action', (req, res) => { | ||||||
|     }); |     }); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | // insert a customer
 | ||||||
|  | router.post('/customer/create', (req, res) => { | ||||||
|  |     const db = req.app.db; | ||||||
|  |     const bcrypt = req.bcrypt; | ||||||
|  | 
 | ||||||
|  |     let doc = { | ||||||
|  |         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, | ||||||
|  |         password: bcrypt.hashSync(req.body.password), | ||||||
|  |         created: new Date() | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     // check for existing customer
 | ||||||
|  |     db.customers.findOne({email: req.body.email}, (err, customer) => { | ||||||
|  |         if(customer){ | ||||||
|  |             res.status(404).json({ | ||||||
|  |                 err: 'A customer already exists with that email address' | ||||||
|  |             }); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         // email is ok to be used.
 | ||||||
|  |         db.customers.insertOne(doc, (err, newCustomer) => { | ||||||
|  |             if(err){ | ||||||
|  |                 if(newCustomer){ | ||||||
|  |                     console.error(colors.red('Failed to insert customer: ' + err)); | ||||||
|  |                     res.status(400).json({ | ||||||
|  |                         err: 'A customer already exists with that email address' | ||||||
|  |                     }); | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  |                 console.error(colors.red('Failed to insert customer: ' + err)); | ||||||
|  |                 res.status(400).json({ | ||||||
|  |                     err: 'Customer creation failed.' | ||||||
|  |                 }); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Customer creation successful
 | ||||||
|  |             req.session.customer = newCustomer.ops[0]; | ||||||
|  |             res.status(200).json({ | ||||||
|  |                 message: 'Successfully logged in', | ||||||
|  |                 customer: newCustomer | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // login the customer and check the password
 | ||||||
|  | router.post('/customer/login_action', (req, res) => { | ||||||
|  |     let db = req.app.db; | ||||||
|  |     let bcrypt = req.bcrypt; | ||||||
|  | 
 | ||||||
|  |     db.customers.findOne({email: req.body.loginEmail}, (err, customer) => { | ||||||
|  |         if(err){ | ||||||
|  |             // An error accurred
 | ||||||
|  |             return res.status(400).json({ | ||||||
|  |                 err: 'Access denied. Check password and try again.' | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // check if customer exists with that email
 | ||||||
|  |         if(customer === undefined || customer === null){ | ||||||
|  |             return res.status(400).json({ | ||||||
|  |                 err: 'A customer with that email does not exist.' | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |         // we have a customer under that email so we compare the password
 | ||||||
|  |         if(bcrypt.compareSync(req.body.loginPassword, customer.password) === false){ | ||||||
|  |             // password is not correct
 | ||||||
|  |             return res.status(400).json({ | ||||||
|  |                 err: 'Access denied. Check password and try again.' | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Customer login successful
 | ||||||
|  |         req.session.customer = customer; | ||||||
|  |         return res.status(200).json({ | ||||||
|  |             message: 'Successfully logged in', | ||||||
|  |             customer: customer | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // customer forgotten password
 | ||||||
|  | router.get('/customer/forgotten', (req, res) => { | ||||||
|  |     res.render('forgotten', { | ||||||
|  |         title: 'Forgotten', | ||||||
|  |         route: 'customer', | ||||||
|  |         forgotType: 'customer', | ||||||
|  |         config: common.getConfig(), | ||||||
|  |         helpers: req.handlebars.helpers, | ||||||
|  |         message: common.clearSessionValue(req.session, 'message'), | ||||||
|  |         messageType: common.clearSessionValue(req.session, 'messageType'), | ||||||
|  |         showFooter: 'showFooter' | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // forgotten password
 | ||||||
|  | router.post('/customer/forgotten_action', (req, res) => { | ||||||
|  |     const db = req.app.db; | ||||||
|  |     const config = common.getConfig(); | ||||||
|  |     let passwordToken = randtoken.generate(30); | ||||||
|  | 
 | ||||||
|  |     // find the user
 | ||||||
|  |     db.customers.findOne({email: req.body.email}, (err, customer) => { | ||||||
|  |         // if we have a customer, set a token, expiry and email it
 | ||||||
|  |         if(customer){ | ||||||
|  |             let tokenExpiry = Date.now() + 3600000; | ||||||
|  |             db.customers.update({email: req.body.email}, {$set: {resetToken: passwordToken, resetTokenExpiry: tokenExpiry}}, {multi: false}, (err, numReplaced) => { | ||||||
|  |                 // send forgotten password email
 | ||||||
|  |                 let mailOpts = { | ||||||
|  |                     to: req.body.email, | ||||||
|  |                     subject: 'Forgotten password request', | ||||||
|  |                     body: `You are receiving this because you (or someone else) have requested the reset of the password for your user account.\n\n | ||||||
|  |                         Please click on the following link, or paste this into your browser to complete the process:\n\n | ||||||
|  |                         ${config.baseUrl}/customer/reset/${passwordToken}\n\n | ||||||
|  |                         If you did not request this, please ignore this email and your password will remain unchanged.\n` | ||||||
|  |                 }; | ||||||
|  | 
 | ||||||
|  |                 // send the email with token to the user
 | ||||||
|  |                 // TODO: Should fix this to properly handle result
 | ||||||
|  |                 common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); | ||||||
|  |                 req.session.message = 'An email has been sent to ' + req.body.email + ' with further instructions'; | ||||||
|  |                 req.session.message_type = 'success'; | ||||||
|  |                 return res.redirect('/customer/forgotten'); | ||||||
|  |             }); | ||||||
|  |         }else{ | ||||||
|  |             req.session.message = 'Account does not exist'; | ||||||
|  |             res.redirect('/customer/forgotten'); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // reset password form
 | ||||||
|  | router.get('/customer/reset/:token', (req, res) => { | ||||||
|  |     const db = req.app.db; | ||||||
|  | 
 | ||||||
|  |     // Find the customer using the token
 | ||||||
|  |     db.customers.findOne({resetToken: req.params.token, resetTokenExpiry: {$gt: Date.now()}}, (err, customer) => { | ||||||
|  |         if(!customer){ | ||||||
|  |             req.session.message = 'Password reset token is invalid or has expired'; | ||||||
|  |             req.session.message_type = 'danger'; | ||||||
|  |             res.redirect('/forgot'); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // show the password reset form
 | ||||||
|  |         res.render('reset', { | ||||||
|  |             title: 'Reset password', | ||||||
|  |             token: req.params.token, | ||||||
|  |             route: 'customer', | ||||||
|  |             config: common.getConfig(), | ||||||
|  |             message: common.clearSessionValue(req.session, 'message'), | ||||||
|  |             message_type: common.clearSessionValue(req.session, 'message_type'), | ||||||
|  |             show_footer: 'show_footer', | ||||||
|  |             helpers: req.handlebars.helpers | ||||||
|  |         }); | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // reset password action
 | ||||||
|  | router.post('/customer/reset/:token', (req, res) => { | ||||||
|  |     const db = req.app.db; | ||||||
|  |     let bcrypt = req.bcrypt; | ||||||
|  | 
 | ||||||
|  |     // get the customer
 | ||||||
|  |     db.customers.findOne({resetToken: req.params.token, resetTokenExpiry: {$gt: Date.now()}}, (err, customer) => { | ||||||
|  |         if(!customer){ | ||||||
|  |             req.session.message = 'Password reset token is invalid or has expired'; | ||||||
|  |             req.session.message_type = 'danger'; | ||||||
|  |             return res.redirect('/forgot'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // update the password and remove the token
 | ||||||
|  |         let newPassword = bcrypt.hashSync(req.body.password); | ||||||
|  |         db.customers.update({email: customer.email}, {$set: {password: newPassword, resetToken: undefined, resetTokenExpiry: undefined}}, {multi: false}, (err, numReplaced) => { | ||||||
|  |             let mailOpts = { | ||||||
|  |                 to: customer.email, | ||||||
|  |                 subject: 'Password successfully reset', | ||||||
|  |                 body: 'This is a confirmation that the password for your account ' + customer.email + ' has just been changed successfully.\n' | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             // TODO: Should fix this to properly handle result
 | ||||||
|  |             common.sendEmail(mailOpts.to, mailOpts.subject, mailOpts.body); | ||||||
|  |             req.session.message = 'Password successfully updated'; | ||||||
|  |             req.session.message_type = 'success'; | ||||||
|  |             return res.redirect('/pay'); | ||||||
|  |         }); | ||||||
|  |         return''; | ||||||
|  |     }); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
|  | // logout the customer
 | ||||||
|  | router.post('/customer/logout', (req, res) => { | ||||||
|  |     req.session.customer = null; | ||||||
|  |     res.status(200).json({}); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| // search products
 | // search products
 | ||||||
| router.get('/search/:searchTerm/:pageNum?', (req, res) => { | router.get('/search/:searchTerm/:pageNum?', (req, res) => { | ||||||
|     let db = req.app.db; |     let db = req.app.db; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,49 @@ | ||||||
|  | {{> menu}} | ||||||
|  | <div class="col-lg-9"> | ||||||
|  |     <div class="row"> | ||||||
|  |         <div class="col-lg-12"> | ||||||
|  |             <h2>Customer</h2> | ||||||
|  |         </div> | ||||||
|  |         <div class="col-xs-12 col-md-12"> | ||||||
|  |             <table class="table-bordered"> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Email:</span></td> | ||||||
|  |                     <td>{{result.email}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Name:</span></td> | ||||||
|  |                     <td>{{result.firstName}} {{result.lastName}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Address 1:</span></td> | ||||||
|  |                     <td>{{result.address1}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Address 2:</span></td> | ||||||
|  |                     <td>{{result.address2}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Country:</span></td> | ||||||
|  |                     <td>{{result.country}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">State:</span></td> | ||||||
|  |                     <td>{{result.state}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Postcode:</span></td> | ||||||
|  |                     <td>{{result.postcode}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Phone number:</span></td> | ||||||
|  |                     <td>{{result.phone}}</td> | ||||||
|  |                 </tr> | ||||||
|  |                 <tr> | ||||||
|  |                     <td><span class="text-info">Creation date:</span></td> | ||||||
|  |                     <td>{{formatDate result.created "DD/MM/YYYY hh:mmA"}}</td> | ||||||
|  |                 </tr> | ||||||
|  |             </table> | ||||||
|  |         </div> | ||||||
|  |     </div> | ||||||
|  |     <input type="hidden" id="productId" value="{{result._id}}"> | ||||||
|  | </div> | ||||||
|  | @ -0,0 +1,64 @@ | ||||||
|  | {{> menu}} | ||||||
|  | <div class="col-lg-9"> | ||||||
|  |     <div class="col-lg-12"> | ||||||
|  |         <h2>Customers</h2> | ||||||
|  |     </div> | ||||||
|  |     <div class="col-lg-12 search_bar"> | ||||||
|  |         <div class="input-group"> | ||||||
|  |             <input type="text" name="customer_filter" id="customer_filter" class="form-control input-lg" placeholder="Filter customers"> | ||||||
|  |             <span class="input-group-btn"> | ||||||
|  |                 <button class="btn btn-success btn-lg" id="btn_customer_filter">Filter</button> | ||||||
|  |                 <a href="/admin/customers" class="hidden-xs btn btn-warning btn-lg"><i class="fa fa-times" aria-hidden="true"></i></a> | ||||||
|  |             </span> | ||||||
|  |         </div> | ||||||
|  |         <p class="text-warning top-pad-10">Customers can be filtered by: email, name or phone numnber</p> | ||||||
|  |     </div> | ||||||
|  |     {{#if customers}} | ||||||
|  |         <div class="col-lg-12"> | ||||||
|  |             <ul class="list-group"> | ||||||
|  |                 <li class="list-group-item"> | ||||||
|  |                     <strong> | ||||||
|  |                         Customers | ||||||
|  |                         {{#if searchTerm}} | ||||||
|  |                             - <span class="text-danger">Filtered term: {{searchTerm}} </span> | ||||||
|  |                         {{/if}} | ||||||
|  |                     </strong> | ||||||
|  |                 </li> | ||||||
|  |                 <li class="list-group-item"> | ||||||
|  |                     <div class="row"> | ||||||
|  |                         <div class="col-md-4"> | ||||||
|  |                             <h5 class="text-info"><strong>Email address</strong></h5> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="col-md-4"> | ||||||
|  |                             <h5 class="text-info"><strong>Name</strong></h5> | ||||||
|  |                         </div> | ||||||
|  |                         <div class="col-md-4"> | ||||||
|  |                             <h5 class="text-info"><strong>Phone number</strong></h5> | ||||||
|  |                         </div> | ||||||
|  |                     </div> | ||||||
|  |                 </li> | ||||||
|  |                 {{#each customers}} | ||||||
|  |                     <li class="list-group-item"> | ||||||
|  |                         <div class="row"> | ||||||
|  |                             <a href="/admin/customer/view/{{this._id}}"> | ||||||
|  |                                 <div class="col-md-4"> | ||||||
|  |                                     <h5 class="">{{this.email}}</h5> | ||||||
|  |                                 </div> | ||||||
|  |                                 <div class="col-md-4"> | ||||||
|  |                                     <h5 class="">{{this.firstName}} {{this.lastName}}</h5> | ||||||
|  |                                 </div> | ||||||
|  |                                 <div class="col-md-4"> | ||||||
|  |                                     <h5 class="">{{this.phone}}</h5> | ||||||
|  |                                 </div> | ||||||
|  |                             </a> | ||||||
|  |                         </div> | ||||||
|  |                     </li> | ||||||
|  |                 {{/each}} | ||||||
|  |             </ul> | ||||||
|  |         </div> | ||||||
|  |     {{else}} | ||||||
|  |     <h4 class="text-center"> | ||||||
|  |         No orders found | ||||||
|  |     </h4> | ||||||
|  |     {{/if}} | ||||||
|  | </div> | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | <div class="col-md-offset-4 col-md-4 col-lg-offset-4 col-lg-4" style="padding-top: 100px" > | ||||||
|  | 	<form class="form-signin" action="/{{route}}/forgotten_action" method="post" role="form" data-toggle="validator"> | ||||||
|  | 		<h2 class="form-signin-heading">Please enter your email address</h2> | ||||||
|  | 		<div class="form-group"> | ||||||
|  | 			<input type="email" name="email" class="form-control" placeholder="email address" required autofocus> | ||||||
|  | 		</div> | ||||||
|  | 		<button class="btn btn-lg btn-primary btn-block" type="submit">Reset</button> | ||||||
|  | 	</form> | ||||||
|  | </div> | ||||||
|  | @ -6,6 +6,8 @@ | ||||||
|         <li class="list-group-item"><i class="fa fa-list fa-icon" aria-hidden="true"></i>   <a href="/admin/products">List</a></li> |         <li class="list-group-item"><i class="fa fa-list fa-icon" aria-hidden="true"></i>   <a href="/admin/products">List</a></li> | ||||||
|         <li class="list-group-item"><strong>Orders</strong></li> |         <li class="list-group-item"><strong>Orders</strong></li> | ||||||
|         <li class="list-group-item"><i class="fa fa-cube fa-icon" aria-hidden="true"></i>   <a href="/admin/orders">List</a></li> |         <li class="list-group-item"><i class="fa fa-cube fa-icon" aria-hidden="true"></i>   <a href="/admin/orders">List</a></li> | ||||||
|  |         <li class="list-group-item"><strong>Customers</strong></li> | ||||||
|  |         <li class="list-group-item"><i class="fa fa-users fa-icon" aria-hidden="true"></i>   <a href="/admin/customers">List</a></li> | ||||||
|         <li class="list-group-item"><strong>Users</strong></li> |         <li class="list-group-item"><strong>Users</strong></li> | ||||||
|         <li class="list-group-item"><i class="fa fa-user-plus fa-icon" aria-hidden="true"></i>   <a href="/admin/user/new">New</a></li> |         <li class="list-group-item"><i class="fa fa-user-plus fa-icon" aria-hidden="true"></i>   <a href="/admin/user/new">New</a></li> | ||||||
|         <li class="list-group-item"><i class="fa fa-user fa-icon" aria-hidden="true"></i>   <a href="/admin/users">Edit</a></li> |         <li class="list-group-item"><i class="fa fa-user fa-icon" aria-hidden="true"></i>   <a href="/admin/users">Edit</a></li> | ||||||
|  |  | ||||||
|  | @ -6,64 +6,93 @@ | ||||||
|         <div class="col-md-5"> |         <div class="col-md-5"> | ||||||
|             <div class="panel panel-default" style="margin-top: 30px;"> |             <div class="panel panel-default" style="margin-top: 30px;"> | ||||||
|                 <div class="panel-heading">Customer details</div> |                 <div class="panel-heading">Customer details</div> | ||||||
|  |                 {{#unless session.customer}} | ||||||
|  |                 <div class="panel-body customer-details-login"> | ||||||
|  |                     <p>Existing customer</p> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <input type="email" class="form-control" id="customerLoginEmail" name="loginEmail" minlength="5" placeholder="Email address" required> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <input type="password" class="form-control" id="customerLoginPassword" name="loginPassword" minlength="5" placeholder="Password" required> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <a href="/customer/forgotten" class="btn btn-default pull-left">Forgotten</a> | ||||||
|  |                     </div> | ||||||
|  |                     <div class="form-group"> | ||||||
|  |                         <button id="customerLogin" class="btn btn-success pull-right" type="submit">Login</button> | ||||||
|  |                     </div> | ||||||
|  |                 </div> | ||||||
|  |                 {{/unless}} | ||||||
|                 <div class="panel-body customer-details"> |                 <div class="panel-body customer-details"> | ||||||
|  |                     {{#if session.customer}} | ||||||
|  |                     <div class="col-xs-12 col-md-12"> | ||||||
|  |                         <button id="customerLogout" class="btn btn-sm btn-success pull-right">Change customer</button> | ||||||
|  |                     </div> | ||||||
|  |                     {{/if}} | ||||||
|                     <form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false"> |                     <form id="shipping-form" class="shipping-form" action="/{{config.paymentGateway}}/checkout_action" method="post" role="form" data-toggle="validator" novalidate="false"> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" required> |                                 <input type="email" class="form-control customerDetails" id="shipEmail" name="shipEmail" minlength="5" placeholder="Email address" value="{{session.customer.email}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-6"> |                         <div class="col-xs-12 col-md-6"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" required> |                                 <input type="text" class="form-control customerDetails" id="shipFirstname" name="shipFirstname" placeholder="First name" value="{{session.customer.firstName}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-6"> |                         <div class="col-xs-12 col-md-6"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" required> |                                 <input type="text" class="form-control customerDetails" id="shipLastname" name="shipLastname" placeholder="Last name" value="{{session.customer.lastName}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" required> |                                 <input type="text" class="form-control customerDetails" id="shipAddr1" name="shipAddr1" placeholder="Address 1" value="{{session.customer.address1}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)"> |                                 <input type="text" class="form-control customerDetails" id="shipAddr2" name="shipAddr2" placeholder="Address 2 (optional)" value="{{session.customer.address1}}"> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-4"> |                         <div class="col-xs-12 col-md-4"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" required> |                                 <input type="text" class="form-control customerDetails" id="shipCountry" name="shipCountry" placeholder="Country" value="{{session.customer.country}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-4"> |                         <div class="col-xs-12 col-md-4"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" required> |                                 <input type="text" class="form-control customerDetails" id="shipState" name="shipState" placeholder="State" value="{{session.customer.state}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-4"> |                         <div class="col-xs-12 col-md-4"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="number" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" required> |                                 <input type="text" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" value="{{session.customer.postcode}}" required> | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|                         <div class="col-xs-12 col-md-12"> |                         <div class="col-xs-12 col-md-12"> | ||||||
|                             <div class="form-group"> |                             <div class="form-group"> | ||||||
|                                 <input type="number" class="form-control customerDetails" id="shipPostcode" name="shipPostcode" placeholder="Post code" required> |                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number" value="{{session.customer.phone}}" required> | ||||||
|                             </div> |  | ||||||
|                         </div> |  | ||||||
|                         <div class="col-xs-12 col-md-12"> |  | ||||||
|                             <div class="form-group"> |  | ||||||
|                                 <input type="number" class="form-control customerDetails" id="shipPhoneNumber" name="shipPhoneNumber" placeholder="Phone number (optional)"> |  | ||||||
|                             </div> |                             </div> | ||||||
|                         </div> |                         </div> | ||||||
|  |                         {{#if session.customer}} | ||||||
|                         {{#ifCond config.paymentGateway '==' 'paypal'}} |                         {{#ifCond config.paymentGateway '==' 'paypal'}} | ||||||
|                         <div class="paypal_button col-xs-12 col-md-12 text-center"> |                         <div class="paypal_button col-xs-12 col-md-12 text-center"> | ||||||
|                             <button id="checkout_paypal" class="btn btn-success" type="submit"><i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i> Pay with PayPal <i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i></button> |                             <button id="checkout_paypal" class="btn btn-success" type="submit"><i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i> Pay with PayPal <i class="fa fa-cc-paypal fa-lg" aria-hidden="true"></i></button> | ||||||
|                         </div> |                         </div> | ||||||
|                         {{/ifCond}} |                         {{/ifCond}} | ||||||
|  |                         {{/if}} | ||||||
|  |                         {{#unless session.customer}} | ||||||
|  |                         <div class="col-xs-12 col-md-12"> | ||||||
|  |                             <p class="text-muted">Enter a password to create an account for next time</p> | ||||||
|  |                             <div class="form-group"> | ||||||
|  |                                 <input type="password" class="form-control customerDetails" id="newCustomerPassword" name="newCustomerPassword" placeholder="Password" required> | ||||||
|  |                             </div> | ||||||
|  |                             <a id="createCustomerAccount" class="btn btn-success pull-right">Create account</a> | ||||||
|  |                         </div> | ||||||
|  |                         {{/unless}} | ||||||
|                     </form> |                     </form> | ||||||
|  |                     {{#if session.customer}} | ||||||
|                     {{#ifCond config.paymentGateway '==' 'stripe'}} |                     {{#ifCond config.paymentGateway '==' 'stripe'}} | ||||||
|                     <div class="col-xs-12 col-md-12 text-center"> |                     <div class="col-xs-12 col-md-12 text-center"> | ||||||
|                         <form method="POST" id="payment-form"> |                         <form method="POST" id="payment-form"> | ||||||
|  | @ -87,6 +116,7 @@ | ||||||
|                         </form> |                         </form> | ||||||
|                     </div> |                     </div> | ||||||
|                     {{/ifCond}} |                     {{/ifCond}} | ||||||
|  |                     {{/if}} | ||||||
|                 </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|  |  | ||||||
|  | @ -0,0 +1,15 @@ | ||||||
|  | <div class="col-md-offset-4 col-md-4 col-lg-offset-4 col-lg-4"> | ||||||
|  | 	<form class="form-signin" action="/{{route}}/reset/{{token}}" method="post" role="form" data-toggle="validator"> | ||||||
|  | 		<h2 class="form-signin-heading">Password reset</h2> | ||||||
|  | 		<div class="form-group"> | ||||||
|  |             <label for="user_password">Password *</label> | ||||||
|  |             <input type="password" class="form-control" id="user_password" name="password" placeholder="Password" required> | ||||||
|  |         </div> | ||||||
|  |         <div class="form-group"> | ||||||
|  |             <label for="frm_user_password_confirm">Confirm password *</label> | ||||||
|  |             <input type="password" data-match="#user_password" placeholder="Confirm password" class="form-control" name="frm_user_password_confirm" required> | ||||||
|  |         </div> | ||||||
|  | 		<button class="btn btn-lg btn-success btn-block" type="submit">Update password</button> | ||||||
|  |         </br> | ||||||
|  | 	</form> | ||||||
|  | </div> | ||||||
		Loading…
	
		Reference in New Issue