UNPKG

ngx-captcha-ssr

Version:

Dynamic captcha (Google reCaptcha) implementation for Angular

134 lines 18 kB
import { isPlatformBrowser } from "@angular/common"; import { Inject, Injectable, NgZone, PLATFORM_ID } from "@angular/core"; import * as i0 from "@angular/core"; export class ScriptService { constructor(zone, platformId) { this.zone = zone; this.platformId = platformId; this.scriptElemId = "ngx-catpcha-script"; /** * Name of the global google recaptcha script */ this.windowGrecaptcha = "grecaptcha"; /** * Name of enterpise property in the global google recaptcha script */ this.windowGrecaptchaEnterprise = "enterprise"; /** * Name of the global callback */ this.windowOnLoadCallbackProperty = "ngx_captcha_onload_callback"; /** * Name of the global callback for enterprise */ this.windowOnLoadEnterpriseCallbackProperty = "ngx_captcha_onload_enterprise_callback"; this.globalDomain = "recaptcha.net"; this.defaultDomain = "google.com"; this.enterpriseApi = "enterprise.js"; this.defaultApi = "api.js"; } registerCaptchaScript(config, render, onLoad, language) { if (isPlatformBrowser(this.platformId)) { if (this.grecaptchaScriptLoaded(config.useEnterprise)) { // recaptcha script is already loaded // just call the callback if (config.useEnterprise) { this.zone.run(() => { onLoad(window[this.windowGrecaptcha][this.windowGrecaptchaEnterprise]); }); } else { this.zone.run(() => { onLoad(window[this.windowGrecaptcha]); }); } return; } // we need to patch the callback through global variable, otherwise callback is not accessible // note: https://github.com/Enngage/ngx-captcha/issues/2 if (config.useEnterprise) { window[this.getCallbackName(true)] = ((() => this.zone.run(onLoad.bind(this, window[this.windowGrecaptcha][this.windowGrecaptchaEnterprise])))); } else { window[this.getCallbackName(false)] = ((() => this.zone.run(onLoad.bind(this, window[this.windowGrecaptcha])))); } // prepare script elem const scriptElem = document.createElement("script"); scriptElem.id = this.scriptElemId; scriptElem.innerHTML = ""; scriptElem.src = this.getCaptchaScriptUrl(config, render, language); scriptElem.async = true; scriptElem.defer = true; // add script to header document.getElementsByTagName("head")[0].appendChild(scriptElem); } } cleanup() { const elem = document.getElementById(this.scriptElemId); if (elem) { elem.remove(); } window[this.getCallbackName()] = undefined; window[this.windowGrecaptcha] = undefined; } /** * Indicates if google recaptcha script is available and ready to be used */ grecaptchaScriptLoaded(useEnterprise) { if (!window[this.getCallbackName(useEnterprise)] || !window[this.windowGrecaptcha]) { return false; } else if (useEnterprise && window[this.windowGrecaptcha][this.windowGrecaptchaEnterprise]) { return true; // if only enterprise script is loaded we need to check some v3's method } else if (window[this.windowGrecaptcha].execute) { return true; } return false; } /** * Gets global callback name * @param useEnterprise Optional flag for enterprise script * @private */ getCallbackName(useEnterprise) { return useEnterprise ? this.windowOnLoadEnterpriseCallbackProperty : this.windowOnLoadCallbackProperty; } /** * Gets language param used in script url */ getLanguageParam(hl) { if (!hl) { return ""; } return `&hl=${hl}`; } /** * Url to google api script */ getCaptchaScriptUrl(config, render, language) { const domain = config.useGlobalDomain ? this.globalDomain : this.defaultDomain; const api = config.useEnterprise ? this.enterpriseApi : this.defaultApi; const callback = this.getCallbackName(config.useEnterprise); return `https://www.${domain}/recaptcha/${api}?onload=${callback}&render=${render}${this.getLanguageParam(language)}`; } } /** @nocollapse */ ScriptService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ScriptService, deps: [{ token: i0.NgZone }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable }); /** @nocollapse */ ScriptService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ScriptService, providedIn: "root" }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: ScriptService, decorators: [{ type: Injectable, args: [{ providedIn: "root", }] }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: Object, decorators: [{ type: Inject, args: [PLATFORM_ID] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NyaXB0LnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL3NlcnZpY2VzL3NjcmlwdC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7O0FBTXhFLE1BQU0sT0FBTyxhQUFhO0lBaUN4QixZQUFzQixJQUFZLEVBQStCLFVBQWtCO1FBQTdELFNBQUksR0FBSixJQUFJLENBQVE7UUFBK0IsZUFBVSxHQUFWLFVBQVUsQ0FBUTtRQWhDbEUsaUJBQVksR0FBVyxvQkFBb0IsQ0FBQztRQUU3RDs7V0FFRztRQUNnQixxQkFBZ0IsR0FBRyxZQUFZLENBQUM7UUFFbkQ7O1dBRUc7UUFDZ0IsK0JBQTBCLEdBQUcsWUFBWSxDQUFDO1FBRTdEOztXQUVHO1FBQ2dCLGlDQUE0QixHQUM3Qyw2QkFBNkIsQ0FBQztRQUVoQzs7V0FFRztRQUNnQiwyQ0FBc0MsR0FDdkQsd0NBQXdDLENBQUM7UUFFeEIsaUJBQVksR0FBVyxlQUFlLENBQUM7UUFFdkMsa0JBQWEsR0FBVyxZQUFZLENBQUM7UUFFckMsa0JBQWEsR0FBVyxlQUFlLENBQUM7UUFFeEMsZUFBVSxHQUFXLFFBQVEsQ0FBQztJQUVzQyxDQUFDO0lBRXhGLHFCQUFxQixDQUNuQixNQUE4QixFQUM5QixNQUFjLEVBQ2QsTUFBaUMsRUFDakMsUUFBaUI7UUFFakIsSUFBSSxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUU7WUFDdEMsSUFBSSxJQUFJLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxFQUFFO2dCQUNyRCxxQ0FBcUM7Z0JBQ3JDLHlCQUF5QjtnQkFDekIsSUFBSSxNQUFNLENBQUMsYUFBYSxFQUFFO29C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OzJCQUFDLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc1BsYXRmb3JtQnJvd3NlciB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcclxuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBOZ1pvbmUsIFBMQVRGT1JNX0lEIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgUmVjYXB0Y2hhQ29uZmlndXJhdGlvbiB9IGZyb20gXCIuLi9tb2RlbHMvcmVjYXB0Y2hhLWNvbmZpZ3VyYXRpb25cIjtcclxuXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiBcInJvb3RcIixcclxufSlcclxuZXhwb3J0IGNsYXNzIFNjcmlwdFNlcnZpY2Uge1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgc2NyaXB0RWxlbUlkOiBzdHJpbmcgPSBcIm5neC1jYXRwY2hhLXNjcmlwdFwiO1xyXG5cclxuICAvKipcclxuICAgKiBOYW1lIG9mIHRoZSBnbG9iYWwgZ29vZ2xlIHJlY2FwdGNoYSBzY3JpcHRcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgd2luZG93R3JlY2FwdGNoYSA9IFwiZ3JlY2FwdGNoYVwiO1xyXG5cclxuICAvKipcclxuICAgKiBOYW1lIG9mIGVudGVycGlzZSBwcm9wZXJ0eSBpbiB0aGUgZ2xvYmFsIGdvb2dsZSByZWNhcHRjaGEgc2NyaXB0XHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHdpbmRvd0dyZWNhcHRjaGFFbnRlcnByaXNlID0gXCJlbnRlcnByaXNlXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIE5hbWUgb2YgdGhlIGdsb2JhbCBjYWxsYmFja1xyXG4gICAqL1xyXG4gIHByb3RlY3RlZCByZWFkb25seSB3aW5kb3dPbkxvYWRDYWxsYmFja1Byb3BlcnR5ID1cclxuICAgIFwibmd4X2NhcHRjaGFfb25sb2FkX2NhbGxiYWNrXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIE5hbWUgb2YgdGhlIGdsb2JhbCBjYWxsYmFjayBmb3IgZW50ZXJwcmlzZVxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCByZWFkb25seSB3aW5kb3dPbkxvYWRFbnRlcnByaXNlQ2FsbGJhY2tQcm9wZXJ0eSA9XHJcbiAgICBcIm5neF9jYXB0Y2hhX29ubG9hZF9lbnRlcnByaXNlX2NhbGxiYWNrXCI7XHJcblxyXG4gIHByb3RlY3RlZCByZWFkb25seSBnbG9iYWxEb21haW46IHN0cmluZyA9IFwicmVjYXB0Y2hhLm5ldFwiO1xyXG5cclxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVmYXVsdERvbWFpbjogc3RyaW5nID0gXCJnb29nbGUuY29tXCI7XHJcblxyXG4gIHByb3RlY3RlZCByZWFkb25seSBlbnRlcnByaXNlQXBpOiBzdHJpbmcgPSBcImVudGVycHJpc2UuanNcIjtcclxuXHJcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IGRlZmF1bHRBcGk6IHN0cmluZyA9IFwiYXBpLmpzXCI7XHJcblxyXG4gIGNvbnN0cnVjdG9yKHByb3RlY3RlZCB6b25lOiBOZ1pvbmUsIEBJbmplY3QoUExBVEZPUk1fSUQpIHByaXZhdGUgcGxhdGZvcm1JZDogT2JqZWN0KSB7IH1cclxuXHJcbiAgcmVnaXN0ZXJDYXB0Y2hhU2NyaXB0KFxyXG4gICAgY29uZmlnOiBSZWNhcHRjaGFDb25maWd1cmF0aW9uLFxyXG4gICAgcmVuZGVyOiBzdHJpbmcsXHJcbiAgICBvbkxvYWQ6IChncmVjYXB0Y2hhOiBhbnkpID0+IHZvaWQsXHJcbiAgICBsYW5ndWFnZT86IHN0cmluZ1xyXG4gICk6IHZvaWQge1xyXG4gICAgaWYgKGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkpIHtcclxuICAgICAgaWYgKHRoaXMuZ3JlY2FwdGNoYVNjcmlwdExvYWRlZChjb25maWcudXNlRW50ZXJwcmlzZSkpIHtcclxuICAgICAgICAvLyByZWNhcHRjaGEgc2NyaXB0IGlzIGFscmVhZHkgbG9hZGVkXHJcbiAgICAgICAgLy8ganVzdCBjYWxsIHRoZSBjYWxsYmFja1xyXG4gICAgICAgIGlmIChjb25maWcudXNlRW50ZXJwcmlzZSkge1xyXG4gICAgICAgICAgdGhpcy56b25lLnJ1bigoKSA9PiB7XHJcbiAgICAgICAgICAgIG9uTG9hZChcclxuICAgICAgICAgICAgICAod2luZG93IGFzIGFueSlbdGhpcy53aW5kb3dHcmVjYXB0Y2hhXVtcclxuICAgICAgICAgICAgICB0aGlzLndpbmRvd0dyZWNhcHRjaGFFbnRlcnByaXNlXHJcbiAgICAgICAgICAgICAgXVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICAgICAgICBvbkxvYWQoKHdpbmRvdyBhcyBhbnkpW3RoaXMud2luZG93R3JlY2FwdGNoYV0pO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gd2UgbmVlZCB0byBwYXRjaCB0aGUgY2FsbGJhY2sgdGhyb3VnaCBnbG9iYWwgdmFyaWFibGUsIG90aGVyd2lzZSBjYWxsYmFjayBpcyBub3QgYWNjZXNzaWJsZVxyXG4gICAgICAvLyBub3RlOiBodHRwczovL2dpdGh1Yi5jb20vRW5uZ2FnZS9uZ3gtY2FwdGNoYS9pc3N1ZXMvMlxyXG4gICAgICBpZiAoY29uZmlnLnVzZUVudGVycHJpc2UpIHtcclxuICAgICAgICAod2luZG93IGFzIGFueSlbdGhpcy5nZXRDYWxsYmFja05hbWUodHJ1ZSldID0gPGFueT4oXHJcbiAgICAgICAgICAoKCkgPT5cclxuICAgICAgICAgICAgdGhpcy56b25lLnJ1bihcclxuICAgICAgICAgICAgICBvbkxvYWQuYmluZChcclxuICAgICAgICAgICAgICAgIHRoaXMsXHJcbiAgICAgICAgICAgICAgICAod2luZG93IGFzIGFueSlbdGhpcy53aW5kb3dHcmVjYXB0Y2hhXVtcclxuICAgICAgICAgICAgICAgIHRoaXMud2luZG93R3JlY2FwdGNoYUVudGVycHJpc2VcclxuICAgICAgICAgICAgICAgIF1cclxuICAgICAgICAgICAgICApXHJcbiAgICAgICAgICAgICkpXHJcbiAgICAgICAgKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAod2luZG93IGFzIGFueSlbdGhpcy5nZXRDYWxsYmFja05hbWUoZmFsc2UpXSA9IDxhbnk+KFxyXG4gICAgICAgICAgKCgpID0+XHJcbiAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oXHJcbiAgICAgICAgICAgICAgb25Mb2FkLmJpbmQodGhpcywgKHdpbmRvdyBhcyBhbnkpW3RoaXMud2luZG93R3JlY2FwdGNoYV0pXHJcbiAgICAgICAgICAgICkpXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gcHJlcGFyZSBzY3JpcHQgZWxlbVxyXG4gICAgICBjb25zdCBzY3JpcHRFbGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNjcmlwdFwiKTtcclxuICAgICAgc2NyaXB0RWxlbS5pZCA9IHRoaXMuc2NyaXB0RWxlbUlkO1xyXG4gICAgICBzY3JpcHRFbGVtLmlubmVySFRNTCA9IFwiXCI7XHJcbiAgICAgIHNjcmlwdEVsZW0uc3JjID0gdGhpcy5nZXRDYXB0Y2hhU2NyaXB0VXJsKGNvbmZpZywgcmVuZGVyLCBsYW5ndWFnZSk7XHJcbiAgICAgIHNjcmlwdEVsZW0uYXN5bmMgPSB0cnVlO1xyXG4gICAgICBzY3JpcHRFbGVtLmRlZmVyID0gdHJ1ZTtcclxuXHJcbiAgICAgIC8vIGFkZCBzY3JpcHQgdG8gaGVhZGVyXHJcbiAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiaGVhZFwiKVswXS5hcHBlbmRDaGlsZChzY3JpcHRFbGVtKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNsZWFudXAoKTogdm9pZCB7XHJcbiAgICBjb25zdCBlbGVtID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5zY3JpcHRFbGVtSWQpO1xyXG5cclxuICAgIGlmIChlbGVtKSB7XHJcbiAgICAgIGVsZW0ucmVtb3ZlKCk7XHJcbiAgICB9XHJcbiAgICAod2luZG93IGFzIGFueSlbdGhpcy5nZXRDYWxsYmFja05hbWUoKV0gPSB1bmRlZmluZWQ7XHJcbiAgICAod2luZG93IGFzIGFueSlbdGhpcy53aW5kb3dHcmVjYXB0Y2hhXSA9IHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluZGljYXRlcyBpZiBnb29nbGUgcmVjYXB0Y2hhIHNjcmlwdCBpcyBhdmFpbGFibGUgYW5kIHJlYWR5IHRvIGJlIHVzZWRcclxuICAgKi9cclxuICBwcml2YXRlIGdyZWNhcHRjaGFTY3JpcHRMb2FkZWQodXNlRW50ZXJwcmlzZT86IGJvb2xlYW4pOiBib29sZWFuIHtcclxuICAgIGlmIChcclxuICAgICAgISh3aW5kb3cgYXMgYW55KVt0aGlzLmdldENhbGxiYWNrTmFtZSh1c2VFbnRlcnByaXNlKV0gfHxcclxuICAgICAgISh3aW5kb3cgYXMgYW55KVt0aGlzLndpbmRvd0dyZWNhcHRjaGFdXHJcbiAgICApIHtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfSBlbHNlIGlmIChcclxuICAgICAgdXNlRW50ZXJwcmlzZSAmJlxyXG4gICAgICAod2luZG93IGFzIGFueSlbdGhpcy53aW5kb3dHcmVjYXB0Y2hhXVt0aGlzLndpbmRvd0dyZWNhcHRjaGFFbnRlcnByaXNlXVxyXG4gICAgKSB7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAvLyBpZiBvbmx5IGVudGVycHJpc2Ugc2NyaXB0IGlzIGxvYWRlZCB3ZSBuZWVkIHRvIGNoZWNrIHNvbWUgdjMncyBtZXRob2RcclxuICAgIH0gZWxzZSBpZiAoKHdpbmRvdyBhcyBhbnkpW3RoaXMud2luZG93R3JlY2FwdGNoYV0uZXhlY3V0ZSkge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgZ2xvYmFsIGNhbGxiYWNrIG5hbWVcclxuICAgKiBAcGFyYW0gdXNlRW50ZXJwcmlzZSBPcHRpb25hbCBmbGFnIGZvciBlbnRlcnByaXNlIHNjcmlwdFxyXG4gICAqIEBwcml2YXRlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBnZXRDYWxsYmFja05hbWUodXNlRW50ZXJwcmlzZT86IGJvb2xlYW4pOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIHVzZUVudGVycHJpc2VcclxuICAgICAgPyB0aGlzLndpbmRvd09uTG9hZEVudGVycHJpc2VDYWxsYmFja1Byb3BlcnR5XHJcbiAgICAgIDogdGhpcy53aW5kb3dPbkxvYWRDYWxsYmFja1Byb3BlcnR5O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBsYW5ndWFnZSBwYXJhbSB1c2VkIGluIHNjcmlwdCB1cmxcclxuICAgKi9cclxuICBwcml2YXRlIGdldExhbmd1YWdlUGFyYW0oaGw/OiBzdHJpbmcpOiBzdHJpbmcge1xyXG4gICAgaWYgKCFobCkge1xyXG4gICAgICByZXR1cm4gXCJcIjtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gYCZobD0ke2hsfWA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcmwgdG8gZ29vZ2xlIGFwaSBzY3JpcHRcclxuICAgKi9cclxuICBwcml2YXRlIGdldENhcHRjaGFTY3JpcHRVcmwoXHJcbiAgICBjb25maWc6IFJlY2FwdGNoYUNvbmZpZ3VyYXRpb24sXHJcbiAgICByZW5kZXI6IHN0cmluZyxcclxuICAgIGxhbmd1YWdlPzogc3RyaW5nXHJcbiAgKTogc3RyaW5nIHtcclxuICAgIGNvbnN0IGRvbWFpbiA9IGNvbmZpZy51c2VHbG9iYWxEb21haW5cclxuICAgICAgPyB0aGlzLmdsb2JhbERvbWFpblxyXG4gICAgICA6IHRoaXMuZGVmYXVsdERvbWFpbjtcclxuICAgIGNvbnN0IGFwaSA9IGNvbmZpZy51c2VFbnRlcnByaXNlID8gdGhpcy5lbnRlcnByaXNlQXBpIDogdGhpcy5kZWZhdWx0QXBpO1xyXG4gICAgY29uc3QgY2FsbGJhY2sgPSB0aGlzLmdldENhbGxiYWNrTmFtZShjb25maWcudXNlRW50ZXJwcmlzZSk7XHJcblxyXG4gICAgcmV0dXJuIGBodHRwczovL3d3dy4ke2RvbWFpbn0vcmVjYXB0Y2hhLyR7YXBpfT9vbmxvYWQ9JHtjYWxsYmFja30mcmVuZGVyPSR7cmVuZGVyfSR7dGhpcy5nZXRMYW5ndWFnZVBhcmFtKFxyXG4gICAgICBsYW5ndWFnZVxyXG4gICAgKX1gO1xyXG4gIH1cclxufVxyXG4iXX0=