Skip to content

Commit 83b12bd

Browse files
authored
Conform to FilesAdapter Interface (#73)
* Conform to FilesAdapter Interface https://github.com/parse-community/parse-server/blob/master/src/Adapters/Files/FilesAdapter.js * Update .travis.yml
1 parent 03b6a7b commit 83b12bd

File tree

3 files changed

+141
-135
lines changed

3 files changed

+141
-135
lines changed

.eslintrc.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"no-multiple-empty-lines": 1,
1919
"no-underscore-dangle": 0,
2020
"no-new": 0,
21-
"func-names": 0,
2221
"prefer-destructuring": 0,
2322
"prefer-object-spread": 0
2423
}

.travis.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
language: node_js
22
node_js:
33
- 10.14.1
4+
branches:
5+
only:
6+
- master
7+
- "/^[0-9]+.[0-9]+.[0-9]+(-.*)?$/"
8+
- "/^greenkeeper/.*$/"
49
after_success: "./node_modules/.bin/codecov"
510
deploy:
611
provider: npm

index.js

Lines changed: 136 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -11,157 +11,159 @@ const awsCredentialsDeprecationNotice = function awsCredentialsDeprecationNotice
1111
'See: https://github.com/parse-server-modules/parse-server-s3-adapter#aws-credentials for details');
1212
};
1313

