From cadb6e82bf608638e7d26112bc837b596a8b9428 Mon Sep 17 00:00:00 2001 From: Tsolis Dimitris Sotiris Date: Sun, 28 Feb 2016 23:49:33 +0200 Subject: [PATCH 1/4] Add FileSystemAdapter --- .gitignore | 4 ++ src/Adapters/Files/FileSystemAdapter.js | 72 +++++++++++++++++++++++++ src/cli/parse-server.js | 16 ++++++ src/index.js | 4 +- 4 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 src/Adapters/Files/FileSystemAdapter.js diff --git a/.gitignore b/.gitignore index de88257b3b..dc65b37514 100644 --- a/.gitignore +++ b/.gitignore @@ -40,3 +40,7 @@ lib/ # cache folder .cache + +# Folder created by FileSystemAdapter +/files + diff --git a/src/Adapters/Files/FileSystemAdapter.js b/src/Adapters/Files/FileSystemAdapter.js new file mode 100644 index 0000000000..cf7c971e91 --- /dev/null +++ b/src/Adapters/Files/FileSystemAdapter.js @@ -0,0 +1,72 @@ +// FileSystemAdapter +// +// Stores files in local file system +// Requires write access to the server's file system. + +import { FilesAdapter } from './FilesAdapter'; +var fs = require('fs'); + +export class FileSystemAdapter extends FilesAdapter { + // For a given config object, filename, and data, store a file + // Returns a promise + createFile(config, filename, data) { + return new Promise((resolve, reject) => { + let filepath = this._getLocalFilePath(config, filename); + fs.writeFile(filepath, data, (err) => { + if(err !== null) { + return reject(err); + } + resolve(data); + }); + }); + } + + deleteFile(config, filename) { + return new Promise((resolve, reject) => { + let filepath = this._getLocalFilePath(config, filename); + fs.readFile( filepath , function (err, data) { + if(err !== null) { + return reject(err); + } + fs.unlink(filepath, (unlinkErr) => { + if(err !== null) { + return reject(unlinkErr); + } + resolve(data); + }); + }); + + }); + } + + getFileData(config, filename) { + return new Promise((resolve, reject) => { + let filepath = this._getLocalFilePath(config, filename); + fs.readFile( filepath , function (err, data) { + if(err !== null) { + return reject(err); + } + resolve(data); + }); + }); + } + + getFileLocation(config, filename) { + return (config.mount + '/' + this._getLocalFilePath(config, filename)); + } + + _getLocalFilePath(config, filename) { + let filesDir = 'files'; + if (!fs.existsSync(filesDir)) { + fs.mkdirSync(filesDir); + } + + let applicationDir = filesDir + '/' + config.applicationId; + if (!fs.existsSync(applicationDir)) { + fs.mkdirSync(applicationDir); + } + return (applicationDir + '/' + encodeURIComponent(filename)); + } +} + +export default FileSystemAdapter; \ No newline at end of file diff --git a/src/cli/parse-server.js b/src/cli/parse-server.js index 627964f981..e8493a8ad8 100755 --- a/src/cli/parse-server.js +++ b/src/cli/parse-server.js @@ -4,6 +4,7 @@ import { ParseServer } from '../index'; import definitions from './cli-definitions'; import program from './utils/commander'; import colors from 'colors'; +import { FileSystemAdapter } from '../Adapters/Files/FileSystemAdapter'; program.loadDefinitions(definitions); @@ -61,6 +62,21 @@ if (!options.serverURL) { options.serverURL = `http://localhost:${options.port}${options.mountPath}`; } +if (options.filesAdapter instanceof FileSystemAdapter) { + var fs = require('fs'); + + try { + fs.mkdirSync('files'); + } catch(e) { + if ( e.code == 'EACCES' ) { + console.error(""); + console.error(colors.red("ERROR: In order to use the FileSystemAdapter, write access to the server's file system is required")); + console.error(""); + process.exit(1); + } + } +} + const app = express(); const api = new ParseServer(options); app.use(options.mountPath, api); diff --git a/src/index.js b/src/index.js index ad715902f5..80feb6490b 100644 --- a/src/index.js +++ b/src/index.js @@ -14,6 +14,7 @@ import cache from './cache'; import PromiseRouter from './PromiseRouter'; import { GridStoreAdapter } from './Adapters/Files/GridStoreAdapter'; import { S3Adapter } from './Adapters/Files/S3Adapter'; +import { FileSystemAdapter } from './Adapters/Files/FileSystemAdapter'; import { FilesController } from './Controllers/FilesController'; import ParsePushAdapter from './Adapters/Push/ParsePushAdapter'; @@ -229,5 +230,6 @@ function getClassName(parseClass) { module.exports = { ParseServer: ParseServer, - S3Adapter: S3Adapter + S3Adapter: S3Adapter, + FileSystemAdapter: FileSystemAdapter }; From e6395f0d4151da6aa10633c434c854318ab850cc Mon Sep 17 00:00:00 2001 From: Tsolis Dimitris Sotiris Date: Mon, 29 Feb 2016 01:33:54 +0200 Subject: [PATCH 2/4] Add options to the FileSystemAdapter constructor --- src/Adapters/Files/FileSystemAdapter.js | 42 +++++++++++++++++++++---- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/Adapters/Files/FileSystemAdapter.js b/src/Adapters/Files/FileSystemAdapter.js index cf7c971e91..d76ace1151 100644 --- a/src/Adapters/Files/FileSystemAdapter.js +++ b/src/Adapters/Files/FileSystemAdapter.js @@ -4,9 +4,19 @@ // Requires write access to the server's file system. import { FilesAdapter } from './FilesAdapter'; +import colors from 'colors'; var fs = require('fs'); +var path = require('path'); export class FileSystemAdapter extends FilesAdapter { + + constructor({filesSubDirectory = ''} = {}) { + super(); + + this._filesDir = filesSubDirectory; + this._mkdir(filesSubDirectory); + } + // For a given config object, filename, and data, store a file // Returns a promise createFile(config, filename, data) { @@ -55,18 +65,38 @@ export class FileSystemAdapter extends FilesAdapter { return (config.mount + '/' + this._getLocalFilePath(config, filename)); } + /* + Helpers + --------------- */ + _getLocalFilePath(config, filename) { let filesDir = 'files'; - if (!fs.existsSync(filesDir)) { - fs.mkdirSync(filesDir); - } - - let applicationDir = filesDir + '/' + config.applicationId; + let applicationDir = filesDir + '/' + this._filesDir; if (!fs.existsSync(applicationDir)) { - fs.mkdirSync(applicationDir); + this._mkdir(applicationDir); } return (applicationDir + '/' + encodeURIComponent(filename)); } + + _mkdir(path, root) { + // snippet found on -> http://stackoverflow.com/a/10600228 + var dirs = path.split('/'), dir = dirs.shift(), root = (root || '') + dir + '/'; + + try { + fs.mkdirSync(root); + } + catch (e) { + if ( e.code == 'EACCES' ) { + console.error(""); + console.error(colors.red("ERROR: In order to use the FileSystemAdapter, write access to the server's file system is required")); + console.error(""); + process.exit(1); + } + //dir wasn't made, something went wrong + if(!fs.statSync(root).isDirectory()) throw new Error(e); + } + return !dirs.length || this._mkdir(dirs.join('/'), root); + } } export default FileSystemAdapter; \ No newline at end of file From eb45405b958005fda0894dfc5e81087ee831ea35 Mon Sep 17 00:00:00 2001 From: Tsolis Dimitris Sotiris Date: Mon, 29 Feb 2016 01:34:42 +0200 Subject: [PATCH 3/4] Remove file system permissions validation from CLI --- src/cli/parse-server.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/cli/parse-server.js b/src/cli/parse-server.js index e8493a8ad8..627964f981 100755 --- a/src/cli/parse-server.js +++ b/src/cli/parse-server.js @@ -4,7 +4,6 @@ import { ParseServer } from '../index'; import definitions from './cli-definitions'; import program from './utils/commander'; import colors from 'colors'; -import { FileSystemAdapter } from '../Adapters/Files/FileSystemAdapter'; program.loadDefinitions(definitions); @@ -62,21 +61,6 @@ if (!options.serverURL) { options.serverURL = `http://localhost:${options.port}${options.mountPath}`; } -if (options.filesAdapter instanceof FileSystemAdapter) { - var fs = require('fs'); - - try { - fs.mkdirSync('files'); - } catch(e) { - if ( e.code == 'EACCES' ) { - console.error(""); - console.error(colors.red("ERROR: In order to use the FileSystemAdapter, write access to the server's file system is required")); - console.error(""); - process.exit(1); - } - } -} - const app = express(); const api = new ParseServer(options); app.use(options.mountPath, api); From 0843aaac0df27435caeac902e269c4c332014f2c Mon Sep 17 00:00:00 2001 From: Tsolis Dimitris Sotiris Date: Mon, 29 Feb 2016 01:41:19 +0200 Subject: [PATCH 4/4] Remove config parameter from _getLocalFilePath() --- src/Adapters/Files/FileSystemAdapter.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Adapters/Files/FileSystemAdapter.js b/src/Adapters/Files/FileSystemAdapter.js index d76ace1151..2376028396 100644 --- a/src/Adapters/Files/FileSystemAdapter.js +++ b/src/Adapters/Files/FileSystemAdapter.js @@ -21,7 +21,7 @@ export class FileSystemAdapter extends FilesAdapter { // Returns a promise createFile(config, filename, data) { return new Promise((resolve, reject) => { - let filepath = this._getLocalFilePath(config, filename); + let filepath = this._getLocalFilePath(filename); fs.writeFile(filepath, data, (err) => { if(err !== null) { return reject(err); @@ -33,7 +33,7 @@ export class FileSystemAdapter extends FilesAdapter { deleteFile(config, filename) { return new Promise((resolve, reject) => { - let filepath = this._getLocalFilePath(config, filename); + let filepath = this._getLocalFilePath(filename); fs.readFile( filepath , function (err, data) { if(err !== null) { return reject(err); @@ -51,7 +51,7 @@ export class FileSystemAdapter extends FilesAdapter { getFileData(config, filename) { return new Promise((resolve, reject) => { - let filepath = this._getLocalFilePath(config, filename); + let filepath = this._getLocalFilePath(filename); fs.readFile( filepath , function (err, data) { if(err !== null) { return reject(err); @@ -62,14 +62,14 @@ export class FileSystemAdapter extends FilesAdapter { } getFileLocation(config, filename) { - return (config.mount + '/' + this._getLocalFilePath(config, filename)); + return (config.mount + '/' + this._getLocalFilePath(filename)); } /* Helpers --------------- */ - _getLocalFilePath(config, filename) { + _getLocalFilePath(filename) { let filesDir = 'files'; let applicationDir = filesDir + '/' + this._filesDir; if (!fs.existsSync(applicationDir)) {