@@ -36,10 +36,11 @@ const { User } = models;
3636/**
3737 * Check existence of a user based on email
3838 */
39- export const exists = async ( req , res ) => {
40- const email = req . query . email . toLowerCase ( ) ;
39+ export const exists = async ( req : express . Request , res : express . Response ) => {
40+ const email = ( req . query . email as string ) . toLowerCase ( ) ;
4141 if ( ! isValidEmail ( email ) ) {
42- return res . send ( { exists : false } ) ;
42+ res . send ( { exists : false } ) ;
43+ return ;
4344 } else {
4445 const rateLimit = new RateLimit (
4546 `user_email_search_ip_${ req . ip } ` ,
@@ -55,7 +56,8 @@ export const exists = async (req, res) => {
5556 attributes : [ 'id' ] ,
5657 where : { email } ,
5758 } ) ;
58- return res . send ( { exists : Boolean ( user ) } ) ;
59+ res . send ( { exists : Boolean ( user ) } ) ;
60+ return ;
5961 }
6062} ;
6163
@@ -66,7 +68,7 @@ export const exists = async (req, res) => {
6668 * create a new account. In the future once signin.js is fully deprecated (replaced by signinV2.js)
6769 * this function should be refactored to remove createProfile.
6870 */
69- export const signin = async ( req , res , next ) => {
71+ export const signin = async ( req : express . Request , res : express . Response , next : express . NextFunction ) => {
7072 const { redirect, websiteUrl, sendLink, resetPassword, createProfile = true } = req . body ;
7173 try {
7274 const rateLimit = new RateLimit (
@@ -76,40 +78,45 @@ export const signin = async (req, res, next) => {
7678 true ,
7779 ) ;
7880 if ( ! ( await rateLimit . registerCall ( ) ) ) {
79- return res . status ( 403 ) . send ( {
81+ res . status ( 403 ) . send ( {
8082 error : { message : 'Rate limit exceeded' } ,
8183 } ) ;
84+ return ;
8285 }
8386 let user = await models . User . findOne ( { where : { email : req . body . user . email . toLowerCase ( ) } } ) ;
8487 if ( ! user && ! createProfile ) {
85- return res . status ( 400 ) . send ( {
88+ res . status ( 400 ) . send ( {
8689 errorCode : 'EMAIL_DOES_NOT_EXIST' ,
8790 message : 'Email does not exist' ,
8891 } ) ;
92+ return ;
8993 } else if ( ! user && createProfile ) {
9094 user = await models . User . createUserWithCollective ( req . body . user ) ;
9195 } else if ( ! user . CollectiveId || user . data ?. requiresVerification === true ) {
92- return res . status ( 403 ) . send ( {
96+ res . status ( 403 ) . send ( {
9397 errorCode : 'EMAIL_AWAITING_VERIFICATION' ,
9498 message : 'Email awaiting verification' ,
9599 } ) ;
100+ return ;
96101 }
97102
98103 // If password set and not passed, challenge user with password
99104 if ( user . passwordHash && ! sendLink && ! resetPassword ) {
100105 if ( ! req . body . user . password ) {
101- return res . status ( 403 ) . send ( {
106+ res . status ( 403 ) . send ( {
102107 errorCode : 'PASSWORD_REQUIRED' ,
103108 message : 'Password requested to complete sign in.' ,
104109 } ) ;
110+ return ;
105111 }
106112 const validPassword = await bcrypt . compare ( req . body . user . password , user . passwordHash ) ;
107113 if ( ! validPassword ) {
108114 // Would be great to be consistent in the way we send errors
109115 // This is what works best with Frontend today
110- return res . status ( 401 ) . send ( {
116+ res . status ( 401 ) . send ( {
111117 error : { errorCode : 'PASSWORD_INVALID' , message : 'Invalid password' } ,
112118 } ) ;
119+ return ;
113120 }
114121
115122 const twoFactorAuthenticationEnabled = parseToBoolean ( config . twoFactorAuthentication . enabled ) ;
@@ -131,12 +138,14 @@ export const signin = async (req, res, next) => {
131138 } ,
132139 auth . TOKEN_EXPIRATION_2FA ,
133140 ) ;
134- return res . send ( { token } ) ;
141+ res . send ( { token } ) ;
142+ return ;
135143 } else {
136144 // Context: this is token generation when using a password and no 2FA
137145 const token = await user . generateSessionToken ( { createActivity : true , updateLastLoginAt : true , req } ) ;
138146 auth . setAuthCookie ( res , token ) ;
139- return res . send ( { token } ) ;
147+ res . send ( { token } ) ;
148+ return ;
140149 }
141150 }
142151
@@ -154,9 +163,10 @@ export const signin = async (req, res, next) => {
154163 ) ;
155164 } catch ( e ) {
156165 reportErrorToSentry ( e , { user } ) ;
157- return res . status ( 500 ) . send ( {
166+ res . status ( 500 ) . send ( {
158167 error : { message : 'Error sending reset password email' } ,
159168 } ) ;
169+ return ;
160170 }
161171 } else {
162172 const collective = await user . getCollective ( ) ;
@@ -175,17 +185,18 @@ export const signin = async (req, res, next) => {
175185 ) ;
176186 } catch ( e ) {
177187 reportErrorToSentry ( e , { user } ) ;
178- return res . status ( 500 ) . send ( {
188+ res . status ( 500 ) . send ( {
179189 error : { message : 'Error sending login email' } ,
180190 } ) ;
191+ return ;
181192 }
182193
183194 // For e2e testing, we enable testuser+(admin|member)@opencollective.com to automatically receive the login link
184195 if ( config . env !== 'production' && user . email . match ( / .* t e s t .* @ o p e n c o l l e c t i v e .c o m $ / ) ) {
185- return res . send ( { success : true , redirect : loginLink } ) ;
196+ res . send ( { success : true , redirect : loginLink } ) ;
197+ return ;
186198 }
187199 }
188-
189200 res . send ( { success : true } ) ;
190201 } catch ( e ) {
191202 next ( e ) ;
@@ -529,25 +540,27 @@ export async function verifyEmail(req: express.Request, res: express.Response) {
529540 *
530541 * B) If no 2FA, we send back a "session" token
531542 */
532- export const exchangeLoginToken = async ( req , res , next ) => {
543+ export const exchangeLoginToken = async ( req : express . Request , res : express . Response , next : express . NextFunction ) => {
533544 const rateLimit = new RateLimit (
534545 `user_exchange_login_token_ip_${ req . ip } ` ,
535546 config . limits . userExchangeLoginTokenPerHourPerIp ,
536547 ONE_HOUR_IN_SECONDS ,
537548 true ,
538549 ) ;
539550 if ( ! ( await rateLimit . registerCall ( ) ) ) {
540- return res . status ( 403 ) . send ( {
551+ res . status ( 403 ) . send ( {
541552 error : { message : 'Rate limit exceeded' } ,
542553 } ) ;
554+ return ;
543555 }
544556
545557 // This is already checked in checkJwtScope but lets' make it clear
546558 if ( req . jwtPayload ?. scope !== 'login' ) {
547559 const errorMessage = `Cannot use this token on this route (scope: ${
548560 req . jwtPayload ?. scope || 'session'
549561 } , expected: login)`;
550- return next ( new BadRequest ( errorMessage ) ) ;
562+ next ( new BadRequest ( errorMessage ) ) ;
563+ return ;
551564 }
552565
553566 // If a guest signs in, it's safe to directly confirm its account
@@ -591,33 +604,37 @@ export const exchangeLoginToken = async (req, res, next) => {
591604/**
592605 * Exchange a session JWT against a fresh one with extended expiration
593606 */
594- export const refreshToken = async ( req , res , next ) => {
607+ export const refreshToken = async ( req : express . Request , res : express . Response , next : express . NextFunction ) => {
595608 const rateLimit = new RateLimit (
596609 `user_refresh_token_ip_${ req . ip } ` ,
597610 config . limits . userRefreshTokenPerHourPerIp ,
598611 ONE_HOUR_IN_SECONDS ,
599612 true ,
600613 ) ;
601614 if ( ! ( await rateLimit . registerCall ( ) ) ) {
602- return res . status ( 403 ) . send ( {
615+ res . status ( 403 ) . send ( {
603616 error : { message : 'Rate limit exceeded' } ,
604617 } ) ;
618+ return ;
605619 }
606620
607621 if ( req . personalToken ) {
608622 const errorMessage = `Cannot use this token on this route (personal token)` ;
609- return next ( new BadRequest ( errorMessage ) ) ;
623+ next ( new BadRequest ( errorMessage ) ) ;
624+ return ;
610625 }
611626
612627 if ( req . jwtPayload ?. scope && req . jwtPayload ?. scope !== 'session' ) {
613628 const errorMessage = `Cannot use this token on this route (scope: ${ req . jwtPayload ?. scope } , expected: session)` ;
614- return next ( new BadRequest ( errorMessage ) ) ;
629+ next ( new BadRequest ( errorMessage ) ) ;
630+ return ;
615631 }
616632
617633 // TODO: not necessary once all oAuth tokens have the scope "oauth"
618634 if ( req . jwtPayload ?. access_token ) {
619635 const errorMessage = `Cannot use this token on this route (oAuth access_token)` ;
620- return next ( new BadRequest ( errorMessage ) ) ;
636+ next ( new BadRequest ( errorMessage ) ) ;
637+ return ;
621638 }
622639
623640 // Context: this is token generation when extending a session
@@ -634,12 +651,17 @@ export const refreshToken = async (req, res, next) => {
634651/**
635652 * Verify the 2FA code or recovery code the user has entered when logging in and send back another JWT.
636653 */
637- export const twoFactorAuthAndUpdateToken = async ( req , res , next ) => {
654+ export const twoFactorAuthAndUpdateToken = async (
655+ req : express . Request ,
656+ res : express . Response ,
657+ next : express . NextFunction ,
658+ ) => {
638659 if ( req . jwtPayload ?. scope !== 'twofactorauth' ) {
639660 const errorMessage = `Cannot use this token on this route (scope: ${
640661 req . jwtPayload ?. scope || 'session'
641662 } , expected: twofactorauth)`;
642- return next ( new BadRequest ( errorMessage ) ) ;
663+ next ( new BadRequest ( errorMessage ) ) ;
664+ return ;
643665 }
644666
645667 const { twoFactorAuthenticatorCode, twoFactorAuthenticationRecoveryCode, twoFactorAuthenticationType } = req . body ;
@@ -654,7 +676,8 @@ export const twoFactorAuthAndUpdateToken = async (req, res, next) => {
654676 } ;
655677
656678 if ( await rateLimit . hasReachedLimit ( ) ) {
657- return next ( new TooManyRequests ( 'Too many attempts. Please try again in an hour' ) ) ;
679+ next ( new TooManyRequests ( 'Too many attempts. Please try again in an hour' ) ) ;
680+ return ;
658681 }
659682
660683 const user = await User . findByPk ( userId ) ;
@@ -669,7 +692,8 @@ export const twoFactorAuthAndUpdateToken = async (req, res, next) => {
669692 twoFactorAuthenticationType ?? ( twoFactorAuthenticatorCode ? TwoFactorMethod . TOTP : TwoFactorMethod . RECOVERY_CODE ) ;
670693
671694 if ( ! code ) {
672- return fail ( new BadRequest ( 'This endpoint requires you to provide a 2FA code or a recovery code' ) ) ;
695+ fail ( new BadRequest ( 'This endpoint requires you to provide a 2FA code or a recovery code' ) ) ;
696+ return ;
673697 }
674698
675699 try {
@@ -682,7 +706,8 @@ export const twoFactorAuthAndUpdateToken = async (req, res, next) => {
682706 req ,
683707 ) ;
684708 } catch {
685- return fail ( new Unauthorized ( 'Two-factor authentication code failed. Please try again' ) ) ;
709+ fail ( new Unauthorized ( 'Two-factor authentication code failed. Please try again' ) ) ;
710+ return ;
686711 }
687712
688713 // Context: this is token generation after signin and valid 2FA authentication
0 commit comments