Skip to content

Instantly share code, notes, and snippets.

@igoralves1
Last active August 30, 2024 16:19
Show Gist options
  • Save igoralves1/4b9f0fa52714973dc9fd7b59a0068635 to your computer and use it in GitHub Desktop.
Save igoralves1/4b9f0fa52714973dc9fd7b59a0068635 to your computer and use it in GitHub Desktop.
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 });
}
}
{
"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 { logger } = require('./logger');
exports.setGlobalVars = () => {
global.Logger = logger(process.env.logLevel);
};
const pino = require('pino');
module.exports.logger = (level) => pino({ level });
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;
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),
})
);
});
});
@igoralves1
Copy link
Author

1 test case is false - "name": "ftestna_mehyui",

2 test true - "name": "ftestna_mehyui_",

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