Skip to content

Commit

Permalink
feat: add mimeTypes validation for uploads
Browse files Browse the repository at this point in the history
  • Loading branch information
denolfe committed May 12, 2021
1 parent 1c6f32f commit a5fcdf0
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/collections/config/sanitize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import baseUploadFields from '../../fields/baseFields/baseUploadFields';
import baseImageUploadFields from '../../fields/baseFields/baseImageUploadFields';
import { formatLabels } from '../../utilities/formatLabels';
import { defaults, authDefaults } from './defaults';
import { mimeTypeValidator } from '../../fields/baseFields/mimeTypeValidator';

const mergeBaseFields = (fields, baseFields) => {
const mergedFields = [];
Expand Down Expand Up @@ -73,6 +74,10 @@ const sanitizeCollection = (collections: PayloadCollectionConfig[], collection:

let uploadFields = baseUploadFields;

if (sanitized.upload.mimeTypes) {
uploadFields.find((f) => f.name === 'mimeType').validate = mimeTypeValidator(sanitized.upload.mimeTypes);
}

if (sanitized.upload.imageSizes && Array.isArray(sanitized.upload.imageSizes)) {
uploadFields = uploadFields.concat(baseImageUploadFields(sanitized.upload.imageSizes));
}
Expand Down
2 changes: 1 addition & 1 deletion src/errors/ValidationError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import APIError from './APIError';

class ValidationError extends APIError {
constructor(results: {message: string, field: string}[]) {
super(`Bad request with ${results.length} errors`, httpStatus.BAD_REQUEST, results);
super(`The following field${results.length === 1 ? ' is' : 's are'} invalid: ${results.map((f) => f.field).join(', ')}`, httpStatus.BAD_REQUEST, results);
}
}

Expand Down
55 changes: 55 additions & 0 deletions src/fields/baseFields/mimeTypeValidator.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { mimeTypeValidator } from './mimeTypeValidator';

describe('mimeTypeValidator', () => {
it('should validate single mimeType', () => {
const mimeTypes = ['image/png'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
});

it('should validate multiple mimeTypes', () => {
const mimeTypes = ['image/png', 'application/pdf'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
expect(validate('application/pdf')).toBe(true);
});

it('should validate using wildcard', () => {
const mimeTypes = ['image/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
expect(validate('image/gif')).toBe(true);
});

it('should validate multiple wildcards', () => {
const mimeTypes = ['image/*', 'audio/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('image/png')).toBe(true);
expect(validate('audio/mpeg')).toBe(true);
});

it('should not validate when unmatched', () => {
const mimeTypes = ['image/png'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('audio/mpeg')).toBe('Invalid file type: \'audio/mpeg\'');
});

it('should not validate when unmatched - multiple mimeTypes', () => {
const mimeTypes = ['image/png', 'application/pdf'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('audio/mpeg')).toBe('Invalid file type: \'audio/mpeg\'');
});

it('should not validate using wildcard - unmatched', () => {
const mimeTypes = ['image/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('audio/mpeg')).toBe('Invalid file type: \'audio/mpeg\'');
});

it('should not validate multiple wildcards - unmatched', () => {
const mimeTypes = ['image/*', 'audio/*'];
const validate = mimeTypeValidator(mimeTypes);
expect(validate('video/mp4')).toBe('Invalid file type: \'video/mp4\'');
expect(validate('application/pdf')).toBe('Invalid file type: \'application/pdf\'');
});
});
9 changes: 9 additions & 0 deletions src/fields/baseFields/mimeTypeValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Validate } from '../config/types';

export const mimeTypeValidator = (mimeTypes: string[]): Validate => (val: string) => {
const cleanedMimeTypes = mimeTypes.map((v) => v.replace('*', ''));

return !cleanedMimeTypes.some((v) => val.startsWith(v))
? `Invalid file type: '${val}'`
: true;
};
2 changes: 1 addition & 1 deletion src/fields/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export type Labels = {
plural: string;
};

export type Validate = (value: unknown, options?: any) => string | boolean | Promise<string | boolean>;
export type Validate = (value: unknown, options?: any) => string | true | Promise<string | true>;

export type OptionObject = {
label: string
Expand Down

0 comments on commit a5fcdf0

Please sign in to comment.