Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Companion server s3 configuration to let bucket key to be a function and passing down the request #4488

Closed
wants to merge 0 commits into from

Conversation

rmoura-92
Copy link
Contributor

@rmoura-92 rmoura-92 commented Jun 6, 2023

had a very specific need to target dynamically buckets based on some req property defined in the implementation of the server config.

typically we do this config for s3.

{
  getKey: (req, filename, metadata) => {
    if (metadata.folder) {
      return metadata.folder + filename;
    }
    return filename;
  },
  bucket: process.env.S3_BUCKET,
  key: process.env.S3_ACCESS_KEY,
  secret: process.env.S3_ACCESS_PKEY,
  region: process.env.S3_REGION
}

now we can augment the bucket key passing a function, the previous way still valid.

{
  getKey: (req, filename, metadata) => {
    if (metadata.folder) {
      return metadata.folder + filename;
    }
    return filename;
  },
  getBucket: (req) => {
    return req.context.bucket; // do whatever u need based on req to manipulate the target bucket
  },
  bucket: process.env.S3_BUCKET_FALLBACK, // ?
  key: process.env.S3_ACCESS_KEY,
  secret: process.env.S3_ACCESS_PKEY,
  region: process.env.S3_REGION
}

Copy link
Contributor

@mifi mifi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR ! I think we should refactor this to allow more code reuse

Copy link
Contributor

@aduh95 aduh95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Mikael, we should avoid the code repetition when we can

packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
@rmoura-92
Copy link
Contributor Author

adjusted with the suggestions

@rmoura-92 rmoura-92 requested a review from mifi June 14, 2023 15:41
@Murderlon
Copy link
Member

Does this mean you're blindly setting the bucket based on the client request? Could this be abused?

bucket: (req) => {
    return req.context.bucket;
},

Copy link
Contributor

@aduh95 aduh95 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should validate the bucket after the function has been called. Also we should probably not disclose to the client the actual error but instead log an error on the server console.

packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
packages/@uppy/companion/src/server/controllers/s3.js Outdated Show resolved Hide resolved
@rmoura-92
Copy link
Contributor Author

rmoura-92 commented Jun 15, 2023

should we fallback to config.bucket? in case of error in the condition from isValidBucket since theres 2 config keys now and bucket is required.

@rmoura-92
Copy link
Contributor Author

rmoura-92 commented Jun 15, 2023

@Murderlon >

you should not use this with uncontrolled inputs for sure like req.params, req.query etc..
just augments the possibilities like getKey if u have that requirement.

in my case i have a middleware that finds a DB record and i add it to req with bucket target.

@mifi
Copy link
Contributor

mifi commented Jun 15, 2023

good! now we just need to actually use the new getBucket function

@@ -36,12 +48,20 @@ module.exports = function s3 (config) {
const client = req.companion.s3Client

if (!client || typeof config.bucket !== 'string') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'd want to support passing a function here, right?

Suggested change
if (!client || typeof config.bucket !== 'string') {
if (!client) {

Copy link
Contributor Author

@rmoura-92 rmoura-92 Jun 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's using config.getBucket key for the function, lines: 27-29

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh that's confusing, I think there should be only one config key for the bucket.

@@ -16,6 +24,10 @@ module.exports = function s3 (config) {
throw new TypeError('s3: The `getKey` option must be a function')
}

function getBucket (req) {
return typeof config.getBucket === 'function' ? config.getBucket(req) : config.bucket
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we use config.bucket instead of config.getBucket? then it can be either a string or a function, and it will be backwards compatible

Comment on lines 57 to 63
const bucket = getBucket(req)

if (!isValidBucket(bucket)) {
logger.error(new TypeError(ERROR_BAD_BUCKET))
res.status(400).json({ error: ERROR_BAD_CONFIG })
return
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is repeated many times. I feel like it could be rewritten to something like this:

function validateBucket(req, res) {
    const bucket = getBucket(req)

    if (isValidBucket(bucket)) return true
    logger.error(ERROR_BAD_BUCKET)
    res.status(400).json({ error: ERROR_BAD_CONFIG })
    return false
}

then call:

if (!validateBucket(req, res)) return

(also I don't think we need to wrap the log message in a TypeError)

@aduh95
Copy link
Contributor

aduh95 commented Jun 27, 2023

@rmoura-92 are you still working on this? The diff now shows 0 file changes.

@rmoura-92
Copy link
Contributor Author

yes tomorrow will try to submit a final version. i clicked on discard by mistake due commits ahead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants