"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.defaultOptions = exports.RestrictionError = exports.Restricter = void 0; /* eslint-disable max-classes-per-file, class-methods-use-this */ /* global AggregateError */ const prettierBytes = require("@transloadit/prettier-bytes"); const match = require("mime-match"); const defaultOptions = { maxFileSize: null, minFileSize: null, maxTotalFileSize: null, maxNumberOfFiles: null, minNumberOfFiles: null, allowedFileTypes: null, requiredMetaFields: [] }; exports.defaultOptions = defaultOptions; class RestrictionError extends Error { constructor() { super(...arguments); this.isRestriction = true; } } exports.RestrictionError = RestrictionError; if (typeof AggregateError === 'undefined') { // eslint-disable-next-line no-global-assign // TODO: remove this "polyfill" in the next major. globalThis.AggregateError = class AggregateError extends Error { constructor(errors, message) { super(message); this.errors = errors; } }; } class Restricter { constructor(getOpts, i18n) { this.i18n = i18n; this.getOpts = () => { const opts = getOpts(); if (opts.restrictions.allowedFileTypes != null && !Array.isArray(opts.restrictions.allowedFileTypes)) { throw new TypeError('`restrictions.allowedFileTypes` must be an array'); } return opts; }; } validate(file, files) { const { maxFileSize, minFileSize, maxTotalFileSize, maxNumberOfFiles, allowedFileTypes } = this.getOpts().restrictions; if (maxNumberOfFiles) { const nonGhostFiles = files.filter(f => !f.isGhost); if (nonGhostFiles.length + 1 > maxNumberOfFiles) { throw new RestrictionError(`${this.i18n('youCanOnlyUploadX', { smart_count: maxNumberOfFiles })}`); } } if (allowedFileTypes) { const isCorrectFileType = allowedFileTypes.some(type => { // check if this is a mime-type if (type.includes('/')) { if (!file.type) return false; return match(file.type.replace(/;.*?$/, ''), type); } // otherwise this is likely an extension if (type[0] === '.' && file.extension) { return file.extension.toLowerCase() === type.slice(1).toLowerCase(); } return false; }); if (!isCorrectFileType) { const allowedFileTypesString = allowedFileTypes.join(', '); throw new RestrictionError(this.i18n('youCanOnlyUploadFileTypes', { types: allowedFileTypesString })); } } // We can't check maxTotalFileSize if the size is unknown. if (maxTotalFileSize && file.size != null) { const totalFilesSize = files.reduce((total, f) => total + f.size, file.size); if (totalFilesSize > maxTotalFileSize) { throw new RestrictionError(this.i18n('exceedsSize', { size: prettierBytes(maxTotalFileSize), file: file.name })); } } // We can't check maxFileSize if the size is unknown. if (maxFileSize && file.size != null && file.size > maxFileSize) { throw new RestrictionError(this.i18n('exceedsSize', { size: prettierBytes(maxFileSize), file: file.name })); } // We can't check minFileSize if the size is unknown. if (minFileSize && file.size != null && file.size < minFileSize) { throw new RestrictionError(this.i18n('inferiorSize', { size: prettierBytes(minFileSize) })); } } validateMinNumberOfFiles(files) { const { minNumberOfFiles } = this.getOpts().restrictions; if (Object.keys(files).length < minNumberOfFiles) { throw new RestrictionError(this.i18n('youHaveToAtLeastSelectX', { smart_count: minNumberOfFiles })); } } getMissingRequiredMetaFields(file) { const error = new RestrictionError(this.i18n('missingRequiredMetaFieldOnFile', { fileName: file.name })); const { requiredMetaFields } = this.getOpts().restrictions; // TODO: migrate to Object.hasOwn in the next major. const own = Object.prototype.hasOwnProperty; const missingFields = []; for (const field of requiredMetaFields) { if (!own.call(file.meta, field) || file.meta[field] === '') { missingFields.push(field); } } return { missingFields, error }; } } exports.Restricter = Restricter;