recaptcha-v3.service.mjs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { isPlatformBrowser } from "@angular/common";
  2. import { Inject, Injectable, Optional, PLATFORM_ID } from "@angular/core";
  3. import { Subject } from "rxjs";
  4. import { loader } from "./load-script";
  5. import { RECAPTCHA_BASE_URL, RECAPTCHA_LANGUAGE, RECAPTCHA_NONCE, RECAPTCHA_V3_SITE_KEY } from "./tokens";
  6. import * as i0 from "@angular/core";
  7. /**
  8. * The main service for working with reCAPTCHA v3 APIs.
  9. *
  10. * Use the `execute` method for executing a single action, and
  11. * `onExecute` observable for listening to all actions at once.
  12. */
  13. export class ReCaptchaV3Service {
  14. constructor(zone, siteKey,
  15. // eslint-disable-next-line @typescript-eslint/ban-types
  16. platformId, baseUrl, nonce, language) {
  17. /** @internal */
  18. this.onLoadComplete = (grecaptcha) => {
  19. this.grecaptcha = grecaptcha;
  20. if (this.actionBacklog && this.actionBacklog.length > 0) {
  21. this.actionBacklog.forEach(([action, subject]) => this.executeActionWithSubject(action, subject));
  22. this.actionBacklog = undefined;
  23. }
  24. };
  25. this.zone = zone;
  26. this.isBrowser = isPlatformBrowser(platformId);
  27. this.siteKey = siteKey;
  28. this.nonce = nonce;
  29. this.language = language;
  30. this.baseUrl = baseUrl;
  31. this.init();
  32. }
  33. get onExecute() {
  34. if (!this.onExecuteSubject) {
  35. this.onExecuteSubject = new Subject();
  36. this.onExecuteObservable = this.onExecuteSubject.asObservable();
  37. }
  38. return this.onExecuteObservable;
  39. }
  40. get onExecuteError() {
  41. if (!this.onExecuteErrorSubject) {
  42. this.onExecuteErrorSubject = new Subject();
  43. this.onExecuteErrorObservable = this.onExecuteErrorSubject.asObservable();
  44. }
  45. return this.onExecuteErrorObservable;
  46. }
  47. /**
  48. * Executes the provided `action` with reCAPTCHA v3 API.
  49. * Use the emitted token value for verification purposes on the backend.
  50. *
  51. * For more information about reCAPTCHA v3 actions and tokens refer to the official documentation at
  52. * https://developers.google.com/recaptcha/docs/v3.
  53. *
  54. * @param {string} action the action to execute
  55. * @returns {Observable<string>} an `Observable` that will emit the reCAPTCHA v3 string `token` value whenever ready.
  56. * The returned `Observable` completes immediately after emitting a value.
  57. */
  58. execute(action) {
  59. const subject = new Subject();
  60. if (this.isBrowser) {
  61. if (!this.grecaptcha) {
  62. if (!this.actionBacklog) {
  63. this.actionBacklog = [];
  64. }
  65. this.actionBacklog.push([action, subject]);
  66. }
  67. else {
  68. this.executeActionWithSubject(action, subject);
  69. }
  70. }
  71. return subject.asObservable();
  72. }
  73. /** @internal */
  74. executeActionWithSubject(action, subject) {
  75. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  76. const onError = (error) => {
  77. this.zone.run(() => {
  78. subject.error(error);
  79. if (this.onExecuteErrorSubject) {
  80. // We don't know any better at this point, unfortunately, so have to resort to `any`
  81. // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
  82. this.onExecuteErrorSubject.next({ action, error });
  83. }
  84. });
  85. };
  86. this.zone.runOutsideAngular(() => {
  87. try {
  88. this.grecaptcha.execute(this.siteKey, { action }).then((token) => {
  89. this.zone.run(() => {
  90. subject.next(token);
  91. subject.complete();
  92. if (this.onExecuteSubject) {
  93. this.onExecuteSubject.next({ action, token });
  94. }
  95. });
  96. }, onError);
  97. }
  98. catch (e) {
  99. onError(e);
  100. }
  101. });
  102. }
  103. /** @internal */
  104. init() {
  105. if (this.isBrowser) {
  106. if ("grecaptcha" in window) {
  107. this.grecaptcha = grecaptcha;
  108. }
  109. else {
  110. const langParam = this.language ? "&hl=" + this.language : "";
  111. loader.loadScript(this.siteKey, this.onLoadComplete, langParam, this.baseUrl, this.nonce);
  112. }
  113. }
  114. }
  115. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: ReCaptchaV3Service, deps: [{ token: i0.NgZone }, { token: RECAPTCHA_V3_SITE_KEY }, { token: PLATFORM_ID }, { token: RECAPTCHA_BASE_URL, optional: true }, { token: RECAPTCHA_NONCE, optional: true }, { token: RECAPTCHA_LANGUAGE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
  116. static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: ReCaptchaV3Service }); }
  117. }
  118. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: ReCaptchaV3Service, decorators: [{
  119. type: Injectable
  120. }], ctorParameters: function () { return [{ type: i0.NgZone }, { type: undefined, decorators: [{
  121. type: Inject,
  122. args: [RECAPTCHA_V3_SITE_KEY]
  123. }] }, { type: Object, decorators: [{
  124. type: Inject,
  125. args: [PLATFORM_ID]
  126. }] }, { type: undefined, decorators: [{
  127. type: Optional
  128. }, {
  129. type: Inject,
  130. args: [RECAPTCHA_BASE_URL]
  131. }] }, { type: undefined, decorators: [{
  132. type: Optional
  133. }, {
  134. type: Inject,
  135. args: [RECAPTCHA_NONCE]
  136. }] }, { type: undefined, decorators: [{
  137. type: Optional
  138. }, {
  139. type: Inject,
  140. args: [RECAPTCHA_LANGUAGE]
  141. }] }]; } });
  142. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjYXB0Y2hhLXYzLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1yZWNhcHRjaGEvc3JjL2xpYi9yZWNhcHRjaGEtdjMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBVSxRQUFRLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xGLE9BQU8sRUFBYyxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFM0MsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsZUFBZSxFQUFFLHFCQUFxQixFQUFFLE1BQU0sVUFBVSxDQUFDOztBQTJCMUc7Ozs7O0dBS0c7QUFFSCxNQUFNLE9BQU8sa0JBQWtCO0lBMkI3QixZQUNFLElBQVksRUFDbUIsT0FBZTtJQUM5Qyx3REFBd0Q7SUFDbkMsVUFBa0IsRUFDQyxPQUFnQixFQUNuQixLQUFjLEVBQ1gsUUFBaUI7UUFxRzNELGdCQUFnQjtRQUNSLG1CQUFjLEdBQUcsQ0FBQyxVQUFpQyxFQUFFLEVBQUU7WUFDN0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7WUFDN0IsSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDdkQsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLHdCQUF3QixDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO2dCQUNsRyxJQUFJLENBQUMsYUFBYSxHQUFHLFNBQVMsQ0FBQzthQUNoQztR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QUFDLGtCQUFrQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vblwiO1xuaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBOZ1pvbmUsIE9wdGlvbmFsLCBQTEFURk9STV9JRCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSBcInJ4anNcIjtcblxuaW1wb3J0IHsgbG9hZGVyIH0gZnJvbSBcIi4vbG9hZC1zY3JpcHRcIjtcbmltcG9ydCB7IFJFQ0FQVENIQV9CQVNFX1VSTCwgUkVDQVBUQ0hBX0xBTkdVQUdFLCBSRUNBUFRDSEFfTk9OQ0UsIFJFQ0FQVENIQV9WM19TSVRFX0tFWSB9IGZyb20gXCIuL3Rva2Vuc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIE9uRXhlY3V0ZURhdGEge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGFjdGlvbiB0aGF0IGhhcyBiZWVuIGV4ZWN1dGVkLlxuICAgKi9cbiAgYWN0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgdG9rZW4gdGhhdCByZUNBUFRDSEEgdjMgcHJvdmlkZWQgd2hlbiBleGVjdXRpbmcgdGhlIGFjdGlvbi5cbiAgICovXG4gIHRva2VuOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT25FeGVjdXRlRXJyb3JEYXRhIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBhY3Rpb24gdGhhdCBoYXMgYmVlbiBleGVjdXRlZC5cbiAgICovXG4gIGFjdGlvbjogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGVycm9yIHdoaWNoIHdhcyBlbmNvdW50ZXJlZFxuICAgKi9cbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgZXJyb3I6IGFueTtcbn1cblxudHlwZSBBY3Rpb25CYWNrbG9nRW50cnkgPSBbc3RyaW5nLCBTdWJqZWN0PHN0cmluZz5dO1xuXG4vKipcbiAqIFRoZSBtYWluIHNlcnZpY2UgZm9yIHdvcmtpbmcgd2l0aCByZUNBUFRDSEEgdjMgQVBJcy5cbiAqXG4gKiBVc2UgdGhlIGBleGVjdXRlYCBtZXRob2QgZm9yIGV4ZWN1dGluZyBhIHNpbmdsZSBhY3Rpb24sIGFuZFxuICogYG9uRXhlY3V0ZWAgb2JzZXJ2YWJsZSBmb3IgbGlzdGVuaW5nIHRvIGFsbCBhY3Rpb25zIGF0IG9uY2UuXG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBSZUNhcHRjaGFWM1NlcnZpY2Uge1xuICAvKiogQGludGVybmFsICovXG4gIHByaXZhdGUgcmVhZG9ubHkgaXNCcm93c2VyOiBib29sZWFuO1xuICAvKiogQGludGVybmFsICovXG4gIHByaXZhdGUgcmVhZG9ubHkgc2l0ZUtleTogc3RyaW5nO1xuICAvKiogQGludGVybmFsICovXG4gIHByaXZhdGUgcmVhZG9ubHkgem9uZTogTmdab25lO1xuICAvKiogQGludGVybmFsICovXG4gIHByaXZhdGUgYWN0aW9uQmFja2xvZzogQWN0aW9uQmFja2xvZ0VudHJ5W10gfCB1bmRlZmluZWQ7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBub25jZTogc3RyaW5nO1xuICAvKiogQGludGVybmFsICovXG4gIHByaXZhdGUgbGFuZ3VhZ2U/OiBzdHJpbmc7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBiYXNlVXJsOiBzdHJpbmc7XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBncmVjYXB0Y2hhOiBSZUNhcHRjaGFWMi5SZUNhcHRjaGE7XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIG9uRXhlY3V0ZVN1YmplY3Q6IFN1YmplY3Q8T25FeGVjdXRlRGF0YT47XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBvbkV4ZWN1dGVFcnJvclN1YmplY3Q6IFN1YmplY3Q8T25FeGVjdXRlRXJyb3JEYXRhPjtcbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIG9uRXhlY3V0ZU9ic2VydmFibGU6IE9ic2VydmFibGU8T25FeGVjdXRlRGF0YT47XG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBvbkV4ZWN1dGVFcnJvck9ic2VydmFibGU6IE9ic2VydmFibGU8T25FeGVjdXRlRXJyb3JEYXRhPjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICB6b25lOiBOZ1pvbmUsXG4gICAgQEluamVjdChSRUNBUFRDSEFfVjNfU0lURV9LRVkpIHNpdGVLZXk6IHN0cmluZyxcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10eXBlc1xuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHBsYXRmb3JtSWQ6IE9iamVjdCxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KFJFQ0FQVENIQV9CQVNFX1VSTCkgYmFzZVVybD86IHN0cmluZyxcbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KFJFQ0FQVENIQV9OT05DRSkgbm9uY2U/OiBzdHJpbmcsXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChSRUNBUFRDSEFfTEFOR1VBR0UpIGxhbmd1YWdlPzogc3RyaW5nLFxuICApIHtcbiAgICB0aGlzLnpvbmUgPSB6b25lO1xuICAgIHRoaXMuaXNCcm93c2VyID0gaXNQbGF0Zm9ybUJyb3dzZXIocGxhdGZvcm1JZCk7XG4gICAgdGhpcy5zaXRlS2V5ID0gc2l0ZUtleTtcbiAgICB0aGlzLm5vbmNlID0gbm9uY2U7XG4gICAgdGhpcy5sYW5ndWFnZSA9IGxhbmd1YWdlO1xuICAgIHRoaXMuYmFzZVVybCA9IGJhc2VVcmw7XG5cbiAgICB0aGlzLmluaXQoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgb25FeGVjdXRlKCk6IE9ic2VydmFibGU8T25FeGVjdXRlRGF0YT4ge1xuICAgIGlmICghdGhpcy5vbkV4ZWN1dGVTdWJqZWN0KSB7XG4gICAgICB0aGlzLm9uRXhlY3V0ZVN1YmplY3QgPSBuZXcgU3ViamVjdDxPbkV4ZWN1dGVEYXRhPigpO1xuICAgICAgdGhpcy5vbkV4ZWN1dGVPYnNlcnZhYmxlID0gdGhpcy5vbkV4ZWN1dGVTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm9uRXhlY3V0ZU9ic2VydmFibGU7XG4gIH1cblxuICBwdWJsaWMgZ2V0IG9uRXhlY3V0ZUVycm9yKCk6IE9ic2VydmFibGU8T25FeGVjdXRlRXJyb3JEYXRhPiB7XG4gICAgaWYgKCF0aGlzLm9uRXhlY3V0ZUVycm9yU3ViamVjdCkge1xuICAgICAgdGhpcy5vbkV4ZWN1dGVFcnJvclN1YmplY3QgPSBuZXcgU3ViamVjdDxPbkV4ZWN1dGVFcnJvckRhdGE+KCk7XG4gICAgICB0aGlzLm9uRXhlY3V0ZUVycm9yT2JzZXJ2YWJsZSA9IHRoaXMub25FeGVjdXRlRXJyb3JTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm9uRXhlY3V0ZUVycm9yT2JzZXJ2YWJsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlcyB0aGUgcHJvdmlkZWQgYGFjdGlvbmAgd2l0aCByZUNBUFRDSEEgdjMgQVBJLlxuICAgKiBVc2UgdGhlIGVtaXR0ZWQgdG9rZW4gdmFsdWUgZm9yIHZlcmlmaWNhdGlvbiBwdXJwb3NlcyBvbiB0aGUgYmFja2VuZC5cbiAgICpcbiAgICogRm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgcmVDQVBUQ0hBIHYzIGFjdGlvbnMgYW5kIHRva2VucyByZWZlciB0byB0aGUgb2ZmaWNpYWwgZG9jdW1lbnRhdGlvbiBhdFxuICAgKiBodHRwczovL2RldmVsb3BlcnMuZ29vZ2xlLmNvbS9yZWNhcHRjaGEvZG9jcy92My5cbiAgICpcbiAgICogQHBhcmFtIHtzdHJpbmd9IGFjdGlvbiB0aGUgYWN0aW9uIHRvIGV4ZWN1dGVcbiAgICogQHJldHVybnMge09ic2VydmFibGU8c3RyaW5nPn0gYW4gYE9ic2VydmFibGVgIHRoYXQgd2lsbCBlbWl0IHRoZSByZUNBUFRDSEEgdjMgc3RyaW5nIGB0b2tlbmAgdmFsdWUgd2hlbmV2ZXIgcmVhZHkuXG4gICAqIFRoZSByZXR1cm5lZCBgT2JzZXJ2YWJsZWAgY29tcGxldGVzIGltbWVkaWF0ZWx5IGFmdGVyIGVtaXR0aW5nIGEgdmFsdWUuXG4gICAqL1xuICBwdWJsaWMgZXhlY3V0ZShhY3Rpb246IHN0cmluZyk6IE9ic2VydmFibGU8c3RyaW5nPiB7XG4gICAgY29uc3Qgc3ViamVjdCA9IG5ldyBTdWJqZWN0PHN0cmluZz4oKTtcbiAgICBpZiAodGhpcy5pc0Jyb3dzZXIpIHtcbiAgICAgIGlmICghdGhpcy5ncmVjYXB0Y2hhKSB7XG4gICAgICAgIGlmICghdGhpcy5hY3Rpb25CYWNrbG9nKSB7XG4gICAgICAgICAgdGhpcy5hY3Rpb25CYWNrbG9nID0gW107XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmFjdGlvbkJhY2tsb2cucHVzaChbYWN0aW9uLCBzdWJqZWN0XSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmV4ZWN1dGVBY3Rpb25XaXRoU3ViamVjdChhY3Rpb24sIHN1YmplY3QpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBzdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwcml2YXRlIGV4ZWN1dGVBY3Rpb25XaXRoU3ViamVjdChhY3Rpb246IHN0cmluZywgc3ViamVjdDogU3ViamVjdDxzdHJpbmc+KTogdm9pZCB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbiAgICBjb25zdCBvbkVycm9yID0gKGVycm9yOiBhbnkpID0+IHtcbiAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICBzdWJqZWN0LmVycm9yKGVycm9yKTtcbiAgICAgICAgaWYgKHRoaXMub25FeGVjdXRlRXJyb3JTdWJqZWN0KSB7XG4gICAgICAgICAgLy8gV2UgZG9uJ3Qga25vdyBhbnkgYmV0dGVyIGF0IHRoaXMgcG9pbnQsIHVuZm9ydHVuYXRlbHksIHNvIGhhdmUgdG8gcmVzb3J0IHRvIGBhbnlgXG4gICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtYXNzaWdubWVudFxuICAgICAgICAgIHRoaXMub25FeGVjdXRlRXJyb3JTdWJqZWN0Lm5leHQoeyBhY3Rpb24sIGVycm9yIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuZ3JlY2FwdGNoYS5leGVjdXRlKHRoaXMuc2l0ZUtleSwgeyBhY3Rpb24gfSkudGhlbigodG9rZW46IHN0cmluZykgPT4ge1xuICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgc3ViamVjdC5uZXh0KHRva2VuKTtcbiAgICAgICAgICAgIHN1YmplY3QuY29tcGxldGUoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm9uRXhlY3V0ZVN1YmplY3QpIHtcbiAgICAgICAgICAgICAgdGhpcy5vbkV4ZWN1dGVTdWJqZWN0Lm5leHQoeyBhY3Rpb24sIHRva2VuIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9LCBvbkVycm9yKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgb25FcnJvcihlKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBpbml0KCkge1xuICAgIGlmICh0aGlzLmlzQnJvd3Nlcikge1xuICAgICAgaWYgKFwiZ3JlY2FwdGNoYVwiIGluIHdpbmRvdykge1xuICAgICAgICB0aGlzLmdyZWNhcHRjaGEgPSBncmVjYXB0Y2hhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgbGFuZ1BhcmFtID0gdGhpcy5sYW5ndWFnZSA/IFwiJmhsPVwiICsgdGhpcy5sYW5ndWFnZSA6IFwiXCI7XG4gICAgICAgIGxvYWRlci5sb2FkU2NyaXB0KHRoaXMuc2l0ZUtleSwgdGhpcy5vbkxvYWRDb21wbGV0ZSwgbGFuZ1BhcmFtLCB0aGlzLmJhc2VVcmwsIHRoaXMubm9uY2UpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcHJpdmF0ZSBvbkxvYWRDb21wbGV0ZSA9IChncmVjYXB0Y2hhOiBSZUNhcHRjaGFWMi5SZUNhcHRjaGEpID0+IHtcbiAgICB0aGlzLmdyZWNhcHRjaGEgPSBncmVjYXB0Y2hhO1xuICAgIGlmICh0aGlzLmFjdGlvbkJhY2tsb2cgJiYgdGhpcy5hY3Rpb25CYWNrbG9nLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuYWN0aW9uQmFja2xvZy5mb3JFYWNoKChbYWN0aW9uLCBzdWJqZWN0XSkgPT4gdGhpcy5leGVjdXRlQWN0aW9uV2l0aFN1YmplY3QoYWN0aW9uLCBzdWJqZWN0KSk7XG4gICAgICB0aGlzLmFjdGlvbkJhY2tsb2cgPSB1bmRlZmluZWQ7XG4gICAgfVxuICB9O1xufVxuIl19