From 6ed00d2c88961e6f7043430353089092549f5ddd Mon Sep 17 00:00:00 2001 From: Oscar Bernal Date: Wed, 23 Dec 2015 09:15:44 -0500 Subject: [PATCH 01/43] added maxFieldsSize override to formidable limit --- lib/storage-service.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/storage-service.js b/lib/storage-service.js index a4e3e94..69ca90f 100644 --- a/lib/storage-service.js +++ b/lib/storage-service.js @@ -40,6 +40,9 @@ function StorageService(options) { if (options.maxFileSize) { this.maxFileSize = options.maxFileSize; } + if (options.maxFieldsSize) { + this.maxFieldsSize = options.maxFieldsSize; + } } @@ -236,6 +239,9 @@ StorageService.prototype.upload = function(req, res, options, cb) { if (this.maxFileSize && !options.maxFileSize) { options.maxFileSize = this.maxFileSize; } + if (this.maxFieldsSize && !options.maxFieldsSize) { + options.maxFieldsSize = this.maxFieldsSize; + } return handler.upload(this.client, req, res, options, cb); }; From 9aba5658a2b96ab9d10c703cf47d401313d2c9ff Mon Sep 17 00:00:00 2001 From: Cristobal Vergara Date: Thu, 28 Jan 2016 11:18:37 -0800 Subject: [PATCH 02/43] Added support for external providers as npm modules. --- lib/factory.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/factory.js b/lib/factory.js index e03bc71..eafc86b 100644 --- a/lib/factory.js +++ b/lib/factory.js @@ -79,8 +79,17 @@ function createClient(options) { // Try to load the provider from providers folder handler = require('./providers/' + provider); } catch (err) { - // Fall back to pkgcloud - handler = require('pkgcloud').storage; + try { + // Fall back to using an external provider + handler = require(provider); + if (!handler || !handler.createClient) { + // Fall back to pkgcloud + handler = require('pkgcloud').storage; + } + } catch(err) { + // Fall back to pkgcloud + handler = require('pkgcloud').storage; + } } patchContainerAndFileClass(provider); return handler.createClient(options); @@ -96,8 +105,13 @@ function getProvider(provider) { // Try to load the provider from providers folder return require('./providers/' + provider); } catch (err) { - // Fall back to pkgcloud - return require('pkgcloud').providers[provider]; + try { + // Fall back to using an external provider + return require(provider); + } catch(err) { + // Fall back to pkgcloud + return require('pkgcloud').providers[provider]; + } } } From f61ad4f23db0eabcf2890bdeeee9e99faf483e17 Mon Sep 17 00:00:00 2001 From: Jose De Gouveia Date: Wed, 7 Sep 2016 17:29:12 +0200 Subject: [PATCH 03/43] added file field name into getFilename function in storage-handler --- lib/storage-handler.js | 7 +++--- test/images/album1/.gitignore | 1 + test/upload-download.test.js | 40 ++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/storage-handler.js b/lib/storage-handler.js index eeba15c..15ab3b1 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -70,7 +70,8 @@ exports.upload = function(provider, req, res, options, cb) { var file = { container: container, name: part.filename, - type: part.mime + type: part.mime, + field: part.name }; // Options for this file @@ -160,7 +161,7 @@ exports.upload = function(provider, req, res, options, cb) { if (fileSize > maxFileSize) { // We are missing some way to tell the provider to cancel upload/multipart upload of the current file. // - s3-upload-stream doesn't provide a way to do this in it's public interface - // - We could call provider.delete file but it would not delete multipart data + // - We could call provider.delete file but it would not delete multipart data self._error(new Error(g.f('{{maxFileSize}} exceeded, received %s bytes of field data (max is %s)', fileSize, maxFileSize))); return; } @@ -203,7 +204,7 @@ function handleError(res, err) { * @header storageService.download(provider, req, res, container, file, cb) */ exports.download = function(provider, req, res, container, file, cb) { - + var fileName = path.basename(file); var params = { container: container || req && req.params.container, diff --git a/test/images/album1/.gitignore b/test/images/album1/.gitignore index 9df892a..9084277 100644 --- a/test/images/album1/.gitignore +++ b/test/images/album1/.gitignore @@ -1,2 +1,3 @@ test.jpg image-*.jpg +customimagefield_test.jpg \ No newline at end of file diff --git a/test/upload-download.test.js b/test/upload-download.test.js index 8950512..b207552 100644 --- a/test/upload-download.test.js +++ b/test/upload-download.test.js @@ -10,6 +10,25 @@ var assert = require('assert'); var app = loopback(); var path = require('path'); +//custom route with renamer +app.post('/custom/upload', function(req, res, next) { + var options = { + container : 'album1', + getFilename : function(file, req, res) { + return file.field + "_" +file.name; + } + }; + ds.connector.upload(req, res, options, function(err,result){ + if (!err){ + res.setHeader('Content-Type', 'application/json'); + res.status(200).send({ result : result }); + }else{ + res.status(500).send(err); + } + }); + +}); + // expose a rest api app.use(loopback.rest()); @@ -168,8 +187,7 @@ describe('storage service', function () { .expect('Content-Type', /json/) .expect(200, function (err, res) { assert.deepEqual(res.body, {"result": {"files": {"image": [ - {"container": "album1", "name": "test.jpg", "type": "image/jpeg", - "size": 60475} + {"container": "album1", "name": "test.jpg", "type": "image/jpeg","field":"image","size": 60475} ]}, "fields": {}}}); done(); }); @@ -184,7 +202,7 @@ describe('storage service', function () { .expect('Content-Type', /json/) .expect(200, function (err, res) { assert.deepEqual(res.body, {"result": {"files": {"image": [ - {"container": "album1", "name": "image-test.jpg", "originalFilename":"test.jpg", "type": "image/jpeg", "acl":"public-read", "size": 60475} + {"container": "album1", "name": "image-test.jpg", "originalFilename":"test.jpg", "type": "image/jpeg", "field":"image", "acl":"public-read", "size": 60475} ]}, "fields": {}}}); done(); }); @@ -315,4 +333,20 @@ describe('storage service', function () { done(); }); }); + + it('should upload a file with custom route accessing directly to the storage connector with renamer',function (done){ + + request('http://localhost:' + app.get('port')) + .post('/custom/upload') + .attach('customimagefield', path.join(__dirname, './fixtures/test.jpg')) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200, function (err, res) { + assert.deepEqual(res.body, {"result": {"files": {"customimagefield": [ + {"container": "album1", "name": "customimagefield_test.jpg", "originalFilename":"test.jpg", "type": "image/jpeg", "field":"customimagefield", "size": 60475} + ]}, "fields": {}}}); + done(); + }); + }); + }); From efe4e089f6db032e3ee4b5afa2f2e9683f9f6e35 Mon Sep 17 00:00:00 2001 From: Jose De Gouveia Date: Wed, 7 Sep 2016 17:29:12 +0200 Subject: [PATCH 04/43] added file field name into getFilename function --- lib/storage-handler.js | 7 +++--- test/images/album1/.gitignore | 1 + test/upload-download.test.js | 40 ++++++++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/lib/storage-handler.js b/lib/storage-handler.js index eeba15c..15ab3b1 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -70,7 +70,8 @@ exports.upload = function(provider, req, res, options, cb) { var file = { container: container, name: part.filename, - type: part.mime + type: part.mime, + field: part.name }; // Options for this file @@ -160,7 +161,7 @@ exports.upload = function(provider, req, res, options, cb) { if (fileSize > maxFileSize) { // We are missing some way to tell the provider to cancel upload/multipart upload of the current file. // - s3-upload-stream doesn't provide a way to do this in it's public interface - // - We could call provider.delete file but it would not delete multipart data + // - We could call provider.delete file but it would not delete multipart data self._error(new Error(g.f('{{maxFileSize}} exceeded, received %s bytes of field data (max is %s)', fileSize, maxFileSize))); return; } @@ -203,7 +204,7 @@ function handleError(res, err) { * @header storageService.download(provider, req, res, container, file, cb) */ exports.download = function(provider, req, res, container, file, cb) { - + var fileName = path.basename(file); var params = { container: container || req && req.params.container, diff --git a/test/images/album1/.gitignore b/test/images/album1/.gitignore index 9df892a..9084277 100644 --- a/test/images/album1/.gitignore +++ b/test/images/album1/.gitignore @@ -1,2 +1,3 @@ test.jpg image-*.jpg +customimagefield_test.jpg \ No newline at end of file diff --git a/test/upload-download.test.js b/test/upload-download.test.js index 8950512..b207552 100644 --- a/test/upload-download.test.js +++ b/test/upload-download.test.js @@ -10,6 +10,25 @@ var assert = require('assert'); var app = loopback(); var path = require('path'); +//custom route with renamer +app.post('/custom/upload', function(req, res, next) { + var options = { + container : 'album1', + getFilename : function(file, req, res) { + return file.field + "_" +file.name; + } + }; + ds.connector.upload(req, res, options, function(err,result){ + if (!err){ + res.setHeader('Content-Type', 'application/json'); + res.status(200).send({ result : result }); + }else{ + res.status(500).send(err); + } + }); + +}); + // expose a rest api app.use(loopback.rest()); @@ -168,8 +187,7 @@ describe('storage service', function () { .expect('Content-Type', /json/) .expect(200, function (err, res) { assert.deepEqual(res.body, {"result": {"files": {"image": [ - {"container": "album1", "name": "test.jpg", "type": "image/jpeg", - "size": 60475} + {"container": "album1", "name": "test.jpg", "type": "image/jpeg","field":"image","size": 60475} ]}, "fields": {}}}); done(); }); @@ -184,7 +202,7 @@ describe('storage service', function () { .expect('Content-Type', /json/) .expect(200, function (err, res) { assert.deepEqual(res.body, {"result": {"files": {"image": [ - {"container": "album1", "name": "image-test.jpg", "originalFilename":"test.jpg", "type": "image/jpeg", "acl":"public-read", "size": 60475} + {"container": "album1", "name": "image-test.jpg", "originalFilename":"test.jpg", "type": "image/jpeg", "field":"image", "acl":"public-read", "size": 60475} ]}, "fields": {}}}); done(); }); @@ -315,4 +333,20 @@ describe('storage service', function () { done(); }); }); + + it('should upload a file with custom route accessing directly to the storage connector with renamer',function (done){ + + request('http://localhost:' + app.get('port')) + .post('/custom/upload') + .attach('customimagefield', path.join(__dirname, './fixtures/test.jpg')) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200, function (err, res) { + assert.deepEqual(res.body, {"result": {"files": {"customimagefield": [ + {"container": "album1", "name": "customimagefield_test.jpg", "originalFilename":"test.jpg", "type": "image/jpeg", "field":"customimagefield", "size": 60475} + ]}, "fields": {}}}); + done(); + }); + }); + }); From 32bf1a90d8000ef570f4ec4df740e72c5bad45e7 Mon Sep 17 00:00:00 2001 From: ole3021 Date: Wed, 7 Dec 2016 16:19:11 +0800 Subject: [PATCH 05/43] fix scope error --- lib/storage-handler.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/storage-handler.js b/lib/storage-handler.js index 52733a2..f3ffa05 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -262,25 +262,26 @@ exports.download = function(provider, req, res, container, file, cb) { cb = function() {}; // avoid double-callback }); } + + function setupPartialDownload(params, stats, res) { + var total = stats.size; + + var parts = range.replace(/bytes=/, '').split('-'); + var partialstart = parts[0]; + var partialend = parts[1]; + + params.start = parseInt(partialstart, 10); + params.end = partialend ? parseInt(partialend, 10) : total - 1; + + var chunksize = (params.end - params.start) + 1; + + res.status(206); + res.set('Content-Range', 'bytes ' + params.start + '-' + params.end + '/' + total); + res.set('Accept-Ranges', 'bytes'); + res.set('Content-Length', chunksize); + }; }; -function setupPartialDownload(params, stats, res) { - var total = stats.size; - - var parts = range.replace(/bytes=/, '').split('-'); - var partialstart = parts[0]; - var partialend = parts[1]; - - params.start = parseInt(partialstart, 10); - params.end = partialend ? parseInt(partialend, 10) : total - 1; - - var chunksize = (params.end - params.start) + 1; - - res.status(206); - res.set('Content-Range', 'bytes ' + params.start + '-' + params.end + '/' + total); - res.set('Accept-Ranges', 'bytes'); - res.set('Content-Length', chunksize); -}; function processError(err, fileName) { if (err.code === 'ENOENT') { From 99fdb64d1ecbce0d8ac7506308483c82b36d2059 Mon Sep 17 00:00:00 2001 From: Jeff Burn Date: Mon, 19 Dec 2016 11:49:43 +1100 Subject: [PATCH 06/43] Fix #185: Validation failures crash server Fixes issue where upload and download methods in FileSystemProvider cause crashes in downstream methods by not returning streams in error scenarios - Add streamError, readStreamError, writeStreamError helper function - Wrap all returns from upload / download methods in streams - Fix incorrect format string - Add new unit tests --- lib/providers/filesystem/index.js | 46 ++++++++++++++++++++++++++----- test/files/.gitignore | 1 + test/fs.test.js | 31 ++++++++++++++++++++- 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 9e6dcbd..5c0e88d 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -13,6 +13,7 @@ var g = require('strong-globalize')(); var fs = require('fs'), path = require('path'), + stream = require('stream'), async = require('async'), File = require('./file').File, Container = require('./container').Container; @@ -56,12 +57,23 @@ function validateName(name, cb) { cb && process.nextTick(cb.bind(null, new Error(g.f('{{FileSystemProvider}}: Invalid name: %s', name)))); if (!cb) { - console.error(g.f('{{FileSystemProvider}}: Invalid name: ', name)); + console.error(g.f('{{FileSystemProvider}}: Invalid name: %s', name)); } return false; } } +function streamError(errStream, err, cb) { + process.nextTick(function() { + errStream.emit('error', err); + cb && cb(null, err); + }); + return errStream; +} + +var writeStreamError = streamError.bind(null, new stream.Writable()); +var readStreamError = streamError.bind(null, new stream.Readable()); + /*! * Populate the metadata from file stat into props * @param {fs.Stats} stat The file stat instance @@ -166,9 +178,19 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) { // File related functions FileSystemProvider.prototype.upload = function(options, cb) { var container = options.container; - if (!validateName(container, cb)) return; + if (!validateName(container)) { + return writeStreamError( + new Error(g.f('{{FileSystemProvider}}: Invalid name: %s', container)), + cb + ); + } var file = options.remote; - if (!validateName(file, cb)) return; + if (!validateName(file)) { + return writeStreamError( + new Error(g.f('{{FileSystemProvider}}: Invalid name: %s', file)), + cb + ); + } var filePath = path.join(this.root, container, file); var fileOpts = {flags: options.flags || 'w+', @@ -186,15 +208,25 @@ FileSystemProvider.prototype.upload = function(options, cb) { }); return stream; } catch (e) { - cb && cb(e); + return writeStreamError(e, cb); } }; FileSystemProvider.prototype.download = function(options, cb) { var container = options.container; - if (!validateName(container, cb)) return; + if (!validateName(container, cb)) { + return readStreamError( + new Error(g.f('{{FileSystemProvider}}: Invalid name: %s', container)), + cb + ); + } var file = options.remote; - if (!validateName(file, cb)) return; + if (!validateName(file, cb)) { + return readStreamError( + new Error(g.f('{{FileSystemProvider}}: Invalid name: %s', file)), + cb + ); + } var filePath = path.join(this.root, container, file); @@ -209,7 +241,7 @@ FileSystemProvider.prototype.download = function(options, cb) { try { return fs.createReadStream(filePath, fileOpts); } catch (e) { - cb && cb(e); + return readStreamError(e, cb); } }; diff --git a/test/files/.gitignore b/test/files/.gitignore index 7173ab8..b053536 100644 --- a/test/files/.gitignore +++ b/test/files/.gitignore @@ -1 +1,2 @@ +a-f1_downloaded.txt f1_downloaded.txt diff --git a/test/fs.test.js b/test/fs.test.js index a9f8c4b..5a2329e 100644 --- a/test/fs.test.js +++ b/test/fs.test.js @@ -110,6 +110,21 @@ describe('FileSystem based storage provider', function() { writer.on('error', done); }); + it('should fail to upload a file with invalid characters', function(done) { + var writer = client.upload({container: 'c1', remote: 'a/f1.txt'}); + fs.createReadStream(path.join(__dirname, 'files/f1.txt')).pipe(writer); + var cb = done; + var clearCb = function() {}; + writer.on('error', function() { + cb(); + cb = clearCb; + }); + writer.on('finish', function() { + cb(new Error('Should have finished with error callback')); + cb = clearCb; + }); + }); + it('should download a file', function(done) { var reader = client.download({ container: 'c1', @@ -120,6 +135,21 @@ describe('FileSystem based storage provider', function() { reader.on('error', done); }); + it('should fail to download a file with invalid characters', function(done) { + var reader = client.download({container: 'c1', remote: 'a/f1.txt'}); + reader.pipe(fs.createWriteStream(path.join(__dirname, 'files/a-f1_downloaded.txt'))); + var cb = done; + var clearCb = function() {}; + reader.on('error', function() { + cb(); + cb = clearCb; + }); + reader.on('end', function() { + cb(new Error('Expected error: Invalid name')); + cb = clearCb; + }); + }); + it('should get files for a container', function(done) { client.getFiles('c1', function(err, files) { assert(!err); @@ -161,4 +191,3 @@ describe('FileSystem based storage provider', function() { }); }); }); - From 8a847ea7056bc86cfce1580a894b21e88a8ab97e Mon Sep 17 00:00:00 2001 From: Siddhi Pai Date: Mon, 13 Feb 2017 10:26:24 -0800 Subject: [PATCH 07/43] Replicate issue_template from loopback repo --- .github/ISSUE_TEMPLATE.md | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index ccc915a..c8b30b2 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,36 +1,21 @@ - - -### Bug or feature request - - - -- [ ] Bug -- [ ] Feature request - -### Description of feature (or steps to reproduce if bug) - - - -### Link to sample repo to reproduce issue (if bug) +Immediate support is available through our subscription plans, +see https://strongloop.com/api-connect-faqs/ --> +### Bug/Feature request + ### Expected result + +### Additional information -### Actual result (if bug) - - - -### Additional information (Node.js version, LoopBack version, etc) - + From 4d392e84ad9cada3999cb4bd1bf602710f80073c Mon Sep 17 00:00:00 2001 From: Siddhi Pai Date: Wed, 15 Feb 2017 15:28:27 -0800 Subject: [PATCH 08/43] Replicate new issue_template from loopback --- .github/ISSUE_TEMPLATE.md | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index c8b30b2..269b11d 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,21 +1,29 @@ - -Immediate support is available through our subscription plans, -see https://strongloop.com/api-connect-faqs/ --> +# Description/Steps to reproduce -### Bug/Feature request + - +# Expected result -### Expected result + - +# Additional information -### Additional information - - + From 656fba9d515c79f1c51ff2d3a74786155cab8da2 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Wed, 1 Mar 2017 15:18:26 -0800 Subject: [PATCH 09/43] Fix eslint --- .eslintignore | 1 + lib/factory.js | 4 ++-- lib/storage-handler.js | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.eslintignore b/.eslintignore index e69de29..3c3629e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -0,0 +1 @@ +node_modules diff --git a/lib/factory.js b/lib/factory.js index 822bf60..52d1510 100644 --- a/lib/factory.js +++ b/lib/factory.js @@ -91,7 +91,7 @@ function createClient(options) { // Fall back to pkgcloud handler = require('pkgcloud').storage; } - } catch(err) { + } catch (err) { // Fall back to pkgcloud handler = require('pkgcloud').storage; } @@ -113,7 +113,7 @@ function getProvider(provider) { try { // Fall back to using an external provider return require(provider); - } catch(err) { + } catch (err) { // Fall back to pkgcloud return require('pkgcloud').providers[provider]; } diff --git a/lib/storage-handler.js b/lib/storage-handler.js index b5a6240..f14a8f7 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -287,7 +287,6 @@ exports.download = function(provider, req, res, container, file, cb) { }; }; - function processError(err, fileName) { if (err.code === 'ENOENT') { err.statusCode = err.status = 404; From 82878077ffd71485b4258deedd4c2a4c0c907cd6 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Wed, 1 Mar 2017 15:33:45 -0800 Subject: [PATCH 10/43] 3.1.0 * Fix eslint (Raymond Feng) * Replicate new issue_template from loopback (Siddhi Pai) * Fix insert of finalNewLine (Loay) * Replicate issue_template from loopback repo (Siddhi Pai) * fix lint (Raymond Camden) * Support nameConflict and makeUnique options (Raymond Camden) * Fix #185: Validation failures crash server (Jeff Burn) * fix scope error (ole3021) * added file field name into getFilename function (Jose De Gouveia) * added file field name into getFilename function in storage-handler (Jose De Gouveia) * Added support for external providers as npm modules. (Cristobal Vergara) * added maxFieldsSize override to formidable limit (Oscar Bernal) --- CHANGES.md | 28 ++++++++++++++++++++++++++++ package.json | 4 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 97e11e6..0e5bcec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,31 @@ +2017-03-01, Version 3.1.0 +========================= + + * Fix eslint (Raymond Feng) + + * Replicate new issue_template from loopback (Siddhi Pai) + + * Fix insert of finalNewLine (Loay) + + * Replicate issue_template from loopback repo (Siddhi Pai) + + * fix lint (Raymond Camden) + + * Support nameConflict and makeUnique options (Raymond Camden) + + * Fix #185: Validation failures crash server (Jeff Burn) + + * fix scope error (ole3021) + + * added file field name into getFilename function (Jose De Gouveia) + + * added file field name into getFilename function in storage-handler (Jose De Gouveia) + + * Added support for external providers as npm modules. (Cristobal Vergara) + + * added maxFieldsSize override to formidable limit (Oscar Bernal) + + 2017-02-10, Version 3.0.1 ========================= diff --git a/package.json b/package.json index eea04d2..c2816b3 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "engines": { "node": ">=4" }, - "version": "3.0.1", + "version": "3.1.0", "main": "index.js", "scripts": { "lint": "eslint .", @@ -16,7 +16,7 @@ "formidable": "^1.0.16", "pkgcloud": "^1.1.0", "strong-globalize": "^2.6.2", - "uuid":"^3.0.1" + "uuid": "^3.0.1" }, "devDependencies": { "eslint": "^2.13.1", From 636692a8a52182e0155bb617b4900827a2c8c68d Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Thu, 9 Mar 2017 08:22:03 -0800 Subject: [PATCH 11/43] Update deps --- lib/providers/filesystem/index.js | 4 ++-- package.json | 10 +++++----- test/upload-download.test.js | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index a0fd84d..a941587 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -201,8 +201,8 @@ FileSystemProvider.prototype.upload = function(options, cb) { }; try { - //simulate the success event in filesystem provider - //fixes: https://github.com/strongloop/loopback-component-storage/issues/58 + // simulate the success event in filesystem provider + // fixes: https://github.com/strongloop/loopback-component-storage/issues/58 // & #23 & #67 var stream = fs.createWriteStream(filePath, fileOpts); stream.on('finish', function() { diff --git a/package.json b/package.json index c2816b3..2c7f0aa 100644 --- a/package.json +++ b/package.json @@ -12,20 +12,20 @@ "posttest": "npm run lint" }, "dependencies": { - "async": "^0.9.0", + "async": "^2.1.5", "formidable": "^1.0.16", "pkgcloud": "^1.1.0", "strong-globalize": "^2.6.2", "uuid": "^3.0.1" }, "devDependencies": { - "eslint": "^2.13.1", - "eslint-config-loopback": "^4.0.0", + "eslint": "^3.17.1", + "eslint-config-loopback": "^8.0.0", "express": "^4.11.0", "loopback": "^3.0.0", "mkdirp": "^0.5.0", - "mocha": "^2.1.0", - "supertest": "^0.15.0", + "mocha": "^3.2.0", + "supertest": "^3.0.0", "semver": "^5.3.0" }, "repository": { diff --git a/test/upload-download.test.js b/test/upload-download.test.js index 4c2c4db..18c041b 100644 --- a/test/upload-download.test.js +++ b/test/upload-download.test.js @@ -14,7 +14,7 @@ var path = require('path'); // configure errorHandler to show full error message app.set('remoting', {errorHandler: {debug: true, log: false}}); -//custom route with renamer +// custom route with renamer app.post('/custom/upload', function(req, res, next) { var options = { container: 'album1', From 6551b744ff8a58b6e551e9a60e9d127d8cfabbd2 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Thu, 9 Mar 2017 08:22:23 -0800 Subject: [PATCH 12/43] 3.2.0 * Update deps (Raymond Feng) --- CHANGES.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 0e5bcec..d7ba551 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +2017-03-09, Version 3.2.0 +========================= + + * Update deps (Raymond Feng) + + 2017-03-01, Version 3.1.0 ========================= diff --git a/package.json b/package.json index 2c7f0aa..90739b5 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "engines": { "node": ">=4" }, - "version": "3.1.0", + "version": "3.2.0", "main": "index.js", "scripts": { "lint": "eslint .", From 8189c5c99110fec737ddd9d600e0100765ee49a7 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Mon, 31 Jul 2017 21:52:33 -0400 Subject: [PATCH 13/43] add .travis.yml --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..dd338dd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - "4" + - "6" + - "8" From ab71df42cccacf2131eea635f51b29c2f9e3324b Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Tue, 1 Aug 2017 21:51:04 -0400 Subject: [PATCH 14/43] update messages.json --- intl/en/messages.json | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/intl/en/messages.json b/intl/en/messages.json index 41f4dca..06a89c1 100644 --- a/intl/en/messages.json +++ b/intl/en/messages.json @@ -1,10 +1,9 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Path does not exist: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Invalid name: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Invalid name: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Invalid name: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Invalid directory: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} exceeded, received {0} bytes of field data (max is {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Invalid name: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" is not allowed (Must be in [{1}])", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} exceeded, received {0} bytes of field data" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} exceeded, received {0} bytes of field data", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Invalid name: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Invalid directory: {0}" } From d8b76ec0f625f400a3c369dedbc79ad928db3ea6 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Mon, 24 Jul 2017 19:47:21 -0400 Subject: [PATCH 15/43] Add CODEOWNER file --- CODEOWNERS | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..e8cad33 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,6 @@ +# Lines starting with '#' are comments. +# Each line is a file pattern followed by one or more owners, +# the last matching pattern has the most precendence. + +# Core team members from IBM +* @kjdelisle @jannyHou @loay @b-admike @ssh24 @virkt25 @dhmlau From 4d37716b58dad7d95c20e9f148ff3192a516a9ad Mon Sep 17 00:00:00 2001 From: Allen Boone Date: Thu, 10 Aug 2017 15:27:31 -0400 Subject: [PATCH 16/43] Update translated strings Q3 2017 --- intl/de/messages.json | 9 ++++----- intl/es/messages.json | 9 ++++----- intl/fr/messages.json | 9 ++++----- intl/it/messages.json | 9 ++++----- intl/ja/messages.json | 9 ++++----- intl/ko/messages.json | 9 ++++----- intl/nl/messages.json | 9 ++++----- intl/pt/messages.json | 9 ++++----- intl/tr/messages.json | 9 ++++----- intl/zh-Hans/messages.json | 9 ++++----- intl/zh-Hant/messages.json | 9 ++++----- 11 files changed, 44 insertions(+), 55 deletions(-) diff --git a/intl/de/messages.json b/intl/de/messages.json index d0bb679..8125dae 100644 --- a/intl/de/messages.json +++ b/intl/de/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Pfad ist nicht vorhanden: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ungültiger Name: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Ungültiger Name: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Ungültiger Name: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ungültiges Verzeichnis: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} überschritten, {0} Byte Felddaten erhalten (Maximum ist {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ungültiger Name: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" ist nicht zulässig (muss in [{1}] sein)", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} überschritten, {0} Byte Felddaten erhalten" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} überschritten, {0} Byte Felddaten erhalten", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Ungültiger Name: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ungültiges Verzeichnis: {0}" } diff --git a/intl/es/messages.json b/intl/es/messages.json index fcde445..4486e1b 100644 --- a/intl/es/messages.json +++ b/intl/es/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: La vía de acceso no existe: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nombre no válido: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Nombre no válido: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Nombre no válido: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directorio no válido: {0}", "45c1c136e750c62179d75a1c99151281": "Se ha superado {{maxFileSize}}, se han recibido {0} bytes de datos de campo (el máximo es {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nombre no válido: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" no está permitido (Debe estar en [{1}])", - "b8a9e184534171cf66caf58d29ad76f5": "Se ha superado {{maxFieldsSize}}, se han recibido {0} bytes de datos de campo" + "b8a9e184534171cf66caf58d29ad76f5": "Se ha superado {{maxFieldsSize}}, se han recibido {0} bytes de datos de campo", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Nombre no válido: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directorio no válido: {0}" } diff --git a/intl/fr/messages.json b/intl/fr/messages.json index 89033f7..b91cc63 100644 --- a/intl/fr/messages.json +++ b/intl/fr/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}} : Le chemin n'existe pas : {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}} : Nom invalide : {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}} : Nom invalide : ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Nom invalide : {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}} : Répertoire non valide : {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} dépassé, réception de {0} octets de données de zone (max est {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}} : Nom invalide : {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" n'est pas autorisé (Doit être dans [{1}])", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} dépassé, réception de {0} octets de données de zone" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} dépassé, réception de {0} octets de données de zone", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Nom invalide : {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}} : Répertoire non valide : {0}" } diff --git a/intl/it/messages.json b/intl/it/messages.json index 1b13054..fe8d6d4 100644 --- a/intl/it/messages.json +++ b/intl/it/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Il percorso non esiste: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome non valido: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Nome non valido: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Nome non valido: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directory non valida: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} superata, sono stati ricevuti {0} byte di dati del campo (il valore massimo è {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome non valido: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" non è consentito (deve essere in [{1}])", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} superata, sono stati ricevuti {0} byte di dati del campo" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} superata, sono stati ricevuti {0} byte di dati del campo", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Nome non valido: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Directory non valida: {0}" } diff --git a/intl/ja/messages.json b/intl/ja/messages.json index 102e052..5258483 100644 --- a/intl/ja/messages.json +++ b/intl/ja/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: パスが存在しません: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 名前が無効です: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: 名前が無効です: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "名前が無効です: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: ディレクトリーが無効です: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} を超過しました。{0} バイトのフィールド・データを受信しました (最大 {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 名前が無効です: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" は許可されていません ([{1}] でなければなりません)", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} を超過しました。{0} バイトのフィールド・データを受信しました" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} を超過しました。{0} バイトのフィールド・データを受信しました", + "c9fb0aba850059a14f4ed5e045e4ec3e": "名前が無効です: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: ディレクトリーが無効です: {0}" } diff --git a/intl/ko/messages.json b/intl/ko/messages.json index fb38f53..580e840 100644 --- a/intl/ko/messages.json +++ b/intl/ko/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: 경로가 존재하지 않음: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 올바르지 않은 이름: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: 올바르지 않은 이름: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "올바르지 않은 이름: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: 올바르지 않은 디렉토리: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}}이(가) 초과되었습니다. {0}바이트의 필드 데이터를 받았습니다(최대값 {1}).", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: 올바르지 않은 이름: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\"이(가) 허용되지 않습니다([{1}]에 있어야 함).", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}}이(가) 초과되었습니다. {0}바이트의 필드 데이터를 받았습니다." + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}}이(가) 초과되었습니다. {0}바이트의 필드 데이터를 받았습니다.", + "c9fb0aba850059a14f4ed5e045e4ec3e": "올바르지 않은 이름: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: 올바르지 않은 디렉토리: {0}" } diff --git a/intl/nl/messages.json b/intl/nl/messages.json index 427eb47..943e96f 100644 --- a/intl/nl/messages.json +++ b/intl/nl/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Pad bestaat niet: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ongeldige naam: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}Ongeldige naam: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Ongeldige naam: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ongeldige directory: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} overschreden, {0} bytes aan veldgegevens ontvangen (max is {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Ongeldige naam: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" is niet toegestaan (moet vallen in [{1}])", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} overschreden, {0} bytes aan veldgegevens ontvangen" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} overschreden, {0} bytes aan veldgegevens ontvangen", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Ongeldige naam: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Ongeldige directory: {0}" } diff --git a/intl/pt/messages.json b/intl/pt/messages.json index 75f85c0..a7b579b 100644 --- a/intl/pt/messages.json +++ b/intl/pt/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Caminho não existe: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome inválido: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Nome inválido: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Nome inválido: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Diretório inválido: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} excedido, recebidos {0} bytes de dados do campo (máximo é {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Nome inválido: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" não é permitido (deve estar em [{1}])", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} excedido, recebidos {0} bytes de dados do campo" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} excedido, recebidos {0} bytes de dados do campo", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Nome inválido: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Diretório inválido: {0}" } diff --git a/intl/tr/messages.json b/intl/tr/messages.json index 047a5f2..34b40d6 100644 --- a/intl/tr/messages.json +++ b/intl/tr/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}: Yol yok: {0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Geçersiz ad: {0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}: Geçersiz ad: ", - "c9fb0aba850059a14f4ed5e045e4ec3e": "Geçersiz ad: {0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Geçersiz dizin: {0}", "45c1c136e750c62179d75a1c99151281": "{{maxFileSize}} aşıldı, {0} baytlık alan verisi alındı (üst sınır {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}: Geçersiz ad: {0}", "78f6f36e8300e15cff778496fb1dd178": "{{contentType}} \"{0}\" kullanılamaz ([{1}] içinde olmalıdır)", - "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} aşıldı, {0} baytlık alan verisi alındı" + "b8a9e184534171cf66caf58d29ad76f5": "{{maxFieldsSize}} aşıldı, {0} baytlık alan verisi alındı", + "c9fb0aba850059a14f4ed5e045e4ec3e": "Geçersiz ad: {0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}: Geçersiz dizin: {0}" } diff --git a/intl/zh-Hans/messages.json b/intl/zh-Hans/messages.json index 33b6a0b..e514e60 100644 --- a/intl/zh-Hans/messages.json +++ b/intl/zh-Hans/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}:路径不存在:{0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:无效名称:{0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}:无效名称", - "c9fb0aba850059a14f4ed5e045e4ec3e": "无效名称:{0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:无效目录:{0}", "45c1c136e750c62179d75a1c99151281": "已超过 {{maxFileSize}},收到 {0} 字节字段数据(最大为 {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:无效名称:{0}", "78f6f36e8300e15cff778496fb1dd178": "不允许 {{contentType}}“{0}”(必须在 [{1}] 中)", - "b8a9e184534171cf66caf58d29ad76f5": "已超过 {{maxFieldsSize}},收到 {0} 字节字段数据" + "b8a9e184534171cf66caf58d29ad76f5": "已超过 {{maxFieldsSize}},收到 {0} 字节字段数据", + "c9fb0aba850059a14f4ed5e045e4ec3e": "无效名称:{0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:无效目录:{0}" } diff --git a/intl/zh-Hant/messages.json b/intl/zh-Hant/messages.json index 072f4a1..b69d1ea 100644 --- a/intl/zh-Hant/messages.json +++ b/intl/zh-Hant/messages.json @@ -1,11 +1,10 @@ { "2eb418c4dc7f7a3e989bb71a8f5388d7": "{{FileSystemProvider}}:路徑不存在:{0}", - "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:無效名稱:{0}", - "95065f7f9499f75f49e3714aa4e2031d": "{{FileSystemProvider}}:無效名稱:", - "c9fb0aba850059a14f4ed5e045e4ec3e": "無效名稱:{0}", - "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:無效目錄:{0}", "45c1c136e750c62179d75a1c99151281": "已超出 {{maxFileSize}},收到 {0} 位元組的欄位資料(最大值為 {1})", + "6af59b6408b92f4c6b13a2c9b06379f2": "{{FileSystemProvider}}:無效名稱:{0}", "78f6f36e8300e15cff778496fb1dd178": "不接受 {{contentType}} \"{0}\"(必須在 [{1}] 中)", - "b8a9e184534171cf66caf58d29ad76f5": "已超出 {{maxFieldsSize}},收到 {0} 位元組的欄位資料" + "b8a9e184534171cf66caf58d29ad76f5": "已超出 {{maxFieldsSize}},收到 {0} 位元組的欄位資料", + "c9fb0aba850059a14f4ed5e045e4ec3e": "無效名稱:{0}", + "f589fe721f4e6fa112d1f66081ed29ac": "{{FileSystemProvider}}:無效目錄:{0}" } From ea5e9807a4083d214e88cf98573ab61abf42dd11 Mon Sep 17 00:00:00 2001 From: Sakib Hasan Date: Wed, 16 Aug 2017 14:27:54 -0400 Subject: [PATCH 17/43] Create Issue and PR Templates (#218) * create issue template * create pr template --- .github/ISSUE_TEMPLATE.md | 10 +++++++++- .github/PULL_REQUEST_TEMPLATE.md | 9 +++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 269b11d..795176c 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -11,7 +11,15 @@ Immediate support: + +# Link to reproduction sandbox + + # Expected result diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d2b240f..368cb4c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,17 +6,18 @@ -- None +- connect to ### Checklist - [ ] New tests added or existing tests modified to cover all changes From d29f47c538484afd2c1897986a4dbf8de9c869f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:28:54 -0300 Subject: [PATCH 18/43] Actualizar README --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index ea8a88e..88e0979 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,22 @@ storage services including: For more details on the architecture of the module, please see the introduction section of the [blog post](https://strongloop.com/strongblog/managing-nodejs-loopback-storage-service-provider/) written up its launch. +## Use +Now you can use Container's name with slash! If you want to create a directory, like `this/isMy/newContainer`, you have to use the char `%2F` instead of `/`, so your Container's name going to be `this%2FisMy%2FnewContainer`. + +## URL Example +Syntax +``` +[POST] <>:<>/api/Containers/<>/ +[POST] <>:<>/api/Containers/<>/upload (For upload file) +``` + +Example +``` +[POST] http://example.com:3000/api/Containers/images%2Fprofile%2Fpersonal/ +[POST] http://example.com:3000/api/Containers/images%2Fprofile%2Fpersonal/upload (For upload file) +``` + ## Examples See https://github.com/strongloop/loopback-example-storage. From 71e0d5255fd12c5e9972305c67e3e71e4bd459bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:45:47 -0300 Subject: [PATCH 19/43] Actualizar dependencias --- package.json | 1 + 1 file changed, 1 insertion(+) mode change 100644 => 100755 package.json diff --git a/package.json b/package.json old mode 100644 new mode 100755 index 90739b5..b8bfec5 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dependencies": { "async": "^2.1.5", "formidable": "^1.0.16", + "mkdirp": "^0.5.1", "pkgcloud": "^1.1.0", "strong-globalize": "^2.6.2", "uuid": "^3.0.1" From 46e681dd47885cfb83e41dbc3165788e8a1c1635 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:46:20 -0300 Subject: [PATCH 20/43] Verificar que nombre de Contenedor es un string --- lib/providers/filesystem/index.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index a941587..6dcc5fd 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -124,6 +124,8 @@ FileSystemProvider.prototype.getContainers = function(cb) { FileSystemProvider.prototype.createContainer = function(options, cb) { var self = this; var name = options.name; + var hasSlash = (typeof name == 'string' ? name.search('%2F') : false); + name = (hasSlash != -1 ? name.replace(/%2F/gi, '/') : name); var dir = path.join(this.root, name); validateName(name, cb) && fs.mkdir(dir, options, function(err) { if (err) { @@ -180,12 +182,8 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) { // File related functions FileSystemProvider.prototype.upload = function(options, cb) { var container = options.container; - if (!validateName(container)) { - return writeStreamError( - new Error(g.f('{{FileSystemProvider}}: Invalid name: %s', container)), - cb - ); - } + var hasSlash = (typeof container == 'string' ? container.search('%2F') : false); + container = (hasSlash != -1 ? container.replace(/%2F/gi, '/') : container); var file = options.remote; if (!validateName(file)) { return writeStreamError( From 22ddb136b1b80620e670d506a2c87a58715729dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:46:40 -0300 Subject: [PATCH 21/43] Verificar si existe dataSources.json --- lib/storage-handler.js | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/lib/storage-handler.js b/lib/storage-handler.js index cc7a444..e9d60fa 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -11,11 +11,31 @@ var IncomingForm = require('formidable'); var StringDecoder = require('string_decoder').StringDecoder; var path = require('path'); var uuid = require('uuid'); - -var defaultOptions = { - maxFileSize: 10 * 1024 * 1024, // 10 MB +var fs = require('fs'); +var defaultOptions = function() { + var dataSources = path.join(__dirname, '../../../server/datasources.json'); + fs.stat(dataSources, function(err, stats) { + if(!error) { + return require(dataSources).container; + } else { + return false; + } + }); }; +var isImage = function(ext) { + switch(ext) { + case '.jpg': + case '.jpeg': + case '.png': + return true; + break; + default: + return false; + break; + } +} + /** * Handle multipart/form-data upload to the storage service * @param {Object} provider The storage service provider From d152ca900acc2308ca6058763f81f9633cfc31db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:50:11 -0300 Subject: [PATCH 22/43] Explicar nueva funcionalidad en README --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 88e0979..d139e3f 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,22 @@ Example [POST] http://example.com:3000/api/Containers/images%2Fprofile%2Fpersonal/upload (For upload file) ``` +## Add option to your dataSources.json +If you want a default name only for the upload images (not files), you have to add `defaultImageName` to your Container options. +**datasources.json** +``` +[...] + "container": { + "name": "container", + "connector": "loopback-component-storage", + "provider": "filesystem", + "maxFileSize": "10485760", + "root": "./storage", + "defaultImageName": "photo" + } +[...] + ``` + ## Examples See https://github.com/strongloop/loopback-example-storage. From 9cefe77adef3dc205d002f852a7ecd47e83198c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 04:34:00 -0300 Subject: [PATCH 23/43] Arreglar error de test --- lib/providers/filesystem/index.js | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 6dcc5fd..8d0f038 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -124,22 +124,24 @@ FileSystemProvider.prototype.getContainers = function(cb) { FileSystemProvider.prototype.createContainer = function(options, cb) { var self = this; var name = options.name; - var hasSlash = (typeof name == 'string' ? name.search('%2F') : false); + var hasSlash = name.search('%2F'); name = (hasSlash != -1 ? name.replace(/%2F/gi, '/') : name); var dir = path.join(this.root, name); - validateName(name, cb) && fs.mkdir(dir, options, function(err) { - if (err) { - return cb && cb(err); + + mkdirp(dir, function(err) { + if(err) { + cb(err); + } else { + fs.stat(dir, function(err, stat) { + var container = null; + if(!err) { + var props = { name: name }; + populateMetadata(stat, props); + container = new Container(self, props); + } + cb(err, container); + }); } - fs.stat(dir, function(err, stat) { - var container = null; - if (!err) { - var props = {name: name}; - populateMetadata(stat, props); - container = new Container(self, props); - } - cb && cb(err, container); - }); }); }; @@ -182,7 +184,7 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) { // File related functions FileSystemProvider.prototype.upload = function(options, cb) { var container = options.container; - var hasSlash = (typeof container == 'string' ? container.search('%2F') : false); + var hasSlash = container.search('%2F'); container = (hasSlash != -1 ? container.replace(/%2F/gi, '/') : container); var file = options.remote; if (!validateName(file)) { From 955b1153f7ed97cfd275bc94661815e05eefb5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 04:42:06 -0300 Subject: [PATCH 24/43] Arreglar errores de eslint --- lib/providers/filesystem/index.js | 6 +++--- lib/storage-handler.js | 13 +++++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 8d0f038..842dca9 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -129,13 +129,13 @@ FileSystemProvider.prototype.createContainer = function(options, cb) { var dir = path.join(this.root, name); mkdirp(dir, function(err) { - if(err) { + if (err) { cb(err); } else { fs.stat(dir, function(err, stat) { var container = null; - if(!err) { - var props = { name: name }; + if (!err) { + var props = {name: name}; populateMetadata(stat, props); container = new Container(self, props); } diff --git a/lib/storage-handler.js b/lib/storage-handler.js index e9d60fa..8bfad14 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -15,7 +15,7 @@ var fs = require('fs'); var defaultOptions = function() { var dataSources = path.join(__dirname, '../../../server/datasources.json'); fs.stat(dataSources, function(err, stats) { - if(!error) { + if (!err) { return require(dataSources).container; } else { return false; @@ -24,7 +24,7 @@ var defaultOptions = function() { }; var isImage = function(ext) { - switch(ext) { + switch (ext) { case '.jpg': case '.jpeg': case '.png': @@ -34,7 +34,7 @@ var isImage = function(ext) { return false; break; } -} +}; /** * Handle multipart/form-data upload to the storage service @@ -93,9 +93,14 @@ exports.upload = function(provider, req, res, options, cb) { this._flushing++; + var fileName = part.filename; + var useDefaultname = (typeof defaultOptions.defaultImageName != 'undefined' ? + true : false); + var file = { container: container, - name: part.filename, + name: (isImage(path.extname(fileName)) && useDefaultname ? + defaultOptions.defaultImageName + path.extname(fileName) : fileName), type: part.mime, field: part.name, }; From d981e28ca1ee3b2671c100617222d9f3358e73ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:20:36 -0300 Subject: [PATCH 25/43] Crear contenedores y subir archivos con '/' --- lib/providers/filesystem/index.js | 7 ++++--- lib/storage-handler.js | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 842dca9..5a8870c 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -16,7 +16,8 @@ var fs = require('fs'), stream = require('stream'), async = require('async'), File = require('./file').File, - Container = require('./container').Container; + Container = require('./container').Container, + mkdirp = require('mkdirp'); module.exports.storage = module.exports; // To make it consistent with pkgcloud @@ -194,8 +195,8 @@ FileSystemProvider.prototype.upload = function(options, cb) { ); } var filePath = path.join(this.root, container, file); - - var fileOpts = {flags: options.flags || 'w+', + var fileOpts = { + flags: options.flags || 'w+', encoding: options.encoding || null, mode: options.mode || parseInt('0666', 8), }; diff --git a/lib/storage-handler.js b/lib/storage-handler.js index 8bfad14..bd66ad9 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -52,7 +52,7 @@ exports.upload = function(provider, req, res, options, cb) { } if (!options.maxFileSize) { - options.maxFileSize = defaultOptions.maxFileSize; + options.maxFileSize = defaultOptions.maxFileSize || 10 * 1024 * 1024; } var form = new IncomingForm(options); From 8f7fdfa20c17372140128f5f3507f12b0ef600cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:46:20 -0300 Subject: [PATCH 27/43] Verificar que nombre de Contenedor es un string --- lib/providers/filesystem/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 5a8870c..3d21f83 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -125,7 +125,7 @@ FileSystemProvider.prototype.getContainers = function(cb) { FileSystemProvider.prototype.createContainer = function(options, cb) { var self = this; var name = options.name; - var hasSlash = name.search('%2F'); + var hasSlash = (typeof name == 'string' ? name.search('%2F') : false); name = (hasSlash != -1 ? name.replace(/%2F/gi, '/') : name); var dir = path.join(this.root, name); @@ -185,7 +185,7 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) { // File related functions FileSystemProvider.prototype.upload = function(options, cb) { var container = options.container; - var hasSlash = container.search('%2F'); + var hasSlash = (typeof container == 'string' ? container.search('%2F') : false); container = (hasSlash != -1 ? container.replace(/%2F/gi, '/') : container); var file = options.remote; if (!validateName(file)) { From 7bd662151af2cdf1ca8620d82c287a92e2942fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:46:40 -0300 Subject: [PATCH 28/43] Verificar si existe dataSources.json --- lib/storage-handler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/storage-handler.js b/lib/storage-handler.js index bd66ad9..911b560 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -15,7 +15,7 @@ var fs = require('fs'); var defaultOptions = function() { var dataSources = path.join(__dirname, '../../../server/datasources.json'); fs.stat(dataSources, function(err, stats) { - if (!err) { + if(!error) { return require(dataSources).container; } else { return false; From 44ed5365782c450bba43328615227df567492603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 04:34:00 -0300 Subject: [PATCH 29/43] Arreglar error de test --- lib/providers/filesystem/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 3d21f83..5a8870c 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -125,7 +125,7 @@ FileSystemProvider.prototype.getContainers = function(cb) { FileSystemProvider.prototype.createContainer = function(options, cb) { var self = this; var name = options.name; - var hasSlash = (typeof name == 'string' ? name.search('%2F') : false); + var hasSlash = name.search('%2F'); name = (hasSlash != -1 ? name.replace(/%2F/gi, '/') : name); var dir = path.join(this.root, name); @@ -185,7 +185,7 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) { // File related functions FileSystemProvider.prototype.upload = function(options, cb) { var container = options.container; - var hasSlash = (typeof container == 'string' ? container.search('%2F') : false); + var hasSlash = container.search('%2F'); container = (hasSlash != -1 ? container.replace(/%2F/gi, '/') : container); var file = options.remote; if (!validateName(file)) { From 38b1b2fae6ca9d99dd2e5ba1335a4b30d040f636 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 04:42:06 -0300 Subject: [PATCH 30/43] Arreglar errores de eslint --- lib/storage-handler.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/storage-handler.js b/lib/storage-handler.js index 911b560..bd66ad9 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -15,7 +15,7 @@ var fs = require('fs'); var defaultOptions = function() { var dataSources = path.join(__dirname, '../../../server/datasources.json'); fs.stat(dataSources, function(err, stats) { - if(!error) { + if (!err) { return require(dataSources).container; } else { return false; From 4005a8fc2e35c9dd4a2e61d44c8f543fcb296480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 03:46:20 -0300 Subject: [PATCH 32/43] Verificar que nombre de Contenedor es un string --- lib/providers/filesystem/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 5a8870c..3d21f83 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -125,7 +125,7 @@ FileSystemProvider.prototype.getContainers = function(cb) { FileSystemProvider.prototype.createContainer = function(options, cb) { var self = this; var name = options.name; - var hasSlash = name.search('%2F'); + var hasSlash = (typeof name == 'string' ? name.search('%2F') : false); name = (hasSlash != -1 ? name.replace(/%2F/gi, '/') : name); var dir = path.join(this.root, name); @@ -185,7 +185,7 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) { // File related functions FileSystemProvider.prototype.upload = function(options, cb) { var container = options.container; - var hasSlash = container.search('%2F'); + var hasSlash = (typeof container == 'string' ? container.search('%2F') : false); container = (hasSlash != -1 ? container.replace(/%2F/gi, '/') : container); var file = options.remote; if (!validateName(file)) { From c0b546aa954676715124a30bd073ba9437e026e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 04:34:00 -0300 Subject: [PATCH 34/43] Arreglar error de test --- lib/providers/filesystem/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 3d21f83..5a8870c 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -125,7 +125,7 @@ FileSystemProvider.prototype.getContainers = function(cb) { FileSystemProvider.prototype.createContainer = function(options, cb) { var self = this; var name = options.name; - var hasSlash = (typeof name == 'string' ? name.search('%2F') : false); + var hasSlash = name.search('%2F'); name = (hasSlash != -1 ? name.replace(/%2F/gi, '/') : name); var dir = path.join(this.root, name); @@ -185,7 +185,7 @@ FileSystemProvider.prototype.getContainer = function(containerName, cb) { // File related functions FileSystemProvider.prototype.upload = function(options, cb) { var container = options.container; - var hasSlash = (typeof container == 'string' ? container.search('%2F') : false); + var hasSlash = container.search('%2F'); container = (hasSlash != -1 ? container.replace(/%2F/gi, '/') : container); var file = options.remote; if (!validateName(file)) { From 6b1f9ffc8d17fa0790b640e940a14c8a7bfcf95c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20Gonz=C3=A1lez=20Aravena?= Date: Tue, 15 Aug 2017 05:33:24 -0300 Subject: [PATCH 35/43] =?UTF-8?q?Arreglar=20petici=C3=B3n=20de=20archivo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/providers/filesystem/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/providers/filesystem/index.js b/lib/providers/filesystem/index.js index 5a8870c..1620db0 100644 --- a/lib/providers/filesystem/index.js +++ b/lib/providers/filesystem/index.js @@ -283,7 +283,6 @@ FileSystemProvider.prototype.getFiles = function(container, options, cb) { FileSystemProvider.prototype.getFile = function(container, file, cb) { var self = this; - if (!validateName(container, cb)) return; if (!validateName(file, cb)) return; var filePath = path.join(this.root, container, file); fs.stat(filePath, function(err, stat) { From 0180ac7b507c24cd2ed088cfa3dd37fec12e0e1a Mon Sep 17 00:00:00 2001 From: Kevin Delisle Date: Wed, 23 Aug 2017 08:27:24 -0400 Subject: [PATCH 36/43] Add stalebot configuration --- .github/stale.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000..bebe60a --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,23 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 60 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 14 +# Issues with these labels will never be considered stale +exemptLabels: + - pinned + - security + - critical + - p1 + - major +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: > + This issue has been closed due to continued inactivity. Thank you for your understanding. + If you believe this to be in error, please contact one of the code owners, + listed in the `CODEOWNERS` file at the top-level of this repository. From 7cf4d883ef02dd6096e7f42aa5a024bcb45bc6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Wed, 30 Aug 2017 15:09:02 +0200 Subject: [PATCH 37/43] Mark HTTP path parameters as required Per Swagger spec 2.0, parameters coming from the path must be marked as required. Before this change, the Swagger spec produced by loopback-swagger was not valid because path parameters were optional. Note that this commit does not fix the problem of the "uploaded" method which does not have any swagger-supported parameters now, and therefore the swagger spec will remain invalid (but with less errors). --- lib/storage-service.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/storage-service.js b/lib/storage-service.js index 021e16a..322b518 100644 --- a/lib/storage-service.js +++ b/lib/storage-service.js @@ -282,7 +282,7 @@ StorageService.prototype.getContainers.http = StorageService.prototype.getContainer.shared = true; StorageService.prototype.getContainer.accepts = [ - {arg: 'container', type: 'string'}, + {arg: 'container', type: 'string', required: true}, ]; StorageService.prototype.getContainer.returns = { arg: 'container', @@ -312,7 +312,7 @@ StorageService.prototype.destroyContainer.http = StorageService.prototype.getFiles.shared = true; StorageService.prototype.getFiles.accepts = [ - {arg: 'container', type: 'string'}, + {arg: 'container', type: 'string', required: true}, ]; StorageService.prototype.getFiles.returns = {arg: 'files', type: 'array', root: true}; StorageService.prototype.getFiles.http = @@ -320,8 +320,8 @@ StorageService.prototype.getFiles.http = StorageService.prototype.getFile.shared = true; StorageService.prototype.getFile.accepts = [ - {arg: 'container', type: 'string'}, - {arg: 'file', type: 'string'}, + {arg: 'container', type: 'string', required: true}, + {arg: 'file', type: 'string', required: true}, ]; StorageService.prototype.getFile.returns = {arg: 'file', type: 'object', root: true}; StorageService.prototype.getFile.http = @@ -329,8 +329,8 @@ StorageService.prototype.getFile.http = StorageService.prototype.removeFile.shared = true; StorageService.prototype.removeFile.accepts = [ - {arg: 'container', type: 'string'}, - {arg: 'file', type: 'string'}, + {arg: 'container', type: 'string', required: true}, + {arg: 'file', type: 'string', required: true}, ]; StorageService.prototype.removeFile.returns = {}; StorageService.prototype.removeFile.http = @@ -347,8 +347,8 @@ StorageService.prototype.upload.http = StorageService.prototype.download.shared = true; StorageService.prototype.download.accepts = [ - {arg: 'container', type: 'string', 'http': {source: 'path'}}, - {arg: 'file', type: 'string', 'http': {source: 'path'}}, + {arg: 'container', type: 'string', required: true, 'http': {source: 'path'}}, + {arg: 'file', type: 'string', required: true, 'http': {source: 'path'}}, {arg: 'req', type: 'object', 'http': {source: 'req'}}, {arg: 'res', type: 'object', 'http': {source: 'res'}}, ]; From 03a57672ea9c8305c53fcc2fe4f2eb36d957b16f Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Wed, 30 Aug 2017 08:30:15 -0700 Subject: [PATCH 38/43] 3.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Mark HTTP path parameters as required (Miroslav Bajtoš) * Add stalebot configuration (Kevin Delisle) * Create Issue and PR Templates (#218) (Sakib Hasan) * Update translated strings Q3 2017 (Allen Boone) * Add CODEOWNER file (Diana Lau) * update messages.json (Diana Lau) * add .travis.yml (Diana Lau) --- CHANGES.md | 18 ++++++++++++++++++ package.json | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index d7ba551..eb13fa5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,21 @@ +2017-08-30, Version 3.3.0 +========================= + + * Mark HTTP path parameters as required (Miroslav Bajtoš) + + * Add stalebot configuration (Kevin Delisle) + + * Create Issue and PR Templates (#218) (Sakib Hasan) + + * Update translated strings Q3 2017 (Allen Boone) + + * Add CODEOWNER file (Diana Lau) + + * update messages.json (Diana Lau) + + * add .travis.yml (Diana Lau) + + 2017-03-09, Version 3.2.0 ========================= diff --git a/package.json b/package.json index 90739b5..fa11bfd 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "engines": { "node": ">=4" }, - "version": "3.2.0", + "version": "3.3.0", "main": "index.js", "scripts": { "lint": "eslint .", From 47d555798cf189577326369a3355e4068287f5d3 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Wed, 30 Aug 2017 13:13:25 -0700 Subject: [PATCH 39/43] Declare container parameter for swagger spec Without this change, generated Swagger spec for the upload operation does not have `container` parameter even it's a variable on the path. As a result, the sepc fails validations. An optional `container` is added to the remote method. Conditional check is added to ensure backward compatibility. --- lib/storage-service.js | 29 +++++++++++++++++++++-------- test/images/album1/.gitignore | 3 ++- test/upload-download.test.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/lib/storage-service.js b/lib/storage-service.js index 322b518..dbb1d50 100644 --- a/lib/storage-service.js +++ b/lib/storage-service.js @@ -225,12 +225,21 @@ StorageService.prototype.removeFile = function(container, file, cb) { /** * Upload middleware for the HTTP request/response + * @param {String} [container] Container name * @param {Request} req Request object * @param {Response} res Response object * @param {Object} [options] Options for upload * @param {Function} cb Callback function */ -StorageService.prototype.upload = function(req, res, options, cb) { +StorageService.prototype.upload = function(container, req, res, options, cb) { + // Test if container is req for backward compatibility + if (typeof container === 'object' && container.url && container.method) { + // First argument is req, shift all args + cb = options; + options = res; + res = req; + req = container; + } if (!cb && 'function' === typeof options) { cb = options; options = {}; @@ -253,6 +262,9 @@ StorageService.prototype.upload = function(req, res, options, cb) { if (this.maxFieldsSize && !options.maxFieldsSize) { options.maxFieldsSize = this.maxFieldsSize; } + if (typeof container === 'string') { + options.container = container; + } return handler.upload(this.client, req, res, options, cb); }; @@ -282,7 +294,7 @@ StorageService.prototype.getContainers.http = StorageService.prototype.getContainer.shared = true; StorageService.prototype.getContainer.accepts = [ - {arg: 'container', type: 'string', required: true}, + {arg: 'container', type: 'string', required: true, 'http': {source: 'path'}}, ]; StorageService.prototype.getContainer.returns = { arg: 'container', @@ -304,7 +316,7 @@ StorageService.prototype.createContainer.http = StorageService.prototype.destroyContainer.shared = true; StorageService.prototype.destroyContainer.accepts = [ - {arg: 'container', type: 'string'}, + {arg: 'container', type: 'string', required: true, 'http': {source: 'path'}}, ]; StorageService.prototype.destroyContainer.returns = {}; StorageService.prototype.destroyContainer.http = @@ -312,7 +324,7 @@ StorageService.prototype.destroyContainer.http = StorageService.prototype.getFiles.shared = true; StorageService.prototype.getFiles.accepts = [ - {arg: 'container', type: 'string', required: true}, + {arg: 'container', type: 'string', required: true, 'http': {source: 'path'}}, ]; StorageService.prototype.getFiles.returns = {arg: 'files', type: 'array', root: true}; StorageService.prototype.getFiles.http = @@ -320,8 +332,8 @@ StorageService.prototype.getFiles.http = StorageService.prototype.getFile.shared = true; StorageService.prototype.getFile.accepts = [ - {arg: 'container', type: 'string', required: true}, - {arg: 'file', type: 'string', required: true}, + {arg: 'container', type: 'string', required: true, 'http': {source: 'path'}}, + {arg: 'file', type: 'string', required: true, 'http': {source: 'path'}}, ]; StorageService.prototype.getFile.returns = {arg: 'file', type: 'object', root: true}; StorageService.prototype.getFile.http = @@ -329,8 +341,8 @@ StorageService.prototype.getFile.http = StorageService.prototype.removeFile.shared = true; StorageService.prototype.removeFile.accepts = [ - {arg: 'container', type: 'string', required: true}, - {arg: 'file', type: 'string', required: true}, + {arg: 'container', type: 'string', required: true, 'http': {source: 'path'}}, + {arg: 'file', type: 'string', required: true, 'http': {source: 'path'}}, ]; StorageService.prototype.removeFile.returns = {}; StorageService.prototype.removeFile.http = @@ -338,6 +350,7 @@ StorageService.prototype.removeFile.http = StorageService.prototype.upload.shared = true; StorageService.prototype.upload.accepts = [ + {arg: 'container', type: 'string', required: true, 'http': {source: 'path'}}, {arg: 'req', type: 'object', 'http': {source: 'req'}}, {arg: 'res', type: 'object', 'http': {source: 'res'}}, ]; diff --git a/test/images/album1/.gitignore b/test/images/album1/.gitignore index 9084277..ea550c4 100644 --- a/test/images/album1/.gitignore +++ b/test/images/album1/.gitignore @@ -1,3 +1,4 @@ test.jpg image-*.jpg -customimagefield_test.jpg \ No newline at end of file +customimagefield_test.jpg +customimagefield1_test.jpg diff --git a/test/upload-download.test.js b/test/upload-download.test.js index 18c041b..7fb6025 100644 --- a/test/upload-download.test.js +++ b/test/upload-download.test.js @@ -32,6 +32,23 @@ app.post('/custom/upload', function(req, res, next) { }); }); +// custom route with renamer +app.post('/custom/uploadWithContainer', function(req, res, next) { + var options = { + getFilename: function(file, req, res) { + return file.field + '_' + file.name; + }, + }; + ds.connector.upload('album1', req, res, options, function(err, result) { + if (!err) { + res.setHeader('Content-Type', 'application/json'); + res.status(200).send({result: result}); + } else { + res.status(500).send(err); + } + }); +}); + // expose a rest api app.use(loopback.rest()); @@ -420,4 +437,20 @@ describe('storage service', function() { done(); }); }); + + it('should upload a file with container param', function(done) { + request('http://localhost:' + app.get('port')) + .post('/custom/uploadWithContainer') + .attach('customimagefield1', path.join(__dirname, './fixtures/test.jpg')) + .set('Accept', 'application/json') + .expect('Content-Type', /json/) + .expect(200, function(err, res) { + assert.deepEqual(res.body, {'result': {'files': {'customimagefield1': [ + {'container': 'album1', 'name': 'customimagefield1_test.jpg', + 'originalFilename': 'test.jpg', 'type': 'image/jpeg', + 'field': 'customimagefield1', 'size': 60475}, + ]}, 'fields': {}}}); + done(); + }); + }); }); From 3508b036d8e37288ddde752fd9e3bf3e48d3b371 Mon Sep 17 00:00:00 2001 From: Raymond Feng Date: Wed, 30 Aug 2017 13:54:54 -0700 Subject: [PATCH 40/43] 3.3.1 * Declare container parameter for swagger spec (Raymond Feng) --- CHANGES.md | 6 ++++++ package.json | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index eb13fa5..61912bb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,9 @@ +2017-08-30, Version 3.3.1 +========================= + + * Declare container parameter for swagger spec (Raymond Feng) + + 2017-08-30, Version 3.3.0 ========================= diff --git a/package.json b/package.json index fa11bfd..0ddd90a 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "engines": { "node": ">=4" }, - "version": "3.3.0", + "version": "3.3.1", "main": "index.js", "scripts": { "lint": "eslint .", From c2d5a5429e43c761ebae15f0e392be4fc6a4a854 Mon Sep 17 00:00:00 2001 From: Rand McKinney Date: Tue, 12 Sep 2017 10:11:20 -0700 Subject: [PATCH 41/43] Update README.md Add Google Cloud support to README --- README.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index ea8a88e..cdb082b 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,20 @@ **NOTE: The loopback-component-storage module supersedes [loopback-storage-service](https://www.npmjs.org/package/loopback-storage-service). Please update your package.json accordingly.** -LoopBack storage component provides Node.js and REST APIs to manage binary contents +LoopBack storage component provides Node.js and REST APIs to manage binary file contents using pluggable storage providers, such as local file systems, Amazon S3, or -Rackspace cloud files. We use [pkgcloud](https://github.com/pkgcloud/pkgcloud) to support the cloud based +Rackspace cloud files. It uses [pkgcloud](https://github.com/pkgcloud/pkgcloud) to support cloud-based storage services including: - Amazon -- Rackspace -- Openstack - Azure +- Google Cloud +- Openstack +- Rackspace -> Please see the [Storage Service Documentaion](http://loopback.io/doc/en/lb2/Storage-component.html). +> Please see the [Storage Service Documentaion](http://loopback.io/doc/en/lb3/Storage-component.html). -For more details on the architecture of the module, please see the introduction section of the [blog post](https://strongloop.com/strongblog/managing-nodejs-loopback-storage-service-provider/) written up its launch. +For more details on the architecture of the module, please see the introduction section of the [blog post](https://strongloop.com/strongblog/managing-nodejs-loopback-storage-service-provider/). ## Examples From e1109e39dd1260d1c4030bc972d5cd0039a7bd57 Mon Sep 17 00:00:00 2001 From: Timo Wolf Date: Sun, 8 Oct 2017 18:00:46 +0200 Subject: [PATCH 42/43] add AWS S3 options for server side encryption Now, the AWS S3 options for server side encryptions are passed to the upload handler. Thus, the client can specify the AWS options and use AWS Server Side Encryption. --- lib/storage-handler.js | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/storage-handler.js b/lib/storage-handler.js index cc7a444..a84ff50 100644 --- a/lib/storage-handler.js +++ b/lib/storage-handler.js @@ -141,6 +141,30 @@ exports.upload = function(provider, req, res, options, cb) { uploadParams.acl = file.acl; } + // add AWS specific options + // See http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property + if (options.StorageClass) { + uploadParams.StorageClass = options.StorageClass; + } + if (options.CacheControl) { + uploadParams.CacheControl = options.CacheControl; + } + if (options.ServerSideEncryption) { + uploadParams.ServerSideEncryption = options.ServerSideEncryption; + } + if (options.SSEKMSKeyId) { + uploadParams.SSEKMSKeyId = options.SSEKMSKeyId; + } + if (options.SSECustomerAlgorithm) { + uploadParams.SSECustomerAlgorithm = options.SSECustomerAlgorithm; + } + if (options.SSECustomerKey) { + uploadParams.SSECustomerKey = options.SSECustomerKey; + } + if (options.SSECustomerKeyMD5) { + uploadParams.SSECustomerKeyMD5 = options.SSECustomerKeyMD5; + } + var writer = provider.upload(uploadParams); writer.on('error', function(err) { From ac4a14a55a2ba61367a28f3aff86e6f49a9070f6 Mon Sep 17 00:00:00 2001 From: Diana Lau Date: Fri, 10 Nov 2017 17:54:11 -0500 Subject: [PATCH 43/43] chore: update license --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index a7161d5..3474cfc 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) IBM Corp. 2013,2016. All Rights Reserved. +Copyright (c) IBM Corp. 2013,2017. All Rights Reserved. Node module: loopback-component-storage This project is licensed under the Artistic License 2.0, full text below.