Skip to content

Commit

Permalink
Add airbnb style guide to linter (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
dplewis authored Sep 11, 2019
1 parent 2990242 commit 03b6a7b
Show file tree
Hide file tree
Showing 6 changed files with 1,109 additions and 784 deletions.
11 changes: 8 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"root": true,
"extends": "eslint:recommended",
"extends": "airbnb-base",
"env": {
"node": true,
"es6": true
},
"parserOptions": {
"ecmaVersion": 6,
"ecmaVersion": 2018,
"sourceType": "module"
},
"rules": {
Expand All @@ -15,6 +15,11 @@
"no-trailing-spaces": 2,
"eol-last": 2,
"space-in-parens": ["error", "never"],
"no-multiple-empty-lines": 1
"no-multiple-empty-lines": 1,
"no-underscore-dangle": 0,
"no-new": 0,
"func-names": 0,
"prefer-destructuring": 0,
"prefer-object-spread": 0
}
}
165 changes: 78 additions & 87 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
'use strict';
// S3Adapter
//
// Stores Parse files in AWS S3.

var AWS = require('aws-sdk');
var optionsFromArguments = require('./lib/optionsFromArguments');
const AWS = require('aws-sdk');
const optionsFromArguments = require('./lib/optionsFromArguments');

const awsCredentialsDeprecationNotice = function awsCredentialsDeprecationNotice() {
// eslint-disable-next-line no-console
console.warn('Passing AWS credentials to this adapter is now DEPRECATED and will be removed in a future version',
'See: https://github.com/parse-server-modules/parse-server-s3-adapter#aws-credentials for details');
}
};

