ng-recaptcha
Advanced tools
Comparing version 4.2.1 to 4.3.0-beta.1
@@ -0,1 +1,11 @@ | ||
<a name="4.3.0-beta.1"></a> | ||
# [4.3.0-beta.1](https://github.com/DethAriel/ng-recaptcha/compare/v4.2.1...v4.3.0-beta.1) (2019-02-08) | ||
### Features | ||
* **component:** add support for reCAPTCHA v3 ([4a083c6](https://github.com/DethAriel/ng-recaptcha/commit/4a083c6)), closes [#129](https://github.com/DethAriel/ng-recaptcha/issues/129) | ||
<a name="4.2.1"></a> | ||
@@ -2,0 +12,0 @@ ## [4.2.1](https://github.com/DethAriel/ng-recaptcha/compare/v4.2.0...v4.2.1) (2018-10-24) |
@@ -5,1 +5,3 @@ export { RecaptchaComponent } from './recaptcha/recaptcha.component'; | ||
export { RECAPTCHA_SETTINGS, RecaptchaSettings } from './recaptcha/recaptcha-settings'; | ||
export { RecaptchaV3Module } from './recaptcha/recaptcha-v3.module'; | ||
export { OnExecuteData, ReCaptchaV3Service, RECAPTCHA_V3_SITE_KEY } from './recaptcha/recaptcha-v3.service'; |
@@ -14,1 +14,6 @@ "use strict"; | ||
exports.RECAPTCHA_SETTINGS = recaptcha_settings_1.RECAPTCHA_SETTINGS; | ||
var recaptcha_v3_module_1 = require("./recaptcha/recaptcha-v3.module"); | ||
exports.RecaptchaV3Module = recaptcha_v3_module_1.RecaptchaV3Module; | ||
var recaptcha_v3_service_1 = require("./recaptcha/recaptcha-v3.service"); | ||
exports.ReCaptchaV3Service = recaptcha_v3_service_1.ReCaptchaV3Service; | ||
exports.RECAPTCHA_V3_SITE_KEY = recaptcha_v3_service_1.RECAPTCHA_V3_SITE_KEY; |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":4,"metadata":{},"exports":[{"from":"./recaptcha/recaptcha.component","export":["RecaptchaComponent"]},{"from":"./recaptcha/recaptcha-loader.service","export":["RecaptchaLoaderService","RECAPTCHA_LANGUAGE","RECAPTCHA_BASE_URL","RECAPTCHA_NONCE"]},{"from":"./recaptcha/recaptcha.module","export":["RecaptchaModule"]},{"from":"./recaptcha/recaptcha-settings","export":["RECAPTCHA_SETTINGS","RecaptchaSettings"]}]}] | ||
[{"__symbolic":"module","version":4,"metadata":{},"exports":[{"from":"./recaptcha/recaptcha.component","export":["RecaptchaComponent"]},{"from":"./recaptcha/recaptcha-loader.service","export":["RecaptchaLoaderService","RECAPTCHA_LANGUAGE","RECAPTCHA_BASE_URL","RECAPTCHA_NONCE"]},{"from":"./recaptcha/recaptcha.module","export":["RecaptchaModule"]},{"from":"./recaptcha/recaptcha-settings","export":["RECAPTCHA_SETTINGS","RecaptchaSettings"]},{"from":"./recaptcha/recaptcha-v3.module","export":["RecaptchaV3Module"]},{"from":"./recaptcha/recaptcha-v3.service","export":["OnExecuteData","ReCaptchaV3Service","RECAPTCHA_V3_SITE_KEY"]}]}] |
{ | ||
"name": "ng-recaptcha", | ||
"version": "4.2.1", | ||
"version": "4.3.0-beta.1", | ||
"description": "Angular component for Google reCAPTCHA", | ||
@@ -5,0 +5,0 @@ "scripts": { |
117
README.md
@@ -8,3 +8,3 @@ # Angular component for Google reCAPTCHA | ||
A simple, configurable, easy-to-start component for handling reCAPTCHA. | ||
A simple, configurable, easy-to-start component for handling reCAPTCHA v2 and v3. | ||
@@ -30,7 +30,10 @@ ## Table of contents | ||
* [Specifying nonce for Content-Security-Policy](#example-csp-nonce) | ||
* [Listening for all actions with reCAPTCHA v3](#example-v3-all-actions) | ||
## <a name="installation"></a>Installation | ||
The easiest way is to install trough [npm](https://www.npmjs.com/package/ng-recaptcha): | ||
``` | ||
The easiest way is to install through [yarn](https://yarnpkg.com/package/ng-recaptcha) or [npm](https://www.npmjs.com/package/ng-recaptcha): | ||
```sh | ||
yarn add ng-recaptcha | ||
npm i ng-recaptcha --save | ||
@@ -41,2 +44,4 @@ ``` | ||
The below applies to reCAPTCHA v2, for basic usage with reCAPTCHA v3 scroll down to [here](#example-basic-v3). | ||
To start with, you need to import the `RecaptchaModule` (more on that [later](#modules)): | ||
@@ -75,3 +80,3 @@ | ||
resolved(captchaResponse: string) { | ||
console.log(`Resolved captcha with response ${captchaResponse}:`); | ||
console.log(`Resolved captcha with response: ${captchaResponse}`); | ||
} | ||
@@ -89,2 +94,54 @@ } | ||
### <a name="example-basic-v3"></a>reCAPTCHA v3 Usage [(see in action)](https://dethariel.github.io/ng-recaptcha/v3) | ||
[reCAPTCHA v3](https://developers.google.com/recaptcha/docs/v3) introduces a different way of bot protection. To work with v3 APIs, `ng-recaptcha` provides a service (as opposed to a component). To start with, you need to import the `RecaptchaV3Module` and provide your reCAPTCHA v3 site key using `RECAPTCHA_V3_SITE_KEY` injection token: | ||
```ts | ||
import { BrowserModule } from '@angular/platform-browser'; | ||
import { RECAPTCHA_V3_SITE_KEY, RecaptchaV3Module } from 'ng-recaptcha'; | ||
import { MyApp } from './app.component.ts'; | ||
@NgModule({ | ||
bootstrap: [MyApp], | ||
declarations: [MyApp], | ||
imports: [ | ||
BrowserModule, | ||
RecaptchaV3Module, | ||
], | ||
providers: [ | ||
{ provide: RECAPTCHA_V3_SITE_KEY, useValue: '<YOUR_SITE_KEY>' }, | ||
], | ||
}) | ||
export class MyAppModule { } | ||
``` | ||
In order to execute a reCAPTCHA v3 action, import the `ReCaptchaV3Service` into your desired component: | ||
```ts | ||
import { ReCaptchaV3Service } from 'ng-recaptcha'; | ||
@Component({ | ||
selector: 'recaptcha-demo', | ||
template: ` | ||
<button (click)="executeImportantAction()">Important action</button> | ||
`, | ||
}) | ||
export class RecaptchaV3DemoComponent { | ||
constructor( | ||
private recaptchaV3Service: ReCaptchaV3Service, | ||
) { | ||
} | ||
public executeImportantAction(): void { | ||
this.recaptchaV3Service.execute('importantAction') | ||
.subscribe((token) => this.handleToken(token)); | ||
} | ||
``` | ||
As always with subscriptions, please don't forget to **unsubscribe**. | ||
A more advanced v3 usage scenario includes listening to all actions and their respectively emitted tokens. This is covered [later on this page](#example-v3-all-actions). | ||
### <a name="playground"></a>Playground | ||
@@ -383,1 +440,53 @@ | ||
``` | ||
### <a name="example-v3-all-actions"></a>Listening for all actions with reCAPTCHA v3 | ||
More often than not you will need to only get a reCAPTCHA token with the action the user is currently taking, and submit it to the backend at that time. However, having a single listener for all events will be desirable. | ||
There is an `Observable` exactly for that purpose: `ReCaptchaV3Service.onExecute`. It emits a value every time a token is received from reCAPTCHA. The shape of payload it operates on is defined via `OnExecuteData` interface: | ||
```ts | ||
interface OnExecuteData { | ||
action: string; | ||
token: string; | ||
} | ||
``` | ||
where `action` is the name of the action that has been executed, and `token` is what reCAPTCHA v3 provided when executing that action. | ||
Here's how you would potentially set this up: | ||
```ts | ||
import { OnExecuteData, ReCaptchaV3Service } from 'ng-recaptcha'; | ||
@Component({ | ||
selector: 'my-component', | ||
templateUrl: './v3-demo.component.html', | ||
}) | ||
export class MyComponent implements OnInit, OnDestroy { | ||
private subscription: Subscription; | ||
constructor( | ||
private recaptchaV3Service: ReCaptchaV3Service, | ||
) { | ||
} | ||
public ngOnInit() { | ||
this.subscription = this.recaptchaV3Service.onExecute | ||
.subscribe((data: OnExecuteData) => { | ||
this.handleRecaptchaExecute(data.action, data.token); | ||
}); | ||
} | ||
public ngOnDestroy() { | ||
if (this.subscription) { | ||
this.subscription.unsubscribe(); | ||
} | ||
} | ||
} | ||
``` | ||
There are a couple things to keep in mind: | ||
* `onExecute` will trigger for **all** actions. If you only need to bulk-process some actions, and not others - you will have to apply filtering yourself. | ||
* `onExecute` observable will provide you with all the events emitted **after** you have subscribed to it - it doesn't keep references to the previously emitted actions. So make sure you add such a subscription as early in your code as you feel is necessary. |
@@ -7,2 +7,3 @@ /// <reference types="grecaptcha" /> | ||
export declare const RECAPTCHA_NONCE: InjectionToken<string>; | ||
export declare function loadScript(renderMode: 'explicit' | string, onLoaded: (grecaptcha: ReCaptchaV2.ReCaptcha) => void, urlParams: string, url?: string, nonce?: string): void; | ||
export declare class RecaptchaLoaderService { | ||
@@ -9,0 +10,0 @@ private readonly platformId; |
@@ -9,2 +9,20 @@ "use strict"; | ||
exports.RECAPTCHA_NONCE = new core_1.InjectionToken('recaptcha-nonce-tag'); | ||
function loadScript(renderMode, onLoaded, urlParams, url, nonce) { | ||
window.ng2recaptchaloaded = function () { | ||
onLoaded(grecaptcha); | ||
}; | ||
var script = document.createElement('script'); | ||
script.innerHTML = ''; | ||
var baseUrl = url || 'https://www.google.com/recaptcha/api.js'; | ||
script.src = baseUrl + "?render=" + renderMode + "&onload=ng2recaptchaloaded" + urlParams; | ||
if (nonce) { | ||
// tslint:disable-next-line:no-any Remove "any" cast once we upgrade Angular to 7 and TypeScript along with it | ||
// tslint:disable-next-line:no-any Remove "any" cast once we upgrade Angular to 7 and TypeScript along with it | ||
script.nonce = nonce; | ||
} | ||
script.async = true; | ||
script.defer = true; | ||
document.head.appendChild(script); | ||
} | ||
exports.loadScript = loadScript; | ||
var RecaptchaLoaderService = /** @class */ (function () { | ||
@@ -29,19 +47,6 @@ function RecaptchaLoaderService( | ||
if (common_1.isPlatformBrowser(this.platformId)) { | ||
window.ng2recaptchaloaded = function () { | ||
RecaptchaLoaderService.ready.next(grecaptcha); | ||
}; | ||
RecaptchaLoaderService.ready = new rxjs_1.BehaviorSubject(null); | ||
var script = document.createElement('script'); | ||
script.innerHTML = ''; | ||
var subject_1 = new rxjs_1.BehaviorSubject(null); | ||
RecaptchaLoaderService.ready = subject_1; | ||
var langParam = this.language ? '&hl=' + this.language : ''; | ||
var baseUrl = this.baseUrl || 'https://www.google.com/recaptcha/api.js'; | ||
script.src = baseUrl + "?render=explicit&onload=ng2recaptchaloaded" + langParam; | ||
if (this.nonce) { | ||
// tslint:disable-next-line:no-any Remove "any" cast once we upgrade Angular to 7 and TypeScript along with it | ||
// tslint:disable-next-line:no-any Remove "any" cast once we upgrade Angular to 7 and TypeScript along with it | ||
script.nonce = this.nonce; | ||
} | ||
script.async = true; | ||
script.defer = true; | ||
document.head.appendChild(script); | ||
loadScript('explicit', function (grecaptcha) { return subject_1.next(grecaptcha); }, langParam, this.baseUrl, this.nonce); | ||
} | ||
@@ -48,0 +53,0 @@ }; |
@@ -1,1 +0,1 @@ | ||
[{"__symbolic":"module","version":4,"metadata":{"RECAPTCHA_LANGUAGE":{"__symbolic":"new","expression":{"__symbolic":"reference","module":"@angular/core","name":"InjectionToken","line":10,"character":38},"arguments":["recaptcha-language"]},"RECAPTCHA_BASE_URL":{"__symbolic":"new","expression":{"__symbolic":"reference","module":"@angular/core","name":"InjectionToken","line":11,"character":38},"arguments":["recaptcha-base-url"]},"RECAPTCHA_NONCE":{"__symbolic":"new","expression":{"__symbolic":"reference","module":"@angular/core","name":"InjectionToken","line":12,"character":35},"arguments":["recaptcha-nonce-tag"]},"RecaptchaLoaderService":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":14,"character":1}}],"members":{"__ctor__":[{"__symbolic":"constructor","parameterDecorators":[[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":33,"character":5},"arguments":[{"__symbolic":"reference","module":"@angular/core","name":"PLATFORM_ID","line":33,"character":12}]}],[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Optional","line":34,"character":5}},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":34,"character":17},"arguments":[{"__symbolic":"reference","name":"RECAPTCHA_LANGUAGE"}]}],[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Optional","line":35,"character":5}},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":35,"character":17},"arguments":[{"__symbolic":"reference","name":"RECAPTCHA_BASE_URL"}]}],[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Optional","line":36,"character":5}},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":36,"character":17},"arguments":[{"__symbolic":"reference","name":"RECAPTCHA_NONCE"}]}]],"parameters":[{"__symbolic":"reference","name":"any"},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"string"}]}],"init":[{"__symbolic":"method"}]},"statics":{"ready":null}}}}] | ||
[{"__symbolic":"module","version":4,"metadata":{"RECAPTCHA_LANGUAGE":{"__symbolic":"new","expression":{"__symbolic":"reference","module":"@angular/core","name":"InjectionToken","line":10,"character":38},"arguments":["recaptcha-language"]},"RECAPTCHA_BASE_URL":{"__symbolic":"new","expression":{"__symbolic":"reference","module":"@angular/core","name":"InjectionToken","line":11,"character":38},"arguments":["recaptcha-base-url"]},"RECAPTCHA_NONCE":{"__symbolic":"new","expression":{"__symbolic":"reference","module":"@angular/core","name":"InjectionToken","line":12,"character":35},"arguments":["recaptcha-nonce-tag"]},"loadScript":{"__symbolic":"function"},"RecaptchaLoaderService":{"__symbolic":"class","decorators":[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Injectable","line":38,"character":1}}],"members":{"__ctor__":[{"__symbolic":"constructor","parameterDecorators":[[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":57,"character":5},"arguments":[{"__symbolic":"reference","module":"@angular/core","name":"PLATFORM_ID","line":57,"character":12}]}],[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Optional","line":58,"character":5}},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":58,"character":17},"arguments":[{"__symbolic":"reference","name":"RECAPTCHA_LANGUAGE"}]}],[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Optional","line":59,"character":5}},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":59,"character":17},"arguments":[{"__symbolic":"reference","name":"RECAPTCHA_BASE_URL"}]}],[{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Optional","line":60,"character":5}},{"__symbolic":"call","expression":{"__symbolic":"reference","module":"@angular/core","name":"Inject","line":60,"character":17},"arguments":[{"__symbolic":"reference","name":"RECAPTCHA_NONCE"}]}]],"parameters":[{"__symbolic":"reference","name":"any"},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"string"},{"__symbolic":"reference","name":"string"}]}],"init":[{"__symbolic":"method"}]},"statics":{"ready":null}}}}] |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
70276
39
633
487
0
1