UNPKG

ngx-captcha

Version:

Dynamic captcha (Google reCaptcha) implementation for Angular

306 lines 34.7 kB
import { Directive, EventEmitter, InjectFlags, Injector, Input, NgZone, Output, Renderer2, } from "@angular/core"; import { NgControl, } from "@angular/forms"; import { ScriptService } from "../services/script.service"; import * as i0 from "@angular/core"; import * as i1 from "../services/script.service"; export class BaseReCaptchaComponentDirective { constructor(renderer, zone, injector, scriptService) { this.renderer = renderer; this.zone = zone; this.injector = injector; this.scriptService = scriptService; /** * Prefix of the captcha element */ this.captchaElemPrefix = "ngx_captcha_id_"; this.setupCaptcha = true; /** * Indicates if global domain 'recaptcha.net' should be used instead of default domain ('google.com') */ this.useGlobalDomain = false; this.useEnterprise = false; /** * Type */ this.type = "image"; /** * Tab index */ this.tabIndex = 0; /** * Called when captcha receives successful response. * Captcha response token is passed to event. */ this.success = new EventEmitter(); /** * Called when captcha is loaded. Event receives id of the captcha */ this.load = new EventEmitter(); /** * Called when captcha is reset. */ this.reset = new EventEmitter(); /** * Called when captcha is loaded & ready. I.e. when you need to execute captcha on component load. */ this.ready = new EventEmitter(); /** * Error callback */ this.error = new EventEmitter(); /** * Expired callback */ this.expire = new EventEmitter(); /** * Indicates if captcha should be set on load */ this.setupAfterLoad = false; /** * If enabled, captcha will reset after receiving success response. This is useful * when invisible captcha need to be resolved multiple times on same page */ this.resetCaptchaAfterSuccess = false; /** * Required by ControlValueAccessor */ this.onChange = (val) => { }; this.onTouched = (val) => { }; /** * Indicates if captcha is loaded */ this.isLoaded = false; } ngAfterViewInit() { this.control = this.injector.get(NgControl, undefined, InjectFlags.Optional)?.control; } ngAfterViewChecked() { if (this.setupCaptcha) { this.setupCaptcha = false; this.setupComponent(); } } ngOnChanges(changes) { // cleanup scripts if language changed because they need to be reloaded if (changes && changes.hl) { // cleanup scripts when language changes if (!changes.hl.firstChange && changes.hl.currentValue !== changes.hl.previousValue) { this.scriptService.cleanup(); } } if (changes && changes.useGlobalDomain) { // cleanup scripts when domain changes if (!changes.useGlobalDomain.firstChange && changes.useGlobalDomain.currentValue !== changes.useGlobalDomain.previousValue) { this.scriptService.cleanup(); } } this.setupCaptcha = true; } /** * Gets captcha response as per reCaptcha docs */ getResponse() { return this.reCaptchaApi.getResponse(this.captchaId); } /** * Gets Id of captcha widget */ getCaptchaId() { return this.captchaId; } /** * Resets captcha */ resetCaptcha() { this.zone.run(() => { // reset captcha using Google js api this.reCaptchaApi.reset(); // required due to forms this.onChange(undefined); this.onTouched(undefined); // trigger reset event this.reset.next(); }); } /** * Gets last submitted captcha response */ getCurrentResponse() { return this.currentResponse; } /** * Reload captcha. Useful when properties (i.e. theme) changed and captcha need to reflect them */ reloadCaptcha() { this.setupComponent(); } ensureCaptchaElem(captchaElemId) { const captchaElem = document.getElementById(captchaElemId); if (!captchaElem) { throw Error(`Captcha element with id '${captchaElemId}' was not found`); } // assign captcha alem this.captchaElem = captchaElem; } /** * Responsible for instantiating captcha element */ renderReCaptcha() { // run outside angular zone due to timeout issues when testing // details: https://github.com/Enngage/ngx-captcha/issues/26 this.zone.runOutsideAngular(() => { // to fix reCAPTCHA placeholder element must be an element or id // https://github.com/Enngage/ngx-captcha/issues/96 setTimeout(() => { this.captchaId = this.reCaptchaApi.render(this.captchaElemId, this.getCaptchaProperties()); this.ready.next(); }, 0); }); } /** * Called when captcha receives response * @param callback Callback */ handleCallback(callback) { this.currentResponse = callback; this.success.next(callback); this.zone.run(() => { this.onChange(callback); this.onTouched(callback); }); if (this.resetCaptchaAfterSuccess) { this.resetCaptcha(); } } getPseudoUniqueNumber() { return new Date().getUTCMilliseconds() + Math.floor(Math.random() * 9999); } setupComponent() { // captcha specific setup this.captchaSpecificSetup(); // create captcha wrapper this.createAndSetCaptchaElem(); this.scriptService.registerCaptchaScript({ useGlobalDomain: this.useGlobalDomain, useEnterprise: this.useEnterprise, }, "explicit", (grecaptcha) => { this.onloadCallback(grecaptcha); }, this.hl); } /** * Called when google's recaptcha script is ready */ onloadCallback(grecapcha) { // assign reference to reCaptcha Api once its loaded this.reCaptchaApi = grecapcha; if (!this.reCaptchaApi) { throw Error(`ReCaptcha Api was not initialized correctly`); } // loaded flag this.isLoaded = true; // fire load event this.load.next(); // render captcha this.renderReCaptcha(); // setup component if it was flagged as such if (this.setupAfterLoad) { this.setupAfterLoad = false; this.setupComponent(); } } generateNewElemId() { return this.captchaElemPrefix + this.getPseudoUniqueNumber(); } createAndSetCaptchaElem() { // generate new captcha id this.captchaElemId = this.generateNewElemId(); if (!this.captchaElemId) { throw Error(`Captcha elem Id is not set`); } if (!this.captchaWrapperElem) { throw Error(`Captcha DOM element is not initialized`); } // remove old html this.captchaWrapperElem.nativeElement.innerHTML = ""; // create new wrapper for captcha const newElem = this.renderer.createElement("div"); newElem.id = this.captchaElemId; this.renderer.appendChild(this.captchaWrapperElem.nativeElement, newElem); // when use captcha in cdk stepper then throwing error Captcha element with id 'ngx_captcha_id_XXXX' not found // to fix it checking ensureCaptchaElem in timeout so that its check in next call and its able to find element setTimeout(() => { // update captcha elem if (this.captchaElemId) { this.ensureCaptchaElem(this.captchaElemId); } }, 0); } /** * To be aligned with the ControlValueAccessor interface we need to implement this method * However as we don't want to update the recaptcha, this doesn't need to be implemented */ writeValue(obj) { } /** * This method helps us tie together recaptcha and our formControl values */ registerOnChange(fn) { this.onChange = fn; } /** * At some point we might be interested whether the user has touched our component */ registerOnTouched(fn) { this.onTouched = fn; } /** * Handles error callback */ handleErrorCallback() { this.zone.run(() => { this.onChange(undefined); this.onTouched(undefined); }); this.error.next(); } /** * Handles expired callback */ handleExpireCallback() { this.expire.next(); // reset captcha on expire callback this.resetCaptcha(); } } /** @nocollapse */ BaseReCaptchaComponentDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: BaseReCaptchaComponentDirective, deps: [{ token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.Injector }, { token: i1.ScriptService }], target: i0.ɵɵFactoryTarget.Directive }); /** @nocollapse */ BaseReCaptchaComponentDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.0.4", type: BaseReCaptchaComponentDirective, inputs: { siteKey: "siteKey", useGlobalDomain: "useGlobalDomain", useEnterprise: "useEnterprise", type: "type", hl: "hl", tabIndex: "tabIndex" }, outputs: { success: "success", load: "load", reset: "reset", ready: "ready", error: "error", expire: "expire" }, usesOnChanges: true, ngImport: i0 }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.0.4", ngImport: i0, type: BaseReCaptchaComponentDirective, decorators: [{ type: Directive }], ctorParameters: function () { return [{ type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.Injector }, { type: i1.ScriptService }]; }, propDecorators: { siteKey: [{ type: Input }], useGlobalDomain: [{ type: Input }], useEnterprise: [{ type: Input }], type: [{ type: Input }], hl: [{ type: Input }], tabIndex: [{ type: Input }], success: [{ type: Output }], load: [{ type: Output }], reset: [{ type: Output }], ready: [{ type: Output }], error: [{ type: Output }], expire: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzZS1yZS1jYXB0Y2hhLWNvbXBvbmVudC5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2NvbXBvbmVudHMvYmFzZS1yZS1jYXB0Y2hhLWNvbXBvbmVudC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUdMLFNBQVMsRUFFVCxZQUFZLEVBQ1osV0FBVyxFQUNYLFFBQVEsRUFDUixLQUFLLEVBQ0wsTUFBTSxFQUVOLE1BQU0sRUFDTixTQUFTLEdBRVYsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUdMLFNBQVMsR0FDVixNQUFNLGdCQUFnQixDQUFDO0FBR3hCLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQzs7O0FBRzNELE1BQU0sT0FBZ0IsK0JBQStCO0lBZ0luRCxZQUNZLFFBQW1CLEVBQ25CLElBQVksRUFDWixRQUFrQixFQUNsQixhQUE0QjtRQUg1QixhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQ25CLFNBQUksR0FBSixJQUFJLENBQVE7UUFDWixhQUFRLEdBQVIsUUFBUSxDQUFVO1FBQ2xCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBakl4Qzs7V0FFRztRQUNnQixzQkFBaUIsR0FBRyxpQkFBaUIsQ0FBQztRQUVqRCxpQkFBWSxHQUFZLElBQUksQ0FBQztRQVFyQzs7V0FFRztRQUNNLG9CQUFlLEdBQVksS0FBSyxDQUFDO1FBRWpDLGtCQUFhLEdBQVksS0FBSyxDQUFDO1FBRXhDOztXQUVHO1FBQ00sU0FBSSxHQUFzQixPQUFPLENBQUM7UUFPM0M7O1dBRUc7UUFDTSxhQUFRLEdBQUcsQ0FBQyxDQUFDO1FBRXRCOzs7V0FHRztRQUNPLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBRS9DOztXQUVHO1FBQ08sU0FBSSxHQUFHLElBQUksWUFBWSxFQUFRLENBQUM7UUFFMUM7O1dBRUc7UUFDTyxVQUFLLEdBQUcsSUFBSSxZ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QUVHO0lBQ0ksaUJBQWlCLENBQUMsRUFBTztRQUM5QixJQUFJLENBQUMsU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQ7O09BRUc7SUFDTyxtQkFBbUI7UUFDM0IsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFO1lBQ2pCLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7WUFDekIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUM1QixDQUFDLENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUVEOztPQUVHO0lBQ08sb0JBQW9CO1FBQzVCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7UUFFbkIsbUNBQW1DO1FBQ25DLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDOzsrSUFyWm1CLCtCQUErQjttSUFBL0IsK0JBQStCOzJGQUEvQiwrQkFBK0I7a0JBRHBELFNBQVM7d0tBZUMsT0FBTztzQkFBZixLQUFLO2dCQUtHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBRUcsYUFBYTtzQkFBckIsS0FBSztnQkFLRyxJQUFJO3NCQUFaLEtBQUs7Z0JBS0csRUFBRTtzQkFBVixLQUFLO2dCQUtHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBTUksT0FBTztzQkFBaEIsTUFBTTtnQkFLRyxJQUFJO3NCQUFiLE1BQU07Z0JBS0csS0FBSztzQkFBZCxNQUFNO2dCQUtHLEtBQUs7c0JBQWQsTUFBTTtnQkFLRyxLQUFLO3NCQUFkLE1BQU07Z0JBS0csTUFBTTtzQkFBZixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBBZnRlclZpZXdDaGVja2VkLFxyXG4gIEFmdGVyVmlld0luaXQsXHJcbiAgRGlyZWN0aXZlLFxyXG4gIEVsZW1lbnRSZWYsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIEluamVjdEZsYWdzLFxyXG4gIEluamVjdG9yLFxyXG4gIElucHV0LFxyXG4gIE5nWm9uZSxcclxuICBPbkNoYW5nZXMsXHJcbiAgT3V0cHV0LFxyXG4gIFJlbmRlcmVyMixcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7XHJcbiAgQWJzdHJhY3RDb250cm9sLFxyXG4gIENvbnRyb2xWYWx1ZUFjY2Vzc29yLFxyXG4gIE5nQ29udHJvbCxcclxufSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcclxuXHJcbmltcG9ydCB7IFJlQ2FwdGNoYVR5cGUgfSBmcm9tIFwiLi4vbW9kZWxzL3JlY2FwdGNoYS10eXBlLmVudW1cIjtcclxuaW1wb3J0IHsgU2NyaXB0U2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlcy9zY3JpcHQuc2VydmljZVwiO1xyXG5cclxuQERpcmVjdGl2ZSgpXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBCYXNlUmVDYXB0Y2hhQ29tcG9uZW50RGlyZWN0aXZlXHJcbiAgaW1wbGVtZW50cyBPbkNoYW5nZXMsIENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBBZnRlclZpZXdJbml0LCBBZnRlclZpZXdDaGVja2VkXHJcbntcclxuICAvKipcclxuICAgKiBQcmVmaXggb2YgdGhlIGNhcHRjaGEgZWxlbWVudFxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCByZWFkb25seSBjYXB0Y2hhRWxlbVByZWZpeCA9IFwibmd4X2NhcHRjaGFfaWRfXCI7XHJcblxyXG4gIHByaXZhdGUgc2V0dXBDYXB0Y2hhOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogR29vZ2xlJ3Mgc2l0ZSBrZXkuXHJcbiAgICogWW91IGNhbiBmaW5kIHRoaXMgdW5kZXIgaHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS9yZWNhcHRjaGFcclxuICAgKi9cclxuICBASW5wdXQoKSBzaXRlS2V5Pzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBJbmRpY2F0ZXMgaWYgZ2xvYmFsIGRvbWFpbiAncmVjYXB0Y2hhLm5ldCcgc2hvdWxkIGJlIHVzZWQgaW5zdGVhZCBvZiBkZWZhdWx0IGRvbWFpbiAoJ2dvb2dsZS5jb20nKVxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIHVzZUdsb2JhbERvbWFpbjogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBASW5wdXQoKSB1c2VFbnRlcnByaXNlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFR5cGVcclxuICAgKi9cclxuICBASW5wdXQoKSB0eXBlOiBcImF1ZGlvXCIgfCBcImltYWdlXCIgPSBcImltYWdlXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIExhbmd1YWdlIGNvZGUuIEF1dG8tZGV0ZWN0cyB0aGUgdXNlcidzIGxhbmd1YWdlIGlmIHVuc3BlY2lmaWVkLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpIGhsPzogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBUYWIgaW5kZXhcclxuICAgKi9cclxuICBASW5wdXQoKSB0YWJJbmRleCA9IDA7XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbGxlZCB3aGVuIGNhcHRjaGEgcmVjZWl2ZXMgc3VjY2Vzc2Z1bCByZXNwb25zZS5cclxuICAgKiBDYXB0Y2hhIHJlc3BvbnNlIHRva2VuIGlzIHBhc3NlZCB0byBldmVudC5cclxuICAgKi9cclxuICBAT3V0cHV0KCkgc3VjY2VzcyA9IG5ldyBFdmVudEVtaXR0ZXI8c3RyaW5nPigpO1xyXG5cclxuICAvKipcclxuICAgKiBDYWxsZWQgd2hlbiBjYXB0Y2hhIGlzIGxvYWRlZC4gRXZlbnQgcmVjZWl2ZXMgaWQgb2YgdGhlIGNhcHRjaGFcclxuICAgKi9cclxuICBAT3V0cHV0KCkgbG9hZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ2FsbGVkIHdoZW4gY2FwdGNoYSBpcyByZXNldC5cclxuICAgKi9cclxuICBAT3V0cHV0KCkgcmVzZXQgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbGxlZCB3aGVuIGNhcHRjaGEgaXMgbG9hZGVkICYgcmVhZHkuIEkuZS4gd2hlbiB5b3UgbmVlZCB0byBleGVjdXRlIGNhcHRjaGEgb24gY29tcG9uZW50IGxvYWQuXHJcbiAgICovXHJcbiAgQE91dHB1dCgpIHJlYWR5ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICAvKipcclxuICAgKiBFcnJvciBjYWxsYmFja1xyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBlcnJvciA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRXhwaXJlZCBjYWxsYmFja1xyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBleHBpcmUgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XHJcblxyXG4gIGFic3RyYWN0IGNhcHRjaGFXcmFwcGVyRWxlbT86IEVsZW1lbnRSZWY7XHJcblxyXG4gIC8qKlxyXG4gICAqIEluZGljYXRlcyBpZiBjYXB0Y2hhIHNob3VsZCBiZSBzZXQgb24gbG9hZFxyXG4gICAqL1xyXG4gIHByaXZhdGUgc2V0dXBBZnRlckxvYWQgPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ2FwdGNoYSBlbGVtZW50XHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIGNhcHRjaGFFbGVtPzogSFRNTEVsZW1lbnQ7XHJcblxyXG4gIC8qKlxyXG4gICAqIElkIG9mIHRoZSBjYXB0Y2hhIGVsZW1cclxuICAgKi9cclxuICBwcm90ZWN0ZWQgY2FwdGNoYUlkPzogbnVtYmVyO1xyXG5cclxuICAvKipcclxuICAgKiBIb2xkcyBsYXN0IHJlc3BvbnNlIHZhbHVlXHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIGN1cnJlbnRSZXNwb25zZT86IHN0cmluZztcclxuXHJcbiAgLyoqXHJcbiAgICogSWYgZW5hYmxlZCwgY2FwdGNoYSB3aWxsIHJlc2V0IGFmdGVyIHJlY2VpdmluZyBzdWNjZXNzIHJlc3BvbnNlLiBUaGlzIGlzIHVzZWZ1bFxyXG4gICAqIHdoZW4gaW52aXNpYmxlIGNhcHRjaGEgbmVlZCB0byBiZSByZXNvbHZlZCBtdWx0aXBsZSB0aW1lcyBvbiBzYW1lIHBhZ2VcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgcmVzZXRDYXB0Y2hhQWZ0ZXJTdWNjZXNzID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIENhcHRjaGEgdHlwZVxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCBhYnN0cmFjdCByZWNhcHRjaGFUeXBlOiBSZUNhcHRjaGFUeXBlO1xyXG5cclxuICAvKipcclxuICAgKiBSZXF1aXJlZCBieSBDb250cm9sVmFsdWVBY2Nlc3NvclxyXG4gICAqL1xyXG4gIHByb3RlY3RlZCBvbkNoYW5nZTogKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpID0+IHZvaWQgPSAodmFsKSA9PiB7fTtcclxuICBwcm90ZWN0ZWQgb25Ub3VjaGVkOiAodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCkgPT4gdm9pZCA9ICh2YWwpID0+IHt9O1xyXG5cclxuICAvKipcclxuICAgKiBJbmRpY2F0ZXMgaWYgY2FwdGNoYSBpcyBsb2FkZWRcclxuICAgKi9cclxuICBwdWJsaWMgaXNMb2FkZWQgPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogUmVmZXJlbmNlIHRvIGdsb2JhbCByZUNhcHRjaGEgQVBJXHJcbiAgICovXHJcbiAgcHVibGljIHJlQ2FwdGNoYUFwaT86IGFueTtcclxuXHJcbiAgLyoqXHJcbiAgICogSWQgb2YgdGhlIERPTSBlbGVtZW50IHdyYXBwaW5nIGNhcHRjaGFcclxuICAgKi9cclxuICBwdWJsaWMgY2FwdGNoYUVsZW1JZD86IHN0cmluZztcclxuXHJcbiAgLyoqXHJcbiAgICogRm9ybSBDb250cm9sIHRvIGJlIGVuYWJsZSB1c2FnZSBpbiByZWFjdGl2ZSBmb3Jtc1xyXG4gICAqL1xyXG4gIHB1YmxpYyBjb250cm9sPzogQWJzdHJhY3RDb250cm9sIHwgbnVsbDtcclxuXHJcbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJvdGVjdGVkIHJlbmRlcmVyOiBSZW5kZXJlcjIsXHJcbiAgICBwcm90ZWN0ZWQgem9uZTogTmdab25lLFxyXG4gICAgcHJvdGVjdGVkIGluamVjdG9yOiBJbmplY3RvcixcclxuICAgIHByb3RlY3RlZCBzY3JpcHRTZXJ2aWNlOiBTY3JpcHRTZXJ2aWNlXHJcbiAgKSB7fVxyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICB0aGlzLmNvbnRyb2wgPSB0aGlzLmluamVjdG9yLmdldDxOZ0NvbnRyb2wgfCB1bmRlZmluZWQ+KFxyXG4gICAgICBOZ0NvbnRyb2wsXHJcbiAgICAgIHVuZGVmaW5lZCxcclxuICAgICAgSW5qZWN0RmxhZ3MuT3B0aW9uYWxcclxuICAgICk/LmNvbnRyb2w7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyVmlld0NoZWNrZWQoKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5zZXR1cENhcHRjaGEpIHtcclxuICAgICAgdGhpcy5zZXR1cENhcHRjaGEgPSBmYWxzZTtcclxuICAgICAgdGhpcy5zZXR1cENvbXBvbmVudCgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyByZUNhcHRjaGEgcHJvcGVydGllc1xyXG4gICAqL1xyXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBnZXRDYXB0Y2hhUHJvcGVydGllcygpOiBhbnk7XHJcblxyXG4gIC8qKlxyXG4gICAqIFVzZWQgZm9yIGNhcHRjaGEgc3BlY2lmaWMgc2V0dXBcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgYWJzdHJhY3QgY2FwdGNoYVNwZWNpZmljU2V0dXAoKTogdm9pZDtcclxuXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xyXG4gICAgLy8gY2xlYW51cCBzY3JpcHRzIGlmIGxhbmd1YWdlIGNoYW5nZWQgYmVjYXVzZSB0aGV5IG5lZWQgdG8gYmUgcmVsb2FkZWRcclxuICAgIGlmIChjaGFuZ2VzICYmIGNoYW5nZXMuaGwpIHtcclxuICAgICAgLy8gY2xlYW51cCBzY3JpcHRzIHdoZW4gbGFuZ3VhZ2UgY2hhbmdlc1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIWNoYW5nZXMuaGwuZmlyc3RDaGFuZ2UgJiZcclxuICAgICAgICBjaGFuZ2VzLmhsLmN1cnJlbnRWYWx1ZSAhPT0gY2hhbmdlcy5obC5wcmV2aW91c1ZhbHVlXHJcbiAgICAgICkge1xyXG4gICAgICAgIHRoaXMuc2NyaXB0U2VydmljZS5jbGVhbnVwKCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAoY2hhbmdlcyAmJiBjaGFuZ2VzLnVzZUdsb2JhbERvbWFpbikge1xyXG4gICAgICAvLyBjbGVhbnVwIHNjcmlwdHMgd2hlbiBkb21haW4gY2hhbmdlc1xyXG4gICAgICBpZiAoXHJcbiAgICAgICAgIWNoYW5nZXMudXNlR2xvYmFsRG9tYWluLmZpcnN0Q2hhbmdlICYmXHJcbiAgICAgICAgY2hhbmdlcy51c2VHbG9iYWxEb21haW4uY3VycmVudFZhbHVlICE9PVxyXG4gICAgICAgICAgY2hhbmdlcy51c2VHbG9iYWxEb21haW4ucHJldmlvdXNWYWx1ZVxyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLnNjcmlwdFNlcnZpY2UuY2xlYW51cCgpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5zZXR1cENhcHRjaGEgPSB0cnVlO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBjYXB0Y2hhIHJlc3BvbnNlIGFzIHBlciByZUNhcHRjaGEgZG9jc1xyXG4gICAqL1xyXG4gIGdldFJlc3BvbnNlKCk6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gdGhpcy5yZUNhcHRjaGFBcGkuZ2V0UmVzcG9uc2UodGhpcy5jYXB0Y2hhSWQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBJZCBvZiBjYXB0Y2hhIHdpZGdldFxyXG4gICAqL1xyXG4gIGdldENhcHRjaGFJZCgpOiBudW1iZXIgfCB1bmRlZmluZWQge1xyXG4gICAgcmV0dXJuIHRoaXMuY2FwdGNoYUlkO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVzZXRzIGNhcHRjaGFcclxuICAgKi9cclxuICByZXNldENhcHRjaGEoKTogdm9pZCB7XHJcbiAgICB0aGlzLnpvbmUucnVuKCgpID0+IHtcclxuICAgICAgLy8gcmVzZXQgY2FwdGNoYSB1c2luZyBHb29nbGUganMgYXBpXHJcbiAgICAgIHRoaXMucmVDYXB0Y2hhQXBpLnJlc2V0KCk7XHJcblxyXG4gICAgICAvLyByZXF1aXJlZCBkdWUgdG8gZm9ybXNcclxuICAgICAgdGhpcy5vbkNoYW5nZSh1bmRlZmluZWQpO1xyXG4gICAgICB0aGlzLm9uVG91Y2hlZCh1bmRlZmluZWQpO1xyXG5cclxuICAgICAgLy8gdHJpZ2dlciByZXNldCBldmVudFxyXG4gICAgICB0aGlzLnJlc2V0Lm5leHQoKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBsYXN0IHN1Ym1pdHRlZCBjYXB0Y2hhIHJlc3BvbnNlXHJcbiAgICovXHJcbiAgZ2V0Q3VycmVudFJlc3BvbnNlKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XHJcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50UmVzcG9uc2U7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZWxvYWQgY2FwdGNoYS4gVXNlZnVsIHdoZW4gcHJvcGVydGllcyAoaS5lLiB0aGVtZSkgY2hhbmdlZCBhbmQgY2FwdGNoYSBuZWVkIHRvIHJlZmxlY3QgdGhlbVxyXG4gICAqL1xyXG4gIHJlbG9hZENhcHRjaGEoKTogdm9pZCB7XHJcbiAgICB0aGlzLnNldHVwQ29tcG9uZW50KCk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgZW5zdXJlQ2FwdGNoYUVsZW0oY2FwdGNoYUVsZW1JZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBjb25zdCBjYXB0Y2hhRWxlbSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGNhcHRjaGFFbGVtSWQpO1xyXG5cclxuICAgIGlmICghY2FwdGNoYUVsZW0pIHtcclxuICAgICAgdGhyb3cgRXJyb3IoYENhcHRjaGEgZWxlbWVudCB3aXRoIGlkICcke2NhcHRjaGFFbGVtSWR9JyB3YXMgbm90IGZvdW5kYCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gYXNzaWduIGNhcHRjaGEgYWxlbVxyXG4gICAgdGhpcy5jYXB0Y2hhRWxlbSA9IGNhcHRjaGFFbGVtO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmVzcG9uc2libGUgZm9yIGluc3RhbnRpYXRpbmcgY2FwdGNoYSBlbGVtZW50XHJcbiAgICovXHJcbiAgcHJvdGVjdGVkIHJlbmRlclJlQ2FwdGNoYSgpOiB2b2lkIHtcclxuICAgIC8vIHJ1biBvdXRzaWRlIGFuZ3VsYXIgem9uZSBkdWUgdG8gdGltZW91dCBpc3N1ZXMgd2hlbiB0ZXN0aW5nXHJcbiAgICAvLyBkZXRhaWxzOiBodHRwczovL2dpdGh1Yi5jb20vRW5uZ2FnZS9uZ3gtY2FwdGNoYS9pc3N1ZXMvMjZcclxuICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XHJcbiAgICAgIC8vIHRvIGZpeCByZUNBUFRDSEEgcGxhY2Vob2xkZXIgZWxlbWVudCBtdXN0IGJlIGFuIGVsZW1lbnQgb3IgaWRcclxuICAgICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL0VubmdhZ2Uvbmd4LWNhcHRjaGEvaXNzdWVzLzk2XHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMuY2FwdGNoYUlkID0gdGhpcy5yZUNhcHRjaGFBcGkucmVuZGVyKFxyXG4gICAgICAgICAgdGhpcy5jYXB0Y2hhRWxlbUlkLFxyXG4gICAgICAgICAgdGhpcy5nZXRDYXB0Y2hhUHJvcGVydGllcygpXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0aGlzLnJlYWR5Lm5leHQoKTtcclxuICAgICAgfSwgMCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENhbGxlZCB3aGVuIGNhcHRjaGEgcmVjZWl2ZXMgcmVzcG9uc2VcclxuICAgKiBAcGFyYW0gY2FsbGJhY2sgQ2FsbGJhY2tcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgaGFuZGxlQ2FsbGJhY2soY2FsbGJhY2s6IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5jdXJyZW50UmVzcG9uc2UgPSBjYWxsYmFjaztcclxuICAgIHRoaXMuc3VjY2Vzcy5uZXh0KGNhbGxiYWNrKTtcclxuXHJcbiAgICB0aGlzLnpvbmUucnVuKCgpID0+IHtcclxuICAgICAgdGhpcy5vbkNoYW5nZShjYWxsYmFjayk7XHJcbiAgICAgIHRoaXMub25Ub3VjaGVkKGNhbGxiYWNrKTtcclxuICAgIH0pO1xyXG5cclxuICAgIGlmICh0aGlzLnJlc2V0Q2FwdGNoYUFmdGVyU3VjY2Vzcykge1xyXG4gICAgICB0aGlzLnJlc2V0Q2FwdGNoYSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRQc2V1ZG9VbmlxdWVOdW1iZXIoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBuZXcgRGF0ZSgpLmdldFVUQ01pbGxpc2Vjb25kcygpICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogOTk5OSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNldHVwQ29tcG9uZW50KCk6IHZvaWQge1xyXG4gICAgLy8gY2FwdGNoYSBzcGVjaWZpYyBzZXR1cFxyXG4gICAgdGhpcy5jYXB0Y2hhU3BlY2lmaWNTZXR1cCgpO1xyXG5cclxuICAgIC8vIGNyZWF0ZSBjYXB0Y2hhIHdyYXBwZXJcclxuICAgIHRoaXMuY3JlYXRlQW5kU2V0Q2FwdGNoYUVsZW0oKTtcclxuXHJcbiAgICB0aGlzLnNjcmlwdFNlcnZpY2UucmVnaXN0ZXJDYXB0Y2hhU2NyaXB0KFxyXG4gICAgICB7XHJcbiAgICAgICAgdXNlR2xvYmFsRG9tYWluOiB0aGlzLnVzZUdsb2JhbERvbWFpbixcclxuICAgICAgICB1c2VFbnRlcnByaXNlOiB0aGlzLnVzZUVudGVycHJpc2UsXHJcbiAgICAgIH0sXHJcbiAgICAgIFwiZXhwbGljaXRcIixcclxuICAgICAgKGdyZWNhcHRjaGEpID0+IHtcclxuICAgICAgICB0aGlzLm9ubG9hZENhbGxiYWNrKGdyZWNhcHRjaGEpO1xyXG4gICAgICB9LFxyXG4gICAgICB0aGlzLmhsXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ2FsbGVkIHdoZW4gZ29vZ2xlJ3MgcmVjYXB0Y2hhIHNjcmlwdCBpcyByZWFkeVxyXG4gICAqL1xyXG4gIHByaXZhdGUgb25sb2FkQ2FsbGJhY2soZ3JlY2FwY2hhOiBhbnkpOiB2b2lkIHtcclxuICAgIC8vIGFzc2lnbiByZWZlcmVuY2UgdG8gcmVDYXB0Y2hhIEFwaSBvbmNlIGl0cyBsb2FkZWRcclxuICAgIHRoaXMucmVDYXB0Y2hhQXBpID0gZ3JlY2FwY2hhO1xyXG5cclxuICAgIGlmICghdGhpcy5yZUNhcHRjaGFBcGkpIHtcclxuICAgICAgdGhyb3cgRXJyb3IoYFJlQ2FwdGNoYSBBcGkgd2FzIG5vdCBpbml0aWFsaXplZCBjb3JyZWN0bHlgKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBsb2FkZWQgZmxhZ1xyXG4gICAgdGhpcy5pc0xvYWRlZCA9IHRydWU7XHJcblxyXG4gICAgLy8gZmlyZSBsb2FkIGV2ZW50XHJcbiAgICB0aGlzLmxvYWQubmV4dCgpO1xyXG5cclxuICAgIC8vIHJlbmRlciBjYXB0Y2hhXHJcbiAgICB0aGlzLnJlbmRlclJlQ2FwdGNoYSgpO1xyXG5cclxuICAgIC8vIHNldHVwIGNvbXBvbmVudCBpZiBpdCB3YXMgZmxhZ2dlZCBhcyBzdWNoXHJcbiAgICBpZiAodGhpcy5zZXR1cEFmdGVyTG9hZCkge1xyXG4gICAgICB0aGlzLnNldHVwQWZ0ZXJMb2FkID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuc2V0dXBDb21wb25lbnQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2VuZXJhdGVOZXdFbGVtSWQoKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0aGlzLmNhcHRjaGFFbGVtUHJlZml4ICsgdGhpcy5nZXRQc2V1ZG9VbmlxdWVOdW1iZXIoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgY3JlYXRlQW5kU2V0Q2FwdGNoYUVsZW0oKTogdm9pZCB7XHJcbiAgICAvLyBnZW5lcmF0ZSBuZXcgY2FwdGNoYSBpZFxyXG4gICAgdGhpcy5jYXB0Y2hhRWxlbUlkID0gdGhpcy5nZW5lcmF0ZU5ld0VsZW1JZCgpO1xyXG5cclxuICAgIGlmICghdGhpcy5jYXB0Y2hhRWxlbUlkKSB7XHJcbiAgICAgIHRocm93IEVycm9yKGBDYXB0Y2hhIGVsZW0gSWQgaXMgbm90IHNldGApO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdGhpcy5jYXB0Y2hhV3JhcHBlckVsZW0pIHtcclxuICAgICAgdGhyb3cgRXJyb3IoYENhcHRjaGEgRE9NIGVsZW1lbnQgaXMgbm90IGluaXRpYWxpemVkYCk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gcmVtb3ZlIG9sZCBodG1sXHJcbiAgICB0aGlzLmNhcHRjaGFXcmFwcGVyRWxlbS5uYXRpdmVFbGVtZW50LmlubmVySFRNTCA9IFwiXCI7XHJcblxyXG4gICAgLy8gY3JlYXRlIG5ldyB3cmFwcGVyIGZvciBjYXB0Y2hhXHJcbiAgICBjb25zdCBuZXdFbGVtID0gdGhpcy5yZW5kZXJlci5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xyXG4gICAgbmV3RWxlbS5pZCA9IHRoaXMuY2FwdGNoYUVsZW1JZDtcclxuXHJcbiAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKHRoaXMuY2FwdGNoYVdyYXBwZXJFbGVtLm5hdGl2ZUVsZW1lbnQsIG5ld0VsZW0pO1xyXG5cclxuICAgIC8vIHdoZW4gdXNlIGNhcHRjaGEgaW4gY2RrIHN0ZXBwZXIgdGhlbiB0aHJvd2luZyBlcnJvciBDYXB0Y2hhIGVsZW1lbnQgd2l0aCBpZCAnbmd4X2NhcHRjaGFfaWRfWFhYWCcgbm90IGZvdW5kXHJcbiAgICAvLyB0byBmaXggaXQgY2hlY2tpbmcgZW5zdXJlQ2FwdGNoYUVsZW0gaW4gdGltZW91dCBzbyB0aGF0IGl0cyBjaGVjayBpbiBuZXh0IGNhbGwgYW5kIGl0cyBhYmxlIHRvIGZpbmQgZWxlbWVudFxyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIC8vIHVwZGF0ZSBjYXB0Y2hhIGVsZW1cclxuICAgICAgaWYgKHRoaXMuY2FwdGNoYUVsZW1JZCkge1xyXG4gICAgICAgIHRoaXMuZW5zdXJlQ2FwdGNoYUVsZW0odGhpcy5jYXB0Y2hhRWxlbUlkKTtcclxuICAgICAgfVxyXG4gICAgfSwgMCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUbyBiZSBhbGlnbmVkIHdpdGggdGhlIENvbnRyb2xWYWx1ZUFjY2Vzc29yIGludGVyZmFjZSB3ZSBuZWVkIHRvIGltcGxlbWVudCB0aGlzIG1ldGhvZFxyXG4gICAqIEhvd2V2ZXIgYXMgd2UgZG9uJ3Qgd2FudCB0byB1cGRhdGUgdGhlIHJlY2FwdGNoYSwgdGhpcyBkb2Vzbid0IG5lZWQgdG8gYmUgaW1wbGVtZW50ZWRcclxuICAgKi9cclxuICBwdWJsaWMgd3JpdGVWYWx1ZShvYmo6IGFueSk6IHZvaWQge31cclxuXHJcbiAgLyoqXHJcbiAgICogVGhpcyBtZXRob2QgaGVscHMgdXMgdGllIHRvZ2V0aGVyIHJlY2FwdGNoYSBhbmQgb3VyIGZvcm1Db250cm9sIHZhbHVlc1xyXG4gICAqL1xyXG4gIHB1YmxpYyByZWdpc3Rlck9uQ2hhbmdlKGZuOiBhbnkpOiB2b2lkIHtcclxuICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEF0IHNvbWUgcG9pbnQgd2UgbWlnaHQgYmUgaW50ZXJlc3RlZCB3aGV0aGVyIHRoZSB1c2VyIGhhcyB0b3VjaGVkIG91ciBjb21wb25lbnRcclxuICAgKi9cclxuICBwdWJsaWMgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xyXG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZXMgZXJyb3IgY2FsbGJhY2tcclxuICAgKi9cclxuICBwcm90ZWN0ZWQgaGFuZGxlRXJyb3JDYWxsYmFjaygpOiB2b2lkIHtcclxuICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xyXG4gICAgICB0aGlzLm9uQ2hhbmdlKHVuZGVmaW5lZCk7XHJcbiAgICAgIHRoaXMub25Ub3VjaGVkKHVuZGVmaW5lZCk7XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLmVycm9yLm5leHQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEhhbmRsZXMgZXhwaXJlZCBjYWxsYmFja1xyXG4gICAqL1xyXG4gIHByb3RlY3RlZCBoYW5kbGVFeHBpcmVDYWxsYmFjaygpOiB2b2lkIHtcclxuICAgIHRoaXMuZXhwaXJlLm5leHQoKTtcclxuXHJcbiAgICAvLyByZXNldCBjYXB0Y2hhIG9uIGV4cGlyZSBjYWxsYmFja1xyXG4gICAgdGhpcy5yZXNldENhcHRjaGEoKTtcclxuICB9XHJcbn1cclxuIl19