Giter VIP home page Giter VIP logo

ember-g-recaptcha's Introduction

ember-g-recaptcha

Easily integrate Google's reCaptcha in your app as an Ember Component.

Install

Run the following command from inside your ember-cli project:

ember install ember-g-recaptcha

  • Ember.js v3.24 or above
  • Ember CLI v3.24 or above
  • Node.js v12 or above

Configure

You need to generate a valid Site Key / Secret Key pair on Google's reCaptcha admin console. Then, you need to set your Site Key in the ENV var on your config/environment.js file, like this:

var ENV = {
  // ...
};

ENV['ember-g-recaptcha'] = {
  jsUrl: 'https://www.google.com/recaptcha/api.js', // default
  sitekey: 'your-recaptcha-site-key',
  hl: 'tr', // Ex: Turkish
};

Basic Usage

Add the component to your template like this:

<GRecaptcha @onSuccess={{this.onCaptchaResolved}} />

then in your component or controller 's actions:

  @action
  onCaptchaResolved(reCaptchaResponse) {
    this.model.set('reCaptchaResponse', reCaptchaResponse);
    // You should then save your model and the server would validate reCaptchaResponse
    // ...
  }

Advanced Usage

Handling Expiration

You know, after some time the reCaptcha response expires; g-recaptcha 's default behavior is to invoke the reset method. But, if you want to perform custom behavior instead (e.g. transitioning to another route) you can pass your custom action via the onExpired property, like this:

<GRecaptcha
  @onSuccess={{this.onCaptchaResolved}}
  @onExpired={{this.onCaptchaExpired}}
/>

then in your component or controller 's actions:

  @action
  onCaptchaExpired() {
    // your custom logic here
  }

Triggering Reset

You might want to arbitrarily trigger reCaptcha reset. For example, if your form submission fails for errors on other fields, you might want to force user to solve a new reCaptcha challenge. To do that, first you'll need to grab a reference to g-recaptcha in your template, like this:

<GRecaptcha
  @onRender={{fn (mut this.gRecaptcha)}}
  @onSuccess={{this.onCaptchaResolved}}
/>

then you'll be able to invoke reset() method on gRecaptcha property anywhere in your component or controller 's code, like this:

this.gRecaptcha.reset();

onRender Callback

You might want to pass a callback function that will be called after the reCaptcha renders on the page. This is great for things like loading spinners. To do so, you can do something like this:

<GRecaptcha
  @onRender={{this.onCaptchaRendered}}
  @onSuccess={{this.onCaptchaResolved}}
/>

then in your component or controller 's actions:

  @action
  onCaptchaRendered() {
    // your custom onRender logic
  }

  @action
  onCaptchaResolved() {
    // ...
  }

Skipping real library download

Sometimes you want to have the behavior of a reCAPTCHA but without the burden of injecting the downloaded library into your web page. This is particularly useful during tests.

<GRecaptcha
  @skip={{true}}
  @onSuccess={{this.onCaptchaResolved}}
/>

Using @skip, you have the power to ignore the reCAPTCHA's real validations but still have the ability to call your success callback.

โš ๏ธ This does not work with onError and onExpired.

Customization

You can pass g-recaptcha the following properties:

  • sitekey
  • theme
  • size
  • tabindex
  • badge
  • isolated
  • skip*

Their meaning is described on this official doc. Also have a look at the dummy app's example templates.

* The skip option is not a official option.

Invisible reCaptcha

Invisible reCaptcha requires different key than classic reCaptcha. You need to register a new key with invisible type. More information

In some cases you may want to use reCaptcha in the invisible mode. The only thing you need do is to add size key to g-recaptcha component with invisible value and create a button with submit type, so you will get something like this:

<GRecaptcha @onSuccess={{this.onCaptchaResolved}} @size='invisible' />

<button {{on 'click' this.submit}} type='button'>Hello</button>

Then in your component you need to define submit method which will execute reCaptcha. For example:

@action
async submit() {
  await window.grecaptcha.execute();
  // Process rest of operations
}

Configuring source JavaScript URL

In some countries, such as China, you may need to customize the source JavaScript URL. Since the google.com domain is blocked in China, you must set the jsUrl in the configuration to use the recaptcha.net. This works outside China as well.

var ENV = {
  // ...
};

ENV['ember-g-recaptcha'] = {
  jsUrl: 'https://www.google.com/recaptcha/api.js', // default
  sitekey: 'your-recaptcha-site-key',
};

This also requires the backend URL to be set to https://recaptcha.net/recaptcha/api/siteverify. For more information on configuring the jsUrl, see this issue.

License

ember-g-recaptcha is released under the MIT License.

ember-g-recaptcha's People

Contributors