14-
// Creates an S3 session.
15-
// Providing AWS access, secret keys and bucket are mandatory
16-
// Region will use sane defaults if omitted
17-
function S3Adapter(...args) {
18-
const options = optionsFromArguments(args);
19-
this._region = options.region;
20-
this._bucket = options.bucket;
21-
this._bucketPrefix = options.bucketPrefix;
22-
this._directAccess = options.directAccess;
23-
this._baseUrl = options.baseUrl;
24-
this._baseUrlDirect = options.baseUrlDirect;
25-
this._signatureVersion = options.signatureVersion;
26-
this._globalCacheControl = options.globalCacheControl;
27-
this._encryption = options.ServerSideEncryption;
14+
class S3Adapter {
15+
// Creates an S3 session.
16+
// Providing AWS access, secret keys and bucket are mandatory
17+
// Region will use sane defaults if omitted
18+
constructor(...args) {
19+
const options = optionsFromArguments(args);
20+
this._region = options.region;
21+
this._bucket = options.bucket;
22+
this._bucketPrefix = options.bucketPrefix;
23+
this._directAccess = options.directAccess;
24+
this._baseUrl = options.baseUrl;
25+
this._baseUrlDirect = options.baseUrlDirect;
26+
this._signatureVersion = options.signatureVersion;
27+
this._globalCacheControl = options.globalCacheControl;
28+
this._encryption = options.ServerSideEncryption;
2829

29-
const s3Options = {
30-
params: { Bucket: this._bucket },
31-
region: this._region,
32-
signatureVersion: this._signatureVersion,
33-
globalCacheControl: this._globalCacheControl,
34-
};
35-
36-
if (options.accessKey && options.secretKey) {
37-
awsCredentialsDeprecationNotice();
38-
s3Options.accessKeyId = options.accessKey;
39-
s3Options.secretAccessKey = options.secretKey;
40-
}
30+
const s3Options = {
31+
params: { Bucket: this._bucket },
32+
region: this._region,
33+
signatureVersion: this._signatureVersion,
34+
globalCacheControl: this._globalCacheControl,
35+
};
4136

42-
Object.assign(s3Options, options.s3overrides);
37+
if (options.accessKey && options.secretKey) {
38+
awsCredentialsDeprecationNotice();
39+
s3Options.accessKeyId = options.accessKey;
40+
s3Options.secretAccessKey = options.secretKey;
41+
}
4342

44-
this._s3Client = new AWS.S3(s3Options);
45-
this._hasBucket = false;
46-
}
43+
Object.assign(s3Options, options.s3overrides);
4744

48-
S3Adapter.prototype.createBucket = function () {
49-
let promise;
50-
if (this._hasBucket) {
51-
promise = Promise.resolve();
52-
} else {
53-
promise = new Promise((resolve) => {
54-
this._s3Client.createBucket(() => {
55-
this._hasBucket = true;
56-
resolve();
57-
});
58-
});
45+
this._s3Client = new AWS.S3(s3Options);
46+
this._hasBucket = false;
5947
}
60-
return promise;
61-
};
6248

63-
// For a given config object, filename, and data, store a file in S3
64-
// Returns a promise containing the S3 object creation response
65-
S3Adapter.prototype.createFile = function (filename, data, contentType) {
66-
const params = {
67-
Key: this._bucketPrefix + filename,
68-
Body: data,
69-
};
70-
if (this._directAccess) {
71-
params.ACL = 'public-read';
72-
}
73-
if (contentType) {
74-
params.ContentType = contentType;
75-
}
76-
if (this._globalCacheControl) {
77-
params.CacheControl = this._globalCacheControl;
78-
}
79-
if (this._encryption === 'AES256' || this._encryption === 'aws:kms') {
80-
params.ServerSideEncryption = this._encryption;
49+
createBucket() {
50+
let promise;
51+
if (this._hasBucket) {
52+
promise = Promise.resolve();
53+
} else {
54+
promise = new Promise((resolve) => {
55+
this._s3Client.createBucket(() => {
56+
this._hasBucket = true;
57+
resolve();
58+
});
59+
});
60+
}
61+
return promise;
8162
}
82-
return this.createBucket().then(() => new Promise((resolve, reject) => {
83-
this._s3Client.upload(params, (err, response) => {
84-
if (err !== null) {
85-
return reject(err);
86-
}
87-
return resolve(response);
88-
});
89-
}));
90-
};
9163

92-
S3Adapter.prototype.deleteFile = function (filename) {
93-
return this.createBucket().then(() => new Promise((resolve, reject) => {
64+
// For a given config object, filename, and data, store a file in S3
65+
// Returns a promise containing the S3 object creation response
66+
createFile(filename, data, contentType) {
9467
const params = {
9568
Key: this._bucketPrefix + filename,
69+
Body: data,
9670
};
97-
this._s3Client.deleteObject(params, (err, data) => {
98-
if (err !== null) {
99-
return reject(err);
100-
}
101-
return resolve(data);
102-
});
103-
}));
104-
};
71+
if (this._directAccess) {
72+
params.ACL = 'public-read';
73+
}
74+
if (contentType) {
75+
params.ContentType = contentType;
76+
}
77+
if (this._globalCacheControl) {
78+
params.CacheControl = this._globalCacheControl;
79+
}
80+
if (this._encryption === 'AES256' || this._encryption === 'aws:kms') {
81+
params.ServerSideEncryption = this._encryption;
82+
}
83+
return this.createBucket().then(() => new Promise((resolve, reject) => {
84+
this._s3Client.upload(params, (err, response) => {
85+
if (err !== null) {
86+
return reject(err);
87+
}
88+
return resolve(response);
89+
});
90+
}));
91+
}
10592

106-
// Search for and return a file if found by filename
107-
// Returns a promise that succeeds with the buffer result from S3
108-
S3Adapter.prototype.getFileData = function (filename) {
109-
const params = { Key: this._bucketPrefix + filename };
110-
return this.createBucket().then(() => new Promise((resolve, reject) => {
111-
this._s3Client.getObject(params, (err, data) => {
112-
if (err !== null) {
113-
return reject(err);
114-
}
115-
// Something happened here...
116-
if (data && !data.Body) {
117-
return reject(data);
118-
}
119-
return resolve(data.Body);
120-
});
121-
}));
122-
};
93+
deleteFile(filename) {
94+
return this.createBucket().then(() => new Promise((resolve, reject) => {
95+
const params = {
96+
Key: this._bucketPrefix + filename,
97+
};
98+
this._s3Client.deleteObject(params, (err, data) => {
99+
if (err !== null) {
100+
return reject(err);
101+
}
102+
return resolve(data);
103+
});
104+
}));
105+
}
123106

124-
// Generates and returns the location of a file stored in S3 for the given request and filename
125-
// The location is the direct S3 link if the option is set,
126-
// otherwise we serve the file through parse-server
127-
S3Adapter.prototype.getFileLocation = function (config, filename) {
128-
const fileName = encodeURIComponent(filename);
129-
if (this._directAccess) {
130-
if (this._baseUrl && this._baseUrlDirect) {
131-
return `${this._baseUrl}/${fileName}`;
132-
} if (this._baseUrl) {
133-
return `${this._baseUrl}/${this._bucketPrefix + fileName}`;
134-
}
135-
return `https://${this._bucket}.s3.amazonaws.com/${this._bucketPrefix + fileName}`;
107+
// Search for and return a file if found by filename
108+
// Returns a promise that succeeds with the buffer result from S3
109+
getFileData(filename) {
110+
const params = { Key: this._bucketPrefix + filename };
111+
return this.createBucket().then(() => new Promise((resolve, reject) => {
112+
this._s3Client.getObject(params, (err, data) => {
113+
if (err !== null) {
114+
return reject(err);
115+
}
116+
// Something happened here...
117+
if (data && !data.Body) {
118+
return reject(data);
119+
}
120+
return resolve(data.Body);
121+
});
122+
}));
136123
}
137-
return (`${config.mount}/files/${config.applicationId}/${fileName}`);
138-
};
139124

140-
S3Adapter.prototype.handleFileStream = function (filename, req, res) {
141-
const params = {
142-
Key: this._bucketPrefix + filename,
143-
Range: req.get('Range'),
144-
};
145-
return this.createBucket().then(() => new Promise((resolve, reject) => {
146-
this._s3Client.getObject(params, (error, data) => {
147-
if (error !== null) {
148-
return reject(error);
125+
// Generates and returns the location of a file stored in S3 for the given request and filename
126+
// The location is the direct S3 link if the option is set,
127+
// otherwise we serve the file through parse-server
128+
getFileLocation(config, filename) {
129+
const fileName = encodeURIComponent(filename);
130+
if (this._directAccess) {
131+
if (this._baseUrl && this._baseUrlDirect) {
132+
return `${this._baseUrl}/${fileName}`;
133+
} if (this._baseUrl) {
134+
return `${this._baseUrl}/${this._bucketPrefix + fileName}`;
149135
}
150-
if (data && !data.Body) {
151-
return reject(data);
152-
}
153-
res.writeHead(206, {
154-
'Accept-Ranges': data.AcceptRanges,
155-
'Content-Length': data.ContentLength,
156-
'Content-Range': data.ContentRange,
157-
'Content-Type': data.ContentType,
136+
return `https://${this._bucket}.s3.amazonaws.com/${this._bucketPrefix + fileName}`;
137+
}
138+
return (`${config.mount}/files/${config.applicationId}/${fileName}`);
139+
}
140+
141+
handleFileStream(filename, req, res) {
142+
const params = {
143+
Key: this._bucketPrefix + filename,
144+
Range: req.get('Range'),
145+
};
146+
return this.createBucket().then(() => new Promise((resolve, reject) => {
147+
this._s3Client.getObject(params, (error, data) => {
148+
if (error !== null) {
149+
return reject(error);
150+
}
151+
if (data && !data.Body) {
152+
return reject(data);
153+
}
154+
res.writeHead(206, {
155+
'Accept-Ranges': data.AcceptRanges,
156+
'Content-Length': data.ContentLength,
157+
'Content-Range': data.ContentRange,
158+
'Content-Type': data.ContentType,
159+
});
160+
res.write(data.Body);
161+
res.end();
162+
return resolve(data.Body);
158163
});
159-
res.write(data.Body);
160-
res.end();
161-
return resolve(data.Body);
162-
});
163-
}));
164-
};
164+
}));
165+
}
166+
}
165167

166168
module.exports = S3Adapter;
167169
module.exports.default = S3Adapter;

0 commit comments

Comments
 (0)