@lifeready/core 1.0.15 → 1.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. package/README.md +62 -62
  2. package/bundles/lifeready-core.umd.js +14321 -14315
  3. package/bundles/lifeready-core.umd.js.map +1 -1
  4. package/bundles/lifeready-core.umd.min.js +1 -1
  5. package/bundles/lifeready-core.umd.min.js.map +1 -1
  6. package/esm2015/lib/_common/ast.js +40 -40
  7. package/esm2015/lib/_common/deferred-promise.js +24 -24
  8. package/esm2015/lib/_common/exceptions.js +157 -157
  9. package/esm2015/lib/_common/queries.gql.js +190 -190
  10. package/esm2015/lib/_common/run-outside-angular.js +79 -79
  11. package/esm2015/lib/_common/types.js +1 -1
  12. package/esm2015/lib/_common/utils.js +52 -52
  13. package/esm2015/lib/api/contact-card.gql.js +79 -79
  14. package/esm2015/lib/api/contact-card.service.js +154 -154
  15. package/esm2015/lib/api/contact-card2.gql.js +60 -60
  16. package/esm2015/lib/api/contact-card2.service.js +103 -103
  17. package/esm2015/lib/api/file.service.js +74 -74
  18. package/esm2015/lib/api/key-exchange.gql.js +188 -188
  19. package/esm2015/lib/api/key-exchange.service.js +442 -442
  20. package/esm2015/lib/api/key-exchange.types.js +18 -18
  21. package/esm2015/lib/api/key-exchange2.gql.js +171 -171
  22. package/esm2015/lib/api/key-exchange2.service.js +479 -479
  23. package/esm2015/lib/api/lock.gql.js +40 -40
  24. package/esm2015/lib/api/lock.service.js +64 -64
  25. package/esm2015/lib/api/lr-apollo.service.js +46 -46
  26. package/esm2015/lib/api/lr-graphql/index.js +6 -6
  27. package/esm2015/lib/api/lr-graphql/lr-graphql.service.js +155 -155
  28. package/esm2015/lib/api/lr-graphql/lr-merged-mutation.js +213 -213
  29. package/esm2015/lib/api/lr-graphql/lr-mutation-base.js +51 -51
  30. package/esm2015/lib/api/lr-graphql/lr-mutation.js +48 -48
  31. package/esm2015/lib/api/lr-graphql/lr.service.js +18 -18
  32. package/esm2015/lib/api/message.service.js +138 -138
  33. package/esm2015/lib/api/persist.service.js +181 -181
  34. package/esm2015/lib/api/query-processor/common-processors.service.js +93 -93
  35. package/esm2015/lib/api/query-processor/index.js +3 -3
  36. package/esm2015/lib/api/query-processor/query-processor.service.js +262 -262
  37. package/esm2015/lib/api/query-processor/tp-password-reset-processor.service.js +109 -109
  38. package/esm2015/lib/api/shared-contact-card.service.js +119 -119
  39. package/esm2015/lib/api/shared-contact-card2.gql.js +41 -41
  40. package/esm2015/lib/api/shared-contact-card2.service.js +117 -117
  41. package/esm2015/lib/api/time.service.js +146 -146
  42. package/esm2015/lib/api/types/graphql.types.js +7 -7
  43. package/esm2015/lib/api/types/index.js +3 -3
  44. package/esm2015/lib/api/types/lr-graphql.types.js +101 -101
  45. package/esm2015/lib/auth/auth.config.js +57 -57
  46. package/esm2015/lib/auth/auth.gql.js +48 -48
  47. package/esm2015/lib/auth/auth.types.js +27 -27
  48. package/esm2015/lib/auth/idle.service.js +168 -168
  49. package/esm2015/lib/auth/idle.types.js +7 -7
  50. package/esm2015/lib/auth/lbop.service.js +355 -355
  51. package/esm2015/lib/auth/life-ready-auth.service.js +488 -488
  52. package/esm2015/lib/auth/password.service.js +320 -320
  53. package/esm2015/lib/auth/register.service.js +172 -172
  54. package/esm2015/lib/auth/two-factor.service.js +74 -74
  55. package/esm2015/lib/category/category-meta.service.js +99 -99
  56. package/esm2015/lib/category/category.gql.js +406 -406
  57. package/esm2015/lib/category/category.service.js +390 -390
  58. package/esm2015/lib/category/category.types.js +29 -29
  59. package/esm2015/lib/cryptography/cryptography.types.js +11 -11
  60. package/esm2015/lib/cryptography/encryption.service.js +189 -189
  61. package/esm2015/lib/cryptography/key-factory.service.js +237 -237
  62. package/esm2015/lib/cryptography/key-graph.service.js +299 -299
  63. package/esm2015/lib/cryptography/key-meta.service.js +200 -200
  64. package/esm2015/lib/cryptography/key.service.js +124 -124
  65. package/esm2015/lib/cryptography/slip39.service.js +169 -169
  66. package/esm2015/lib/cryptography/web-crypto.service.js +29 -29
  67. package/esm2015/lib/items2/item2.gql.js +139 -139
  68. package/esm2015/lib/items2/item2.service.js +498 -498
  69. package/esm2015/lib/items2/item2.types.js +1 -1
  70. package/esm2015/lib/life-ready.config.js +84 -84
  71. package/esm2015/lib/life-ready.module.js +74 -74
  72. package/esm2015/lib/notification/notification.gql.js +43 -43
  73. package/esm2015/lib/notification/notification.service.js +118 -118
  74. package/esm2015/lib/plan/plan.gql.js +123 -123
  75. package/esm2015/lib/plan/plan.service.js +149 -149
  76. package/esm2015/lib/plan/plan.types.js +11 -11
  77. package/esm2015/lib/record/record-attachment.service.js +101 -101
  78. package/esm2015/lib/record/record.gql.js +179 -179
  79. package/esm2015/lib/record/record.service.js +206 -206
  80. package/esm2015/lib/record/record.types.js +15 -15
  81. package/esm2015/lib/record-type/record-type.service.js +75 -75
  82. package/esm2015/lib/record-type/record-type.types.js +28 -28
  83. package/esm2015/lib/scenario/scenario.constants.js +2 -2
  84. package/esm2015/lib/scenario/scenario.controller.js +34 -34
  85. package/esm2015/lib/scenario/scenario.gql.js +72 -72
  86. package/esm2015/lib/scenario/scenario.gql.private.js +198 -198
  87. package/esm2015/lib/scenario/scenario.service.js +538 -538
  88. package/esm2015/lib/scenario/scenario.types.js +1 -1
  89. package/esm2015/lib/trusted-parties/tp-assembly.gql.private.js +22 -22
  90. package/esm2015/lib/trusted-parties/tp-assembly.js +362 -362
  91. package/esm2015/lib/trusted-parties/tp-assembly.types.js +1 -1
  92. package/esm2015/lib/trusted-parties/tp-password-reset-request.service.js +113 -113
  93. package/esm2015/lib/trusted-parties/tp-password-reset-user.service.js +129 -129
  94. package/esm2015/lib/trusted-parties/tp-password-reset.constants.js +4 -4
  95. package/esm2015/lib/trusted-parties/tp-password-reset.controller.js +34 -34
  96. package/esm2015/lib/trusted-parties/tp-password-reset.gql.js +237 -236
  97. package/esm2015/lib/trusted-parties/tp-password-reset.service.js +95 -95
  98. package/esm2015/lib/trusted-parties/trusted-party.gql.js +148 -148
  99. package/esm2015/lib/trusted-parties/trusted-party.service.js +326 -326
  100. package/esm2015/lib/trusted-parties/trusted-party.types.js +41 -41
  101. package/esm2015/lib/trusted-parties/trusted-party2.gql.js +87 -87
  102. package/esm2015/lib/trusted-parties/trusted-party2.service.js +218 -215
  103. package/esm2015/lib/users/profile-details.service.js +214 -214
  104. package/esm2015/lib/users/profile.gql.js +97 -97
  105. package/esm2015/lib/users/profile.service.js +169 -169
  106. package/esm2015/lib/users/profile.types.js +34 -34
  107. package/esm2015/lib/users/user.gql.js +60 -60
  108. package/esm2015/lib/users/user.service.js +79 -79
  109. package/esm2015/lib/users/user.types.js +5 -5
  110. package/esm2015/lifeready-core.js +13 -13
  111. package/esm2015/public-api.js +71 -71
  112. package/fesm2015/lifeready-core.js +12263 -12258
  113. package/fesm2015/lifeready-core.js.map +1 -1
  114. package/lib/_common/ast.d.ts +11 -11
  115. package/lib/_common/deferred-promise.d.ts +12 -12
  116. package/lib/_common/exceptions.d.ts +109 -109
  117. package/lib/_common/queries.gql.d.ts +10 -10
  118. package/lib/_common/run-outside-angular.d.ts +14 -14
  119. package/lib/_common/types.d.ts +10 -10
  120. package/lib/_common/utils.d.ts +9 -9
  121. package/lib/api/contact-card.gql.d.ts +7 -7
  122. package/lib/api/contact-card.service.d.ts +52 -52
  123. package/lib/api/contact-card2.gql.d.ts +34 -34
  124. package/lib/api/contact-card2.service.d.ts +49 -49
  125. package/lib/api/file.service.d.ts +18 -18
  126. package/lib/api/key-exchange.gql.d.ts +9 -9
  127. package/lib/api/key-exchange.service.d.ts +39 -39
  128. package/lib/api/key-exchange.types.d.ts +196 -196
  129. package/lib/api/key-exchange2.gql.d.ts +125 -125
  130. package/lib/api/key-exchange2.service.d.ts +187 -187
  131. package/lib/api/lock.gql.d.ts +27 -27
  132. package/lib/api/lock.service.d.ts +34 -34
  133. package/lib/api/lr-apollo.service.d.ts +15 -15
  134. package/lib/api/lr-graphql/index.d.ts +5 -5
  135. package/lib/api/lr-graphql/lr-graphql.service.d.ts +60 -60
  136. package/lib/api/lr-graphql/lr-merged-mutation.d.ts +28 -28
  137. package/lib/api/lr-graphql/lr-mutation-base.d.ts +28 -28
  138. package/lib/api/lr-graphql/lr-mutation.d.ts +8 -8
  139. package/lib/api/lr-graphql/lr.service.d.ts +9 -9
  140. package/lib/api/message.service.d.ts +58 -58
  141. package/lib/api/persist.service.d.ts +31 -31
  142. package/lib/api/query-processor/common-processors.service.d.ts +36 -36
  143. package/lib/api/query-processor/index.d.ts +2 -2
  144. package/lib/api/query-processor/query-processor.service.d.ts +18 -18
  145. package/lib/api/query-processor/tp-password-reset-processor.service.d.ts +15 -15
  146. package/lib/api/shared-contact-card.service.d.ts +33 -33
  147. package/lib/api/shared-contact-card2.gql.d.ts +36 -36
  148. package/lib/api/shared-contact-card2.service.d.ts +45 -45
  149. package/lib/api/time.service.d.ts +16 -16
  150. package/lib/api/types/graphql.types.d.ts +29 -29
  151. package/lib/api/types/index.d.ts +2 -2
  152. package/lib/api/types/lr-graphql.types.d.ts +504 -502
  153. package/lib/auth/auth.config.d.ts +5 -5
  154. package/lib/auth/auth.gql.d.ts +15 -15
  155. package/lib/auth/auth.types.d.ts +66 -66
  156. package/lib/auth/idle.service.d.ts +40 -40
  157. package/lib/auth/idle.types.d.ts +10 -10
  158. package/lib/auth/lbop.service.d.ts +91 -91
  159. package/lib/auth/life-ready-auth.service.d.ts +61 -61
  160. package/lib/auth/password.service.d.ts +78 -78
  161. package/lib/auth/register.service.d.ts +25 -25
  162. package/lib/auth/two-factor.service.d.ts +15 -15
  163. package/lib/category/category-meta.service.d.ts +23 -23
  164. package/lib/category/category.gql.d.ts +45 -45
  165. package/lib/category/category.service.d.ts +67 -67
  166. package/lib/category/category.types.d.ts +79 -79
  167. package/lib/cryptography/cryptography.types.d.ts +83 -83
  168. package/lib/cryptography/encryption.service.d.ts +41 -41
  169. package/lib/cryptography/key-factory.service.d.ts +38 -38
  170. package/lib/cryptography/key-graph.service.d.ts +41 -41
  171. package/lib/cryptography/key-meta.service.d.ts +44 -44
  172. package/lib/cryptography/key.service.d.ts +36 -36
  173. package/lib/cryptography/slip39.service.d.ts +43 -43
  174. package/lib/cryptography/web-crypto.service.d.ts +5 -5
  175. package/lib/items2/item2.gql.d.ts +123 -123
  176. package/lib/items2/item2.service.d.ts +203 -203
  177. package/lib/items2/item2.types.d.ts +70 -70
  178. package/lib/life-ready.config.d.ts +14 -14
  179. package/lib/life-ready.module.d.ts +5 -5
  180. package/lib/notification/notification.gql.d.ts +37 -37
  181. package/lib/notification/notification.service.d.ts +63 -63
  182. package/lib/plan/plan.gql.d.ts +11 -11
  183. package/lib/plan/plan.service.d.ts +33 -33
  184. package/lib/plan/plan.types.d.ts +31 -31
  185. package/lib/record/record-attachment.service.d.ts +16 -16
  186. package/lib/record/record.gql.d.ts +14 -14
  187. package/lib/record/record.service.d.ts +25 -25
  188. package/lib/record/record.types.d.ts +57 -57
  189. package/lib/record-type/record-type.service.d.ts +11 -11
  190. package/lib/record-type/record-type.types.d.ts +50 -50
  191. package/lib/scenario/scenario.constants.d.ts +1 -1
  192. package/lib/scenario/scenario.controller.d.ts +10 -10
  193. package/lib/scenario/scenario.gql.d.ts +62 -62
  194. package/lib/scenario/scenario.gql.private.d.ts +16 -16
  195. package/lib/scenario/scenario.service.d.ts +233 -233
  196. package/lib/scenario/scenario.types.d.ts +50 -50
  197. package/lib/trusted-parties/tp-assembly.d.ts +177 -177
  198. package/lib/trusted-parties/tp-assembly.gql.private.d.ts +5 -5
  199. package/lib/trusted-parties/tp-assembly.types.d.ts +38 -38
  200. package/lib/trusted-parties/tp-password-reset-request.service.d.ts +20 -20
  201. package/lib/trusted-parties/tp-password-reset-user.service.d.ts +35 -35
  202. package/lib/trusted-parties/tp-password-reset.constants.d.ts +3 -3
  203. package/lib/trusted-parties/tp-password-reset.controller.d.ts +10 -10
  204. package/lib/trusted-parties/tp-password-reset.gql.d.ts +224 -223
  205. package/lib/trusted-parties/tp-password-reset.service.d.ts +189 -188
  206. package/lib/trusted-parties/trusted-party.gql.d.ts +9 -9
  207. package/lib/trusted-parties/trusted-party.service.d.ts +44 -44
  208. package/lib/trusted-parties/trusted-party.types.d.ts +102 -102
  209. package/lib/trusted-parties/trusted-party2.gql.d.ts +79 -79
  210. package/lib/trusted-parties/trusted-party2.service.d.ts +115 -114
  211. package/lib/users/profile-details.service.d.ts +21 -21
  212. package/lib/users/profile.gql.d.ts +11 -11
  213. package/lib/users/profile.service.d.ts +35 -35
  214. package/lib/users/profile.types.d.ts +96 -96
  215. package/lib/users/user.gql.d.ts +9 -9
  216. package/lib/users/user.service.d.ts +12 -12
  217. package/lib/users/user.types.d.ts +23 -23
  218. package/lifeready-core.d.ts +12 -12
  219. package/lifeready-core.metadata.json +1 -1
  220. package/package.json +1 -1
  221. package/public-api.d.ts +67 -67
