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

API Sign: Change the S3 Provider into a signer #1698

Merged
merged 20 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions mod/provider/_provider.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,11 @@ const file = require('./file')

const cloudfront = require('./cloudfront')

const s3 = require('./s3')

module.exports = async (req, res) => {

const provider = {
cloudfront,
file,
s3
file
}

if (!Object.hasOwn(provider, req.params.provider)) {
Expand Down
102 changes: 0 additions & 102 deletions mod/provider/s3.js

This file was deleted.

4 changes: 3 additions & 1 deletion mod/sign/_sign.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ The sign module provides access to different request signer methods.
*/

const cloudinary = require('./cloudinary')
const s3 = require('./s3')

const signerModules = {
cloudinary
cloudinary,
s3
}

/**
Expand Down
97 changes: 97 additions & 0 deletions mod/sign/s3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/**
@module /sign/s3

Signs requests to S3. Provides functions for get, list, delete and put to S3.
*/

const {
S3Client,
PutObjectCommand,
GetObjectCommand,
DeleteObjectCommand,
ListObjectsCommand
} = require('@aws-sdk/client-s3')

const { getSignedUrl } = require('@aws-sdk/s3-request-presigner');

/**
@function s3
@async

@description
The s3 signer method signs requests for the s3 service.

Provides methods for list, get, trash and put

@param {Object} req HTTP request.
@param {Object} res HTTP response.
@param {Object} req.params Request parameter.
@param {string} params.region
@param {string} params.bucket
@param {string} params.key
@param {string} params.command

@returns {Promise<String>} The signed url associated to the request params.
**/
module.exports = async function s3(req, res){

//Read credentials from an env key
const credentials = Object.fromEntries(new URLSearchParams(process.env.AWS_S3_CLIENT))

const s3Client = new S3Client({
credentials,
region: req.params.region
})

req.params.s3Client = s3Client

//Assign the corresponding function to the requested command
const commands = {
get: () => objectAction(req.params,GetObjectCommand),
trash: () => objectAction(req.params,DeleteObjectCommand),
put: () => objectAction(req.params,PutObjectCommand),
list: () => objectAction(req.params,ListObjectsCommand)
}

if (!Object.hasOwn(commands, req.params.command)) {
return res.status(400).send(`S3 command validation failed.`)
}

return commands[req.params.command]()
}

async function objectAction(reqParams, objectCommand) {
AlexanderGeere marked this conversation as resolved.
Show resolved Hide resolved

//The parameters required per action for S3
//S3 Parameters are capitalised
const actionParams = {
get: {'key':'Key','bucket': 'Bucket'},
list: {'bucket': 'Bucket'},
put: {'key': 'Key','bucket': 'Bucket','region': 'Region'},
trash: {'key': 'Key','bucket': 'Bucket'}
}

try {

//Transfrom our keys into aws key names
const commandParams = Object.keys(reqParams)
.filter(key => Object.keys(actionParams[reqParams.command]).includes(key))
.reduce((acc, key) => ({
...acc,
...{ [actionParams[reqParams.command][key]]: reqParams[key]}
}),
{}
)

const command = new objectCommand(commandParams)

const signedURL = await getSignedUrl(reqParams.s3Client, command, {
expiresIn: 3600,
});

return JSON.stringify(signedURL);

} catch (err) {
console.error(err)
}
}
Loading