Skip to content

Add the addFileNameHash option that allows users to remove the hash f… #4915

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
#### Advanced options

* `fileKey` - For migrated apps, this is necessary to provide access to files already hosted on Parse.
* `preserveFileName` - Set to true to remove the unique hash added to the file names. Defaults to false.
* `allowClientClassCreation` - Set to false to disable client class creation. Defaults to true.
* `enableAnonymousUsers` - Set to false to disable anonymous users. Defaults to true.
* `auth` - Used to configure support for [3rd party authentication](http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication).
Expand Down
42 changes: 39 additions & 3 deletions spec/FilesController.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ const mockAdapter = {
}

// Small additional tests to improve overall coverage
describe("FilesController",() =>{
describe("FilesController", () => {
it("should properly expand objects", (done) => {

const config = Config.get(Parse.applicationId);
const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse');
const filesController = new FilesController(gridStoreAdapter)
const result = filesController.expandFilesInObject(config, function(){});
const result = filesController.expandFilesInObject(config, function () { });

expect(result).toBeUndefined();

Expand All @@ -43,7 +43,7 @@ describe("FilesController",() =>{

reconfigureServer({ filesAdapter: mockAdapter })
.then(() => new Promise(resolve => setTimeout(resolve, 1000)))
.then(() => new Parse.File("yolo.txt", [1,2,3], "text/plain").save())
.then(() => new Parse.File("yolo.txt", [1, 2, 3], "text/plain").save())
.then(
() => done.fail('should not succeed'),
() => setImmediate(() => Parse.Promise.as('done'))
Expand All @@ -62,4 +62,40 @@ describe("FilesController",() =>{
done();
});
});

it("should add a unique hash to the file name when the preserveFileName option is false", (done) => {

const config = Config.get(Parse.applicationId)
const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse')
spyOn(gridStoreAdapter, 'createFile')
gridStoreAdapter.createFile.and.returnValue(Promise.resolve())
const fileName = 'randomFileName.pdf'
const regexEscapedFileName = fileName.replace(/\./g, "\\$&")
const filesController = new FilesController(gridStoreAdapter, null, { preserveFileName: false })

filesController.createFile(config, fileName)

expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1)
expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toMatch(`^.{32}_${regexEscapedFileName}$`)

done();
});

it("should not add a unique hash to the file name when the preserveFileName option is false", (done) => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

false should be true in the description

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. My mistake. Should I make another PR fixing it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep go ahead ;)


const config = Config.get(Parse.applicationId)
const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse')
spyOn(gridStoreAdapter, 'createFile')
gridStoreAdapter.createFile.and.returnValue(Promise.resolve())
const fileName = 'randomFileName.pdf'
const filesController = new FilesController(gridStoreAdapter, null, { preserveFileName: true })

filesController.createFile(config, fileName)

expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1)
expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toEqual(fileName)

done();
});

});
8 changes: 5 additions & 3 deletions src/Controllers/FilesController.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { randomHexString } from '../cryptoUtils';
import AdaptableController from './AdaptableController';
import { FilesAdapter } from '../Adapters/Files/FilesAdapter';
import path from 'path';
import path from 'path';
import mime from 'mime';

const legacyFilesRegex = new RegExp("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}-.*");
Expand All @@ -25,9 +25,11 @@ export class FilesController extends AdaptableController {
contentType = mime.getType(filename);
}

filename = randomHexString(32) + '_' + filename;
if (!this.options.preserveFileName) {
filename = randomHexString(32) + '_' + filename;
}

var location = this.adapter.getFileLocation(config, filename);
const location = this.adapter.getFileLocation(config, filename);
return this.adapter.createFile(filename, data, contentType).then(() => {
return Promise.resolve({
url: location,
Expand Down
3 changes: 2 additions & 1 deletion src/Controllers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,15 @@ export function getFilesController(options: ParseServerOptions): FilesController
databaseURI,
filesAdapter,
databaseAdapter,
preserveFileName,
} = options;
if (!filesAdapter && databaseAdapter) {
throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.';
}
const filesControllerAdapter = loadAdapter(filesAdapter, () => {
return new GridStoreAdapter(databaseURI);
});
return new FilesController(filesControllerAdapter, appId);
return new FilesController(filesControllerAdapter, appId, { preserveFileName });
}

export function getUserController(options: ParseServerOptions): UserController {
Expand Down
6 changes: 6 additions & 0 deletions src/Options/Definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ module.exports.ParseServerOptions = {
"env": "PARSE_SERVER_FILE_KEY",
"help": "Key for your files"
},
"preserveFileName": {
"env": "PARSE_SERVER_PRESERVE_FILE_NAME",
"help": "Enable (or disable) the addition of a unique hash to the file names",
"action": parsers.booleanParser,
"default": false
},
"userSensitiveFields": {
"env": "PARSE_SERVER_USER_SENSITIVE_FIELDS",
"help": "Personally identifiable information fields in the user table the should be removed for non-authorized users.",
Expand Down
3 changes: 3 additions & 0 deletions src/Options/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ export interface ParseServerOptions {
webhookKey: ?string;
/* Key for your files */
fileKey: ?string;
/* Enable (or disable) the addition of a unique hash to the file names
:ENV: PARSE_SERVER_PRESERVE_FILE_NAME */
preserveFileName: ?boolean; // = false
/* Personally identifiable information fields in the user table the should be removed for non-authorized users. */
userSensitiveFields: ?string[]; // = ["email"]
/* Enable (or disable) anon users, defaults to true
Expand Down