Skip to content

Commit

Permalink
Merge pull request #114 from chvarkov/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
chvarkov authored Mar 18, 2023
2 parents 18e7d68 + 455443e commit 1068a19
Show file tree
Hide file tree
Showing 16 changed files with 82 additions and 110 deletions.
54 changes: 25 additions & 29 deletions package-lock.json

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

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
"url": "https://github.com/chvarkov/google-recaptcha/issues"
},
"homepage": "https://github.com/chvarkov/google-recaptcha",
"dependencies": {
"axios": "^1.3.4"
},
"peerDependencies": {
"@nestjs/axios": ">=1.0.0 <2.0.0",
"@nestjs/common": ">=8.0.0 <10.0.0",
"@nestjs/core": ">=8.0.0 <10.0.0",
"rxjs": ">=7.0.0 <8.0.0",
"axios": ">=1.0.0 <2.0.0"
"@nestjs/core": ">=8.0.0 <10.0.0"
},
"peerDependenciesMeta": {
"@nestjs/graphql": {
Expand All @@ -44,7 +44,7 @@
},
"devDependencies": {
"@nestjs/apollo": "^10.0.22",
"@nestjs/axios": "^1.0.0",
"@nestjs/axios": "^2.0.0",
"@nestjs/common": "^9.0.11",
"@nestjs/core": "^9.0.11",
"@nestjs/graphql": "^10.0.22",
Expand Down
29 changes: 7 additions & 22 deletions src/google-recaptcha.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,17 @@ import {
GoogleRecaptchaModuleOptions,
GoogleRecaptchaOptionsFactory,
} from './interfaces/google-recaptcha-module-options';
import { RECAPTCHA_AXIOS_INSTANCE, RECAPTCHA_HTTP_SERVICE, RECAPTCHA_LOGGER, RECAPTCHA_OPTIONS } from './provider.declarations';
import { RECAPTCHA_AXIOS_INSTANCE, RECAPTCHA_LOGGER, RECAPTCHA_OPTIONS } from './provider.declarations';
import { RecaptchaRequestResolver } from './services/recaptcha-request.resolver';
import { Reflector } from '@nestjs/core';
import * as axios from 'axios';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import { Agent } from 'https';
import { RecaptchaValidatorResolver } from './services/recaptcha-validator.resolver';
import { EnterpriseReasonTransformer } from './services/enterprise-reason.transformer';
import { xor } from './helpers/xor';
import { HttpService } from '@nestjs/axios';

export class GoogleRecaptchaModule {
private static axiosDefaultConfig: axios.AxiosRequestConfig = {
private static axiosDefaultConfig: AxiosRequestConfig = {
timeout: 60_000,
httpsAgent: new Agent({ keepAlive: true }),
};
Expand All @@ -45,14 +44,9 @@ export class GoogleRecaptchaModule {
this.validateOptions(options);

const internalProviders: Provider[] = [
{
provide: RECAPTCHA_HTTP_SERVICE,
useFactory: (axiosInstance: axios.AxiosInstance) => new HttpService(axiosInstance),
inject: [RECAPTCHA_AXIOS_INSTANCE],
},
{
provide: RECAPTCHA_AXIOS_INSTANCE,
useFactory: (): axios.AxiosInstance => this.createAxiosInstance(
useFactory: (): AxiosInstance => axios.create(
this.transformAxiosConfig({
...this.axiosDefaultConfig,
...options.axiosConfig,
Expand Down Expand Up @@ -88,22 +82,17 @@ export class GoogleRecaptchaModule {
];

const internalProviders: Provider[] = [
{
provide: RECAPTCHA_HTTP_SERVICE,
useFactory: (axiosInstance: axios.AxiosInstance) => new HttpService(axiosInstance),
inject: [RECAPTCHA_AXIOS_INSTANCE],
},
{
provide: RECAPTCHA_AXIOS_INSTANCE,
useFactory: (options: GoogleRecaptchaModuleOptions): axios.AxiosInstance => {
useFactory: (options: GoogleRecaptchaModuleOptions): AxiosInstance => {
this.validateOptions(options);

const transformedAxiosConfig = this.transformAxiosConfig({
...this.axiosDefaultConfig,
...options.axiosConfig,
headers: null,
});
return this.createAxiosInstance(transformedAxiosConfig);
return axios.create(transformedAxiosConfig);
},
inject: [RECAPTCHA_OPTIONS],
},
Expand All @@ -118,7 +107,7 @@ export class GoogleRecaptchaModule {
};
}

private static transformAxiosConfig(axiosConfig: axios.AxiosRequestConfig): axios.AxiosRequestConfig {
private static transformAxiosConfig(axiosConfig: AxiosRequestConfig): AxiosRequestConfig {
const config = { ...axiosConfig };

delete config.baseURL;
Expand Down Expand Up @@ -179,8 +168,4 @@ export class GoogleRecaptchaModule {
private static isGoogleRecaptchaFactory(object?: GoogleRecaptchaOptionsFactory): object is GoogleRecaptchaOptionsFactory {
return !!object && typeof object.createGoogleRecaptchaOptions === 'function';
}

private static createAxiosInstance(axiosConfig: axios.AxiosRequestConfig): axios.AxiosInstance {
return axios['create'](axiosConfig); // TODO: Updated when axios ts declaration will be fixed
}
}
2 changes: 0 additions & 2 deletions src/provider.declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,4 @@ export const RECAPTCHA_VALIDATION_OPTIONS = Symbol('RECAPTCHA_VALIDATION_OPTIONS

export const RECAPTCHA_AXIOS_INSTANCE = 'RECAPTCHA_AXIOS_INSTANCE';

export const RECAPTCHA_HTTP_SERVICE = 'RECAPTCHA_HTTP_SERVICE';

export const RECAPTCHA_LOGGER = 'RECAPTCHA_LOGGER';
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Inject, Injectable, LiteralObject, Logger } from '@nestjs/common';
import { RECAPTCHA_HTTP_SERVICE, RECAPTCHA_LOGGER, RECAPTCHA_OPTIONS } from '../../provider.declarations';
import { HttpService } from '@nestjs/axios';
import { RECAPTCHA_AXIOS_INSTANCE, RECAPTCHA_LOGGER, RECAPTCHA_OPTIONS } from '../../provider.declarations';
import { GoogleRecaptchaModuleOptions } from '../../interfaces/google-recaptcha-module-options';
import { VerifyResponseOptions } from '../../interfaces/verify-response-decorator-options';
import { AbstractGoogleRecaptchaValidator } from './abstract-google-recaptcha-validator';
Expand All @@ -11,8 +10,8 @@ import { GoogleRecaptchaNetworkException } from '../../exceptions/google-recaptc
import { GoogleRecaptchaContext } from '../../enums/google-recaptcha-context';
import { VerifyResponseEnterprise, VerifyTokenEnterpriseEvent } from '../../interfaces/verify-response-enterprise';
import { EnterpriseReasonTransformer } from '../enterprise-reason.transformer';
import { firstValueFrom } from 'rxjs';
import { getErrorInfo } from '../../helpers/get-error-info';
import { AxiosInstance } from 'axios';

type VerifyResponse = [VerifyResponseEnterprise, LiteralObject];

Expand All @@ -21,7 +20,7 @@ export class GoogleRecaptchaEnterpriseValidator extends AbstractGoogleRecaptchaV
private readonly headers = { 'Content-Type': 'application/json' };

constructor(
@Inject(RECAPTCHA_HTTP_SERVICE) private readonly http: HttpService,
@Inject(RECAPTCHA_AXIOS_INSTANCE) private readonly axios: AxiosInstance,
@Inject(RECAPTCHA_LOGGER) private readonly logger: Logger,
@Inject(RECAPTCHA_OPTIONS) options: GoogleRecaptchaModuleOptions,
private readonly enterpriseReasonTransformer: EnterpriseReasonTransformer
Expand Down Expand Up @@ -94,7 +93,7 @@ export class GoogleRecaptchaEnterpriseValidator extends AbstractGoogleRecaptchaV
this.logger.debug({ body }, `${GoogleRecaptchaContext.GoogleRecaptchaEnterprise}.request`);
}

return firstValueFrom(this.http.post<VerifyResponseEnterprise>(url, body, config))
return this.axios.post<VerifyResponseEnterprise>(url, body, config)
.then((res) => res.data)
.then((data): VerifyResponse => {
if (this.options.debug) {
Expand Down
9 changes: 4 additions & 5 deletions src/services/validators/google-recaptcha.validator.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { Inject, Injectable, Logger } from '@nestjs/common';
import { RECAPTCHA_HTTP_SERVICE, RECAPTCHA_LOGGER, RECAPTCHA_OPTIONS } from '../../provider.declarations';
import { RECAPTCHA_AXIOS_INSTANCE, RECAPTCHA_LOGGER, RECAPTCHA_OPTIONS } from '../../provider.declarations';
import * as qs from 'querystring';
import * as axios from 'axios';
import { GoogleRecaptchaNetwork } from '../../enums/google-recaptcha-network';
import { VerifyResponseOptions } from '../../interfaces/verify-response-decorator-options';
import { VerifyResponseV2, VerifyResponseV3 } from '../../interfaces/verify-response';
import { ErrorCode } from '../../enums/error-code';
import { GoogleRecaptchaNetworkException } from '../../exceptions/google-recaptcha-network.exception';
import { HttpService } from '@nestjs/axios';
import { GoogleRecaptchaModuleOptions } from '../../interfaces/google-recaptcha-module-options';
import { AbstractGoogleRecaptchaValidator } from './abstract-google-recaptcha-validator';
import { RecaptchaVerificationResult } from '../../models/recaptcha-verification-result';
import { GoogleRecaptchaContext } from '../../enums/google-recaptcha-context';
import { firstValueFrom } from 'rxjs';
import { getErrorInfo } from '../../helpers/get-error-info';
import { AxiosInstance } from 'axios';

@Injectable()
export class GoogleRecaptchaValidator extends AbstractGoogleRecaptchaValidator<VerifyResponseV3> {
Expand All @@ -22,7 +21,7 @@ export class GoogleRecaptchaValidator extends AbstractGoogleRecaptchaValidator<V
private readonly headers = { 'Content-Type': 'application/x-www-form-urlencoded' };

constructor(
@Inject(RECAPTCHA_HTTP_SERVICE) private readonly http: HttpService,
@Inject(RECAPTCHA_AXIOS_INSTANCE) private readonly axios: AxiosInstance,
@Inject(RECAPTCHA_LOGGER) private readonly logger: Logger,
@Inject(RECAPTCHA_OPTIONS) options: GoogleRecaptchaModuleOptions
) {
Expand Down Expand Up @@ -82,7 +81,7 @@ export class GoogleRecaptchaValidator extends AbstractGoogleRecaptchaValidator<V
this.logger.debug({ body }, `${GoogleRecaptchaContext.GoogleRecaptcha}.request`);
}

return firstValueFrom(this.http.post(url, body, config))
return this.axios.post(url, body, config)
.then((res) => res.data)
.then((data) => {
if (this.options.debug) {
Expand Down
4 changes: 2 additions & 2 deletions test/get-error-info.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getErrorInfo } from '../src/helpers/get-error-info';
import { LiteralObject } from '@nestjs/common';
import { AxiosError } from 'axios';
import { AxiosError, InternalAxiosRequestConfig } from 'axios';

describe('getErrorInfo', () => {
test('Error', () => {
Expand All @@ -23,7 +23,7 @@ describe('getErrorInfo', () => {
response: {
headers: {},
status: 400,
config: {},
config: {} as InternalAxiosRequestConfig,
request: {},
statusText: 'Bad request',
data: {
Expand Down
6 changes: 2 additions & 4 deletions test/google-recaptcha-async-module.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { TestConfigModule } from './assets/test-config-module';
import { TestConfigService } from './assets/test-config-service';
import { GoogleRecaptchaModuleOptionsFactory } from './assets/test-recaptcha-options-factory';
import { HttpModule, HttpService } from '@nestjs/axios';
import { RECAPTCHA_AXIOS_INSTANCE, RECAPTCHA_HTTP_SERVICE, RECAPTCHA_OPTIONS } from '../src/provider.declarations';
import { RECAPTCHA_AXIOS_INSTANCE, RECAPTCHA_OPTIONS } from '../src/provider.declarations';
import { AxiosInstance, AxiosProxyConfig, AxiosRequestConfig } from 'axios';
import * as https from 'https';
import { Type } from '@nestjs/common';
Expand Down Expand Up @@ -72,9 +72,7 @@ describe('Google recaptcha async module', () => {

expect(options.axiosConfig.data).toBe('TEST');

const httpService: HttpService = app.get(RECAPTCHA_HTTP_SERVICE);

const httpsAgent: https.Agent = httpService.axiosRef.defaults.httpsAgent;
const httpsAgent: https.Agent = axiosInstance.defaults.httpsAgent;

expect(httpsAgent).toBeInstanceOf(https.Agent);
expect(httpsAgent.options.timeout).toBe(17_000);
Expand Down
4 changes: 2 additions & 2 deletions test/helpers/create-google-recaptcha-enterprise-validator.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { HttpService } from '@nestjs/axios';
import { Logger } from '@nestjs/common';
import { GoogleRecaptchaEnterpriseValidator, GoogleRecaptchaModuleOptions } from '../../src';
import { EnterpriseReasonTransformer } from '../../src/services/enterprise-reason.transformer';
import axios from 'axios';

export function createGoogleRecaptchaEnterpriseValidator(options: GoogleRecaptchaModuleOptions): GoogleRecaptchaEnterpriseValidator {
return new GoogleRecaptchaEnterpriseValidator(new HttpService(), new Logger(), options, new EnterpriseReasonTransformer());
return new GoogleRecaptchaEnterpriseValidator(axios.create(), new Logger(), options, new EnterpriseReasonTransformer());
}
4 changes: 2 additions & 2 deletions test/helpers/create-google-recaptcha-validator.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { GoogleRecaptchaValidator } from '../../src/services/validators/google-recaptcha.validator';
import { HttpService } from '@nestjs/axios';
import { Logger } from '@nestjs/common';
import { GoogleRecaptchaModuleOptions } from '../../src';
import axios from 'axios';

export function createGoogleRecaptchaValidator(options: GoogleRecaptchaModuleOptions): GoogleRecaptchaValidator {
return new GoogleRecaptchaValidator(new HttpService(), new Logger(), options);
return new GoogleRecaptchaValidator(axios.create(options.axiosConfig), new Logger(), options);
}
6 changes: 3 additions & 3 deletions test/integrations/graphql/graphql-recaptcha-v2-v3.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { INestApplication, Module } from '@nestjs/common';
import { GoogleRecaptchaModule, Recaptcha, RecaptchaResult, RecaptchaVerificationResult } from '../../../src';
import { Test, TestingModule } from '@nestjs/testing';
import { RECAPTCHA_HTTP_SERVICE } from '../../../src/provider.declarations';
import * as request from 'supertest';
import { MockedRecaptchaApi } from '../../utils/mocked-recaptcha-api';
import { VerifyResponseV3 } from '../../../src/interfaces/verify-response';
Expand All @@ -10,6 +9,7 @@ import { IncomingMessage } from 'http';
import { Args, Field, GraphQLModule, InputType, Mutation, ObjectType, Query, Resolver } from '@nestjs/graphql';
import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo';
import * as path from 'path';
import { RECAPTCHA_AXIOS_INSTANCE } from '../../../src/provider.declarations';

@InputType()
export class FeedbackInput {
Expand Down Expand Up @@ -81,9 +81,9 @@ describe('HTTP Recaptcha V2 V3', () => {
}),
],
})
.overrideProvider(RECAPTCHA_HTTP_SERVICE)
.overrideProvider(RECAPTCHA_AXIOS_INSTANCE)
.useFactory({
factory: () => mockedRecaptchaApi.getHttpService(),
factory: () => mockedRecaptchaApi.getAxios(),
})
.compile();

Expand Down
Loading

0 comments on commit 1068a19

Please sign in to comment.