Skip to content

Commit cc4b5fa

Browse files
GabrielLombaflovilmart
authored andcommitted
Add the addFileNameHash option that allows users to remove the hash f… (#4915)
* Add the addFileNameHash option that allows users to remove the hash from file names * Change option name to preserveFileName * Revert changes to package-lock.json
1 parent ac2f485 commit cc4b5fa

File tree

6 files changed

+56
-7
lines changed

6 files changed

+56
-7
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ The client keys used with Parse are no longer necessary with Parse Server. If yo
232232
#### Advanced options
233233

234234
* `fileKey` - For migrated apps, this is necessary to provide access to files already hosted on Parse.
235+
* `preserveFileName` - Set to true to remove the unique hash added to the file names. Defaults to false.
235236
* `allowClientClassCreation` - Set to false to disable client class creation. Defaults to true.
236237
* `enableAnonymousUsers` - Set to false to disable anonymous users. Defaults to true.
237238
* `auth` - Used to configure support for [3rd party authentication](http://docs.parseplatform.org/parse-server/guide/#oauth-and-3rd-party-authentication).

spec/FilesController.spec.js

+39-3
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ const mockAdapter = {
1414
}
1515

1616
// Small additional tests to improve overall coverage
17-
describe("FilesController",() =>{
17+
describe("FilesController", () => {
1818
it("should properly expand objects", (done) => {
1919

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

2525
expect(result).toBeUndefined();
2626

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

4444
reconfigureServer({ filesAdapter: mockAdapter })
4545
.then(() => new Promise(resolve => setTimeout(resolve, 1000)))
46-
.then(() => new Parse.File("yolo.txt", [1,2,3], "text/plain").save())
46+
.then(() => new Parse.File("yolo.txt", [1, 2, 3], "text/plain").save())
4747
.then(
4848
() => done.fail('should not succeed'),
4949
() => setImmediate(() => Parse.Promise.as('done'))
@@ -62,4 +62,40 @@ describe("FilesController",() =>{
6262
done();
6363
});
6464
});
65+
66+
it("should add a unique hash to the file name when the preserveFileName option is false", (done) => {
67+
68+
const config = Config.get(Parse.applicationId)
69+
const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse')
70+
spyOn(gridStoreAdapter, 'createFile')
71+
gridStoreAdapter.createFile.and.returnValue(Promise.resolve())
72+
const fileName = 'randomFileName.pdf'
73+
const regexEscapedFileName = fileName.replace(/\./g, "\\$&")
74+
const filesController = new FilesController(gridStoreAdapter, null, { preserveFileName: false })
75+
76+
filesController.createFile(config, fileName)
77+
78+
expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1)
79+
expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toMatch(`^.{32}_${regexEscapedFileName}$`)
80+
81+
done();
82+
});
83+
84+
it("should not add a unique hash to the file name when the preserveFileName option is false", (done) => {
85+
86+
const config = Config.get(Parse.applicationId)
87+
const gridStoreAdapter = new GridStoreAdapter('mongodb://localhost:27017/parse')
88+
spyOn(gridStoreAdapter, 'createFile')
89+
gridStoreAdapter.createFile.and.returnValue(Promise.resolve())
90+
const fileName = 'randomFileName.pdf'
91+
const filesController = new FilesController(gridStoreAdapter, null, { preserveFileName: true })
92+
93+
filesController.createFile(config, fileName)
94+
95+
expect(gridStoreAdapter.createFile).toHaveBeenCalledTimes(1)
96+
expect(gridStoreAdapter.createFile.calls.mostRecent().args[0]).toEqual(fileName)
97+
98+
done();
99+
});
100+
65101
});

src/Controllers/FilesController.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import { randomHexString } from '../cryptoUtils';
33
import AdaptableController from './AdaptableController';
44
import { FilesAdapter } from '../Adapters/Files/FilesAdapter';
5-
import path from 'path';
5+
import path from 'path';
66
import mime from 'mime';
77

88
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}-.*");
@@ -25,9 +25,11 @@ export class FilesController extends AdaptableController {
2525
contentType = mime.getType(filename);
2626
}
2727

28-
filename = randomHexString(32) + '_' + filename;
28+
if (!this.options.preserveFileName) {
29+
filename = randomHexString(32) + '_' + filename;
30+
}
2931

30-
var location = this.adapter.getFileLocation(config, filename);
32+
const location = this.adapter.getFileLocation(config, filename);
3133
return this.adapter.createFile(filename, data, contentType).then(() => {
3234
return Promise.resolve({
3335
url: location,

src/Controllers/index.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,15 @@ export function getFilesController(options: ParseServerOptions): FilesController
8282
databaseURI,
8383
filesAdapter,
8484
databaseAdapter,
85+
preserveFileName,
8586
} = options;
8687
if (!filesAdapter && databaseAdapter) {
8788
throw 'When using an explicit database adapter, you must also use an explicit filesAdapter.';
8889
}
8990
const filesControllerAdapter = loadAdapter(filesAdapter, () => {
9091
return new GridStoreAdapter(databaseURI);
9192
});
92-
return new FilesController(filesControllerAdapter, appId);
93+
return new FilesController(filesControllerAdapter, appId, { preserveFileName });
9394
}
9495

9596
export function getUserController(options: ParseServerOptions): UserController {

src/Options/Definitions.js

+6
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ module.exports.ParseServerOptions = {
135135
"env": "PARSE_SERVER_FILE_KEY",
136136
"help": "Key for your files"
137137
},
138+
"preserveFileName": {
139+
"env": "PARSE_SERVER_PRESERVE_FILE_NAME",
140+
"help": "Enable (or disable) the addition of a unique hash to the file names",
141+
"action": parsers.booleanParser,
142+
"default": false
143+
},
138144
"userSensitiveFields": {
139145
"env": "PARSE_SERVER_USER_SENSITIVE_FIELDS",
140146
"help": "Personally identifiable information fields in the user table the should be removed for non-authorized users.",

src/Options/index.js

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ export interface ParseServerOptions {
6464
webhookKey: ?string;
6565
/* Key for your files */
6666
fileKey: ?string;
67+
/* Enable (or disable) the addition of a unique hash to the file names
68+
:ENV: PARSE_SERVER_PRESERVE_FILE_NAME */
69+
preserveFileName: ?boolean; // = false
6770
/* Personally identifiable information fields in the user table the should be removed for non-authorized users. */
6871
userSensitiveFields: ?string[]; // = ["email"]
6972
/* Enable (or disable) anon users, defaults to true

0 commit comments

Comments
 (0)