@@ -1,488 +1,488 @@
1
- import { __awaiter } from "tslib";
2
- import { Inject, Injectable, isDevMode } from '@angular/core';
3
- import { Hub } from '@aws-amplify/core';
4
- import { ReplaySubject } from 'rxjs';
5
- import { KeyGraphService } from '../cryptography/key-graph.service';
6
- import { KeyService } from '../cryptography/key.service';
7
- import { ProfileService } from '../users/profile.service';
8
- import { PasswordChangeStatus } from '../users/profile.types';
9
- import { LrConcurrentAccessException, LrBadRequestException, LrBadStateException, LrException, } from '../_common/exceptions';
10
- import { RecoveryStatus, } from './auth.types';
11
- import { PasswordService } from './password.service';
12
- import { AuthClass } from '@aws-amplify/auth/lib-esm/Auth';
13
- import { CompleteTpPasswordResetRequestMutation, CreateTpAssemblyKeyChallengeMutation, PreCompleteTpPasswordResetRequestMutation, TpPasswordResetUserQuery, } from '../trusted-parties/tp-password-reset.gql';
14
- import { IdleService } from './idle.service';
15
- import { KeyFactoryService } from '../cryptography/key-factory.service';
16
- import { LrGraphQLService, LrMutation } from '../api/lr-graphql';
17
- import { TpClaimState } from '../api/types';
18
- import { TpPasswordResetProcessorService } from '../api/query-processor/tp-password-reset-processor.service';
19
- import { SetSessionEncryptionKeyMutation } from './auth.gql';
20
- import { PersistService } from '../api/persist.service';
21
- import { JWK } from 'node-jose';
22
- import { LR_CONFIG } from '../life-ready.config';
23
- import { EncryptionService } from '../cryptography/encryption.service';
24
- import { Slip39Service } from '../cryptography/slip39.service';
25
- import { TP_PASSWORD_RESET_CLIENT_NONCE_LENGTH, TP_PASSWORD_RESET_USERNAME_SUFFIX, } from '../trusted-parties/tp-password-reset.constants';
26
- import { TpPasswordResetAssemblyController } from '../trusted-parties/tp-password-reset.controller';
27
- import * as i0 from "@angular/core";
28
- import * as i1 from "../life-ready.config";
29
- import * as i2 from "@aws-amplify/auth/lib-esm/Auth";
30
- import * as i3 from "../cryptography/key-factory.service";
31
- import * as i4 from "../cryptography/key.service";
32
- import * as i5 from "../users/profile.service";
33
- import * as i6 from "../cryptography/key-graph.service";
34
- import * as i7 from "./password.service";
35
- import * as i8 from "./idle.service";
36
- import * as i9 from "../api/lr-graphql/lr-graphql.service";
37
- import * as i10 from "../api/query-processor/tp-password-reset-processor.service";
38
- import * as i11 from "../api/persist.service";
39
- import * as i12 from "../cryptography/encryption.service";
40
- import * as i13 from "../cryptography/slip39.service";
41
- import * as i14 from "../trusted-parties/tp-password-reset.controller";
42
- export const initialiseAuth = (authService) => {
43
- return () => authService.initialise();
44
- };
45
- export class LifeReadyAuthService {
46
- constructor(config, auth, keyFactory, keyService, profileService, keyGraphService, passwordService, idleService, lrGraphQL, tpPasswordResetProcessorService, persistService, encryptionService, slip39Service, assemblyController) {
47
- this.config = config;
48
- this.auth = auth;
49
- this.keyFactory = keyFactory;
50
- this.keyService = keyService;
51
- this.profileService = profileService;
52
- this.keyGraphService = keyGraphService;
53
- this.passwordService = passwordService;
54
- this.idleService = idleService;
55
- this.lrGraphQL = lrGraphQL;
56
- this.tpPasswordResetProcessorService = tpPasswordResetProcessorService;
57
- this.persistService = persistService;
58
- this.encryptionService = encryptionService;
59
- this.slip39Service = slip39Service;
60
- this.assemblyController = assemblyController;
61
- this.hubSubject = new ReplaySubject(1);
62
- }
63
- initialise() {
64
- return __awaiter(this, void 0, void 0, function* () {
65
- Hub.listen('auth', (data) => this.hubSubject.next(data.payload));
66
- });
67
- }
68
- loginIdpImpl(emailOrPhone, password, passIdpParams, recoveryStatus) {
69
- return __awaiter(this, void 0, void 0, function* () {
70
- const passIdpResult = yield this.keyFactory.derivePassIdp(Object.assign({ password }, passIdpParams));
71
- // Use the derived password to signin with cognito
72
- const user = yield this.auth.signIn(emailOrPhone, this.passwordService.getPassIdpString(passIdpResult.jwk));
73
- user.recoveryStatus = recoveryStatus;
74
- return user;
75
- });
76
- }
77
- loginIdp(emailOrPhone, password) {
78
- return __awaiter(this, void 0, void 0, function* () {
79
- // Download the salt needed to derive the PassIdp
80
- const passIdpApiResult = yield this.profileService.getPassIdpParams(emailOrPhone);
81
- if (passIdpApiResult.passwordChangeStatus === PasswordChangeStatus.InProgress) {
82
- throw new LrConcurrentAccessException('A password change is in progress');
83
- }
84
- if (passIdpApiResult.passwordChangeStatus === PasswordChangeStatus.Recovery) {
85
- console.log('In recovery mode.');
86
- // Let's say we don't know if the password is the new one or the old one. We just have to try both.
87
- try {
88
- const user = yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.newPassIdpParams, RecoveryStatus.NEW_PASSWORD);
89
- // New password worked. Let's set to the current password
90
- // --Potential Failure Point 1--
91
- // if changePasswordComplete() doesn't get called, then it should remain
92
- console.log('New password works!');
93
- return user;
94
- }
95
- catch (error) {
96
- // Just bubble up any other type of error.
97
- if (error.code !== 'NotAuthorizedException') {
98
- throw error;
99
- }
100
- // pass, try again assuming it's the old password
101
- }
102
- // Now assume it's the previous password. Any exception is allowed to bubble up.
103
- try {
104
- const user = yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.currentPassIdpParams, RecoveryStatus.OLD_PASSWORD);
105
- // Old password worked.
106
- console.log('Old password works!');
107
- return user;
108
- }
109
- catch (error) {
110
- // Just bubble up any other type of error.
111
- throw error.code === 'NotAuthorizedException'
112
- ? new LrBadRequestException('The password change request was interrupted, please try to login with both your new and old password')
113
- : error;
114
- }
115
- }
116
- // Try against as the TP password reset account
117
- if (passIdpApiResult.tpPasswordReset) {
118
- try {
119
- // TP password reset is in process. We need to try the password against both
120
- // original account and the new reset account.
121
- const reset = passIdpApiResult.tpPasswordReset;
122
- const ret = yield this.loginIdpImpl(reset.resetUsername, password, reset.passIdpParams, RecoveryStatus.NONE);
123
- ret.isTpPasswordResetUser = true;
124
- return ret;
125
- }
126
- catch (err) {
127
- // continue, try again as regular user.
128
- }
129
- }
130
- // Login as regular user
131
- return yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.currentPassIdpParams, RecoveryStatus.NONE);
132
- });
133
- }
134
- handleSessionEncryptionKey() {
135
- return __awaiter(this, void 0, void 0, function* () {
136
- if (this.config.disableSessionEncryptionKey) {
137
- if (!isDevMode()) {
138
- const msg = 'You should not set disableSessionEncryptionKey=True in mode prod. It defaults to false.';
139
- console.error(msg);
140
- throw new Error(msg);
141
- }
142
- else {
143
- console.warn('You have set disableSessionEncryptionKey=True. Make sure not to do this in prod mode.');
144
- }
145
- }
146
- else {
147
- // Set the session key to a new encryption key for this session
148
- const sessionEncryptionKey = yield this.keyFactory.createKey();
149
- yield this.lrGraphQL.lrMutate(new LrMutation({
150
- mutation: SetSessionEncryptionKeyMutation,
151
- variables: {
152
- input: {
153
- sessionEncryptionKey: JSON.stringify(sessionEncryptionKey.toJSON(true)),
154
- },
155
- },
156
- }), {
157
- includeKeyGraph: false,
158
- });
159
- this.persistService.setServerSessionEncryptionKey(sessionEncryptionKey);
160
- }
161
- });
162
- }
163
- handlePostAuth(cognitoUser) {
164
- return __awaiter(this, void 0, void 0, function* () {
165
- yield this.handlePasswordRecovery(cognitoUser);
166
- yield this.handleSessionEncryptionKey();
167
- });
168
- }
169
- login(emailOrPhone, password, { tpPasswordResetAutoComplete = true } = {}) {
170
- var _a;
171
- return __awaiter(this, void 0, void 0, function* () {
172
- let loginResult = yield this.loginImpl(emailOrPhone, password);
173
- if (tpPasswordResetAutoComplete &&
174
- ((_a = loginResult.resetUser) === null || _a === void 0 ? void 0 : _a.state) === TpClaimState.APPROVED) {
175
- yield this.completeRequest(password);
176
- loginResult = yield this.loginImpl(emailOrPhone, password);
177
- }
178
- return loginResult;
179
- });
180
- }
181
- loginImpl(emailOrPhone, password) {
182
- return __awaiter(this, void 0, void 0, function* () {
183
- yield this.logout();
184
- const cognitoUser = yield this.loginIdp(emailOrPhone, password);
185
- // todo: Meet MFA challenges.
186
- if (['SMS_MFA', 'SOFTWARE_TOKEN_MFA'].includes(cognitoUser.challengeName)) {
187
- return { hasChallenge: true, challenge: cognitoUser };
188
- }
189
- yield this.handlePostAuth(cognitoUser);
190
- if (cognitoUser.isTpPasswordResetUser) {
191
- // Assuming there is no MFA on the TP reset user.
192
- const resetUser = yield this.loadResetUser(password);
193
- return { hasChallenge: false, resetUser };
194
- }
195
- else {
196
- const user = yield this.loadUser(cognitoUser, password);
197
- yield this.idleService.start(); // Run idleService whenever user is logged in.
198
- return { hasChallenge: false, user };
199
- }
200
- });
201
- }
202
- // TODO <AZ> We need to handle the isTpPasswordResetUser=True case here after MFA as well.
203
- verifyLogin(challenge, password, rememberMe, code) {
204
- return __awaiter(this, void 0, void 0, function* () {
205
- yield this.auth.confirmSignIn(challenge, code, challenge.challengeName);
206
- // TODO: this.auth.confirmSignIn() could return another challenge.
207
- const cognitoUser = yield this.auth.currentAuthenticatedUser();
208
- yield this.handlePostAuth(challenge);
209
- const user = yield this.loadUser(cognitoUser, password);
210
- if (rememberMe) {
211
- cognitoUser.setDeviceStatusRemembered({
212
- onSuccess: () => { },
213
- onFailure: (e) => console.error(e),
214
- });
215
- }
216
- return user;
217
- });
218
- }
219
- handlePasswordRecovery(user) {
220
- return __awaiter(this, void 0, void 0, function* () {
221
- if (user.recoveryStatus !== RecoveryStatus.NONE) {
222
- const jwtToken = user
223
- .getSignInUserSession()
224
- .getAccessToken()
225
- .getJwtToken();
226
- yield this.passwordService.changePasswordComplete(jwtToken, user.recoveryStatus === RecoveryStatus.NEW_PASSWORD);
227
- }
228
- });
229
- }
230
- getUserOrResetUser(reload = false) {
231
- return __awaiter(this, void 0, void 0, function* () {
232
- const cognitoUser = yield this.auth.currentAuthenticatedUser();
233
- if (cognitoUser.getUsername().endsWith(TP_PASSWORD_RESET_USERNAME_SUFFIX)) {
234
- return this.getResetUser(reload);
235
- }
236
- else {
237
- return this.getUser(reload);
238
- }
239
- });
240
- }
241
- getResetUser(reload = false) {
242
- return __awaiter(this, void 0, void 0, function* () {
243
- if (!reload && this.currentResetUser) {
244
- return this.currentResetUser;
245
- }
246
- this.currentResetUser = yield this.loadResetUser();
247
- yield this.idleService.start(); // Run idleService whenever user is logged in.
248
- return this.currentResetUser;
249
- });
250
- }
251
- getUser(reload = false) {
252
- return __awaiter(this, void 0, void 0, function* () {
253
- if (!reload && this.currentUser) {
254
- return this.currentUser;
255
- }
256
- this.currentUser = yield this.loadUser(yield this.auth.currentAuthenticatedUser());
257
- console.log('Starting idle service.');
258
- yield this.idleService.start(); // Run idleService whenever user is logged in.
259
- return this.currentUser;
260
- });
261
- }
262
- mapTPVaultAccess(features) {
263
- const tpVaultFeature = features === null || features === void 0 ? void 0 : features.tpVault;
264
- return ((tpVaultFeature === null || tpVaultFeature === void 0 ? void 0 : tpVaultFeature.length) > 0 &&
265
- tpVaultFeature.some((feature) => feature.toUpperCase() === 'ACCESS'));
266
- }
267
- loadUser(cognitoUser, password) {
268
- return __awaiter(this, void 0, void 0, function* () {
269
- const { currentUser, contactCard, userPlans, } = yield this.profileService.getCurrentUser();
270
- if (currentUser.sessionEncryptionKey) {
271
- this.persistService.setServerSessionEncryptionKey(yield JWK.asKey(currentUser.sessionEncryptionKey));
272
- }
273
- const userAttributes = yield this.auth.userAttributes(cognitoUser);
274
- if (password) {
275
- const passKey = (yield this.keyFactory.derivePassKey(Object.assign({ password }, currentUser.currentUserKey.passKey.passKeyParams))).jwk;
276
- yield this.idleService.persistMasterKey(yield this.keyGraphService.unwrapWithPassKey(currentUser.currentUserKey.passKey.id, passKey, currentUser.currentUserKey.masterKey.id));
277
- }
278
- yield this.keyGraphService.populateKeys(currentUser.currentUserKey);
279
- return {
280
- id: currentUser.id,
281
- sub: this.getUserAttribute('sub', userAttributes),
282
- username: currentUser.username,
283
- currentUserKey: currentUser.currentUserKey,
284
- getAccessJwtToken: () => cognitoUser.getSignInUserSession().getAccessToken().getJwtToken(),
285
- email: this.getUserAttribute('email', userAttributes),
286
- emailVerified: this.getUserAttribute('email_verified', userAttributes) === 'true',
287
- phone: this.getUserAttribute('phone_number', userAttributes),
288
- phoneVerified: this.getUserAttribute('phone_number_verified', userAttributes) ===
289
- 'true',
290
- contactCard: Object.assign({}, (yield this.profileService.decryptContactCard(contactCard))),
291
- userDelete: currentUser.userDelete,
292
- userPlans,
293
- hasTPVaultAccess: this.mapTPVaultAccess(currentUser.features),
294
- features: currentUser.features,
295
- sessionEncryptionKey: currentUser.sessionEncryptionKey,
296
- };
297
- });
298
- }
299
- watchAuth() {
300
- return this.hubSubject;
301
- }
302
- logout() {
303
- return __awaiter(this, void 0, void 0, function* () {
304
- this.currentUser = null;
305
- this.keyService.purgeKeys();
306
- this.keyGraphService.purgeKeys();
307
- yield Promise.all([this.auth.signOut(), this.profileService.signOut()]);
308
- });
309
- }
310
- getUserAttribute(attributeName, userAttributes) {
311
- const userAttribute = userAttributes.find((x) => x.getName() === attributeName);
312
- return userAttribute ? userAttribute.getValue() : null;
313
- }
314
- loadResetUser(password) {
315
- return __awaiter(this, void 0, void 0, function* () {
316
- const { tpPasswordResetUser: resetUser } = yield this.lrGraphQL.query({
317
- query: TpPasswordResetUserQuery,
318
- });
319
- if (resetUser.sessionEncryptionKey) {
320
- this.persistService.setServerSessionEncryptionKey(yield JWK.asKey(resetUser.sessionEncryptionKey));
321
- }
322
- // Update the keys
323
- if (password) {
324
- const passKey = (yield this.keyFactory.derivePassKey(Object.assign({ password }, resetUser.passKey.passKeyParams))).jwk;
325
- yield this.idleService.persistMasterKey(yield this.keyGraphService.unwrapWithPassKey(resetUser.passKey.id, passKey, resetUser.masterKey.id));
326
- }
327
- this.keyService.populateKeys({
328
- passKey: {
329
- id: resetUser.passKey.id,
330
- },
331
- masterKey: {
332
- id: resetUser.masterKey.id,
333
- },
334
- });
335
- const userAttributes = yield this.auth.userAttributes(yield this.auth.currentAuthenticatedUser());
336
- const sub = this.getUserAttribute('sub', userAttributes);
337
- return Object.assign(Object.assign({}, (yield this.tpPasswordResetProcessorService.processTpPasswordResetUserNode(resetUser))), { sub });
338
- });
339
- }
340
- refreshAccessToken() {
341
- return __awaiter(this, void 0, void 0, function* () {
342
- const cognitoUser = yield this.auth.currentAuthenticatedUser();
343
- const refreshToken = cognitoUser.getSignInUserSession().getRefreshToken();
344
- return new Promise((resolve, reject) => {
345
- cognitoUser.refreshSession(refreshToken, (err, data) => {
346
- if (err) {
347
- console.error('Error refreshing token: ', err);
348
- reject(err);
349
- }
350
- else {
351
- console.log('Token refresh complete: ', data);
352
- resolve(0);
353
- }
354
- });
355
- });
356
- });
357
- }
358
- completeRequest(newPassword) {
359
- return __awaiter(this, void 0, void 0, function* () {
360
- const resetUser = yield this.getResetUser(true);
361
- if (resetUser.state !== TpClaimState.APPROVED) {
362
- throw new LrBadStateException('Password reset request has not been approved.');
363
- }
364
- // --------------------------------------------------------------
365
- // Prepare all materials to ensure there are no errors.
366
- // --------------------------------------------------------------
367
- const assemblyKey = yield this.recoverAssemblyKey(resetUser);
368
- const { rootKey } = yield this.encryptionService.decrypt(assemblyKey, resetUser.assemblyCipherData);
369
- console.log(rootKey);
370
- // Making sure it's a valid key.
371
- const rootKeyJwk = yield JWK.asKey(rootKey);
372
- const masterKey = yield this.keyGraphService.getKey(resetUser.masterKey.id);
373
- const masterKeyWrappedRootKey = yield this.encryptionService.encryptToString(masterKey.jwk, rootKeyJwk.toJSON(true));
374
- // The new password
375
- const newPassIdpResult = yield this.keyFactory.derivePassIdp(Object.assign({ password: newPassword }, resetUser.passKey.passIdpParams));
376
- const newIdpPassword = this.passwordService.getPassIdpString(newPassIdpResult.jwk);
377
- // --------------------------------------------------------------
378
- // Get assembly key challenge
379
- // --------------------------------------------------------------
380
- const challenge = (yield this.lrGraphQL.lrMutate(new LrMutation({
381
- mutation: CreateTpAssemblyKeyChallengeMutation,
382
- variables: {
383
- input: {},
384
- },
385
- }), {
386
- includeKeyGraph: false,
387
- })).createTpAssemblyKeyChallenge.challenge;
388
- console.log(challenge);
389
- // Sign the challenge
390
- // Generate a client side nonce that's no in the server's control.
391
- challenge.clientNonce = this.keyFactory.randomString(TP_PASSWORD_RESET_CLIENT_NONCE_LENGTH);
392
- console.log(challenge);
393
- const assemblyKeyVerifierPrk = yield this.encryptionService.decrypt(assemblyKey, resetUser.wrappedAssemblyKeyVerifierPrk);
394
- const signedChallenge = yield this.encryptionService.sign(assemblyKeyVerifierPrk, challenge);
395
- // --------------------------------------------------------------
396
- // Change password for the original user
397
- // --------------------------------------------------------------
398
- const tempIdpPassword = (yield this.lrGraphQL.lrMutate(new LrMutation({
399
- mutation: PreCompleteTpPasswordResetRequestMutation,
400
- variables: {
401
- input: {
402
- signedChallenge: JSON.stringify(signedChallenge),
403
- },
404
- },
405
- }), {
406
- includeKeyGraph: false,
407
- })).preCompleteTpPasswordResetRequest.idpPassword;
408
- // --------------------------------------------------------------
409
- // Login as the original user using new temporary password
410
- // --------------------------------------------------------------
411
- // At this point, the original account's password has been changed
412
- // to a temporary password. It is no longer possible for the user
413
- // to use the original password to login. Any successful login
414
- // can only be using the temporary password. So it's safe to assume
415
- // that we want to "complete" the password reset.
416
- // The maybe 2FA so we listen for the auth event from Amplify.
417
- const retPromise = new Promise((resolve) => {
418
- const listener = (data) => __awaiter(this, void 0, void 0, function* () {
419
- if (data.payload.event !== 'signIn') {
420
- return;
421
- }
422
- Hub.remove('auth', listener);
423
- console.log(data.payload);
424
- yield this.auth.signIn(resetUser.username, newIdpPassword);
425
- // Switch over to the new set of keys
426
- yield this.lrGraphQL.lrMutate(new LrMutation({
427
- mutation: CompleteTpPasswordResetRequestMutation,
428
- variables: {
429
- input: {
430
- masterKeyWrappedRootKey,
431
- masterKeyId: masterKey.id,
432
- },
433
- },
434
- }));
435
- resolve();
436
- });
437
- Hub.listen('auth', listener);
438
- });
439
- // Signin as the original user. Password has been reset to temporary one. It should return
440
- // with NEW_PASSWORD_REQUIRED
441
- let user = yield this.auth.signIn(resetUser.username, tempIdpPassword, {
442
- noProxy: 'true',
443
- });
444
- if (user.challengeName !== 'NEW_PASSWORD_REQUIRED') {
445
- throw new LrException({
446
- message: 'Internal error. Expecting Cognito to have done a password reset after call to PreCompleteTpPasswordResetRequestMutation.',
447
- });
448
- }
449
- // Set new password on Idp
450
- // the awsFetch() function passes NEW_PASSWORD_REQUIRED directly to AWS without
451
- // going through the proxy.
452
- user = yield this.auth.completeNewPassword(user, newIdpPassword, {});
453
- return retPromise;
454
- });
455
- }
456
- recoverAssemblyKey(resetUser) {
457
- return __awaiter(this, void 0, void 0, function* () {
458
- const prk = yield this.keyGraphService.getKey(resetUser.pxk.id);
459
- const partials = yield Promise.all(resetUser.approvals
460
- .filter((approval) => !!approval.receiverCipherPartialAssemblyKey)
461
- .map((approval) => this.encryptionService.decrypt(prk, approval.receiverCipherPartialAssemblyKey)));
462
- return this.assemblyController.recoverAssemblyKey(partials);
463
- });
464
- }
465
- }
466
- LifeReadyAuthService.ɵprov = i0.ɵɵdefineInjectable({ factory: function LifeReadyAuthService_Factory() { return new LifeReadyAuthService(i0.ɵɵinject(i1.LR_CONFIG), i0.ɵɵinject(i2.AuthClass), i0.ɵɵinject(i3.KeyFactoryService), i0.ɵɵinject(i4.KeyService), i0.ɵɵinject(i5.ProfileService), i0.ɵɵinject(i6.KeyGraphService), i0.ɵɵinject(i7.PasswordService), i0.ɵɵinject(i8.IdleService), i0.ɵɵinject(i9.LrGraphQLService), i0.ɵɵinject(i10.TpPasswordResetProcessorService), i0.ɵɵinject(i11.PersistService), i0.ɵɵinject(i12.EncryptionService), i0.ɵɵinject(i13.Slip39Service), i0.ɵɵinject(i14.TpPasswordResetAssemblyController)); }, token: LifeReadyAuthService, providedIn: "root" });
467
- LifeReadyAuthService.decorators = [
468
- { type: Injectable, args: [{
469
- providedIn: 'root',
470
- },] }
471
- ];
472
- LifeReadyAuthService.ctorParameters = () => [
473
- { type: undefined, decorators: [{ type: Inject, args: [LR_CONFIG,] }] },
474
- { type: AuthClass },
475
- { type: KeyFactoryService },
476
- { type: KeyService },
477
- { type: ProfileService },
478
- { type: KeyGraphService },
479
- { type: PasswordService },
480
- { type: IdleService },
481
- { type: LrGraphQLService },
482
- { type: TpPasswordResetProcessorService },
483
- { type: PersistService },
484
- { type: EncryptionService },
485
- { type: Slip39Service },
486
- { type: TpPasswordResetAssemblyController }
487
- ];
488
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlmZS1yZWFkeS1hdXRoLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiQzovUHJvamVjdHMva2MtY2xpZW50L3Byb2plY3RzL2NvcmUvc3JjLyIsInNvdXJjZXMiOlsibGliL2F1dGgvbGlmZS1yZWFkeS1hdXRoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU5RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFeEMsT0FBTyxFQUFjLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDcEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQ0wsMkJBQTJCLEVBQzNCLHFCQUFxQixFQUNyQixtQkFBbUIsRUFDbkIsV0FBVyxHQUNaLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUtMLGNBQWMsR0FDZixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzNELE9BQU8sRUFDTCxzQ0FBc0MsRUFDdEMsb0NBQW9DLEVBQ3BDLHlDQUF5QyxFQUN6Qyx3QkFBd0IsR0FDekIsTUFBTSwwQ0FBMEMsQ0FBQztBQUNsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDeEUsT0FBTyxFQUFFLGdCQUFn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QyxDQUMxQyxDQUNGLENBQ0osQ0FBQztZQUVGLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlELENBQUM7S0FBQTs7OztZQTVuQkYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7NENBT0ksTUFBTSxTQUFDLFNBQVM7WUF6Q1osU0FBUztZQVFULGlCQUFpQjtZQXpCakIsVUFBVTtZQUNWLGNBQWM7WUFGZCxlQUFlO1lBaUJmLGVBQWU7WUFRZixXQUFXO1lBRVgsZ0JBQWdCO1lBRWhCLCtCQUErQjtZQUUvQixjQUFjO1lBR2QsaUJBQWlCO1lBQ2pCLGFBQWE7WUFLYixpQ0FBaUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIGlzRGV2TW9kZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb2duaXRvVXNlciB9IGZyb20gJ0Bhd3MtYW1wbGlmeS9hdXRoJztcclxuaW1wb3J0IHsgSHViIH0gZnJvbSAnQGF3cy1hbXBsaWZ5L2NvcmUnO1xyXG5pbXBvcnQgeyBDb2duaXRvVXNlckF0dHJpYnV0ZSB9IGZyb20gJ2FtYXpvbi1jb2duaXRvLWlkZW50aXR5LWpzJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgUmVwbGF5U3ViamVjdCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBQYXNzSWRwUGFyYW1zIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2NyeXB0b2dyYXBoeS50eXBlcyc7XHJcbmltcG9ydCB7IEtleUdyYXBoU2VydmljZSB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9rZXktZ3JhcGguc2VydmljZSc7XHJcbmltcG9ydCB7IEtleVNlcnZpY2UgfSBmcm9tICcuLi9jcnlwdG9ncmFwaHkva2V5LnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBQcm9maWxlU2VydmljZSB9IGZyb20gJy4uL3VzZXJzL3Byb2ZpbGUuc2VydmljZSc7XHJcbmltcG9ydCB7IFBhc3N3b3JkQ2hhbmdlU3RhdHVzIH0gZnJvbSAnLi4vdXNlcnMvcHJvZmlsZS50eXBlcyc7XHJcbmltcG9ydCB7XHJcbiAgTHJDb25jdXJyZW50QWNjZXNzRXhjZXB0aW9uLFxyXG4gIExyQmFkUmVxdWVzdEV4Y2VwdGlvbixcclxuICBMckJhZFN0YXRlRXhjZXB0aW9uLFxyXG4gIExyRXhjZXB0aW9uLFxyXG59IGZyb20gJy4uL19jb21tb24vZXhjZXB0aW9ucyc7XHJcbmltcG9ydCB7XHJcbiAgQ29nbml0b0NoYWxsZW5nZVVzZXIsXHJcbiAgQ3VycmVudFVzZXIsXHJcbiAgVHBQYXNzd29yZFJlc2V0VXNlcixcclxuICBMb2dpblJlc3VsdCxcclxuICBSZWNvdmVyeVN0YXR1cyxcclxufSBmcm9tICcuL2F1dGgudHlwZXMnO1xyXG5pbXBvcnQgeyBQYXNzd29yZFNlcnZpY2UgfSBmcm9tICcuL3Bhc3N3b3JkLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBBdXRoQ2xhc3MgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aC9saWItZXNtL0F1dGgnO1xyXG5pbXBvcnQge1xyXG4gIENvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLFxyXG4gIENyZWF0ZVRwQXNzZW1ibHlLZXlDaGFsbGVuZ2VNdXRhdGlvbixcclxuICBQcmVDb21wbGV0ZVRwUGFzc3dvcmRSZXNldFJlcXVlc3RNdXRhdGlvbixcclxuICBUcFBhc3N3b3JkUmVzZXRVc2VyUXVlcnksXHJcbn0gZnJvbSAnLi4vdHJ1c3RlZC1wYXJ0aWVzL3RwLXBhc3N3b3JkLXJlc2V0LmdxbCc7XHJcbmltcG9ydCB7IElkbGVTZXJ2aWNlIH0gZnJvbSAnLi9pZGxlLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBLZXlGYWN0b3J5U2VydmljZSB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9rZXktZmFjdG9yeS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgTHJHcmFwaFFMU2VydmljZSwgTHJNdXRhdGlvbiB9IGZyb20gJy4uL2FwaS9sci1ncmFwaHFsJztcclxuaW1wb3J0IHsgVHBDbGFpbVN0YXRlLCBUcFBhc3N3b3JkUmVzZXRVc2VyTm9kZSB9IGZyb20gJy4uL2FwaS90eXBlcyc7XHJcbmltcG9ydCB7IFRwUGFzc3dvcmRSZXNldFByb2Nlc3NvclNlcnZpY2UgfSBmcm9tICcuLi9hcGkvcXVlcnktcHJvY2Vzc29yL3RwLXBhc3N3b3JkLXJlc2V0LXByb2Nlc3Nvci5zZXJ2aWNlJztcclxuaW1wb3J0IHsgU2V0U2Vzc2lvbkVuY3J5cHRpb25LZXlNdXRhdGlvbiB9IGZyb20gJy4vYXV0aC5ncWwnO1xyXG5pbXBvcnQgeyBQZXJzaXN0U2VydmljZSB9IGZyb20gJy4uL2FwaS9wZXJzaXN0LnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBKV0sgfSBmcm9tICdub2RlLWpvc2UnO1xyXG5pbXBvcnQgeyBMaWZlUmVhZHlDb25maWcsIExSX0NPTkZJRyB9IGZyb20gJy4uL2xpZmUtcmVhZHkuY29uZmlnJztcclxuaW1wb3J0IHsgRW5jcnlwdGlvblNlcnZpY2UgfSBmcm9tICcuLi9jcnlwdG9ncmFwaHkvZW5jcnlwdGlvbi5zZXJ2aWNlJztcclxuaW1wb3J0IHsgU2xpcDM5U2VydmljZSB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9zbGlwMzkuc2VydmljZSc7XHJcbmltcG9ydCB7XHJcbiAgVFBfUEFTU1dPUkRfUkVTRVRfQ0xJRU5UX05PTkNFX0xFTkdUSCxcclxuICBUUF9QQVNTV09SRF9SRVNFVF9VU0VSTkFNRV9TVUZGSVgsXHJcbn0gZnJvbSAnLi4vdHJ1c3RlZC1wYXJ0aWVzL3RwLXBhc3N3b3JkLXJlc2V0LmNvbnN0YW50cyc7XHJcbmltcG9ydCB7IFRwUGFzc3dvcmRSZXNldEFzc2VtYmx5Q29udHJvbGxlciB9IGZyb20gJy4uL3RydXN0ZWQtcGFydGllcy90cC1wYXNzd29yZC1yZXNldC5jb250cm9sbGVyJztcclxuXHJcbmV4cG9ydCBjb25zdCBpbml0aWFsaXNlQXV0aCA9IChhdXRoU2VydmljZTogTGlmZVJlYWR5QXV0aFNlcnZpY2UpID0+IHtcclxuICByZXR1cm4gKCkgPT4gYXV0aFNlcnZpY2UuaW5pdGlhbGlzZSgpO1xyXG59O1xyXG5cclxuZXhwb3J0IGludGVyZmFjZSBMb2dpbk9wdGlvbnMge1xyXG4gIHRwUGFzc3dvcmRSZXNldEF1dG9Db21wbGV0ZT86IGJvb2xlYW47XHJcbn1cclxuXHJcbkBJbmplY3RhYmxlKHtcclxuICBwcm92aWRlZEluOiAncm9vdCcsXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBMaWZlUmVhZHlBdXRoU2VydmljZSB7XHJcbiAgcHJpdmF0ZSBodWJTdWJqZWN0OiBSZXBsYXlTdWJqZWN0PGFueT4gPSBuZXcgUmVwbGF5U3ViamVjdDxhbnk+KDEpO1xyXG4gIHByaXZhdGUgY3VycmVudFVzZXI6IEN1cnJlbnRVc2VyO1xyXG4gIHByaXZhdGUgY3VycmVudFJlc2V0VXNlcjogVHBQYXNzd29yZFJlc2V0VXNlcjtcclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBASW5qZWN0KExSX0NPTkZJRykgcHJpdmF0ZSBjb25maWc6IExpZmVSZWFkeUNvbmZpZyxcclxuICAgIHByaXZhdGUgYXV0aDogQXV0aENsYXNzLFxyXG4gICAgcHJpdmF0ZSBrZXlGYWN0b3J5OiBLZXlGYWN0b3J5U2VydmljZSxcclxuICAgIHByaXZhdGUga2V5U2VydmljZTogS2V5U2VydmljZSxcclxuICAgIHByaXZhdGUgcHJvZmlsZVNlcnZpY2U6IFByb2ZpbGVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBrZXlHcmFwaFNlcnZpY2U6IEtleUdyYXBoU2VydmljZSxcclxuICAgIHByaXZhdGUgcGFzc3dvcmRTZXJ2aWNlOiBQYXNzd29yZFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGlkbGVTZXJ2aWNlOiBJZGxlU2VydmljZSxcclxuICAgIHByaXZhdGUgbHJHcmFwaFFMOiBMckdyYXBoUUxTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB0cFBhc3N3b3JkUmVzZXRQcm9jZXNzb3JTZXJ2aWNlOiBUcFBhc3N3b3JkUmVzZXRQcm9jZXNzb3JTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBwZXJzaXN0U2VydmljZTogUGVyc2lzdFNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGVuY3J5cHRpb25TZXJ2aWNlOiBFbmNyeXB0aW9uU2VydmljZSxcclxuICAgIHByaXZhdGUgc2xpcDM5U2VydmljZTogU2xpcDM5U2VydmljZSxcclxuICAgIHByaXZhdGUgYXNzZW1ibHlDb250cm9sbGVyOiBUcFBhc3N3b3JkUmVzZXRBc3NlbWJseUNvbnRyb2xsZXJcclxuICApIHt9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBpbml0aWFsaXNlKCkge1xyXG4gICAgSHViLmxpc3RlbignYXV0aCcsIChkYXRhKSA9PiB0aGlzLmh1YlN1YmplY3QubmV4dChkYXRhLnBheWxvYWQpKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgbG9naW5JZHBJbXBsKFxyXG4gICAgZW1haWxPclBob25lOiBzdHJpbmcsXHJcbiAgICBwYXNzd29yZDogc3RyaW5nLFxyXG4gICAgcGFzc0lkcFBhcmFtczogUGFzc0lkcFBhcmFtcyxcclxuICAgIHJlY292ZXJ5U3RhdHVzOiBSZWNvdmVyeVN0YXR1c1xyXG4gICk6IFByb21pc2U8Q29nbml0b0NoYWxsZW5nZVVzZXI+IHtcclxuICAgIGNvbnN0IHBhc3NJZHBSZXN1bHQgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0lkcCh7XHJcbiAgICAgIHBhc3N3b3JkLFxyXG4gICAgICAuLi5wYXNzSWRwUGFyYW1zLFxyXG4gICAgfSk7XHJcbiAgICAvLyBVc2UgdGhlIGRlcml2ZWQgcGFzc3dvcmQgdG8gc2lnbmluIHdpdGggY29nbml0b1xyXG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuYXV0aC5zaWduSW4oXHJcbiAgICAgIGVtYWlsT3JQaG9uZSxcclxuICAgICAgdGhpcy5wYXNzd29yZFNlcnZpY2UuZ2V0UGFzc0lkcFN0cmluZyhwYXNzSWRwUmVzdWx0Lmp3aylcclxuICAgICk7XHJcblxyXG4gICAgdXNlci5yZWNvdmVyeVN0YXR1cyA9IHJlY292ZXJ5U3RhdHVzO1xyXG5cclxuICAgIHJldHVybiB1c2VyO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBsb2dpbklkcChcclxuICAgIGVtYWlsT3JQaG9uZTogc3RyaW5nLFxyXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xyXG4gICk6IFByb21pc2U8Q29nbml0b0NoYWxsZW5nZVVzZXI+IHtcclxuICAgIC8vIERvd25sb2FkIHRoZSBzYWx0IG5lZWRlZCB0byBkZXJpdmUgdGhlIFBhc3NJZHBcclxuICAgIGNvbnN0IHBhc3NJZHBBcGlSZXN1bHQgPSBhd2FpdCB0aGlzLnByb2ZpbGVTZXJ2aWNlLmdldFBhc3NJZHBQYXJhbXMoXHJcbiAgICAgIGVtYWlsT3JQaG9uZVxyXG4gICAgKTtcclxuXHJcbiAgICBpZiAoXHJcbiAgICAgIHBhc3NJZHBBcGlSZXN1bHQucGFzc3dvcmRDaGFuZ2VTdGF0dXMgPT09IFBhc3N3b3JkQ2hhbmdlU3RhdHVzLkluUHJvZ3Jlc3NcclxuICAgICkge1xyXG4gICAgICB0aHJvdyBuZXcgTHJDb25jdXJyZW50QWNjZXNzRXhjZXB0aW9uKCdBIHBhc3N3b3JkIGNoYW5nZSBpcyBpbiBwcm9ncmVzcycpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChcclxuICAgICAgcGFzc0lkcEFwaVJlc3VsdC5wYXNzd29yZENoYW5nZVN0YXR1cyA9PT0gUGFzc3dvcmRDaGFuZ2VTdGF0dXMuUmVjb3ZlcnlcclxuICAgICkge1xyXG4gICAgICBjb25zb2xlLmxvZygnSW4gcmVjb3ZlcnkgbW9kZS4nKTtcclxuICAgICAgLy8gTGV0J3Mgc2F5IHdlIGRvbid0IGtub3cgaWYgdGhlIHBhc3N3b3JkIGlzIHRoZSBuZXcgb25lIG9yIHRoZSBvbGQgb25lLiBXZSBqdXN0IGhhdmUgdG8gdHJ5IGJvdGguXHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMubG9naW5JZHBJbXBsKFxyXG4gICAgICAgICAgZW1haWxPclBob25lLFxyXG4gICAgICAgICAgcGFzc3dvcmQsXHJcbiAgICAgICAgICBwYXNzSWRwQXBpUmVzdWx0Lm5ld1Bhc3NJZHBQYXJhbXMsXHJcbiAgICAgICAgICBSZWNvdmVyeVN0YXR1cy5ORVdfUEFTU1dPUkRcclxuICAgICAgICApO1xyXG4gICAgICAgIC8vIE5ldyBwYXNzd29yZCB3b3JrZWQuIExldCdzIHNldCB0byB0aGUgY3VycmVudCBwYXNzd29yZFxyXG5cclxuICAgICAgICAvLyAtLVBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDEtLVxyXG4gICAgICAgIC8vIGlmIGNoYW5nZVBhc3N3b3JkQ29tcGxldGUoKSBkb2Vzbid0IGdldCBjYWxsZWQsIHRoZW4gaXQgc2hvdWxkIHJlbWFpblxyXG5cclxuICAgICAgICBjb25zb2xlLmxvZygnTmV3IHBhc3N3b3JkIHdvcmtzIScpO1xyXG5cclxuICAgICAgICByZXR1cm4gdXNlcjtcclxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAvLyBKdXN0IGJ1YmJsZSB1cCBhbnkgb3RoZXIgdHlwZSBvZiBlcnJvci5cclxuICAgICAgICBpZiAoZXJyb3IuY29kZSAhPT0gJ05vdEF1dGhvcml6ZWRFeGNlcHRpb24nKSB7XHJcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gcGFzcywgdHJ5IGFnYWluIGFzc3VtaW5nIGl0J3MgdGhlIG9sZCBwYXNzd29yZFxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBOb3cgYXNzdW1lIGl0J3MgdGhlIHByZXZpb3VzIHBhc3N3b3JkLiBBbnkgZXhjZXB0aW9uIGlzIGFsbG93ZWQgdG8gYnViYmxlIHVwLlxyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmxvZ2luSWRwSW1wbChcclxuICAgICAgICAgIGVtYWlsT3JQaG9uZSxcclxuICAgICAgICAgIHBhc3N3b3JkLFxyXG4gICAgICAgICAgcGFzc0lkcEFwaVJlc3VsdC5jdXJyZW50UGFzc0lkcFBhcmFtcyxcclxuICAgICAgICAgIFJlY292ZXJ5U3RhdHVzLk9MRF9QQVNTV09SRFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgLy8gT2xkIHBhc3N3b3JkIHdvcmtlZC5cclxuICAgICAgICBjb25zb2xlLmxvZygnT2xkIHBhc3N3b3JkIHdvcmtzIScpO1xyXG5cclxuICAgICAgICByZXR1cm4gdXNlcjtcclxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAvLyBKdXN0IGJ1YmJsZSB1cCBhbnkgb3RoZXIgdHlwZSBvZiBlcnJvci5cclxuICAgICAgICB0aHJvdyBlcnJvci5jb2RlID09PSAnTm90QXV0aG9yaXplZEV4Y2VwdGlvbidcclxuICAgICAgICAgID8gbmV3IExyQmFkUmVxdWVzdEV4Y2VwdGlvbihcclxuICAgICAgICAgICAgICAnVGhlIHBhc3N3b3JkIGNoYW5nZSByZXF1ZXN0IHdhcyBpbnRlcnJ1cHRlZCwgcGxlYXNlIHRyeSB0byBsb2dpbiB3aXRoIGJvdGggeW91ciBuZXcgYW5kIG9sZCBwYXNzd29yZCdcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgICAgOiBlcnJvcjtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIFRyeSBhZ2FpbnN0IGFzIHRoZSBUUCBwYXNzd29yZCByZXNldCBhY2NvdW50XHJcbiAgICBpZiAocGFzc0lkcEFwaVJlc3VsdC50cFBhc3N3b3JkUmVzZXQpIHtcclxuICAgICAgdHJ5IHtcclxuICAgICAgICAvLyBUUCBwYXNzd29yZCByZXNldCBpcyBpbiBwcm9jZXNzLiBXZSBuZWVkIHRvIHRyeSB0aGUgcGFzc3dvcmQgYWdhaW5zdCBib3RoXHJcbiAgICAgICAgLy8gb3JpZ2luYWwgYWNjb3VudCBhbmQgdGhlIG5ldyByZXNldCBhY2NvdW50LlxyXG4gICAgICAgIGNvbnN0IHJlc2V0ID0gcGFzc0lkcEFwaVJlc3VsdC50cFBhc3N3b3JkUmVzZXQ7XHJcbiAgICAgICAgY29uc3QgcmV0ID0gYXdhaXQgdGhpcy5sb2dpbklkcEltcGwoXHJcbiAgICAgICAgICByZXNldC5yZXNldFVzZXJuYW1lLFxyXG4gICAgICAgICAgcGFzc3dvcmQsXHJcbiAgICAgICAgICByZXNldC5wYXNzSWRwUGFyYW1zLFxyXG4gICAgICAgICAgUmVjb3ZlcnlTdGF0dXMuTk9ORVxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0LmlzVHBQYXNzd29yZFJlc2V0VXNlciA9IHRydWU7XHJcblxyXG4gICAgICAgIHJldHVybiByZXQ7XHJcbiAgICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAgIC8vIGNvbnRpbnVlLCB0cnkgYWdhaW4gYXMgcmVndWxhciB1c2VyLlxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gTG9naW4gYXMgcmVndWxhciB1c2VyXHJcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5sb2dpbklkcEltcGwoXHJcbiAgICAgIGVtYWlsT3JQaG9uZSxcclxuICAgICAgcGFzc3dvcmQsXHJcbiAgICAgIHBhc3NJZHBBcGlSZXN1bHQuY3VycmVudFBhc3NJZHBQYXJhbXMsXHJcbiAgICAgIFJlY292ZXJ5U3RhdHVzLk5PTkVcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBwcm90ZWN0ZWQgYXN5bmMgaGFuZGxlU2Vzc2lvbkVuY3J5cHRpb25LZXkoKSB7XHJcbiAgICBpZiAodGhpcy5jb25maWcuZGlzYWJsZVNlc3Npb25FbmNyeXB0aW9uS2V5KSB7XHJcbiAgICAgIGlmICghaXNEZXZNb2RlKCkpIHtcclxuICAgICAgICBjb25zdCBtc2cgPVxyXG4gICAgICAgICAgJ1lvdSBzaG91bGQgbm90IHNldCBkaXNhYmxlU2Vzc2lvbkVuY3J5cHRpb25LZXk9VHJ1ZSBpbiBtb2RlIHByb2QuIEl0IGRlZmF1bHRzIHRvIGZhbHNlLic7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNvbnNvbGUud2FybihcclxuICAgICAgICAgICdZb3UgaGF2ZSBzZXQgZGlzYWJsZVNlc3Npb25FbmNyeXB0aW9uS2V5PVRydWUuIE1ha2Ugc3VyZSBub3QgdG8gZG8gdGhpcyBpbiBwcm9kIG1vZGUuJ1xyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIFNldCB0aGUgc2Vzc2lvbiBrZXkgdG8gYSBuZXcgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgc2Vzc2lvblxyXG4gICAgICBjb25zdCBzZXNzaW9uRW5jcnlwdGlvbktleSA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5jcmVhdGVLZXkoKTtcclxuICAgICAgYXdhaXQgdGhpcy5sckdyYXBoUUwubHJNdXRhdGUoXHJcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xyXG4gICAgICAgICAgbXV0YXRpb246IFNldFNlc3Npb25FbmNyeXB0aW9uS2V5TXV0YXRpb24sXHJcbiAgICAgICAgICB2YXJpYWJsZXM6IHtcclxuICAgICAgICAgICAgaW5wdXQ6IHtcclxuICAgICAgICAgICAgICBzZXNzaW9uRW5jcnlwdGlvbktleTogSlNPTi5zdHJpbmdpZnkoXHJcbiAgICAgICAgICAgICAgICBzZXNzaW9uRW5jcnlwdGlvbktleS50b0pTT04odHJ1ZSlcclxuICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9KSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBpbmNsdWRlS2V5R3JhcGg6IGZhbHNlLFxyXG4gICAgICAgIH1cclxuICAgICAgKTtcclxuXHJcbiAgICAgIHRoaXMucGVyc2lzdFNlcnZpY2Uuc2V0U2VydmVyU2Vzc2lvbkVuY3J5cHRpb25LZXkoc2Vzc2lvbkVuY3J5cHRpb25LZXkpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJvdGVjdGVkIGFzeW5jIGhhbmRsZVBvc3RBdXRoKGNvZ25pdG9Vc2VyOiBDb2duaXRvQ2hhbGxlbmdlVXNlcikge1xyXG4gICAgYXdhaXQgdGhpcy5oYW5kbGVQYXNzd29yZFJlY292ZXJ5KGNvZ25pdG9Vc2VyKTtcclxuICAgIGF3YWl0IHRoaXMuaGFuZGxlU2Vzc2lvbkVuY3J5cHRpb25LZXkoKTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBsb2dpbihcclxuICAgIGVtYWlsT3JQaG9uZTogc3RyaW5nLFxyXG4gICAgcGFzc3dvcmQ6IHN0cmluZyxcclxuICAgIHsgdHBQYXNzd29yZFJlc2V0QXV0b0NvbXBsZXRlID0gdHJ1ZSB9OiBMb2dpbk9wdGlvbnMgPSB7fVxyXG4gICkge1xyXG4gICAgbGV0IGxvZ2luUmVzdWx0ID0gYXdhaXQgdGhpcy5sb2dpbkltcGwoZW1haWxPclBob25lLCBwYXNzd29yZCk7XHJcblxyXG4gICAgaWYgKFxyXG4gICAgICB0cFBhc3N3b3JkUmVzZXRBdXRvQ29tcGxldGUgJiZcclxuICAgICAgbG9naW5SZXN1bHQucmVzZXRVc2VyPy5zdGF0ZSA9PT0gVHBDbGFpbVN0YXRlLkFQUFJPVkVEXHJcbiAgICApIHtcclxuICAgICAgYXdhaXQgdGhpcy5jb21wbGV0ZVJlcXVlc3QocGFzc3dvcmQpO1xyXG4gICAgICBsb2dpblJlc3VsdCA9IGF3YWl0IHRoaXMubG9naW5JbXBsKGVtYWlsT3JQaG9uZSwgcGFzc3dvcmQpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBsb2dpblJlc3VsdDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBsb2dpbkltcGwoXHJcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZyxcclxuICAgIHBhc3N3b3JkOiBzdHJpbmdcclxuICApOiBQcm9taXNlPExvZ2luUmVzdWx0PiB7XHJcbiAgICBhd2FpdCB0aGlzLmxvZ291dCgpO1xyXG4gICAgY29uc3QgY29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmxvZ2luSWRwKGVtYWlsT3JQaG9uZSwgcGFzc3dvcmQpO1xyXG5cclxuICAgIC8vIHRvZG86IE1lZXQgTUZBIGNoYWxsZW5nZXMuXHJcbiAgICBpZiAoWydTTVNfTUZBJywgJ1NPRlRXQVJFX1RPS0VOX01GQSddLmluY2x1ZGVzKGNvZ25pdG9Vc2VyLmNoYWxsZW5nZU5hbWUpKSB7XHJcbiAgICAgIHJldHVybiB7IGhhc0NoYWxsZW5nZTogdHJ1ZSwgY2hhbGxlbmdlOiBjb2duaXRvVXNlciB9O1xyXG4gICAgfVxyXG5cclxuICAgIGF3YWl0IHRoaXMuaGFuZGxlUG9zdEF1dGgoY29nbml0b1VzZXIpO1xyXG5cclxuICAgIGlmIChjb2duaXRvVXNlci5pc1RwUGFzc3dvcmRSZXNldFVzZXIpIHtcclxuICAgICAgLy8gQXNzdW1pbmcgdGhlcmUgaXMgbm8gTUZBIG9uIHRoZSBUUCByZXNldCB1c2VyLlxyXG4gICAgICBjb25zdCByZXNldFVzZXIgPSBhd2FpdCB0aGlzLmxvYWRSZXNldFVzZXIocGFzc3dvcmQpO1xyXG4gICAgICByZXR1cm4geyBoYXNDaGFsbGVuZ2U6IGZhbHNlLCByZXNldFVzZXIgfTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmxvYWRVc2VyKGNvZ25pdG9Vc2VyLCBwYXNzd29yZCk7XHJcbiAgICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2Uuc3RhcnQoKTsgLy8gUnVuIGlkbGVTZXJ2aWNlIHdoZW5ldmVyIHVzZXIgaXMgbG9nZ2VkIGluLlxyXG4gICAgICByZXR1cm4geyBoYXNDaGFsbGVuZ2U6IGZhbHNlLCB1c2VyIH07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBUT0RPIDxBWj4gV2UgbmVlZCB0byBoYW5kbGUgdGhlIGlzVHBQYXNzd29yZFJlc2V0VXNlcj1UcnVlIGNhc2UgaGVyZSBhZnRlciBNRkEgYXMgd2VsbC5cclxuICBwdWJsaWMgYXN5bmMgdmVyaWZ5TG9naW4oXHJcbiAgICBjaGFsbGVuZ2U6IENvZ25pdG9DaGFsbGVuZ2VVc2VyLFxyXG4gICAgcGFzc3dvcmQ6IHN0cmluZyxcclxuICAgIHJlbWVtYmVyTWU6IGJvb2xlYW4sXHJcbiAgICBjb2RlOiBzdHJpbmdcclxuICApOiBQcm9taXNlPEN1cnJlbnRVc2VyPiB7XHJcbiAgICBhd2FpdCB0aGlzLmF1dGguY29uZmlybVNpZ25JbihjaGFsbGVuZ2UsIGNvZGUsIGNoYWxsZW5nZS5jaGFsbGVuZ2VOYW1lKTtcclxuXHJcbiAgICAvLyBUT0RPOiB0aGlzLmF1dGguY29uZmlybVNpZ25JbigpIGNvdWxkIHJldHVybiBhbm90aGVyIGNoYWxsZW5nZS5cclxuXHJcbiAgICBjb25zdCBjb2duaXRvVXNlcjogQ29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XHJcblxyXG4gICAgYXdhaXQgdGhpcy5oYW5kbGVQb3N0QXV0aChjaGFsbGVuZ2UpO1xyXG5cclxuICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmxvYWRVc2VyKGNvZ25pdG9Vc2VyLCBwYXNzd29yZCk7XHJcblxyXG4gICAgaWYgKHJlbWVtYmVyTWUpIHtcclxuICAgICAgY29nbml0b1VzZXIuc2V0RGV2aWNlU3RhdHVzUmVtZW1iZXJlZCh7XHJcbiAgICAgICAgb25TdWNjZXNzOiAoKSA9PiB7fSxcclxuICAgICAgICBvbkZhaWx1cmU6IChlKSA9PiBjb25zb2xlLmVycm9yKGUpLFxyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdXNlcjtcclxuICB9XHJcblxyXG4gIGFzeW5jIGhhbmRsZVBhc3N3b3JkUmVjb3ZlcnkodXNlcjogQ29nbml0b0NoYWxsZW5nZVVzZXIpIHtcclxuICAgIGlmICh1c2VyLnJlY292ZXJ5U3RhdHVzICE9PSBSZWNvdmVyeVN0YXR1cy5OT05FKSB7XHJcbiAgICAgIGNvbnN0IGp3dFRva2VuID0gdXNlclxyXG4gICAgICAgIC5nZXRTaWduSW5Vc2VyU2Vzc2lvbigpXHJcbiAgICAgICAgLmdldEFjY2Vzc1Rva2VuKClcclxuICAgICAgICAuZ2V0Snd0VG9rZW4oKTtcclxuICAgICAgYXdhaXQgdGhpcy5wYXNzd29yZFNlcnZpY2UuY2hhbmdlUGFzc3dvcmRDb21wbGV0ZShcclxuICAgICAgICBqd3RUb2tlbixcclxuICAgICAgICB1c2VyLnJlY292ZXJ5U3RhdHVzID09PSBSZWNvdmVyeVN0YXR1cy5ORVdfUEFTU1dPUkRcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGFzeW5jIGdldFVzZXJPclJlc2V0VXNlcihcclxuICAgIHJlbG9hZDogYm9vbGVhbiA9IGZhbHNlXHJcbiAgKTogUHJvbWlzZTxDdXJyZW50VXNlciB8IFRwUGFzc3dvcmRSZXNldFVzZXI+IHtcclxuICAgIGNvbnN0IGNvZ25pdG9Vc2VyID0gYXdhaXQgdGhpcy5hdXRoLmN1cnJlbnRBdXRoZW50aWNhdGVkVXNlcigpO1xyXG5cclxuICAgIGlmIChjb2duaXRvVXNlci5nZXRVc2VybmFtZSgpLmVuZHNXaXRoKFRQX1BBU1NXT1JEX1JFU0VUX1VTRVJOQU1FX1NVRkZJWCkpIHtcclxuICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVzZXRVc2VyKHJlbG9hZCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gdGhpcy5nZXRVc2VyKHJlbG9hZCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBnZXRSZXNldFVzZXIocmVsb2FkOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPFRwUGFzc3dvcmRSZXNldFVzZXI+IHtcclxuICAgIGlmICghcmVsb2FkICYmIHRoaXMuY3VycmVudFJlc2V0VXNlcikge1xyXG4gICAgICByZXR1cm4gdGhpcy5jdXJyZW50UmVzZXRVc2VyO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuY3VycmVudFJlc2V0VXNlciA9IGF3YWl0IHRoaXMubG9hZFJlc2V0VXNlcigpO1xyXG5cclxuICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2Uuc3RhcnQoKTsgLy8gUnVuIGlkbGVTZXJ2aWNlIHdoZW5ldmVyIHVzZXIgaXMgbG9nZ2VkIGluLlxyXG5cclxuICAgIHJldHVybiB0aGlzLmN1cnJlbnRSZXNldFVzZXI7XHJcbiAgfVxyXG5cclxuICBhc3luYyBnZXRVc2VyKHJlbG9hZDogYm9vbGVhbiA9IGZhbHNlKTogUHJvbWlzZTxDdXJyZW50VXNlcj4ge1xyXG4gICAgaWYgKCFyZWxvYWQgJiYgdGhpcy5jdXJyZW50VXNlcikge1xyXG4gICAgICByZXR1cm4gdGhpcy5jdXJyZW50VXNlcjtcclxuICAgIH1cclxuICAgIHRoaXMuY3VycmVudFVzZXIgPSBhd2FpdCB0aGlzLmxvYWRVc2VyKFxyXG4gICAgICBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKClcclxuICAgICk7XHJcbiAgICBjb25zb2xlLmxvZygnU3RhcnRpbmcgaWRsZSBzZXJ2aWNlLicpO1xyXG4gICAgYXdhaXQgdGhpcy5pZGxlU2VydmljZS5zdGFydCgpOyAvLyBSdW4gaWRsZVNlcnZpY2Ugd2hlbmV2ZXIgdXNlciBpcyBsb2dnZWQgaW4uXHJcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50VXNlcjtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgbWFwVFBWYXVsdEFjY2VzcyhmZWF0dXJlcz86IGFueSk6IGJvb2xlYW4ge1xyXG4gICAgY29uc3QgdHBWYXVsdEZlYXR1cmUgPSBmZWF0dXJlcz8udHBWYXVsdDtcclxuICAgIHJldHVybiAoXHJcbiAgICAgIHRwVmF1bHRGZWF0dXJlPy5sZW5ndGggPiAwICYmXHJcbiAgICAgIHRwVmF1bHRGZWF0dXJlLnNvbWUoKGZlYXR1cmUpID0+IGZlYXR1cmUudG9VcHBlckNhc2UoKSA9PT0gJ0FDQ0VTUycpXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBsb2FkVXNlcihcclxuICAgIGNvZ25pdG9Vc2VyOiBDb2duaXRvVXNlcixcclxuICAgIHBhc3N3b3JkPzogc3RyaW5nXHJcbiAgKTogUHJvbWlzZTxDdXJyZW50VXNlcj4ge1xyXG4gICAgY29uc3Qge1xyXG4gICAgICBjdXJyZW50VXNlcixcclxuICAgICAgY29udGFjdENhcmQsXHJcbiAgICAgIHVzZXJQbGFucyxcclxuICAgIH0gPSBhd2FpdCB0aGlzLnByb2ZpbGVTZXJ2aWNlLmdldEN1cnJlbnRVc2VyKCk7XHJcblxyXG4gICAgaWYgKGN1cnJlbnRVc2VyLnNlc3Npb25FbmNyeXB0aW9uS2V5KSB7XHJcbiAgICAgIHRoaXMucGVyc2lzdFNlcnZpY2Uuc2V0U2VydmVyU2Vzc2lvbkVuY3J5cHRpb25LZXkoXHJcbiAgICAgICAgYXdhaXQgSldLLmFzS2V5KGN1cnJlbnRVc2VyLnNlc3Npb25FbmNyeXB0aW9uS2V5KVxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHVzZXJBdHRyaWJ1dGVzID0gYXdhaXQgdGhpcy5hdXRoLnVzZXJBdHRyaWJ1dGVzKGNvZ25pdG9Vc2VyKTtcclxuXHJcbiAgICBpZiAocGFzc3dvcmQpIHtcclxuICAgICAgY29uc3QgcGFzc0tleSA9IChcclxuICAgICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0tleSh7XHJcbiAgICAgICAgICBwYXNzd29yZCxcclxuICAgICAgICAgIC4uLmN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5LnBhc3NLZXkucGFzc0tleVBhcmFtcyxcclxuICAgICAgICB9KVxyXG4gICAgICApLmp3aztcclxuXHJcbiAgICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2UucGVyc2lzdE1hc3RlcktleShcclxuICAgICAgICBhd2FpdCB0aGlzLmtleUdyYXBoU2VydmljZS51bndyYXBXaXRoUGFzc0tleShcclxuICAgICAgICAgIGN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5LnBhc3NLZXkuaWQsXHJcbiAgICAgICAgICBwYXNzS2V5LFxyXG4gICAgICAgICAgY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkubWFzdGVyS2V5LmlkXHJcbiAgICAgICAgKVxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UucG9wdWxhdGVLZXlzKGN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5KTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBpZDogY3VycmVudFVzZXIuaWQsXHJcbiAgICAgIHN1YjogdGhpcy5nZXRVc2VyQXR0cmlidXRlKCdzdWInLCB1c2VyQXR0cmlidXRlcyksXHJcbiAgICAgIHVzZXJuYW1lOiBjdXJyZW50VXNlci51c2VybmFtZSxcclxuICAgICAgY3VycmVudFVzZXJLZXk6IGN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5LFxyXG4gICAgICBnZXRBY2Nlc3NKd3RUb2tlbjogKCkgPT5cclxuICAgICAgICBjb2duaXRvVXNlci5nZXRTaWduSW5Vc2VyU2Vzc2lvbigpLmdldEFjY2Vzc1Rva2VuKCkuZ2V0Snd0VG9rZW4oKSxcclxuICAgICAgZW1haWw6IHRoaXMuZ2V0VXNlckF0dHJpYnV0ZSgnZW1haWwnLCB1c2VyQXR0cmlidXRlcyksXHJcbiAgICAgIGVtYWlsVmVyaWZpZWQ6XHJcbiAgICAgICAgdGhpcy5nZXRVc2VyQXR0cmlidXRlKCdlbWFpbF92ZXJpZmllZCcsIHVzZXJBdHRyaWJ1dGVzKSA9PT0gJ3RydWUnLFxyXG4gICAgICBwaG9uZTogdGhpcy5nZXRVc2VyQXR0cmlidXRlKCdwaG9uZV9udW1iZXInLCB1c2VyQXR0cmlidXRlcyksXHJcbiAgICAgIHBob25lVmVyaWZpZWQ6XHJcbiAgICAgICAgdGhpcy5nZXRVc2VyQXR0cmlidXRlKCdwaG9uZV9udW1iZXJfdmVyaWZpZWQnLCB1c2VyQXR0cmlidXRlcykgPT09XHJcbiAgICAgICAgJ3RydWUnLFxyXG4gICAgICBjb250YWN0Q2FyZDoge1xyXG4gICAgICAgIC4uLihhd2FpdCB0aGlzLnByb2ZpbGVTZXJ2aWNlLmRlY3J5cHRDb250YWN0Q2FyZChjb250YWN0Q2FyZCkpLFxyXG4gICAgICB9LFxyXG4gICAgICB1c2VyRGVsZXRlOiBjdXJyZW50VXNlci51c2VyRGVsZXRlLFxyXG4gICAgICB1c2VyUGxhbnMsXHJcbiAgICAgIGhhc1RQVmF1bHRBY2Nlc3M6IHRoaXMubWFwVFBWYXVsdEFjY2VzcyhjdXJyZW50VXNlci5mZWF0dXJlcyksXHJcbiAgICAgIGZlYXR1cmVzOiBjdXJyZW50VXNlci5mZWF0dXJlcyxcclxuICAgICAgc2Vzc2lvbkVuY3J5cHRpb25LZXk6IGN1cnJlbnRVc2VyLnNlc3Npb25FbmNyeXB0aW9uS2V5LFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyB3YXRjaEF1dGgoKTogT2JzZXJ2YWJsZTxhbnk+IHtcclxuICAgIHJldHVybiB0aGlzLmh1YlN1YmplY3Q7XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgbG9nb3V0KCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgdGhpcy5jdXJyZW50VXNlciA9IG51bGw7XHJcbiAgICB0aGlzLmtleVNlcnZpY2UucHVyZ2VLZXlzKCk7XHJcbiAgICB0aGlzLmtleUdyYXBoU2VydmljZS5wdXJnZUtleXMoKTtcclxuXHJcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbdGhpcy5hdXRoLnNpZ25PdXQoKSwgdGhpcy5wcm9maWxlU2VydmljZS5zaWduT3V0KCldKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0VXNlckF0dHJpYnV0ZShcclxuICAgIGF0dHJpYnV0ZU5hbWU6IHN0cmluZyxcclxuICAgIHVzZXJBdHRyaWJ1dGVzOiBDb2duaXRvVXNlckF0dHJpYnV0ZVtdXHJcbiAgKSB7XHJcbiAgICBjb25zdCB1c2VyQXR0cmlidXRlID0gdXNlckF0dHJpYnV0ZXMuZmluZChcclxuICAgICAgKHgpID0+IHguZ2V0TmFtZSgpID09PSBhdHRyaWJ1dGVOYW1lXHJcbiAgICApO1xyXG5cclxuICAgIHJldHVybiB1c2VyQXR0cmlidXRlID8gdXNlckF0dHJpYnV0ZS5nZXRWYWx1ZSgpIDogbnVsbDtcclxuICB9XHJcblxyXG4gIHB1YmxpYyBhc3luYyBsb2FkUmVzZXRVc2VyKHBhc3N3b3JkPzogc3RyaW5nKTogUHJvbWlzZTxUcFBhc3N3b3JkUmVzZXRVc2VyPiB7XHJcbiAgICBjb25zdCB7IHRwUGFzc3dvcmRSZXNldFVzZXI6IHJlc2V0VXNlciB9ID0gYXdhaXQgdGhpcy5sckdyYXBoUUwucXVlcnkoe1xyXG4gICAgICBxdWVyeTogVHBQYXNzd29yZFJlc2V0VXNlclF1ZXJ5LFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKHJlc2V0VXNlci5zZXNzaW9uRW5jcnlwdGlvbktleSkge1xyXG4gICAgICB0aGlzLnBlcnNpc3RTZXJ2aWNlLnNldFNlcnZlclNlc3Npb25FbmNyeXB0aW9uS2V5KFxyXG4gICAgICAgIGF3YWl0IEpXSy5hc0tleShyZXNldFVzZXIuc2Vzc2lvbkVuY3J5cHRpb25LZXkpXHJcbiAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVXBkYXRlIHRoZSBrZXlzXHJcbiAgICBpZiAocGFzc3dvcmQpIHtcclxuICAgICAgY29uc3QgcGFzc0tleSA9IChcclxuICAgICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0tleSh7XHJcbiAgICAgICAgICBwYXNzd29yZCxcclxuICAgICAgICAgIC4uLnJlc2V0VXNlci5wYXNzS2V5LnBhc3NLZXlQYXJhbXMsXHJcbiAgICAgICAgfSlcclxuICAgICAgKS5qd2s7XHJcblxyXG4gICAgICBhd2FpdCB0aGlzLmlkbGVTZXJ2aWNlLnBlcnNpc3RNYXN0ZXJLZXkoXHJcbiAgICAgICAgYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UudW53cmFwV2l0aFBhc3NLZXkoXHJcbiAgICAgICAgICByZXNldFVzZXIucGFzc0tleS5pZCxcclxuICAgICAgICAgIHBhc3NLZXksXHJcbiAgICAgICAgICByZXNldFVzZXIubWFzdGVyS2V5LmlkXHJcbiAgICAgICAgKVxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMua2V5U2VydmljZS5wb3B1bGF0ZUtleXMoe1xyXG4gICAgICBwYXNzS2V5OiB7XHJcbiAgICAgICAgaWQ6IHJlc2V0VXNlci5wYXNzS2V5LmlkLFxyXG4gICAgICB9LFxyXG4gICAgICBtYXN0ZXJLZXk6IHtcclxuICAgICAgICBpZDogcmVzZXRVc2VyLm1hc3RlcktleS5pZCxcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHVzZXJBdHRyaWJ1dGVzID0gYXdhaXQgdGhpcy5hdXRoLnVzZXJBdHRyaWJ1dGVzKFxyXG4gICAgICBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKClcclxuICAgICk7XHJcbiAgICBjb25zdCBzdWIgPSB0aGlzLmdldFVzZXJBdHRyaWJ1dGUoJ3N1YicsIHVzZXJBdHRyaWJ1dGVzKTtcclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAuLi4oYXdhaXQgdGhpcy50cFBhc3N3b3JkUmVzZXRQcm9jZXNzb3JTZXJ2aWNlLnByb2Nlc3NUcFBhc3N3b3JkUmVzZXRVc2VyTm9kZShcclxuICAgICAgICByZXNldFVzZXJcclxuICAgICAgKSksXHJcbiAgICAgIHN1YixcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgYXN5bmMgcmVmcmVzaEFjY2Vzc1Rva2VuKCkge1xyXG4gICAgY29uc3QgY29nbml0b1VzZXI6IENvZ25pdG9Vc2VyID0gYXdhaXQgdGhpcy5hdXRoLmN1cnJlbnRBdXRoZW50aWNhdGVkVXNlcigpO1xyXG4gICAgY29uc3QgcmVmcmVzaFRva2VuID0gY29nbml0b1VzZXIuZ2V0U2lnbkluVXNlclNlc3Npb24oKS5nZXRSZWZyZXNoVG9rZW4oKTtcclxuXHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBjb2duaXRvVXNlci5yZWZyZXNoU2Vzc2lvbihyZWZyZXNoVG9rZW4sIChlcnIsIGRhdGEpID0+IHtcclxuICAgICAgICBpZiAoZXJyKSB7XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciByZWZyZXNoaW5nIHRva2VuOiAnLCBlcnIpO1xyXG4gICAgICAgICAgcmVqZWN0KGVycik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnNvbGUubG9nKCdUb2tlbiByZWZyZXNoIGNvbXBsZXRlOiAnLCBkYXRhKTtcclxuICAgICAgICAgIHJlc29sdmUoMCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgY29tcGxldGVSZXF1ZXN0KG5ld1Bhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGNvbnN0IHJlc2V0VXNlciA9IGF3YWl0IHRoaXMuZ2V0UmVzZXRVc2VyKHRydWUpO1xyXG5cclxuICAgIGlmIChyZXNldFVzZXIuc3RhdGUgIT09IFRwQ2xhaW1TdGF0ZS5BUFBST1ZFRCkge1xyXG4gICAgICB0aHJvdyBuZXcgTHJCYWRTdGF0ZUV4Y2VwdGlvbihcclxuICAgICAgICAnUGFzc3dvcmQgcmVzZXQgcmVxdWVzdCBoYXMgbm90IGJlZW4gYXBwcm92ZWQuJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICAvLyBQcmVwYXJlIGFsbCBtYXRlcmlhbHMgdG8gZW5zdXJlIHRoZXJlIGFyZSBubyBlcnJvcnMuXHJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgY29uc3QgYXNzZW1ibHlLZXkgPSBhd2FpdCB0aGlzLnJlY292ZXJBc3NlbWJseUtleShyZXNldFVzZXIpO1xyXG5cclxuICAgIGNvbnN0IHsgcm9vdEtleSB9ID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFxyXG4gICAgICBhc3NlbWJseUtleSxcclxuICAgICAgcmVzZXRVc2VyLmFzc2VtYmx5Q2lwaGVyRGF0YVxyXG4gICAgKTtcclxuICAgIGNvbnNvbGUubG9nKHJvb3RLZXkpO1xyXG5cclxuICAgIC8vIE1ha2luZyBzdXJlIGl0J3MgYSB2YWxpZCBrZXkuXHJcbiAgICBjb25zdCByb290S2V5SndrID0gYXdhaXQgSldLLmFzS2V5KHJvb3RLZXkpO1xyXG5cclxuICAgIGNvbnN0IG1hc3RlcktleSA9IGF3YWl0IHRoaXMua2V5R3JhcGhTZXJ2aWNlLmdldEtleShyZXNldFVzZXIubWFzdGVyS2V5LmlkKTtcclxuXHJcbiAgICBjb25zdCBtYXN0ZXJLZXlXcmFwcGVkUm9vdEtleSA9IGF3YWl0IHRoaXMuZW5jcnlwdGlvblNlcnZpY2UuZW5jcnlwdFRvU3RyaW5nKFxyXG4gICAgICBtYXN0ZXJLZXkuandrLFxyXG4gICAgICByb290S2V5SndrLnRvSlNPTih0cnVlKVxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBUaGUgbmV3IHBhc3N3b3JkXHJcbiAgICBjb25zdCBuZXdQYXNzSWRwUmVzdWx0ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmRlcml2ZVBhc3NJZHAoe1xyXG4gICAgICBwYXNzd29yZDogbmV3UGFzc3dvcmQsXHJcbiAgICAgIC4uLnJlc2V0VXNlci5wYXNzS2V5LnBhc3NJZHBQYXJhbXMsXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBuZXdJZHBQYXNzd29yZCA9IHRoaXMucGFzc3dvcmRTZXJ2aWNlLmdldFBhc3NJZHBTdHJpbmcoXHJcbiAgICAgIG5ld1Bhc3NJZHBSZXN1bHQuandrXHJcbiAgICApO1xyXG5cclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICAvLyBHZXQgYXNzZW1ibHkga2V5IGNoYWxsZW5nZVxyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgIGNvbnN0IGNoYWxsZW5nZSA9IChcclxuICAgICAgYXdhaXQgdGhpcy5sckdyYXBoUUwubHJNdXRhdGUoXHJcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xyXG4gICAgICAgICAgbXV0YXRpb246IENyZWF0ZVRwQXNzZW1ibHlLZXlDaGFsbGVuZ2VNdXRhdGlvbixcclxuICAgICAgICAgIHZhcmlhYmxlczoge1xyXG4gICAgICAgICAgICBpbnB1dDoge30sXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgIH0pLFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIGluY2x1ZGVLZXlHcmFwaDogZmFsc2UsXHJcbiAgICAgICAgfVxyXG4gICAgICApXHJcbiAgICApLmNyZWF0ZVRwQXNzZW1ibHlLZXlDaGFsbGVuZ2UuY2hhbGxlbmdlO1xyXG5cclxuICAgIGNvbnNvbGUubG9nKGNoYWxsZW5nZSk7XHJcblxyXG4gICAgLy8gU2lnbiB0aGUgY2hhbGxlbmdlXHJcbiAgICAvLyBHZW5lcmF0ZSBhIGNsaWVudCBzaWRlIG5vbmNlIHRoYXQncyBubyBpbiB0aGUgc2VydmVyJ3MgY29udHJvbC5cclxuICAgIGNoYWxsZW5nZS5jbGllbnROb25jZSA9IHRoaXMua2V5RmFjdG9yeS5yYW5kb21TdHJpbmcoXHJcbiAgICAgIFRQX1BBU1NXT1JEX1JFU0VUX0NMSUVOVF9OT05DRV9MRU5HVEhcclxuICAgICk7XHJcbiAgICBjb25zb2xlLmxvZyhjaGFsbGVuZ2UpO1xyXG5cclxuICAgIGNvbnN0IGFzc2VtYmx5S2V5VmVyaWZpZXJQcmsgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQoXHJcbiAgICAgIGFzc2VtYmx5S2V5LFxyXG4gICAgICByZXNldFVzZXIud3JhcHBlZEFzc2VtYmx5S2V5VmVyaWZpZXJQcmtcclxuICAgICk7XHJcbiAgICBjb25zdCBzaWduZWRDaGFsbGVuZ2UgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLnNpZ24oXHJcbiAgICAgIGFzc2VtYmx5S2V5VmVyaWZpZXJQcmssXHJcbiAgICAgIGNoYWxsZW5nZVxyXG4gICAgKTtcclxuXHJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxyXG4gICAgLy8gQ2hhbmdlIHBhc3N3b3JkIGZvciB0aGUgb3JpZ2luYWwgdXNlclxyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgIGNvbnN0IHRlbXBJZHBQYXNzd29yZCA9IChcclxuICAgICAgYXdhaXQgdGhpcy5sckdyYXBoUUwubHJNdXRhdGUoXHJcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xyXG4gICAgICAgICAgbXV0YXRpb246IFByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLFxyXG4gICAgICAgICAgdmFyaWFibGVzOiB7XHJcbiAgICAgICAgICAgIGlucHV0OiB7XHJcbiAgICAgICAgICAgICAgc2lnbmVkQ2hhbGxlbmdlOiBKU09OLnN0cmluZ2lmeShzaWduZWRDaGFsbGVuZ2UpLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgfSxcclxuICAgICAgICB9KSxcclxuICAgICAgICB7XHJcbiAgICAgICAgICBpbmNsdWRlS2V5R3JhcGg6IGZhbHNlLFxyXG4gICAgICAgIH1cclxuICAgICAgKVxyXG4gICAgKS5wcmVDb21wbGV0ZVRwUGFzc3dvcmRSZXNldFJlcXVlc3QuaWRwUGFzc3dvcmQ7XHJcblxyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cclxuICAgIC8vIExvZ2luIGFzIHRoZSBvcmlnaW5hbCB1c2VyIHVzaW5nIG5ldyB0ZW1wb3JhcnkgcGFzc3dvcmRcclxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcbiAgICAvLyBBdCB0aGlzIHBvaW50LCB0aGUgb3JpZ2luYWwgYWNjb3VudCdzIHBhc3N3b3JkIGhhcyBiZWVuIGNoYW5nZWRcclxuICAgIC8vIHRvIGEgdGVtcG9yYXJ5IHBhc3N3b3JkLiBJdCBpcyBubyBsb25nZXIgcG9zc2libGUgZm9yIHRoZSB1c2VyXHJcbiAgICAvLyB0byB1c2UgdGhlIG9yaWdpbmFsIHBhc3N3b3JkIHRvIGxvZ2luLiBBbnkgc3VjY2Vzc2Z1bCBsb2dpblxyXG4gICAgLy8gY2FuIG9ubHkgYmUgdXNpbmcgdGhlIHRlbXBvcmFyeSBwYXNzd29yZC4gU28gaXQncyBzYWZlIHRvIGFzc3VtZVxyXG4gICAgLy8gdGhhdCB3ZSB3YW50IHRvIFwiY29tcGxldGVcIiB0aGUgcGFzc3dvcmQgcmVzZXQuXHJcblxyXG4gICAgLy8gVGhlIG1heWJlIDJGQSBzbyB3ZSBsaXN0ZW4gZm9yIHRoZSBhdXRoIGV2ZW50IGZyb20gQW1wbGlmeS5cclxuICAgIGNvbnN0IHJldFByb21pc2UgPSBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xyXG4gICAgICBjb25zdCBsaXN0ZW5lciA9IGFzeW5jIChkYXRhKSA9PiB7XHJcbiAgICAgICAgaWYgKGRhdGEucGF5bG9hZC5ldmVudCAhPT0gJ3NpZ25JbicpIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIEh1Yi5yZW1vdmUoJ2F1dGgnLCBsaXN0ZW5lcik7XHJcblxyXG4gICAgICAgIGNvbnNvbGUubG9nKGRhdGEucGF5bG9hZCk7XHJcblxyXG4gICAgICAgIGF3YWl0IHRoaXMuYXV0aC5zaWduSW4ocmVzZXRVc2VyLnVzZXJuYW1lLCBuZXdJZHBQYXNzd29yZCk7XHJcblxyXG4gICAgICAgIC8vIFN3aXRjaCBvdmVyIHRvIHRoZSBuZXcgc2V0IG9mIGtleXNcclxuICAgICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcclxuICAgICAgICAgIG5ldyBMck11dGF0aW9uKHtcclxuICAgICAgICAgICAgbXV0YXRpb246IENvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLFxyXG4gICAgICAgICAgICB2YXJpYWJsZXM6IHtcclxuICAgICAgICAgICAgICBpbnB1dDoge1xyXG4gICAgICAgICAgICAgICAgbWFzdGVyS2V5V3JhcHBlZFJvb3RLZXksXHJcbiAgICAgICAgICAgICAgICBtYXN0ZXJLZXlJZDogbWFzdGVyS2V5LmlkLFxyXG4gICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgfTtcclxuXHJcbiAgICAgIEh1Yi5saXN0ZW4oJ2F1dGgnLCBsaXN0ZW5lcik7XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBTaWduaW4gYXMgdGhlIG9yaWdpbmFsIHVzZXIuIFBhc3N3b3JkIGhhcyBiZWVuIHJlc2V0IHRvIHRlbXBvcmFyeSBvbmUuIEl0IHNob3VsZCByZXR1cm5cclxuICAgIC8vIHdpdGggTkVXX1BBU1NXT1JEX1JFUVVJUkVEXHJcbiAgICBsZXQgdXNlciA9IGF3YWl0IHRoaXMuYXV0aC5zaWduSW4ocmVzZXRVc2VyLnVzZXJuYW1lLCB0ZW1wSWRwUGFzc3dvcmQsIHtcclxuICAgICAgbm9Qcm94eTogJ3RydWUnLFxyXG4gICAgfSk7XHJcblxyXG4gICAgaWYgKHVzZXIuY2hhbGxlbmdlTmFtZSAhPT0gJ05FV19QQVNTV09SRF9SRVFVSVJFRCcpIHtcclxuICAgICAgdGhyb3cgbmV3IExyRXhjZXB0aW9uKHtcclxuICAgICAgICBtZXNzYWdlOlxyXG4gICAgICAgICAgJ0ludGVybmFsIGVycm9yLiBFeHBlY3RpbmcgQ29nbml0byB0byBoYXZlIGRvbmUgYSBwYXNzd29yZCByZXNldCBhZnRlciBjYWxsIHRvIFByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLicsXHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFNldCBuZXcgcGFzc3dvcmQgb24gSWRwXHJcbiAgICAvLyB0aGUgYXdzRmV0Y2goKSBmdW5jdGlvbiBwYXNzZXMgTkVXX1BBU1NXT1JEX1JFUVVJUkVEIGRpcmVjdGx5IHRvIEFXUyB3aXRob3V0XHJcbiAgICAvLyBnb2luZyB0aHJvdWdoIHRoZSBwcm94eS5cclxuICAgIHVzZXIgPSBhd2FpdCB0aGlzLmF1dGguY29tcGxldGVOZXdQYXNzd29yZCh1c2VyLCBuZXdJZHBQYXNzd29yZCwge30pO1xyXG5cclxuICAgIHJldHVybiByZXRQcm9taXNlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyByZWNvdmVyQXNzZW1ibHlLZXkoXHJcbiAgICByZXNldFVzZXI6IFRwUGFzc3dvcmRSZXNldFVzZXJOb2RlXHJcbiAgKTogUHJvbWlzZTxKV0suS2V5PiB7XHJcbiAgICBjb25zdCBwcmsgPSBhd2FpdCB0aGlzLmtleUdyYXBoU2VydmljZS5nZXRLZXkocmVzZXRVc2VyLnB4ay5pZCk7XHJcblxyXG4gICAgY29uc3QgcGFydGlhbHMgPSBhd2FpdCBQcm9taXNlLmFsbChcclxuICAgICAgcmVzZXRVc2VyLmFwcHJvdmFsc1xyXG4gICAgICAgIC5maWx0ZXIoKGFwcHJvdmFsKSA9PiAhIWFwcHJvdmFsLnJlY2VpdmVyQ2lwaGVyUGFydGlhbEFzc2VtYmx5S2V5KVxyXG4gICAgICAgIC5tYXAoKGFwcHJvdmFsKSA9PlxyXG4gICAgICAgICAgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFxyXG4gICAgICAgICAgICBwcmssXHJcbiAgICAgICAgICAgIGFwcHJvdmFsLnJlY2VpdmVyQ2lwaGVyUGFydGlhbEFzc2VtYmx5S2V5XHJcbiAgICAgICAgICApXHJcbiAgICAgICAgKVxyXG4gICAgKTtcclxuXHJcbiAgICByZXR1cm4gdGhpcy5hc3NlbWJseUNvbnRyb2xsZXIucmVjb3ZlckFzc2VtYmx5S2V5KHBhcnRpYWxzKTtcclxuICB9XHJcbn1cclxuIl19
1
+ import { __awaiter } from "tslib";
2
+ import { Inject, Injectable, isDevMode } from '@angular/core';
3
+ import { Hub } from '@aws-amplify/core';
4
+ import { ReplaySubject } from 'rxjs';
5
+ import { KeyGraphService } from '../cryptography/key-graph.service';
6
+ import { KeyService } from '../cryptography/key.service';
7
+ import { ProfileService } from '../users/profile.service';
8
+ import { PasswordChangeStatus } from '../users/profile.types';
9
+ import { LrConcurrentAccessException, LrBadRequestException, LrBadStateException, LrException, } from '../_common/exceptions';
10
+ import { RecoveryStatus, } from './auth.types';
11
+ import { PasswordService } from './password.service';
12
+ import { AuthClass } from '@aws-amplify/auth/lib-esm/Auth';
13
+ import { CompleteTpPasswordResetRequestMutation, CreateTpAssemblyKeyChallengeMutation, PreCompleteTpPasswordResetRequestMutation, TpPasswordResetUserQuery, } from '../trusted-parties/tp-password-reset.gql';
14
+ import { IdleService } from './idle.service';
15
+ import { KeyFactoryService } from '../cryptography/key-factory.service';
16
+ import { LrGraphQLService, LrMutation } from '../api/lr-graphql';
17
+ import { TpClaimState } from '../api/types';
18
+ import { TpPasswordResetProcessorService } from '../api/query-processor/tp-password-reset-processor.service';
19
+ import { SetSessionEncryptionKeyMutation } from './auth.gql';
20
+ import { PersistService } from '../api/persist.service';
21
+ import { JWK } from 'node-jose';
22
+ import { LR_CONFIG } from '../life-ready.config';
23
+ import { EncryptionService } from '../cryptography/encryption.service';
24
+ import { Slip39Service } from '../cryptography/slip39.service';
25
+ import { TP_PASSWORD_RESET_CLIENT_NONCE_LENGTH, TP_PASSWORD_RESET_USERNAME_SUFFIX, } from '../trusted-parties/tp-password-reset.constants';
26
+ import { TpPasswordResetAssemblyController } from '../trusted-parties/tp-password-reset.controller';
27
+ import * as i0 from "@angular/core";
28
+ import * as i1 from "../life-ready.config";
29
+ import * as i2 from "@aws-amplify/auth/lib-esm/Auth";
30
+ import * as i3 from "../cryptography/key-factory.service";
31
+ import * as i4 from "../cryptography/key.service";
32
+ import * as i5 from "../users/profile.service";
33
+ import * as i6 from "../cryptography/key-graph.service";
34
+ import * as i7 from "./password.service";
35
+ import * as i8 from "./idle.service";
36
+ import * as i9 from "../api/lr-graphql/lr-graphql.service";
37
+ import * as i10 from "../api/query-processor/tp-password-reset-processor.service";
38
+ import * as i11 from "../api/persist.service";
39
+ import * as i12 from "../cryptography/encryption.service";
40
+ import * as i13 from "../cryptography/slip39.service";
41
+ import * as i14 from "../trusted-parties/tp-password-reset.controller";
42
+ export const initialiseAuth = (authService) => {
43
+ return () => authService.initialise();
44
+ };
45
+ export class LifeReadyAuthService {
46
+ constructor(config, auth, keyFactory, keyService, profileService, keyGraphService, passwordService, idleService, lrGraphQL, tpPasswordResetProcessorService, persistService, encryptionService, slip39Service, assemblyController) {
47
+ this.config = config;
48
+ this.auth = auth;
49
+ this.keyFactory = keyFactory;
50
+ this.keyService = keyService;
51
+ this.profileService = profileService;
52
+ this.keyGraphService = keyGraphService;
53
+ this.passwordService = passwordService;
54
+ this.idleService = idleService;
55
+ this.lrGraphQL = lrGraphQL;
56
+ this.tpPasswordResetProcessorService = tpPasswordResetProcessorService;
57
+ this.persistService = persistService;
58
+ this.encryptionService = encryptionService;
59
+ this.slip39Service = slip39Service;
60
+ this.assemblyController = assemblyController;
61
+ this.hubSubject = new ReplaySubject(1);
62
+ }
63
+ initialise() {
64
+ return __awaiter(this, void 0, void 0, function* () {
65
+ Hub.listen('auth', (data) => this.hubSubject.next(data.payload));
66
+ });
67
+ }
68
+ loginIdpImpl(emailOrPhone, password, passIdpParams, recoveryStatus) {
69
+ return __awaiter(this, void 0, void 0, function* () {
70
+ const passIdpResult = yield this.keyFactory.derivePassIdp(Object.assign({ password }, passIdpParams));
71
+ // Use the derived password to signin with cognito
72
+ const user = yield this.auth.signIn(emailOrPhone, this.passwordService.getPassIdpString(passIdpResult.jwk));
73
+ user.recoveryStatus = recoveryStatus;
74
+ return user;
75
+ });
76
+ }
77
+ loginIdp(emailOrPhone, password) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ // Download the salt needed to derive the PassIdp
80
+ const passIdpApiResult = yield this.profileService.getPassIdpParams(emailOrPhone);
81
+ if (passIdpApiResult.passwordChangeStatus === PasswordChangeStatus.InProgress) {
82
+ throw new LrConcurrentAccessException('A password change is in progress');
83
+ }
84
+ if (passIdpApiResult.passwordChangeStatus === PasswordChangeStatus.Recovery) {
85
+ console.log('In recovery mode.');
86
+ // Let's say we don't know if the password is the new one or the old one. We just have to try both.
87
+ try {
88
+ const user = yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.newPassIdpParams, RecoveryStatus.NEW_PASSWORD);
89
+ // New password worked. Let's set to the current password
90
+ // --Potential Failure Point 1--
91
+ // if changePasswordComplete() doesn't get called, then it should remain
92
+ console.log('New password works!');
93
+ return user;
94
+ }
95
+ catch (error) {
96
+ // Just bubble up any other type of error.
97
+ if (error.code !== 'NotAuthorizedException') {
98
+ throw error;
99
+ }
100
+ // pass, try again assuming it's the old password
101
+ }
102
+ // Now assume it's the previous password. Any exception is allowed to bubble up.
103
+ try {
104
+ const user = yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.currentPassIdpParams, RecoveryStatus.OLD_PASSWORD);
105
+ // Old password worked.
106
+ console.log('Old password works!');
107
+ return user;
108
+ }
109
+ catch (error) {
110
+ // Just bubble up any other type of error.
111
+ throw error.code === 'NotAuthorizedException'
112
+ ? new LrBadRequestException('The password change request was interrupted, please try to login with both your new and old password')
113
+ : error;
114
+ }
115
+ }
116
+ // Try against as the TP password reset account
117
+ if (passIdpApiResult.tpPasswordReset) {
118
+ try {
119
+ // TP password reset is in process. We need to try the password against both
120
+ // original account and the new reset account.
121
+ const reset = passIdpApiResult.tpPasswordReset;
122
+ const ret = yield this.loginIdpImpl(reset.resetUsername, password, reset.passIdpParams, RecoveryStatus.NONE);
123
+ ret.isTpPasswordResetUser = true;
124
+ return ret;
125
+ }
126
+ catch (err) {
127
+ // continue, try again as regular user.
128
+ }
129
+ }
130
+ // Login as regular user
131
+ return yield this.loginIdpImpl(emailOrPhone, password, passIdpApiResult.currentPassIdpParams, RecoveryStatus.NONE);
132
+ });
133
+ }
134
+ handleSessionEncryptionKey() {
135
+ return __awaiter(this, void 0, void 0, function* () {
136
+ if (this.config.disableSessionEncryptionKey) {
137
+ if (!isDevMode()) {
138
+ const msg = 'You should not set disableSessionEncryptionKey=True in mode prod. It defaults to false.';
139
+ console.error(msg);
140
+ throw new Error(msg);
141
+ }
142
+ else {
143
+ console.warn('You have set disableSessionEncryptionKey=True. Make sure not to do this in prod mode.');
144
+ }
145
+ }
146
+ else {
147
+ // Set the session key to a new encryption key for this session
148
+ const sessionEncryptionKey = yield this.keyFactory.createKey();
149
+ yield this.lrGraphQL.lrMutate(new LrMutation({
150
+ mutation: SetSessionEncryptionKeyMutation,
151
+ variables: {
152
+ input: {
153
+ sessionEncryptionKey: JSON.stringify(sessionEncryptionKey.toJSON(true)),
154
+ },
155
+ },
156
+ }), {
157
+ includeKeyGraph: false,
158
+ });
159
+ this.persistService.setServerSessionEncryptionKey(sessionEncryptionKey);
160
+ }
161
+ });
162
+ }
163
+ handlePostAuth(cognitoUser) {
164
+ return __awaiter(this, void 0, void 0, function* () {
165
+ yield this.handlePasswordRecovery(cognitoUser);
166
+ yield this.handleSessionEncryptionKey();
167
+ });
168
+ }
169
+ login(emailOrPhone, password, { tpPasswordResetAutoComplete = true } = {}) {
170
+ var _a;
171
+ return __awaiter(this, void 0, void 0, function* () {
172
+ let loginResult = yield this.loginImpl(emailOrPhone, password);
173
+ if (tpPasswordResetAutoComplete &&
174
+ ((_a = loginResult.resetUser) === null || _a === void 0 ? void 0 : _a.state) === TpClaimState.APPROVED) {
175
+ yield this.completeRequest(password);
176
+ loginResult = yield this.loginImpl(emailOrPhone, password);
177
+ }
178
+ return loginResult;
179
+ });
180
+ }
181
+ loginImpl(emailOrPhone, password) {
182
+ return __awaiter(this, void 0, void 0, function* () {
183
+ yield this.logout();
184
+ const cognitoUser = yield this.loginIdp(emailOrPhone, password);
185
+ // todo: Meet MFA challenges.
186
+ if (['SMS_MFA', 'SOFTWARE_TOKEN_MFA'].includes(cognitoUser.challengeName)) {
187
+ return { hasChallenge: true, challenge: cognitoUser };
188
+ }
189
+ yield this.handlePostAuth(cognitoUser);
190
+ if (cognitoUser.isTpPasswordResetUser) {
191
+ // Assuming there is no MFA on the TP reset user.
192
+ const resetUser = yield this.loadResetUser(password);
193
+ return { hasChallenge: false, resetUser };
194
+ }
195
+ else {
196
+ const user = yield this.loadUser(cognitoUser, password);
197
+ yield this.idleService.start(); // Run idleService whenever user is logged in.
198
+ return { hasChallenge: false, user };
199
+ }
200
+ });
201
+ }
202
+ // TODO <AZ> We need to handle the isTpPasswordResetUser=True case here after MFA as well.
203
+ verifyLogin(challenge, password, rememberMe, code) {
204
+ return __awaiter(this, void 0, void 0, function* () {
205
+ yield this.auth.confirmSignIn(challenge, code, challenge.challengeName);
206
+ // TODO: this.auth.confirmSignIn() could return another challenge.
207
+ const cognitoUser = yield this.auth.currentAuthenticatedUser();
208
+ yield this.handlePostAuth(challenge);
209
+ const user = yield this.loadUser(cognitoUser, password);
210
+ if (rememberMe) {
211
+ cognitoUser.setDeviceStatusRemembered({
212
+ onSuccess: () => { },
213
+ onFailure: (e) => console.error(e),
214
+ });
215
+ }
216
+ return user;
217
+ });
218
+ }
219
+ handlePasswordRecovery(user) {
220
+ return __awaiter(this, void 0, void 0, function* () {
221
+ if (user.recoveryStatus !== RecoveryStatus.NONE) {
222
+ const jwtToken = user
223
+ .getSignInUserSession()
224
+ .getAccessToken()
225
+ .getJwtToken();
226
+ yield this.passwordService.changePasswordComplete(jwtToken, user.recoveryStatus === RecoveryStatus.NEW_PASSWORD);
227
+ }
228
+ });
229
+ }
230
+ getUserOrResetUser(reload = false) {
231
+ return __awaiter(this, void 0, void 0, function* () {
232
+ const cognitoUser = yield this.auth.currentAuthenticatedUser();
233
+ if (cognitoUser.getUsername().endsWith(TP_PASSWORD_RESET_USERNAME_SUFFIX)) {
234
+ return this.getResetUser(reload);
235
+ }
236
+ else {
237
+ return this.getUser(reload);
238
+ }
239
+ });
240
+ }
241
+ getResetUser(reload = false) {
242
+ return __awaiter(this, void 0, void 0, function* () {
243
+ if (!reload && this.currentResetUser) {
244
+ return this.currentResetUser;
245
+ }
246
+ this.currentResetUser = yield this.loadResetUser();
247
+ yield this.idleService.start(); // Run idleService whenever user is logged in.
248
+ return this.currentResetUser;
249
+ });
250
+ }
251
+ getUser(reload = false) {
252
+ return __awaiter(this, void 0, void 0, function* () {
253
+ if (!reload && this.currentUser) {
254
+ return this.currentUser;
255
+ }
256
+ this.currentUser = yield this.loadUser(yield this.auth.currentAuthenticatedUser());
257
+ console.log('Starting idle service.');
258
+ yield this.idleService.start(); // Run idleService whenever user is logged in.
259
+ return this.currentUser;
260
+ });
261
+ }
262
+ mapTPVaultAccess(features) {
263
+ const tpVaultFeature = features === null || features === void 0 ? void 0 : features.tpVault;
264
+ return ((tpVaultFeature === null || tpVaultFeature === void 0 ? void 0 : tpVaultFeature.length) > 0 &&
265
+ tpVaultFeature.some((feature) => feature.toUpperCase() === 'ACCESS'));
266
+ }
267
+ loadUser(cognitoUser, password) {
268
+ return __awaiter(this, void 0, void 0, function* () {
269
+ const { currentUser, contactCard, userPlans, } = yield this.profileService.getCurrentUser();
270
+ if (currentUser.sessionEncryptionKey) {
271
+ this.persistService.setServerSessionEncryptionKey(yield JWK.asKey(currentUser.sessionEncryptionKey));
272
+ }
273
+ const userAttributes = yield this.auth.userAttributes(cognitoUser);
274
+ if (password) {
275
+ const passKey = (yield this.keyFactory.derivePassKey(Object.assign({ password }, currentUser.currentUserKey.passKey.passKeyParams))).jwk;
276
+ yield this.idleService.persistMasterKey(yield this.keyGraphService.unwrapWithPassKey(currentUser.currentUserKey.passKey.id, passKey, currentUser.currentUserKey.masterKey.id));
277
+ }
278
+ yield this.keyGraphService.populateKeys(currentUser.currentUserKey);
279
+ return {
280
+ id: currentUser.id,
281
+ sub: this.getUserAttribute('sub', userAttributes),
282
+ username: currentUser.username,
283
+ currentUserKey: currentUser.currentUserKey,
284
+ getAccessJwtToken: () => cognitoUser.getSignInUserSession().getAccessToken().getJwtToken(),
285
+ email: this.getUserAttribute('email', userAttributes),
286
+ emailVerified: this.getUserAttribute('email_verified', userAttributes) === 'true',
287
+ phone: this.getUserAttribute('phone_number', userAttributes),
288
+ phoneVerified: this.getUserAttribute('phone_number_verified', userAttributes) ===
289
+ 'true',
290
+ contactCard: Object.assign({}, (yield this.profileService.decryptContactCard(contactCard))),
291
+ userDelete: currentUser.userDelete,
292
+ userPlans,
293
+ hasTPVaultAccess: this.mapTPVaultAccess(currentUser.features),
294
+ features: currentUser.features,
295
+ sessionEncryptionKey: currentUser.sessionEncryptionKey,
296
+ };
297
+ });
298
+ }
299
+ watchAuth() {
300
+ return this.hubSubject;
301
+ }
302
+ logout() {
303
+ return __awaiter(this, void 0, void 0, function* () {
304
+ this.currentUser = null;
305
+ this.keyService.purgeKeys();
306
+ this.keyGraphService.purgeKeys();
307
+ yield Promise.all([this.auth.signOut(), this.profileService.signOut()]);
308
+ });
309
+ }
310
+ getUserAttribute(attributeName, userAttributes) {
311
+ const userAttribute = userAttributes.find((x) => x.getName() === attributeName);
312
+ return userAttribute ? userAttribute.getValue() : null;
313
+ }
314
+ loadResetUser(password) {
315
+ return __awaiter(this, void 0, void 0, function* () {
316
+ const { tpPasswordResetUser: resetUser } = yield this.lrGraphQL.query({
317
+ query: TpPasswordResetUserQuery,
318
+ });
319
+ if (resetUser.sessionEncryptionKey) {
320
+ this.persistService.setServerSessionEncryptionKey(yield JWK.asKey(resetUser.sessionEncryptionKey));
321
+ }
322
+ // Update the keys
323
+ if (password) {
324
+ const passKey = (yield this.keyFactory.derivePassKey(Object.assign({ password }, resetUser.passKey.passKeyParams))).jwk;
325
+ yield this.idleService.persistMasterKey(yield this.keyGraphService.unwrapWithPassKey(resetUser.passKey.id, passKey, resetUser.masterKey.id));
326
+ }
327
+ this.keyService.populateKeys({
328
+ passKey: {
329
+ id: resetUser.passKey.id,
330
+ },
331
+ masterKey: {
332
+ id: resetUser.masterKey.id,
333
+ },
334
+ });
335
+ const userAttributes = yield this.auth.userAttributes(yield this.auth.currentAuthenticatedUser());
336
+ const sub = this.getUserAttribute('sub', userAttributes);
337
+ return Object.assign(Object.assign({}, (yield this.tpPasswordResetProcessorService.processTpPasswordResetUserNode(resetUser))), { sub });
338
+ });
339
+ }
340
+ refreshAccessToken() {
341
+ return __awaiter(this, void 0, void 0, function* () {
342
+ const cognitoUser = yield this.auth.currentAuthenticatedUser();
343
+ const refreshToken = cognitoUser.getSignInUserSession().getRefreshToken();
344
+ return new Promise((resolve, reject) => {
345
+ cognitoUser.refreshSession(refreshToken, (err, data) => {
346
+ if (err) {
347
+ console.error('Error refreshing token: ', err);
348
+ reject(err);
349
+ }
350
+ else {
351
+ console.log('Token refresh complete: ', data);
352
+ resolve(0);
353
+ }
354
+ });
355
+ });
356
+ });
357
+ }
358
+ completeRequest(newPassword) {
359
+ return __awaiter(this, void 0, void 0, function* () {
360
+ const resetUser = yield this.getResetUser(true);
361
+ if (resetUser.state !== TpClaimState.APPROVED) {
362
+ throw new LrBadStateException('Password reset request has not been approved.');
363
+ }
364
+ // --------------------------------------------------------------
365
+ // Prepare all materials to ensure there are no errors.
366
+ // --------------------------------------------------------------
367
+ const assemblyKey = yield this.recoverAssemblyKey(resetUser);
368
+ const { rootKey } = yield this.encryptionService.decrypt(assemblyKey, resetUser.assemblyCipherData);
369
+ console.log(rootKey);
370
+ // Making sure it's a valid key.
371
+ const rootKeyJwk = yield JWK.asKey(rootKey);
372
+ const masterKey = yield this.keyGraphService.getKey(resetUser.masterKey.id);
373
+ const masterKeyWrappedRootKey = yield this.encryptionService.encryptToString(masterKey.jwk, rootKeyJwk.toJSON(true));
374
+ // The new password
375
+ const newPassIdpResult = yield this.keyFactory.derivePassIdp(Object.assign({ password: newPassword }, resetUser.passKey.passIdpParams));
376
+ const newIdpPassword = this.passwordService.getPassIdpString(newPassIdpResult.jwk);
377
+ // --------------------------------------------------------------
378
+ // Get assembly key challenge
379
+ // --------------------------------------------------------------
380
+ const challenge = (yield this.lrGraphQL.lrMutate(new LrMutation({
381
+ mutation: CreateTpAssemblyKeyChallengeMutation,
382
+ variables: {
383
+ input: {},
384
+ },
385
+ }), {
386
+ includeKeyGraph: false,
387
+ })).createTpAssemblyKeyChallenge.challenge;
388
+ console.log(challenge);
389
+ // Sign the challenge
390
+ // Generate a client side nonce that's no in the server's control.
391
+ challenge.clientNonce = this.keyFactory.randomString(TP_PASSWORD_RESET_CLIENT_NONCE_LENGTH);
392
+ console.log(challenge);
393
+ const assemblyKeyVerifierPrk = yield this.encryptionService.decrypt(assemblyKey, resetUser.wrappedAssemblyKeyVerifierPrk);
394
+ const signedChallenge = yield this.encryptionService.sign(assemblyKeyVerifierPrk, challenge);
395
+ // --------------------------------------------------------------
396
+ // Change password for the original user
397
+ // --------------------------------------------------------------
398
+ const tempIdpPassword = (yield this.lrGraphQL.lrMutate(new LrMutation({
399
+ mutation: PreCompleteTpPasswordResetRequestMutation,
400
+ variables: {
401
+ input: {
402
+ signedChallenge: JSON.stringify(signedChallenge),
403
+ },
404
+ },
405
+ }), {
406
+ includeKeyGraph: false,
407
+ })).preCompleteTpPasswordResetRequest.idpPassword;
408
+ // --------------------------------------------------------------
409
+ // Login as the original user using new temporary password
410
+ // --------------------------------------------------------------
411
+ // At this point, the original account's password has been changed
412
+ // to a temporary password. It is no longer possible for the user
413
+ // to use the original password to login. Any successful login
414
+ // can only be using the temporary password. So it's safe to assume
415
+ // that we want to "complete" the password reset.
416
+ // The maybe 2FA so we listen for the auth event from Amplify.
417
+ const retPromise = new Promise((resolve) => {
418
+ const listener = (data) => __awaiter(this, void 0, void 0, function* () {
419
+ if (data.payload.event !== 'signIn') {
420
+ return;
421
+ }
422
+ Hub.remove('auth', listener);
423
+ console.log(data.payload);
424
+ yield this.auth.signIn(resetUser.username, newIdpPassword);
425
+ // Switch over to the new set of keys
426
+ yield this.lrGraphQL.lrMutate(new LrMutation({
427
+ mutation: CompleteTpPasswordResetRequestMutation,
428
+ variables: {
429
+ input: {
430
+ masterKeyWrappedRootKey,
431
+ masterKeyId: masterKey.id,
432
+ },
433
+ },
434
+ }));
435
+ resolve();
436
+ });
437
+ Hub.listen('auth', listener);
438
+ });
439
+ // Signin as the original user. Password has been reset to temporary one. It should return
440
+ // with NEW_PASSWORD_REQUIRED
441
+ let user = yield this.auth.signIn(resetUser.username, tempIdpPassword, {
442
+ noProxy: 'true',
443
+ });
444
+ if (user.challengeName !== 'NEW_PASSWORD_REQUIRED') {
445
+ throw new LrException({
446
+ message: 'Internal error. Expecting Cognito to have done a password reset after call to PreCompleteTpPasswordResetRequestMutation.',
447
+ });
448
+ }
449
+ // Set new password on Idp
450
+ // the awsFetch() function passes NEW_PASSWORD_REQUIRED directly to AWS without
451
+ // going through the proxy.
452
+ user = yield this.auth.completeNewPassword(user, newIdpPassword, {});
453
+ return retPromise;
454
+ });
455
+ }
456
+ recoverAssemblyKey(resetUser) {
457
+ return __awaiter(this, void 0, void 0, function* () {
458
+ const prk = yield this.keyGraphService.getKey(resetUser.pxk.id);
459
+ const partials = yield Promise.all(resetUser.approvals
460
+ .filter((approval) => !!approval.receiverCipherPartialAssemblyKey)
461
+ .map((approval) => this.encryptionService.decrypt(prk, approval.receiverCipherPartialAssemblyKey)));
462
+ return this.assemblyController.recoverAssemblyKey(partials);
463
+ });
464
+ }
465
+ }
466
+ LifeReadyAuthService.ɵprov = i0.ɵɵdefineInjectable({ factory: function LifeReadyAuthService_Factory() { return new LifeReadyAuthService(i0.ɵɵinject(i1.LR_CONFIG), i0.ɵɵinject(i2.AuthClass), i0.ɵɵinject(i3.KeyFactoryService), i0.ɵɵinject(i4.KeyService), i0.ɵɵinject(i5.ProfileService), i0.ɵɵinject(i6.KeyGraphService), i0.ɵɵinject(i7.PasswordService), i0.ɵɵinject(i8.IdleService), i0.ɵɵinject(i9.LrGraphQLService), i0.ɵɵinject(i10.TpPasswordResetProcessorService), i0.ɵɵinject(i11.PersistService), i0.ɵɵinject(i12.EncryptionService), i0.ɵɵinject(i13.Slip39Service), i0.ɵɵinject(i14.TpPasswordResetAssemblyController)); }, token: LifeReadyAuthService, providedIn: "root" });
467
+ LifeReadyAuthService.decorators = [
468
+ { type: Injectable, args: [{
469
+ providedIn: 'root',
470
+ },] }
471
+ ];
472
+ LifeReadyAuthService.ctorParameters = () => [
473
+ { type: undefined, decorators: [{ type: Inject, args: [LR_CONFIG,] }] },
474
+ { type: AuthClass },
475
+ { type: KeyFactoryService },
476
+ { type: KeyService },
477
+ { type: ProfileService },
478
+ { type: KeyGraphService },
479
+ { type: PasswordService },
480
+ { type: IdleService },
481
+ { type: LrGraphQLService },
482
+ { type: TpPasswordResetProcessorService },
483
+ { type: PersistService },
484
+ { type: EncryptionService },
485
+ { type: Slip39Service },
486
+ { type: TpPasswordResetAssemblyController }
487
+ ];
488
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGlmZS1yZWFkeS1hdXRoLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiL29wdC9hdGxhc3NpYW4vcGlwZWxpbmVzL2FnZW50L2J1aWxkL3Byb2plY3RzL2NvcmUvc3JjLyIsInNvdXJjZXMiOlsibGliL2F1dGgvbGlmZS1yZWFkeS1hdXRoLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUU5RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFeEMsT0FBTyxFQUFjLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUVqRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDcEUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM5RCxPQUFPLEVBQ0wsMkJBQTJCLEVBQzNCLHFCQUFxQixFQUNyQixtQkFBbUIsRUFDbkIsV0FBVyxHQUNaLE1BQU0sdUJBQXVCLENBQUM7QUFDL0IsT0FBTyxFQUtMLGNBQWMsR0FDZixNQUFNLGNBQWMsQ0FBQztBQUN0QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDckQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQzNELE9BQU8sRUFDTCxzQ0FBc0MsRUFDdEMsb0NBQW9DLEVBQ3BDLHlDQUF5QyxFQUN6Qyx3QkFBd0IsR0FDekIsTUFBTSwwQ0FBMEMsQ0FBQztBQUNsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDeEUs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UUFBUSxDQUFDLGdDQUFnQyxDQUMxQyxDQUNGLENBQ0osQ0FBQztZQUVGLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzlELENBQUM7S0FBQTs7OztZQTVuQkYsVUFBVSxTQUFDO2dCQUNWLFVBQVUsRUFBRSxNQUFNO2FBQ25COzs7NENBT0ksTUFBTSxTQUFDLFNBQVM7WUF6Q1osU0FBUztZQVFULGlCQUFpQjtZQXpCakIsVUFBVTtZQUNWLGNBQWM7WUFGZCxlQUFlO1lBaUJmLGVBQWU7WUFRZixXQUFXO1lBRVgsZ0JBQWdCO1lBRWhCLCtCQUErQjtZQUUvQixjQUFjO1lBR2QsaUJBQWlCO1lBQ2pCLGFBQWE7WUFLYixpQ0FBaUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3QsIEluamVjdGFibGUsIGlzRGV2TW9kZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29nbml0b1VzZXIgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aCc7XG5pbXBvcnQgeyBIdWIgfSBmcm9tICdAYXdzLWFtcGxpZnkvY29yZSc7XG5pbXBvcnQgeyBDb2duaXRvVXNlckF0dHJpYnV0ZSB9IGZyb20gJ2FtYXpvbi1jb2duaXRvLWlkZW50aXR5LWpzJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFJlcGxheVN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IFBhc3NJZHBQYXJhbXMgfSBmcm9tICcuLi9jcnlwdG9ncmFwaHkvY3J5cHRvZ3JhcGh5LnR5cGVzJztcbmltcG9ydCB7IEtleUdyYXBoU2VydmljZSB9IGZyb20gJy4uL2NyeXB0b2dyYXBoeS9rZXktZ3JhcGguc2VydmljZSc7XG5pbXBvcnQgeyBLZXlTZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2tleS5zZXJ2aWNlJztcbmltcG9ydCB7IFByb2ZpbGVTZXJ2aWNlIH0gZnJvbSAnLi4vdXNlcnMvcHJvZmlsZS5zZXJ2aWNlJztcbmltcG9ydCB7IFBhc3N3b3JkQ2hhbmdlU3RhdHVzIH0gZnJvbSAnLi4vdXNlcnMvcHJvZmlsZS50eXBlcyc7XG5pbXBvcnQge1xuICBMckNvbmN1cnJlbnRBY2Nlc3NFeGNlcHRpb24sXG4gIExyQmFkUmVxdWVzdEV4Y2VwdGlvbixcbiAgTHJCYWRTdGF0ZUV4Y2VwdGlvbixcbiAgTHJFeGNlcHRpb24sXG59IGZyb20gJy4uL19jb21tb24vZXhjZXB0aW9ucyc7XG5pbXBvcnQge1xuICBDb2duaXRvQ2hhbGxlbmdlVXNlcixcbiAgQ3VycmVudFVzZXIsXG4gIFRwUGFzc3dvcmRSZXNldFVzZXIsXG4gIExvZ2luUmVzdWx0LFxuICBSZWNvdmVyeVN0YXR1cyxcbn0gZnJvbSAnLi9hdXRoLnR5cGVzJztcbmltcG9ydCB7IFBhc3N3b3JkU2VydmljZSB9IGZyb20gJy4vcGFzc3dvcmQuc2VydmljZSc7XG5pbXBvcnQgeyBBdXRoQ2xhc3MgfSBmcm9tICdAYXdzLWFtcGxpZnkvYXV0aC9saWItZXNtL0F1dGgnO1xuaW1wb3J0IHtcbiAgQ29tcGxldGVUcFBhc3N3b3JkUmVzZXRSZXF1ZXN0TXV0YXRpb24sXG4gIENyZWF0ZVRwQXNzZW1ibHlLZXlDaGFsbGVuZ2VNdXRhdGlvbixcbiAgUHJlQ29tcGxldGVUcFBhc3N3b3JkUmVzZXRSZXF1ZXN0TXV0YXRpb24sXG4gIFRwUGFzc3dvcmRSZXNldFVzZXJRdWVyeSxcbn0gZnJvbSAnLi4vdHJ1c3RlZC1wYXJ0aWVzL3RwLXBhc3N3b3JkLXJlc2V0LmdxbCc7XG5pbXBvcnQgeyBJZGxlU2VydmljZSB9IGZyb20gJy4vaWRsZS5zZXJ2aWNlJztcbmltcG9ydCB7IEtleUZhY3RvcnlTZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2tleS1mYWN0b3J5LnNlcnZpY2UnO1xuaW1wb3J0IHsgTHJHcmFwaFFMU2VydmljZSwgTHJNdXRhdGlvbiB9IGZyb20gJy4uL2FwaS9sci1ncmFwaHFsJztcbmltcG9ydCB7IFRwQ2xhaW1TdGF0ZSwgVHBQYXNzd29yZFJlc2V0VXNlck5vZGUgfSBmcm9tICcuLi9hcGkvdHlwZXMnO1xuaW1wb3J0IHsgVHBQYXNzd29yZFJlc2V0UHJvY2Vzc29yU2VydmljZSB9IGZyb20gJy4uL2FwaS9xdWVyeS1wcm9jZXNzb3IvdHAtcGFzc3dvcmQtcmVzZXQtcHJvY2Vzc29yLnNlcnZpY2UnO1xuaW1wb3J0IHsgU2V0U2Vzc2lvbkVuY3J5cHRpb25LZXlNdXRhdGlvbiB9IGZyb20gJy4vYXV0aC5ncWwnO1xuaW1wb3J0IHsgUGVyc2lzdFNlcnZpY2UgfSBmcm9tICcuLi9hcGkvcGVyc2lzdC5zZXJ2aWNlJztcbmltcG9ydCB7IEpXSyB9IGZyb20gJ25vZGUtam9zZSc7XG5pbXBvcnQgeyBMaWZlUmVhZHlDb25maWcsIExSX0NPTkZJRyB9IGZyb20gJy4uL2xpZmUtcmVhZHkuY29uZmlnJztcbmltcG9ydCB7IEVuY3J5cHRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L2VuY3J5cHRpb24uc2VydmljZSc7XG5pbXBvcnQgeyBTbGlwMzlTZXJ2aWNlIH0gZnJvbSAnLi4vY3J5cHRvZ3JhcGh5L3NsaXAzOS5zZXJ2aWNlJztcbmltcG9ydCB7XG4gIFRQX1BBU1NXT1JEX1JFU0VUX0NMSUVOVF9OT05DRV9MRU5HVEgsXG4gIFRQX1BBU1NXT1JEX1JFU0VUX1VTRVJOQU1FX1NVRkZJWCxcbn0gZnJvbSAnLi4vdHJ1c3RlZC1wYXJ0aWVzL3RwLXBhc3N3b3JkLXJlc2V0LmNvbnN0YW50cyc7XG5pbXBvcnQgeyBUcFBhc3N3b3JkUmVzZXRBc3NlbWJseUNvbnRyb2xsZXIgfSBmcm9tICcuLi90cnVzdGVkLXBhcnRpZXMvdHAtcGFzc3dvcmQtcmVzZXQuY29udHJvbGxlcic7XG5cbmV4cG9ydCBjb25zdCBpbml0aWFsaXNlQXV0aCA9IChhdXRoU2VydmljZTogTGlmZVJlYWR5QXV0aFNlcnZpY2UpID0+IHtcbiAgcmV0dXJuICgpID0+IGF1dGhTZXJ2aWNlLmluaXRpYWxpc2UoKTtcbn07XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9naW5PcHRpb25zIHtcbiAgdHBQYXNzd29yZFJlc2V0QXV0b0NvbXBsZXRlPzogYm9vbGVhbjtcbn1cblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIExpZmVSZWFkeUF1dGhTZXJ2aWNlIHtcbiAgcHJpdmF0ZSBodWJTdWJqZWN0OiBSZXBsYXlTdWJqZWN0PGFueT4gPSBuZXcgUmVwbGF5U3ViamVjdDxhbnk+KDEpO1xuICBwcml2YXRlIGN1cnJlbnRVc2VyOiBDdXJyZW50VXNlcjtcbiAgcHJpdmF0ZSBjdXJyZW50UmVzZXRVc2VyOiBUcFBhc3N3b3JkUmVzZXRVc2VyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoTFJfQ09ORklHKSBwcml2YXRlIGNvbmZpZzogTGlmZVJlYWR5Q29uZmlnLFxuICAgIHByaXZhdGUgYXV0aDogQXV0aENsYXNzLFxuICAgIHByaXZhdGUga2V5RmFjdG9yeTogS2V5RmFjdG9yeVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBrZXlTZXJ2aWNlOiBLZXlTZXJ2aWNlLFxuICAgIHByaXZhdGUgcHJvZmlsZVNlcnZpY2U6IFByb2ZpbGVTZXJ2aWNlLFxuICAgIHByaXZhdGUga2V5R3JhcGhTZXJ2aWNlOiBLZXlHcmFwaFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBwYXNzd29yZFNlcnZpY2U6IFBhc3N3b3JkU2VydmljZSxcbiAgICBwcml2YXRlIGlkbGVTZXJ2aWNlOiBJZGxlU2VydmljZSxcbiAgICBwcml2YXRlIGxyR3JhcGhRTDogTHJHcmFwaFFMU2VydmljZSxcbiAgICBwcml2YXRlIHRwUGFzc3dvcmRSZXNldFByb2Nlc3NvclNlcnZpY2U6IFRwUGFzc3dvcmRSZXNldFByb2Nlc3NvclNlcnZpY2UsXG4gICAgcHJpdmF0ZSBwZXJzaXN0U2VydmljZTogUGVyc2lzdFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBlbmNyeXB0aW9uU2VydmljZTogRW5jcnlwdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBzbGlwMzlTZXJ2aWNlOiBTbGlwMzlTZXJ2aWNlLFxuICAgIHByaXZhdGUgYXNzZW1ibHlDb250cm9sbGVyOiBUcFBhc3N3b3JkUmVzZXRBc3NlbWJseUNvbnRyb2xsZXJcbiAgKSB7fVxuXG4gIHB1YmxpYyBhc3luYyBpbml0aWFsaXNlKCkge1xuICAgIEh1Yi5saXN0ZW4oJ2F1dGgnLCAoZGF0YSkgPT4gdGhpcy5odWJTdWJqZWN0Lm5leHQoZGF0YS5wYXlsb2FkKSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGxvZ2luSWRwSW1wbChcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZyxcbiAgICBwYXNzd29yZDogc3RyaW5nLFxuICAgIHBhc3NJZHBQYXJhbXM6IFBhc3NJZHBQYXJhbXMsXG4gICAgcmVjb3ZlcnlTdGF0dXM6IFJlY292ZXJ5U3RhdHVzXG4gICk6IFByb21pc2U8Q29nbml0b0NoYWxsZW5nZVVzZXI+IHtcbiAgICBjb25zdCBwYXNzSWRwUmVzdWx0ID0gYXdhaXQgdGhpcy5rZXlGYWN0b3J5LmRlcml2ZVBhc3NJZHAoe1xuICAgICAgcGFzc3dvcmQsXG4gICAgICAuLi5wYXNzSWRwUGFyYW1zLFxuICAgIH0pO1xuICAgIC8vIFVzZSB0aGUgZGVyaXZlZCBwYXNzd29yZCB0byBzaWduaW4gd2l0aCBjb2duaXRvXG4gICAgY29uc3QgdXNlciA9IGF3YWl0IHRoaXMuYXV0aC5zaWduSW4oXG4gICAgICBlbWFpbE9yUGhvbmUsXG4gICAgICB0aGlzLnBhc3N3b3JkU2VydmljZS5nZXRQYXNzSWRwU3RyaW5nKHBhc3NJZHBSZXN1bHQuandrKVxuICAgICk7XG5cbiAgICB1c2VyLnJlY292ZXJ5U3RhdHVzID0gcmVjb3ZlcnlTdGF0dXM7XG5cbiAgICByZXR1cm4gdXNlcjtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9naW5JZHAoXG4gICAgZW1haWxPclBob25lOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xuICApOiBQcm9taXNlPENvZ25pdG9DaGFsbGVuZ2VVc2VyPiB7XG4gICAgLy8gRG93bmxvYWQgdGhlIHNhbHQgbmVlZGVkIHRvIGRlcml2ZSB0aGUgUGFzc0lkcFxuICAgIGNvbnN0IHBhc3NJZHBBcGlSZXN1bHQgPSBhd2FpdCB0aGlzLnByb2ZpbGVTZXJ2aWNlLmdldFBhc3NJZHBQYXJhbXMoXG4gICAgICBlbWFpbE9yUGhvbmVcbiAgICApO1xuXG4gICAgaWYgKFxuICAgICAgcGFzc0lkcEFwaVJlc3VsdC5wYXNzd29yZENoYW5nZVN0YXR1cyA9PT0gUGFzc3dvcmRDaGFuZ2VTdGF0dXMuSW5Qcm9ncmVzc1xuICAgICkge1xuICAgICAgdGhyb3cgbmV3IExyQ29uY3VycmVudEFjY2Vzc0V4Y2VwdGlvbignQSBwYXNzd29yZCBjaGFuZ2UgaXMgaW4gcHJvZ3Jlc3MnKTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBwYXNzSWRwQXBpUmVzdWx0LnBhc3N3b3JkQ2hhbmdlU3RhdHVzID09PSBQYXNzd29yZENoYW5nZVN0YXR1cy5SZWNvdmVyeVxuICAgICkge1xuICAgICAgY29uc29sZS5sb2coJ0luIHJlY292ZXJ5IG1vZGUuJyk7XG4gICAgICAvLyBMZXQncyBzYXkgd2UgZG9uJ3Qga25vdyBpZiB0aGUgcGFzc3dvcmQgaXMgdGhlIG5ldyBvbmUgb3IgdGhlIG9sZCBvbmUuIFdlIGp1c3QgaGF2ZSB0byB0cnkgYm90aC5cbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHVzZXIgPSBhd2FpdCB0aGlzLmxvZ2luSWRwSW1wbChcbiAgICAgICAgICBlbWFpbE9yUGhvbmUsXG4gICAgICAgICAgcGFzc3dvcmQsXG4gICAgICAgICAgcGFzc0lkcEFwaVJlc3VsdC5uZXdQYXNzSWRwUGFyYW1zLFxuICAgICAgICAgIFJlY292ZXJ5U3RhdHVzLk5FV19QQVNTV09SRFxuICAgICAgICApO1xuICAgICAgICAvLyBOZXcgcGFzc3dvcmQgd29ya2VkLiBMZXQncyBzZXQgdG8gdGhlIGN1cnJlbnQgcGFzc3dvcmRcblxuICAgICAgICAvLyAtLVBvdGVudGlhbCBGYWlsdXJlIFBvaW50IDEtLVxuICAgICAgICAvLyBpZiBjaGFuZ2VQYXNzd29yZENvbXBsZXRlKCkgZG9lc24ndCBnZXQgY2FsbGVkLCB0aGVuIGl0IHNob3VsZCByZW1haW5cblxuICAgICAgICBjb25zb2xlLmxvZygnTmV3IHBhc3N3b3JkIHdvcmtzIScpO1xuXG4gICAgICAgIHJldHVybiB1c2VyO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgLy8gSnVzdCBidWJibGUgdXAgYW55IG90aGVyIHR5cGUgb2YgZXJyb3IuXG4gICAgICAgIGlmIChlcnJvci5jb2RlICE9PSAnTm90QXV0aG9yaXplZEV4Y2VwdGlvbicpIHtcbiAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfVxuICAgICAgICAvLyBwYXNzLCB0cnkgYWdhaW4gYXNzdW1pbmcgaXQncyB0aGUgb2xkIHBhc3N3b3JkXG4gICAgICB9XG5cbiAgICAgIC8vIE5vdyBhc3N1bWUgaXQncyB0aGUgcHJldmlvdXMgcGFzc3dvcmQuIEFueSBleGNlcHRpb24gaXMgYWxsb3dlZCB0byBidWJibGUgdXAuXG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5sb2dpbklkcEltcGwoXG4gICAgICAgICAgZW1haWxPclBob25lLFxuICAgICAgICAgIHBhc3N3b3JkLFxuICAgICAgICAgIHBhc3NJZHBBcGlSZXN1bHQuY3VycmVudFBhc3NJZHBQYXJhbXMsXG4gICAgICAgICAgUmVjb3ZlcnlTdGF0dXMuT0xEX1BBU1NXT1JEXG4gICAgICAgICk7XG4gICAgICAgIC8vIE9sZCBwYXNzd29yZCB3b3JrZWQuXG4gICAgICAgIGNvbnNvbGUubG9nKCdPbGQgcGFzc3dvcmQgd29ya3MhJyk7XG5cbiAgICAgICAgcmV0dXJuIHVzZXI7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAvLyBKdXN0IGJ1YmJsZSB1cCBhbnkgb3RoZXIgdHlwZSBvZiBlcnJvci5cbiAgICAgICAgdGhyb3cgZXJyb3IuY29kZSA9PT0gJ05vdEF1dGhvcml6ZWRFeGNlcHRpb24nXG4gICAgICAgICAgPyBuZXcgTHJCYWRSZXF1ZXN0RXhjZXB0aW9uKFxuICAgICAgICAgICAgICAnVGhlIHBhc3N3b3JkIGNoYW5nZSByZXF1ZXN0IHdhcyBpbnRlcnJ1cHRlZCwgcGxlYXNlIHRyeSB0byBsb2dpbiB3aXRoIGJvdGggeW91ciBuZXcgYW5kIG9sZCBwYXNzd29yZCdcbiAgICAgICAgICAgIClcbiAgICAgICAgICA6IGVycm9yO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFRyeSBhZ2FpbnN0IGFzIHRoZSBUUCBwYXNzd29yZCByZXNldCBhY2NvdW50XG4gICAgaWYgKHBhc3NJZHBBcGlSZXN1bHQudHBQYXNzd29yZFJlc2V0KSB7XG4gICAgICB0cnkge1xuICAgICAgICAvLyBUUCBwYXNzd29yZCByZXNldCBpcyBpbiBwcm9jZXNzLiBXZSBuZWVkIHRvIHRyeSB0aGUgcGFzc3dvcmQgYWdhaW5zdCBib3RoXG4gICAgICAgIC8vIG9yaWdpbmFsIGFjY291bnQgYW5kIHRoZSBuZXcgcmVzZXQgYWNjb3VudC5cbiAgICAgICAgY29uc3QgcmVzZXQgPSBwYXNzSWRwQXBpUmVzdWx0LnRwUGFzc3dvcmRSZXNldDtcbiAgICAgICAgY29uc3QgcmV0ID0gYXdhaXQgdGhpcy5sb2dpbklkcEltcGwoXG4gICAgICAgICAgcmVzZXQucmVzZXRVc2VybmFtZSxcbiAgICAgICAgICBwYXNzd29yZCxcbiAgICAgICAgICByZXNldC5wYXNzSWRwUGFyYW1zLFxuICAgICAgICAgIFJlY292ZXJ5U3RhdHVzLk5PTkVcbiAgICAgICAgKTtcbiAgICAgICAgcmV0LmlzVHBQYXNzd29yZFJlc2V0VXNlciA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBjb250aW51ZSwgdHJ5IGFnYWluIGFzIHJlZ3VsYXIgdXNlci5cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBMb2dpbiBhcyByZWd1bGFyIHVzZXJcbiAgICByZXR1cm4gYXdhaXQgdGhpcy5sb2dpbklkcEltcGwoXG4gICAgICBlbWFpbE9yUGhvbmUsXG4gICAgICBwYXNzd29yZCxcbiAgICAgIHBhc3NJZHBBcGlSZXN1bHQuY3VycmVudFBhc3NJZHBQYXJhbXMsXG4gICAgICBSZWNvdmVyeVN0YXR1cy5OT05FXG4gICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBoYW5kbGVTZXNzaW9uRW5jcnlwdGlvbktleSgpIHtcbiAgICBpZiAodGhpcy5jb25maWcuZGlzYWJsZVNlc3Npb25FbmNyeXB0aW9uS2V5KSB7XG4gICAgICBpZiAoIWlzRGV2TW9kZSgpKSB7XG4gICAgICAgIGNvbnN0IG1zZyA9XG4gICAgICAgICAgJ1lvdSBzaG91bGQgbm90IHNldCBkaXNhYmxlU2Vzc2lvbkVuY3J5cHRpb25LZXk9VHJ1ZSBpbiBtb2RlIHByb2QuIEl0IGRlZmF1bHRzIHRvIGZhbHNlLic7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IobXNnKTtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ1lvdSBoYXZlIHNldCBkaXNhYmxlU2Vzc2lvbkVuY3J5cHRpb25LZXk9VHJ1ZS4gTWFrZSBzdXJlIG5vdCB0byBkbyB0aGlzIGluIHByb2QgbW9kZS4nXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFNldCB0aGUgc2Vzc2lvbiBrZXkgdG8gYSBuZXcgZW5jcnlwdGlvbiBrZXkgZm9yIHRoaXMgc2Vzc2lvblxuICAgICAgY29uc3Qgc2Vzc2lvbkVuY3J5cHRpb25LZXkgPSBhd2FpdCB0aGlzLmtleUZhY3RvcnkuY3JlYXRlS2V5KCk7XG4gICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xuICAgICAgICAgIG11dGF0aW9uOiBTZXRTZXNzaW9uRW5jcnlwdGlvbktleU11dGF0aW9uLFxuICAgICAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICAgICAgc2Vzc2lvbkVuY3J5cHRpb25LZXk6IEpTT04uc3RyaW5naWZ5KFxuICAgICAgICAgICAgICAgIHNlc3Npb25FbmNyeXB0aW9uS2V5LnRvSlNPTih0cnVlKVxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIGluY2x1ZGVLZXlHcmFwaDogZmFsc2UsXG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIHRoaXMucGVyc2lzdFNlcnZpY2Uuc2V0U2VydmVyU2Vzc2lvbkVuY3J5cHRpb25LZXkoc2Vzc2lvbkVuY3J5cHRpb25LZXkpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBoYW5kbGVQb3N0QXV0aChjb2duaXRvVXNlcjogQ29nbml0b0NoYWxsZW5nZVVzZXIpIHtcbiAgICBhd2FpdCB0aGlzLmhhbmRsZVBhc3N3b3JkUmVjb3ZlcnkoY29nbml0b1VzZXIpO1xuICAgIGF3YWl0IHRoaXMuaGFuZGxlU2Vzc2lvbkVuY3J5cHRpb25LZXkoKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBsb2dpbihcbiAgICBlbWFpbE9yUGhvbmU6IHN0cmluZyxcbiAgICBwYXNzd29yZDogc3RyaW5nLFxuICAgIHsgdHBQYXNzd29yZFJlc2V0QXV0b0NvbXBsZXRlID0gdHJ1ZSB9OiBMb2dpbk9wdGlvbnMgPSB7fVxuICApIHtcbiAgICBsZXQgbG9naW5SZXN1bHQgPSBhd2FpdCB0aGlzLmxvZ2luSW1wbChlbWFpbE9yUGhvbmUsIHBhc3N3b3JkKTtcblxuICAgIGlmIChcbiAgICAgIHRwUGFzc3dvcmRSZXNldEF1dG9Db21wbGV0ZSAmJlxuICAgICAgbG9naW5SZXN1bHQucmVzZXRVc2VyPy5zdGF0ZSA9PT0gVHBDbGFpbVN0YXRlLkFQUFJPVkVEXG4gICAgKSB7XG4gICAgICBhd2FpdCB0aGlzLmNvbXBsZXRlUmVxdWVzdChwYXNzd29yZCk7XG4gICAgICBsb2dpblJlc3VsdCA9IGF3YWl0IHRoaXMubG9naW5JbXBsKGVtYWlsT3JQaG9uZSwgcGFzc3dvcmQpO1xuICAgIH1cblxuICAgIHJldHVybiBsb2dpblJlc3VsdDtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBsb2dpbkltcGwoXG4gICAgZW1haWxPclBob25lOiBzdHJpbmcsXG4gICAgcGFzc3dvcmQ6IHN0cmluZ1xuICApOiBQcm9taXNlPExvZ2luUmVzdWx0PiB7XG4gICAgYXdhaXQgdGhpcy5sb2dvdXQoKTtcbiAgICBjb25zdCBjb2duaXRvVXNlciA9IGF3YWl0IHRoaXMubG9naW5JZHAoZW1haWxPclBob25lLCBwYXNzd29yZCk7XG5cbiAgICAvLyB0b2RvOiBNZWV0IE1GQSBjaGFsbGVuZ2VzLlxuICAgIGlmIChbJ1NNU19NRkEnLCAnU09GVFdBUkVfVE9LRU5fTUZBJ10uaW5jbHVkZXMoY29nbml0b1VzZXIuY2hhbGxlbmdlTmFtZSkpIHtcbiAgICAgIHJldHVybiB7IGhhc0NoYWxsZW5nZTogdHJ1ZSwgY2hhbGxlbmdlOiBjb2duaXRvVXNlciB9O1xuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuaGFuZGxlUG9zdEF1dGgoY29nbml0b1VzZXIpO1xuXG4gICAgaWYgKGNvZ25pdG9Vc2VyLmlzVHBQYXNzd29yZFJlc2V0VXNlcikge1xuICAgICAgLy8gQXNzdW1pbmcgdGhlcmUgaXMgbm8gTUZBIG9uIHRoZSBUUCByZXNldCB1c2VyLlxuICAgICAgY29uc3QgcmVzZXRVc2VyID0gYXdhaXQgdGhpcy5sb2FkUmVzZXRVc2VyKHBhc3N3b3JkKTtcbiAgICAgIHJldHVybiB7IGhhc0NoYWxsZW5nZTogZmFsc2UsIHJlc2V0VXNlciB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5sb2FkVXNlcihjb2duaXRvVXNlciwgcGFzc3dvcmQpO1xuICAgICAgYXdhaXQgdGhpcy5pZGxlU2VydmljZS5zdGFydCgpOyAvLyBSdW4gaWRsZVNlcnZpY2Ugd2hlbmV2ZXIgdXNlciBpcyBsb2dnZWQgaW4uXG4gICAgICByZXR1cm4geyBoYXNDaGFsbGVuZ2U6IGZhbHNlLCB1c2VyIH07XG4gICAgfVxuICB9XG5cbiAgLy8gVE9ETyA8QVo+IFdlIG5lZWQgdG8gaGFuZGxlIHRoZSBpc1RwUGFzc3dvcmRSZXNldFVzZXI9VHJ1ZSBjYXNlIGhlcmUgYWZ0ZXIgTUZBIGFzIHdlbGwuXG4gIHB1YmxpYyBhc3luYyB2ZXJpZnlMb2dpbihcbiAgICBjaGFsbGVuZ2U6IENvZ25pdG9DaGFsbGVuZ2VVc2VyLFxuICAgIHBhc3N3b3JkOiBzdHJpbmcsXG4gICAgcmVtZW1iZXJNZTogYm9vbGVhbixcbiAgICBjb2RlOiBzdHJpbmdcbiAgKTogUHJvbWlzZTxDdXJyZW50VXNlcj4ge1xuICAgIGF3YWl0IHRoaXMuYXV0aC5jb25maXJtU2lnbkluKGNoYWxsZW5nZSwgY29kZSwgY2hhbGxlbmdlLmNoYWxsZW5nZU5hbWUpO1xuXG4gICAgLy8gVE9ETzogdGhpcy5hdXRoLmNvbmZpcm1TaWduSW4oKSBjb3VsZCByZXR1cm4gYW5vdGhlciBjaGFsbGVuZ2UuXG5cbiAgICBjb25zdCBjb2duaXRvVXNlcjogQ29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XG5cbiAgICBhd2FpdCB0aGlzLmhhbmRsZVBvc3RBdXRoKGNoYWxsZW5nZSk7XG5cbiAgICBjb25zdCB1c2VyID0gYXdhaXQgdGhpcy5sb2FkVXNlcihjb2duaXRvVXNlciwgcGFzc3dvcmQpO1xuXG4gICAgaWYgKHJlbWVtYmVyTWUpIHtcbiAgICAgIGNvZ25pdG9Vc2VyLnNldERldmljZVN0YXR1c1JlbWVtYmVyZWQoe1xuICAgICAgICBvblN1Y2Nlc3M6ICgpID0+IHt9LFxuICAgICAgICBvbkZhaWx1cmU6IChlKSA9PiBjb25zb2xlLmVycm9yKGUpLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHVzZXI7XG4gIH1cblxuICBhc3luYyBoYW5kbGVQYXNzd29yZFJlY292ZXJ5KHVzZXI6IENvZ25pdG9DaGFsbGVuZ2VVc2VyKSB7XG4gICAgaWYgKHVzZXIucmVjb3ZlcnlTdGF0dXMgIT09IFJlY292ZXJ5U3RhdHVzLk5PTkUpIHtcbiAgICAgIGNvbnN0IGp3dFRva2VuID0gdXNlclxuICAgICAgICAuZ2V0U2lnbkluVXNlclNlc3Npb24oKVxuICAgICAgICAuZ2V0QWNjZXNzVG9rZW4oKVxuICAgICAgICAuZ2V0Snd0VG9rZW4oKTtcbiAgICAgIGF3YWl0IHRoaXMucGFzc3dvcmRTZXJ2aWNlLmNoYW5nZVBhc3N3b3JkQ29tcGxldGUoXG4gICAgICAgIGp3dFRva2VuLFxuICAgICAgICB1c2VyLnJlY292ZXJ5U3RhdHVzID09PSBSZWNvdmVyeVN0YXR1cy5ORVdfUEFTU1dPUkRcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgZ2V0VXNlck9yUmVzZXRVc2VyKFxuICAgIHJlbG9hZDogYm9vbGVhbiA9IGZhbHNlXG4gICk6IFByb21pc2U8Q3VycmVudFVzZXIgfCBUcFBhc3N3b3JkUmVzZXRVc2VyPiB7XG4gICAgY29uc3QgY29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XG5cbiAgICBpZiAoY29nbml0b1VzZXIuZ2V0VXNlcm5hbWUoKS5lbmRzV2l0aChUUF9QQVNTV09SRF9SRVNFVF9VU0VSTkFNRV9TVUZGSVgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRSZXNldFVzZXIocmVsb2FkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuZ2V0VXNlcihyZWxvYWQpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldFJlc2V0VXNlcihyZWxvYWQ6IGJvb2xlYW4gPSBmYWxzZSk6IFByb21pc2U8VHBQYXNzd29yZFJlc2V0VXNlcj4ge1xuICAgIGlmICghcmVsb2FkICYmIHRoaXMuY3VycmVudFJlc2V0VXNlcikge1xuICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFJlc2V0VXNlcjtcbiAgICB9XG5cbiAgICB0aGlzLmN1cnJlbnRSZXNldFVzZXIgPSBhd2FpdCB0aGlzLmxvYWRSZXNldFVzZXIoKTtcblxuICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2Uuc3RhcnQoKTsgLy8gUnVuIGlkbGVTZXJ2aWNlIHdoZW5ldmVyIHVzZXIgaXMgbG9nZ2VkIGluLlxuXG4gICAgcmV0dXJuIHRoaXMuY3VycmVudFJlc2V0VXNlcjtcbiAgfVxuXG4gIGFzeW5jIGdldFVzZXIocmVsb2FkOiBib29sZWFuID0gZmFsc2UpOiBQcm9taXNlPEN1cnJlbnRVc2VyPiB7XG4gICAgaWYgKCFyZWxvYWQgJiYgdGhpcy5jdXJyZW50VXNlcikge1xuICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFVzZXI7XG4gICAgfVxuICAgIHRoaXMuY3VycmVudFVzZXIgPSBhd2FpdCB0aGlzLmxvYWRVc2VyKFxuICAgICAgYXdhaXQgdGhpcy5hdXRoLmN1cnJlbnRBdXRoZW50aWNhdGVkVXNlcigpXG4gICAgKTtcbiAgICBjb25zb2xlLmxvZygnU3RhcnRpbmcgaWRsZSBzZXJ2aWNlLicpO1xuICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2Uuc3RhcnQoKTsgLy8gUnVuIGlkbGVTZXJ2aWNlIHdoZW5ldmVyIHVzZXIgaXMgbG9nZ2VkIGluLlxuICAgIHJldHVybiB0aGlzLmN1cnJlbnRVc2VyO1xuICB9XG5cbiAgcHJpdmF0ZSBtYXBUUFZhdWx0QWNjZXNzKGZlYXR1cmVzPzogYW55KTogYm9vbGVhbiB7XG4gICAgY29uc3QgdHBWYXVsdEZlYXR1cmUgPSBmZWF0dXJlcz8udHBWYXVsdDtcbiAgICByZXR1cm4gKFxuICAgICAgdHBWYXVsdEZlYXR1cmU/Lmxlbmd0aCA+IDAgJiZcbiAgICAgIHRwVmF1bHRGZWF0dXJlLnNvbWUoKGZlYXR1cmUpID0+IGZlYXR1cmUudG9VcHBlckNhc2UoKSA9PT0gJ0FDQ0VTUycpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZFVzZXIoXG4gICAgY29nbml0b1VzZXI6IENvZ25pdG9Vc2VyLFxuICAgIHBhc3N3b3JkPzogc3RyaW5nXG4gICk6IFByb21pc2U8Q3VycmVudFVzZXI+IHtcbiAgICBjb25zdCB7XG4gICAgICBjdXJyZW50VXNlcixcbiAgICAgIGNvbnRhY3RDYXJkLFxuICAgICAgdXNlclBsYW5zLFxuICAgIH0gPSBhd2FpdCB0aGlzLnByb2ZpbGVTZXJ2aWNlLmdldEN1cnJlbnRVc2VyKCk7XG5cbiAgICBpZiAoY3VycmVudFVzZXIuc2Vzc2lvbkVuY3J5cHRpb25LZXkpIHtcbiAgICAgIHRoaXMucGVyc2lzdFNlcnZpY2Uuc2V0U2VydmVyU2Vzc2lvbkVuY3J5cHRpb25LZXkoXG4gICAgICAgIGF3YWl0IEpXSy5hc0tleShjdXJyZW50VXNlci5zZXNzaW9uRW5jcnlwdGlvbktleSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlckF0dHJpYnV0ZXMgPSBhd2FpdCB0aGlzLmF1dGgudXNlckF0dHJpYnV0ZXMoY29nbml0b1VzZXIpO1xuXG4gICAgaWYgKHBhc3N3b3JkKSB7XG4gICAgICBjb25zdCBwYXNzS2V5ID0gKFxuICAgICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0tleSh7XG4gICAgICAgICAgcGFzc3dvcmQsXG4gICAgICAgICAgLi4uY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkucGFzc0tleS5wYXNzS2V5UGFyYW1zLFxuICAgICAgICB9KVxuICAgICAgKS5qd2s7XG5cbiAgICAgIGF3YWl0IHRoaXMuaWRsZVNlcnZpY2UucGVyc2lzdE1hc3RlcktleShcbiAgICAgICAgYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UudW53cmFwV2l0aFBhc3NLZXkoXG4gICAgICAgICAgY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkucGFzc0tleS5pZCxcbiAgICAgICAgICBwYXNzS2V5LFxuICAgICAgICAgIGN1cnJlbnRVc2VyLmN1cnJlbnRVc2VyS2V5Lm1hc3RlcktleS5pZFxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLmtleUdyYXBoU2VydmljZS5wb3B1bGF0ZUtleXMoY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXkpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiBjdXJyZW50VXNlci5pZCxcbiAgICAgIHN1YjogdGhpcy5nZXRVc2VyQXR0cmlidXRlKCdzdWInLCB1c2VyQXR0cmlidXRlcyksXG4gICAgICB1c2VybmFtZTogY3VycmVudFVzZXIudXNlcm5hbWUsXG4gICAgICBjdXJyZW50VXNlcktleTogY3VycmVudFVzZXIuY3VycmVudFVzZXJLZXksXG4gICAgICBnZXRBY2Nlc3NKd3RUb2tlbjogKCkgPT5cbiAgICAgICAgY29nbml0b1VzZXIuZ2V0U2lnbkluVXNlclNlc3Npb24oKS5nZXRBY2Nlc3NUb2tlbigpLmdldEp3dFRva2VuKCksXG4gICAgICBlbWFpbDogdGhpcy5nZXRVc2VyQXR0cmlidXRlKCdlbWFpbCcsIHVzZXJBdHRyaWJ1dGVzKSxcbiAgICAgIGVtYWlsVmVyaWZpZWQ6XG4gICAgICAgIHRoaXMuZ2V0VXNlckF0dHJpYnV0ZSgnZW1haWxfdmVyaWZpZWQnLCB1c2VyQXR0cmlidXRlcykgPT09ICd0cnVlJyxcbiAgICAgIHBob25lOiB0aGlzLmdldFVzZXJBdHRyaWJ1dGUoJ3Bob25lX251bWJlcicsIHVzZXJBdHRyaWJ1dGVzKSxcbiAgICAgIHBob25lVmVyaWZpZWQ6XG4gICAgICAgIHRoaXMuZ2V0VXNlckF0dHJpYnV0ZSgncGhvbmVfbnVtYmVyX3ZlcmlmaWVkJywgdXNlckF0dHJpYnV0ZXMpID09PVxuICAgICAgICAndHJ1ZScsXG4gICAgICBjb250YWN0Q2FyZDoge1xuICAgICAgICAuLi4oYXdhaXQgdGhpcy5wcm9maWxlU2VydmljZS5kZWNyeXB0Q29udGFjdENhcmQoY29udGFjdENhcmQpKSxcbiAgICAgIH0sXG4gICAgICB1c2VyRGVsZXRlOiBjdXJyZW50VXNlci51c2VyRGVsZXRlLFxuICAgICAgdXNlclBsYW5zLFxuICAgICAgaGFzVFBWYXVsdEFjY2VzczogdGhpcy5tYXBUUFZhdWx0QWNjZXNzKGN1cnJlbnRVc2VyLmZlYXR1cmVzKSxcbiAgICAgIGZlYXR1cmVzOiBjdXJyZW50VXNlci5mZWF0dXJlcyxcbiAgICAgIHNlc3Npb25FbmNyeXB0aW9uS2V5OiBjdXJyZW50VXNlci5zZXNzaW9uRW5jcnlwdGlvbktleSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHdhdGNoQXV0aCgpOiBPYnNlcnZhYmxlPGFueT4ge1xuICAgIHJldHVybiB0aGlzLmh1YlN1YmplY3Q7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgbG9nb3V0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuY3VycmVudFVzZXIgPSBudWxsO1xuICAgIHRoaXMua2V5U2VydmljZS5wdXJnZUtleXMoKTtcbiAgICB0aGlzLmtleUdyYXBoU2VydmljZS5wdXJnZUtleXMoKTtcblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFt0aGlzLmF1dGguc2lnbk91dCgpLCB0aGlzLnByb2ZpbGVTZXJ2aWNlLnNpZ25PdXQoKV0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRVc2VyQXR0cmlidXRlKFxuICAgIGF0dHJpYnV0ZU5hbWU6IHN0cmluZyxcbiAgICB1c2VyQXR0cmlidXRlczogQ29nbml0b1VzZXJBdHRyaWJ1dGVbXVxuICApIHtcbiAgICBjb25zdCB1c2VyQXR0cmlidXRlID0gdXNlckF0dHJpYnV0ZXMuZmluZChcbiAgICAgICh4KSA9PiB4LmdldE5hbWUoKSA9PT0gYXR0cmlidXRlTmFtZVxuICAgICk7XG5cbiAgICByZXR1cm4gdXNlckF0dHJpYnV0ZSA/IHVzZXJBdHRyaWJ1dGUuZ2V0VmFsdWUoKSA6IG51bGw7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgbG9hZFJlc2V0VXNlcihwYXNzd29yZD86IHN0cmluZyk6IFByb21pc2U8VHBQYXNzd29yZFJlc2V0VXNlcj4ge1xuICAgIGNvbnN0IHsgdHBQYXNzd29yZFJlc2V0VXNlcjogcmVzZXRVc2VyIH0gPSBhd2FpdCB0aGlzLmxyR3JhcGhRTC5xdWVyeSh7XG4gICAgICBxdWVyeTogVHBQYXNzd29yZFJlc2V0VXNlclF1ZXJ5LFxuICAgIH0pO1xuXG4gICAgaWYgKHJlc2V0VXNlci5zZXNzaW9uRW5jcnlwdGlvbktleSkge1xuICAgICAgdGhpcy5wZXJzaXN0U2VydmljZS5zZXRTZXJ2ZXJTZXNzaW9uRW5jcnlwdGlvbktleShcbiAgICAgICAgYXdhaXQgSldLLmFzS2V5KHJlc2V0VXNlci5zZXNzaW9uRW5jcnlwdGlvbktleSlcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gVXBkYXRlIHRoZSBrZXlzXG4gICAgaWYgKHBhc3N3b3JkKSB7XG4gICAgICBjb25zdCBwYXNzS2V5ID0gKFxuICAgICAgICBhd2FpdCB0aGlzLmtleUZhY3RvcnkuZGVyaXZlUGFzc0tleSh7XG4gICAgICAgICAgcGFzc3dvcmQsXG4gICAgICAgICAgLi4ucmVzZXRVc2VyLnBhc3NLZXkucGFzc0tleVBhcmFtcyxcbiAgICAgICAgfSlcbiAgICAgICkuandrO1xuXG4gICAgICBhd2FpdCB0aGlzLmlkbGVTZXJ2aWNlLnBlcnNpc3RNYXN0ZXJLZXkoXG4gICAgICAgIGF3YWl0IHRoaXMua2V5R3JhcGhTZXJ2aWNlLnVud3JhcFdpdGhQYXNzS2V5KFxuICAgICAgICAgIHJlc2V0VXNlci5wYXNzS2V5LmlkLFxuICAgICAgICAgIHBhc3NLZXksXG4gICAgICAgICAgcmVzZXRVc2VyLm1hc3RlcktleS5pZFxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMua2V5U2VydmljZS5wb3B1bGF0ZUtleXMoe1xuICAgICAgcGFzc0tleToge1xuICAgICAgICBpZDogcmVzZXRVc2VyLnBhc3NLZXkuaWQsXG4gICAgICB9LFxuICAgICAgbWFzdGVyS2V5OiB7XG4gICAgICAgIGlkOiByZXNldFVzZXIubWFzdGVyS2V5LmlkLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHVzZXJBdHRyaWJ1dGVzID0gYXdhaXQgdGhpcy5hdXRoLnVzZXJBdHRyaWJ1dGVzKFxuICAgICAgYXdhaXQgdGhpcy5hdXRoLmN1cnJlbnRBdXRoZW50aWNhdGVkVXNlcigpXG4gICAgKTtcbiAgICBjb25zdCBzdWIgPSB0aGlzLmdldFVzZXJBdHRyaWJ1dGUoJ3N1YicsIHVzZXJBdHRyaWJ1dGVzKTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi4oYXdhaXQgdGhpcy50cFBhc3N3b3JkUmVzZXRQcm9jZXNzb3JTZXJ2aWNlLnByb2Nlc3NUcFBhc3N3b3JkUmVzZXRVc2VyTm9kZShcbiAgICAgICAgcmVzZXRVc2VyXG4gICAgICApKSxcbiAgICAgIHN1YixcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHJlZnJlc2hBY2Nlc3NUb2tlbigpIHtcbiAgICBjb25zdCBjb2duaXRvVXNlcjogQ29nbml0b1VzZXIgPSBhd2FpdCB0aGlzLmF1dGguY3VycmVudEF1dGhlbnRpY2F0ZWRVc2VyKCk7XG4gICAgY29uc3QgcmVmcmVzaFRva2VuID0gY29nbml0b1VzZXIuZ2V0U2lnbkluVXNlclNlc3Npb24oKS5nZXRSZWZyZXNoVG9rZW4oKTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBjb2duaXRvVXNlci5yZWZyZXNoU2Vzc2lvbihyZWZyZXNoVG9rZW4sIChlcnIsIGRhdGEpID0+IHtcbiAgICAgICAgaWYgKGVycikge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHJlZnJlc2hpbmcgdG9rZW46ICcsIGVycik7XG4gICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc29sZS5sb2coJ1Rva2VuIHJlZnJlc2ggY29tcGxldGU6ICcsIGRhdGEpO1xuICAgICAgICAgIHJlc29sdmUoMCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgYXN5bmMgY29tcGxldGVSZXF1ZXN0KG5ld1Bhc3N3b3JkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXNldFVzZXIgPSBhd2FpdCB0aGlzLmdldFJlc2V0VXNlcih0cnVlKTtcblxuICAgIGlmIChyZXNldFVzZXIuc3RhdGUgIT09IFRwQ2xhaW1TdGF0ZS5BUFBST1ZFRCkge1xuICAgICAgdGhyb3cgbmV3IExyQmFkU3RhdGVFeGNlcHRpb24oXG4gICAgICAgICdQYXNzd29yZCByZXNldCByZXF1ZXN0IGhhcyBub3QgYmVlbiBhcHByb3ZlZC4nXG4gICAgICApO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gUHJlcGFyZSBhbGwgbWF0ZXJpYWxzIHRvIGVuc3VyZSB0aGVyZSBhcmUgbm8gZXJyb3JzLlxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgYXNzZW1ibHlLZXkgPSBhd2FpdCB0aGlzLnJlY292ZXJBc3NlbWJseUtleShyZXNldFVzZXIpO1xuXG4gICAgY29uc3QgeyByb290S2V5IH0gPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQoXG4gICAgICBhc3NlbWJseUtleSxcbiAgICAgIHJlc2V0VXNlci5hc3NlbWJseUNpcGhlckRhdGFcbiAgICApO1xuICAgIGNvbnNvbGUubG9nKHJvb3RLZXkpO1xuXG4gICAgLy8gTWFraW5nIHN1cmUgaXQncyBhIHZhbGlkIGtleS5cbiAgICBjb25zdCByb290S2V5SndrID0gYXdhaXQgSldLLmFzS2V5KHJvb3RLZXkpO1xuXG4gICAgY29uc3QgbWFzdGVyS2V5ID0gYXdhaXQgdGhpcy5rZXlHcmFwaFNlcnZpY2UuZ2V0S2V5KHJlc2V0VXNlci5tYXN0ZXJLZXkuaWQpO1xuXG4gICAgY29uc3QgbWFzdGVyS2V5V3JhcHBlZFJvb3RLZXkgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmVuY3J5cHRUb1N0cmluZyhcbiAgICAgIG1hc3RlcktleS5qd2ssXG4gICAgICByb290S2V5SndrLnRvSlNPTih0cnVlKVxuICAgICk7XG5cbiAgICAvLyBUaGUgbmV3IHBhc3N3b3JkXG4gICAgY29uc3QgbmV3UGFzc0lkcFJlc3VsdCA9IGF3YWl0IHRoaXMua2V5RmFjdG9yeS5kZXJpdmVQYXNzSWRwKHtcbiAgICAgIHBhc3N3b3JkOiBuZXdQYXNzd29yZCxcbiAgICAgIC4uLnJlc2V0VXNlci5wYXNzS2V5LnBhc3NJZHBQYXJhbXMsXG4gICAgfSk7XG5cbiAgICBjb25zdCBuZXdJZHBQYXNzd29yZCA9IHRoaXMucGFzc3dvcmRTZXJ2aWNlLmdldFBhc3NJZHBTdHJpbmcoXG4gICAgICBuZXdQYXNzSWRwUmVzdWx0Lmp3a1xuICAgICk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEdldCBhc3NlbWJseSBrZXkgY2hhbGxlbmdlXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCBjaGFsbGVuZ2UgPSAoXG4gICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcbiAgICAgICAgbmV3IExyTXV0YXRpb24oe1xuICAgICAgICAgIG11dGF0aW9uOiBDcmVhdGVUcEFzc2VtYmx5S2V5Q2hhbGxlbmdlTXV0YXRpb24sXG4gICAgICAgICAgdmFyaWFibGVzOiB7XG4gICAgICAgICAgICBpbnB1dDoge30sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgICAgIHtcbiAgICAgICAgICBpbmNsdWRlS2V5R3JhcGg6IGZhbHNlLFxuICAgICAgICB9XG4gICAgICApXG4gICAgKS5jcmVhdGVUcEFzc2VtYmx5S2V5Q2hhbGxlbmdlLmNoYWxsZW5nZTtcblxuICAgIGNvbnNvbGUubG9nKGNoYWxsZW5nZSk7XG5cbiAgICAvLyBTaWduIHRoZSBjaGFsbGVuZ2VcbiAgICAvLyBHZW5lcmF0ZSBhIGNsaWVudCBzaWRlIG5vbmNlIHRoYXQncyBubyBpbiB0aGUgc2VydmVyJ3MgY29udHJvbC5cbiAgICBjaGFsbGVuZ2UuY2xpZW50Tm9uY2UgPSB0aGlzLmtleUZhY3RvcnkucmFuZG9tU3RyaW5nKFxuICAgICAgVFBfUEFTU1dPUkRfUkVTRVRfQ0xJRU5UX05PTkNFX0xFTkdUSFxuICAgICk7XG4gICAgY29uc29sZS5sb2coY2hhbGxlbmdlKTtcblxuICAgIGNvbnN0IGFzc2VtYmx5S2V5VmVyaWZpZXJQcmsgPSBhd2FpdCB0aGlzLmVuY3J5cHRpb25TZXJ2aWNlLmRlY3J5cHQoXG4gICAgICBhc3NlbWJseUtleSxcbiAgICAgIHJlc2V0VXNlci53cmFwcGVkQXNzZW1ibHlLZXlWZXJpZmllclBya1xuICAgICk7XG4gICAgY29uc3Qgc2lnbmVkQ2hhbGxlbmdlID0gYXdhaXQgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5zaWduKFxuICAgICAgYXNzZW1ibHlLZXlWZXJpZmllclByayxcbiAgICAgIGNoYWxsZW5nZVxuICAgICk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIENoYW5nZSBwYXNzd29yZCBmb3IgdGhlIG9yaWdpbmFsIHVzZXJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGNvbnN0IHRlbXBJZHBQYXNzd29yZCA9IChcbiAgICAgIGF3YWl0IHRoaXMubHJHcmFwaFFMLmxyTXV0YXRlKFxuICAgICAgICBuZXcgTHJNdXRhdGlvbih7XG4gICAgICAgICAgbXV0YXRpb246IFByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLFxuICAgICAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICAgICAgc2lnbmVkQ2hhbGxlbmdlOiBKU09OLnN0cmluZ2lmeShzaWduZWRDaGFsbGVuZ2UpLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgICAge1xuICAgICAgICAgIGluY2x1ZGVLZXlHcmFwaDogZmFsc2UsXG4gICAgICAgIH1cbiAgICAgIClcbiAgICApLnByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdC5pZHBQYXNzd29yZDtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gTG9naW4gYXMgdGhlIG9yaWdpbmFsIHVzZXIgdXNpbmcgbmV3IHRlbXBvcmFyeSBwYXNzd29yZFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gQXQgdGhpcyBwb2ludCwgdGhlIG9yaWdpbmFsIGFjY291bnQncyBwYXNzd29yZCBoYXMgYmVlbiBjaGFuZ2VkXG4gICAgLy8gdG8gYSB0ZW1wb3JhcnkgcGFzc3dvcmQuIEl0IGlzIG5vIGxvbmdlciBwb3NzaWJsZSBmb3IgdGhlIHVzZXJcbiAgICAvLyB0byB1c2UgdGhlIG9yaWdpbmFsIHBhc3N3b3JkIHRvIGxvZ2luLiBBbnkgc3VjY2Vzc2Z1bCBsb2dpblxuICAgIC8vIGNhbiBvbmx5IGJlIHVzaW5nIHRoZSB0ZW1wb3JhcnkgcGFzc3dvcmQuIFNvIGl0J3Mgc2FmZSB0byBhc3N1bWVcbiAgICAvLyB0aGF0IHdlIHdhbnQgdG8gXCJjb21wbGV0ZVwiIHRoZSBwYXNzd29yZCByZXNldC5cblxuICAgIC8vIFRoZSBtYXliZSAyRkEgc28gd2UgbGlzdGVuIGZvciB0aGUgYXV0aCBldmVudCBmcm9tIEFtcGxpZnkuXG4gICAgY29uc3QgcmV0UHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICBjb25zdCBsaXN0ZW5lciA9IGFzeW5jIChkYXRhKSA9PiB7XG4gICAgICAgIGlmIChkYXRhLnBheWxvYWQuZXZlbnQgIT09ICdzaWduSW4nKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgSHViLnJlbW92ZSgnYXV0aCcsIGxpc3RlbmVyKTtcblxuICAgICAgICBjb25zb2xlLmxvZyhkYXRhLnBheWxvYWQpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuYXV0aC5zaWduSW4ocmVzZXRVc2VyLnVzZXJuYW1lLCBuZXdJZHBQYXNzd29yZCk7XG5cbiAgICAgICAgLy8gU3dpdGNoIG92ZXIgdG8gdGhlIG5ldyBzZXQgb2Yga2V5c1xuICAgICAgICBhd2FpdCB0aGlzLmxyR3JhcGhRTC5sck11dGF0ZShcbiAgICAgICAgICBuZXcgTHJNdXRhdGlvbih7XG4gICAgICAgICAgICBtdXRhdGlvbjogQ29tcGxldGVUcFBhc3N3b3JkUmVzZXRSZXF1ZXN0TXV0YXRpb24sXG4gICAgICAgICAgICB2YXJpYWJsZXM6IHtcbiAgICAgICAgICAgICAgaW5wdXQ6IHtcbiAgICAgICAgICAgICAgICBtYXN0ZXJLZXlXcmFwcGVkUm9vdEtleSxcbiAgICAgICAgICAgICAgICBtYXN0ZXJLZXlJZDogbWFzdGVyS2V5LmlkLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIHJlc29sdmUoKTtcbiAgICAgIH07XG5cbiAgICAgIEh1Yi5saXN0ZW4oJ2F1dGgnLCBsaXN0ZW5lcik7XG4gICAgfSk7XG5cbiAgICAvLyBTaWduaW4gYXMgdGhlIG9yaWdpbmFsIHVzZXIuIFBhc3N3b3JkIGhhcyBiZWVuIHJlc2V0IHRvIHRlbXBvcmFyeSBvbmUuIEl0IHNob3VsZCByZXR1cm5cbiAgICAvLyB3aXRoIE5FV19QQVNTV09SRF9SRVFVSVJFRFxuICAgIGxldCB1c2VyID0gYXdhaXQgdGhpcy5hdXRoLnNpZ25JbihyZXNldFVzZXIudXNlcm5hbWUsIHRlbXBJZHBQYXNzd29yZCwge1xuICAgICAgbm9Qcm94eTogJ3RydWUnLFxuICAgIH0pO1xuXG4gICAgaWYgKHVzZXIuY2hhbGxlbmdlTmFtZSAhPT0gJ05FV19QQVNTV09SRF9SRVFVSVJFRCcpIHtcbiAgICAgIHRocm93IG5ldyBMckV4Y2VwdGlvbih7XG4gICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgJ0ludGVybmFsIGVycm9yLiBFeHBlY3RpbmcgQ29nbml0byB0byBoYXZlIGRvbmUgYSBwYXNzd29yZCByZXNldCBhZnRlciBjYWxsIHRvIFByZUNvbXBsZXRlVHBQYXNzd29yZFJlc2V0UmVxdWVzdE11dGF0aW9uLicsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBTZXQgbmV3IHBhc3N3b3JkIG9uIElkcFxuICAgIC8vIHRoZSBhd3NGZXRjaCgpIGZ1bmN0aW9uIHBhc3NlcyBORVdfUEFTU1dPUkRfUkVRVUlSRUQgZGlyZWN0bHkgdG8gQVdTIHdpdGhvdXRcbiAgICAvLyBnb2luZyB0aHJvdWdoIHRoZSBwcm94eS5cbiAgICB1c2VyID0gYXdhaXQgdGhpcy5hdXRoLmNvbXBsZXRlTmV3UGFzc3dvcmQodXNlciwgbmV3SWRwUGFzc3dvcmQsIHt9KTtcblxuICAgIHJldHVybiByZXRQcm9taXNlO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyByZWNvdmVyQXNzZW1ibHlLZXkoXG4gICAgcmVzZXRVc2VyOiBUcFBhc3N3b3JkUmVzZXRVc2VyTm9kZVxuICApOiBQcm9taXNlPEpXSy5LZXk+IHtcbiAgICBjb25zdCBwcmsgPSBhd2FpdCB0aGlzLmtleUdyYXBoU2VydmljZS5nZXRLZXkocmVzZXRVc2VyLnB4ay5pZCk7XG5cbiAgICBjb25zdCBwYXJ0aWFscyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgcmVzZXRVc2VyLmFwcHJvdmFsc1xuICAgICAgICAuZmlsdGVyKChhcHByb3ZhbCkgPT4gISFhcHByb3ZhbC5yZWNlaXZlckNpcGhlclBhcnRpYWxBc3NlbWJseUtleSlcbiAgICAgICAgLm1hcCgoYXBwcm92YWwpID0+XG4gICAgICAgICAgdGhpcy5lbmNyeXB0aW9uU2VydmljZS5kZWNyeXB0KFxuICAgICAgICAgICAgcHJrLFxuICAgICAgICAgICAgYXBwcm92YWwucmVjZWl2ZXJDaXBoZXJQYXJ0aWFsQXNzZW1ibHlLZXlcbiAgICAgICAgICApXG4gICAgICAgIClcbiAgICApO1xuXG4gICAgcmV0dXJuIHRoaXMuYXNzZW1ibHlDb250cm9sbGVyLnJlY292ZXJBc3NlbWJseUtleShwYXJ0aWFscyk7XG4gIH1cbn1cbiJdfQ==