Skip to content

Commit

Permalink
@uppy/companion: remove searchProviders wrapper & move s3 options (
Browse files Browse the repository at this point in the history
  • Loading branch information
Murderlon authored and aduh95 committed May 30, 2022
1 parent 7abf690 commit aaeb89b
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 82 deletions.
2 changes: 1 addition & 1 deletion packages/@uppy/companion/src/companion.js
Expand Up @@ -117,7 +117,7 @@ module.exports.app = (optionsArg = {}) => {

// add uppy options to the request object so it can be accessed by subsequent handlers.
app.use('*', middlewares.getCompanionMiddleware(options))
app.use('/s3', s3(options.providerOptions.s3))
app.use('/s3', s3(options.s3))
app.use('/url', url())

app.post('/:providerName/preauth', middlewares.hasSessionAndProvider, controllers.preauth)
Expand Down
24 changes: 14 additions & 10 deletions packages/@uppy/companion/src/config/companion.js
Expand Up @@ -8,15 +8,14 @@ const defaultOptions = {
protocol: 'http',
path: '',
},
providerOptions: {
s3: {
acl: 'public-read', // todo default to no ACL in next major
endpoint: 'https://{service}.{region}.amazonaws.com',
conditions: [],
useAccelerateEndpoint: false,
getKey: (req, filename) => filename,
expires: ms('5 minutes') / 1000,
},
providerOptions: {},
s3: {
acl: 'public-read', // todo default to no ACL in next major
endpoint: 'https://{service}.{region}.amazonaws.com',
conditions: [],
useAccelerateEndpoint: false,
getKey: (req, filename) => filename,
expires: ms('5 minutes') / 1000,
},
allowLocalUrls: false,
logClientVersion: true,
Expand All @@ -30,7 +29,8 @@ const defaultOptions = {
*/
function getMaskableSecrets (companionOptions) {
const secrets = []
const { providerOptions, customProviders } = companionOptions
const { providerOptions, customProviders, s3 } = companionOptions

Object.keys(providerOptions).forEach((provider) => {
if (providerOptions[provider].secret) {
secrets.push(providerOptions[provider].secret)
Expand All @@ -45,6 +45,10 @@ function getMaskableSecrets (companionOptions) {
})
}

if (s3?.secret) {
secrets.push(s3.secret)
}

return secrets
}

Expand Down
2 changes: 1 addition & 1 deletion packages/@uppy/companion/src/server/Uploader.js
Expand Up @@ -345,7 +345,7 @@ class Uploader {
storage: redis.client(),
s3: req.companion.s3Client ? {
client: req.companion.s3Client,
options: req.companion.options.providerOptions.s3,
options: req.companion.options.s3,
} : null,
chunkSize: req.companion.options.chunkSize,
}
Expand Down
6 changes: 3 additions & 3 deletions packages/@uppy/companion/src/server/middlewares.js
Expand Up @@ -69,14 +69,14 @@ exports.cookieAuthToken = (req, res, next) => {
}

exports.loadSearchProviderToken = (req, res, next) => {
const { searchProviders } = req.companion.options.providerOptions
const { providerOptions } = req.companion.options
const providerName = req.params.searchProviderName
if (!searchProviders || !searchProviders[providerName] || !searchProviders[providerName].key) {
if (!providerOptions[providerName] || !providerOptions[providerName].key) {
logger.info(`unconfigured credentials for ${providerName}`, 'searchtoken.load.unset', req.id)
return res.sendStatus(501)
}

req.companion.providerToken = searchProviders[providerName].key
req.companion.providerToken = providerOptions[providerName].key
next()
}

Expand Down
2 changes: 0 additions & 2 deletions packages/@uppy/companion/src/server/provider/index.js
Expand Up @@ -188,8 +188,6 @@ module.exports.addProviderOptions = (companionOptions, grantConfig) => {
} else if (server.path) {
grantConfig[authProvider].callback = `${server.path}${grantConfig[authProvider].callback}`
}
} else if (!['s3', 'searchProviders'].includes(providerName)) {
logger.warn(`skipping one found unsupported provider "${providerName}".`, 'provider.options.skip')
}
})
}
22 changes: 11 additions & 11 deletions packages/@uppy/companion/src/server/s3-client.js
Expand Up @@ -8,35 +8,35 @@ const AWS = require('aws-sdk')
*/
module.exports = (companionOptions) => {
let s3Client = null
if (companionOptions.providerOptions.s3) {
const s3ProviderOptions = companionOptions.providerOptions.s3
if (companionOptions.s3) {
const { s3 } = companionOptions

if (s3ProviderOptions.accessKeyId || s3ProviderOptions.secretAccessKey) {
if (s3.accessKeyId || s3.secretAccessKey) {
throw new Error('Found `providerOptions.s3.accessKeyId` or `providerOptions.s3.secretAccessKey` configuration, but Companion requires `key` and `secret` option names instead. Please use the `key` property instead of `accessKeyId` and the `secret` property instead of `secretAccessKey`.')
}

const rawClientOptions = s3ProviderOptions.awsClientOptions
const rawClientOptions = s3.awsClientOptions
if (rawClientOptions && (rawClientOptions.accessKeyId || rawClientOptions.secretAccessKey)) {
throw new Error('Found unsupported `providerOptions.s3.awsClientOptions.accessKeyId` or `providerOptions.s3.awsClientOptions.secretAccessKey` configuration. Please use the `providerOptions.s3.key` and `providerOptions.s3.secret` options instead.')
}

const s3ClientOptions = {
signatureVersion: 'v4',
endpoint: s3ProviderOptions.endpoint,
region: s3ProviderOptions.region,
endpoint: s3.endpoint,
region: s3.region,
// backwards compat
useAccelerateEndpoint: s3ProviderOptions.useAccelerateEndpoint,
useAccelerateEndpoint: s3.useAccelerateEndpoint,
...rawClientOptions,
}

// Use credentials to allow assumed roles to pass STS sessions in.
// If the user doesn't specify key and secret, the default credentials (process-env)
// will be used by S3 in calls below.
if (s3ProviderOptions.key && s3ProviderOptions.secret && !s3ClientOptions.credentials) {
if (s3.key && s3.secret && !s3ClientOptions.credentials) {
s3ClientOptions.credentials = new AWS.Credentials(
s3ProviderOptions.key,
s3ProviderOptions.secret,
s3ProviderOptions.sessionToken,
s3.key,
s3.secret,
s3.sessionToken,
)
}
s3Client = new S3(s3ClientOptions)
Expand Down
37 changes: 14 additions & 23 deletions packages/@uppy/companion/src/standalone/helper.js
Expand Up @@ -64,26 +64,22 @@ const getConfigFromEnv = () => {
verificationToken: getSecret('COMPANION_ZOOM_VERIFICATION_TOKEN'),
credentialsURL: process.env.COMPANION_ZOOM_KEYS_ENDPOINT,
},
// TODO: remove the redundant searchProviders warpper in next major version
searchProviders: {
unsplash: {
key: process.env.COMPANION_UNSPLASH_KEY,
secret: process.env.COMPANION_UNSPLASH_SECRET,
},
},
// TODO: move s3 out of providerOptions, it's a destination, not a source
s3: {
key: process.env.COMPANION_AWS_KEY,
secret: getSecret('COMPANION_AWS_SECRET'),
bucket: process.env.COMPANION_AWS_BUCKET,
endpoint: process.env.COMPANION_AWS_ENDPOINT,
region: process.env.COMPANION_AWS_REGION,
useAccelerateEndpoint:
process.env.COMPANION_AWS_USE_ACCELERATE_ENDPOINT === 'true',
expires: parseInt(process.env.COMPANION_AWS_EXPIRES || '300', 10),
acl: process.env.COMPANION_AWS_DISABLE_ACL === 'true' ? null : (process.env.COMPANION_AWS_ACL || 'public-read'), // todo default to no ACL in next major and remove COMPANION_AWS_DISABLE_ACL
unsplash: {
key: process.env.COMPANION_UNSPLASH_KEY,
secret: process.env.COMPANION_UNSPLASH_SECRET,
},
},
s3: {
key: process.env.COMPANION_AWS_KEY,
secret: getSecret('COMPANION_AWS_SECRET'),
bucket: process.env.COMPANION_AWS_BUCKET,
endpoint: process.env.COMPANION_AWS_ENDPOINT,
region: process.env.COMPANION_AWS_REGION,
useAccelerateEndpoint:
process.env.COMPANION_AWS_USE_ACCELERATE_ENDPOINT === 'true',
expires: parseInt(process.env.COMPANION_AWS_EXPIRES || '300', 10),
acl: process.env.COMPANION_AWS_DISABLE_ACL === 'true' ? null : (process.env.COMPANION_AWS_ACL || 'public-read'), // todo default to no ACL in next major and remove COMPANION_AWS_DISABLE_ACL
},
server: {
host: process.env.COMPANION_DOMAIN,
protocol: process.env.COMPANION_PROTOCOL,
Expand Down Expand Up @@ -190,11 +186,6 @@ exports.buildHelpfulStartupMessage = (companionOptions) => {
const buildURL = utils.getURLBuilder(companionOptions)
const callbackURLs = []
Object.keys(companionOptions.providerOptions).forEach((providerName) => {
// s3 does not need redirect_uris
if (providerName === 's3') {
return
}

callbackURLs.push(buildURL(`/connect/${providerName}/redirect`, true))
})

Expand Down
58 changes: 27 additions & 31 deletions website/src/docs/companion.md
Expand Up @@ -323,16 +323,16 @@ const options = {
key: '***',
secret: '***',
},
s3: {
getKey: (req, filename, metadata) => filename,
key: '***',
secret: '***',
bucket: 'bucket-name',
region: 'us-east-1',
useAccelerateEndpoint: false, // default: false,
expires: 3600, // default: 300 (5 minutes)
acl: 'private', // default: public-read
},
},
s3: {
getKey: (req, filename, metadata) => filename,
key: '***',
secret: '***',
bucket: 'bucket-name',
region: 'us-east-1',
useAccelerateEndpoint: false, // default: false,
expires: 3600, // default: 300 (5 minutes)
acl: 'private', // default: public-read
},
server: {
host: 'localhost:3020', // or yourdomain.com
Expand Down Expand Up @@ -417,34 +417,34 @@ Please see [Supported Providers](https://uppy.io/docs/companion/#Supported-provi

Companion comes with signature endpoints for AWS S3. These can be used by the Uppy client to sign requests to upload files directly to S3, without exposing secret S3 keys in the browser. Companion also supports uploading files from providers like Dropbox and Instagram directly into S3.

The S3 features can be configured using the `providerOptions.s3` property.
The S3 features can be configured using the `s3` property.

#### `providerOptions.s3.key`
#### `s3.key`

The S3 access key ID. The standalone Companion server populates this with the value of the `COMPANION_AWS_KEY` environment variable by default.

#### `providerOptions.s3.secret`
#### `s3.secret`

The S3 secret access key. The standalone Companion server populates this with the value of the `COMPANION_AWS_SECRET` environment variable by default.

#### `providerOptions.s3.bucket`
#### `s3.bucket`

The name of the bucket to store uploaded files in. The standalone Companion server populates this with the value of the `COMPANION_AWS_BUCKET` environment variable by default.

#### `providerOptions.s3.region`
#### `s3.region`

The datacenter region where the target bucket is located. The standalone Companion server populates this with the value of the `COMPANION_AWS_REGION` environment variable by default.

#### `providerOptions.s3.awsClientOptions`
#### `s3.awsClientOptions`

You can supply any [S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) in the `providerOptions.s3.awsClientOptions` object, _except for_ the below:
You can supply any [S3 option supported by the AWS SDK](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) in the `s3.awsClientOptions` object, _except for_ the below:

* `accessKeyId`. Instead, use the `providerOptions.s3.key` property. This is to make configuration names consistent between different Companion features.
* `secretAccessKey`. Instead, use the `providerOptions.s3.secret` property. This is to make configuration names consistent between different Companion features.
* `accessKeyId`. Instead, use the `s3.key` property. This is to make configuration names consistent between different Companion features.
* `secretAccessKey`. Instead, use the `s3.secret` property. This is to make configuration names consistent between different Companion features.

Be aware that some options may cause wrong behaviour if they conflict with Companion’s assumptions. If you find that a particular option does not work as expected, please [open an issue on the Uppy repository](https://github.com/transloadit/uppy/issues/new) so we can document it here.

#### `providerOptions.s3.getKey(req, filename, metadata)`
#### `s3.getKey(req, filename, metadata)`

Get the key name for a file. The key is the file path to which the file will be uploaded in your bucket. This option should be a function receiving three arguments:

Expand All @@ -456,24 +456,20 @@ This function should return a string `key`. The `req` parameter can be used to u

```js
app.use(authenticationMiddleware)
app.use(uppy.app({
providerOptions: {
s3: {
getKey: (req, filename, metadata) => `${req.user.id}/${filename}`,
/* auth options */
},
app.use(companion.app({
s3: {
getKey: (req, filename, metadata) => `${req.user.id}/${filename}`,
/* auth options */
},
}))
```

The default implementation returns the `filename`, so all files will be uploaded to the root of the bucket as their original file name.

```js
app.use(uppy.app({
providerOptions: {
s3: {
getKey: (req, filename, metadata) => filename,
},
app.use(companion.app({
s3: {
getKey: (req, filename, metadata) => filename,
},
}))
```
Expand Down

0 comments on commit aaeb89b

Please sign in to comment.