UNPKG

@netgrif/components-core

Version:

Netgrif Application engine frontend core Angular library

223 lines 30.1 kB
import { Injectable } from '@angular/core'; import { ReplaySubject } from 'rxjs'; import { User } from '../models/user'; import { filter, take, tap } from 'rxjs/operators'; import { HttpErrorResponse } from '@angular/common/http'; import * as i0 from "@angular/core"; import * as i1 from "../../authentication/services/authentication/authentication.service"; import * as i2 from "../../resources/engine-endpoint/user-resource.service"; import * as i3 from "../../authentication/models/user.transformer"; import * as i4 from "../../logger/services/logger.service"; import * as i5 from "../../authentication/session/services/session.service"; import * as i6 from "../../authentication/anonymous/anonymous.service"; import * as i7 from "../../configuration/configuration.service"; export class UserService { _authService; _userResource; _userTransform; _log; _session; _anonymousService; _config; _user; _userChange$; _anonymousUserChange$; _loginCalled; _subAuth; _subAnonym; _publicLoadCalled; GLOBAL_ROLE_PREFIX = 'global_'; constructor(_authService, _userResource, _userTransform, _log, _session, _anonymousService, _config) { this._authService = _authService; this._userResource = _userResource; this._userTransform = _userTransform; this._log = _log; this._session = _session; this._anonymousService = _anonymousService; this._config = _config; this._user = this.emptyUser(); this._loginCalled = false; this._userChange$ = new ReplaySubject(1); this._anonymousUserChange$ = new ReplaySubject(1); this._config.loaded$ .pipe(filter(loaded => loaded), take(1)).subscribe(() => { setTimeout(() => { this._subAuth = this._authService.authenticated$.subscribe(auth => { if (auth && !this._loginCalled) { this.loadUser(); } else if (!auth) { this.clearUser(); this.publishUserChange(); } }); }); this._subAnonym = this._anonymousService.tokenSet.subscribe(token => { if (token) { this.loadPublicUser(); } else { this.clearUser(); this.publishAnonymousUserChange(); } }); }); } get user() { return this._user; } get user$() { return this._userChange$.asObservable(); } get anonymousUser() { return this.anonymousUser; } get anonymousUser$() { return this._anonymousUserChange$.asObservable(); } ngOnDestroy() { this._userChange$.complete(); this._anonymousUserChange$.complete(); this._subAuth.unsubscribe(); this._subAnonym.unsubscribe(); } /** * Check if user has specified authority. * @param authority - If provided authority is array of authorities. * Method make intersection of the provided authorities and user's authorities. * If calculated intersection isn't empty returns true, otherwise false. */ hasAuthority(authority) { const user = this._user.getSelfOrImpersonated(); if (!authority || !user.authorities) { return false; } if (authority instanceof Array) { return authority.some(a => user.authorities.some(u => u === a)); } else { return user.authorities.some(a => a === authority); } } hasRole(role) { const user = this._user.getSelfOrImpersonated(); if (!role || !user.roles) { return false; } return user.roles.some(r => r === role); } /** * Checks whether the user has role with a specific stringId * @param roleStringId ID of the role we want to check */ hasRoleById(roleStringId) { const user = this._user.getSelfOrImpersonated(); if (!roleStringId || !user.roles) { return false; } return user.roles.some(r => r.stringId === roleStringId); } /** * Checks whether the user has a role with the specified identifier in a process with the specified identifier (any version), * or if the role is global (with prefix 'global_'). * @param roleIdentifier identifier (import ID) of the role we want to check * @param netIdentifier identifier (import ID) of the process the role is defined in */ hasRoleByIdentifier(roleIdentifier, netIdentifier) { const user = this._user.getSelfOrImpersonated(); if (!roleIdentifier || !user.roles) { return false; } return user.roles.some(r => { const matchesRole = r.importId === roleIdentifier; const isGlobalRole = r.importId.startsWith(this.GLOBAL_ROLE_PREFIX); const matchesNet = r.netImportId === netIdentifier; return matchesRole && (isGlobalRole || matchesNet); }); } /** * Checks whether the user has role with the specified name in a process with the specified identifier (any version) * @param roleName name of the role we want to check * @param netIdentifier identifier (import ID) of the process the role is defined in */ hasRoleByName(roleName, netIdentifier) { const user = this._user.getSelfOrImpersonated(); if (!roleName || !netIdentifier || !user.roles) { return false; } return user.roles.some(r => r.netImportId === netIdentifier && r.name === roleName); } login(credentials) { this._loginCalled = true; return this._authService.login(credentials).pipe(tap((authUser) => { this._user = authUser; this._loginCalled = false; this.publishUserChange(); })); } logout() { return this._authService.logout().pipe(tap(() => { this._user = this.emptyUser(); this.publishUserChange(); })); } reload() { this.loadUser(); } emptyUser() { return new User('', '', '', '', '', '', [], [], [], []); } loadUser() { this._userResource.getLoggedUser().pipe(take(1)).subscribe((user) => { if (user) { const backendUser = { ...user, id: user.id.toString() }; this._user = this._userTransform.transform(backendUser); this.publishUserChange(); } }, error => { if (error instanceof HttpErrorResponse && error.status === 401) { this._log.debug('Authentication token is invalid. Clearing stream'); this._session.clear(); } else { this._log.error('Loading logged user has failed! Initialisation has not be completed successfully!', error); } }); } loadPublicUser() { this._userResource.getPublicLoggedUser().pipe(take(1)).subscribe((user) => { if (user) { const backendUser = { ...user, id: user.id.toString() }; this._user = this._userTransform.transform(backendUser); this.publishAnonymousUserChange(); } }, error => { this._log.error('Loading logged user has failed! Initialisation has not be completed successfully!', error); this._publicLoadCalled = false; }); } clearUser() { this._user = this.emptyUser(); } isUserEmpty(user) { return !user || (!user.id && user.roles.length === 0); } isCurrentUserEmpty() { return this.isUserEmpty(this.user); } publishUserChange() { this._userChange$.next(this.user); } publishAnonymousUserChange() { this._anonymousUserChange$.next(this.user); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserService, deps: [{ token: i1.AuthenticationService }, { token: i2.UserResourceService }, { token: i3.UserTransformer }, { token: i4.LoggerService }, { token: i5.SessionService }, { token: i6.AnonymousService }, { token: i7.ConfigurationService }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: UserService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i1.AuthenticationService }, { type: i2.UserResourceService }, { type: i3.UserTransformer }, { type: i4.LoggerService }, { type: i5.SessionService }, { type: i6.AnonymousService }, { type: i7.ConfigurationService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmV0Z3JpZi1jb21wb25lbnRzLWNvcmUvc3JjL2xpYi91c2VyL3NlcnZpY2VzL3VzZXIuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsVUFBVSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBRXBELE9BQU8sRUFBYSxhQUFhLEVBQWUsTUFBTSxNQUFNLENBQUM7QUFFN0QsT0FBTyxFQUFDLElBQUksRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBRXBDLE9BQU8sRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBS2pELE9BQU8sRUFBQyxpQkFBaUIsRUFBQyxNQUFNLHNCQUFzQixDQUFDOzs7Ozs7Ozs7QUFTdkQsTUFBTSxPQUFPLFdBQVc7SUFZRTtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQWhCWixLQUFLLENBQU87SUFDWixZQUFZLENBQXNCO0lBQ2xDLHFCQUFxQixDQUFzQjtJQUMzQyxZQUFZLENBQVU7SUFDdEIsUUFBUSxDQUFlO0lBQ3ZCLFVBQVUsQ0FBZTtJQUMzQixpQkFBaUIsQ0FBVTtJQUVuQixrQkFBa0IsR0FBRyxTQUFTLENBQUM7SUFFL0MsWUFBc0IsWUFBbUMsRUFDbkMsYUFBa0MsRUFDbEMsY0FBK0IsRUFDL0IsSUFBbUIsRUFDbkIsUUFBd0IsRUFDeEIsaUJBQW1DLEVBQ25DLE9BQTZCO1FBTjdCLGlCQUFZLEdBQVosWUFBWSxDQUF1QjtRQUNuQyxrQkFBYSxHQUFiLGFBQWEsQ0FBcUI7UUFDbEMsbUJBQWMsR0FBZCxjQUFjLENBQWlCO1FBQy9CLFNBQUksR0FBSixJQUFJLENBQWU7UUFDbkIsYUFBUSxHQUFSLFFBQVEsQ0FBZ0I7UUFDeEIsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFrQjtRQUNuQyxZQUFPLEdBQVAsT0FB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Q0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFUywwQkFBMEI7UUFDaEMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDL0MsQ0FBQzt3R0EzTlEsV0FBVzs0R0FBWCxXQUFXLGNBRlIsTUFBTTs7NEZBRVQsV0FBVztrQkFIdkIsVUFBVTttQkFBQztvQkFDUixVQUFVLEVBQUUsTUFBTTtpQkFDckIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGUsIE9uRGVzdHJveX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0NvbmZpZ3VyYXRpb25TZXJ2aWNlfSBmcm9tIFwiLi4vLi4vY29uZmlndXJhdGlvbi9jb25maWd1cmF0aW9uLnNlcnZpY2VcIjtcbmltcG9ydCB7T2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCwgU3Vic2NyaXB0aW9ufSBmcm9tICdyeGpzJztcbmltcG9ydCB7UHJvY2Vzc1JvbGV9IGZyb20gJy4uLy4uL3Jlc291cmNlcy9pbnRlcmZhY2UvcHJvY2Vzcy1yb2xlJztcbmltcG9ydCB7VXNlcn0gZnJvbSAnLi4vbW9kZWxzL3VzZXInO1xuaW1wb3J0IHtDcmVkZW50aWFsc30gZnJvbSAnLi4vLi4vYXV0aGVudGljYXRpb24vbW9kZWxzL2NyZWRlbnRpYWxzJztcbmltcG9ydCB7ZmlsdGVyLCB0YWtlLCB0YXB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7QXV0aGVudGljYXRpb25TZXJ2aWNlfSBmcm9tICcuLi8uLi9hdXRoZW50aWNhdGlvbi9zZXJ2aWNlcy9hdXRoZW50aWNhdGlvbi9hdXRoZW50aWNhdGlvbi5zZXJ2aWNlJztcbmltcG9ydCB7VXNlclJlc291cmNlU2VydmljZX0gZnJvbSAnLi4vLi4vcmVzb3VyY2VzL2VuZ2luZS1lbmRwb2ludC91c2VyLXJlc291cmNlLnNlcnZpY2UnO1xuaW1wb3J0IHtVc2VyVHJhbnNmb3JtZXJ9IGZyb20gJy4uLy4uL2F1dGhlbnRpY2F0aW9uL21vZGVscy91c2VyLnRyYW5zZm9ybWVyJztcbmltcG9ydCB7TG9nZ2VyU2VydmljZX0gZnJvbSAnLi4vLi4vbG9nZ2VyL3NlcnZpY2VzL2xvZ2dlci5zZXJ2aWNlJztcbmltcG9ydCB7SHR0cEVycm9yUmVzcG9uc2V9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7U2Vzc2lvblNlcnZpY2V9IGZyb20gJy4uLy4uL2F1dGhlbnRpY2F0aW9uL3Nlc3Npb24vc2VydmljZXMvc2Vzc2lvbi5zZXJ2aWNlJztcbmltcG9ydCB7VXNlclJlc291cmNlfSBmcm9tICcuLi8uLi9yZXNvdXJjZXMvaW50ZXJmYWNlL3VzZXItcmVzb3VyY2UnO1xuaW1wb3J0IHtBbm9ueW1vdXNTZXJ2aWNlfSBmcm9tICcuLi8uLi9hdXRoZW50aWNhdGlvbi9hbm9ueW1vdXMvYW5vbnltb3VzLnNlcnZpY2UnO1xuXG5cbkBJbmplY3RhYmxlKHtcbiAgICBwcm92aWRlZEluOiAncm9vdCdcbn0pXG5leHBvcnQgY2xhc3MgVXNlclNlcnZpY2UgaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuXG4gICAgcHJvdGVjdGVkIF91c2VyOiBVc2VyO1xuICAgIHByb3RlY3RlZCBfdXNlckNoYW5nZSQ6IFJlcGxheVN1YmplY3Q8VXNlcj47XG4gICAgcHJvdGVjdGVkIF9hbm9ueW1vdXNVc2VyQ2hhbmdlJDogUmVwbGF5U3ViamVjdDxVc2VyPjtcbiAgICBwcm90ZWN0ZWQgX2xvZ2luQ2FsbGVkOiBib29sZWFuO1xuICAgIHByb3RlY3RlZCBfc3ViQXV0aDogU3Vic2NyaXB0aW9uO1xuICAgIHByb3RlY3RlZCBfc3ViQW5vbnltOiBTdWJzY3JpcHRpb247XG4gICAgcHJpdmF0ZSBfcHVibGljTG9hZENhbGxlZDogYm9vbGVhbjtcblxuICAgIHB1YmxpYyByZWFkb25seSBHTE9CQUxfUk9MRV9QUkVGSVggPSAnZ2xvYmFsXyc7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgX2F1dGhTZXJ2aWNlOiBBdXRoZW50aWNhdGlvblNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF91c2VyUmVzb3VyY2U6IFVzZXJSZXNvdXJjZVNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF91c2VyVHJhbnNmb3JtOiBVc2VyVHJhbnNmb3JtZXIsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9sb2c6IExvZ2dlclNlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9zZXNzaW9uOiBTZXNzaW9uU2VydmljZSxcbiAgICAgICAgICAgICAgICBwcm90ZWN0ZWQgX2Fub255bW91c1NlcnZpY2U6IEFub255bW91c1NlcnZpY2UsXG4gICAgICAgICAgICAgICAgcHJvdGVjdGVkIF9jb25maWc6IENvbmZpZ3VyYXRpb25TZXJ2aWNlKSB7XG4gICAgICAgIHRoaXMuX3VzZXIgPSB0aGlzLmVtcHR5VXNlcigpO1xuICAgICAgICB0aGlzLl9sb2dpbkNhbGxlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLl91c2VyQ2hhbmdlJCA9IG5ldyBSZXBsYXlTdWJqZWN0PFVzZXI+KDEpO1xuICAgICAgICB0aGlzLl9hbm9ueW1vdXNVc2VyQ2hhbmdlJCA9IG5ldyBSZXBsYXlTdWJqZWN0PFVzZXI+KDEpO1xuICAgICAgICB0aGlzLl9jb25maWcubG9hZGVkJFxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgZmlsdGVyKGxvYWRlZCA9PiBsb2FkZWQpLFxuICAgICAgICAgICAgICAgIHRha2UoMSlcbiAgICAgICAgICAgICkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3N1YkF1dGggPSB0aGlzLl9hdXRoU2VydmljZS5hdXRoZW50aWNhdGVkJC5zdWJzY3JpYmUoYXV0aCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhdXRoICYmICF0aGlzLl9sb2dpbkNhbGxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkVXNlcigpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFhdXRoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNsZWFyVXNlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wdWJsaXNoVXNlckNoYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRoaXMuX3N1YkFub255bSA9IHRoaXMuX2Fub255bW91c1NlcnZpY2UudG9rZW5TZXQuc3Vic2NyaWJlKHRva2VuID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkUHVibGljVXNlcigpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXJVc2VyKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaEFub255bW91c1VzZXJDaGFuZ2UoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZ2V0IHVzZXIoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl91c2VyO1xuICAgIH1cblxuICAgIGdldCB1c2VyJCgpOiBPYnNlcnZhYmxlPFVzZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3VzZXJDaGFuZ2UkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIGdldCBhbm9ueW1vdXNVc2VyKCk6IFVzZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5hbm9ueW1vdXNVc2VyO1xuICAgIH1cblxuICAgIGdldCBhbm9ueW1vdXNVc2VyJCgpOiBPYnNlcnZhYmxlPFVzZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Fub255bW91c1VzZXJDaGFuZ2UkLmFzT2JzZXJ2YWJsZSgpO1xuICAgIH1cblxuICAgIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgICAgICB0aGlzLl91c2VyQ2hhbmdlJC5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLl9hbm9ueW1vdXNVc2VyQ2hhbmdlJC5jb21wbGV0ZSgpO1xuICAgICAgICB0aGlzLl9zdWJBdXRoLnVuc3Vic2NyaWJlKCk7XG4gICAgICAgIHRoaXMuX3N1YkFub255bS51bnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHVzZXIgaGFzIHNwZWNpZmllZCBhdXRob3JpdHkuXG4gICAgICogQHBhcmFtIGF1dGhvcml0eSAtIElmIHByb3ZpZGVkIGF1dGhvcml0eSBpcyBhcnJheSBvZiBhdXRob3JpdGllcy5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgTWV0aG9kIG1ha2UgaW50ZXJzZWN0aW9uIG9mIHRoZSBwcm92aWRlZCBhdXRob3JpdGllcyBhbmQgdXNlcidzIGF1dGhvcml0aWVzLlxuICAgICAqICAgICAgICAgICAgICAgICAgICBJZiBjYWxjdWxhdGVkIGludGVyc2VjdGlvbiBpc24ndCBlbXB0eSByZXR1cm5zIHRydWUsIG90aGVyd2lzZSBmYWxzZS5cbiAgICAgKi9cbiAgICBwdWJsaWMgaGFzQXV0aG9yaXR5KGF1dGhvcml0eTogQXJyYXk8c3RyaW5nPiB8IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCB1c2VyID0gdGhpcy5fdXNlci5nZXRTZWxmT3JJbXBlcnNvbmF0ZWQoKTtcbiAgICAgICAgaWYgKCFhdXRob3JpdHkgfHwgIXVzZXIuYXV0aG9yaXRpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYXV0aG9yaXR5IGluc3RhbmNlb2YgQXJyYXkpIHtcbiAgICAgICAgICAgIHJldHVybiBhdXRob3JpdHkuc29tZShhID0+IHVzZXIuYXV0aG9yaXRpZXMuc29tZSh1ID0+IHUgPT09IGEpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB1c2VyLmF1dGhvcml0aWVzLnNvbWUoYSA9PiBhID09PSBhdXRob3JpdHkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHVibGljIGhhc1JvbGUocm9sZTogUHJvY2Vzc1JvbGUpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgdXNlciA9IHRoaXMuX3VzZXIuZ2V0U2VsZk9ySW1wZXJzb25hdGVkKCk7XG4gICAgICAgIGlmICghcm9sZSB8fCAhdXNlci5yb2xlcykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1c2VyLnJvbGVzLnNvbWUociA9PiByID09PSByb2xlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVja3Mgd2hldGhlciB0aGUgdXNlciBoYXMgcm9sZSB3aXRoIGEgc3BlY2lmaWMgc3RyaW5nSWRcbiAgICAgKiBAcGFyYW0gcm9sZVN0cmluZ0lkIElEIG9mIHRoZSByb2xlIHdlIHdhbnQgdG8gY2hlY2tcbiAgICAgKi9cbiAgICBwdWJsaWMgaGFzUm9sZUJ5SWQocm9sZVN0cmluZ0lkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICAgICAgY29uc3QgdXNlciA9IHRoaXMuX3VzZXIuZ2V0U2VsZk9ySW1wZXJzb25hdGVkKCk7XG4gICAgICAgIGlmICghcm9sZVN0cmluZ0lkIHx8ICF1c2VyLnJvbGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVzZXIucm9sZXMuc29tZShyID0+IHIuc3RyaW5nSWQgPT09IHJvbGVTdHJpbmdJZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIHVzZXIgaGFzIGEgcm9sZSB3aXRoIHRoZSBzcGVjaWZpZWQgaWRlbnRpZmllciBpbiBhIHByb2Nlc3Mgd2l0aCB0aGUgc3BlY2lmaWVkIGlkZW50aWZpZXIgKGFueSB2ZXJzaW9uKSxcbiAgICAgKiBvciBpZiB0aGUgcm9sZSBpcyBnbG9iYWwgKHdpdGggcHJlZml4ICdnbG9iYWxfJykuXG4gICAgICogQHBhcmFtIHJvbGVJZGVudGlmaWVyIGlkZW50aWZpZXIgKGltcG9ydCBJRCkgb2YgdGhlIHJvbGUgd2Ugd2FudCB0byBjaGVja1xuICAgICAqIEBwYXJhbSBuZXRJZGVudGlmaWVyIGlkZW50aWZpZXIgKGltcG9ydCBJRCkgb2YgdGhlIHByb2Nlc3MgdGhlIHJvbGUgaXMgZGVmaW5lZCBpblxuICAgICAqL1xuICAgIHB1YmxpYyBoYXNSb2xlQnlJZGVudGlmaWVyKHJvbGVJZGVudGlmaWVyOiBzdHJpbmcsIG5ldElkZW50aWZpZXI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCB1c2VyID0gdGhpcy5fdXNlci5nZXRTZWxmT3JJbXBlcnNvbmF0ZWQoKTtcbiAgICAgICAgaWYgKCFyb2xlSWRlbnRpZmllciB8fCAhdXNlci5yb2xlcykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVzZXIucm9sZXMuc29tZShyID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG1hdGNoZXNSb2xlID0gci5pbXBvcnRJZCA9PT0gcm9sZUlkZW50aWZpZXI7XG4gICAgICAgICAgICBjb25zdCBpc0dsb2JhbFJvbGUgPSByLmltcG9ydElkLnN0YXJ0c1dpdGgodGhpcy5HTE9CQUxfUk9MRV9QUkVGSVgpO1xuICAgICAgICAgICAgY29uc3QgbWF0Y2hlc05ldCA9IHIubmV0SW1wb3J0SWQgPT09IG5ldElkZW50aWZpZXI7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlc1JvbGUgJiYgKGlzR2xvYmFsUm9sZSB8fCBtYXRjaGVzTmV0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIHdoZXRoZXIgdGhlIHVzZXIgaGFzIHJvbGUgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUgaW4gYSBwcm9jZXNzIHdpdGggdGhlIHNwZWNpZmllZCBpZGVudGlmaWVyIChhbnkgdmVyc2lvbilcbiAgICAgKiBAcGFyYW0gcm9sZU5hbWUgbmFtZSBvZiB0aGUgcm9sZSB3ZSB3YW50IHRvIGNoZWNrXG4gICAgICogQHBhcmFtIG5ldElkZW50aWZpZXIgaWRlbnRpZmllciAoaW1wb3J0IElEKSBvZiB0aGUgcHJvY2VzcyB0aGUgcm9sZSBpcyBkZWZpbmVkIGluXG4gICAgICovXG4gICAgcHVibGljIGhhc1JvbGVCeU5hbWUocm9sZU5hbWU6IHN0cmluZywgbmV0SWRlbnRpZmllcjogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgICAgIGNvbnN0IHVzZXIgPSB0aGlzLl91c2VyLmdldFNlbGZPckltcGVyc29uYXRlZCgpO1xuICAgICAgICBpZiAoIXJvbGVOYW1lIHx8ICFuZXRJZGVudGlmaWVyIHx8ICF1c2VyLnJvbGVzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVzZXIucm9sZXMuc29tZShyID0+IHIubmV0SW1wb3J0SWQgPT09IG5ldElkZW50aWZpZXIgJiYgci5uYW1lID09PSByb2xlTmFtZSk7XG4gICAgfVxuXG4gICAgcHVibGljIGxvZ2luKGNyZWRlbnRpYWxzOiBDcmVkZW50aWFscyk6IE9ic2VydmFibGU8VXNlcj4ge1xuICAgICAgICB0aGlzLl9sb2dpbkNhbGxlZCA9IHRydWU7XG4gICAgICAgIHJldHVybiB0aGlzLl9hdXRoU2VydmljZS5sb2dpbihjcmVkZW50aWFscykucGlwZShcbiAgICAgICAgICAgIHRhcCgoYXV0aFVzZXI6IFVzZXIpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl91c2VyID0gYXV0aFVzZXI7XG4gICAgICAgICAgICAgICAgdGhpcy5fbG9naW5DYWxsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hVc2VyQ2hhbmdlKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBsb2dvdXQoKTogT2JzZXJ2YWJsZTxvYmplY3Q+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2F1dGhTZXJ2aWNlLmxvZ291dCgpLnBpcGUoXG4gICAgICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3VzZXIgPSB0aGlzLmVtcHR5VXNlcigpO1xuICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaFVzZXJDaGFuZ2UoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHJlbG9hZCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5sb2FkVXNlcigpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBlbXB0eVVzZXIoKSB7XG4gICAgICAgIHJldHVybiBuZXcgVXNlcignJywgJycsICcnLCAnJywgJycsICcnLCBbXSwgW10sIFtdLCBbXSk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIGxvYWRVc2VyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl91c2VyUmVzb3VyY2UuZ2V0TG9nZ2VkVXNlcigpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCh1c2VyOiBVc2VyUmVzb3VyY2UpID0+IHtcbiAgICAgICAgICAgIGlmICh1c2VyKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgYmFja2VuZFVzZXIgPSB7Li4udXNlciwgaWQ6IHVzZXIuaWQudG9TdHJpbmcoKX07XG4gICAgICAgICAgICAgICAgdGhpcy5fdXNlciA9IHRoaXMuX3VzZXJUcmFuc2Zvcm0udHJhbnNmb3JtKGJhY2tlbmRVc2VyKTtcbiAgICAgICAgICAgICAgICB0aGlzLnB1Ymxpc2hVc2VyQ2hhbmdlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIGVycm9yID0+IHtcbiAgICAgICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEh0dHBFcnJvclJlc3BvbnNlICYmIGVycm9yLnN0YXR1cyA9PT0gNDAxKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbG9nLmRlYnVnKCdBdXRoZW50aWNhdGlvbiB0b2tlbiBpcyBpbnZhbGlkLiBDbGVhcmluZyBzdHJlYW0nKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXNzaW9uLmNsZWFyKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX2xvZy5lcnJvcignTG9hZGluZyBsb2dnZWQgdXNlciBoYXMgZmFpbGVkISBJbml0aWFsaXNhdGlvbiBoYXMgbm90IGJlIGNvbXBsZXRlZCBzdWNjZXNzZnVsbHkhJywgZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgbG9hZFB1YmxpY1VzZXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX3VzZXJSZXNvdXJjZS5nZXRQdWJsaWNMb2dnZWRVc2VyKCkucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUoKHVzZXI6IFVzZXJSZXNvdXJjZSkgPT4ge1xuICAgICAgICAgICAgaWYgKHVzZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBiYWNrZW5kVXNlciA9IHsuLi51c2VyLCBpZDogdXNlci5pZC50b1N0cmluZygpfTtcbiAgICAgICAgICAgICAgICB0aGlzLl91c2VyID0gdGhpcy5fdXNlclRyYW5zZm9ybS50cmFuc2Zvcm0oYmFja2VuZFVzZXIpO1xuICAgICAgICAgICAgICAgIHRoaXMucHVibGlzaEFub255bW91c1VzZXJDaGFuZ2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgZXJyb3IgPT4ge1xuICAgICAgICAgICAgdGhpcy5fbG9nLmVycm9yKCdMb2FkaW5nIGxvZ2dlZCB1c2VyIGhhcyBmYWlsZWQhIEluaXRpYWxpc2F0aW9uIGhhcyBub3QgYmUgY29tcGxldGVkIHN1Y2Nlc3NmdWxseSEnLCBlcnJvcik7XG4gICAgICAgICAgICB0aGlzLl9wdWJsaWNMb2FkQ2FsbGVkID0gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBjbGVhclVzZXIoKSB7XG4gICAgICAgIHRoaXMuX3VzZXIgPSB0aGlzLmVtcHR5VXNlcigpO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc1VzZXJFbXB0eSh1c2VyOiBVc2VyKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhdXNlciB8fCAoIXVzZXIuaWQgJiYgdXNlci5yb2xlcy5sZW5ndGggPT09IDApO1xuICAgIH1cblxuICAgIHB1YmxpYyBpc0N1cnJlbnRVc2VyRW1wdHkoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzVXNlckVtcHR5KHRoaXMudXNlcilcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcHVibGlzaFVzZXJDaGFuZ2UoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX3VzZXJDaGFuZ2UkLm5leHQodGhpcy51c2VyKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgcHVibGlzaEFub255bW91c1VzZXJDaGFuZ2UoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2Fub255bW91c1VzZXJDaGFuZ2UkLm5leHQodGhpcy51c2VyKTtcbiAgICB9XG59XG4iXX0=