Last active
August 30, 2024 16:19
-
-
Save igoralves1/4b9f0fa52714973dc9fd7b59a0068635 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const AWS = require('aws-sdk'); | |
const moment = require('moment'); | |
const { setGlobalVars } = require("./global-vars"); | |
const responses = require("./api_responses"); | |
const util = require('./data/util'); | |
const logCat = "BlobUpload"; | |
module.exports.handler = async (event) => { | |
const logSubCat = `${logCat}-handler`; | |
setGlobalVars(); | |
Logger.info({ | |
logCat, logSubCat, message: 'Event data', data: event?.body, | |
}); | |
Logger.info({ | |
logCat, logSubCat, message: 'Headers data', data: event?.headers, | |
}); | |
const data = util.parseJson(event.body); | |
if (!data) { | |
Logger.error({logCat, logSubCat, message: 'Invalid Payload', data: {}}); | |
return responses._400({ message: 'Invalid Payload' }); | |
} | |
Logger.info({ logCat, logSubCat, message: 'Bucket', data: process.env.KITEWHEEL_BUCKET }); | |
try { | |
if (data.name == 'undefined' || data.name == '') { | |
throw new Error("Name parameter is missing"); | |
} | |
const s3 = new AWS.S3({}); | |
const regex =/(?!(^((2(5[0-5]|[0-4][0-9])|[01]?[0-9]{1,2})\.){3}(2(5[0-5]|[0-4][0-9])|[01]?[0-9]{1,2})$|^xn--|.+-s3alias$))^[a-z0-9][a-z0-9.-_]{1,61}[a-z0-9_]$/ | |
let name = new String(); | |
name = data.name; | |
if (!name.match(regex)) { | |
throw new Error("Bucket Name is not valid"); | |
} | |
const bucketName = process.env.KITEWHEEL_BUCKET + '/' + name; | |
params = { | |
Bucket: bucketName, | |
Key: `${Math.floor(Math.random() * 1000)}.${moment().unix()}.json`, | |
Body: JSON.stringify(data), | |
}; | |
Logger.info({ logCat, logSubCat, message: 'S3->PutObject Params', data: params }); | |
const result = await s3.upload(params).promise(); | |
Logger.info({ logCat, logSubCat, message: 'S3->PutObject', data: result }); | |
return responses._200(result); | |
} catch (error) { | |
Logger.error({logCat, logSubCat, message: 'S3->PutObject Error', data: error}); | |
return responses._400({ error: error.message }); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "ftestna_mehyui_", | |
"version": "1", | |
"data": { | |
"event": "string", | |
"timestamp": "timestamp", | |
"environment": "string", | |
"properties": { | |
"user_id": "string", | |
"application_name": "string", | |
"payload": [ | |
{ | |
"field": "string", | |
"value": "string" | |
} | |
] | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { logger } = require('./logger'); | |
exports.setGlobalVars = () => { | |
global.Logger = logger(process.env.logLevel); | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const pino = require('pino'); | |
module.exports.logger = (level) => pino({ level }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const responses = { | |
_200(data = {}) { | |
return { | |
headers: { | |
'Content-Type': 'application/json', | |
'Access-Control-Allow-Methods': '*', | |
'Access-Control-Allow-Origin': '*', | |
'Access-Control-Allow-Headers': 'Content-Type, X-Amz-Date, Authorization, X-Api-Key, X-Amz-Security-Token', | |
}, | |
statusCode: 200, | |
body: JSON.stringify(data), | |
}; | |
}, | |
_400(data = {}) { | |
return { | |
headers: { | |
'Content-Type': 'application/json', | |
'Access-Control-Allow-Methods': '*', | |
'Access-Control-Allow-Origin': '*', | |
}, | |
statusCode: 400, | |
body: JSON.stringify(data), | |
}; | |
}, | |
_401(data = {}) { | |
return { | |
headers: { | |
'Content-Type': 'application/json', | |
'Access-Control-Allow-Methods': '*', | |
'Access-Control-Allow-Origin': '*', | |
}, | |
statusCode: 400, | |
body: JSON.stringify(data), | |
}; | |
}, | |
_500(data = {}) { | |
return { | |
headers: { | |
'Content-Type': 'application/json', | |
'Access-Control-Allow-Methods': '*', | |
'Access-Control-Allow-Origin': '*', | |
}, | |
statusCode: 500, | |
body: JSON.stringify(data), | |
}; | |
}, | |
_204(data = {}) { | |
return { | |
headers: { | |
'Content-Type': 'application/json', | |
'Access-Control-Allow-Methods': '*', | |
'Access-Control-Allow-Origin': '*', | |
}, | |
statusCode: 204, | |
body: JSON.stringify(data), | |
}; | |
}, | |
}; | |
module.exports = responses; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const AWS = require("aws-sdk"); | |
const { handler } = require("../handler"); | |
jest.mock("aws-sdk"); | |
describe("s3 handler test", () => { | |
beforeEach(() => { | |
jest.clearAllMocks(); | |
process.env.KITEWHEEL_BUCKET = "test-bucket"; | |
process.env.logLevel = "error"; | |
}); | |
test('should fail when name starts with underscore e.g "_ftestna_mehyui"', async () => { | |
const event = { | |
body: JSON.stringify({ | |
name: "_ftestna_mehyui", | |
version: "1", | |
data: { | |
event: "string", | |
timestamp: "timestamp", | |
environment: "string", | |
properties: { | |
user_id: "string", | |
application_name: "string", | |
payload: [{ field: "string", value: "string" }], | |
}, | |
}, | |
}), | |
}; | |
const mockS3Instance = { | |
upload: jest.fn().mockReturnThis(), | |
promise: jest.fn().mockResolvedValue({ | |
Location: "https://test-bucket.s3.amazonaws.com/file.json", | |
}), | |
}; | |
AWS.S3.mockImplementation(() => mockS3Instance); | |
const result = await handler(event); | |
expect(result.statusCode).toBe(400); | |
expect(JSON.parse(result.body).error).toBe("Bucket Name is not valid"); | |
}); | |
test('should pass when name is valid e.g "ftestna_mehyui_"', async () => { | |
const event = { | |
body: JSON.stringify({ | |
name: "ftestna_mehyui_", | |
version: "1", | |
data: { | |
event: "string", | |
timestamp: "timestamp", | |
environment: "string", | |
properties: { | |
user_id: "string", | |
application_name: "string", | |
payload: [{ field: "string", value: "string" }], | |
}, | |
}, | |
}), | |
}; | |
const mockS3Instance = { | |
upload: jest.fn().mockReturnThis(), | |
promise: jest.fn().mockResolvedValue({ | |
Location: "https://test-bucket.s3.amazonaws.com/file.json", | |
}), | |
}; | |
AWS.S3.mockImplementation(() => mockS3Instance); | |
const result = await handler(event); | |
expect(result.statusCode).toBe(200); | |
expect(JSON.parse(result.body).Location).toBe( | |
"https://test-bucket.s3.amazonaws.com/file.json" | |
); | |
expect(mockS3Instance.upload).toHaveBeenCalledWith( | |
expect.objectContaining({ | |
Bucket: "test-bucket/ftestna_mehyui_", | |
Key: expect.any(String), | |
Body: expect.any(String), | |
}) | |
); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
1 test case is false - "name": "ftestna_mehyui",
2 test true - "name": "ftestna_mehyui_",