Skip to content

Commit

Permalink
Error if any ENVs are missing (#8)
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanto authored Mar 29, 2021
1 parent 2333087 commit 2178fa9
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 101 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
"react-dom": "^17.0.1",
"size-limit": "^4.7.0",
"tsdx": "^0.14.1",
"tslib": "^2.0.3",
"typescript": "^4.0.5"
"tslib": "^2.1.0",
"typescript": "^4.2.3"
},
"dependencies": {
"aws-sdk": "^2.791.0",
Expand Down
113 changes: 59 additions & 54 deletions src/hooks/use-s3-upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,60 +63,65 @@ export const useS3Upload = () => {
let res = await fetch(`/api/s3-upload?filename=${filename}`);
let data = await res.json();

let s3 = new S3({
accessKeyId: data.token.Credentials.AccessKeyId,
secretAccessKey: data.token.Credentials.SecretAccessKey,
sessionToken: data.token.Credentials.SessionToken,
});

let blob = await getFileContents(file);

let params = {
ACL: 'public-read',
Bucket: data.bucket,
Key: data.key,
Body: blob,
CacheControl: 'max-age=630720000, public',
ContentType: file.type,
};

// at some point make this configurable
// let uploadOptions = {
// partSize: 100 * 1024 * 1024,
// queueSize: 1,
// };

let s3Upload = s3.upload(params);

setFiles(files => [
...files,
{ file, progress: 0, uploaded: 0, size: file.size },
]);

s3Upload.on('httpUploadProgress', event => {
if (event.total) {
setFiles(files =>
files.map(trackedFile =>
trackedFile.file === file
? {
file,
uploaded: event.loaded,
size: event.total,
progress: (event.loaded / event.total) * 100,
}
: trackedFile
)
);
}
});

let uploadResult = await s3Upload.promise();

return {
url: uploadResult.Location,
bucket: uploadResult.Bucket,
key: uploadResult.Key,
};
if (data.error) {
console.error(data.error);
throw data.error;
} else {
let s3 = new S3({
accessKeyId: data.token.Credentials.AccessKeyId,
secretAccessKey: data.token.Credentials.SecretAccessKey,
sessionToken: data.token.Credentials.SessionToken,
});

let blob = await getFileContents(file);

let params = {
ACL: 'public-read',
Bucket: data.bucket,
Key: data.key,
Body: blob,
CacheControl: 'max-age=630720000, public',
ContentType: file.type,
};

// at some point make this configurable
// let uploadOptions = {
// partSize: 100 * 1024 * 1024,
// queueSize: 1,
// };

let s3Upload = s3.upload(params);

setFiles(files => [
...files,
{ file, progress: 0, uploaded: 0, size: file.size },
]);

s3Upload.on('httpUploadProgress', event => {
if (event.total) {
setFiles(files =>
files.map(trackedFile =>
trackedFile.file === file
? {
file,
uploaded: event.loaded,
size: event.total,
progress: (event.loaded / event.total) * 100,
}
: trackedFile
)
);
}
});

let uploadResult = await s3Upload.promise();

return {
url: uploadResult.Location,
bucket: uploadResult.Bucket,
key: uploadResult.Key,
};
}
};

return {
Expand Down
91 changes: 54 additions & 37 deletions src/pages/api/s3-upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,67 @@ type Options = {

let makeRouteHandler = (options: Options = {}): Handler => {
let route: NextRouteHandler = async function(req, res) {
let config = {
accessKeyId: process.env.S3_UPLOAD_KEY,
secretAccessKey: process.env.S3_UPLOAD_SECRET,
region: process.env.S3_UPLOAD_REGION,
};

let bucket = process.env.S3_UPLOAD_BUCKET;

let filename = req.query.filename as string;
let key = options.key
? options.key(req, filename)
: `next-s3-uploads/${uuidv4()}/${filename.replace(/\s/g, '-')}`;

let policy = {
Statement: [
{
Sid: 'Stmt1S3UploadAssets',
Effect: 'Allow',
Action: ['s3:PutObject', 's3:PutObjectAcl'],
Resource: [`arn:aws:s3:::${bucket}/${key}`],
},
],
};

let sts = new aws.STS(config);

let token = await sts
.getFederationToken({
Name: 'S3UploadWebToken',
Policy: JSON.stringify(policy),
DurationSeconds: 60 * 60, // 1 hour
})
.promise();

res.statusCode = 200;

res.status(200).json({ token, key, bucket });
let missing = missingEnvs();
if (missing.length > 0) {
res
.status(500)
.json({ error: `Next S3 Upload: Missing ENVs ${missing.join(', ')}` });
} else {
let config = {
accessKeyId: process.env.S3_UPLOAD_KEY,
secretAccessKey: process.env.S3_UPLOAD_SECRET,
region: process.env.S3_UPLOAD_REGION,
};

let bucket = process.env.S3_UPLOAD_BUCKET;

let filename = req.query.filename as string;
let key = options.key
? options.key(req, filename)
: `next-s3-uploads/${uuidv4()}/${filename.replace(/\s/g, '-')}`;

let policy = {
Statement: [
{
Sid: 'Stmt1S3UploadAssets',
Effect: 'Allow',
Action: ['s3:PutObject', 's3:PutObjectAcl'],
Resource: [`arn:aws:s3:::${bucket}/${key}`],
},
],
};

let sts = new aws.STS(config);

let token = await sts
.getFederationToken({
Name: 'S3UploadWebToken',
Policy: JSON.stringify(policy),
DurationSeconds: 60 * 60, // 1 hour
})
.promise();

res.statusCode = 200;

res.status(200).json({ token, key, bucket });
}
};

let configure = (options: Options) => makeRouteHandler(options);

return Object.assign(route, { configure });
};

let missingEnvs = (): string[] => {
let keys = [
'S3_UPLOAD_KEY',
'S3_UPLOAD_SECRET',
'S3_UPLOAD_REGION',
'S3_UPLOAD_BUCKET',
];
return keys.filter(key => !process.env[key]);
};

let APIRoute = makeRouteHandler();

export { APIRoute };
16 changes: 8 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10094,10 +10094,10 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

tslib@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c"
integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==
tslib@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==

tsutils@^3.17.1:
version "3.17.1"
Expand Down Expand Up @@ -10190,10 +10190,10 @@ typescript@^3.7.3:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa"
integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==

typescript@^4.0.5:
version "4.0.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389"
integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ==
typescript@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.3.tgz#39062d8019912d43726298f09493d598048c1ce3"
integrity sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==

unicode-canonical-property-names-ecmascript@^1.0.4:
version "1.0.4"
Expand Down

0 comments on commit 2178fa9

Please sign in to comment.