UNPKG

@uppy/companion

Version:

OAuth helper and remote fetcher for Uppy's (https://uppy.io) extensible file upload widget with support for drag&drop, resumable uploads, previews, restrictions, file processing/encoding, remote providers like Dropbox and Google Drive, S3 and more :dog:

165 lines (145 loc) 4.53 kB
import fs from 'node:fs' import validator from 'validator' import { defaultGetKey } from '../server/helpers/utils.js' import logger from '../server/logger.js' export const defaultOptions = { server: { protocol: 'http', path: '', }, providerOptions: {}, s3: { endpoint: 'https://{service}.{region}.amazonaws.com', conditions: [], useAccelerateEndpoint: false, getKey: defaultGetKey, expires: 800, // seconds }, enableUrlEndpoint: false, enableGooglePickerEndpoint: false, allowLocalUrls: false, periodicPingUrls: [], streamingUpload: true, clientSocketConnectTimeout: 60000, metrics: true, } /** * @param {object} companionOptions */ export function getMaskableSecrets(companionOptions) { const secrets = [] const { providerOptions, customProviders, s3 } = companionOptions Object.keys(providerOptions).forEach((provider) => { if (providerOptions[provider].secret) { secrets.push(providerOptions[provider].secret) } }) if (customProviders) { Object.keys(customProviders).forEach((provider) => { if (customProviders[provider].config?.secret) { secrets.push(customProviders[provider].config.secret) } }) } if (s3?.secret) { secrets.push(s3.secret) } return secrets } /** * validates that the mandatory companion options are set. * If it is invalid, it will console an error of unset options and exits the process. * If it is valid, nothing happens. * * @param {object} companionOptions */ export const validateConfig = (companionOptions) => { const mandatoryOptions = ['secret', 'filePath', 'server.host'] /** @type {string[]} */ const unspecified = [] mandatoryOptions.forEach((i) => { const value = i .split('.') .reduce((prev, curr) => (prev ? prev[curr] : undefined), companionOptions) if (!value) unspecified.push(`"${i}"`) }) // vaidate that all required config is specified if (unspecified.length) { const messagePrefix = 'Please specify the following options to use companion:' throw new Error(`${messagePrefix}\n${unspecified.join(',\n')}`) } // validate that specified filePath is writeable/readable. try { // @ts-ignore fs.accessSync( `${companionOptions.filePath}`, fs.constants.R_OK | fs.constants.W_OK, ) } catch (_err) { throw new Error( `No access to "${companionOptions.filePath}". Please ensure the directory exists and with read/write permissions.`, ) } const { providerOptions, periodicPingUrls, server } = companionOptions if (server?.path) { // see https://github.com/transloadit/uppy/issues/4271 // todo fix the code so we can allow `/` if (server.path === '/') throw new Error( "If you want to use '/' as server.path, leave the 'path' variable unset", ) } if (providerOptions) { const deprecatedOptions = { microsoft: 'providerOptions.onedrive', google: 'providerOptions.drive', s3: 's3', } Object.keys(deprecatedOptions).forEach((deprecated) => { if (Object.hasOwn(providerOptions, deprecated)) { throw new Error( `The Provider option "providerOptions.${deprecated}" is no longer supported. Please use the option "${deprecatedOptions[deprecated]}" instead.`, ) } }) } if ( companionOptions.uploadUrls == null || companionOptions.uploadUrls.length === 0 ) { if (process.env.NODE_ENV === 'production') throw new Error('uploadUrls is required') logger.error( 'Running without uploadUrls is a security risk and Companion will refuse to start up when running in production (NODE_ENV=production)', 'startup.uploadUrls', ) } if (companionOptions.corsOrigins == null) { throw new TypeError( 'Option corsOrigins is required. To disable security, pass true', ) } if (companionOptions.corsOrigins === '*') { throw new TypeError( 'Option corsOrigins cannot be "*". To disable security, pass true', ) } if ( periodicPingUrls != null && (!Array.isArray(periodicPingUrls) || periodicPingUrls.some( (url2) => !validator.isURL(url2, { protocols: ['http', 'https'], require_protocol: true, require_tld: false, }), )) ) { throw new TypeError('Invalid periodicPingUrls') } if (companionOptions.maxFilenameLength <= 0) { throw new TypeError('Option maxFilenameLength must be greater than 0') } }