algodave avatar binoculars avatar brunoocasali avatar craig2017 avatar eliasmelgaco avatar ember-tomster avatar jamesdixon avatar josemarluedke avatar nbrookie avatar pixelik avatar rxbsxn avatar safeforge avatar simonexmachina avatar sinankeskin avatar staffe avatar tneems avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

ember-g-recaptcha's Issues

TypeError: window.grecaptcha.render is not a function

Version: 0.4.0

I got this error in Sentry from an ip in Germany:

TypeError: window.grecaptcha.render is not a function

and this is the code (I've put a <---- on the faulty line) from Sentry:

var properties = this.getProperties('sitekey', 'theme', 'type', 'size', 'tabindex');
var parameters = _ember['default'].merge(properties, {
callback: this.get('successCallback').bind(this),
  'expired-callback': this.get('expiredCallback').bind(this)
});
var widgetId = window.grecaptcha.render(container, parameters);  <----
this.set('widgetId', widgetId);
this.set('ref', this);

from file: ember-g-recaptcha/components/g-recaptcha.js

Any idea why that happened?

Disable GRecaptcha in e2e tests

Hello, how is everything?

My case involves more performance gains in e2e tests than anything else.
Currently my authentication flows need captcha to work and this is expected for security reasons,
the big question is that using captcha in test environments is very expensive, as it involves downloading the google library,
and generate its configuration (which takes time, mainly in unstable or bad connections as it happens in emerging countries like Brazil - where I am at the moment).

The idea in this case, is to create a kind of "fallback" / "mock" for the GRecaptcha functions so that the fake captcha flows continue to work in test.

What I thought was to add an option:

// controller

isActive = window.ENABLE_RECAPTCHA // (each app will have their owns)
<GRecaptcha
  @sitekey={{this.recaptchaKey}}
  @onSuccess={{action this.onSuccess}}
  @onExpired={{action this.onExpired}}
  @size="invisible"
  @active={{this.isActive}}
/>

With this kind of control, we could only enable recaptcha when is really needed.

PS: I can work on this improvement ;)

ember-cli-babel update

Ember 3.x
DEPRECATION: ember-cli-babel 5.x has been deprecated. Please upgrade to at least ember-cli-babel 6.6.

Is this add-on dead?

We are bumping our Ember versions from 3.4 to 3.12 when we are being halted by deprecation warnings from this add-on. There appear to be outstanding pull-requests that fix those specified deprecations, but it doesn't look like there has been any original follow-up by the codeowner/codeowners.

Appending same query param twice in `components/g-recaptcha.js` + unnecessary `&` at the end

You append the same query param on line 65 and then on line 71

On line 66 you're also sometimes adding an empty string for no reason so you end up with an extra & at the end of the string in those cases

So in the end you end up with:

https://....?explicit=true&onload=...&&onload=...

Code should be:

  @action
  _initialize(element) {
    const globalName = `__ember_g_recaptcha_${this.elementId}_onload`

    window[globalName] = () => {
      this._render(element)
    }

    let baseUrl = [
      `${this.config['jsUrl'] || 'https://www.google.com/recaptcha/api.js'}?render=explicit`,
      `onload=${globalName}`
    ]

    if (this.config['hl']) {
      baseUrl.push(`hl=${this.config['hl']}`)
    }

    if (!this.options['skip']) {
      this._appendScript(baseUrl.join('&'))
    } else {
      this._render()
    }
  }

DEPRECATION: Use of `merge` has been deprecated. Please use `assign` instead.

Ember 3.x produces the following deprecation:

DEPRECATION: Use of merge has been deprecated. Please use assign instead. [deprecation id: ember-polyfills.deprecate-merge] See https://emberjs.com/deprecations/v3.x/#toc_ember-polyfills-deprecate-merge for more details.

Solution: replace merge with assign:

