Lambda Router
index.js
const Router = require('./Router');
const orgs = require('./orgs');
exports.handler = async (event, context, callback)=> {
const router = Router(event, context, callback);
router.attach(orgs);
const out = await router.handle();
if(out) return out;
callback(null, {
statusCode: 200,
body: JSON.stringify(event)
});
};
users.js
const DB = require('./DB');
const routes = {
'GET:/users': async (evt, callback)=> {
const list = await DB.getUserList();
callback(null, { statusCode: 200, body: list });
},
'GET:/users/{id}': async (evt, callback)=> {
const {id} = evt.pathParameters;
if(id === 'test') {
const user = await DB.getUser('dominip');
return { statusCode: 200, body: user };
}
const item = await DB.getUser(id);
if(!item) {
callback(null, { statusCode: 404, body: null});
} else {
callback(null, { statusCode: 200, body: item });
}
},
'POST:/users': async (evt, callback)=> {
const {id, name, pwd, email, duration, org} = JSON.parse(evt.body);
let item = await DB.createUser({id, name, pwd, email, duration, org});
if(item) {
callback(null, { statusCode: 200, body: item });
} else {
callback(null, { statusCode: 409, body: {error: "something went wrong"} });
}
},
'DELETE:/users/{id}': async (evt, callback)=> {
const {id} = evt.pathParameters;
const item = await DB.deleteUser(id);
if(item) {
callback(null, { statusCode: 200, body: item });
} else {
callback("error", { statusCode: 500 });
}
},
'PUT:/users/{id}': async (evt, callback)=> {
},
};
module.exports = routes;
db.js
const AWS = require('aws-sdk');
const bcrypt = require('./bcrypt')
const TABLE_USER = 'partner_users';
const ddb = new AWS.DynamoDB.DocumentClient({
apiVersion: '2012-08-10',
region: process.env.AWS_REGION,
sslEnabled: false,
paramValidation: false,
convertResponseTypes: false
});
const GetAllItems = async (TableName)=> {
try {
const data = await ddb.scan({ TableName }).promise();
return data.Items;
} catch (e) {
return [];
}
};
const CreateItem = async (TableName, Item)=> {
try {
await ddb.put({ TableName, Item }).promise();
} catch(err) {
return null;
}
return Item;
};
const GetItemById = async (TableName, id)=> {
try {
const data = await ddb.get({
TableName,
Key: { id }
}).promise();
return data.Item;
} catch (e) {
return null;
}
};
const DeleteItemById = async (TableName, id)=> {
try {
await ddb.delete({
TableName,
Key: { id }
}).promise();
return {deletedItem: {id}};
} catch (e) {
return {deletedItem: null};
}
};
const getHash = (pwd, rounds=10)=> {
const salt = bcrypt.genSaltSync(rounds);
return bcrypt.hashSync(pwd, salt);
};
const getUserList = async ()=> {
return await GetAllItems(TABLE_USER);
};
const createUser = async ({id, name, pwd, email, duration, org})=> {
pwd = getHash(pwd);
duration = parseInt(duration) || 365;
const exp = Date.now() + duration*24*60*60*1000; // duration is in days
return await CreateItem(TABLE_USER, {id, name, pwd, email, exp, org});
};
const getUser = async (id)=> {
return await GetItemById(TABLE_USER, id);
};
const deleteUser = async (id)=> {
return await DeleteItemById(TABLE_USER, id);
};
module.exports = {
getUserList,
createUser,
getUser,
deleteUser,
};
Router.js
module.exports = (event, context, cb) => {
const myRoutes = {};
const sanitizeResponse = (res)=> {
// Enable CORS
res.headers = Object.assign({}, res.headers, {
"Access-Control-Allow-Headers": 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Set-Cookie',
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*"
});
if(res.body && typeof res.body !== 'string') res.body = JSON.stringify(res.body);
return res;
};
const sanitizedCallback = (err, res)=> {
sanitizeResponse(res);
cb(err, res);
};
const attach = (routes)=> {
Object.assign(myRoutes, routes);
};
const handle = async ()=> {
const routeKey = event.httpMethod + ':' + event.resource;
if(myRoutes[routeKey]) {
return sanitizeResponse(await myRoutes[routeKey](event, sanitizedCallback));
}
return null;
};
return {attach, handle};
};