1 | import { urlBase64Decode } from '../../helpers';
|
2 | export class NbAuthToken {
|
3 | constructor() {
|
4 | this.payload = null;
|
5 | }
|
6 | getName() {
|
7 | return this.constructor.NAME;
|
8 | }
|
9 | getPayload() {
|
10 | return this.payload;
|
11 | }
|
12 | }
|
13 | export class NbAuthTokenNotFoundError extends Error {
|
14 | constructor(message) {
|
15 | super(message);
|
16 | Object.setPrototypeOf(this, new.target.prototype);
|
17 | }
|
18 | }
|
19 | export class NbAuthIllegalTokenError extends Error {
|
20 | constructor(message) {
|
21 | super(message);
|
22 | Object.setPrototypeOf(this, new.target.prototype);
|
23 | }
|
24 | }
|
25 | export class NbAuthEmptyTokenError extends NbAuthIllegalTokenError {
|
26 | constructor(message) {
|
27 | super(message);
|
28 | Object.setPrototypeOf(this, new.target.prototype);
|
29 | }
|
30 | }
|
31 | export class NbAuthIllegalJWTTokenError extends NbAuthIllegalTokenError {
|
32 | constructor(message) {
|
33 | super(message);
|
34 | Object.setPrototypeOf(this, new.target.prototype);
|
35 | }
|
36 | }
|
37 | export function nbAuthCreateToken(tokenClass, token, ownerStrategyName, createdAt) {
|
38 | return new tokenClass(token, ownerStrategyName, createdAt);
|
39 | }
|
40 | export function decodeJwtPayload(payload) {
|
41 | if (payload.length === 0) {
|
42 | throw new NbAuthEmptyTokenError('Cannot extract from an empty payload.');
|
43 | }
|
44 | const parts = payload.split('.');
|
45 | if (parts.length !== 3) {
|
46 | throw new NbAuthIllegalJWTTokenError(`The payload ${payload} is not valid JWT payload and must consist of three parts.`);
|
47 | }
|
48 | let decoded;
|
49 | try {
|
50 | decoded = urlBase64Decode(parts[1]);
|
51 | }
|
52 | catch (e) {
|
53 | throw new NbAuthIllegalJWTTokenError(`The payload ${payload} is not valid JWT payload and cannot be parsed.`);
|
54 | }
|
55 | if (!decoded) {
|
56 | throw new NbAuthIllegalJWTTokenError(`The payload ${payload} is not valid JWT payload and cannot be decoded.`);
|
57 | }
|
58 | return JSON.parse(decoded);
|
59 | }
|
60 | /**
|
61 | * Wrapper for simple (text) token
|
62 | */
|
63 | export class NbAuthSimpleToken extends NbAuthToken {
|
64 | constructor(token, ownerStrategyName, createdAt) {
|
65 | super();
|
66 | this.token = token;
|
67 | this.ownerStrategyName = ownerStrategyName;
|
68 | this.createdAt = createdAt;
|
69 | try {
|
70 | this.parsePayload();
|
71 | }
|
72 | catch (err) {
|
73 | if (!(err instanceof NbAuthTokenNotFoundError)) {
|
74 | // token is present but has got a problem, including illegal
|
75 | throw err;
|
76 | }
|
77 | }
|
78 | this.createdAt = this.prepareCreatedAt(createdAt);
|
79 | }
|
80 | parsePayload() {
|
81 | this.payload = null;
|
82 | }
|
83 | prepareCreatedAt(date) {
|
84 | return date ? date : new Date();
|
85 | }
|
86 | /**
|
87 | * Returns the token's creation date
|
88 | * @returns {Date}
|
89 | */
|
90 | getCreatedAt() {
|
91 | return this.createdAt;
|
92 | }
|
93 | /**
|
94 | * Returns the token value
|
95 | * @returns string
|
96 | */
|
97 | getValue() {
|
98 | return this.token;
|
99 | }
|
100 | getOwnerStrategyName() {
|
101 | return this.ownerStrategyName;
|
102 | }
|
103 | /**
|
104 | * Is non empty and valid
|
105 | * @returns {boolean}
|
106 | */
|
107 | isValid() {
|
108 | return !!this.getValue();
|
109 | }
|
110 | /**
|
111 | * Validate value and convert to string, if value is not valid return empty string
|
112 | * @returns {string}
|
113 | */
|
114 | toString() {
|
115 | return !!this.token ? this.token : '';
|
116 | }
|
117 | }
|
118 | NbAuthSimpleToken.NAME = 'nb:auth:simple:token';
|
119 | /**
|
120 | * Wrapper for JWT token with additional methods.
|
121 | */
|
122 | export class NbAuthJWTToken extends NbAuthSimpleToken {
|
123 | /**
|
124 | * for JWT token, the iat (issued at) field of the token payload contains the creation Date
|
125 | */
|
126 | prepareCreatedAt(date) {
|
127 | const decoded = this.getPayload();
|
128 | return decoded && decoded.iat ? new Date(Number(decoded.iat) * 1000) : super.prepareCreatedAt(date);
|
129 | }
|
130 | /**
|
131 | * Returns payload object
|
132 | * @returns any
|
133 | */
|
134 | parsePayload() {
|
135 | if (!this.token) {
|
136 | throw new NbAuthTokenNotFoundError('Token not found. ');
|
137 | }
|
138 | this.payload = decodeJwtPayload(this.token);
|
139 | }
|
140 | /**
|
141 | * Returns expiration date
|
142 | * @returns Date
|
143 | */
|
144 | getTokenExpDate() {
|
145 | const decoded = this.getPayload();
|
146 | if (decoded && !decoded.hasOwnProperty('exp')) {
|
147 | return null;
|
148 | }
|
149 | const date = new Date(0);
|
150 | date.setUTCSeconds(decoded.exp); // 'cause jwt token are set in seconds
|
151 | return date;
|
152 | }
|
153 | /**
|
154 | * Is data expired
|
155 | * @returns {boolean}
|
156 | */
|
157 | isValid() {
|
158 | return super.isValid() && (!this.getTokenExpDate() || new Date() < this.getTokenExpDate());
|
159 | }
|
160 | }
|
161 | NbAuthJWTToken.NAME = 'nb:auth:jwt:token';
|
162 | const prepareOAuth2Token = (data) => {
|
163 | if (typeof data === 'string') {
|
164 | try {
|
165 | return JSON.parse(data);
|
166 | }
|
167 | catch (e) { }
|
168 | }
|
169 | return data;
|
170 | };
|
171 | /**
|
172 | * Wrapper for OAuth2 token whose access_token is a JWT Token
|
173 | */
|
174 | export class NbAuthOAuth2Token extends NbAuthSimpleToken {
|
175 | constructor(data = {}, ownerStrategyName, createdAt) {
|
176 | // we may get it as string when retrieving from a storage
|
177 | super(prepareOAuth2Token(data), ownerStrategyName, createdAt);
|
178 | }
|
179 | /**
|
180 | * Returns the token value
|
181 | * @returns string
|
182 | */
|
183 | getValue() {
|
184 | return this.token.access_token;
|
185 | }
|
186 | /**
|
187 | * Returns the refresh token
|
188 | * @returns string
|
189 | */
|
190 | getRefreshToken() {
|
191 | return this.token.refresh_token;
|
192 | }
|
193 | /**
|
194 | * put refreshToken in the token payload
|
195 | * @param refreshToken
|
196 | */
|
197 | setRefreshToken(refreshToken) {
|
198 | this.token.refresh_token = refreshToken;
|
199 | }
|
200 | /**
|
201 | * Parses token payload
|
202 | * @returns any
|
203 | */
|
204 | parsePayload() {
|
205 | if (!this.token) {
|
206 | throw new NbAuthTokenNotFoundError('Token not found.');
|
207 | }
|
208 | else {
|
209 | if (!Object.keys(this.token).length) {
|
210 | throw new NbAuthEmptyTokenError('Cannot extract payload from an empty token.');
|
211 | }
|
212 | }
|
213 | this.payload = this.token;
|
214 | }
|
215 | /**
|
216 | * Returns the token type
|
217 | * @returns string
|
218 | */
|
219 | getType() {
|
220 | return this.token.token_type;
|
221 | }
|
222 | /**
|
223 | * Is data expired
|
224 | * @returns {boolean}
|
225 | */
|
226 | isValid() {
|
227 | return super.isValid() && (!this.getTokenExpDate() || new Date() < this.getTokenExpDate());
|
228 | }
|
229 | /**
|
230 | * Returns expiration date
|
231 | * @returns Date
|
232 | */
|
233 | getTokenExpDate() {
|
234 | if (!this.token.hasOwnProperty('expires_in')) {
|
235 | return null;
|
236 | }
|
237 | return new Date(this.createdAt.getTime() + Number(this.token.expires_in) * 1000);
|
238 | }
|
239 | /**
|
240 | * Convert to string
|
241 | * @returns {string}
|
242 | */
|
243 | toString() {
|
244 | return JSON.stringify(this.token);
|
245 | }
|
246 | }
|
247 | NbAuthOAuth2Token.NAME = 'nb:auth:oauth2:token';
|
248 | /**
|
249 | * Wrapper for OAuth2 token embedding JWT tokens
|
250 | */
|
251 | export class NbAuthOAuth2JWTToken extends NbAuthOAuth2Token {
|
252 | parsePayload() {
|
253 | super.parsePayload();
|
254 | this.parseAccessTokenPayload();
|
255 | }
|
256 | parseAccessTokenPayload() {
|
257 | const accessToken = this.getValue();
|
258 | if (!accessToken) {
|
259 | throw new NbAuthTokenNotFoundError('access_token key not found.');
|
260 | }
|
261 | this.accessTokenPayload = decodeJwtPayload(accessToken);
|
262 | }
|
263 | /**
|
264 | * Returns access token payload
|
265 | * @returns any
|
266 | */
|
267 | getAccessTokenPayload() {
|
268 | return this.accessTokenPayload;
|
269 | }
|
270 | /**
|
271 | * for Oauth2 JWT token, the iat (issued at) field of the access_token payload
|
272 | */
|
273 | prepareCreatedAt(date) {
|
274 | const payload = this.accessTokenPayload;
|
275 | return payload && payload.iat ? new Date(Number(payload.iat) * 1000) : super.prepareCreatedAt(date);
|
276 | }
|
277 | /**
|
278 | * Is token valid
|
279 | * @returns {boolean}
|
280 | */
|
281 | isValid() {
|
282 | return this.accessTokenPayload && super.isValid();
|
283 | }
|
284 | /**
|
285 | * Returns expiration date :
|
286 | * - exp if set,
|
287 | * - super.getExpDate() otherwise
|
288 | * @returns Date
|
289 | */
|
290 | getTokenExpDate() {
|
291 | if (this.accessTokenPayload && this.accessTokenPayload.hasOwnProperty('exp')) {
|
292 | const date = new Date(0);
|
293 | date.setUTCSeconds(this.accessTokenPayload.exp);
|
294 | return date;
|
295 | }
|
296 | else {
|
297 | return super.getTokenExpDate();
|
298 | }
|
299 | }
|
300 | }
|
301 | NbAuthOAuth2JWTToken.NAME = 'nb:auth:oauth2:jwt:token';
|
302 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvZnJhbWV3b3JrL2F1dGgvc2VydmljZXMvdG9rZW4vdG9rZW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVoRCxNQUFNLE9BQWdCLFdBQVc7SUFBakM7UUFFWSxZQUFPLEdBQVEsSUFBSSxDQUFDO0lBZ0JoQyxDQUFDO0lBUEMsT0FBTztRQUNMLE9BQVEsSUFBSSxDQUFDLFdBQWdDLENBQUMsSUFBSSxDQUFDO0lBQ3JELENBQUM7SUFFRCxVQUFVO1FBQ1IsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTyx3QkFBeUIsU0FBUSxLQUFLO0lBQ2pELFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTyx1QkFBd0IsU0FBUSxLQUFLO0lBQ2hELFlBQVksT0FBZTtRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3BELENBQUM7Q0FDRjtBQUVELE1BQU0sT0FBTyxxQkFBc0IsU0FBUSx1QkFBdUI7SUFDaEUsWUFBWSxPQUFlO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNmLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDcEQsQ0FBQztDQUNGO0FBRUQsTUFBTSxPQUFPLDBCQUEyQixTQUFRLHVCQUF1QjtJQUNy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Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgdXJsQmFzZTY0RGVjb2RlIH0gZnJvbSAnLi4vLi4vaGVscGVycyc7XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBOYkF1dGhUb2tlbiB7XG5cbiAgcHJvdGVjdGVkIHBheWxvYWQ6IGFueSA9IG51bGw7XG5cbiAgYWJzdHJhY3QgZ2V0VmFsdWUoKTogc3RyaW5nO1xuICBhYnN0cmFjdCBpc1ZhbGlkKCk6IGJvb2xlYW47XG4gIC8vIHRoZSBzdHJhdGVneSBuYW1lIHVzZWQgdG8gYWNxdWlyZSB0aGlzIHRva2VuIChuZWVkZWQgZm9yIHJlZnJlc2hpbmcgdG9rZW4pXG4gIGFic3RyYWN0IGdldE93bmVyU3RyYXRlZ3lOYW1lKCk6IHN0cmluZztcbiAgYWJzdHJhY3QgZ2V0Q3JlYXRlZEF0KCk6IERhdGU7XG4gIGFic3RyYWN0IHRvU3RyaW5nKCk6IHN0cmluZztcblxuICBnZXROYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuICh0aGlzLmNvbnN0cnVjdG9yIGFzIE5iQXV0aFRva2VuQ2xhc3MpLk5BTUU7XG4gIH1cblxuICBnZXRQYXlsb2FkKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMucGF5bG9hZDtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTmJBdXRoVG9rZW5Ob3RGb3VuZEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgbmV3LnRhcmdldC5wcm90b3R5cGUpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBOYkF1dGhJbGxlZ2FsVG9rZW5FcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIG5ldy50YXJnZXQucHJvdG90eXBlKTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgTmJBdXRoRW1wdHlUb2tlbkVycm9yIGV4dGVuZHMgTmJBdXRoSWxsZWdhbFRva2VuRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgbmV3LnRhcmdldC5wcm90b3R5cGUpO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBOYkF1dGhJbGxlZ2FsSldUVG9rZW5FcnJvciBleHRlbmRzIE5iQXV0aElsbGVnYWxUb2tlbkVycm9yIHtcbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nKSB7XG4gICAgc3VwZXIobWVzc2FnZSk7XG4gICAgT2JqZWN0LnNldFByb3RvdHlwZU9mKHRoaXMsIG5ldy50YXJnZXQucHJvdG90eXBlKTtcbiAgfVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5iQXV0aFJlZnJlc2hhYmxlVG9rZW4ge1xuICBnZXRSZWZyZXNoVG9rZW4oKTogc3RyaW5nO1xuICBzZXRSZWZyZXNoVG9rZW4ocmVmcmVzaFRva2VuOiBzdHJpbmcpO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE5iQXV0aFRva2VuQ2xhc3M8VCA9IE5iQXV0aFRva2VuPiB7XG4gIE5BTUU6IHN0cmluZztcbiAgbmV3IChyYXc6IGFueSwgc3RyYXRlZ3lOYW1lOiBzdHJpbmcsIGV4cERhdGU/OiBEYXRlKTogVDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5iQXV0aENyZWF0ZVRva2VuPFQgZXh0ZW5kcyBOYkF1dGhUb2tlbj4odG9rZW5DbGFzczogTmJBdXRoVG9rZW5DbGFzczxUPixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b2tlbjogYW55LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG93bmVyU3RyYXRlZ3lOYW1lOiBzdHJpbmcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlZEF0PzogRGF0ZSkge1xuICByZXR1cm4gbmV3IHRva2VuQ2xhc3ModG9rZW4sIG93bmVyU3RyYXRlZ3lOYW1lLCBjcmVhdGVkQXQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVjb2RlSnd0UGF5bG9hZChwYXlsb2FkOiBzdHJpbmcpOiBhbnkge1xuXG4gIGlmIChwYXlsb2FkLmxlbmd0aCA9PT0gMCkge1xuICAgIHRocm93IG5ldyBOYkF1dGhFbXB0eVRva2VuRXJyb3IoJ0Nhbm5vdCBleHRyYWN0IGZyb20gYW4gZW1wdHkgcGF5bG9hZC4nKTtcbiAgfVxuXG4gIGNvbnN0IHBhcnRzID0gcGF5bG9hZC5zcGxpdCgnLicpO1xuXG4gIGlmIChwYXJ0cy5sZW5ndGggIT09IDMpIHtcbiAgICB0aHJvdyBuZXcgTmJBdXRoSWxsZWdhbEpXVFRva2VuRXJyb3IoXG4gICAgICBgVGhlIHBheWxvYWQgJHtwYXlsb2FkfSBpcyBub3QgdmFsaWQgSldUIHBheWxvYWQgYW5kIG11c3QgY29uc2lzdCBvZiB0aHJlZSBwYXJ0cy5gKTtcbiAgfVxuXG4gIGxldCBkZWNvZGVkO1xuICB0cnkge1xuICAgIGRlY29kZWQgPSB1cmxCYXNlNjREZWNvZGUocGFydHNbMV0pO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IE5iQXV0aElsbGVnYWxKV1RUb2tlbkVycm9yKFxuICAgICAgYFRoZSBwYXlsb2FkICR7cGF5bG9hZH0gaXMgbm90IHZhbGlkIEpXVCBwYXlsb2FkIGFuZCBjYW5ub3QgYmUgcGFyc2VkLmApO1xuICB9XG5cbiAgaWYgKCFkZWNvZGVkKSB7XG4gICAgdGhyb3cgbmV3IE5iQXV0aElsbGVnYWxKV1RUb2tlbkVycm9yKFxuICAgICAgYFRoZSBwYXlsb2FkICR7cGF5bG9hZH0gaXMgbm90IHZhbGlkIEpXVCBwYXlsb2FkIGFuZCBjYW5ub3QgYmUgZGVjb2RlZC5gKTtcbiAgfVxuICByZXR1cm4gSlNPTi5wYXJzZShkZWNvZGVkKTtcbn1cblxuLyoqXG4gKiBXcmFwcGVyIGZvciBzaW1wbGUgKHRleHQpIHRva2VuXG4gKi9cbmV4cG9ydCBjbGFzcyBOYkF1dGhTaW1wbGVUb2tlbiBleHRlbmRzIE5iQXV0aFRva2VuIHtcblxuICBzdGF0aWMgTkFNRSA9ICduYjphdXRoOnNpbXBsZTp0b2tlbic7XG5cbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHJlYWRvbmx5IHRva2VuOiBhbnksXG4gICAgICAgICAgICAgIHByb3RlY3RlZCByZWFkb25seSBvd25lclN0cmF0ZWd5TmFtZTogc3RyaW5nLFxuICAgICAgICAgICAgICBwcm90ZWN0ZWQgY3JlYXRlZEF0PzogRGF0ZSkge1xuICAgIHN1cGVyKCk7XG4gICAgdHJ5IHtcbiAgICAgIHRoaXMucGFyc2VQYXlsb2FkKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoIShlcnIgaW5zdGFuY2VvZiBOYkF1dGhUb2tlbk5vdEZvdW5kRXJyb3IpKSB7XG4gICAgICAgIC8vIHRva2VuIGlzIHByZXNlbnQgYnV0IGhhcyBnb3QgYSBwcm9ibGVtLCBpbmNsdWRpbmcgaWxsZWdhbFxuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMuY3JlYXRlZEF0ID0gdGhpcy5wcmVwYXJlQ3JlYXRlZEF0KGNyZWF0ZWRBdCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcGFyc2VQYXlsb2FkKCk6IGFueSB7XG4gICAgdGhpcy5wYXlsb2FkID0gbnVsbDtcbiAgfVxuXG4gIHByb3RlY3RlZCBwcmVwYXJlQ3JlYXRlZEF0KGRhdGU6IERhdGUpIHtcbiAgICByZXR1cm4gZGF0ZSA/IGRhdGUgOiBuZXcgRGF0ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHRva2VuJ3MgY3JlYXRpb24gZGF0ZVxuICAgKiBAcmV0dXJucyB7RGF0ZX1cbiAgICovXG4gIGdldENyZWF0ZWRBdCgpOiBEYXRlIHtcbiAgICByZXR1cm4gdGhpcy5jcmVhdGVkQXQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdG9rZW4gdmFsdWVcbiAgICogQHJldHVybnMgc3RyaW5nXG4gICAqL1xuICBnZXRWYWx1ZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnRva2VuO1xuICB9XG5cbiAgZ2V0T3duZXJTdHJhdGVneU5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5vd25lclN0cmF0ZWd5TmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJcyBub24gZW1wdHkgYW5kIHZhbGlkXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgaXNWYWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gISF0aGlzLmdldFZhbHVlKCk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdmFsdWUgYW5kIGNvbnZlcnQgdG8gc3RyaW5nLCBpZiB2YWx1ZSBpcyBub3QgdmFsaWQgcmV0dXJuIGVtcHR5IHN0cmluZ1xuICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgKi9cbiAgdG9TdHJpbmcoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gISF0aGlzLnRva2VuID8gdGhpcy50b2tlbiA6ICcnO1xuICB9XG59XG5cbi8qKlxuICogV3JhcHBlciBmb3IgSldUIHRva2VuIHdpdGggYWRkaXRpb25hbCBtZXRob2RzLlxuICovXG5leHBvcnQgY2xhc3MgTmJBdXRoSldUVG9rZW4gZXh0ZW5kcyBOYkF1dGhTaW1wbGVUb2tlbiB7XG5cbiAgc3RhdGljIE5BTUUgPSAnbmI6YXV0aDpqd3Q6dG9rZW4nO1xuXG4gIC8qKlxuICAgKiBmb3IgSldUIHRva2VuLCB0aGUgaWF0IChpc3N1ZWQgYXQpIGZpZWxkIG9mIHRoZSB0b2tlbiBwYXlsb2FkIGNvbnRhaW5zIHRoZSBjcmVhdGlvbiBEYXRlXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlcGFyZUNyZWF0ZWRBdChkYXRlOiBEYXRlKSB7XG4gICAgICBjb25zdCBkZWNvZGVkID0gdGhpcy5nZXRQYXlsb2FkKCk7XG4gICAgICByZXR1cm4gZGVjb2RlZCAmJiBkZWNvZGVkLmlhdCA/IG5ldyBEYXRlKE51bWJlcihkZWNvZGVkLmlhdCkgKiAxMDAwKSA6IHN1cGVyLnByZXBhcmVDcmVhdGVkQXQoZGF0ZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwYXlsb2FkIG9iamVjdFxuICAgKiBAcmV0dXJucyBhbnlcbiAgICovXG4gIHByb3RlY3RlZCBwYXJzZVBheWxvYWQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnRva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgTmJBdXRoVG9rZW5Ob3RGb3VuZEVycm9yKCdUb2tlbiBub3QgZm91bmQuICcpXG4gICAgfVxuICAgIHRoaXMucGF5bG9hZCA9IGRlY29kZUp3dFBheWxvYWQodGhpcy50b2tlbik7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBleHBpcmF0aW9uIGRhdGVcbiAgICogQHJldHVybnMgRGF0ZVxuICAgKi9cbiAgZ2V0VG9rZW5FeHBEYXRlKCk6IERhdGUge1xuICAgIGNvbnN0IGRlY29kZWQgPSB0aGlzLmdldFBheWxvYWQoKTtcbiAgICBpZiAoZGVjb2RlZCAmJiAhZGVjb2RlZC5oYXNPd25Qcm9wZXJ0eSgnZXhwJykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoMCk7XG4gICAgZGF0ZS5zZXRVVENTZWNvbmRzKGRlY29kZWQuZXhwKTsgLy8gJ2NhdXNlIGp3dCB0b2tlbiBhcmUgc2V0IGluIHNlY29uZHNcbiAgICByZXR1cm4gZGF0ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJcyBkYXRhIGV4cGlyZWRcbiAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAqL1xuICBpc1ZhbGlkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBzdXBlci5pc1ZhbGlkKCkgJiYgKCF0aGlzLmdldFRva2VuRXhwRGF0ZSgpIHx8IG5ldyBEYXRlKCkgPCB0aGlzLmdldFRva2VuRXhwRGF0ZSgpKTtcbiAgfVxufVxuXG5jb25zdCBwcmVwYXJlT0F1dGgyVG9rZW4gPSAoZGF0YSkgPT4ge1xuICBpZiAodHlwZW9mIGRhdGEgPT09ICdzdHJpbmcnKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBKU09OLnBhcnNlKGRhdGEpO1xuICAgIH0gY2F0Y2ggKGUpIHt9XG4gIH1cbiAgcmV0dXJuIGRhdGE7XG59O1xuXG4vKipcbiAqIFdyYXBwZXIgZm9yIE9BdXRoMiB0b2tlbiB3aG9zZSBhY2Nlc3NfdG9rZW4gaXMgYSBKV1QgVG9rZW5cbiAqL1xuZXhwb3J0IGNsYXNzIE5iQXV0aE9BdXRoMlRva2VuIGV4dGVuZHMgTmJBdXRoU2ltcGxlVG9rZW4ge1xuXG4gIHN0YXRpYyBOQU1FID0gJ25iOmF1dGg6b2F1dGgyOnRva2VuJztcblxuICBjb25zdHJ1Y3RvciggZGF0YTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmd8bnVtYmVyIH18c3RyaW5nID0ge30sXG4gICAgICAgICAgICAgICBvd25lclN0cmF0ZWd5TmFtZTogc3RyaW5nLFxuICAgICAgICAgICAgICAgY3JlYXRlZEF0PzogRGF0ZSkge1xuXG4gICAgLy8gd2UgbWF5IGdldCBpdCBhcyBzdHJpbmcgd2hlbiByZXRyaWV2aW5nIGZyb20gYSBzdG9yYWdlXG4gICAgc3VwZXIocHJlcGFyZU9BdXRoMlRva2VuKGRhdGEpLCBvd25lclN0cmF0ZWd5TmFtZSwgY3JlYXRlZEF0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0b2tlbiB2YWx1ZVxuICAgKiBAcmV0dXJucyBzdHJpbmdcbiAgICovXG4gIGdldFZhbHVlKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMudG9rZW4uYWNjZXNzX3Rva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHJlZnJlc2ggdG9rZW5cbiAgICogQHJldHVybnMgc3RyaW5nXG4gICAqL1xuICBnZXRSZWZyZXNoVG9rZW4oKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy50b2tlbi5yZWZyZXNoX3Rva2VuO1xuICB9XG5cbiAgLyoqXG4gICAqICBwdXQgcmVmcmVzaFRva2VuIGluIHRoZSB0b2tlbiBwYXlsb2FkXG4gICAgKiBAcGFyYW0gcmVmcmVzaFRva2VuXG4gICAqL1xuICBzZXRSZWZyZXNoVG9rZW4ocmVmcmVzaFRva2VuOiBzdHJpbmcpIHtcbiAgICB0aGlzLnRva2VuLnJlZnJlc2hfdG9rZW4gPSByZWZyZXNoVG9rZW47XG4gIH1cblxuICAvKipcbiAgICogUGFyc2VzIHRva2VuIHBheWxvYWRcbiAgICogQHJldHVybnMgYW55XG4gICAqL1xuICBwcm90ZWN0ZWQgcGFyc2VQYXlsb2FkKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy50b2tlbikge1xuICAgICAgdGhyb3cgbmV3IE5iQXV0aFRva2VuTm90Rm91bmRFcnJvcignVG9rZW4gbm90IGZvdW5kLicpXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghT2JqZWN0LmtleXModGhpcy50b2tlbikubGVuZ3RoKSB7XG4gICAgICAgIHRocm93IG5ldyBOYkF1dGhFbXB0eVRva2VuRXJyb3IoJ0Nhbm5vdCBleHRyYWN0IHBheWxvYWQgZnJvbSBhbiBlbXB0eSB0b2tlbi4nKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5wYXlsb2FkID0gdGhpcy50b2tlbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB0b2tlbiB0eXBlXG4gICAqIEByZXR1cm5zIHN0cmluZ1xuICAgKi9cbiAgZ2V0VHlwZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnRva2VuLnRva2VuX3R5cGU7XG4gIH1cblxuICAvKipcbiAgICogSXMgZGF0YSBleHBpcmVkXG4gICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgKi9cbiAgaXNWYWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gc3VwZXIuaXNWYWxpZCgpICYmICghdGhpcy5nZXRUb2tlbkV4cERhdGUoKSB8fCBuZXcgRGF0ZSgpIDwgdGhpcy5nZXRUb2tlbkV4cERhdGUoKSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBleHBpcmF0aW9uIGRhdGVcbiAgICogQHJldHVybnMgRGF0ZVxuICAgKi9cbiAgZ2V0VG9rZW5FeHBEYXRlKCk6IERhdGUge1xuICAgIGlmICghdGhpcy50b2tlbi5oYXNPd25Qcm9wZXJ0eSgnZXhwaXJlc19pbicpKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBEYXRlKHRoaXMuY3JlYXRlZEF0LmdldFRpbWUoKSArIE51bWJlcih0aGlzLnRva2VuLmV4cGlyZXNfaW4pICogMTAwMCk7XG59XG5cbiAgLyoqXG4gICAqIENvbnZlcnQgdG8gc3RyaW5nXG4gICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAqL1xuICB0b1N0cmluZygpOiBzdHJpbmcge1xuICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLnRva2VuKTtcbiAgfVxufVxuXG4vKipcbiAqIFdyYXBwZXIgZm9yIE9BdXRoMiB0b2tlbiBlbWJlZGRpbmcgSldUIHRva2Vuc1xuICovXG5leHBvcnQgY2xhc3MgTmJBdXRoT0F1dGgySldUVG9rZW4gZXh0ZW5kcyBOYkF1dGhPQXV0aDJUb2tlbiB7XG5cbiAgc3RhdGljIE5BTUUgPSAnbmI6YXV0aDpvYXV0aDI6and0OnRva2VuJztcblxuICBwcm90ZWN0ZWQgYWNjZXNzVG9rZW5QYXlsb2FkOiBhbnk7XG5cbiAgcHJvdGVjdGVkIHBhcnNlUGF5bG9hZCgpOiB2b2lkIHtcbiAgICBzdXBlci5wYXJzZVBheWxvYWQoKTtcbiAgICB0aGlzLnBhcnNlQWNjZXNzVG9rZW5QYXlsb2FkKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcGFyc2VBY2Nlc3NUb2tlblBheWxvYWQoKTogYW55IHtcbiAgICBjb25zdCBhY2Nlc3NUb2tlbiA9IHRoaXMuZ2V0VmFsdWUoKTtcbiAgICBpZiAoIWFjY2Vzc1Rva2VuKSB7XG4gICAgICB0aHJvdyBuZXcgTmJBdXRoVG9rZW5Ob3RGb3VuZEVycm9yKCdhY2Nlc3NfdG9rZW4ga2V5IG5vdCBmb3VuZC4nKVxuICAgIH1cbiAgICB0aGlzLmFjY2Vzc1Rva2VuUGF5bG9hZCA9IGRlY29kZUp3dFBheWxvYWQoYWNjZXNzVG9rZW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWNjZXNzIHRva2VuIHBheWxvYWRcbiAgICogQHJldHVybnMgYW55XG4gICAqL1xuICBnZXRBY2Nlc3NUb2tlblBheWxvYWQoKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5hY2Nlc3NUb2tlblBheWxvYWQ7XG4gIH1cblxuICAvKipcbiAgICogZm9yIE9hdXRoMiBKV1QgdG9rZW4sIHRoZSBpYXQgKGlzc3VlZCBhdCkgZmllbGQgb2YgdGhlIGFjY2Vzc190b2tlbiBwYXlsb2FkXG4gICAqL1xuICBwcm90ZWN0ZWQgcHJlcGFyZUNyZWF0ZWRBdChkYXRlOiBEYXRlKSB7XG4gICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuYWNjZXNzVG9rZW5QYXlsb2FkO1xuICAgIHJldHVybiBwYXlsb2FkICYmIHBheWxvYWQuaWF0ID8gbmV3IERhdGUoTnVtYmVyKHBheWxvYWQuaWF0KSAqIDEwMDApIDogc3VwZXIucHJlcGFyZUNyZWF0ZWRBdChkYXRlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJcyB0b2tlbiB2YWxpZFxuICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICovXG4gIGlzVmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYWNjZXNzVG9rZW5QYXlsb2FkICYmIHN1cGVyLmlzVmFsaWQoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGV4cGlyYXRpb24gZGF0ZSA6XG4gICAqIC0gZXhwIGlmIHNldCxcbiAgICogLSBzdXBlci5nZXRFeHBEYXRlKCkgb3RoZXJ3aXNlXG4gICAqIEByZXR1cm5zIERhdGVcbiAgICovXG4gIGdldFRva2VuRXhwRGF0ZSgpOiBEYXRlIHtcbiAgICBpZiAodGhpcy5hY2Nlc3NUb2tlblBheWxvYWQgJiYgdGhpcy5hY2Nlc3NUb2tlblBheWxvYWQuaGFzT3duUHJvcGVydHkoJ2V4cCcpKSB7XG4gICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoMCk7XG4gICAgICBkYXRlLnNldFVUQ1NlY29uZHModGhpcy5hY2Nlc3NUb2tlblBheWxvYWQuZXhwKTtcbiAgICAgIHJldHVybiBkYXRlO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc3VwZXIuZ2V0VG9rZW5FeHBEYXRlKCk7XG4gICAgfVxuICB9XG59XG4iXX0= |
\ | No newline at end of file |