Skip to content

Commit 041595d

Browse files
Mike Patnodedplewis
Mike Patnode
authored andcommitted
Move filename validation into adaptor for AWS "directories". Add preserveFileName Support (#76)
* Add support for the validateFilename method * Add AWS preserveFileName support with options for "directories" * Don't extend FilesAdapter (pre-emptive PR request) * Minor test improvements * Remove all dependencies. Bump version number * speling is hard * Don't encode / when returning urls. closes #75 * Make % safe * Allow filename validation and key generation to be methods * Parse.Error return type no longer required
1 parent fa3f3a5 commit 041595d

File tree

6 files changed

+227
-49
lines changed

6 files changed

+227
-49
lines changed

README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,14 @@ The preferred method is to use the default AWS credentials pattern. If no AWS c
6666
"baseUrlDirect": false, // default value
6767
"signatureVersion": 'v4', // default value
6868
"globalCacheControl": null, // default value. Or 'public, max-age=86400' for 24 hrs Cache-Control
69-
"ServerSideEncryption": 'AES256|aws:kms' //AES256 or aws:kms, or if you do not pass this, encryption won't be done
69+
"ServerSideEncryption": 'AES256|aws:kms', //AES256 or aws:kms, or if you do not pass this, encryption won't be done
70+
"validateFilename": null, // Default to parse-server FilesAdapter::validateFilename.
71+
"generateKey": null // Will default to Parse.FilesController.preserveFileName
7072
}
7173
}
7274
}
7375
```
76+
***Note*** By default Parse.FilesController.preserveFileName will prefix all filenames with a random hex code. You will want to disable that if you enable it here or wish to use S3 "directories".
7477

7578
### using environment variables
7679

@@ -109,7 +112,16 @@ var s3Adapter = new S3Adapter('accessKey',
109112
directAccess: false,
110113
baseUrl: 'http://images.example.com',
111114
signatureVersion: 'v4',
112-
globalCacheControl: 'public, max-age=86400' // 24 hrs Cache-Control.
115+
globalCacheControl: 'public, max-age=86400', // 24 hrs Cache-Control.
116+
validateFilename: (filename) => {
117+
if (filename.length > 1024) {
118+
return 'Filename too long.';
119+
}
120+
return null; // Return null on success
121+
},
122+
generateKey: (filename) => {
123+
return `${Date.now()}_${filename}`; // unique prefix for every filename
124+
}
113125
});
114126
115127
var api = new ParseServer({
@@ -145,7 +157,9 @@ var s3Options = {
145157
"directAccess": false, // default value
146158
"baseUrl": null // default value
147159
"signatureVersion": 'v4', // default value
148-
"globalCacheControl": null // default value. Or 'public, max-age=86400' for 24 hrs Cache-Control
160+
"globalCacheControl": null, // default value. Or 'public, max-age=86400' for 24 hrs Cache-Control
161+
"validateFilename": () => null, // Anything goes!
162+
"generateKey": (filename) => filename, // Ensure Parse.FilesController.preserveFileName is true!
149163
}
150164
151165
var s3Adapter = new S3Adapter(s3Options);

index.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ class S3Adapter {
2626
this._signatureVersion = options.signatureVersion;
2727
this._globalCacheControl = options.globalCacheControl;
2828
this._encryption = options.ServerSideEncryption;
29+
this._generateKey = options.generateKey;
30+
// Optional FilesAdaptor method
31+
this.validateFilename = options.validateFilename;
2932

3033
const s3Options = {
3134
params: { Bucket: this._bucket },
@@ -68,6 +71,11 @@ class S3Adapter {
6871
Key: this._bucketPrefix + filename,
6972
Body: data,
7073
};
74+
75+
if (this._generateKey instanceof Function) {
76+
params.Key = this._bucketPrefix + this._generateKey(filename);
77+
}
78+
7179
if (this._directAccess) {
7280
params.ACL = 'public-read';
7381
}
@@ -126,7 +134,7 @@ class S3Adapter {
126134
// The location is the direct S3 link if the option is set,
127135
// otherwise we serve the file through parse-server
128136
getFileLocation(config, filename) {
129-
const fileName = encodeURIComponent(filename);
137+
const fileName = filename.split('/').map(encodeURIComponent).join('/');
130138
if (this._directAccess) {
131139
if (this._baseUrl && this._baseUrlDirect) {
132140
return `${this._baseUrl}/${fileName}`;

lib/optionsFromArguments.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ const optionsFromArguments = function optionsFromArguments(args) {
6464
options.signatureVersion = otherOptions.signatureVersion;
6565
options.globalCacheControl = otherOptions.globalCacheControl;
6666
options.ServerSideEncryption = otherOptions.ServerSideEncryption;
67+
options.generateKey = otherOptions.generateKey;
68+
options.validateFilename = otherOptions.validateFilename;
6769
s3overrides = otherOptions.s3overrides;
6870
}
6971
} else if (args.length === 1) {
@@ -90,6 +92,8 @@ const optionsFromArguments = function optionsFromArguments(args) {
9092
options = fromEnvironmentOrDefault(options, 'baseUrlDirect', 'S3_BASE_URL_DIRECT', false);
9193
options = fromEnvironmentOrDefault(options, 'signatureVersion', 'S3_SIGNATURE_VERSION', 'v4');
9294
options = fromEnvironmentOrDefault(options, 'globalCacheControl', 'S3_GLOBAL_CACHE_CONTROL', null);
95+
options = fromOptionsDictionaryOrDefault(options, 'generateKey', null);
96+
options = fromOptionsDictionaryOrDefault(options, 'validateFilename', null);
9397

9498
return options;
9599
};

package-lock.json

Lines changed: 65 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@parse/s3-files-adapter",
3-
"version": "1.3.0",
3+
"version": "1.4.0",
44
"description": "AWS S3 adapter for parse-server",
55
"main": "index.js",
66
"scripts": {
@@ -25,7 +25,8 @@
2525
},
2626
"homepage": "https://github.com/parse-community/parse-server-s3-adapter#readme",
2727
"dependencies": {
28-
"aws-sdk": "^2.59.0"
28+
"aws-sdk": "^2.59.0",
29+
"parse": "^2.9.1"
2930
},
3031
"devDependencies": {
3132
"codecov": "^3.0.0",

0 commit comments

Comments
 (0)