UNPKG

17.9 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6
7var _logger = require('./logger');
8
9var _logger2 = _interopRequireDefault(_logger);
10
11var _util = require('util');
12
13var _keyid = require('./keyid');
14
15var _httpSignatureParser = require('./http-signature-parser');
16
17var _httpSignatureParser2 = _interopRequireDefault(_httpSignatureParser);
18
19var _authContext = require('@leisurelink/auth-context');
20
21var _request = require('./schemas/request');
22
23var _request2 = _interopRequireDefault(_request);
24
25var _bluebird = require('bluebird');
26
27var _bluebird2 = _interopRequireDefault(_bluebird);
28
29var _httpSignature = require('http-signature');
30
31var _httpSignature2 = _interopRequireDefault(_httpSignature);
32
33var _schemas = require('./schemas');
34
35var _trustedBaseSchema = require('./schemas/trusted-base-schema');
36
37function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
38
39const logger = (0, _logger2.default)('base');
40
41function transformForLog(value) {
42 if (_authContext.AuthContext.isContext(value)) {
43 return value.toAuditString();
44 }
45 if (typeof value === 'object' && value !== null) {
46 return (0, _util.inspect)(value, false, 9);
47 }
48 return '' + value;
49}
50
51function checkVerified(auth) {
52 if (!auth.verified) {
53 logger.debug(`Invalid authority; unverifiable: ${ transformForLog(auth) }.`);
54 return null;
55 }
56 return auth;
57}
58
59function checkVerifiedAndNotExpired(auth) {
60 if (!checkVerified(auth)) {
61 return null;
62 }
63 if (auth.isExpired) {
64 logger.debug(`Invalid authority; expired: ${ transformForLog(auth) }.`);
65 return null;
66 }
67 return auth;
68}
69
70const DEFA_LANG = 'en-US';
71let POSSIBLY_OVERRIDDEN_DEFA_LANG = process.env.AUTH_DEFAULT_LANG || DEFA_LANG;
72
73let $keyId = Symbol('keyId');
74let $lang = Symbol('lang');
75let $scope = Symbol('scope');
76let $resolveEndpointKey = Symbol('resolveEndpointKey');
77let $resolveEndpointClaims = Symbol('resolveEndpointClaims');
78
79class TrustedEndpoint {
80 constructor(opts) {
81 const options = (0, _schemas.validate)(opts, _trustedBaseSchema.optionsSchema);
82
83 this[$lang] = options.lang || POSSIBLY_OVERRIDDEN_DEFA_LANG;
84 this[$scope] = options.scope;
85 this[$keyId] = options.keyId instanceof _keyid.KeyId ? options.keyId : _keyid.KeyId.parse(options.keyId);
86 this[$resolveEndpointKey] = options.resolveEndpointKey;
87 this[$resolveEndpointClaims] = options.resolveEndpointClaims;
88
89 logger.debug(`new ${ this.constructor.name }({ keyId: '${ this.keyId }', scope = ${ this[$scope] }`);
90 }
91
92 get keyId() {
93 return this[$keyId];
94 }
95
96 get lang() {
97 return this[$lang];
98 }
99
100 verify(token) {
101 let scope = this[$scope];
102 return new _bluebird2.default((resolve, reject) => {
103 scope.verify(token, (err, ctx) => {
104 if (err) reject(err);else resolve(ctx);
105 });
106 });
107 }
108
109 resolveAndVerifyClaims(keyId) {
110 keyId = keyId instanceof _keyid.KeyId ? keyId : _keyid.KeyId.parse(keyId);
111 return this[$resolveEndpointClaims](this.lang, keyId.principalId).then(token => {
112 logger.debug(`resolved endpoint claims: ${ token }`);
113 return this.verify(token);
114 }).then(checkVerifiedAndNotExpired);
115 }
116
117 resolveEndpointKey(keyId) {
118 return this[$resolveEndpointKey](this.lang, keyId);
119 }
120
121 getLocalAuth() {
122 return this.resolveAndVerifyClaims(this.keyId);
123 }
124
125 getRemoteAuth(request) {
126 (0, _schemas.validate)(request, _request2.default);
127 let self = this;
128 let auth = {};
129 let parser = new _httpSignatureParser2.default(_httpSignature2.default);
130 return new _bluebird2.default((resolve, reject) => {
131 let parsed = parser.parseRequest(request);
132 return this.resolveEndpointKey(parsed.keyId).then(key => parser.verifySignature(parsed, key)).then(parsed => {
133 if (parsed) {
134 return this.resolveAndVerifyClaims(parsed.keyId);
135 }
136 return null;
137 }).then(endpoint => {
138 if (endpoint) {
139 logger.debug(`endpoint authority: ${ endpoint }`);
140 auth.remoteEndpoint = endpoint;
141 }
142 if (request.headers['x-authentic-user']) {
143 logger.debug('X-Authentic-User header contains JWT; verifying user authority...');
144 return self.verify(request.headers['x-authentic-user']).then(checkVerifiedAndNotExpired);
145 }
146 if (parsed.params.jwt) {
147 logger.debug('Signature contains JWT; verifying user authority...');
148 return self.verify(parsed.params.jwt).then(checkVerifiedAndNotExpired);
149 }
150 return null;
151 }).then(user => {
152 if (user) {
153 logger.debug(`user authority: ${ user }`);
154 auth.remoteUser = user;
155 return resolve(auth);
156 }
157 if (request.headers['x-authentic-origin']) {
158 logger.debug('X-Authentic-Origin header contains JWT; verifying originating endpoint authority...');
159 return self.verify(request.headers['x-authentic-origin'])
160 // be more lax with the expiration on originating endpoint, since it could take some time for messaging to flow through the system
161 .then(checkVerified);
162 }
163 return null;
164 }).then(originatingEndpoint => {
165 if (originatingEndpoint) {
166 logger.debug(`originatingEndpoint: ${ originatingEndpoint }`);
167 auth.originatingEndpoint = originatingEndpoint;
168 }
169 return resolve(auth);
170 }).catch(e => reject(e));
171 });
172 }
173}
174
175exports.default = TrustedEndpoint;
176module.exports = exports['default'];
177//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL2xpYi90cnVzdGVkLWVuZHBvaW50LWJhc2UuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7Ozs7QUFDQTs7QUFDQTs7QUFDQTs7OztBQUNBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUVBOztBQUNBOzs7O0FBRUEsTUFBTSxTQUFTLHNCQUFhLE1BQWIsQ0FBVDs7QUFFTixTQUFTLGVBQVQsQ0FBeUIsS0FBekIsRUFBZ0M7QUFDOUIsTUFBSSx5QkFBWSxTQUFaLENBQXNCLEtBQXRCLENBQUosRUFBa0M7QUFDaEMsV0FBTyxNQUFNLGFBQU4sRUFBUCxDQURnQztHQUFsQztBQUdBLE1BQUksT0FBTyxLQUFQLEtBQWtCLFFBQWxCLElBQThCLFVBQVUsSUFBVixFQUFnQjtBQUNoRCxXQUFPLG1CQUFRLEtBQVIsRUFBZSxLQUFmLEVBQXNCLENBQXRCLENBQVAsQ0FEZ0Q7R0FBbEQ7QUFHQSxTQUFPLEtBQUssS0FBTCxDQVB1QjtDQUFoQzs7QUFVQSxTQUFTLGFBQVQsQ0FBdUIsSUFBdkIsRUFBNkI7QUFDM0IsTUFBSSxDQUFDLEtBQUssUUFBTCxFQUFlO0FBQ2xCLFdBQU8sS0FBUCxDQUFhLENBQUMsaUNBQUQsR0FBb0MsZ0JBQWdCLElBQWhCLENBQXBDLEVBQTBELENBQTFELENBQWIsRUFEa0I7QUFFbEIsV0FBTyxJQUFQLENBRmtCO0dBQXBCO0FBSUEsU0FBTyxJQUFQLENBTDJCO0NBQTdCOztBQVFBLFNBQVMsMEJBQVQsQ0FBb0MsSUFBcEMsRUFBMEM7QUFDeEMsTUFBSSxDQUFDLGNBQWMsSUFBZCxDQUFELEVBQXFCO0FBQ3ZCLFdBQU8sSUFBUCxDQUR1QjtHQUF6QjtBQUdBLE1BQUksS0FBSyxTQUFMLEVBQWdCO0FBQ2xCLFdBQU8sS0FBUCxDQUFhLENBQUMsNEJBQUQsR0FBK0IsZ0JBQWdCLElBQWhCLENBQS9CLEVBQXFELENBQXJELENBQWIsRUFEa0I7QUFFbEIsV0FBTyxJQUFQLENBRmtCO0dBQXBCO0FBSUEsU0FBTyxJ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U0FBVjtBQUtBLFlBQUksUUFBUSxPQUFSLENBQWdCLG9CQUFoQixDQUFKLEVBQTJDO0FBQ3pDLGlCQUFPLEtBQVAsQ0FBYSxxRkFBYixFQUR5QztBQUV6QyxpQkFBTyxLQUFLLE1BQUwsQ0FBWSxRQUFRLE9BQVIsQ0FBZ0Isb0JBQWhCLENBQVo7O1dBRUosSUFGSSxDQUVDLGFBRkQsQ0FBUCxDQUZ5QztTQUEzQztBQU1BLGVBQU8sSUFBUCxDQVpjO09BQVIsQ0F4QkgsQ0FxQ0YsSUFyQ0UsQ0FxQ0csdUJBQXVCO0FBQzdCLFlBQUksbUJBQUosRUFBeUI7QUFDdkIsaUJBQU8sS0FBUCxDQUFhLENBQUMscUJBQUQsR0FBd0IsbUJBQXhCLEVBQTRDLENBQXpELEVBRHVCO0FBRXZCLGVBQUssbUJBQUwsR0FBMkIsbUJBQTNCLENBRnVCO1NBQXpCO0FBSUEsZUFBTyxRQUFRLElBQVIsQ0FBUCxDQUw2QjtPQUF2QixDQXJDSCxDQTRDSixLQTVDSSxDQTRDRSxLQUFLLE9BQU8sQ0FBUCxDQUFMLENBNUNULENBRnFDO0tBQXBCLENBQW5CLENBTHFCO0dBQXZCO0NBbERGOztrQkEyR2UiLCJmaWxlIjoidHJ1c3RlZC1lbmRwb2ludC1iYXNlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNyZWF0ZUxvZ2dlciBmcm9tICcuL2xvZ2dlcic7XG5pbXBvcnQgeyBpbnNwZWN0IH0gZnJvbSAndXRpbCc7XG5pbXBvcnQgeyBLZXlJZCB9IGZyb20gJy4va2V5aWQnO1xuaW1wb3J0IFNpZ1BhcnNlciBmcm9tICcuL2h0dHAtc2lnbmF0dXJlLXBhcnNlcic7XG5pbXBvcnQgeyBBdXRoQ29udGV4dCB9IGZyb20gJ0BsZWlzdXJlbGluay9hdXRoLWNvbnRleHQnO1xuaW1wb3J0IHJlcXVlc3RTY2hlbWEgZnJvbSAnLi9zY2hlbWFzL3JlcXVlc3QnO1xuaW1wb3J0IFByb21pc2UgZnJvbSAnYmx1ZWJpcmQnO1xuaW1wb3J0IEh0dHBTaWcgZnJvbSAnaHR0cC1zaWduYXR1cmUnO1xuXG5pbXBvcnQgeyB2YWxpZGF0ZSB9IGZyb20gJy4vc2NoZW1hcyc7XG5pbXBvcnQgeyBvcHRpb25zU2NoZW1hIH0gZnJvbSAnLi9zY2hlbWFzL3RydXN0ZWQtYmFzZS1zY2hlbWEnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ2Jhc2UnKTtcblxuZnVuY3Rpb24gdHJhbnNmb3JtRm9yTG9nKHZhbHVlKSB7XG4gIGlmIChBdXRoQ29udGV4dC5pc0NvbnRleHQodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlLnRvQXVkaXRTdHJpbmcoKTtcbiAgfVxuICBpZiAodHlwZW9mKHZhbHVlKSA9PT0gJ29iamVjdCcgJiYgdmFsdWUgIT09IG51bGwpIHtcbiAgICByZXR1cm4gaW5zcGVjdCh2YWx1ZSwgZmFsc2UsIDkpO1xuICB9XG4gIHJldHVybiAnJyArIHZhbHVlO1xufVxuXG5mdW5jdGlvbiBjaGVja1ZlcmlmaWVkKGF1dGgpIHtcbiAgaWYgKCFhdXRoLnZlcmlmaWVkKSB7XG4gICAgbG9nZ2VyLmRlYnVnKGBJbnZhbGlkIGF1dGhvcml0eTsgdW52ZXJpZmlhYmxlOiAke3RyYW5zZm9ybUZvckxvZyhhdXRoKX0uYCk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgcmV0dXJuIGF1dGg7XG59XG5cbmZ1bmN0aW9uIGNoZWNrVmVyaWZpZWRBbmROb3RFeHBpcmVkKGF1dGgpIHtcbiAgaWYgKCFjaGVja1ZlcmlmaWVkKGF1dGgpKXtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuICBpZiAoYXV0aC5pc0V4cGlyZWQpIHtcbiAgICBsb2dnZXIuZGVidWcoYEludmFsaWQgYXV0aG9yaXR5OyBleHBpcmVkOiAke3RyYW5zZm9ybUZvckxvZyhhdXRoKX0uYCk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgcmV0dXJuIGF1dGg7XG59XG5cbmNvbnN0IERFRkFfTEFORyA9ICdlbi1VUyc7XG5sZXQgUE9TU0lCTFlfT1ZFUlJJRERFTl9ERUZBX0xBTkcgPSBwcm9jZXNzLmVudi5BVVRIX0RFRkFVTFRfTEFORyB8fCBERUZBX0xBTkc7XG5cbmxldCAka2V5SWQgPSBTeW1ib2woJ2tleUlkJyk7XG5sZXQgJGxhbmcgPSBTeW1ib2woJ2xhbmcnKTtcbmxldCAkc2NvcGUgPSBTeW1ib2woJ3Njb3BlJyk7XG5sZXQgJHJlc29sdmVFbmRwb2ludEtleSA9IFN5bWJvbCgncmVzb2x2ZUVuZHBvaW50S2V5Jyk7XG5sZXQgJHJlc29sdmVFbmRwb2ludENsYWltcyA9IFN5bWJvbCgncmVzb2x2ZUVuZHBvaW50Q2xhaW1zJyk7XG5cbmNsYXNzIFRydXN0ZWRFbmRwb2ludCB7XG4gIGNvbnN0cnVjdG9yKG9wdHMpIHtcbiAgICBjb25zdCBvcHRpb25zID0gdmFsaWRhdGUob3B0cywgb3B0aW9uc1NjaGVtYSk7XG5cbiAgICB0aGlzWyRsYW5nXSA9IG9wdGlvbnMubGFuZyB8fCBQT1NTSUJMWV9PVkVSUklEREVOX0RFRkFfTEFORztcbiAgICB0aGlzWyRzY29wZV0gPSBvcHRpb25zLnNjb3BlO1xuICAgIHRoaXNbJGtleUlkXSA9IChvcHRpb25zLmtleUlkIGluc3RhbmNlb2YgS2V5SWQpID8gb3B0aW9ucy5rZXlJZCA6IEtleUlkLnBhcnNlKG9wdGlvbnMua2V5SWQpO1xuICAgIHRoaXNbJHJlc29sdmVFbmRwb2ludEtleV0gPSBvcHRpb25zLnJlc29sdmVFbmRwb2ludEtleTtcbiAgICB0aGlzWyRyZXNvbHZlRW5kcG9pbnRDbGFpbXNdID0gb3B0aW9ucy5yZXNvbHZlRW5kcG9pbnRDbGFpbXM7XG5cbiAgICBsb2dnZXIuZGVidWcoYG5ldyAke3RoaXMuY29uc3RydWN0b3IubmFtZX0oeyBrZXlJZDogJyR7dGhpcy5rZXlJZH0nLCBzY29wZSA9ICR7dGhpc1skc2NvcGVdfWApO1xuICB9XG5cbiAgZ2V0IGtleUlkKCkge1xuICAgIHJldHVybiB0aGlzWyRrZXlJZF07XG4gIH1cblxuICBnZXQgbGFuZygpIHtcbiAgICByZXR1cm4gdGhpc1skbGFuZ107XG4gIH1cblxuICB2ZXJpZnkodG9rZW4pIHtcbiAgICBsZXQgc2NvcGUgPSB0aGlzWyRzY29wZV07XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKFxuICAgICAgKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBzY29wZS52ZXJpZnkodG9rZW4sIChlcnIsIGN0eCkgPT4ge1xuICAgICAgICAgIGlmIChlcnIpIHJlamVjdChlcnIpO1xuICAgICAgICAgIGVsc2UgcmVzb2x2ZShjdHgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcmVzb2x2ZUFuZFZlcmlmeUNsYWltcyhrZXlJZCkge1xuICAgIGtleUlkID0gKGtleUlkIGluc3RhbmNlb2YgS2V5SWQpID8ga2V5SWQgOiBLZXlJZC5wYXJzZShrZXlJZCk7XG4gICAgcmV0dXJuIHRoaXNbJHJlc29sdmVFbmRwb2ludENsYWltc10odGhpcy5sYW5nLCBrZXlJZC5wcmluY2lwYWxJZClcbiAgICAgIC50aGVuKHRva2VuID0+IHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKGByZXNvbHZlZCBlbmRwb2ludCBjbGFpbXM6ICR7dG9rZW59YCk7XG4gICAgICAgIHJldHVybiB0aGlzLnZlcmlmeSh0b2tlbik7XG4gICAgICB9KVxuICAgICAgLnRoZW4oY2hlY2tWZXJpZmllZEFuZE5vdEV4cGlyZWQpO1xuICB9XG5cbiAgcmVzb2x2ZUVuZHBvaW50S2V5KGtleUlkKSB7XG4gICAgcmV0dXJuIHRoaXNbJHJlc29sdmVFbmRwb2ludEtleV0odGhpcy5sYW5nLCBrZXlJZCk7XG4gIH1cblxuICBnZXRMb2NhbEF1dGgoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVzb2x2ZUFuZFZlcmlmeUNsYWltcyh0aGlzLmtleUlkKTtcbiAgfVxuXG4gIGdldFJlbW90ZUF1dGgocmVxdWVzdCkge1xuICAgIHZhbGlkYXRlKHJlcXVlc3QsIHJlcXVlc3RTY2hlbWEpO1xuICAgIGxldCBzZWxmID0gdGhpcztcbiAgICBsZXQgYXV0aCA9IHt9O1xuICAgIGxldCBwYXJzZXIgPSBuZXcgU2lnUGFyc2VyKEh0dHBTaWcpO1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PntcbiAgICAgIGxldCBwYXJzZWQgPSBwYXJzZXIucGFyc2VSZXF1ZXN0KHJlcXVlc3QpO1xuICAgICAgcmV0dXJuIHRoaXMucmVzb2x2ZUVuZHBvaW50S2V5KHBhcnNlZC5rZXlJZClcbiAgICAgICAgLnRoZW4oa2V5ID0+IHBhcnNlci52ZXJpZnlTaWduYXR1cmUocGFyc2VkLCBrZXkpKVxuICAgICAgICAudGhlbihwYXJzZWQgPT4ge1xuICAgICAgICAgIGlmIChwYXJzZWQpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc29sdmVBbmRWZXJpZnlDbGFpbXMocGFyc2VkLmtleUlkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0pXG4gICAgICAgIC50aGVuKGVuZHBvaW50ID0+IHtcbiAgICAgICAgICBpZiAoZW5kcG9pbnQpIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgZW5kcG9pbnQgYXV0aG9yaXR5OiAke2VuZHBvaW50fWApO1xuICAgICAgICAgICAgYXV0aC5yZW1vdGVFbmRwb2ludCA9IGVuZHBvaW50O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocmVxdWVzdC5oZWFkZXJzWyd4LWF1dGhlbnRpYy11c2VyJ10pIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnWC1BdXRoZW50aWMtVXNlciBoZWFkZXIgY29udGFpbnMgSldUOyB2ZXJpZnlpbmcgdXNlciBhdXRob3JpdHkuLi4nKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLnZlcmlmeShyZXF1ZXN0LmhlYWRlcnNbJ3gtYXV0aGVudGljLXVzZXInXSlcbiAgICAgICAgICAgICAgLnRoZW4oY2hlY2tWZXJpZmllZEFuZE5vdEV4cGlyZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAocGFyc2VkLnBhcmFtcy5qd3QpIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnU2lnbmF0dXJlIGNvbnRhaW5zIEpXVDsgdmVyaWZ5aW5nIHVzZXIgYXV0aG9yaXR5Li4uJyk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZi52ZXJpZnkocGFyc2VkLnBhcmFtcy5qd3QpXG4gICAgICAgICAgICAgIC50aGVuKGNoZWNrVmVyaWZpZWRBbmROb3RFeHBpcmVkKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH0pLnRoZW4odXNlciA9PiB7XG4gICAgICAgICAgaWYgKHVzZXIpIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZyhgdXNlciBhdXRob3JpdHk6ICR7dXNlcn1gKTtcbiAgICAgICAgICAgIGF1dGgucmVtb3RlVXNlciA9IHVzZXI7XG4gICAgICAgICAgICByZXR1cm4gcmVzb2x2ZShhdXRoKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHJlcXVlc3QuaGVhZGVyc1sneC1hdXRoZW50aWMtb3JpZ2luJ10pIHtcbiAgICAgICAgICAgIGxvZ2dlci5kZWJ1ZygnWC1BdXRoZW50aWMtT3JpZ2luIGhlYWRlciBjb250YWlucyBKV1Q7IHZlcmlmeWluZyBvcmlnaW5hdGluZyBlbmRwb2ludCBhdXRob3JpdHkuLi4nKTtcbiAgICAgICAgICAgIHJldHVybiBzZWxmLnZlcmlmeShyZXF1ZXN0LmhlYWRlcnNbJ3gtYXV0aGVudGljLW9yaWdpbiddKVxuICAgICAgICAgICAgICAvLyBiZSBtb3JlIGxheCB3aXRoIHRoZSBleHBpcmF0aW9uIG9uIG9yaWdpbmF0aW5nIGVuZHBvaW50LCBzaW5jZSBpdCBjb3VsZCB0YWtlIHNvbWUgdGltZSBmb3IgbWVzc2FnaW5nIHRvIGZsb3cgdGhyb3VnaCB0aGUgc3lzdGVtXG4gICAgICAgICAgICAgIC50aGVuKGNoZWNrVmVyaWZpZWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSkudGhlbihvcmlnaW5hdGluZ0VuZHBvaW50ID0+IHtcbiAgICAgICAgICBpZiAob3JpZ2luYXRpbmdFbmRwb2ludCkge1xuICAgICAgICAgICAgbG9nZ2VyLmRlYnVnKGBvcmlnaW5hdGluZ0VuZHBvaW50OiAke29yaWdpbmF0aW5nRW5kcG9pbnR9YCk7XG4gICAgICAgICAgICBhdXRoLm9yaWdpbmF0aW5nRW5kcG9pbnQgPSBvcmlnaW5hdGluZ0VuZHBvaW50O1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gcmVzb2x2ZShhdXRoKTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGUgPT4gcmVqZWN0KGUpKTtcbiAgICB9KTtcblxuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IFRydXN0ZWRFbmRwb2ludDtcbiJdfQ==
\No newline at end of file