ember-g-recaptcha/addon/components/g-recaptcha.js line 4, and 24:
4:import { merge } from '@ember/polyfills';
24:let parameters = merge(properties, {

Double GRecaptcha in the same page doesn't work

I've been trying to put more more than one GRepatcha in the same page. For this, I set separate ids for each <GRecaptcha ... /> and these id assignments work just fine. But the reference to this.element is lost in this anonymous callback function and always resolves to the element of the last <GRecaptcha />. SInce the grecaptcha.render is called on the same this.element multiple times, it leads to the error.

Notify component on ReCaptcha APIs loaded

The renderReCaptcha() method currently waits 500ms and retries until ReCaptcha APIs are available. it would be great to have that method invoked once, right after the global grecaptcha object is available.

ReCapthca APIs JavaScript is actually able to notify that by invoking a global function whose name you can pass it as the onload parameter, like this:
https://www.google.com/recaptcha/api.js?onload=onloadCallback
(read here to learn more)

However, I have no idea atm how to achieve that. Perhaps a global function that simply acts as a proxy for the renderReCaptcha() method? But then, how to invoke a component's method from a global function? Here's an interesting discussion:
http://stackoverflow.com/questions/19970200/emberjs-calling-components-methods-from-outside-with-a-couple-solutions-call

Any ideas welcome!

Cannot read property 'defineProperty' of undefined

Hey,
I've just tried updating the addon from 0.4.0 to 0.9.0 and upon loading a page with recaptcha I'm getting Cannot read property 'defineProperty' of undefined error in the console.

After a bit of searching, I found a similar issue raised in ember-cli-qunit: ember-cli/ember-cli-qunit#202. I believe the issue is due to this file: configuration.js, and it appears to work if I rename the Object import to EmberObject. Not sure if doing this will have any other knock-on effects though.

My app is currently running Ember version 2.15

Seemingly arbitrary test failures: "reCAPTCHA placeholder element must be an element or id"

Many of our sites are using this add-on with Ember 3.20 but are currently stuck on the v0.10.0 due to later versions seeming to cause issues while testing.

A quick example:

not ok 66 Firefox 69.0 - [151 ms] - Acceptance | portfolio-test.js: Navigated to /portfolio-companies and header text is PORTFOLIO
    ---
        actual: >
            [object Object]
        stack: >
            p</<@https://www.gstatic.com/recaptcha/releases/r8jtf1oixV0IGff4hgB4EzDF/recaptcha__en.js:363:325
            renderReCaptcha@http://localhost:7357/assets/vendor.js:121958:40
            didInsertElement/window.__ember_g_recaptcha_onload_callback@http://localhost:7357/assets/vendor.js:122007:14

        message: >
            reCAPTCHA placeholder element must be an element or id
        negative: >
            false
        browser log: |

The major confusion though is that this sort of test failure is inconsistent. For example, if we ran through all the tests again, this specific test might actually pass, whereas another totally different test might suddenly fail with the same error message. We have spent some time in this but are perplexed. Because we are on Ember 3.20, we are also getting some linting failures for being on v0.10.0 which we are simply ignoring for now.

It's possible this is something that has to be solved on our end, but this problem has persisted throughout each of our sites using the ember-g-recaptcha library. I'm not really clear what the issue is but I thought I might at least mention in it here.

Error after upgrading to Ember 4.4.0

I have been using ember-g-recaptcha for quite a while to regulate access to an email form on my Ember 2.* website. I am in the process of upgrading this implementation to Ember 4.4.0, but I am unable to get the ember-g-recaptcha GRecaptcha component to work in that context.

I receive the following error when trying to render the GRecaptcha component (while running locally against the Ember development server):

recaptcha__en.js:206 Uncaught Error: Missing required parameters: sitekey
    at Dw.<anonymous> (recaptcha__en.js:206:228)
    at new Dw (recaptcha__en.js:454:222)
    at T6.<anonymous> (recaptcha__en.js:306:483)
    at new T6 (recaptcha__en.js:682:388)
    at Array.<anonymous> (recaptcha__en.js:141:79)
    at recaptcha__en.js:415:279
    at Array.forEach (<anonymous>)
    at Array.<anonymous> (recaptcha__en.js:415:247)
    at Array.<anonymous> (recaptcha__en.js:354:496)
    at Q.<computed>.<computed>.<computed>.Q.<computed>.<computed>.<computed> [as gor] (recaptcha__en.js:133:232)

I have the following in my environment.js:

    const ENV = {
        // The usual stuff
    };

    ENV['ember-g-recaptcha'] = {
        jsUrl: 'https://www.google.com/recaptcha/api.js?render=explicit', // default
        sitekey: '<my valid Google recaptcha site key>,
    };

...and the following in my template (with corresponding @action blocks in my Controller):

<GRecaptcha
    @onExpired={{this.onCaptchaExpired}}
    @onSuccess={{this.onCaptchaResolved}}
/>

I have no idea what I could be missing. Any insight would be greatly appreciated.

Uncaught TypeError: Cannot read property 'defineProperty' of undefined

I was getting TypeError: window.grecaptcha.render is not a function #9 error, so I have decided to update from ^0.5.0 to ^0.8.0 and after I was getting this error:

at Module.callback (vendor.js:196560)

define('ember-g-recaptcha/configuration', ['exports'], function (exports) {
  'use strict';

  Object.defineProperty(exports, "__esModule", { // `Object.defineProperty` throws error
    value: true
  });
  var Object = Ember.Object;
  exports.default = Object.create();
});

This probably happens after this commit.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.