Skip to content

Commit

Permalink
Refactor, added Error exception assert
Browse files Browse the repository at this point in the history
Installed chai-as-promised (again)
  • Loading branch information
nuxy committed Apr 25, 2024
1 parent 335c407 commit f4de7a3
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 66 deletions.
22 changes: 14 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@lambda-lambda-lambda/router": "latest",
"@types/aws-lambda": "^8.10.111",
"chai": "^4.3.7",
"chai-as-promised": "^7.1.1",
"clone": "^2.1.2",
"cookie": "^0.5.0",
"eslint": "^7.32.0",
Expand Down
96 changes: 46 additions & 50 deletions plugins/GoogleRecaptchaHandler/src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,60 +2,56 @@

const https = require('https');

const {RouterError} = require('@lambda-lambda-lambda/router/src/router/Error');

/**
* Middleware to validate Google ReCAPTCHA invisible responses.
*
* @requires AppConfigPlugin
*/
module.exports = async (req, res, next) => {
return new Promise(function(resolve) {
const {google} = req.plugin('config');

const secretKey = google?.reCaptcha?.secretKey;

if (!secretKey) {
/* istanbul ignore next */
throw new Error('Missing Google API secret key');
}

if (req.method() === 'POST') {
const captchaResponse = req.param('g-recaptcha-response');

const options = {
hostname: 'www.google.com',
port: 443,
path: '/recaptcha/api/siteverify',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};

const httpRequest = https.request(options, hr => {

/* istanbul ignore next */
if (hr.statusCode === 200) {
hr.on('data', buffer => {
const {success} = JSON.parse(buffer.toString());

if (success !== true) {

// Return error response.
res.status(400).send('Bad Request');
}

resolve();
});
} else {
console.warn(`Google API error: ${hr.statusMessage}`);

// Return error response.
res.status(500).send('Internal Server Error');
}
});

httpRequest.write(`secret=${secretKey}&response=${captchaResponse}`);
httpRequest.end();
}
});
const {google} = req.plugin('config');

const secretKey = google?.reCaptcha?.secretKey;

if (!secretKey) {
throw new RouterError('Missing Google API secret key');
}

/* istanbul ignore next */
if (req.method() === 'POST') {
const captchaResponse = req.param('g-recaptcha-response');

const options = {
hostname: 'www.google.com',
port: 443,
path: '/recaptcha/api/siteverify',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};

const httpRequest = https.request(options, hr => {
if (hr.statusCode === 200) {
hr.on('data', buffer => {
const {success} = JSON.parse(buffer.toString());

if (success !== true) {

// Return error response.
res.status(400).send('Bad Request');
}
});
} else {
console.warn(`Google API error: ${hr.statusMessage}`);

// Return error response.
res.status(500).send('Internal Server Error');
}
});

httpRequest.write(`secret=${secretKey}&response=${captchaResponse}`);
httpRequest.end();
}
};
72 changes: 64 additions & 8 deletions plugins/GoogleRecaptchaHandler/test/unit.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
'use strict';

const event = require(`${PACKAGE_ROOT}/event.json`);
const chai = require('chai');
const event = require(`${PACKAGE_ROOT}/event.json`);
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const sinon = require('sinon');
const https = require('https');

chai.use(chaiAsPromised);

const expect = chai.expect;

// Load modules.
const Request = require('@lambda-lambda-lambda/router/src/router/Request.js');
const Response = require('@lambda-lambda-lambda/router/src/router/Response.js');
const Stack = require('@lambda-lambda-lambda/router/src/router/Stack.js');
const Utils = require('@lambda-lambda-lambda/router/src/router/Utils.js');
const middleware = require(PLUGIN_ROOT);
const {RouterError} = require('@lambda-lambda-lambda/router/src/router/Error');
const Request = require('@lambda-lambda-lambda/router/src/router/Request.js');
const Response = require('@lambda-lambda-lambda/router/src/router/Response.js');
const Stack = require('@lambda-lambda-lambda/router/src/router/Stack.js');
const Utils = require('@lambda-lambda-lambda/router/src/router/Utils.js');
const middleware = require(PLUGIN_ROOT);

afterEach(() => {
sinon.restore();
});

describe('GoogleReCaptchaHandler', function() {
describe('success', function() {
Expand All @@ -33,7 +43,7 @@ describe('GoogleReCaptchaHandler', function() {
Utils.setFuncName(dependency, 'middleware');
Utils.setFuncName(middleware, 'middleware');

const route = function(req, res) {
const route = async function(req, res, next) {
res.status(200).send();
};

Expand Down Expand Up @@ -69,4 +79,50 @@ describe('GoogleReCaptchaHandler', function() {
expect(result.body).to.be.undefined;
});
});

describe('error', function() {
const stack = new Stack();

const dependency = function(req, res, next) {
const config = {
google: {
reCaptcha: {
secretKey: ''
}
}
};

req.plugin('config', config);
next();
};

Utils.setFuncName(dependency, 'middleware');
Utils.setFuncName(middleware, 'middleware');

const route = async function(req, res, next) {
res.status(200).send();
};

Utils.setFuncName(route, 'route:index');

stack.middleware = [dependency, middleware];
stack.routes = route;

// Define form POST parameters.
event.Records[0].cf.request.method = 'POST';
event.Records[0].cf.request.uri = '/path/to/resource';
event.Records[0].cf.request.body = {
data: Buffer.from('g-recaptcha-response=GOOGLE_RESPONSE')
.toString('base64')
};

const req = new Request(event.Records[0].cf.request, {});
const res = new Response({});

it('should throw RouterError', function() {
const result = stack.exec(req, res);

return expect(result).to.be.rejectedWith(RouterError, /Missing Google API secret key/);
});
});
});

0 comments on commit f4de7a3

Please # to comment.