diff --git a/packages/core/upload/server/services/extensions/content-manager/entity-manager.js b/packages/core/upload/server/services/extensions/content-manager/entity-manager.js index b1a22ffbdd..51117e4b5b 100644 --- a/packages/core/upload/server/services/extensions/content-manager/entity-manager.js +++ b/packages/core/upload/server/services/extensions/content-manager/entity-manager.js @@ -58,11 +58,12 @@ const signEntityMedia = async (entity, uid) => { return signedEntity; }; -const addSignedFileUrlsToAdmin = () => { +const addSignedFileUrlsToAdmin = async () => { const { provider } = strapi.plugins.upload; + const isPrivate = await provider.isPrivate(); // We only need to sign the file urls if the provider is private - if (!provider.isPrivate()) { + if (!isPrivate) { return; } diff --git a/packages/core/upload/server/services/file.js b/packages/core/upload/server/services/file.js index 938168d936..5695552020 100644 --- a/packages/core/upload/server/services/file.js +++ b/packages/core/upload/server/services/file.js @@ -23,18 +23,13 @@ const deleteByIds = async (ids = []) => { return filesToDelete; }; -const signFileUrl = async (fileIdentifier) => { - const { provider } = strapi.plugins.upload; - const { url } = await provider.getSignedUrl(fileIdentifier); - return url; -}; - const signFileUrls = async (file) => { const { provider } = strapi.plugins.upload; const { provider: providerConfig } = strapi.config.get('plugin.upload'); + const isPrivate = await provider.isPrivate(); // Check file provider and if provider is private - if (file.provider !== providerConfig || !provider.isPrivate()) { + if (file.provider !== providerConfig || !isPrivate) { return file; } @@ -57,6 +52,5 @@ const signFileUrls = async (file) => { module.exports = { getFolderPath, deleteByIds, - signFileUrl, signFileUrls, }; diff --git a/packages/providers/upload-aws-s3/README.md b/packages/providers/upload-aws-s3/README.md index d35adc75a8..c5b874b7c5 100644 --- a/packages/providers/upload-aws-s3/README.md +++ b/packages/providers/upload-aws-s3/README.md @@ -25,6 +25,10 @@ npm install @strapi/provider-upload-aws-s3 --save - `provider` defines the name of the provider - `providerOptions` is passed down during the construction of the provider. (ex: `new AWS.S3(config)`). [Complete list of options](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#constructor-property) +- `providerOptions.params` is passed directly to the parameters to each method respectively. + - `ACL` is the access control list for the object. Defaults to `public-read`. + - `signedUrlExpires` is the number of seconds before a signed URL expires. (See [how signed URLs work](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html)). Defaults to 7 days and URLs are only signed when ACL is set to `private`. + - `Bucket` is the name of the bucket to upload to. - `actionOptions` is passed directly to the parameters to each method respectively. You can find the complete list of [upload/ uploadStream options](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#upload-property) and [delete options](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObject-property) See the [documentation about using a provider](https://docs.strapi.io/developer-docs/latest/plugins/upload.html#using-a-provider) for information on installing and using a provider. To understand how environment variables are used in Strapi, please refer to the [documentation about environment variables](https://docs.strapi.io/developer-docs/latest/setup-deployment-guides/configurations/optional/environment.html#environment-variables). @@ -44,6 +48,8 @@ module.exports = ({ env }) => ({ secretAccessKey: env('AWS_ACCESS_SECRET'), region: env('AWS_REGION'), params: { + ACL: env('AWS_ACL', 'public-read'), + signedUrlExpires: env('AWS_SIGNED_URL_EXPIRES', 60 * 60 * 24 * 7), Bucket: env('AWS_BUCKET'), }, }, diff --git a/packages/providers/upload-aws-s3/lib/index.js b/packages/providers/upload-aws-s3/lib/index.js index d1b0031f4e..524ce01abd 100644 --- a/packages/providers/upload-aws-s3/lib/index.js +++ b/packages/providers/upload-aws-s3/lib/index.js @@ -21,6 +21,8 @@ module.exports = { ...config, }); + const ACL = get(config, ['params', 'ACL'], 'public-read'); + const upload = (file, customParams = {}) => new Promise((resolve, reject) => { // upload file on S3 bucket @@ -30,7 +32,7 @@ module.exports = { { Key: fileKey, Body: file.stream || Buffer.from(file.buffer, 'binary'), - ACL: 'private', + ACL, ContentType: file.mime, ...customParams, }, @@ -53,24 +55,27 @@ module.exports = { return { isPrivate() { - return get(config, ['params', 'isPrivate'], false); + return ACL === 'private'; }, /** - * - * @param {string} fileIdentifier - * @param {*} customParams - * @returns + * @param {Object} file + * @param {string} file.path + * @param {string} file.hash + * @param {string} file.ext + * @param {Object} customParams + * @returns {Promise<{url: string}>} */ getSignedUrl(file, customParams = {}) { return new Promise((resolve, reject) => { const path = file.path ? `${file.path}/` : ''; const fileKey = `${path}${file.hash}${file.ext}`; + S3.getSignedUrl( 'getObject', { Bucket: config.params.Bucket, Key: fileKey, - Expires: 60 * 60 * 24 * 7, // TODO: Make this configurable. + Expires: get(config, ['params', 'signedUrlExpires'], 60 * 60 * 24 * 7), // 7 days }, (err, url) => { if (err) {