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,33 +420,54 @@ 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);
|
||||
|
||||
// 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, '_')));
|
||||
|
||||
// save the new file
|
||||
source.pipe(dest);
|
||||
source.on('end', () => { });
|
||||
// Get the mime type of the file
|
||||
const mimeType = mime.lookup(file.originalname);
|
||||
|
||||
// delete the temp file.
|
||||
fs.unlink(file.path, (err) => {
|
||||
if(err){
|
||||
console.info(err.stack);
|
||||
}
|
||||
});
|
||||
// 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;
|
||||
}
|
||||
let imagePath = path.join('/uploads', req.body.directory, file.originalname.replace(/ /g, '_'));
|
||||
|
||||
const productPath = product.productPermalink;
|
||||
let uploadDir = path.join('public/uploads', productPath);
|
||||
|
||||
// Check directory and create (if needed)
|
||||
common.checkDirectorySync(uploadDir);
|
||||
|
||||
let source = fs.createReadStream(file.path);
|
||||
let dest = fs.createWriteStream(path.join(uploadDir, file.originalname.replace(/ /g, '_')));
|
||||
|
||||
// save the new file
|
||||
source.pipe(dest);
|
||||
source.on('end', () => { });
|
||||
|
||||
// delete the temp file.
|
||||
fs.unlinkSync(file.path);
|
||||
|
||||
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