Add limitations to file uploads
							parent
							
								
									6345ef8318
								
							
						
					
					
						commit
						65b18cfe42
					
				|  | @ -35,6 +35,17 @@ const restrictedRoutes = [ | |||
|     {route: '/admin/file/delete', response: 'json'} | ||||
| ]; | ||||
| 
 | ||||
| // Allowed mime types for product images
 | ||||
| exports.allowedMimeType = [ | ||||
|     'image/jpeg', | ||||
|     'image/png', | ||||
|     'image/gif', | ||||
|     'image/bmp', | ||||
|     'image/webp' | ||||
| ]; | ||||
| 
 | ||||
| exports.fileSizeLimit = 10485760; | ||||
| 
 | ||||
| // common functions
 | ||||
| exports.restrict = (req, res, next) => { | ||||
|     exports.checkLogin(req, res, next); | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
|   "name": "express-cart", | ||||
|   "version": "1.1.5", | ||||
|   "version": "1.1.6", | ||||
|   "lockfileVersion": 1, | ||||
|   "requires": true, | ||||
|   "dependencies": { | ||||
|  | @ -499,6 +499,12 @@ | |||
|       "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "asynckit": { | ||||
|       "version": "0.4.0", | ||||
|       "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", | ||||
|       "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "atob": { | ||||
|       "version": "2.0.3", | ||||
|       "resolved": "https://registry.npmjs.org/atob/-/atob-2.0.3.tgz", | ||||
|  | @ -1968,6 +1974,15 @@ | |||
|       "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", | ||||
|       "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=" | ||||
|     }, | ||||
|     "combined-stream": { | ||||
|       "version": "1.0.6", | ||||
|       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", | ||||
|       "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "delayed-stream": "1.0.0" | ||||
|       } | ||||
|     }, | ||||
|     "commander": { | ||||
|       "version": "2.12.2", | ||||
|       "resolved": "https://registry.npmjs.org/commander/-/commander-2.12.2.tgz", | ||||
|  | @ -2140,6 +2155,12 @@ | |||
|       "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", | ||||
|       "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" | ||||
|     }, | ||||
|     "cookiejar": { | ||||
|       "version": "2.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.2.tgz", | ||||
|       "integrity": "sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "copy-descriptor": { | ||||
|       "version": "0.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", | ||||
|  | @ -2353,6 +2374,12 @@ | |||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "delayed-stream": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", | ||||
|       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "depd": { | ||||
|       "version": "1.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", | ||||
|  | @ -2672,8 +2699,7 @@ | |||
|     "escape-string-regexp": { | ||||
|       "version": "1.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", | ||||
|       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", | ||||
|       "dev": true | ||||
|       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" | ||||
|     }, | ||||
|     "escope": { | ||||
|       "version": "3.6.0", | ||||
|  | @ -3468,6 +3494,23 @@ | |||
|       "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", | ||||
|       "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" | ||||
|     }, | ||||
|     "form-data": { | ||||
|       "version": "2.3.2", | ||||
|       "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", | ||||
|       "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "asynckit": "0.4.0", | ||||
|         "combined-stream": "1.0.6", | ||||
|         "mime-types": "2.1.17" | ||||
|       } | ||||
|     }, | ||||
|     "formidable": { | ||||
|       "version": "1.2.1", | ||||
|       "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", | ||||
|       "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==", | ||||
|       "dev": true | ||||
|     }, | ||||
|     "forwarded": { | ||||
|       "version": "0.1.2", | ||||
|       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", | ||||
|  | @ -5450,6 +5493,14 @@ | |||
|       "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", | ||||
|       "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" | ||||
|     }, | ||||
|     "inherits-ex": { | ||||
|       "version": "1.2.3", | ||||
|       "resolved": "https://registry.npmjs.org/inherits-ex/-/inherits-ex-1.2.3.tgz", | ||||
|       "integrity": "sha512-DCZqD7BpjXqaha8IKcoAE3ZZr6Hi12ropV1h+3pBnirE14mNRwLuYySvYxUSBemTQ40SjAxPL8BTk2Xw/3IF9w==", | ||||
|       "requires": { | ||||
|         "xtend": "4.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "ini": { | ||||
|       "version": "1.3.5", | ||||
|       "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", | ||||
|  | @ -6600,9 +6651,20 @@ | |||
|       "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" | ||||
|     }, | ||||
|     "mime-db": { | ||||
|       "version": "1.30.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", | ||||
|       "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" | ||||
|       "version": "1.33.0", | ||||
|       "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", | ||||
|       "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" | ||||
|     }, | ||||
|     "mime-type": { | ||||
|       "version": "3.0.5", | ||||
|       "resolved": "https://registry.npmjs.org/mime-type/-/mime-type-3.0.5.tgz", | ||||
|       "integrity": "sha1-ftKSan2oImifgSVPWYf+lQNiLpo=", | ||||
|       "requires": { | ||||
|         "media-typer": "0.3.0", | ||||
|         "minimatch": "3.0.4", | ||||
|         "path.js": "1.0.7", | ||||
|         "util-ex": "0.3.15" | ||||
|       } | ||||
|     }, | ||||
|     "mime-types": { | ||||
|       "version": "2.1.17", | ||||
|  | @ -6610,6 +6672,13 @@ | |||
|       "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", | ||||
|       "requires": { | ||||
|         "mime-db": "1.30.0" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "mime-db": { | ||||
|           "version": "1.30.0", | ||||
|           "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", | ||||
|           "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "mimic-fn": { | ||||
|  | @ -6673,21 +6742,54 @@ | |||
|       "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" | ||||
|     }, | ||||
|     "mongodb": { | ||||
|       "version": "3.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.0.0.tgz", | ||||
|       "integrity": "sha1-GN2P+S14k97MQI2virDrQIR1Ip8=", | ||||
|       "version": "2.2.3", | ||||
|       "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.3.tgz", | ||||
|       "integrity": "sha1-SSztvnOHVSyc8uT1vEDreOBiA6s=", | ||||
|       "requires": { | ||||
|         "mongodb-core": "3.0.0" | ||||
|         "es6-promise": "3.0.2", | ||||
|         "mongodb-core": "2.0.6", | ||||
|         "readable-stream": "1.0.31" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "bson": { | ||||
|           "version": "0.5.7", | ||||
|           "resolved": "https://registry.npmjs.org/bson/-/bson-0.5.7.tgz", | ||||
|           "integrity": "sha1-DRH+CTbB/uAp4R9wY/XQqyQi6j4=" | ||||
|         }, | ||||
|         "es6-promise": { | ||||
|           "version": "3.0.2", | ||||
|           "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz", | ||||
|           "integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y=" | ||||
|         }, | ||||
|         "isarray": { | ||||
|           "version": "0.0.1", | ||||
|           "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", | ||||
|           "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" | ||||
|         }, | ||||
|         "mongodb-core": { | ||||
|           "version": "3.0.0", | ||||
|           "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.0.0.tgz", | ||||
|           "integrity": "sha1-tNBsvoj6iPaola+lJCpBvVMJvHQ=", | ||||
|           "version": "2.0.6", | ||||
|           "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.0.6.tgz", | ||||
|           "integrity": "sha1-fxvnnYhklcitaW1w476DTWHhuEM=", | ||||
|           "requires": { | ||||
|             "bson": "1.0.4", | ||||
|             "bson": "0.5.7", | ||||
|             "require_optional": "1.0.1" | ||||
|           } | ||||
|         }, | ||||
|         "readable-stream": { | ||||
|           "version": "1.0.31", | ||||
|           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.31.tgz", | ||||
|           "integrity": "sha1-jyUC4LyeOw2huUUgqrtOJgPsr64=", | ||||
|           "requires": { | ||||
|             "core-util-is": "1.0.2", | ||||
|             "inherits": "2.0.3", | ||||
|             "isarray": "0.0.1", | ||||
|             "string_decoder": "0.10.31" | ||||
|           } | ||||
|         }, | ||||
|         "string_decoder": { | ||||
|           "version": "0.10.31", | ||||
|           "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", | ||||
|           "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|  | @ -7325,6 +7427,16 @@ | |||
|         "pify": "2.3.0" | ||||
|       } | ||||
|     }, | ||||
|     "path.js": { | ||||
|       "version": "1.0.7", | ||||
|       "resolved": "https://registry.npmjs.org/path.js/-/path.js-1.0.7.tgz", | ||||
|       "integrity": "sha1-fRNrYH3hm/2YugaIdJJih+ZTSTk=", | ||||
|       "requires": { | ||||
|         "escape-string-regexp": "1.0.5", | ||||
|         "inherits-ex": "1.2.3", | ||||
|         "util-ex": "0.3.15" | ||||
|       } | ||||
|     }, | ||||
|     "paypal-rest-sdk": { | ||||
|       "version": "1.8.1", | ||||
|       "resolved": "https://registry.npmjs.org/paypal-rest-sdk/-/paypal-rest-sdk-1.8.1.tgz", | ||||
|  | @ -8553,6 +8665,35 @@ | |||
|         "safe-buffer": "5.1.1" | ||||
|       } | ||||
|     }, | ||||
|     "superagent": { | ||||
|       "version": "3.8.2", | ||||
|       "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", | ||||
|       "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "component-emitter": "1.2.1", | ||||
|         "cookiejar": "2.1.2", | ||||
|         "debug": "3.1.0", | ||||
|         "extend": "3.0.1", | ||||
|         "form-data": "2.3.2", | ||||
|         "formidable": "1.2.1", | ||||
|         "methods": "1.1.2", | ||||
|         "mime": "1.4.1", | ||||
|         "qs": "6.5.1", | ||||
|         "readable-stream": "2.3.3" | ||||
|       }, | ||||
|       "dependencies": { | ||||
|         "debug": { | ||||
|           "version": "3.1.0", | ||||
|           "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", | ||||
|           "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", | ||||
|           "dev": true, | ||||
|           "requires": { | ||||
|             "ms": "2.0.0" | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "supertap": { | ||||
|       "version": "1.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/supertap/-/supertap-1.0.0.tgz", | ||||
|  | @ -8589,6 +8730,16 @@ | |||
|         } | ||||
|       } | ||||
|     }, | ||||
|     "supertest": { | ||||
|       "version": "3.1.0", | ||||
|       "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.1.0.tgz", | ||||
|       "integrity": "sha512-O44AMnmJqx294uJQjfUmEyYOg7d9mylNFsMw/Wkz4evKd1njyPrtCN+U6ZIC7sKtfEVQhfTqFFijlXx8KP/Czw==", | ||||
|       "dev": true, | ||||
|       "requires": { | ||||
|         "methods": "1.1.2", | ||||
|         "superagent": "3.8.2" | ||||
|       } | ||||
|     }, | ||||
|     "supports-color": { | ||||
|       "version": "2.0.0", | ||||
|       "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", | ||||
|  | @ -9195,6 +9346,15 @@ | |||
|       "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", | ||||
|       "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" | ||||
|     }, | ||||
|     "util-ex": { | ||||
|       "version": "0.3.15", | ||||
|       "resolved": "https://registry.npmjs.org/util-ex/-/util-ex-0.3.15.tgz", | ||||
|       "integrity": "sha1-+SYc2hPEMn0HQMvme+Eife2LAFg=", | ||||
|       "requires": { | ||||
|         "inherits-ex": "1.2.3", | ||||
|         "xtend": "4.0.1" | ||||
|       } | ||||
|     }, | ||||
|     "utils-merge": { | ||||
|       "version": "1.0.1", | ||||
|       "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| { | ||||
|   "name": "express-cart", | ||||
|   "version": "1.1.6", | ||||
|   "version": "1.1.7", | ||||
|   "description": "A fully functioning Node.js shopping cart with Stripe, PayPal and Authorize.net payments.", | ||||
|   "private": false, | ||||
|   "scripts": { | ||||
|  | @ -27,6 +27,8 @@ | |||
|     "html-entities": "^1.2.0", | ||||
|     "lodash": "^4.13.1", | ||||
|     "lunr": "^2.1.5", | ||||
|     "mime-db": "^1.33.0", | ||||
|     "mime-type": "^3.0.5", | ||||
|     "moment": "^2.15.2", | ||||
|     "mongodb": "2.2.3", | ||||
|     "morgan": "^1.9.0", | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ const fs = require('fs'); | |||
| const path = require('path'); | ||||
| const multer = require('multer'); | ||||
| const glob = require('glob'); | ||||
| const mime = require('mime-type/with-db'); | ||||
| const router = express.Router(); | ||||
| 
 | ||||
| // Admin section
 | ||||
|  | @ -419,13 +420,43 @@ router.post('/admin/file/upload', common.restrict, common.checkAccess, upload.si | |||
|     const db = req.app.db; | ||||
| 
 | ||||
|     if(req.file){ | ||||
|         // check for upload select
 | ||||
|         let uploadDir = path.join('public/uploads', req.body.directory); | ||||
|         let file = req.file; | ||||
| 
 | ||||
|         // Get the mime type of the file
 | ||||
|         const mimeType = mime.lookup(file.originalname); | ||||
|          | ||||
|         // Check for allowed mime type and file size
 | ||||
|         if(!common.allowedMimeType.includes(mimeType) || file.size > common.fileSizeLimit){ | ||||
|             // Remove temp file
 | ||||
|             fs.unlinkSync(file.path); | ||||
| 
 | ||||
|             // Redirect to error
 | ||||
|             req.session.message = 'File type not allowed or too large. Please try again.'; | ||||
|             req.session.messageType = 'danger'; | ||||
|             res.redirect('/admin/product/edit/' + req.body.productId); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // get the product form the DB
 | ||||
|         db.products.findOne({_id: common.getId(req.body.productId)}, (err, product) => { | ||||
|             if(err){ | ||||
|                 console.info(err.stack); | ||||
|                 // delete the temp file.
 | ||||
|                 fs.unlinkSync(file.path); | ||||
| 
 | ||||
|                 // Redirect to error
 | ||||
|                 req.session.message = 'File upload error. Please try again.'; | ||||
|                 req.session.messageType = 'danger'; | ||||
|                 res.redirect('/admin/product/edit/' + req.body.productId); | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             const productPath = product.productPermalink; | ||||
|             let uploadDir = path.join('public/uploads', productPath); | ||||
| 
 | ||||
|             // Check directory and create (if needed)
 | ||||
|             common.checkDirectorySync(uploadDir); | ||||
| 
 | ||||
|         let file = req.file; | ||||
|             let source = fs.createReadStream(file.path); | ||||
|             let dest = fs.createWriteStream(path.join(uploadDir, file.originalname.replace(/ /g, '_'))); | ||||
| 
 | ||||
|  | @ -434,18 +465,9 @@ router.post('/admin/file/upload', common.restrict, common.checkAccess, upload.si | |||
|             source.on('end', () => { }); | ||||
| 
 | ||||
|             // delete the temp file.
 | ||||
|         fs.unlink(file.path, (err) => { | ||||
|             if(err){ | ||||
|                 console.info(err.stack); | ||||
|             } | ||||
|         }); | ||||
|             fs.unlinkSync(file.path); | ||||
| 
 | ||||
|         // get the product form the DB
 | ||||
|         db.products.findOne({_id: common.getId(req.body.productId)}, (err, product) => { | ||||
|             if(err){ | ||||
|                 console.info(err.stack); | ||||
|             } | ||||
|             let imagePath = path.join('/uploads', req.body.directory, file.originalname.replace(/ /g, '_')); | ||||
|             let imagePath = path.join('/uploads', productPath, file.originalname.replace(/ /g, '_')); | ||||
| 
 | ||||
|             // if there isn't a product featured image, set this one
 | ||||
|             if(!product.productImage){ | ||||
|  | @ -464,6 +486,10 @@ router.post('/admin/file/upload', common.restrict, common.checkAccess, upload.si | |||
|             } | ||||
|         }); | ||||
|     }else{ | ||||
|         // delete the temp file.
 | ||||
|         fs.unlinkSync(file.path); | ||||
| 
 | ||||
|         // Redirect to error
 | ||||
|         req.session.message = 'File upload error. Please select a file.'; | ||||
|         req.session.messageType = 'danger'; | ||||
|         res.redirect('/admin/product/edit/' + req.body.productId); | ||||
|  |  | |||
|  | @ -149,7 +149,6 @@ | |||
|                         Select file<input type="file" name="upload_file" id="upload_file"> | ||||
|                     </span> | ||||
|                     <input type="hidden" id="productId" name="productId" value="{{result._id}}"/> | ||||
|                     <input type="hidden" id="directory" name="directory" value="{{result.productPermalink}}"/> | ||||
|                 </div> | ||||
|                 <div class="modal-footer"> | ||||
|                     <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue