UNPKG

slr-angularx-social-login

Version:

Social login and authentication module for Angular 13. Supports authentication with Google, Facebook, Amazon, and VK. Can be extended to other providers also.

191 lines 24.1 kB
import { Inject, Injectable } from '@angular/core'; import { AsyncSubject, ReplaySubject } from 'rxjs'; import { GoogleLoginProvider } from './providers/google-login-provider'; import * as i0 from "@angular/core"; /** * The service encapsulating the social login functionality. Exposes methods like * `signIn`, `signOut`. Also, exposes an `authState` `Observable` that one can * subscribe to get the current logged in user information. * * @dynamic */ export class SocialAuthService { /** * @param config A `SocialAuthServiceConfig` object or a `Promise` that resolves to a `SocialAuthServiceConfig` object */ constructor(config) { this.providers = new Map(); this.autoLogin = false; this._user = null; this._authState = new ReplaySubject(1); /* Consider making this an enum comprising LOADING, LOADED, FAILED etc. */ this.initialized = false; this._initState = new AsyncSubject(); if (config instanceof Promise) { config.then((config) => { this.initialize(config); }); } else { this.initialize(config); } } /** An `Observable` that one can subscribe to get the current logged in user information */ get authState() { return this._authState.asObservable(); } /** An `Observable` to communicate the readiness of the service and associated login providers */ get initState() { return this._initState.asObservable(); } initialize(config) { this.autoLogin = config.autoLogin !== undefined ? config.autoLogin : false; const { onError = console.error } = config; config.providers.forEach((item) => { this.providers.set(item.id, item.provider); }); Promise.all(Array.from(this.providers.values()).map((provider) => provider.initialize())) .then(() => { if (this.autoLogin) { const loginStatusPromises = []; let loggedIn = false; this.providers.forEach((provider, key) => { let promise = provider.getLoginStatus(); loginStatusPromises.push(promise); promise .then((user) => { user.provider = key; this._user = user; this._authState.next(user); loggedIn = true; }) .catch(console.debug); }); Promise.all(loginStatusPromises).catch(() => { if (!loggedIn) { this._user = null; this._authState.next(null); } }); } }) .catch((error) => { onError(error); }) .finally(() => { this.initialized = true; this._initState.next(this.initialized); this._initState.complete(); }); } refreshAuthToken(providerId) { return new Promise((resolve, reject) => { if (!this.initialized) { reject(SocialAuthService.ERR_NOT_INITIALIZED); } else if (providerId !== GoogleLoginProvider.PROVIDER_ID) { reject(SocialAuthService.ERR_NOT_SUPPORTED_FOR_REFRESH_TOKEN); } else { const providerObject = this.providers.get(providerId); if (providerObject) { providerObject .getLoginStatus({ refreshToken: true }) .then((user) => { user.provider = providerId; this._user = user; this._authState.next(user); resolve(); }) .catch((err) => { reject(err); }); } else { reject(SocialAuthService.ERR_LOGIN_PROVIDER_NOT_FOUND); } } }); } /** * A method used to sign in a user with a specific `LoginProvider`. * * @param providerId Id with which the `LoginProvider` has been registered with the service * @param signInOptions Optional `LoginProvider` specific arguments * @returns A `Promise` that resolves to the authenticated user information */ signIn(providerId, signInOptions) { return new Promise((resolve, reject) => { if (!this.initialized) { reject(SocialAuthService.ERR_NOT_INITIALIZED); } else { let providerObject = this.providers.get(providerId); if (providerObject) { providerObject .signIn(signInOptions) .then((user) => { user.provider = providerId; resolve(user); this._user = user; this._authState.next(user); }) .catch((err) => { reject(err); }); } else { reject(SocialAuthService.ERR_LOGIN_PROVIDER_NOT_FOUND); } } }); } /** * A method used to sign out the currently loggen in user. * * @param revoke Optional parameter to specify whether a hard sign out is to be performed * @returns A `Promise` that resolves if the operation is successful, rejects otherwise */ signOut(revoke = false) { return new Promise((resolve, reject) => { if (!this.initialized) { reject(SocialAuthService.ERR_NOT_INITIALIZED); } else if (!this._user) { reject(SocialAuthService.ERR_NOT_LOGGED_IN); } else { let providerId = this._user.provider; let providerObject = this.providers.get(providerId); if (providerObject) { providerObject .signOut(revoke) .then(() => { resolve(); this._user = null; this._authState.next(null); }) .catch((err) => { reject(err); }); } else { reject(SocialAuthService.ERR_LOGIN_PROVIDER_NOT_FOUND); } } }); } } SocialAuthService.ERR_LOGIN_PROVIDER_NOT_FOUND = 'Login provider not found'; SocialAuthService.ERR_NOT_LOGGED_IN = 'Not logged in'; SocialAuthService.ERR_NOT_INITIALIZED = 'Login providers not ready yet. Are there errors on your console?'; SocialAuthService.ERR_NOT_SUPPORTED_FOR_REFRESH_TOKEN = 'Chosen login provider is not supported for refreshing a token'; SocialAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: SocialAuthService, deps: [{ token: 'SocialAuthServiceConfig' }], target: i0.ɵɵFactoryTarget.Injectable }); SocialAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: SocialAuthService }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: SocialAuthService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: undefined, decorators: [{ type: Inject, args: ['SocialAuthServiceConfig'] }] }]; } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic29jaWFsYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcHJvamVjdHMvbGliL3NyYy9zb2NpYWxhdXRoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDbkQsT0FBTyxFQUFFLFlBQVksRUFBYyxhQUFhLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFHL0QsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7O0FBV3hFOzs7Ozs7R0FNRztBQUVILE1BQU0sT0FBTyxpQkFBaUI7SUE2QjVCOztPQUVHO0lBQ0gsWUFFRSxNQUFrRTtRQXpCNUQsY0FBUyxHQUErQixJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2xELGNBQVMsR0FBRyxLQUFLLENBQUM7UUFFbEIsVUFBSyxHQUFlLElBQUksQ0FBQztRQUN6QixlQUFVLEdBQThCLElBQUksYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRXJFLDBFQUEwRTtRQUNsRSxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUNwQixlQUFVLEdBQTBCLElBQUksWUFBWSxFQUFFLENBQUM7UUFtQjdELElBQUksTUFBTSxZQUFZLE9BQU8sRUFBRTtZQUM3QixNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7Z0JBQ3JCLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDMUIsQ0FBQyxDQUFDLENBQUM7U0FDSjthQUFNO1lBQ0wsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUN6QjtJQUNILENBQUM7SUF4QkQsMkZBQTJGO0lBQzNGLElBQUksU0FBUztRQUNYLE9BQU8sSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0lBRUQsaUdBQWlHO0lBQ2pHLElBQUksU0FBUztRQUNYLE9B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SSxDQUFDLEdBQUcsRUFBRTt3QkFDVCxPQUFPLEVBQUUsQ0FBQzt3QkFFVixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQzt3QkFDbEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQzdCLENBQUMsQ0FBQzt5QkFDRCxLQUFLLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTt3QkFDYixNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7b0JBQ2QsQ0FBQyxDQUFDLENBQUM7aUJBQ047cUJBQU07b0JBQ0wsTUFBTSxDQUFDLGlCQUFpQixDQUFDLDRCQUE0QixDQUFDLENBQUM7aUJBQ3hEO2FBQ0Y7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7O0FBekx1Qiw4Q0FBNEIsR0FDbEQsMEJBQTJCLENBQUE7QUFDTCxtQ0FBaUIsR0FBRyxlQUFnQixDQUFBO0FBQ3BDLHFDQUFtQixHQUN6QyxrRUFBbUUsQ0FBQTtBQUM3QyxxREFBbUMsR0FDekQsK0RBQWdFLENBQUE7OEdBUHZELGlCQUFpQixrQkFpQ2xCLHlCQUF5QjtrSEFqQ3hCLGlCQUFpQjsyRkFBakIsaUJBQWlCO2tCQUQ3QixVQUFVOzswQkFrQ04sTUFBTTsyQkFBQyx5QkFBeUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEFzeW5jU3ViamVjdCwgT2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTG9naW5Qcm92aWRlciB9IGZyb20gJy4vZW50aXRpZXMvbG9naW4tcHJvdmlkZXInO1xuaW1wb3J0IHsgU29jaWFsVXNlciB9IGZyb20gJy4vZW50aXRpZXMvc29jaWFsLXVzZXInO1xuaW1wb3J0IHsgR29vZ2xlTG9naW5Qcm92aWRlciB9IGZyb20gJy4vcHJvdmlkZXJzL2dvb2dsZS1sb2dpbi1wcm92aWRlcic7XG5cbi8qKlxuICogQW4gaW50ZXJmYWNlIHRvIGRlZmluZSB0aGUgc2hhcGUgb2YgdGhlIHNlcnZpY2UgY29uZmlndXJhdGlvbiBvcHRpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNvY2lhbEF1dGhTZXJ2aWNlQ29uZmlnIHtcbiAgYXV0b0xvZ2luPzogYm9vbGVhbjtcbiAgcHJvdmlkZXJzOiB7IGlkOiBzdHJpbmc7IHByb3ZpZGVyOiBMb2dpblByb3ZpZGVyIH1bXTtcbiAgb25FcnJvcj86IChlcnJvcjogYW55KSA9PiBhbnk7XG59XG5cbi8qKlxuICogVGhlIHNlcnZpY2UgZW5jYXBzdWxhdGluZyB0aGUgc29jaWFsIGxvZ2luIGZ1bmN0aW9uYWxpdHkuIEV4cG9zZXMgbWV0aG9kcyBsaWtlXG4gKiBgc2lnbkluYCwgYHNpZ25PdXRgLiBBbHNvLCBleHBvc2VzIGFuIGBhdXRoU3RhdGVgIGBPYnNlcnZhYmxlYCB0aGF0IG9uZSBjYW5cbiAqIHN1YnNjcmliZSB0byBnZXQgdGhlIGN1cnJlbnQgbG9nZ2VkIGluIHVzZXIgaW5mb3JtYXRpb24uXG4gKlxuICogQGR5bmFtaWNcbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFNvY2lhbEF1dGhTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgRVJSX0xPR0lOX1BST1ZJREVSX05PVF9GT1VORCA9XG4gICAgJ0xvZ2luIHByb3ZpZGVyIG5vdCBmb3VuZCc7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IEVSUl9OT1RfTE9HR0VEX0lOID0gJ05vdCBsb2dnZWQgaW4nO1xuICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBFUlJfTk9UX0lOSVRJQUxJWkVEID1cbiAgICAnTG9naW4gcHJvdmlkZXJzIG5vdCByZWFkeSB5ZXQuIEFyZSB0aGVyZSBlcnJvcnMgb24geW91ciBjb25zb2xlPyc7XG4gIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IEVSUl9OT1RfU1VQUE9SVEVEX0ZPUl9SRUZSRVNIX1RPS0VOID1cbiAgICAnQ2hvc2VuIGxvZ2luIHByb3ZpZGVyIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHJlZnJlc2hpbmcgYSB0b2tlbic7XG5cbiAgcHJpdmF0ZSBwcm92aWRlcnM6IE1hcDxzdHJpbmcsIExvZ2luUHJvdmlkZXI+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIGF1dG9Mb2dpbiA9IGZhbHNlO1xuXG4gIHByaXZhdGUgX3VzZXI6IFNvY2lhbFVzZXIgPSBudWxsO1xuICBwcml2YXRlIF9hdXRoU3RhdGU6IFJlcGxheVN1YmplY3Q8U29jaWFsVXNlcj4gPSBuZXcgUmVwbGF5U3ViamVjdCgxKTtcblxuICAvKiBDb25zaWRlciBtYWtpbmcgdGhpcyBhbiBlbnVtIGNvbXByaXNpbmcgTE9BRElORywgTE9BREVELCBGQUlMRUQgZXRjLiAqL1xuICBwcml2YXRlIGluaXRpYWxpemVkID0gZmFsc2U7XG4gIHByaXZhdGUgX2luaXRTdGF0ZTogQXN5bmNTdWJqZWN0PGJvb2xlYW4+ID0gbmV3IEFzeW5jU3ViamVjdCgpO1xuXG4gIC8qKiBBbiBgT2JzZXJ2YWJsZWAgdGhhdCBvbmUgY2FuIHN1YnNjcmliZSB0byBnZXQgdGhlIGN1cnJlbnQgbG9nZ2VkIGluIHVzZXIgaW5mb3JtYXRpb24gKi9cbiAgZ2V0IGF1dGhTdGF0ZSgpOiBPYnNlcnZhYmxlPFNvY2lhbFVzZXI+IHtcbiAgICByZXR1cm4gdGhpcy5fYXV0aFN0YXRlLmFzT2JzZXJ2YWJsZSgpO1xuICB9XG5cbiAgLyoqIEFuIGBPYnNlcnZhYmxlYCB0byBjb21tdW5pY2F0ZSB0aGUgcmVhZGluZXNzIG9mIHRoZSBzZXJ2aWNlIGFuZCBhc3NvY2lhdGVkIGxvZ2luIHByb3ZpZGVycyAqL1xuICBnZXQgaW5pdFN0YXRlKCk6IE9ic2VydmFibGU8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLl9pbml0U3RhdGUuYXNPYnNlcnZhYmxlKCk7XG4gIH1cblxuICAvKipcbiAgICogQHBhcmFtIGNvbmZpZyBBIGBTb2NpYWxBdXRoU2VydmljZUNvbmZpZ2Agb2JqZWN0IG9yIGEgYFByb21pc2VgIHRoYXQgcmVzb2x2ZXMgdG8gYSBgU29jaWFsQXV0aFNlcnZpY2VDb25maWdgIG9iamVjdFxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdCgnU29jaWFsQXV0aFNlcnZpY2VDb25maWcnKVxuICAgIGNvbmZpZzogU29jaWFsQXV0aFNlcnZpY2VDb25maWcgfCBQcm9taXNlPFNvY2lhbEF1dGhTZXJ2aWNlQ29uZmlnPlxuICApIHtcbiAgICBpZiAoY29uZmlnIGluc3RhbmNlb2YgUHJvbWlzZSkge1xuICAgICAgY29uZmlnLnRoZW4oKGNvbmZpZykgPT4ge1xuICAgICAgICB0aGlzLmluaXRpYWxpemUoY29uZmlnKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmluaXRpYWxpemUoY29uZmlnKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluaXRpYWxpemUoY29uZmlnOiBTb2NpYWxBdXRoU2VydmljZUNvbmZpZykge1xuICAgIHRoaXMuYXV0b0xvZ2luID0gY29uZmlnLmF1dG9Mb2dpbiAhPT0gdW5kZWZpbmVkID8gY29uZmlnLmF1dG9Mb2dpbiA6IGZhbHNlO1xuICAgIGNvbnN0IHsgb25FcnJvciA9IGNvbnNvbGUuZXJyb3IgfSA9IGNvbmZpZztcblxuICAgIGNvbmZpZy5wcm92aWRlcnMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgdGhpcy5wcm92aWRlcnMuc2V0KGl0ZW0uaWQsIGl0ZW0ucHJvdmlkZXIpO1xuICAgIH0pO1xuXG4gICAgUHJvbWlzZS5hbGwoXG4gICAgICBBcnJheS5mcm9tKHRoaXMucHJvdmlkZXJzLnZhbHVlcygpKS5tYXAoKHByb3ZpZGVyKSA9PlxuICAgICAgICBwcm92aWRlci5pbml0aWFsaXplKClcbiAgICAgIClcbiAgICApXG4gICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgIGlmICh0aGlzLmF1dG9Mb2dpbikge1xuICAgICAgICAgIGNvbnN0IGxvZ2luU3RhdHVzUHJvbWlzZXMgPSBbXTtcbiAgICAgICAgICBsZXQgbG9nZ2VkSW4gPSBmYWxzZTtcblxuICAgICAgICAgIHRoaXMucHJvdmlkZXJzLmZvckVhY2goKHByb3ZpZGVyOiBMb2dpblByb3ZpZGVyLCBrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgbGV0IHByb21pc2UgPSBwcm92aWRlci5nZXRMb2dpblN0YXR1cygpO1xuICAgICAgICAgICAgbG9naW5TdGF0dXNQcm9taXNlcy5wdXNoKHByb21pc2UpO1xuICAgICAgICAgICAgcHJvbWlzZVxuICAgICAgICAgICAgICAudGhlbigodXNlcjogU29jaWFsVXNlcikgPT4ge1xuICAgICAgICAgICAgICAgIHVzZXIucHJvdmlkZXIgPSBrZXk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLl91c2VyID0gdXNlcjtcbiAgICAgICAgICAgICAgICB0aGlzLl9hdXRoU3RhdGUubmV4dCh1c2VyKTtcbiAgICAgICAgICAgICAgICBsb2dnZWRJbiA9IHRydWU7XG4gICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgIC5jYXRjaChjb25zb2xlLmRlYnVnKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBQcm9taXNlLmFsbChsb2dpblN0YXR1c1Byb21pc2VzKS5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIWxvZ2dlZEluKSB7XG4gICAgICAgICAgICAgIHRoaXMuX3VzZXIgPSBudWxsO1xuICAgICAgICAgICAgICB0aGlzLl9hdXRoU3RhdGUubmV4dChudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgb25FcnJvcihlcnJvcik7XG4gICAgICB9KVxuICAgICAgLmZpbmFsbHkoKCkgPT4ge1xuICAgICAgICB0aGlzLmluaXRpYWxpemVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5faW5pdFN0YXRlLm5leHQodGhpcy5pbml0aWFsaXplZCk7XG4gICAgICAgIHRoaXMuX2luaXRTdGF0ZS5jb21wbGV0ZSgpO1xuICAgICAgfSk7XG4gIH1cblxuICByZWZyZXNoQXV0aFRva2VuKHByb3ZpZGVySWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgcmVqZWN0KFNvY2lhbEF1dGhTZXJ2aWNlLkVSUl9OT1RfSU5JVElBTElaRUQpO1xuICAgICAgfSBlbHNlIGlmIChwcm92aWRlcklkICE9PSBHb29nbGVMb2dpblByb3ZpZGVyLlBST1ZJREVSX0lEKSB7XG4gICAgICAgIHJlamVjdChTb2NpYWxBdXRoU2VydmljZS5FUlJfTk9UX1NVUFBPUlRFRF9GT1JfUkVGUkVTSF9UT0tFTik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBwcm92aWRlck9iamVjdCA9IHRoaXMucHJvdmlkZXJzLmdldChwcm92aWRlcklkKTtcbiAgICAgICAgaWYgKHByb3ZpZGVyT2JqZWN0KSB7XG4gICAgICAgICAgcHJvdmlkZXJPYmplY3RcbiAgICAgICAgICAgIC5nZXRMb2dpblN0YXR1cyh7IHJlZnJlc2hUb2tlbjogdHJ1ZSB9KVxuICAgICAgICAgICAgLnRoZW4oKHVzZXI6IFNvY2lhbFVzZXIpID0+IHtcbiAgICAgICAgICAgICAgdXNlci5wcm92aWRlciA9IHByb3ZpZGVySWQ7XG4gICAgICAgICAgICAgIHRoaXMuX3VzZXIgPSB1c2VyO1xuICAgICAgICAgICAgICB0aGlzLl9hdXRoU3RhdGUubmV4dCh1c2VyKTtcbiAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICAgICAgICAgIHJlamVjdChlcnIpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmVqZWN0KFNvY2lhbEF1dGhTZXJ2aWNlLkVSUl9MT0dJTl9QUk9WSURFUl9OT1RfRk9VTkQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQSBtZXRob2QgdXNlZCB0byBzaWduIGluIGEgdXNlciB3aXRoIGEgc3BlY2lmaWMgYExvZ2luUHJvdmlkZXJgLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvdmlkZXJJZCBJZCB3aXRoIHdoaWNoIHRoZSBgTG9naW5Qcm92aWRlcmAgaGFzIGJlZW4gcmVnaXN0ZXJlZCB3aXRoIHRoZSBzZXJ2aWNlXG4gICAqIEBwYXJhbSBzaWduSW5PcHRpb25zIE9wdGlvbmFsIGBMb2dpblByb3ZpZGVyYCBzcGVjaWZpYyBhcmd1bWVudHNcbiAgICogQHJldHVybnMgQSBgUHJvbWlzZWAgdGhhdCByZXNvbHZlcyB0byB0aGUgYXV0aGVudGljYXRlZCB1c2VyIGluZm9ybWF0aW9uXG4gICAqL1xuICBzaWduSW4ocHJvdmlkZXJJZDogc3RyaW5nLCBzaWduSW5PcHRpb25zPzogYW55KTogUHJvbWlzZTxTb2NpYWxVc2VyPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIGlmICghdGhpcy5pbml0aWFsaXplZCkge1xuICAgICAgICByZWplY3QoU29jaWFsQXV0aFNlcnZpY2UuRVJSX05PVF9JTklUSUFMSVpFRCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBsZXQgcHJvdmlkZXJPYmplY3QgPSB0aGlzLnByb3ZpZGVycy5nZXQocHJvdmlkZXJJZCk7XG4gICAgICAgIGlmIChwcm92aWRlck9iamVjdCkge1xuICAgICAgICAgIHByb3ZpZGVyT2JqZWN0XG4gICAgICAgICAgICAuc2lnbkluKHNpZ25Jbk9wdGlvbnMpXG4gICAgICAgICAgICAudGhlbigodXNlcjogU29jaWFsVXNlcikgPT4ge1xuICAgICAgICAgICAgICB1c2VyLnByb3ZpZGVyID0gcHJvdmlkZXJJZDtcbiAgICAgICAgICAgICAgcmVzb2x2ZSh1c2VyKTtcblxuICAgICAgICAgICAgICB0aGlzLl91c2VyID0gdXNlcjtcbiAgICAgICAgICAgICAgdGhpcy5fYXV0aFN0YXRlLm5leHQodXNlcik7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZWplY3QoU29jaWFsQXV0aFNlcnZpY2UuRVJSX0xPR0lOX1BST1ZJREVSX05PVF9GT1VORCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBIG1ldGhvZCB1c2VkIHRvIHNpZ24gb3V0IHRoZSBjdXJyZW50bHkgbG9nZ2VuIGluIHVzZXIuXG4gICAqXG4gICAqIEBwYXJhbSByZXZva2UgT3B0aW9uYWwgcGFyYW1ldGVyIHRvIHNwZWNpZnkgd2hldGhlciBhIGhhcmQgc2lnbiBvdXQgaXMgdG8gYmUgcGVyZm9ybWVkXG4gICAqIEByZXR1cm5zIEEgYFByb21pc2VgIHRoYXQgcmVzb2x2ZXMgaWYgdGhlIG9wZXJhdGlvbiBpcyBzdWNjZXNzZnVsLCByZWplY3RzIG90aGVyd2lzZVxuICAgKi9cbiAgc2lnbk91dChyZXZva2U6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZWQpIHtcbiAgICAgICAgcmVqZWN0KFNvY2lhbEF1dGhTZXJ2aWNlLkVSUl9OT1RfSU5JVElBTElaRUQpO1xuICAgICAgfSBlbHNlIGlmICghdGhpcy5fdXNlcikge1xuICAgICAgICByZWplY3QoU29jaWFsQXV0aFNlcnZpY2UuRVJSX05PVF9MT0dHRURfSU4pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGV0IHByb3ZpZGVySWQgPSB0aGlzLl91c2VyLnByb3ZpZGVyO1xuICAgICAgICBsZXQgcHJvdmlkZXJPYmplY3QgPSB0aGlzLnByb3ZpZGVycy5nZXQocHJvdmlkZXJJZCk7XG4gICAgICAgIGlmIChwcm92aWRlck9iamVjdCkge1xuICAgICAgICAgIHByb3ZpZGVyT2JqZWN0XG4gICAgICAgICAgICAuc2lnbk91dChyZXZva2UpXG4gICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgIHJlc29sdmUoKTtcblxuICAgICAgICAgICAgICB0aGlzLl91c2VyID0gbnVsbDtcbiAgICAgICAgICAgICAgdGhpcy5fYXV0aFN0YXRlLm5leHQobnVsbCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZWplY3QoU29jaWFsQXV0aFNlcnZpY2UuRVJSX0xPR0lOX1BST1ZJREVSX05PVF9GT1VORCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufVxuIl19