Skip to content

Commit

Permalink
Updated google recaptcha module options. Updated readme.
Browse files Browse the repository at this point in the history
  • Loading branch information
chvarkov committed Jan 15, 2021
1 parent fd030eb commit 26306e0
Show file tree
Hide file tree
Showing 8 changed files with 49 additions and 40 deletions.
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@

The [NestJS](https://docs.nestjs.com/) module to protect your endpoints via [google recaptcha](https://www.google.com/recaptcha/about/).

- [Installation](#Installation)
- [Configuration](#Configuration)
- [Usage](#Usage)
- [Error handling](#ErrorHandling)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [Error handling](#error-handling)

Usage example [here](https://github.com/chvarkov/google-recaptcha-example)


### Installation <a name="Installation"></a>
## Installation

```
$ npm i @nestlab/google-recaptcha
```

### Configuration <a name="Configuration"></a>
## Configuration

```typescript
@Module({
Expand All @@ -25,7 +25,7 @@ $ npm i @nestlab/google-recaptcha
secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
response: req => req.headers.recaptcha,
skipIf: process.env.NODE_ENV !== 'production',
useRecaptchaNet: false,
network: GoogleRecaptchaNetwork.Recaptcha,
agent: null
})
],
Expand All @@ -36,13 +36,13 @@ export class AppModule {

**Configuration options**

| Property | Description |
|-------------------|-------------|
| `secretKey` | **Required.**<br> Type: `string`<br> Google recaptcha secret key |
| `response` | **Required.**<br> Type: `(request) => string`<br> Function that returns response (recaptcha token) by request |
| `skipIf` | Optional.<br> Type: `boolean` \| `(request) => boolean \| Promise<boolean>` <br> Function that returns true if you allow the request to skip the recaptcha verification. Useful for involing other check methods (e.g. custom privileged API key) or for development or testing |
| `useRecaptchaNet` | Optional.<br> Type: `boolean`<br> If your server has trouble connecting to https://www.google.com. You can use https://recaptcha.net instead, just set true |
| `agent` | Optional.<br> Type: `https.Agent`<br> If you need to use an agent |
| Property | Description |
|-------------|-------------|
| `secretKey` | **Required.**<br> Type: `string`<br> Google recaptcha secret key |
| `response` | **Required.**<br> Type: `(request) => string`<br> Function that returns response (recaptcha token) by request |
| `skipIf` | Optional.<br> Type: `boolean` \| `(request) => boolean \| Promise<boolean>` <br> Function that returns true if you allow the request to skip the recaptcha verification. Useful for involing other check methods (e.g. custom privileged API key) or for development or testing |
| `network` | Optional.<br> Type: `GoogleRecaptchaNetwork` \| `boolean`<br> Default: `GoogleRecaptchaNetwork.Google` <br> If your server has trouble connecting to https://google.com then you can set networks:<br> `GoogleRecaptchaNetwork.Google` = 'https://www.google.com/recaptcha/api/siteverify'<br>`GoogleRecaptchaNetwork.Recaptcha` = 'https://recaptcha.net/recaptcha/api/siteverify'<br> or set any api url |
| `agent` | Optional.<br> Type: `https.Agent`<br> If you need to use an agent |

If you want import configs from your [ConfigService](https://docs.nestjs.com/techniques/configuration#getting-started) via [custom getter function](https://docs.nestjs.com/techniques/configuration#custom-getter-functions) that will return `GoogleRecaptchaModuleOptions` object.

Expand All @@ -60,7 +60,7 @@ export class AppModule {
}
```

### Usage <a name="Usage"></a>
## Usage

Use `@Recaptcha` decorator to protect your endpoints.

Expand Down Expand Up @@ -107,7 +107,7 @@ export class FeedbackController {

```

### Error handling <a name="ErrorHandling"></a>
### Error handling

Google recaptcha guard will throw GoogleRecaptchaException on error.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestlab/google-recaptcha",
"version": "1.1.11",
"version": "1.2.0",
"description": "Google recaptcha module for NestJS.",
"keywords": [
"nest",
Expand Down
4 changes: 4 additions & 0 deletions src/enums/google-recaptcha-network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum GoogleRecaptchaNetwork {
Google = 'https://www.google.com/recaptcha/api/siteverify',
Recaptcha = 'https://recaptcha.net/recaptcha/api/siteverify',
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export { GoogleRecaptchaGuard } from './guards/google-recaptcha.guard';
export { GoogleRecaptchaModule } from './google-recaptcha.module';
export { GoogleRecaptchaModuleOptions } from './interfaces/google-recaptcha-module-options';
export { ErrorCode } from './enums/error-code';
export { GoogleRecaptchaNetwork } from './enums/google-recaptcha-network'
export { GoogleRecaptchaException } from './exceptions/google-recaptcha.exception';
9 changes: 6 additions & 3 deletions src/interfaces/google-recaptcha-validator-options.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import * as https from "https";
import {GoogleRecaptchaNetwork} from "../enums/google-recaptcha-network";

export interface GoogleRecaptchaValidatorOptions {
secretKey: string;
/**
* If your server has trouble connecting to https://www.google.com,
* set it to `true` to use https://recaptcha.net instead.
* If your server has trouble connecting to https://google.com then you can set networks:
* GoogleRecaptchaNetwork.Google = 'https://www.google.com/recaptcha/api/siteverify'
* GoogleRecaptchaNetwork.Recaptcha = 'https://recaptcha.net/recaptcha/api/siteverify'
* or set any api url
*/
useRecaptchaNet?: boolean;
network?: GoogleRecaptchaNetwork | string;
/**
* If your server has trouble connecting to https://www.google.com,
* you can use an agent (`proxy-agent` or other NPM modules)
Expand Down
6 changes: 3 additions & 3 deletions src/services/google-recaptcha.validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import { RECAPTCHA_OPTIONS } from '../provider.declarations';
import * as qs from 'querystring';
import { GoogleRecaptchaValidationResult } from '../interfaces/google-recaptcha-validation-result';
import { ErrorCode } from '../enums/error-code';
import { GoogleRecaptchaNetwork } from '../enums/google-recaptcha-network';

@Injectable()
export class GoogleRecaptchaValidator {
private readonly apiUrl = 'https://www.google.com/recaptcha/api/siteverify';
private readonly apiUrlUseRecaptchaNet = 'https://recaptcha.net/recaptcha/api/siteverify';
private readonly defaultNetwork = GoogleRecaptchaNetwork.Google;
private readonly headers = {'Content-Type': 'application/x-www-form-urlencoded'};

constructor(private readonly http: HttpService,
Expand All @@ -18,7 +18,7 @@ export class GoogleRecaptchaValidator {
validate(response: string): Promise<GoogleRecaptchaValidationResult> {
const data = qs.stringify({secret: this.options.secretKey, response});

const url = this.options.useRecaptchaNet ? this.apiUrlUseRecaptchaNet : this.apiUrl;
const url = this.options.network || this.defaultNetwork;

return this.http.post(url, data, {
headers: this.headers,
Expand Down
14 changes: 7 additions & 7 deletions test/google-recaptcha-async-module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Test } from '@nestjs/testing';
import { Module } from '@nestjs/common';
import { GoogleRecaptchaValidator } from '../src/services/google-recaptcha.validator';
import { GoogleRecaptchaModule } from '../src/google-recaptcha.module';
import { GoogleRecaptchaModuleOptions } from '../src';
import { GoogleRecaptchaOptionsFactory } from '../src/interfaces/google-recaptcha-module-options';
import {Test} from '@nestjs/testing';
import {Module} from '@nestjs/common';
import {GoogleRecaptchaValidator} from '../src/services/google-recaptcha.validator';
import {GoogleRecaptchaModule} from '../src/google-recaptcha.module';
import {GoogleRecaptchaModuleOptions, GoogleRecaptchaNetwork} from '../src';
import {GoogleRecaptchaOptionsFactory} from '../src/interfaces/google-recaptcha-module-options';

export class GoogleRecaptchaModuleOptionsFactory implements GoogleRecaptchaOptionsFactory {
createGoogleRecaptchaOptions(): Promise<GoogleRecaptchaModuleOptions> {
Expand All @@ -17,7 +17,7 @@ export class TestConfigService {
secretKey: 'secret',
response: req => req.body.recaptcha,
skipIf: () => true,
useRecaptchaNet: false,
network: GoogleRecaptchaNetwork.Google,
agent: null
};
}
Expand Down
21 changes: 11 additions & 10 deletions test/google-recaptcha-module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Test } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { GoogleRecaptchaValidator } from '../src/services/google-recaptcha.validator';
import { GoogleRecaptchaGuard } from '../src/guards/google-recaptcha.guard';
import { GoogleRecaptchaModule } from '../src/google-recaptcha.module';
import { Agent } from 'https';
import { RECAPTCHA_OPTIONS } from '../src/provider.declarations';
import { GoogleRecaptchaModuleOptions } from '../src';
import {Test} from '@nestjs/testing';
import {INestApplication} from '@nestjs/common';
import {GoogleRecaptchaValidator} from '../src/services/google-recaptcha.validator';
import {GoogleRecaptchaGuard} from '../src/guards/google-recaptcha.guard';
import {GoogleRecaptchaModule} from '../src/google-recaptcha.module';
import {Agent} from 'https';
import {RECAPTCHA_OPTIONS} from '../src/provider.declarations';
import {GoogleRecaptchaModuleOptions} from '../src';

describe('Google recaptcha module', () => {
const customNetwork = 'CUSTOM_URL';
let app: INestApplication;

beforeAll(async () => {
Expand All @@ -17,7 +18,7 @@ describe('Google recaptcha module', () => {
secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
response: req => req.headers.authorization,
skipIf: () => process.env.NODE_ENV !== 'production',
useRecaptchaNet: true,
network: customNetwork,
agent: new Agent({maxFreeSockets: 10}),
}),
],
Expand All @@ -42,7 +43,7 @@ describe('Google recaptcha module', () => {
const options: GoogleRecaptchaModuleOptions = app.get(RECAPTCHA_OPTIONS);

expect(options).toBeDefined();
expect(options.useRecaptchaNet).toBeTruthy();
expect(options.network).toBe(customNetwork);
expect(options.agent).toBeDefined();
expect(options.agent).toBeInstanceOf(Agent);
expect(options.agent.maxFreeSockets).toBe(10);
Expand Down

0 comments on commit 26306e0

Please sign in to comment.