-
Notifications
You must be signed in to change notification settings - Fork 50
/
Copy pathauth.controller.ts
150 lines (141 loc) · 4.72 KB
/
auth.controller.ts
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
export {};
import { NextFunction, Request, Response, Router } from 'express';
const httpStatus = require('http-status');
import { User } from '../../api/models';
const RefreshToken = require('../models/refreshToken.model');
const moment = require('moment-timezone');
import { apiJson, randomString } from '../../api/utils/Utils';
import { sendEmail, welcomeEmail, forgotPasswordEmail, slackWebhook } from '../../api/utils/MsgUtils';
const { SEC_ADMIN_EMAIL, JWT_EXPIRATION_MINUTES, slackEnabled, emailEnabled } = require('../../config/vars');
/**
* Returns a formated object with tokens
* @private
*/
function generateTokenResponse(user: any, accessToken: string) {
const tokenType = 'Bearer';
const refreshToken = RefreshToken.generate(user).token;
const expiresIn = moment().add(JWT_EXPIRATION_MINUTES, 'minutes');
return {
tokenType,
accessToken,
refreshToken,
expiresIn
};
}
/**
* Returns jwt token if registration was successful
* @public
*/
exports.register = async (req: Request, res: Response, next: NextFunction) => {
try {
const user = await new User(req.body).save();
const userTransformed = user.transform();
const token = generateTokenResponse(user, user.token());
res.status(httpStatus.CREATED);
const data = { token, user: userTransformed };
if (slackEnabled) {
slackWebhook(`New User: ${user.email}`); // notify when new user registered
}
if (emailEnabled) {
// for testing: it can only email to "authorized recipients" in Mailgun Account Settings.
// sendEmail(welcomeEmail({ name: user.name, email: user.email }));
}
return apiJson({ req, res, data });
} catch (error) {
return next(User.checkDuplicateEmail(error));
}
};
/**
* Returns jwt token if valid username and password is provided
* @public
*/
exports.login = async (req: Request, res: Response, next: NextFunction) => {
try {
const { user, accessToken } = await User.findAndGenerateToken(req.body);
const { email } = user;
const token = generateTokenResponse(user, accessToken);
if (email === SEC_ADMIN_EMAIL) {
// setAdminToken(token); // remember admin token for checking later
} else {
const { ip, headers } = req;
slackWebhook(`User logged in: ${email} - IP: ${ip} - User Agent: ${headers['user-agent']}`);
}
const userTransformed = user.transform();
const data = { token, user: userTransformed };
return apiJson({ req, res, data });
} catch (error) {
return next(error);
}
};
/**
* Logout function: delete token from DB.
* @public
*/
exports.logout = async (req: Request, res: Response, next: NextFunction) => {
console.log('- logout');
try {
const { userId } = req.body;
await RefreshToken.findAndDeleteToken({ userId });
const data = { status: 'OK' };
return apiJson({ req, res, data });
} catch (error) {
return next(error);
}
};
/**
* login with an existing user or creates a new one if valid accessToken token
* Returns jwt token
* @public
*/
exports.oAuth = async (req: any, res: Response, next: NextFunction) => {
try {
const { user } = req;
const accessToken = user.token();
const token = generateTokenResponse(user, accessToken);
const userTransformed = user.transform();
return res.json({ token, user: userTransformed });
} catch (error) {
return next(error);
}
};
/**
* Returns a new jwt when given a valid refresh token
* @public
*/
exports.refresh = async (req: Request, res: Response, next: NextFunction) => {
try {
const { email, refreshToken } = req.body;
const refreshObject = await RefreshToken.findOneAndRemove({
userEmail: email,
token: refreshToken
});
const { user, accessToken } = await User.findAndGenerateToken({ email, refreshObject });
const response = generateTokenResponse(user, accessToken);
return res.json(response);
} catch (error) {
return next(error);
}
};
/**
* Send email to a registered user's email with a one-time temporary password
* @public
*/
exports.forgotPassword = async (req: Request, res: Response, next: NextFunction) => {
try {
const { email: reqEmail } = req.body;
const user = await User.findOne({ email: reqEmail });
if (!user) {
// RETURN A GENERIC ERROR - DON'T EXPOSE the real reason (user not found) for security.
return next({ message: 'Invalid request' });
}
// user found => generate temp password, then email it to user:
const { name, email } = user;
const tempPass = randomString(10, 'abcdefghijklmnopqrstuvwxyz0123456789');
user.tempPassword = tempPass;
await user.save();
sendEmail(forgotPasswordEmail({ name, email, tempPass }));
return apiJson({ req, res, data: { status: 'OK' } });
} catch (error) {
return next(error);
}
};