vix-ui
Version:
A set of essential UI modules for your Angular application in ViSenze
462 lines (461 loc) • 31.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes} checked by tsc
*/
import * as tslib_1 from "tslib";
import { OAuthService } from 'angular-oauth2-oidc';
import { Injectable } from '@angular/core';
import * as OktaAuth from '@okta/okta-auth-js';
import { AuthConfigService } from './auth-config.service';
import { OktaService } from './okta.service';
import { UserInfo } from '../modules/user-info';
import { UserGroups } from '../modules/user-groups';
/**
* VixAuthService is the interface exported to users. It wraps all API and methods.
*/
var VixAuthService = /** @class */ (function () {
function VixAuthService(oauth, authConfig, okta) {
this.oauth = oauth;
this.authConfig = authConfig;
this.okta = okta;
this.oktaAuth = new OktaAuth({
url: this.authConfig.getUrl(),
issuer: this.authConfig.getIssuer()
});
}
/**
* Check permissions by userGroups and requireGroups
*
* @param userGroups groups users are in
* @param requireGroups groups application requires user to have
* @returns true/false
*/
/**
* Check permissions by userGroups and requireGroups
*
* @param {?} userGroups groups users are in
* @param {?} requireGroups groups application requires user to have
* @return {?} true/false
*/
VixAuthService.hasPermission = /**
* Check permissions by userGroups and requireGroups
*
* @param {?} userGroups groups users are in
* @param {?} requireGroups groups application requires user to have
* @return {?} true/false
*/
function (userGroups, requireGroups) {
return userGroups.hasPermission(requireGroups);
};
/**
* Use tokenManager to store userId
* TODO: actually I have problems in create a cache object to hold all these cache variables, so I use tokenManager to do these works.
* TODO: need to create a share service to provide cache service
*
* @param userId
*/
/**
* Use tokenManager to store userId
* TODO: actually I have problems in create a cache object to hold all these cache variables, so I use tokenManager to do these works.
* TODO: need to create a share service to provide cache service
*
* @param {?} userId
* @return {?}
*/
VixAuthService.prototype.setUserId = /**
* Use tokenManager to store userId
* TODO: actually I have problems in create a cache object to hold all these cache variables, so I use tokenManager to do these works.
* TODO: need to create a share service to provide cache service
*
* @param {?} userId
* @return {?}
*/
function (userId) {
var /** @type {?} */ obj = {
accessToken: 'userId',
expiresAt: Math.round((new Date()).getTime() / 1000 + 3600),
scopes: [userId]
};
this.oktaAuth.tokenManager.add('userId', obj);
};
/**
* Get userId from tokenManager
* @returns
*/
/**
* Get userId from tokenManager
* @return {?}
*/
VixAuthService.prototype.getUserId = /**
* Get userId from tokenManager
* @return {?}
*/
function () {
var /** @type {?} */ userIdObj = this.oktaAuth.tokenManager.get('userId');
if (userIdObj) {
return this.oktaAuth.tokenManager.get('userId').scopes[0];
}
else {
return null;
}
};
/**
* Store userGroup and shared among browsers by TokenManager with key 'userGroup'
*
* @param userGroups
*/
/**
* Store userGroup and shared among browsers by TokenManager with key 'userGroup'
*
* @param {?} userGroups
* @return {?}
*/
VixAuthService.prototype.setCurrentUserGroups = /**
* Store userGroup and shared among browsers by TokenManager with key 'userGroup'
*
* @param {?} userGroups
* @return {?}
*/
function (userGroups) {
var /** @type {?} */ obj = {
accessToken: 'userGroups',
expiresAt: Math.round((new Date()).getTime() / 1000 + 3600),
scopes: userGroups.groups
};
this.oktaAuth.tokenManager.add('userGroups', obj);
};
/**
* Get stored userGroups and refresh if expires
*
* @returns
*/
/**
* Get stored userGroups and refresh if expires
*
* @return {?}
*/
VixAuthService.prototype.getLoginUserGroups = /**
* Get stored userGroups and refresh if expires
*
* @return {?}
*/
function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var userGroupsTokenObj, nowSecond, tmpUserGroups, userGroups;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
userGroupsTokenObj = this.oktaAuth.tokenManager.get('userGroups');
nowSecond = (new Date()).getTime() / 1000;
if (!(!userGroupsTokenObj || nowSecond > userGroupsTokenObj.expireAt)) return [3 /*break*/, 2];
return [4 /*yield*/, this.getUserGroups(this.getUserId())];
case 1:
tmpUserGroups = _a.sent();
this.setCurrentUserGroups(tmpUserGroups);
_a.label = 2;
case 2:
userGroups = new UserGroups(null);
userGroups.groups = this.oktaAuth.tokenManager.get('userGroups').scopes;
return [2 /*return*/, userGroups];
}
});
});
};
/**
* Get current login userInfo
* TODO: we can cache user info includes groups information when finished login
*
* @returns
*/
/**
* Get current login userInfo
* TODO: we can cache user info includes groups information when finished login
*
* @return {?}
*/
VixAuthService.prototype.getUserInfo = /**
* Get current login userInfo
* TODO: we can cache user info includes groups information when finished login
*
* @return {?}
*/
function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var oktaUserInfo;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.isLogin()) return [3 /*break*/, 3];
return [4 /*yield*/, this.okta.getUserInfo(this.getUserId())];
case 1:
oktaUserInfo = _a.sent();
return [4 /*yield*/, new UserInfo(oktaUserInfo)];
case 2: return [2 /*return*/, _a.sent()];
case 3: return [2 /*return*/, Promise.reject('not login')];
}
});
});
};
/**
* get userGroup by given userId
*
* @param userId
* @returns
*/
/**
* get userGroup by given userId
*
* @param {?} userId
* @return {?}
*/
VixAuthService.prototype.getUserGroups = /**
* get userGroup by given userId
*
* @param {?} userId
* @return {?}
*/
function (userId) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var oktaUserGroups, err_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.isLogin()) return [3 /*break*/, 6];
_a.label = 1;
case 1:
_a.trys.push([1, 4, , 5]);
return [4 /*yield*/, this.okta.getUserGroups(userId)];
case 2:
oktaUserGroups = _a.sent();
return [4 /*yield*/, new UserGroups(oktaUserGroups)];
case 3: return [2 /*return*/, _a.sent()];
case 4:
err_1 = _a.sent();
console.log('getUserGroups err', err_1);
// return new UserGroups(null);
return [3 /*break*/, 5];
case 5: return [3 /*break*/, 7];
case 6: return [2 /*return*/, null];
case 7: return [2 /*return*/];
}
});
});
};
/**
* Return if already login by check the existence of accessToken
*
* @returns
*/
/**
* Return if already login by check the existence of accessToken
*
* @return {?}
*/
VixAuthService.prototype.isLogin = /**
* Return if already login by check the existence of accessToken
*
* @return {?}
*/
function () {
return !!this.getUserId();
};
/**
* Redirect to url for Google login
*/
/**
* Redirect to url for Google login
* @param {?} redirectUrl
* @return {?}
*/
VixAuthService.prototype.loginWithGoogle = /**
* Redirect to url for Google login
* @param {?} redirectUrl
* @return {?}
*/
function (redirectUrl) {
window.location.href = this.authConfig.getUrl() + "/oauth2/v1/authorize?" +
("idp=0oadulhuz78SMW8cD0h7&client_id=" + this.authConfig.getClientId() + "&response_type=id_token&") +
"response_mode=fragment&scope=openid&scope=email&scope=picture&scope=name&" +
("state=WM6D&nonce=YsG76jo&redirect_uri=" + redirectUrl);
};
/**
* Login by username and password
*
* @param username
* @param password
* @returns
*/
/**
* Login by username and password
*
* @param {?} username
* @param {?} password
* @return {?}
*/
VixAuthService.prototype.loginWithPassword = /**
* Login by username and password
*
* @param {?} username
* @param {?} password
* @return {?}
*/
function (username, password) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var nonce, signInResponse, session;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.oauth.createAndSaveNonce()];
case 1:
nonce = _a.sent();
return [4 /*yield*/, this.oktaAuth.signIn({ username: username, password: password })];
case 2:
signInResponse = _a.sent();
if (!(signInResponse.status === 'SUCCESS')) return [3 /*break*/, 5];
return [4 /*yield*/, this.oktaAuth.token.getWithoutPrompt({
clientId: this.authConfig.getClientId(),
responseType: ['id_token', 'token'],
scopes: ['openid', 'profile', 'email'],
sessionToken: signInResponse.sessionToken,
nonce: nonce,
redirectUri: window.location.origin
})];
case 3:
_a.sent();
return [4 /*yield*/, this.getSession()];
case 4:
session = _a.sent();
if (session.status === 'ACTIVE') {
console.log('session ACTIVE');
this.setUserId(session.userId);
}
return [2 /*return*/, Promise.resolve('login successfully')];
case 5: return [2 /*return*/, Promise.reject('username or password error')];
}
});
});
};
/**
* List all groups
*
* @return {?}
*/
VixAuthService.prototype.listGroups = /**
* List all groups
*
* @return {?}
*/
function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.okta.listGroups()];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Get session
*
* @return {?}
*/
VixAuthService.prototype.getSession = /**
* Get session
*
* @return {?}
*/
function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.oktaAuth.session.get()];
case 1: return [2 /*return*/, _a.sent()];
}
});
});
};
/**
* Navigate browser to login page
* @return {?}
*/
VixAuthService.prototype.navigateToLoginPage = /**
* Navigate browser to login page
* @return {?}
*/
function () {
console.log('navigateToLoginPage:', this.authConfig.getLoginUrl());
document.location.href = this.authConfig.getLoginUrl();
};
/**
* Navigate browser to redirect page
*/
/**
* Navigate browser to redirect page
* @return {?}
*/
VixAuthService.prototype.navigateToRedirectPage = /**
* Navigate browser to redirect page
* @return {?}
*/
function () {
console.log('navigateToRedirectPage:', this.authConfig.getRedirectUrl());
document.location.href = this.authConfig.getRedirectUrl();
};
/**
* Logout current user and clear token
*
* @returns
*/
/**
* Logout current user and clear token
*
* @return {?}
*/
VixAuthService.prototype.logout = /**
* Logout current user and clear token
*
* @return {?}
*/
function () {
var _this = this;
if (this.isLogin()) {
this.oktaAuth.tokenManager.clear();
console.log('start to logout');
this.oktaAuth.signOut().then(function () {
console.log('logout done, to navigate', _this.authConfig.getLoginUrl());
_this.navigateToLoginPage();
});
}
else {
}
};
VixAuthService.decorators = [
{ type: Injectable },
];
/** @nocollapse */
VixAuthService.ctorParameters = function () { return [
{ type: OAuthService, },
{ type: AuthConfigService, },
{ type: OktaService, },
]; };
return VixAuthService;
}());
export { VixAuthService };
function VixAuthService_tsickle_Closure_declarations() {
/** @type {!Array<{type: !Function, args: (undefined|!Array<?>)}>} */
VixAuthService.decorators;
/**
* @nocollapse
* @type {function(): !Array<(null|{type: ?, decorators: (undefined|!Array<{type: !Function, args: (undefined|!Array<?>)}>)})>}
*/
VixAuthService.ctorParameters;
/** @type {?} */
VixAuthService.prototype.oktaAuth;
/** @type {?} */
VixAuthService.prototype.oauth;
/** @type {?} */
VixAuthService.prototype.authConfig;
/** @type {?} */
VixAuthService.prototype.okta;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vdml4LXVpLyIsInNvdXJjZXMiOlsidml4LXNlcnZpY2VzL2F1dGgvc2VydmljZXMvYXV0aC5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDM0MsT0FBTyxLQUFLLFFBQVEsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7Ozs7SUFTbEQsd0JBQW9CLEtBQW1CLEVBQ25CLFlBQ0E7UUFGQSxVQUFLLEdBQUwsS0FBSyxDQUFjO1FBQ25CLGVBQVUsR0FBVixVQUFVO1FBQ1YsU0FBSSxHQUFKLElBQUk7UUFDdEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLFFBQVEsQ0FBQztZQUMzQixHQUFHLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUU7WUFDN0IsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUyxFQUFFO1NBQ3BDLENBQUMsQ0FBQztLQUNKO0lBR0Q7Ozs7OztPQU1HOzs7Ozs7OztJQUNJLDRCQUFhOzs7Ozs7O0lBQXBCLFVBQXFCLFVBQXNCLEVBQUUsYUFBdUI7UUFDbEUsTUFBTSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDaEQ7SUFFRDs7Ozs7O09BTUc7Ozs7Ozs7OztJQUNILGtDQUFTOzs7Ozs7OztJQUFULFVBQVUsTUFBYztRQUN0QixxQkFBTSxHQUFHLEdB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Ozs7OztRQUN4QixPQUFPLENBQUMsR0FBRyxDQUFDLHNCQUFzQixFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztRQUNuRSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLFdBQVcsRUFBRSxDQUFDOztJQUd6RDs7T0FFRzs7Ozs7SUFDSCwrQ0FBc0I7Ozs7SUFBdEI7UUFDRSxPQUFPLENBQUMsR0FBRyxDQUFDLHlCQUF5QixFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsY0FBYyxFQUFFLENBQUMsQ0FBQztRQUN6RSxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLGNBQWMsRUFBRSxDQUFDO0tBQzNEO0lBRUQ7Ozs7T0FJRzs7Ozs7O0lBQ0gsK0JBQU07Ozs7O0lBQU47UUFBQSxpQkFVQztRQVRDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDbkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDbkMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQy9CLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDO2dCQUMzQixPQUFPLENBQUMsR0FBRyxDQUFDLDBCQUEwQixFQUFFLEtBQUksQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztnQkFDdkUsS0FBSSxDQUFDLG1CQUFtQixFQUFFLENBQUM7YUFDNUIsQ0FBQyxDQUFDO1NBQ0o7UUFBQyxJQUFJLENBQUMsQ0FBQztTQUNQO0tBQ0Y7O2dCQTFORixVQUFVOzs7O2dCQVhGLFlBQVk7Z0JBR1osaUJBQWlCO2dCQUNqQixXQUFXOzt5QkFKcEI7O1NBWWEsY0FBYyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9BdXRoU2VydmljZSB9IGZyb20gJ2FuZ3VsYXItb2F1dGgyLW9pZGMnO1xuaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0ICogYXMgT2t0YUF1dGggZnJvbSAnQG9rdGEvb2t0YS1hdXRoLWpzJztcbmltcG9ydCB7IEF1dGhDb25maWdTZXJ2aWNlIH0gZnJvbSAnLi9hdXRoLWNvbmZpZy5zZXJ2aWNlJztcbmltcG9ydCB7IE9rdGFTZXJ2aWNlIH0gZnJvbSAnLi9va3RhLnNlcnZpY2UnO1xuaW1wb3J0IHsgVXNlckluZm8gfSBmcm9tICcuLi9tb2R1bGVzL3VzZXItaW5mbyc7XG5pbXBvcnQgeyBVc2VyR3JvdXBzIH0gZnJvbSAnLi4vbW9kdWxlcy91c2VyLWdyb3Vwcyc7XG5cbi8qKlxuICogVml4QXV0aFNlcnZpY2UgaXMgdGhlIGludGVyZmFjZSBleHBvcnRlZCB0byB1c2Vycy4gSXQgd3JhcHMgYWxsIEFQSSBhbmQgbWV0aG9kcy5cbiAqL1xuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFZpeEF1dGhTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBva3RhQXV0aDogYW55O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgb2F1dGg6IE9BdXRoU2VydmljZSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBhdXRoQ29uZmlnOiBBdXRoQ29uZmlnU2VydmljZSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBva3RhOiBPa3RhU2VydmljZSkge1xuICAgIHRoaXMub2t0YUF1dGggPSBuZXcgT2t0YUF1dGgoe1xuICAgICAgdXJsOiB0aGlzLmF1dGhDb25maWcuZ2V0VXJsKCksXG4gICAgICBpc3N1ZXI6IHRoaXMuYXV0aENvbmZpZy5nZXRJc3N1ZXIoKVxuICAgIH0pO1xuICB9XG5cblxuICAvKipcbiAgICogQ2hlY2sgcGVybWlzc2lvbnMgYnkgdXNlckdyb3VwcyBhbmQgcmVxdWlyZUdyb3Vwc1xuICAgKlxuICAgKiBAcGFyYW0gdXNlckdyb3VwcyBncm91cHMgdXNlcnMgYXJlIGluXG4gICAqIEBwYXJhbSByZXF1aXJlR3JvdXBzIGdyb3VwcyBhcHBsaWNhdGlvbiByZXF1aXJlcyB1c2VyIHRvIGhhdmVcbiAgICogQHJldHVybnMgdHJ1ZS9mYWxzZVxuICAgKi9cbiAgc3RhdGljIGhhc1Blcm1pc3Npb24odXNlckdyb3VwczogVXNlckdyb3VwcywgcmVxdWlyZUdyb3Vwczogc3RyaW5nW10pOiBib29sZWFuIHtcbiAgICByZXR1cm4gdXNlckdyb3Vwcy5oYXNQZXJtaXNzaW9uKHJlcXVpcmVHcm91cHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVzZSB0b2tlbk1hbmFnZXIgdG8gc3RvcmUgdXNlcklkXG4gICAqIFRPRE86IGFjdHVhbGx5IEkgaGF2ZSBwcm9ibGVtcyBpbiBjcmVhdGUgYSBjYWNoZSBvYmplY3QgdG8gaG9sZCBhbGwgdGhlc2UgY2FjaGUgdmFyaWFibGVzLCBzbyBJIHVzZSB0b2tlbk1hbmFnZXIgdG8gZG8gdGhlc2Ugd29ya3MuXG4gICAqIFRPRE86IG5lZWQgdG8gY3JlYXRlIGEgc2hhcmUgc2VydmljZSB0byBwcm92aWRlIGNhY2hlIHNlcnZpY2VcbiAgICpcbiAgICogQHBhcmFtIHVzZXJJZFxuICAgKi9cbiAgc2V0VXNlcklkKHVzZXJJZDogc3RyaW5nKSB7XG4gICAgY29uc3Qgb2JqID0ge1xuICAgICAgYWNjZXNzVG9rZW46ICd1c2VySWQnLFxuICAgICAgZXhwaXJlc0F0OiBNYXRoLnJvdW5kKChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLyAxMDAwICsgMzYwMCksXG4gICAgICBzY29wZXM6IFt1c2VySWRdXG4gICAgfTtcbiAgICB0aGlzLm9rdGFBdXRoLnRva2VuTWFuYWdlci5hZGQoJ3VzZXJJZCcsIG9iaik7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHVzZXJJZCBmcm9tIHRva2VuTWFuYWdlclxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgZ2V0VXNlcklkKCkge1xuICAgIGNvbnN0IHVzZXJJZE9iaiA9IHRoaXMub2t0YUF1dGgudG9rZW5NYW5hZ2VyLmdldCgndXNlcklkJyk7XG4gICAgaWYgKHVzZXJJZE9iaikge1xuICAgICAgcmV0dXJuIHRoaXMub2t0YUF1dGgudG9rZW5NYW5hZ2VyLmdldCgndXNlcklkJykuc2NvcGVzWzBdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3RvcmUgdXNlckdyb3VwIGFuZCBzaGFyZWQgYW1vbmcgYnJvd3NlcnMgYnkgVG9rZW5NYW5hZ2VyIHdpdGgga2V5ICd1c2VyR3JvdXAnXG4gICAqXG4gICAqIEBwYXJhbSB1c2VyR3JvdXBzXG4gICAqL1xuICBzZXRDdXJyZW50VXNlckdyb3Vwcyh1c2VyR3JvdXBzOiBVc2VyR3JvdXBzKSB7XG4gICAgY29uc3Qgb2JqID0ge1xuICAgICAgYWNjZXNzVG9rZW46ICd1c2VyR3JvdXBzJyxcbiAgICAgIGV4cGlyZXNBdDogTWF0aC5yb3VuZCgobmV3IERhdGUoKSkuZ2V0VGltZSgpIC8gMTAwMCArIDM2MDApLFxuICAgICAgc2NvcGVzOiB1c2VyR3JvdXBzLmdyb3Vwc1xuICAgIH07XG4gICAgdGhpcy5va3RhQXV0aC50b2tlbk1hbmFnZXIuYWRkKCd1c2VyR3JvdXBzJywgb2JqKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgc3RvcmVkIHVzZXJHcm91cHMgYW5kIHJlZnJlc2ggaWYgZXhwaXJlc1xuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgYXN5bmMgZ2V0TG9naW5Vc2VyR3JvdXBzKCk6IFByb21pc2U8VXNlckdyb3Vwcz4ge1xuICAgIGNvbnN0IHVzZXJHcm91cHNUb2tlbk9iaiA9IHRoaXMub2t0YUF1dGgudG9rZW5NYW5hZ2VyLmdldCgndXNlckdyb3VwcycpO1xuICAgIGNvbnN0IG5vd1NlY29uZCA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLyAxMDAwO1xuICAgIGlmICghdXNlckdyb3Vwc1Rva2VuT2JqIHx8IG5vd1NlY29uZCA+IHVzZXJHcm91cHNUb2tlbk9iai5leHBpcmVBdCkge1xuICAgICAgY29uc3QgdG1wVXNlckdyb3VwcyA9IGF3YWl0IHRoaXMuZ2V0VXNlckdyb3Vwcyh0aGlzLmdldFVzZXJJZCgpKTtcbiAgICAgIHRoaXMuc2V0Q3VycmVudFVzZXJHcm91cHModG1wVXNlckdyb3Vwcyk7XG4gICAgfVxuICAgIGNvbnN0IHVzZXJHcm91cHMgPSBuZXcgVXNlckdyb3VwcyhudWxsKTtcbiAgICB1c2VyR3JvdXBzLmdyb3VwcyA9IHRoaXMub2t0YUF1dGgudG9rZW5NYW5hZ2VyLmdldCgndXNlckdyb3VwcycpLnNjb3BlcztcbiAgICByZXR1cm4gdXNlckdyb3VwcztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY3VycmVudCBsb2dpbiB1c2VySW5mb1xuICAgKiBUT0RPOiB3ZSBjYW4gY2FjaGUgdXNlciBpbmZvIGluY2x1ZGVzIGdyb3VwcyBpbmZvcm1hdGlvbiB3aGVuIGZpbmlzaGVkIGxvZ2luXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBhc3luYyBnZXRVc2VySW5mbygpOiBQcm9taXNlPFVzZXJJbmZvPiB7XG4gICAgaWYgKHRoaXMuaXNMb2dpbigpKSB7XG4gICAgICBjb25zdCBva3RhVXNlckluZm8gPSBhd2FpdCB0aGlzLm9rdGEuZ2V0VXNlckluZm8odGhpcy5nZXRVc2VySWQoKSk7XG4gICAgICByZXR1cm4gYXdhaXQgbmV3IFVzZXJJbmZvKG9rdGFVc2VySW5mbyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdCgnbm90IGxvZ2luJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIGdldCB1c2VyR3JvdXAgYnkgZ2l2ZW4gdXNlcklkXG4gICAqXG4gICAqIEBwYXJhbSB1c2VySWRcbiAgICogQHJldHVybnNcbiAgICovXG4gIGFzeW5jIGdldFVzZXJHcm91cHModXNlcklkOiBzdHJpbmcpOiBQcm9taXNlPFVzZXJHcm91cHM+IHtcbiAgICBpZiAodGhpcy5pc0xvZ2luKCkpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IG9rdGFVc2VyR3JvdXBzID0gYXdhaXQgdGhpcy5va3RhLmdldFVzZXJHcm91cHModXNlcklkKTtcbiAgICAgICAgcmV0dXJuIGF3YWl0IG5ldyBVc2VyR3JvdXBzKG9rdGFVc2VyR3JvdXBzKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBjb25zb2xlLmxvZygnZ2V0VXNlckdyb3VwcyBlcnInLCBlcnIpO1xuICAgICAgICAvLyByZXR1cm4gbmV3IFVzZXJHcm91cHMobnVsbCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gaWYgYWxyZWFkeSBsb2dpbiBieSBjaGVjayB0aGUgZXhpc3RlbmNlIG9mIGFjY2Vzc1Rva2VuXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBpc0xvZ2luKCk6IGFueSB7XG4gICAgcmV0dXJuICEhdGhpcy5nZXRVc2VySWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWRpcmVjdCB0byB1cmwgZm9yIEdvb2dsZSBsb2dpblxuICAgKi9cbiAgbG9naW5XaXRoR29vZ2xlKHJlZGlyZWN0VXJsOiBzdHJpbmcpIHtcbiAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IGAke3RoaXMuYXV0aENvbmZpZy5nZXRVcmwoKX0vb2F1dGgyL3YxL2F1dGhvcml6ZT9gICtcbiAgICAgIGBpZHA9MG9hZHVsaHV6NzhTTVc4Y0QwaDcmY2xpZW50X2lkPSR7dGhpcy5hdXRoQ29uZmlnLmdldENsaWVudElkKCl9JnJlc3BvbnNlX3R5cGU9aWRfdG9rZW4mYCArXG4gICAgICBgcmVzcG9uc2VfbW9kZT1mcmFnbWVudCZzY29wZT1vcGVuaWQmc2NvcGU9ZW1haWwmc2NvcGU9cGljdHVyZSZzY29wZT1uYW1lJmAgK1xuICAgICAgYHN0YXRlPVdNNkQmbm9uY2U9WXNHNzZqbyZyZWRpcmVjdF91cmk9JHtyZWRpcmVjdFVybH1gO1xuICB9XG5cbiAgLyoqXG4gICAqIExvZ2luIGJ5IHVzZXJuYW1lIGFuZCBwYXNzd29yZFxuICAgKlxuICAgKiBAcGFyYW0gdXNlcm5hbWVcbiAgICogQHBhcmFtIHBhc3N3b3JkXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBhc3luYyBsb2dpbldpdGhQYXNzd29yZCh1c2VybmFtZTogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcbiAgICBjb25zdCBub25jZSA9IGF3YWl0IHRoaXMub2F1dGguY3JlYXRlQW5kU2F2ZU5vbmNlKCk7XG4gICAgY29uc3Qgc2lnbkluUmVzcG9uc2UgPSBhd2FpdCB0aGlzLm9rdGFBdXRoLnNpZ25Jbih7dXNlcm5hbWU6IHVzZXJuYW1lLCBwYXNzd29yZDogcGFzc3dvcmR9KTtcbiAgICBpZiAoc2lnbkluUmVzcG9uc2Uuc3RhdHVzID09PSAnU1VDQ0VTUycpIHtcbiAgICAgIGF3YWl0IHRoaXMub2t0YUF1dGgudG9rZW4uZ2V0V2l0aG91dFByb21wdCh7XG4gICAgICAgIGNsaWVudElkOiB0aGlzLmF1dGhDb25maWcuZ2V0Q2xpZW50SWQoKSxcbiAgICAgICAgcmVzcG9uc2VUeXBlOiBbJ2lkX3Rva2VuJywgJ3Rva2VuJ10sXG4gICAgICAgIHNjb3BlczogWydvcGVuaWQnLCAncHJvZmlsZScsICdlbWFpbCddLFxuICAgICAgICBzZXNzaW9uVG9rZW46IHNpZ25JblJlc3BvbnNlLnNlc3Npb25Ub2tlbixcbiAgICAgICAgbm9uY2U6IG5vbmNlLFxuICAgICAgICByZWRpcmVjdFVyaTogd2luZG93LmxvY2F0aW9uLm9yaWdpblxuICAgICAgfSk7XG4gICAgICBjb25zdCBzZXNzaW9uID0gYXdhaXQgdGhpcy5nZXRTZXNzaW9uKCk7XG4gICAgICBpZiAoc2Vzc2lvbi5zdGF0dXMgPT09ICdBQ1RJVkUnKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdzZXNzaW9uIEFDVElWRScpO1xuICAgICAgICB0aGlzLnNldFVzZXJJZChzZXNzaW9uLnVzZXJJZCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCdsb2dpbiBzdWNjZXNzZnVsbHknKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KCd1c2VybmFtZSBvciBwYXNzd29yZCBlcnJvcicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0IGFsbCBncm91cHNcbiAgICpcbiAgICogQHJldHVybnNcbiAgICovXG4gIHB1YmxpYyBhc3luYyBsaXN0R3JvdXBzKCkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLm9rdGEubGlzdEdyb3VwcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBzZXNzaW9uXG4gICAqXG4gICAqIEByZXR1cm5zXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0U2Vzc2lvbigpIHtcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5va3RhQXV0aC5zZXNzaW9uLmdldCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE5hdmlnYXRlIGJyb3dzZXIgdG8gbG9naW4gcGFnZVxuICAgKi9cbiAgcHVibGljIG5hdmlnYXRlVG9Mb2dpblBhZ2UoKSB7XG4gICAgY29uc29sZS5sb2coJ25hdmlnYXRlVG9Mb2dpblBhZ2U6JywgdGhpcy5hdXRoQ29uZmlnLmdldExvZ2luVXJsKCkpO1xuICAgIGRvY3VtZW50LmxvY2F0aW9uLmhyZWYgPSB0aGlzLmF1dGhDb25maWcuZ2V0TG9naW5VcmwoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBOYXZpZ2F0ZSBicm93c2VyIHRvIHJlZGlyZWN0IHBhZ2VcbiAgICovXG4gIG5hdmlnYXRlVG9SZWRpcmVjdFBhZ2UoKSB7XG4gICAgY29uc29sZS5sb2coJ25hdmlnYXRlVG9SZWRpcmVjdFBhZ2U6JywgdGhpcy5hdXRoQ29uZmlnLmdldFJlZGlyZWN0VXJsKCkpO1xuICAgIGRvY3VtZW50LmxvY2F0aW9uLmhyZWYgPSB0aGlzLmF1dGhDb25maWcuZ2V0UmVkaXJlY3RVcmwoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMb2dvdXQgY3VycmVudCB1c2VyIGFuZCBjbGVhciB0b2tlblxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKi9cbiAgbG9nb3V0KCkge1xuICAgIGlmICh0aGlzLmlzTG9naW4oKSkge1xuICAgICAgdGhpcy5va3RhQXV0aC50b2tlbk1hbmFnZXIuY2xlYXIoKTtcbiAgICAgIGNvbnNvbGUubG9nKCdzdGFydCB0byBsb2dvdXQnKTtcbiAgICAgIHRoaXMub2t0YUF1dGguc2lnbk91dCgpLnRoZW4oKCkgPT4ge1xuICAgICAgICBjb25zb2xlLmxvZygnbG9nb3V0IGRvbmUsIHRvIG5hdmlnYXRlJywgdGhpcy5hdXRoQ29uZmlnLmdldExvZ2luVXJsKCkpO1xuICAgICAgICB0aGlzLm5hdmlnYXRlVG9Mb2dpblBhZ2UoKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgfVxuICB9XG59XG4iXX0=