refactor: Add new Parse Server option fileUpload.fileExtensions to restrict file upload by file extension (#8539)

This commit is contained in:
Manuel
2023-05-21 01:31:52 +02:00
committed by GitHub
parent db4c214eac
commit a27482c57e
6 changed files with 209 additions and 25 deletions

View File

@@ -37,8 +37,14 @@ describe('Parse.File testing', () => {
});
});
it('works with _ContentType', done => {
request({
it('works with _ContentType', async () => {
await reconfigureServer({
fileUpload: {
enableForPublic: true,
fileExtensions: ['*'],
},
});
let response = await request({
method: 'POST',
url: 'http://localhost:8378/1/files/file',
body: JSON.stringify({
@@ -47,21 +53,18 @@ describe('Parse.File testing', () => {
_ContentType: 'text/html',
base64: 'PGh0bWw+PC9odG1sPgo=',
}),
}).then(response => {
const b = response.data;
expect(b.name).toMatch(/_file.html/);
expect(b.url).toMatch(/^http:\/\/localhost:8378\/1\/files\/test\/.*file.html$/);
request({ url: b.url }).then(response => {
const body = response.text;
try {
expect(response.headers['content-type']).toMatch('^text/html');
expect(body).toEqual('<html></html>\n');
} catch (e) {
jfail(e);
}
done();
});
});
const b = response.data;
expect(b.name).toMatch(/_file.html/);
expect(b.url).toMatch(/^http:\/\/localhost:8378\/1\/files\/test\/.*file.html$/);
response = await request({ url: b.url });
const body = response.text;
try {
expect(response.headers['content-type']).toMatch('^text/html');
expect(body).toEqual('<html></html>\n');
} catch (e) {
jfail(e);
}
});
it('works without Content-Type', done => {
@@ -351,25 +354,28 @@ describe('Parse.File testing', () => {
ok(object.toJSON().file.url);
});
it('content-type used with no extension', done => {
it('content-type used with no extension', async () => {
await reconfigureServer({
fileUpload: {
enableForPublic: true,
fileExtensions: ['*'],
},
});
const headers = {
'Content-Type': 'text/html',
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
};
request({
let response = await request({
method: 'POST',
headers: headers,
url: 'http://localhost:8378/1/files/file',
body: 'fee fi fo',
}).then(response => {
const b = response.data;
expect(b.name).toMatch(/\.html$/);
request({ url: b.url }).then(response => {
expect(response.headers['content-type']).toMatch(/^text\/html/);
done();
});
});
const b = response.data;
expect(b.name).toMatch(/\.html$/);
response = await request({ url: b.url });
expect(response.headers['content-type']).toMatch(/^text\/html/);
});
it('filename is url encoded', done => {
@@ -1298,6 +1304,136 @@ describe('Parse.File testing', () => {
await expectAsync(reconfigureServer({ fileUpload: { [key]: value } })).toBeResolved();
}
}
await expectAsync(
reconfigureServer({
fileUpload: {
fileExtensions: 1,
},
})
).toBeRejectedWith('fileUpload.fileExtensions must be an array.');
});
});
describe('fileExtensions', () => {
it('works with _ContentType', async () => {
await reconfigureServer({
silent: false,
fileUpload: {
enableForPublic: true,
fileExtensions: ['png'],
},
});
await expectAsync(
request({
method: 'POST',
url: 'http://localhost:8378/1/files/file',
body: JSON.stringify({
_ApplicationId: 'test',
_JavaScriptKey: 'test',
_ContentType: 'text/html',
base64: 'PGh0bWw+PC9odG1sPgo=',
}),
}).catch(e => {
throw new Error(e.data.error);
})
).toBeRejectedWith(
new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`)
);
});
it('works without Content-Type', async () => {
await reconfigureServer({
fileUpload: {
enableForPublic: true,
},
});
const headers = {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
};
await expectAsync(
request({
method: 'POST',
headers: headers,
url: 'http://localhost:8378/1/files/file.html',
body: '<html></html>\n',
}).catch(e => {
throw new Error(e.data.error);
})
).toBeRejectedWith(
new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`)
);
});
it('works with array', async () => {
await reconfigureServer({
fileUpload: {
enableForPublic: true,
fileExtensions: ['jpg'],
},
});
await expectAsync(
request({
method: 'POST',
url: 'http://localhost:8378/1/files/file',
body: JSON.stringify({
_ApplicationId: 'test',
_JavaScriptKey: 'test',
_ContentType: 'text/html',
base64: 'PGh0bWw+PC9odG1sPgo=',
}),
}).catch(e => {
throw new Error(e.data.error);
})
).toBeRejectedWith(
new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`)
);
});
it('works with array without Content-Type', async () => {
await reconfigureServer({
fileUpload: {
enableForPublic: true,
fileExtensions: ['jpg'],
},
});
const headers = {
'X-Parse-Application-Id': 'test',
'X-Parse-REST-API-Key': 'rest',
};
await expectAsync(
request({
method: 'POST',
headers: headers,
url: 'http://localhost:8378/1/files/file.html',
body: '<html></html>\n',
}).catch(e => {
throw new Error(e.data.error);
})
).toBeRejectedWith(
new Parse.Error(Parse.Error.FILE_SAVE_ERROR, `File upload of extension html is disabled.`)
);
});
it('works with array with correct file type', async () => {
await reconfigureServer({
fileUpload: {
enableForPublic: true,
fileExtensions: ['html'],
},
});
const response = await request({
method: 'POST',
url: 'http://localhost:8378/1/files/file',
body: JSON.stringify({
_ApplicationId: 'test',
_JavaScriptKey: 'test',
_ContentType: 'text/html',
base64: 'PGh0bWw+PC9odG1sPgo=',
}),
});
const b = response.data;
expect(b.name).toMatch(/_file.html$/);
expect(b.url).toMatch(/^http:\/\/localhost:8378\/1\/files\/test\/.*file.html$/);
});
});
});