// Creates an S3 session.
// Providing AWS access, secret keys and bucket are mandatory
// Region will use sane defaults if omitted
function S3Adapter() {
var options = optionsFromArguments(arguments);
function S3Adapter(...args) {
const options = optionsFromArguments(args);
this._region = options.region;
this._bucket = options.bucket;
this._bucketPrefix = options.bucketPrefix;
Expand All @@ -27,11 +26,11 @@ function S3Adapter() {
this._globalCacheControl = options.globalCacheControl;
this._encryption = options.ServerSideEncryption;

let s3Options = {
const s3Options = {
params: { Bucket: this._bucket },
region: this._region,
signatureVersion: this._signatureVersion,
globalCacheControl: this._globalCacheControl
globalCacheControl: this._globalCacheControl,
};

if (options.accessKey && options.secretKey) {
Expand All @@ -46,8 +45,8 @@ function S3Adapter() {
this._hasBucket = false;
}

S3Adapter.prototype.createBucket = function() {
var promise;
S3Adapter.prototype.createBucket = function () {
let promise;
if (this._hasBucket) {
promise = Promise.resolve();
} else {
Expand All @@ -59,118 +58,110 @@ S3Adapter.prototype.createBucket = function() {
});
}
return promise;
}
};

// For a given config object, filename, and data, store a file in S3
// Returns a promise containing the S3 object creation response
S3Adapter.prototype.createFile = function(filename, data, contentType) {
let params = {
S3Adapter.prototype.createFile = function (filename, data, contentType) {
const params = {
Key: this._bucketPrefix + filename,
Body: data
Body: data,
};
if (this._directAccess) {
params.ACL = "public-read"
params.ACL = 'public-read';
}
if (contentType) {
params.ContentType = contentType;
}
if(this._globalCacheControl) {
if (this._globalCacheControl) {
params.CacheControl = this._globalCacheControl;
}
if(this._encryption == 'AES256' || this._encryption == 'aws:kms'){
if (this._encryption === 'AES256' || this._encryption === 'aws:kms') {
params.ServerSideEncryption = this._encryption;
}
return this.createBucket().then(() => {
return new Promise((resolve, reject) => {
this._s3Client.upload(params, (err, data) => {
if (err !== null) {
return reject(err);
}
resolve(data);
});
return this.createBucket().then(() => new Promise((resolve, reject) => {
this._s3Client.upload(params, (err, response) => {
if (err !== null) {
return reject(err);
}
return resolve(response);
});
});
}
}));
};

S3Adapter.prototype.deleteFile = function(filename) {
return this.createBucket().then(() => {
return new Promise((resolve, reject) => {
let params = {
Key: this._bucketPrefix + filename
};
this._s3Client.deleteObject(params, (err, data) =>{
if(err !== null) {
return reject(err);
}
resolve(data);
});
S3Adapter.prototype.deleteFile = function (filename) {
return this.createBucket().then(() => new Promise((resolve, reject) => {
const params = {
Key: this._bucketPrefix + filename,
};
this._s3Client.deleteObject(params, (err, data) => {
if (err !== null) {
return reject(err);
}
return resolve(data);
});
});
}
}));
};

// Search for and return a file if found by filename
// Returns a promise that succeeds with the buffer result from S3
S3Adapter.prototype.getFileData = function(filename) {
let params = {Key: this._bucketPrefix + filename};
return this.createBucket().then(() => {
return new Promise((resolve, reject) => {
this._s3Client.getObject(params, (err, data) => {
if (err !== null) {
return reject(err);
}
// Something happened here...
if (data && !data.Body) {
return reject(data);
}
resolve(data.Body);
});
S3Adapter.prototype.getFileData = function (filename) {
const params = { Key: this._bucketPrefix + filename };
return this.createBucket().then(() => new Promise((resolve, reject) => {
this._s3Client.getObject(params, (err, data) => {
if (err !== null) {
return reject(err);
}
// Something happened here...
if (data && !data.Body) {
return reject(data);
}
return resolve(data.Body);
});
});
}
}));
};

// Generates and returns the location of a file stored in S3 for the given request and filename
// The location is the direct S3 link if the option is set, otherwise we serve the file through parse-server
S3Adapter.prototype.getFileLocation = function(config, filename) {
filename = encodeURIComponent(filename);
// The location is the direct S3 link if the option is set,
// otherwise we serve the file through parse-server
S3Adapter.prototype.getFileLocation = function (config, filename) {
const fileName = encodeURIComponent(filename);
if (this._directAccess) {
if (this._baseUrl && this._baseUrlDirect) {
return `${this._baseUrl}/${filename}`;
} else if (this._baseUrl) {
return `${this._baseUrl}/${this._bucketPrefix + filename}`;
} else {
return `https://${this._bucket}.s3.amazonaws.com/${this._bucketPrefix + filename}`;
return `${this._baseUrl}/${fileName}`;
} if (this._baseUrl) {
return `${this._baseUrl}/${this._bucketPrefix + fileName}`;
}
return `https://${this._bucket}.s3.amazonaws.com/${this._bucketPrefix + fileName}`;
}
return (config.mount + '/files/' + config.applicationId + '/' + filename);
}
return (`${config.mount}/files/${config.applicationId}/${fileName}`);
};

S3Adapter.prototype.handleFileStream = function (filename, req, res) {
const params = {
Key: this._bucketPrefix + filename,
Range: req.get('Range'),
};
return this.createBucket().then(() => {
return new Promise((resolve, reject) => {
this._s3Client.getObject(params, (error, data) => {
if (error !== null) {
return reject(error);
}
if (data && !data.Body) {
return reject(data);
}
res.writeHead(206, {
'Accept-Ranges': data.AcceptRanges,
'Content-Length': data.ContentLength,
'Content-Range': data.ContentRange,
'Content-Type': data.ContentType,
});
res.write(data.Body);
res.end();
resolve(data.Body);
return this.createBucket().then(() => new Promise((resolve, reject) => {
this._s3Client.getObject(params, (error, data) => {
if (error !== null) {
return reject(error);
}
if (data && !data.Body) {
return reject(data);
}
res.writeHead(206, {
'Accept-Ranges': data.AcceptRanges,
'Content-Length': data.ContentLength,
'Content-Range': data.ContentRange,
'Content-Type': data.ContentType,
});
res.write(data.Body);
res.end();
return resolve(data.Body);
});
});
}
}));
};

module.exports = S3Adapter;
module.exports.default = S3Adapter;
65 changes: 32 additions & 33 deletions lib/optionsFromArguments.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
'use strict';

const DEFAULT_S3_REGION = 'us-east-1';

function requiredOrFromEnvironment(options, key, env) {
options[key] = options[key] || process.env[env];
if (!options[key]) {
throw `S3Adapter requires option '${key}' or env. variable ${env}`;
const opts = Object.assign({}, options);
opts[key] = options[key] || process.env[env];
if (!opts[key]) {
throw new Error(`S3Adapter requires option '${key}' or env. variable ${env}`);
}
return options;
return opts;
}

function fromEnvironmentOrDefault(options, key, env, defaultValue) {
options[key] = options[key] || process.env[env] || defaultValue;
const opts = Object.assign({}, options);
opts[key] = options[key] || process.env[env] || defaultValue;
// If we used the overrides,
// make sure they take priority
if(options.s3overrides){
if(options.s3overrides[key]){
options[key] = options.s3overrides[key];
}else if (options.s3overrides.params && options.s3overrides.params.Bucket) {
options.bucket = options.s3overrides.params.Bucket;
if (opts.s3overrides) {
if (opts.s3overrides[key]) {
opts[key] = opts.s3overrides[key];
} else if (opts.s3overrides.params && opts.s3overrides.params.Bucket) {
opts.bucket = opts.s3overrides.params.Bucket;
}
}
return options;
return opts;
}

function fromOptionsDictionaryOrDefault(options, key, defaultValue) {
options[key] = options[key] || defaultValue;
return options;
const opts = Object.assign({}, options);
opts[key] = options[key] || defaultValue;
return opts;
}

const optionsFromArguments = function optionsFromArguments(args) {
Expand All @@ -35,17 +37,17 @@ const optionsFromArguments = function optionsFromArguments(args) {
let s3overrides = {};
let otherOptions;

if (typeof stringOrOptions == 'string') {
if (args.length == 1) {
if (typeof stringOrOptions === 'string') {
if (args.length === 1) {
options.bucket = stringOrOptions;
} else if (args.length == 2) {
} else if (args.length === 2) {
options.bucket = stringOrOptions;
if (typeof args[1] != 'object') {
if (typeof args[1] !== 'object') {
throw new Error('Failed to configure S3Adapter. Arguments don\'t make sense');
}
otherOptions = args[1];
} else if (args.length > 2) {
if (typeof args[1] != 'string' || typeof args[2] != 'string') {
if (typeof args[1] !== 'string' || typeof args[2] !== 'string') {
throw new Error('Failed to configure S3Adapter. Arguments don\'t make sense');
}
options.accessKey = args[0];
Expand All @@ -63,19 +65,17 @@ const optionsFromArguments = function optionsFromArguments(args) {
options.globalCacheControl = otherOptions.globalCacheControl;
options.ServerSideEncryption = otherOptions.ServerSideEncryption;
}
} else {
if (args.length == 1) {
Object.assign(options, stringOrOptions);
} else if (args.length == 2) {
Object.assign(options, stringOrOptions);
s3overrides = args[1];
} else if (args.length === 1) {
Object.assign(options, stringOrOptions);
} else if (args.length === 2) {
Object.assign(options, stringOrOptions);
s3overrides = args[1];

if (s3overrides.params) {
options.bucket = s3overrides.params.Bucket;
}
} else if (args.length > 2) {
throw new Error('Failed to configure S3Adapter. Arguments don\'t make sense');
if (s3overrides.params) {
options.bucket = s3overrides.params.Bucket;
}
} else if (args.length > 2) {
throw new Error('Failed to configure S3Adapter. Arguments don\'t make sense');
}

options = fromOptionsDictionaryOrDefault(options, 's3overrides', s3overrides);
Expand All @@ -88,10 +88,9 @@ const optionsFromArguments = function optionsFromArguments(args) {
options = fromEnvironmentOrDefault(options, 'baseUrl', 'S3_BASE_URL', null);
options = fromEnvironmentOrDefault(options, 'baseUrlDirect', 'S3_BASE_URL_DIRECT', false);
options = fromEnvironmentOrDefault(options, 'signatureVersion', 'S3_SIGNATURE_VERSION', 'v4');
options = fromEnvironmentOrDefault(
options, 'globalCacheControl', 'S3_GLOBAL_CACHE_CONTROL', null);
options = fromEnvironmentOrDefault(options, 'globalCacheControl', 'S3_GLOBAL_CACHE_CONTROL', null);

return options;
}
};

module.exports = optionsFromArguments;
Loading

0 comments on commit 03b6a7b

Please sign in to comment.