Skip to content

Commit f4de7a3

Browse files
committed
Refactor, added Error exception assert
Installed chai-as-promised (again)
1 parent 335c407 commit f4de7a3

File tree

4 files changed

+125
-66
lines changed

4 files changed

+125
-66
lines changed

package-lock.json

+14-8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
"@lambda-lambda-lambda/router": "latest",
3131
"@types/aws-lambda": "^8.10.111",
3232
"chai": "^4.3.7",
33+
"chai-as-promised": "^7.1.1",
3334
"clone": "^2.1.2",
3435
"cookie": "^0.5.0",
3536
"eslint": "^7.32.0",

plugins/GoogleRecaptchaHandler/src/plugin.js

+46-50
Original file line numberDiff line numberDiff line change
@@ -2,60 +2,56 @@
22

33
const https = require('https');
44

5+
const {RouterError} = require('@lambda-lambda-lambda/router/src/router/Error');
6+
57
/**
68
* Middleware to validate Google ReCAPTCHA invisible responses.
79
*
810
* @requires AppConfigPlugin
911
*/
1012
module.exports = async (req, res, next) => {
11-
return new Promise(function(resolve) {
12-
const {google} = req.plugin('config');
13-
14-
const secretKey = google?.reCaptcha?.secretKey;
15-
16-
if (!secretKey) {
17-
/* istanbul ignore next */
18-
throw new Error('Missing Google API secret key');
19-
}
20-
21-
if (req.method() === 'POST') {
22-
const captchaResponse = req.param('g-recaptcha-response');
23-
24-
const options = {
25-
hostname: 'www.google.com',
26-
port: 443,
27-
path: '/recaptcha/api/siteverify',
28-
method: 'POST',
29-
headers: {
30-
'Content-Type': 'application/x-www-form-urlencoded'
31-
}
32-
};
33-
34-
const httpRequest = https.request(options, hr => {
35-
36-
/* istanbul ignore next */
37-
if (hr.statusCode === 200) {
38-
hr.on('data', buffer => {
39-
const {success} = JSON.parse(buffer.toString());
40-
41-
if (success !== true) {
42-
43-
// Return error response.
44-
res.status(400).send('Bad Request');
45-
}
46-
47-
resolve();
48-
});
49-
} else {
50-
console.warn(`Google API error: ${hr.statusMessage}`);
51-
52-
// Return error response.
53-
res.status(500).send('Internal Server Error');
54-
}
55-
});
56-
57-
httpRequest.write(`secret=${secretKey}&response=${captchaResponse}`);
58-
httpRequest.end();
59-
}
60-
});
13+
const {google} = req.plugin('config');
14+
15+
const secretKey = google?.reCaptcha?.secretKey;
16+
17+
if (!secretKey) {
18+
throw new RouterError('Missing Google API secret key');
19+
}
20+
21+
/* istanbul ignore next */
22+
if (req.method() === 'POST') {
23+
const captchaResponse = req.param('g-recaptcha-response');
24+
25+
const options = {
26+
hostname: 'www.google.com',
27+
port: 443,
28+
path: '/recaptcha/api/siteverify',
29+
method: 'POST',
30+
headers: {
31+
'Content-Type': 'application/x-www-form-urlencoded'
32+
}
33+
};
34+
35+
const httpRequest = https.request(options, hr => {
36+
if (hr.statusCode === 200) {
37+
hr.on('data', buffer => {
38+
const {success} = JSON.parse(buffer.toString());
39+
40+
if (success !== true) {
41+
42+
// Return error response.
43+
res.status(400).send('Bad Request');
44+
}
45+
});
46+
} else {
47+
console.warn(`Google API error: ${hr.statusMessage}`);
48+
49+
// Return error response.
50+
res.status(500).send('Internal Server Error');
51+
}
52+
});
53+
54+
httpRequest.write(`secret=${secretKey}&response=${captchaResponse}`);
55+
httpRequest.end();
56+
}
6157
};

plugins/GoogleRecaptchaHandler/test/unit.js

+64-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
'use strict';
22

3-
const event = require(`${PACKAGE_ROOT}/event.json`);
4-
const chai = require('chai');
3+
const event = require(`${PACKAGE_ROOT}/event.json`);
4+
const chai = require('chai');
5+
const chaiAsPromised = require('chai-as-promised');
6+
const sinon = require('sinon');
7+
const https = require('https');
8+
9+
chai.use(chaiAsPromised);
510

611
const expect = chai.expect;
712

813
// Load modules.
9-
const Request = require('@lambda-lambda-lambda/router/src/router/Request.js');
10-
const Response = require('@lambda-lambda-lambda/router/src/router/Response.js');
11-
const Stack = require('@lambda-lambda-lambda/router/src/router/Stack.js');
12-
const Utils = require('@lambda-lambda-lambda/router/src/router/Utils.js');
13-
const middleware = require(PLUGIN_ROOT);
14+
const {RouterError} = require('@lambda-lambda-lambda/router/src/router/Error');
15+
const Request = require('@lambda-lambda-lambda/router/src/router/Request.js');
16+
const Response = require('@lambda-lambda-lambda/router/src/router/Response.js');
17+
const Stack = require('@lambda-lambda-lambda/router/src/router/Stack.js');
18+
const Utils = require('@lambda-lambda-lambda/router/src/router/Utils.js');
19+
const middleware = require(PLUGIN_ROOT);
20+
21+
afterEach(() => {
22+
sinon.restore();
23+
});
1424

1525
describe('GoogleReCaptchaHandler', function() {
1626
describe('success', function() {
@@ -33,7 +43,7 @@ describe('GoogleReCaptchaHandler', function() {
3343
Utils.setFuncName(dependency, 'middleware');
3444
Utils.setFuncName(middleware, 'middleware');
3545

36-
const route = function(req, res) {
46+
const route = async function(req, res, next) {
3747
res.status(200).send();
3848
};
3949

@@ -69,4 +79,50 @@ describe('GoogleReCaptchaHandler', function() {
6979
expect(result.body).to.be.undefined;
7080
});
7181
});
82+
83+
describe('error', function() {
84+
const stack = new Stack();
85+
86+
const dependency = function(req, res, next) {
87+
const config = {
88+
google: {
89+
reCaptcha: {
90+
secretKey: ''
91+
}
92+
}
93+
};
94+
95+
req.plugin('config', config);
96+
next();
97+
};
98+
99+
Utils.setFuncName(dependency, 'middleware');
100+
Utils.setFuncName(middleware, 'middleware');
101+
102+
const route = async function(req, res, next) {
103+
res.status(200).send();
104+
};
105+
106+
Utils.setFuncName(route, 'route:index');
107+
108+
stack.middleware = [dependency, middleware];
109+
stack.routes = route;
110+
111+
// Define form POST parameters.
112+
event.Records[0].cf.request.method = 'POST';
113+
event.Records[0].cf.request.uri = '/path/to/resource';
114+
event.Records[0].cf.request.body = {
115+
data: Buffer.from('g-recaptcha-response=GOOGLE_RESPONSE')
116+
.toString('base64')
117+
};
118+
119+
const req = new Request(event.Records[0].cf.request, {});
120+
const res = new Response({});
121+
122+
it('should throw RouterError', function() {
123+
const result = stack.exec(req, res);
124+
125+
return expect(result).to.be.rejectedWith(RouterError, /Missing Google API secret key/);
126+
});
127+
});
72128
});

0 commit comments

Comments
 (0)