Skip to content

Commit c4c6e6d

Browse files
committed
feat: use express-validator in password endpoints
1 parent 289600d commit c4c6e6d

File tree

3 files changed

+67
-56
lines changed

3 files changed

+67
-56
lines changed

packages/password/package.json

+2-3
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,15 @@
2424
"dependencies": {
2525
"@accounts/two-factor": "^0.32.4",
2626
"bcryptjs": "2.4.3",
27-
"tslib": "2.6.2",
28-
"validator": "^13.11.0"
27+
"express-validator": "^7.0.1",
28+
"tslib": "2.6.2"
2929
},
3030
"devDependencies": {
3131
"@accounts/server": "^0.33.1",
3232
"@accounts/types": "^0.33.1",
3333
"@types/bcryptjs": "2.4.6",
3434
"@types/express": "^4.17.21",
3535
"@types/lodash.set": "4.3.9",
36-
"@types/validator": "^13",
3736
"graphql": "16.8.1",
3837
"graphql-modules": "3.0.0-alpha-20231106133212-0b04b56e",
3938
"lodash.set": "4.3.2",
+63-43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
import { type Injector } from 'graphql-modules';
22
import type { Request, Response, NextFunction } from 'express';
3-
import validator from 'validator';
43
import 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

615
function 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+
];

yarn.lock

+2-10
Original file line numberDiff line numberDiff line change
@@ -538,14 +538,13 @@ __metadata:
538538
"@types/bcryptjs": "npm:2.4.6"
539539
"@types/express": "npm:^4.17.21"
540540
"@types/lodash.set": "npm:4.3.9"
541-
"@types/validator": "npm:^13"
542541
bcryptjs: "npm:2.4.3"
542+
express-validator: "npm:^7.0.1"
543543
graphql: "npm:16.8.1"
544544
graphql-modules: "npm:3.0.0-alpha-20231106133212-0b04b56e"
545545
lodash.set: "npm:4.3.2"
546546
reflect-metadata: "npm:0.1.13"
547547
tslib: "npm:2.6.2"
548-
validator: "npm:^13.11.0"
549548
peerDependencies:
550549
"@accounts/server": ^0.32.0 || ^0.33.0
551550
graphql: ^16.0.0
@@ -8542,13 +8541,6 @@ __metadata:
85428541
languageName: node
85438542
linkType: hard
85448543

8545-
"@types/validator@npm:^13":
8546-
version: 13.11.6
8547-
resolution: "@types/validator@npm:13.11.6"
8548-
checksum: 3201902a8e5d4784d1c67f5a5a796d1500bae10fe5413ed75fdbdf5d6b5572952445f3482ffe64908531b20171d4c5cfe94934de3fd401781bb6cf9f95766b02
8549-
languageName: node
8550-
linkType: hard
8551-
85528544
"@types/webidl-conversions@npm:*":
85538545
version: 7.0.3
85548546
resolution: "@types/webidl-conversions@npm:7.0.3"
@@ -28921,7 +28913,7 @@ __metadata:
2892128913
languageName: node
2892228914
linkType: hard
2892328915

28924-
"validator@npm:^13.11.0, validator@npm:^13.9.0":
28916+
"validator@npm:^13.9.0":
2892528917
version: 13.11.0
2892628918
resolution: "validator@npm:13.11.0"
2892728919
checksum: 0107da3add5a4ebc6391dac103c55f6d8ed055bbcc29a4c9cbf89eacfc39ba102a5618c470bdc33c6487d30847771a892134a8c791f06ef0962dd4b7a60ae0f5

0 commit comments

Comments
 (0)