11import { type Injector } from 'graphql-modules' ;
22import type { Request , Response , NextFunction } from 'express' ;
3- import validator from 'validator' ;
43import AccountsPassword from '../accounts-password' ;
4+ import { body , matchedData , param , validationResult } from 'express-validator' ;
5+
6+ function matchOrThrow < T extends Record < string , any > = Record < string , any > > (
7+ ...args : Parameters < typeof matchedData >
8+ ) : T {
9+ if ( ! validationResult ( args [ 0 ] ) . isEmpty ( ) ) {
10+ throw new Error ( 'Validation error' ) ;
11+ }
12+ return matchedData ( ...args ) as T ;
13+ }
514
615function getHtml ( title : string , body : string ) {
716 return `
@@ -30,14 +39,11 @@ export const infosMiddleware = (req: Request, _res: Response, next: NextFunction
3039 next ( ) ;
3140} ;
3241
33- export const verifyEmail =
34- ( accountsPasswordOrInjector : Injector | AccountsPassword ) =>
42+ export const verifyEmail = ( accountsPasswordOrInjector : Injector | AccountsPassword ) => [
43+ param ( 'token' ) . isString ( ) . notEmpty ( ) ,
3544 async ( req : Request , res : Response ) => {
3645 try {
37- const { token } = req . params ;
38- if ( token == null ) {
39- throw new Error ( 'Token is missing' ) ;
40- }
46+ const { token } = matchOrThrow < { token : string } > ( req ) ;
4147 const accountsPassword =
4248 accountsPasswordOrInjector instanceof AccountsPassword
4349 ? accountsPasswordOrInjector
@@ -47,8 +53,8 @@ export const verifyEmail =
4753 getHtml (
4854 'Email successfully verified' ,
4955 `
50- <h3>The email address has been successfully verified.</h3>
51- `
56+ <h3>The email address has been successfully verified.</h3>
57+ `
5258 )
5359 ) ;
5460 } catch ( err : any ) {
@@ -57,24 +63,20 @@ export const verifyEmail =
5763 getHtml (
5864 'Email verification error' ,
5965 `
60- <h3>The email address couldn't be verified: ${ err . message ?? 'unknown error' } </h3>
61- `
66+ <h3>The email address couldn't be verified: ${ err . message ?? 'unknown error' } </h3>
67+ `
6268 )
6369 ) ;
6470 }
65- } ;
71+ } ,
72+ ] ;
6673
67- export const resetPassword =
68- ( accountsPasswordOrInjector : Injector | AccountsPassword ) =>
74+ export const resetPassword = ( accountsPasswordOrInjector : Injector | AccountsPassword ) => [
75+ body ( 'token' ) . isString ( ) . notEmpty ( ) ,
76+ body ( 'newPassword' ) . isString ( ) . notEmpty ( ) ,
6977 async ( req : Request , res : Response ) => {
7078 try {
71- const { token, newPassword } = req . body ;
72- if ( token == null ) {
73- throw new Error ( 'Token is missing' ) ;
74- }
75- if ( newPassword == null ) {
76- throw new Error ( 'New password is missing' ) ;
77- }
79+ const { token, newPassword } = matchOrThrow < { token : string ; newPassword : string } > ( req ) ;
7880 const accountsPassword =
7981 accountsPasswordOrInjector instanceof AccountsPassword
8082 ? accountsPasswordOrInjector
@@ -84,8 +86,44 @@ export const resetPassword =
8486 getHtml (
8587 'Password successfully changed' ,
8688 `
87- <h3>The password has been successfully changed.</h3>
88- `
89+ <h3>The password has been successfully changed.</h3>
90+ `
91+ )
92+ ) ;
93+ } catch ( err : any ) {
94+ //codeql[js/xss-through-exception]
95+ res . send (
96+ getHtml (
97+ 'Password reset error' ,
98+ `
99+ <h3>The password couldn't be changed: ${ err . message ?? 'unknown error' } </h3>
100+ `
101+ )
102+ ) ;
103+ }
104+ } ,
105+ ] ;
106+
107+ export const resetPasswordForm = [
108+ param ( 'token' ) . isString ( ) . notEmpty ( ) . escape ( ) ,
109+ ( req : Request , res : Response ) => {
110+ try {
111+ const { token } = matchOrThrow < { token : string } > ( req ) ;
112+ res . send (
113+ getHtml (
114+ 'Reset password' ,
115+ `
116+ <div class="container">
117+ <h1>Reset your password</h1>
118+ <form action="/resetPassword" method="POST">
119+ <input type="hidden" name="token" value=${ token } />
120+ <div class="form-group">
121+ <label for="newPassword">New password</label>
122+ <input type="text" class="form-control" id="newPassword" value="" placeholder="Enter your new password" name="newPassword">
123+ </div>
124+ <button type="submit" class="btn btn-primary">Submit</button>
125+ </form>
126+ `
89127 )
90128 ) ;
91129 } catch ( err : any ) {
@@ -99,23 +137,5 @@ export const resetPassword =
99137 )
100138 ) ;
101139 }
102- } ;
103-
104- export const resetPasswordForm = ( req : Request , res : Response ) : Response =>
105- res . send (
106- getHtml (
107- 'Reset password' ,
108- `
109- <div class="container">
110- <h1>Reset your password</h1>
111- <form action="/resetPassword" method="POST">
112- <input type="hidden" name="token" value=${ validator . escape ( req . params . token ) } />
113- <div class="form-group">
114- <label for="newPassword">New password</label>
115- <input type="text" class="form-control" id="newPassword" value="" placeholder="Enter your new password" name="newPassword">
116- </div>
117- <button type="submit" class="btn btn-primary">Submit</button>
118- </form>
119- `
120- )
121- ) ;
140+ } ,
141+ ] ;
0 commit comments