Skip to content

Commit

Permalink
Merge pull request #4 from chvarkov/develop
Browse files Browse the repository at this point in the history
Added docs. Added reexport.
  • Loading branch information
chvarkov authored Oct 23, 2020
2 parents a05ec9d + 83b64be commit 2de48d0
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 30 deletions.
128 changes: 102 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# Google recaptcha module

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)

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

### Install

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

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

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

```typescript
@Module({
Expand All @@ -23,7 +32,9 @@ export class AppModule {
}
```

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

Use `@Recaptcha` decorator to protect your endpoints.

```typescript

Expand All @@ -32,43 +43,108 @@ export class FeedbackController {
@Recaptcha()
@Post('send')
async send(): Promise<any> {
// TODO: Implement it.
// TODO: Your implementation.
}
}

```

### Error handling
If you want use google recaptcha guard in combination with another guards then you can use `@UseGuards` decorator.

Example error customization. You can return or throw HttpException or return string.
```typescript

If you will return string, then response will have status code 400 (Bad request).
@Controller('feedback')
export class FeedbackController {
@UseGuards(Guard1, GoogleRecaptchaGuard, Guard2)
@Post('send')
async send(): Promise<any> {
// TODO: Your implementation.
}
}

```

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

Google recaptcha guard will throw GoogleRecaptchaException on error.

`GoogleRecaptchaException` has data with google recaptcha error codes.

`GoogleRecaptchaException``BadRequestException``HttpException``Error`.

You can handle it via [ExceptionFilter](https://docs.nestjs.com/exception-filters).

Example exception filter implementation.

```typescript
GoogleRecaptchaModule.forRoot({
secretKey: process.env.GOOGLE_RECAPTCHA_SECRET_KEY,
response: req => req.headers.recaptcha,
skipIf: () => process.env.NODE_ENV !== 'production',
onError: (errorCodes: ErrorCode[]) => {
switch (errorCodes.shift()) {
case ErrorCode.MissingInputSecret:
return 'The secret parameter is missing.';
case ErrorCode.InvalidInputSecret:
return 'The secret parameter is invalid or malformed.';
case ErrorCode.MissingInputResponse:
return 'The response parameter is missing.';

@Catch(GoogleRecaptchaException)
export class GoogleRecaptchaFilter implements ExceptionFilter {
catch(exception: GoogleRecaptchaException, host: ArgumentsHost): any {
const res: Response = host.switchToHttp().getResponse();

const firstErrorCode = exception.errorCodes.shift();

const transformedError = this.transformError(firstErrorCode);

res.status(transformedError.status).send({
type: 'GoogleRecaptchaError',
message: transformedError.message,
});
}

transformError(errorCode: ErrorCode): {status: number, message: string} {
switch (errorCode) {
case ErrorCode.InvalidInputResponse:
return 'The response parameter is invalid or malformed.';
case ErrorCode.BadRequest:
return 'The request is invalid or malformed.';
return {
status: HttpStatus.BAD_REQUEST,
message: 'The response parameter is invalid or malformed.',
};

case ErrorCode.MissingInputResponse:
return {
status: HttpStatus.BAD_REQUEST,
message: 'The response parameter is missing.',
};

case ErrorCode.TimeoutOrDuplicate:
return 'The response is no longer valid: either is too old or has been used previously.';
return {
status: HttpStatus.BAD_REQUEST,
message: 'The response is no longer valid: either is too old or has been used previously.',
};

case ErrorCode.InvalidInputSecret:
case ErrorCode.MissingInputSecret:
return {
status: HttpStatus.INTERNAL_SERVER_ERROR,
message: 'Invalid module configuration. Please check public-secret keys.',
};

case ErrorCode.UnknownError:
case ErrorCode.BadRequest:
default:
return new BadGatewayException('Unknown error when checking captcha.');
return {
status: HttpStatus.INTERNAL_SERVER_ERROR,
message: 'Unexpected error. Please submit issue to @nestlab/google-recaptcha.',
};
}
},
})
}
}

```

And add your filter to application

```typescript

async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new ErrorFilter(), new GoogleRecaptchaFilter());
await app.listen(3000);
}
bootstrap();


```

Enjoy!
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.0.14",
"version": "1.1.0",
"description": "Google recaptcha module for NestJS.",
"keywords": [
"nest",
Expand Down
6 changes: 3 additions & 3 deletions src/exceptions/google-recaptcha.exception.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ForbiddenException } from '@nestjs/common';
import { BadRequestException } from '@nestjs/common';
import { ErrorCode } from '../enums/error-code';

export class GoogleRecaptchaException extends ForbiddenException {
export class GoogleRecaptchaException extends BadRequestException {
constructor(public readonly errorCodes: ErrorCode[]) {
super();
super(`Google recaptcha errors: ${errorCodes.join(', ')}.`);
}
}
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ 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 { GoogleRecaptchaException } from './exceptions/google-recaptcha.exception';

0 comments on commit 2de48d0

Please sign in to comment.