11'use strict' ;
2- const bcrypt = require ( 'cryptjs ' ) ;
2+ const bcrypt = require ( 'bcryptjs ' ) ;
33const express = require ( 'express' ) ;
44const crypto = require ( 'crypto' ) ;
55const router = express . Router ( ) ;
@@ -14,24 +14,21 @@ const { verifyCaptcha } = require('../util/captcha');
1414const {
1515 checkIfTokenSent,
1616 checkIfTokenValid,
17- decodeToken,
17+ decodeToken
1818} = require ( '../util/token-functions' ) ;
1919const jwt = require ( 'jsonwebtoken' ) ;
20- const { OK , BAD_REQUEST , FORBIDDEN , UNAUTHORIZED , NOT_FOUND , CONFLICT } =
21- require ( '../../util/constants' ) . STATUS_CODES ;
22- const membershipState = require ( '../../util/constants' ) . MEMBERSHIP_STATE ;
23- const PASSWORD_RESET_EXPIRATION =
24- require ( '../../util/constants' ) . PASSWORD_RESET_EXPIRATION ;
25- const {
26- sendVerificationEmail,
27- sendPasswordReset,
28- } = require ( '../util/emailHelpers' ) ;
2920const {
30- userWithEmailExists,
31- checkIfPageCountResets,
32- findPasswordReset,
33- } = require ( '../util/userHelpers' ) ;
34-
21+ OK ,
22+ BAD_REQUEST ,
23+ FORBIDDEN ,
24+ UNAUTHORIZED ,
25+ NOT_FOUND ,
26+ CONFLICT
27+ } = require ( '../../util/constants' ) . STATUS_CODES ;
28+ const membershipState = require ( '../../util/constants' ) . MEMBERSHIP_STATE ;
29+ const PASSWORD_RESET_EXPIRATION = require ( '../../util/constants' ) . PASSWORD_RESET_EXPIRATION ;
30+ const { sendVerificationEmail, sendPasswordReset } = require ( '../util/emailHelpers' ) ;
31+ const { userWithEmailExists, checkIfPageCountResets, findPasswordReset } = require ( '../util/userHelpers' ) ;
3532
3633const AuditLogActions = require ( '../util/auditLogActions.js' ) ;
3734const AuditLog = require ( '../models/AuditLog.js' ) ;
@@ -41,13 +38,13 @@ router.post('/register', async (req, res) => {
4138 const registrationStatus = await registerUser ( req . body ) ;
4239 if ( registrationStatus . userSaved ) {
4340 const name = req . body . firstName + ' ' + req . body . lastName ;
44- const user = await User . findOne ( { email : req . body . email } ) ;
41+ const user = await User . findOne ( { email : req . body . email } ) ;
4542
4643 if ( user ) {
4744 AuditLog . create ( {
4845 userId : user . _id ,
4946 action : AuditLogActions . SIGN_UP ,
50- details : { email : req . body . email } ,
47+ details : { email : req . body . email }
5148 } ) . catch ( logger . error ) ;
5249 }
5350
@@ -56,7 +53,7 @@ router.post('/register', async (req, res) => {
5653 }
5754 if ( registrationStatus . status === 'BAD_REQUEST' ) {
5855 return res . status ( BAD_REQUEST ) . send ( {
59- message : registrationStatus . message ,
56+ message : registrationStatus . message
6057 } ) ;
6158 }
6259 return res . status ( CONFLICT ) . send ( { message : registrationStatus . message } ) ;
@@ -72,7 +69,7 @@ router.post('/resendVerificationEmail', async (req, res) => {
7269 if ( ! maybeUser ) {
7370 return res . sendStatus ( NOT_FOUND ) ;
7471 }
75- let name = maybeUser . firstName + ' ' + maybeUser . lastName ;
72+ let name = maybeUser . firstName + ' ' + maybeUser . lastName ;
7673 sendVerificationEmail ( name , req . body . email ) ;
7774 res . sendStatus ( OK ) ;
7875} ) ;
@@ -83,15 +80,15 @@ router.post('/sendPasswordReset', async (req, res) => {
8380
8481 if ( invalidEmail ) {
8582 return res . status ( BAD_REQUEST ) . send ( {
86- message : 'Invalid email.' ,
83+ message : 'Invalid email.'
8784 } ) ;
8885 }
8986
9087 if ( process . env . NODE_ENV === 'production' ) {
9188 const captchaValid = await verifyCaptcha ( req . body . captchaToken ) ;
9289 if ( ! captchaValid . success ) {
9390 return res . status ( BAD_REQUEST ) . send ( {
94- message : 'Captcha verification failed.' ,
91+ message : 'Captcha verification failed.'
9592 } ) ;
9693 }
9794 }
@@ -104,22 +101,20 @@ router.post('/sendPasswordReset', async (req, res) => {
104101 return res . sendStatus ( OK ) ;
105102 }
106103 if (
107- [ membershipState . PENDING , membershipState . BANNED ] . includes (
108- result . accessLevel
109- )
104+ [
105+ membershipState . PENDING ,
106+ membershipState . BANNED ,
107+ ] . includes ( result . accessLevel )
110108 ) {
111109 return res . status ( UNAUTHORIZED ) . send ( {
112- message : 'Cannot reset password, account is in a bad state!' ,
110+ message : 'Cannot reset password, account is in a bad state!'
113111 } ) ;
114112 }
115113
116114 const buffer = crypto . randomBytes ( 12 ) ;
117115 let id = buffer . toString ( 'base64' ) ;
118116
119- const resetToken = id
120- . replace ( / \+ / g, '-' )
121- . replace ( / \/ / g, '_' )
122- . replace ( / = + $ / , '' ) ;
117+ const resetToken = id . replace ( / \+ / g, '-' ) . replace ( / \/ / g, '_' ) . replace ( / = + $ / , '' ) ;
123118 try {
124119 const passwordReset = new PasswordReset ( {
125120 resetToken,
@@ -134,7 +129,6 @@ router.post('/sendPasswordReset', async (req, res) => {
134129 } ) ;
135130} ) ;
136131
137-
138132// User Login
139133router . post ( '/login' , function ( req , res ) {
140134 if ( ! req . body . email || ! req . body . password ) {
@@ -143,7 +137,7 @@ router.post('/login', function(req, res) {
143137
144138 User . findOne (
145139 {
146- email : req . body . email . toLowerCase ( ) ,
140+ email : req . body . email . toLowerCase ( )
147141 } ,
148142 function ( error , user ) {
149143 if ( error ) {
@@ -152,75 +146,83 @@ router.post('/login', function(req, res) {
152146 }
153147
154148 if ( ! user ) {
155- return res . status ( UNAUTHORIZED ) . send ( {
156- message : 'Username or password does not match our records.' ,
149+ res
150+ . status ( UNAUTHORIZED )
151+ . send ( {
152+ message : 'Username or password does not match our records.'
153+ } ) ;
154+ } else {
155+ // Check if password matches database
156+ user . comparePassword ( req . body . password , function ( error , isMatch ) {
157+ if ( isMatch && ! error ) {
158+ if ( user . accessLevel === membershipState . BANNED ) {
159+ return res
160+ . status ( UNAUTHORIZED )
161+ . send ( {
162+ message : 'The account with email ' +
163+ req . body . email +
164+ ' is banned' ,
165+ } ) ;
166+ }
167+
168+ // Check if the user's email has been verified
169+ if ( ! user . emailVerified ) {
170+ return res
171+ . status ( UNAUTHORIZED )
172+ . send ( { message : `The email ${ req . body . email } has not been verified` } ) ;
173+ }
174+
175+ // If the username and password matches the database, assign and
176+ // return a jwt token
177+ const jwtOptions = {
178+ expiresIn : '2h'
179+ } ;
180+
181+ // check here to see if we should reset the pagecount. If so, do it
182+ if ( checkIfPageCountResets ( user . lastLogin ) ) {
183+ user . pagesPrinted = 0 ;
184+ }
185+
186+ // Include fields from the User model that should
187+ // be passed to the JSON Web Token (JWT)
188+ const userToBeSigned = {
189+ firstName : user . firstName ,
190+ lastName : user . lastName ,
191+ email : user . email ,
192+ accessLevel : user . accessLevel ,
193+ pagesPrinted : user . pagesPrinted ,
194+ _id : user . _id
195+ } ;
196+ user
197+ . save ( )
198+ . then ( ( ) => {
199+ const token = jwt . sign (
200+ userToBeSigned , config . secretKey , jwtOptions
201+ ) ;
202+ // Create audit log on successful sign-in
203+ AuditLog . create ( {
204+ userId : user . _id ,
205+ action : AuditLogActions . LOG_IN ,
206+ details : { email : user . email }
207+ } ) . catch ( logger . error ) ;
208+
209+ res . json ( { token : 'JWT ' + token } ) ;
210+ } )
211+ . catch ( ( error ) => {
212+ logger . error ( 'unable to login user' , error ) ;
213+ res . sendStatus ( SERVER_ERROR ) ;
214+ } ) ;
215+ } else {
216+ res . status ( UNAUTHORIZED ) . send ( {
217+ message : 'Username or password does not match our records.'
218+ } ) ;
219+ }
157220 } ) ;
158221 }
159-
160- user . comparePassword ( req . body . password , function ( error , isMatch ) {
161- if ( error || ! isMatch ) {
162- return res . status ( UNAUTHORIZED ) . send ( {
163- message : 'Username or password does not match our records.' ,
164- } ) ;
165- }
166- if ( user . accessLevel === membershipState . BANNED ) {
167- return res . status ( UNAUTHORIZED ) . send ( {
168- message : 'The account with email ' + req . body . email + ' is banned' ,
169- } ) ;
170- }
171-
172- if ( ! user . emailVerified ) {
173- return res . status ( UNAUTHORIZED ) . send ( {
174- message : `The email ${ req . body . email } has not been verified` ,
175- } ) ;
176- }
177-
178- const jwtOptions = {
179- expiresIn : '2h' ,
180- } ;
181-
182- if ( checkIfPageCountResets ( user . lastLogin ) ) {
183- user . pagesPrinted = 0 ;
184- }
185-
186- user . lastLogin = new Date ( ) ;
187-
188- const userToBeSigned = {
189- firstName : user . firstName ,
190- lastName : user . lastName ,
191- email : user . email ,
192- accessLevel : user . accessLevel ,
193- pagesPrinted : user . pagesPrinted ,
194- _id : user . _id ,
195- } ;
196-
197- user
198- . save ( )
199- . then ( ( ) => {
200- const token = jwt . sign (
201- userToBeSigned ,
202- config . secretKey ,
203- jwtOptions
204- ) ;
205- AuditLog . create ( {
206- userId : user . _id ,
207- action : AuditLogActions . LOG_IN ,
208- details : { email : user . email } ,
209- } ) . catch ( logger . error ) ;
210-
211- res . json ( { token : 'JWT' + token } ) ;
212- } )
213- . catch ( ( error ) => {
214- logger . error ( 'unable to login user' , error ) ;
215- res . sendStatus ( SERVER_ERROR ) ;
216- } ) ;
217- } ) ;
218222 }
219223 ) ;
220224} ) ;
221225
222-
223-
224226// Verifies the users session if they have an active jwtToken.
225227// Used on the inital load of root '/'
226228// Returns the name and accesslevel of the user w/ the given access token
@@ -249,6 +251,7 @@ router.post('/generateHashedId', async (req, res) => {
249251 // bcrypts library
250252 bcrypt . genSalt ( 10 , function ( error , salt ) {
251253 if ( error ) {
254+ // reject('Bcrypt failed')
252255 res . sendStatus ( BAD_REQUEST ) ;
253256 }
254257
@@ -272,39 +275,35 @@ router.post('/validateVerificationEmail', async (req, res) => {
272275 res . sendStatus ( NOT_FOUND ) ;
273276 }
274277
275- bcrypt . compare (
276- String ( result . _id ) ,
277- req . body . hashedId ,
278- async function ( error , isMatch ) {
279- if ( error ) {
280- res . sendStatus ( BAD_REQUEST ) ;
281- }
282- if ( isMatch ) {
283- result . emailVerified = true ;
284- result . accessLevel = membershipState . NON_MEMBER ;
285- await result
286- . save ( )
287- . then ( ( _ ) => {
288- res . sendStatus ( OK ) ;
289- } )
290- . catch ( ( err ) => {
291- res . sendStatus ( BAD_REQUEST ) ;
292- } ) ;
293- } else {
294- res . sendStatus ( BAD_REQUEST ) ;
295- }
278+ bcrypt . compare ( String ( result . _id ) , req . body . hashedId , async function (
279+ error ,
280+ isMatch ) {
281+ if ( error ) {
282+ res . sendStatus ( BAD_REQUEST ) ;
296283 }
297- ) ;
284+ if ( isMatch ) {
285+ result . emailVerified = true ;
286+ result . accessLevel = membershipState . NON_MEMBER ;
287+ await result
288+ . save ( )
289+ . then ( _ => {
290+ res . sendStatus ( OK ) ;
291+ } )
292+ . catch ( err => {
293+ res . sendStatus ( BAD_REQUEST ) ;
294+ } ) ;
295+ } else {
296+ res . sendStatus ( BAD_REQUEST ) ;
297+ }
298+ } ) ;
298299 } ) ;
299300} ) ;
300301
301302router . post ( '/validatePasswordReset' , async ( req , res ) => {
302303 try {
303304 const passwordReset = await findPasswordReset ( req . body . resetToken ) ;
304305 if ( ! passwordReset ) {
305- return res
306- . status ( NOT_FOUND )
307- . send ( { message : 'Invalid or expired reset tokennn.' } ) ;
306+ return res . status ( NOT_FOUND ) . send ( { message : 'Invalid or expired reset token.' } ) ;
308307 }
309308 res . sendStatus ( OK ) ;
310309 } catch ( error ) {
@@ -317,7 +316,7 @@ router.post('/resetPassword', async (req, res) => {
317316 const testPassword = testPasswordStrength ( req . body . password ) ;
318317 if ( ! testPassword . success ) {
319318 return res . status ( BAD_REQUEST ) . send ( {
320- message : 'Password does not meet requirements.' ,
319+ message : 'Password does not meet requirements.'
321320 } ) ;
322321 }
323322
@@ -354,4 +353,3 @@ router.post('/resetPassword', async (req, res) => {
354353} ) ;
355354
356355module . exports = router ;
357-
0 commit comments