/** * Model: Users */ const AWS = require('aws-sdk') const shortid = require('shortid') const utils = require('../utils') const dynamodb = new AWS.DynamoDB.DocumentClient({ region: process.env.AWS_REGION }) /** * Register user * @param {string} user.email User email * @param {string} user.password User password */ const register = async(user = {}) => { // Validate if (!user.email) { throw new Error(`"email" is required`) } if (!user.password) { throw new Error(`"password" is required`) } if (!utils.validateEmailAddress(user.email)) { throw new Error(`"${user.email}" is not a valid email address`) } // Check if user is already registered const existingUser = await getByEmail(user.email) if (existingUser) { throw new Error(`A user with email "${user.email}" is already registered`) } user.password = utils.hashPassword(user.password) // Save const params = { TableName: process.env.db, Item: { hk: user.email, sk: 'user', sk2: shortid.generate(), createdAt: Date.now(), updatedAt: Date.now(), password: user.password, } } await dynamodb.put(params).promise() } /** * Get user by email address * @param {string} email */ const getByEmail = async(email) => { // Validate if (!email) { throw new Error(`"email" is required`) } if (!utils.validateEmailAddress(email)) { throw new Error(`"${email}" is not a valid email address`) } // Query const params = { TableName: process.env.db, KeyConditionExpression: 'hk = :hk', ExpressionAttributeValues: { ':hk': email } } let user = await dynamodb.query(params).promise() user = user.Items && user.Items[0] ? user.Items[0] : null if (user) { user.id = user.sk2 user.email = user.hk } return user } /** * Get user by id * @param {string} id */ const getById = async(id) => { // Validate if (!id) { throw new Error(`"id" is required`) } // Query const params = { TableName: process.env.db, IndexName: process.env.dbIndex1, KeyConditionExpression: 'sk2 = :sk2 and sk = :sk', ExpressionAttributeValues: { ':sk2': id, ':sk': 'user' } } let user = await dynamodb.query(params).promise() user = user.Items && user.Items[0] ? user.Items[0] : null if (user) { user.id = user.sk2 user.email = user.hk } return user } /** * Convert user record to public format * This hides the keys used for the dynamodb's single table design and returns human-readable properties. * @param {*} user */ const convertToPublicFormat = (user = {}) => { user.email = user.hk || null user.id = user.sk2 || null if (user.hk) delete user.hk if (user.sk) delete user.sk if (user.sk2) delete user.sk2 if (user.password) delete user.password return user } module.exports = { register, getByEmail, getById, convertToPublicFormat, }