-
Notifications
You must be signed in to change notification settings - Fork 6
/
Users.js
151 lines (131 loc) · 4.7 KB
/
Users.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
const uuid = require('uuid');
const middy = require('middy');
const sanitizer = require('validator');
const bcrypt = require('bcryptjs-then');
const { jsonBodyParser } = require('middy/middlewares');
const DB = require('../../db');
const requestSchema = require('../Requests/Users');
const validatorMiddleware = require('../Middleware/Validator');
const apiResponseMiddleware = require('../Middleware/ApiResponse');
const { signToken, userByEmail, userById } = require('../Helpers/Users');
const TableName = process.env.TABLENAME_USERS;
/**
* POST /register ----------------------------------------------------
* User Sign Up
* @param event
* @param context
* @param cb
*/
const register = async (event, context, cb) => {
const { firstName, lastName, email, password } = event.body;
const params = {
TableName,
Item: {
id: await uuid.v1(),
firstName: sanitizer.trim(firstName),
lastName: sanitizer.trim(lastName),
email: sanitizer.normalizeEmail(sanitizer.trim(email)),
password: await bcrypt.hash(password, 8),
level: 'standard',
createdAt: new Date().getTime(),
updatedAt: new Date().getTime(),
},
};
return userByEmail(params.Item.email) // Does the email already exist?
.then(user => { if (user) throw new Error('User with that email exists') })
.then(() => DB.put(params).promise()) // Add the data to the DB
.then(() => userById(params.Item.id)) // Get user data from DB
.then(user => cb(null, {
statusCode: 201,
message: 'Success - you are now registered',
data: { token: signToken(params.Item.id), ...user },
}));
}
module.exports.register = middy(register)
.use(jsonBodyParser())
.use(validatorMiddleware({ inputSchema: requestSchema.register }))
.use(apiResponseMiddleware());
/**
* POST /login ----------------------------------------------------
* Logs a user in - returns a JWT token
* @param event
* @param context
* @param cb
*/
const login = async (event, context, cb) => {
const { email, password } = event.body;
return userByEmail(email) // Does the email exist?
.then(user => { if (!user) { throw new Error('Username/Password is not correct'); } return user; })
.then(async (user) => { // Check if passwords match
const passwordIsValid = await bcrypt.compare(password, user.password);
if (!passwordIsValid) throw new Error('Username/Password is not correct');
return user;
})
.then(user => cb(null, {
message: 'Success - you are now logged in',
data: { token: signToken(user.id), ...user },
}));
}
module.exports.login = middy(login)
.use(jsonBodyParser())
.use(validatorMiddleware({ inputSchema: requestSchema.login }))
.use(apiResponseMiddleware());
/**
* GET /user ----------------------------------------------------
* Returns authenticated user's login details
* @param event
* @param context
* @param cb
*/
const user = (event, context, cb) => cb(null, {
message: 'Success - user data retrieved',
data: event.requestContext.authorizer.user,
});
module.exports.user = middy(user)
.use(apiResponseMiddleware());
/**
* PUT /user ----------------------------------------------------
* Update my User account
* @param event
* @param context
* @param cb
*/
const update = async (event, context, cb) => {
const { firstName, lastName, email, password } = event.body;
const id = event.requestContext.authorizer.principalId;
// Create update query based on user input
let query = 'set firstName=:fn, lastName=:ln, email=:em, updatedAt=:ud';
const queryValues = {
':fn': sanitizer.trim(firstName),
':ln': sanitizer.trim(lastName),
':em': sanitizer.normalizeEmail(sanitizer.trim(email)),
':ud': new Date().getTime(),
};
// Password is optional, if provided, pass to query
if (password) {
query += ', password=:pw';
queryValues[':pw'] = await bcrypt.hash(password, 8);
}
const params = {
TableName,
Key: { id },
UpdateExpression: query,
ExpressionAttributeValues: queryValues,
ReturnValues: 'ALL_NEW',
}
return userByEmail(queryValues[':em']) // Check if the new email already exists
.then((foundUser) => {
if (foundUser && foundUser.email) {
// New email exists, and doesn't belong to the current user
if (foundUser.email === queryValues[':em'] && foundUser.id !== id) {
throw new Error('That email belongs to another user');
}
}
})
.then(() => DB.update(params).promise()) // Update the data to the DB
.then(user => cb(null, {message: 'Success - user updated', data: user }));
}
module.exports.update = middy(update)
.use(jsonBodyParser())
.use(validatorMiddleware({ inputSchema: requestSchema.update }))
.use(apiResponseMiddleware());