studiokit-scaffolding-js 7.0.12-next.1.3 → 7.0.12-next.2.1

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 (258) hide show
  1. package/lib/components/ActionList.js +164 -37
  2. package/lib/components/AlertDialog.js +128 -12
  3. package/lib/components/AlertWithIcon.js +88 -29
  4. package/lib/components/ConnectedModal.js +35 -12
  5. package/lib/components/Dropdowns/GroupsDropdown.js +63 -45
  6. package/lib/components/Dropdowns/ManagedNavDropdown.js +92 -67
  7. package/lib/components/Dropdowns/UserDropdown.js +105 -24
  8. package/lib/components/Dropdowns/index.js +4 -10
  9. package/lib/components/EntityOwnerList.js +47 -21
  10. package/lib/components/Error.js +101 -12
  11. package/lib/components/ErrorBoundary.js +127 -38
  12. package/lib/components/ErrorMessage.js +39 -12
  13. package/lib/components/Forms/DateField.js +56 -45
  14. package/lib/components/Forms/TimeField.js +76 -45
  15. package/lib/components/Forms/index.js +3 -5
  16. package/lib/components/Groups/CreateEditCopySaveButtons.js +109 -14
  17. package/lib/components/Groups/ExternalGroups/Attach.js +206 -151
  18. package/lib/components/Groups/ExternalGroups/Table.js +176 -48
  19. package/lib/components/Groups/GroupCreateOrEditCommonProps.js +2 -2
  20. package/lib/components/Groups/RosterSyncInfo.js +142 -23
  21. package/lib/components/HOC/AccessibleAppComponent.js +88 -72
  22. package/lib/components/HOC/ActivityRequiredComponent.js +68 -33
  23. package/lib/components/HOC/AsyncComponent.js +49 -41
  24. package/lib/components/HOC/AuthenticatedComponent.js +55 -44
  25. package/lib/components/HOC/CollectionComponent.js +154 -104
  26. package/lib/components/HOC/CollectionFirstItemComponent.js +45 -40
  27. package/lib/components/HOC/CollectionItemComponent.js +152 -100
  28. package/lib/components/HOC/ConnectedModalComponent.js +87 -69
  29. package/lib/components/HOC/DataDependentComponent.js +26 -27
  30. package/lib/components/HOC/EntityComponent.js +57 -53
  31. package/lib/components/HOC/FullscreenModalComponent.js +139 -108
  32. package/lib/components/HOC/GroupActivityRequiredComponent.js +27 -20
  33. package/lib/components/HOC/GuidComponent.js +20 -20
  34. package/lib/components/HOC/ModelContextDependencyVerifyComponent.js +32 -29
  35. package/lib/components/HOC/ModelErrorRedirectComponent.js +37 -39
  36. package/lib/components/HOC/SearchPersistorComponent.js +237 -173
  37. package/lib/components/HOC/UnauthenticatedComponent.js +32 -30
  38. package/lib/components/HOC/UserComponent.js +6 -8
  39. package/lib/components/Icons/IconAlphaList.js +28 -8
  40. package/lib/components/Icons/IconExternalUser.js +28 -8
  41. package/lib/components/Icons/IconImpersonation.js +28 -8
  42. package/lib/components/Icons/IconStopImpersonating.js +28 -8
  43. package/lib/components/Icons/IconTable.js +29 -9
  44. package/lib/components/Icons/IconTableDeleteCol.js +28 -8
  45. package/lib/components/Icons/IconTableDeleteRow.js +28 -8
  46. package/lib/components/Icons/IconTableInsertCol.js +28 -8
  47. package/lib/components/Icons/IconTableInsertRow.js +28 -8
  48. package/lib/components/Impersonation/Button.js +71 -16
  49. package/lib/components/Impersonation/Link.js +72 -16
  50. package/lib/components/Impersonation/UserDetail.js +60 -11
  51. package/lib/components/Loading.js +23 -8
  52. package/lib/components/LockDownBrowser/Check.js +188 -51
  53. package/lib/components/LockDownBrowser/ExitButton.js +22 -13
  54. package/lib/components/LockDownBrowser/Launch.js +64 -64
  55. package/lib/components/Lti/Confirm.js +147 -14
  56. package/lib/components/Lti/CreateNonLtiGroupAlertDialog.js +165 -36
  57. package/lib/components/Lti/Launch.js +99 -25
  58. package/lib/components/Lti/LaunchGroup.js +81 -16
  59. package/lib/components/ManageTable.js +304 -90
  60. package/lib/components/ManageTableNoDataComponent.js +38 -7
  61. package/lib/components/NewVersionAlert.js +76 -49
  62. package/lib/components/NotFound.js +81 -11
  63. package/lib/components/Notifications.js +179 -129
  64. package/lib/components/PaginationNextButton.js +28 -9
  65. package/lib/components/PaginationPreviousButton.js +28 -9
  66. package/lib/components/Quill/CustomToolbar.js +427 -222
  67. package/lib/components/Quill/Formats/Image.js +67 -67
  68. package/lib/components/Quill/Formats/List.js +38 -47
  69. package/lib/components/Quill/Formats/Video.js +23 -26
  70. package/lib/components/Quill/ImageDropModule.js +136 -114
  71. package/lib/components/Quill/ImageWarning.js +41 -12
  72. package/lib/components/Quill/ImageWithAltTextModal.js +420 -89
  73. package/lib/components/Quill/Specs/CustomImageSpec.js +32 -31
  74. package/lib/components/Quill/Specs/CustomVideoSpec.js +22 -23
  75. package/lib/components/Quill/TableModule/Blots/BaseTableBlot.js +89 -97
  76. package/lib/components/Quill/TableModule/Blots/TableBlot.js +47 -50
  77. package/lib/components/Quill/TableModule/Blots/TableBodyBlot.js +48 -51
  78. package/lib/components/Quill/TableModule/Blots/TableCellBlot.js +219 -224
  79. package/lib/components/Quill/TableModule/Blots/TableContainer.js +75 -86
  80. package/lib/components/Quill/TableModule/Blots/TableRowBlot.js +70 -73
  81. package/lib/components/Quill/TableModule/constants.js +40 -42
  82. package/lib/components/Quill/TableModule/index.js +357 -305
  83. package/lib/components/Quill/TableModule/utils.js +39 -48
  84. package/lib/components/Quill/accessibilityFix.js +219 -223
  85. package/lib/components/Quill/index.js +30 -33
  86. package/lib/components/RefreshIndicator/Bordered.js +44 -10
  87. package/lib/components/RefreshIndicator/Inline.js +43 -12
  88. package/lib/components/RefreshIndicator/index.js +257 -62
  89. package/lib/components/SearchControls.js +211 -14
  90. package/lib/components/SentryRoute.js +5 -7
  91. package/lib/components/Tables/RoleFilter.js +66 -38
  92. package/lib/components/Tables/TextFilter.js +58 -18
  93. package/lib/components/UserRoles/Add.js +193 -99
  94. package/lib/components/UserRoles/Context.js +3 -6
  95. package/lib/components/UserRoles/RoleCell.js +176 -75
  96. package/lib/components/UserRoles/Select.js +151 -20
  97. package/lib/components/UserRoles/Table.js +215 -82
  98. package/lib/components/UserRoles/index.js +526 -386
  99. package/lib/config/eslint/index.js +26 -29
  100. package/lib/config/eslint/lib/order.js +21 -28
  101. package/lib/config/eslint/lib/prettier.js +15 -19
  102. package/lib/config/eslint/lib/typescript.js +87 -113
  103. package/lib/config/eslint/react.js +18 -15
  104. package/lib/constants/baseActivity.js +26 -28
  105. package/lib/constants/baseRole.js +10 -12
  106. package/lib/constants/configuration.js +43 -55
  107. package/lib/constants/externalProviderType.js +6 -8
  108. package/lib/constants/fetchErrorData.js +10 -12
  109. package/lib/constants/index.js +13 -15
  110. package/lib/constants/lockDownBrowser.js +23 -25
  111. package/lib/constants/mockData.js +370 -300
  112. package/lib/constants/modelStatus.js +11 -13
  113. package/lib/constants/notificationType.js +8 -10
  114. package/lib/constants/operatingSystem.js +8 -10
  115. package/lib/constants/shard.js +7 -9
  116. package/lib/constants/table.js +18 -22
  117. package/lib/constants/tier.js +8 -10
  118. package/lib/constants/userRole.js +11 -8
  119. package/lib/endpointMappings.js +191 -182
  120. package/lib/hooks/useCollection.js +79 -65
  121. package/lib/hooks/useCollectionConfiguration.js +220 -80
  122. package/lib/hooks/useCollectionItem.js +151 -57
  123. package/lib/hooks/useGuid.js +16 -9
  124. package/lib/hooks/usePrevious.js +14 -13
  125. package/lib/index.js +11 -26
  126. package/lib/redux/actionCreator.js +44 -35
  127. package/lib/redux/actions/AuthAction.js +45 -32
  128. package/lib/redux/actions/ModalAction.js +6 -8
  129. package/lib/redux/actions/ModelAction.js +95 -43
  130. package/lib/redux/actions/NotificationAction.js +6 -8
  131. package/lib/redux/actions/SearchAction.js +5 -7
  132. package/lib/redux/actions/index.js +6 -8
  133. package/lib/redux/configureReducers.js +48 -46
  134. package/lib/redux/configureStore.js +77 -91
  135. package/lib/redux/helpers.js +2 -5
  136. package/lib/redux/reducers/authReducer.js +44 -43
  137. package/lib/redux/reducers/index.js +7 -14
  138. package/lib/redux/reducers/modalsReducer.js +43 -31
  139. package/lib/redux/reducers/modelsReducer.js +131 -137
  140. package/lib/redux/reducers/notificationsReducer.js +20 -20
  141. package/lib/redux/reducers/searchReducer.js +13 -13
  142. package/lib/redux/sagas/appInsightsSaga.js +19 -21
  143. package/lib/redux/sagas/authSaga.js +248 -234
  144. package/lib/redux/sagas/caliperSaga.js +142 -131
  145. package/lib/redux/sagas/clockOffsetSaga.js +29 -32
  146. package/lib/redux/sagas/configurationSaga.js +8 -10
  147. package/lib/redux/sagas/downtimeApiErrorSaga.js +16 -19
  148. package/lib/redux/sagas/errorSaga.js +23 -24
  149. package/lib/redux/sagas/googleAnalyticsSaga.js +24 -27
  150. package/lib/redux/sagas/identityProviderSaga.js +19 -21
  151. package/lib/redux/sagas/initialDataLoadSaga.js +34 -31
  152. package/lib/redux/sagas/lockDownBrowserErrorSaga.js +25 -22
  153. package/lib/redux/sagas/modelFetchSaga.js +302 -286
  154. package/lib/redux/sagas/noStoreSaga.js +60 -61
  155. package/lib/redux/sagas/postLoginDataSaga.js +37 -32
  156. package/lib/redux/sagas/postLoginRedirectSaga.js +22 -27
  157. package/lib/redux/sagas/rootSaga.js +77 -60
  158. package/lib/redux/sagas/sentrySaga.js +25 -28
  159. package/lib/redux/sagas/userIdSaga.js +13 -15
  160. package/lib/services/codeProviderService.js +21 -21
  161. package/lib/services/dateService.js +6 -8
  162. package/lib/services/documentService.js +10 -11
  163. package/lib/services/fetchService.js +103 -95
  164. package/lib/services/persistenceService.js +27 -30
  165. package/lib/services/ticketProviderService.js +25 -25
  166. package/lib/services/tokenPersistenceService.js +8 -10
  167. package/lib/services/windowService.js +14 -16
  168. package/lib/startup.js +110 -101
  169. package/lib/types/AppConfiguration.js +2 -2
  170. package/lib/types/Artifact.js +7 -9
  171. package/lib/types/BaseReduxState.js +2 -2
  172. package/lib/types/Client.js +2 -2
  173. package/lib/types/Collection.js +2 -2
  174. package/lib/types/Configuration.js +2 -2
  175. package/lib/types/DeepLinkingResponseRequest.js +2 -2
  176. package/lib/types/DeletableModel.js +2 -2
  177. package/lib/types/Event.js +2 -2
  178. package/lib/types/ExternalGroup.js +2 -2
  179. package/lib/types/ExternalProvider.js +2 -2
  180. package/lib/types/ExternalTerm.js +2 -2
  181. package/lib/types/Group.js +2 -2
  182. package/lib/types/IdentityProvider.js +2 -2
  183. package/lib/types/LtiLaunch.js +2 -2
  184. package/lib/types/NameOnlyEntity.js +2 -2
  185. package/lib/types/Notification.js +2 -2
  186. package/lib/types/OptionalRecord.js +2 -2
  187. package/lib/types/OwnerSchedule.js +2 -2
  188. package/lib/types/PropertyOfType.js +2 -2
  189. package/lib/types/Quill.js +2 -2
  190. package/lib/types/RoleDescription.js +2 -2
  191. package/lib/types/Search.js +2 -2
  192. package/lib/types/SimpleLocation.js +2 -2
  193. package/lib/types/UniTime.js +2 -2
  194. package/lib/types/User.js +2 -2
  195. package/lib/types/UserRole.js +2 -2
  196. package/lib/types/auth/AuthState.js +2 -2
  197. package/lib/types/auth/CasV1LoginRequestBody.js +2 -2
  198. package/lib/types/auth/ClientCredentials.js +2 -2
  199. package/lib/types/auth/CodeProviderService.js +2 -2
  200. package/lib/types/auth/LocalLoginRequestBody.js +2 -2
  201. package/lib/types/auth/TicketProviderService.js +2 -2
  202. package/lib/types/auth/TokenPersistenceService.js +2 -2
  203. package/lib/types/auth/index.js +8 -10
  204. package/lib/types/externals.d.js +2 -0
  205. package/lib/types/index.js +29 -31
  206. package/lib/types/net/EndpointConfig.js +2 -2
  207. package/lib/types/net/EndpointMapping.js +2 -2
  208. package/lib/types/net/EndpointMappings.js +2 -2
  209. package/lib/types/net/ErrorHandler.js +2 -2
  210. package/lib/types/net/FetchConfig.js +2 -2
  211. package/lib/types/net/FetchErrorData.js +6 -8
  212. package/lib/types/net/FetchResult.js +2 -2
  213. package/lib/types/net/HTTPMethod.js +2 -2
  214. package/lib/types/net/HTTPStatusCode.js +12 -14
  215. package/lib/types/net/Metadata.js +2 -2
  216. package/lib/types/net/Model.js +2 -2
  217. package/lib/types/net/ModelCollection.js +2 -2
  218. package/lib/types/net/ModelsState.js +2 -2
  219. package/lib/types/net/OAuthToken.js +2 -2
  220. package/lib/types/net/OAuthTokenOrNull.js +2 -2
  221. package/lib/types/net/TokenAccessFunction.js +2 -2
  222. package/lib/types/net/index.js +17 -19
  223. package/lib/utils/baseActivity.js +83 -85
  224. package/lib/utils/baseRole.js +32 -36
  225. package/lib/utils/collection.js +403 -297
  226. package/lib/utils/cookies.js +19 -23
  227. package/lib/utils/date.js +188 -205
  228. package/lib/utils/dom.js +130 -131
  229. package/lib/utils/domainIdentifier.js +4 -8
  230. package/lib/utils/entityUserRole.js +2 -5
  231. package/lib/utils/error.js +14 -19
  232. package/lib/utils/events.js +32 -31
  233. package/lib/utils/externalGroup.js +20 -25
  234. package/lib/utils/externalProviders.js +4 -7
  235. package/lib/utils/externalTerms.js +6 -6
  236. package/lib/utils/fetch.js +168 -176
  237. package/lib/utils/group.js +14 -11
  238. package/lib/utils/groupDates.js +38 -46
  239. package/lib/utils/groupRoles.js +23 -32
  240. package/lib/utils/lockDownBrowser.js +12 -15
  241. package/lib/utils/logger.js +23 -28
  242. package/lib/utils/lti.js +4 -7
  243. package/lib/utils/model.js +28 -43
  244. package/lib/utils/number.js +9 -13
  245. package/lib/utils/promise.js +23 -26
  246. package/lib/utils/quill.js +55 -60
  247. package/lib/utils/route.js +52 -60
  248. package/lib/utils/search.js +72 -87
  249. package/lib/utils/shard.js +33 -42
  250. package/lib/utils/sort.js +47 -50
  251. package/lib/utils/string.js +10 -12
  252. package/lib/utils/table.js +29 -33
  253. package/lib/utils/timezone.js +7 -12
  254. package/lib/utils/url.js +130 -144
  255. package/lib/utils/user.js +54 -64
  256. package/lib/utils/userAgent.js +7 -14
  257. package/lib/utils/userRole.js +36 -39
  258. package/package.json +17 -3
@@ -1,274 +1,288 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getOAuthToken = exports.takeMatchesModelFetchFailed = exports.matchesModelFetchFailed = exports.takeMatchesModelFetchReceived = exports.matchesModelFetchReceived = void 0;
4
- exports.getTokenFromCode = getTokenFromCode;
5
- exports.getTokenFromRefreshToken = getTokenFromRefreshToken;
6
- exports.performTokenRefresh = performTokenRefresh;
7
- exports.loginFlow = loginFlow;
8
- exports.credentialsLoginFlow = credentialsLoginFlow;
9
- exports.casV1LoginFlow = casV1LoginFlow;
10
- exports.localLoginFlow = localLoginFlow;
11
- exports.casTicketLoginFlow = casTicketLoginFlow;
12
- exports.handleAuthFailure = handleAuthFailure;
13
- exports.default = authSaga;
14
- const effects_1 = require("redux-saga/effects");
15
- const codeProviderService_1 = require("../../services/codeProviderService");
16
- const ticketProviderService_1 = require("../../services/ticketProviderService");
17
- const tokenPersistenceService_1 = require("../../services/tokenPersistenceService");
18
- const types_1 = require("../../types");
19
- const logger_1 = require("../../utils/logger");
20
- const actions_1 = require("../actions");
1
+ import { all, call, put, race, take, takeEvery } from 'redux-saga/effects';
2
+ import { codeProviderService as defaultCodeProviderService } from '../../services/codeProviderService';
3
+ import { ticketProviderService as defaultTicketProviderService } from '../../services/ticketProviderService';
4
+ import { tokenPersistenceService as defaultTokenPersistenceService } from '../../services/tokenPersistenceService';
5
+ import { HTTP_STATUS_CODE } from '../../types';
6
+ import { getLogger } from '../../utils/logger';
7
+ import { AUTH_ACTION_TYPE, AUTH_CAS_V1_LOGIN_REQUEST_ACTION_TYPE, AUTH_LOCAL_LOGIN_REQUEST_ACTION_TYPE, AUTH_TOKEN_ACTION_TYPE, AUTH_TOKEN_SUCCESS_ACTION_TYPE, isTransientModelFetchErrorAction, isTransientModelFetchResultAction, MODEL_FETCH_ERROR_ACTION_TYPE, MODEL_FETCH_REQUEST_ACTION_TYPE, MODEL_REMOVE_KEY_ACTION_TYPE } from '../actions';
8
+
21
9
  //#region Helpers
22
- const matchesModelFetchReceived = (action, modelName) => (0, actions_1.isTransientModelFetchResultAction)(action) && action.modelPath === modelName;
23
- exports.matchesModelFetchReceived = matchesModelFetchReceived;
24
- const takeMatchesModelFetchReceived = (modelName) => (incomingAction) => (0, exports.matchesModelFetchReceived)(incomingAction, modelName);
25
- exports.takeMatchesModelFetchReceived = takeMatchesModelFetchReceived;
26
- const matchesModelFetchFailed = (action, modelName) => (0, actions_1.isTransientModelFetchErrorAction)(action) && action.modelPath === modelName;
27
- exports.matchesModelFetchFailed = matchesModelFetchFailed;
28
- const takeMatchesModelFetchFailed = (modelName) => (incomingAction) => (0, exports.matchesModelFetchFailed)(incomingAction, modelName);
29
- exports.takeMatchesModelFetchFailed = takeMatchesModelFetchFailed;
10
+
11
+ export const matchesModelFetchReceived = (action, modelName) => isTransientModelFetchResultAction(action) && action.modelPath === modelName;
12
+ export const takeMatchesModelFetchReceived = modelName => incomingAction => matchesModelFetchReceived(incomingAction, modelName);
13
+ export const matchesModelFetchFailed = (action, modelName) => isTransientModelFetchErrorAction(action) && action.modelPath === modelName;
14
+ export const takeMatchesModelFetchFailed = modelName => incomingAction => matchesModelFetchFailed(incomingAction, modelName);
15
+
30
16
  //#endregion Helpers
17
+
31
18
  //#region Local Variables
19
+
32
20
  let clientCredentials;
33
21
  let oauthToken = null;
34
22
  let tokenPersistenceService;
35
23
  let refreshLock;
36
24
  let logger;
25
+
37
26
  //#endregion Local Variables
38
- function* getTokenFromCode(code) {
39
- const getTokenModelName = 'getToken';
40
- // Manually creating form-url-encoded body here because NOTHING else uses this content-type
41
- // but the OAuth spec requires it
42
- const formBody = [
43
- 'grant_type=authorization_code',
44
- `client_id=${clientCredentials.client_id}`,
45
- `client_secret=${clientCredentials.client_secret}`,
46
- `code=${encodeURIComponent(code)}`
47
- ];
48
- const formBodyString = formBody.join('&');
49
- yield (0, effects_1.put)({
50
- type: actions_1.MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
51
- modelName: getTokenModelName,
52
- body: formBodyString,
53
- noStore: true
54
- });
55
- const { fetchResultAction, fetchErrorAction } = yield (0, effects_1.race)({
56
- fetchResultAction: (0, effects_1.take)((0, exports.takeMatchesModelFetchReceived)(getTokenModelName)),
57
- fetchErrorAction: (0, effects_1.take)((0, exports.takeMatchesModelFetchFailed)(getTokenModelName))
58
- });
59
- if (fetchErrorAction || !(fetchResultAction === null || fetchResultAction === void 0 ? void 0 : fetchResultAction.data)) {
60
- return null;
27
+
28
+ export function* getTokenFromCode(code) {
29
+ const getTokenModelName = 'getToken';
30
+ // Manually creating form-url-encoded body here because NOTHING else uses this content-type
31
+ // but the OAuth spec requires it
32
+ const formBody = ['grant_type=authorization_code', `client_id=${clientCredentials.client_id}`, `client_secret=${clientCredentials.client_secret}`, `code=${encodeURIComponent(code)}`];
33
+ const formBodyString = formBody.join('&');
34
+ yield put({
35
+ type: MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
36
+ modelName: getTokenModelName,
37
+ body: formBodyString,
38
+ noStore: true
39
+ });
40
+ const {
41
+ fetchResultAction,
42
+ fetchErrorAction
43
+ } = yield race({
44
+ fetchResultAction: take(takeMatchesModelFetchReceived(getTokenModelName)),
45
+ fetchErrorAction: take(takeMatchesModelFetchFailed(getTokenModelName))
46
+ });
47
+ if (fetchErrorAction || !fetchResultAction?.data) {
48
+ return null;
49
+ }
50
+ return fetchResultAction.data;
51
+ }
52
+ export function* getTokenFromRefreshToken(oauthTokenParam) {
53
+ const getTokenModelName = 'getToken';
54
+ // Manually creating form-url-encoded body here because NOTHING else uses this content-type
55
+ // but the OAuth spec requires it
56
+ const formBody = ['grant_type=refresh_token', `client_id=${clientCredentials.client_id}`, `client_secret=${clientCredentials.client_secret}`, `refresh_token=${encodeURIComponent(oauthTokenParam.refresh_token)}`];
57
+ const formBodyString = formBody.join('&');
58
+ yield put({
59
+ type: MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
60
+ modelName: getTokenModelName,
61
+ body: formBodyString,
62
+ noStore: true
63
+ });
64
+ const {
65
+ fetchResultAction,
66
+ fetchErrorAction
67
+ } = yield race({
68
+ fetchResultAction: take(takeMatchesModelFetchReceived(getTokenModelName)),
69
+ fetchErrorAction: take(takeMatchesModelFetchFailed(getTokenModelName))
70
+ });
71
+ // any error response
72
+ if (fetchErrorAction) {
73
+ // ignore server errors
74
+ if (fetchErrorAction.errorData?.status && fetchErrorAction.errorData.status >= HTTP_STATUS_CODE.INTERNAL_SERVER_ERROR) {
75
+ return oauthTokenParam;
61
76
  }
62
- return fetchResultAction.data;
77
+ return null;
78
+ }
79
+ // for some reason the response had no body
80
+ if (!fetchResultAction?.data) {
81
+ return null;
82
+ }
83
+ return fetchResultAction.data;
63
84
  }
64
- function* getTokenFromRefreshToken(oauthTokenParam) {
65
- var _a;
66
- const getTokenModelName = 'getToken';
67
- // Manually creating form-url-encoded body here because NOTHING else uses this content-type
68
- // but the OAuth spec requires it
69
- const formBody = [
70
- 'grant_type=refresh_token',
71
- `client_id=${clientCredentials.client_id}`,
72
- `client_secret=${clientCredentials.client_secret}`,
73
- `refresh_token=${encodeURIComponent(oauthTokenParam.refresh_token)}`
74
- ];
75
- const formBodyString = formBody.join('&');
76
- yield (0, effects_1.put)({
77
- type: actions_1.MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
78
- modelName: getTokenModelName,
79
- body: formBodyString,
80
- noStore: true
85
+ export function* performTokenRefresh() {
86
+ if (refreshLock || !oauthToken) {
87
+ // already refreshing. wait for the current refresh to succeed or fail.
88
+ yield race({
89
+ refreshSuccess: take(AUTH_TOKEN_SUCCESS_ACTION_TYPE.TOKEN_REFRESH_SUCCEEDED),
90
+ refreshFailed: take(AUTH_ACTION_TYPE.TOKEN_REFRESH_FAILED)
81
91
  });
82
- const { fetchResultAction, fetchErrorAction } = yield (0, effects_1.race)({
83
- fetchResultAction: (0, effects_1.take)((0, exports.takeMatchesModelFetchReceived)(getTokenModelName)),
84
- fetchErrorAction: (0, effects_1.take)((0, exports.takeMatchesModelFetchFailed)(getTokenModelName))
92
+ return;
93
+ }
94
+ logger.debug('Refreshing OAuth token');
95
+ refreshLock = true;
96
+ // oauthToken will be set to:
97
+ // 1. new token (success)
98
+ // 2. same token (failed from timeout or server error)
99
+ // 3. null (fail)
100
+ const originalAccessToken = oauthToken.access_token;
101
+ oauthToken = yield call(getTokenFromRefreshToken, oauthToken);
102
+ if (!!oauthToken && oauthToken.access_token !== originalAccessToken) {
103
+ logger.debug('OAuth token refreshed');
104
+ yield call(tokenPersistenceService.persistToken, oauthToken);
105
+ yield put({
106
+ type: AUTH_TOKEN_SUCCESS_ACTION_TYPE.TOKEN_REFRESH_SUCCEEDED,
107
+ oauthToken
85
108
  });
86
- // any error response
87
- if (fetchErrorAction) {
88
- // ignore server errors
89
- if (((_a = fetchErrorAction.errorData) === null || _a === void 0 ? void 0 : _a.status) &&
90
- fetchErrorAction.errorData.status >= types_1.HTTP_STATUS_CODE.INTERNAL_SERVER_ERROR) {
91
- return oauthTokenParam;
92
- }
93
- return null;
94
- }
95
- // for some reason the response had no body
96
- if (!(fetchResultAction === null || fetchResultAction === void 0 ? void 0 : fetchResultAction.data)) {
97
- return null;
98
- }
99
- return fetchResultAction.data;
100
- }
101
- function* performTokenRefresh() {
102
- if (refreshLock || !oauthToken) {
103
- // already refreshing. wait for the current refresh to succeed or fail.
104
- yield (0, effects_1.race)({
105
- refreshSuccess: (0, effects_1.take)(actions_1.AUTH_TOKEN_SUCCESS_ACTION_TYPE.TOKEN_REFRESH_SUCCEEDED),
106
- refreshFailed: (0, effects_1.take)(actions_1.AUTH_ACTION_TYPE.TOKEN_REFRESH_FAILED)
107
- });
108
- return;
109
- }
110
- logger.debug('Refreshing OAuth token');
111
- refreshLock = true;
112
- // oauthToken will be set to:
113
- // 1. new token (success)
114
- // 2. same token (failed from timeout or server error)
115
- // 3. null (fail)
116
- const originalAccessToken = oauthToken.access_token;
117
- oauthToken = yield (0, effects_1.call)(getTokenFromRefreshToken, oauthToken);
118
- if (!!oauthToken && oauthToken.access_token !== originalAccessToken) {
119
- logger.debug('OAuth token refreshed');
120
- yield (0, effects_1.call)(tokenPersistenceService.persistToken, oauthToken);
121
- yield (0, effects_1.put)({ type: actions_1.AUTH_TOKEN_SUCCESS_ACTION_TYPE.TOKEN_REFRESH_SUCCEEDED, oauthToken });
122
- }
123
- else if (oauthToken === null) {
124
- logger.debug('OAuth token failed to refresh');
125
- // This should never happen outside of the token having been revoked on the server side
126
- yield (0, effects_1.all)({
127
- refreshFailed: (0, effects_1.put)({ type: actions_1.AUTH_ACTION_TYPE.TOKEN_REFRESH_FAILED }),
128
- logOut: (0, effects_1.put)({ type: actions_1.AUTH_ACTION_TYPE.LOG_OUT_REQUESTED })
129
- });
130
- }
131
- refreshLock = false;
132
- }
133
- function* loginFlow(modelFetchRequestAction) {
134
- var _a;
135
- yield (0, effects_1.put)(modelFetchRequestAction);
136
- const { fetchResultAction, fetchErrorAction } = yield (0, effects_1.race)({
137
- fetchResultAction: (0, effects_1.take)((0, exports.takeMatchesModelFetchReceived)(modelFetchRequestAction.modelName)),
138
- fetchErrorAction: (0, effects_1.take)((0, exports.takeMatchesModelFetchFailed)(modelFetchRequestAction.modelName))
109
+ } else if (oauthToken === null) {
110
+ logger.debug('OAuth token failed to refresh');
111
+ // This should never happen outside of the token having been revoked on the server side
112
+ yield all({
113
+ refreshFailed: put({
114
+ type: AUTH_ACTION_TYPE.TOKEN_REFRESH_FAILED
115
+ }),
116
+ logOut: put({
117
+ type: AUTH_ACTION_TYPE.LOG_OUT_REQUESTED
118
+ })
139
119
  });
140
- if (fetchErrorAction) {
141
- return null;
142
- }
143
- const code = (_a = fetchResultAction === null || fetchResultAction === void 0 ? void 0 : fetchResultAction.data) === null || _a === void 0 ? void 0 : _a.code;
144
- if (!code) {
145
- return null;
146
- }
147
- return yield (0, effects_1.call)(getTokenFromCode, code);
120
+ }
121
+ refreshLock = false;
148
122
  }
149
- function* credentialsLoginFlow(action, modelName) {
150
- const modelFetchRequestAction = {
151
- // set required defaults
152
- type: actions_1.MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
153
- modelName,
154
- noStore: true,
155
- // force no retry
156
- noRetry: true,
157
- // pass thru body
158
- body: action.body
159
- };
160
- return yield (0, effects_1.call)(loginFlow, modelFetchRequestAction);
123
+ export function* loginFlow(modelFetchRequestAction) {
124
+ yield put(modelFetchRequestAction);
125
+ const {
126
+ fetchResultAction,
127
+ fetchErrorAction
128
+ } = yield race({
129
+ fetchResultAction: take(takeMatchesModelFetchReceived(modelFetchRequestAction.modelName)),
130
+ fetchErrorAction: take(takeMatchesModelFetchFailed(modelFetchRequestAction.modelName))
131
+ });
132
+ if (fetchErrorAction) {
133
+ return null;
134
+ }
135
+ const code = fetchResultAction?.data?.code;
136
+ if (!code) {
137
+ return null;
138
+ }
139
+ return yield call(getTokenFromCode, code);
161
140
  }
162
- function* casV1LoginFlow(action) {
163
- return yield (0, effects_1.call)(credentialsLoginFlow, action, 'codeFromCasV1');
141
+ export function* credentialsLoginFlow(action, modelName) {
142
+ const modelFetchRequestAction = {
143
+ // set required defaults
144
+ type: MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
145
+ modelName,
146
+ noStore: true,
147
+ // force no retry
148
+ noRetry: true,
149
+ // pass thru body
150
+ body: action.body
151
+ };
152
+ return yield call(loginFlow, modelFetchRequestAction);
164
153
  }
165
- function* localLoginFlow(action) {
166
- return yield (0, effects_1.call)(credentialsLoginFlow, action, 'codeFromLocalCredentials');
154
+ export function* casV1LoginFlow(action) {
155
+ return yield call(credentialsLoginFlow, action, 'codeFromCasV1');
167
156
  }
168
- function* casTicketLoginFlow(ticket, service) {
169
- const modelFetchRequestAction = {
170
- type: actions_1.MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
171
- modelName: 'codeFromCasTicket',
172
- noStore: true,
173
- queryParams: {
174
- ticket,
175
- service
176
- }
177
- };
178
- return yield (0, effects_1.call)(loginFlow, modelFetchRequestAction);
157
+ export function* localLoginFlow(action) {
158
+ return yield call(credentialsLoginFlow, action, 'codeFromLocalCredentials');
179
159
  }
180
- function* handleAuthFailure(action) {
181
- // This should be unlikely since we normally have a refresh token loop happening
182
- // but if the app is backgrounded, the loop might not be caught up yet
183
- if (oauthToken && action.errorData && action.errorData.status === types_1.HTTP_STATUS_CODE.UNAUTHORIZED) {
184
- logger.debug('token expired - refreshing');
185
- yield (0, effects_1.call)(performTokenRefresh);
160
+ export function* casTicketLoginFlow(ticket, service) {
161
+ const modelFetchRequestAction = {
162
+ type: MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
163
+ modelName: 'codeFromCasTicket',
164
+ noStore: true,
165
+ queryParams: {
166
+ ticket,
167
+ service
186
168
  }
169
+ };
170
+ return yield call(loginFlow, modelFetchRequestAction);
187
171
  }
188
- const getOAuthToken = function* (modelName) {
189
- // Don't try to refresh the token if we're already in a request to refresh the token
190
- if (modelName === 'getToken') {
191
- return null;
192
- }
193
- if (oauthToken && oauthToken['.expires']) {
194
- const thirtySecondsFromNow = new Date();
195
- thirtySecondsFromNow.setSeconds(thirtySecondsFromNow.getSeconds() + 30);
196
- if (new Date(oauthToken['.expires']) < thirtySecondsFromNow) {
197
- // start a token refresh and wait for the success action in case another refresh is currently happening
198
- yield (0, effects_1.call)(performTokenRefresh);
199
- return oauthToken;
200
- }
172
+ export function* handleAuthFailure(action) {
173
+ // This should be unlikely since we normally have a refresh token loop happening
174
+ // but if the app is backgrounded, the loop might not be caught up yet
175
+ if (oauthToken && action.errorData && action.errorData.status === HTTP_STATUS_CODE.UNAUTHORIZED) {
176
+ logger.debug('token expired - refreshing');
177
+ yield call(performTokenRefresh);
178
+ }
179
+ }
180
+ export const getOAuthToken = function* (modelName) {
181
+ // Don't try to refresh the token if we're already in a request to refresh the token
182
+ if (modelName === 'getToken') {
183
+ return null;
184
+ }
185
+ if (oauthToken && oauthToken['.expires']) {
186
+ const thirtySecondsFromNow = new Date();
187
+ thirtySecondsFromNow.setSeconds(thirtySecondsFromNow.getSeconds() + 30);
188
+ if (new Date(oauthToken['.expires']) < thirtySecondsFromNow) {
189
+ // start a token refresh and wait for the success action in case another refresh is currently happening
190
+ yield call(performTokenRefresh);
191
+ return oauthToken;
201
192
  }
202
- return oauthToken;
193
+ }
194
+ return oauthToken;
203
195
  };
204
- exports.getOAuthToken = getOAuthToken;
205
- function* authSaga(clientCredentialsParam, tokenPersistenceServiceParam = tokenPersistenceService_1.tokenPersistenceService, ticketProviderService = ticketProviderService_1.ticketProviderService, codeProviderService = codeProviderService_1.codeProviderService) {
206
- logger = (0, logger_1.getLogger)();
196
+ export default function authSaga(clientCredentialsParam) {
197
+ let tokenPersistenceServiceParam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultTokenPersistenceService;
198
+ let ticketProviderService = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : defaultTicketProviderService;
199
+ let codeProviderService = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : defaultCodeProviderService;
200
+ return function* () {
201
+ logger = getLogger();
207
202
  clientCredentials = clientCredentialsParam;
208
203
  tokenPersistenceService = tokenPersistenceServiceParam;
204
+
209
205
  // Try to get persisted token (normally in AsyncStorage or LocalStorage)
210
- oauthToken = yield (0, effects_1.call)(tokenPersistenceService.getPersistedToken);
206
+ oauthToken = yield call(tokenPersistenceService.getPersistedToken);
207
+
211
208
  // If no token, try to get CAS ticket (normally in the URL), use it to get a token
212
209
  if (!oauthToken) {
213
- const casTicket = ticketProviderService.getTicket();
214
- ticketProviderService.removeTicket();
215
- const service = ticketProviderService.getAppServiceName();
216
- if (casTicket && service) {
217
- oauthToken = yield (0, effects_1.call)(casTicketLoginFlow, casTicket, service);
218
- }
210
+ const casTicket = ticketProviderService.getTicket();
211
+ ticketProviderService.removeTicket();
212
+ const service = ticketProviderService.getAppServiceName();
213
+ if (casTicket && service) {
214
+ oauthToken = yield call(casTicketLoginFlow, casTicket, service);
215
+ }
219
216
  }
217
+
220
218
  // If OAuth Code exists (normally in the URL), use it to get a token
221
219
  // e.g. LTI, Shibboleth, Facebook, Google
222
220
  const code = codeProviderService.getCode();
223
221
  if (code) {
224
- // Log out the current user if a new token is about to be generated from the OAuth Code
225
- if (oauthToken) {
226
- yield (0, effects_1.all)({
227
- clearUserData: (0, effects_1.put)({ type: actions_1.MODEL_REMOVE_KEY_ACTION_TYPE, modelPath: 'user' }),
228
- clearPersistentToken: (0, effects_1.call)(tokenPersistenceService.persistToken, null)
229
- });
230
- oauthToken = null;
231
- }
232
- oauthToken = yield (0, effects_1.call)(getTokenFromCode, code);
222
+ // Log out the current user if a new token is about to be generated from the OAuth Code
223
+ if (oauthToken) {
224
+ yield all({
225
+ clearUserData: put({
226
+ type: MODEL_REMOVE_KEY_ACTION_TYPE,
227
+ modelPath: 'user'
228
+ }),
229
+ clearPersistentToken: call(tokenPersistenceService.persistToken, null)
230
+ });
231
+ oauthToken = null;
232
+ }
233
+ oauthToken = yield call(getTokenFromCode, code);
233
234
  }
234
235
  codeProviderService.removeCode();
235
- yield (0, effects_1.put)({ type: actions_1.AUTH_TOKEN_ACTION_TYPE.AUTH_INITIALIZED, oauthToken });
236
- yield (0, effects_1.takeEvery)(actions_1.MODEL_FETCH_ERROR_ACTION_TYPE.TRY_FETCH_FAILED, handleAuthFailure);
236
+ yield put({
237
+ type: AUTH_TOKEN_ACTION_TYPE.AUTH_INITIALIZED,
238
+ oauthToken
239
+ });
240
+ yield takeEvery(MODEL_FETCH_ERROR_ACTION_TYPE.TRY_FETCH_FAILED, handleAuthFailure);
237
241
  do {
238
- if (!oauthToken) {
239
- const { casV1Action, localLoginAction } = yield (0, effects_1.race)({
240
- casV1Action: (0, effects_1.take)(actions_1.AUTH_CAS_V1_LOGIN_REQUEST_ACTION_TYPE.CAS_V1_LOGIN_REQUEST),
241
- localLoginAction: (0, effects_1.take)(actions_1.AUTH_LOCAL_LOGIN_REQUEST_ACTION_TYPE.LOCAL_LOGIN_REQUEST)
242
- });
243
- yield (0, effects_1.put)({ type: actions_1.AUTH_ACTION_TYPE.LOGIN_REQUESTED });
244
- if (casV1Action) {
245
- oauthToken = yield (0, effects_1.call)(casV1LoginFlow, casV1Action);
246
- }
247
- else if (localLoginAction) {
248
- oauthToken = yield (0, effects_1.call)(localLoginFlow, localLoginAction);
249
- }
250
- }
251
- if (oauthToken) {
252
- yield (0, effects_1.call)(tokenPersistenceService.persistToken, oauthToken);
253
- yield (0, effects_1.all)({
254
- loginSuccess: (0, effects_1.put)({
255
- type: actions_1.AUTH_TOKEN_SUCCESS_ACTION_TYPE.GET_TOKEN_SUCCEEDED,
256
- oauthToken
257
- }),
258
- getUserInfo: (0, effects_1.put)({
259
- type: actions_1.MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
260
- modelName: 'user.userInfo'
261
- }),
262
- logOut: (0, effects_1.take)(actions_1.AUTH_ACTION_TYPE.LOG_OUT_REQUESTED)
263
- });
264
- }
265
- else {
266
- yield (0, effects_1.put)({ type: actions_1.AUTH_ACTION_TYPE.LOGIN_FAILED });
242
+ if (!oauthToken) {
243
+ const {
244
+ casV1Action,
245
+ localLoginAction
246
+ } = yield race({
247
+ casV1Action: take(AUTH_CAS_V1_LOGIN_REQUEST_ACTION_TYPE.CAS_V1_LOGIN_REQUEST),
248
+ localLoginAction: take(AUTH_LOCAL_LOGIN_REQUEST_ACTION_TYPE.LOCAL_LOGIN_REQUEST)
249
+ });
250
+ yield put({
251
+ type: AUTH_ACTION_TYPE.LOGIN_REQUESTED
252
+ });
253
+ if (casV1Action) {
254
+ oauthToken = yield call(casV1LoginFlow, casV1Action);
255
+ } else if (localLoginAction) {
256
+ oauthToken = yield call(localLoginFlow, localLoginAction);
267
257
  }
268
- yield (0, effects_1.all)({
269
- clearUserData: (0, effects_1.put)({ type: actions_1.MODEL_REMOVE_KEY_ACTION_TYPE, modelPath: 'user' }),
270
- clearPersistentToken: (0, effects_1.call)(tokenPersistenceService.persistToken, null)
258
+ }
259
+ if (oauthToken) {
260
+ yield call(tokenPersistenceService.persistToken, oauthToken);
261
+ yield all({
262
+ loginSuccess: put({
263
+ type: AUTH_TOKEN_SUCCESS_ACTION_TYPE.GET_TOKEN_SUCCEEDED,
264
+ oauthToken
265
+ }),
266
+ getUserInfo: put({
267
+ type: MODEL_FETCH_REQUEST_ACTION_TYPE.FETCH_REQUEST,
268
+ modelName: 'user.userInfo'
269
+ }),
270
+ logOut: take(AUTH_ACTION_TYPE.LOG_OUT_REQUESTED)
271
271
  });
272
- oauthToken = null;
272
+ } else {
273
+ yield put({
274
+ type: AUTH_ACTION_TYPE.LOGIN_FAILED
275
+ });
276
+ }
277
+ yield all({
278
+ clearUserData: put({
279
+ type: MODEL_REMOVE_KEY_ACTION_TYPE,
280
+ modelPath: 'user'
281
+ }),
282
+ clearPersistentToken: call(tokenPersistenceService.persistToken, null)
283
+ });
284
+ oauthToken = null;
273
285
  } while (true);
286
+ }();
274
287
  }
288
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJhbGwiLCJjYWxsIiwicHV0IiwicmFjZSIsInRha2UiLCJ0YWtlRXZlcnkiLCJjb2RlUHJvdmlkZXJTZXJ2aWNlIiwiZGVmYXVsdENvZGVQcm92aWRlclNlcnZpY2UiLCJ0aWNrZXRQcm92aWRlclNlcnZpY2UiLCJkZWZhdWx0VGlja2V0UHJvdmlkZXJTZXJ2aWNlIiwidG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2UiLCJkZWZhdWx0VG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2UiLCJIVFRQX1NUQVRVU19DT0RFIiwiZ2V0TG9nZ2VyIiwiQVVUSF9BQ1RJT05fVFlQRSIsIkFVVEhfQ0FTX1YxX0xPR0lOX1JFUVVFU1RfQUNUSU9OX1RZUEUiLCJBVVRIX0xPQ0FMX0xPR0lOX1JFUVVFU1RfQUNUSU9OX1RZUEUiLCJBVVRIX1RPS0VOX0FDVElPTl9UWVBFIiwiQVVUSF9UT0tFTl9TVUNDRVNTX0FDVElPTl9UWVBFIiwiaXNUcmFuc2llbnRNb2RlbEZldGNoRXJyb3JBY3Rpb24iLCJpc1RyYW5zaWVudE1vZGVsRmV0Y2hSZXN1bHRBY3Rpb24iLCJNT0RFTF9GRVRDSF9FUlJPUl9BQ1RJT05fVFlQRSIsIk1PREVMX0ZFVENIX1JFUVVFU1RfQUNUSU9OX1RZUEUiLCJNT0RFTF9SRU1PVkVfS0VZX0FDVElPTl9UWVBFIiwibWF0Y2hlc01vZGVsRmV0Y2hSZWNlaXZlZCIsImFjdGlvbiIsIm1vZGVsTmFtZSIsIm1vZGVsUGF0aCIsInRha2VNYXRjaGVzTW9kZWxGZXRjaFJlY2VpdmVkIiwiaW5jb21pbmdBY3Rpb24iLCJtYXRjaGVzTW9kZWxGZXRjaEZhaWxlZCIsInRha2VNYXRjaGVzTW9kZWxGZXRjaEZhaWxlZCIsImNsaWVudENyZWRlbnRpYWxzIiwib2F1dGhUb2tlbiIsInJlZnJlc2hMb2NrIiwibG9nZ2VyIiwiZ2V0VG9rZW5Gcm9tQ29kZSIsImNvZGUiLCJnZXRUb2tlbk1vZGVsTmFtZSIsImZvcm1Cb2R5IiwiY2xpZW50X2lkIiwiY2xpZW50X3NlY3JldCIsImVuY29kZVVSSUNvbXBvbmVudCIsImZvcm1Cb2R5U3RyaW5nIiwiam9pbiIsInR5cGUiLCJGRVRDSF9SRVFVRVNUIiwiYm9keSIsIm5vU3RvcmUiLCJmZXRjaFJlc3VsdEFjdGlvbiIsImZldGNoRXJyb3JBY3Rpb24iLCJkYXRhIiwiZ2V0VG9rZW5Gcm9tUmVmcmVzaFRva2VuIiwib2F1dGhUb2tlblBhcmFtIiwicmVmcmVzaF90b2tlbiIsImVycm9yRGF0YSIsInN0YXR1cyIsIklOVEVSTkFMX1NFUlZFUl9FUlJPUiIsInBlcmZvcm1Ub2tlblJlZnJlc2giLCJyZWZyZXNoU3VjY2VzcyIsIlRPS0VOX1JFRlJFU0hfU1VDQ0VFREVEIiwicmVmcmVzaEZhaWxlZCIsIlRPS0VOX1JFRlJFU0hfRkFJTEVEIiwiZGVidWciLCJvcmlnaW5hbEFjY2Vzc1Rva2VuIiwiYWNjZXNzX3Rva2VuIiwicGVyc2lzdFRva2VuIiwibG9nT3V0IiwiTE9HX09VVF9SRVFVRVNURUQiLCJsb2dpbkZsb3ciLCJtb2RlbEZldGNoUmVxdWVzdEFjdGlvbiIsImNyZWRlbnRpYWxzTG9naW5GbG93Iiwibm9SZXRyeSIsImNhc1YxTG9naW5GbG93IiwibG9jYWxMb2dpbkZsb3ciLCJjYXNUaWNrZXRMb2dpbkZsb3ciLCJ0aWNrZXQiLCJzZXJ2aWNlIiwicXVlcnlQYXJhbXMiLCJoYW5kbGVBdXRoRmFpbHVyZSIsIlVOQVVUSE9SSVpFRCIsImdldE9BdXRoVG9rZW4iLCJ0aGlydHlTZWNvbmRzRnJvbU5vdyIsIkRhdGUiLCJzZXRTZWNvbmRzIiwiZ2V0U2Vjb25kcyIsImF1dGhTYWdhIiwiY2xpZW50Q3JlZGVudGlhbHNQYXJhbSIsInRva2VuUGVyc2lzdGVuY2VTZXJ2aWNlUGFyYW0iLCJhcmd1bWVudHMiLCJsZW5ndGgiLCJ1bmRlZmluZWQiLCJnZXRQZXJzaXN0ZWRUb2tlbiIsImNhc1RpY2tldCIsImdldFRpY2tldCIsInJlbW92ZVRpY2tldCIsImdldEFwcFNlcnZpY2VOYW1lIiwiZ2V0Q29kZSIsImNsZWFyVXNlckRhdGEiLCJjbGVhclBlcnNpc3RlbnRUb2tlbiIsInJlbW92ZUNvZGUiLCJBVVRIX0lOSVRJQUxJWkVEIiwiVFJZX0ZFVENIX0ZBSUxFRCIsImNhc1YxQWN0aW9uIiwibG9jYWxMb2dpbkFjdGlvbiIsIkNBU19WMV9MT0dJTl9SRVFVRVNUIiwiTE9DQUxfTE9HSU5fUkVRVUVTVCIsIkxPR0lOX1JFUVVFU1RFRCIsImxvZ2luU3VjY2VzcyIsIkdFVF9UT0tFTl9TVUNDRUVERUQiLCJnZXRVc2VySW5mbyIsIkxPR0lOX0ZBSUxFRCJdLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9yZWR1eC9zYWdhcy9hdXRoU2FnYS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBTYWdhSXRlcmF0b3IgfSBmcm9tICdAcmVkdXgtc2FnYS9jb3JlJ1xuaW1wb3J0IHsgQW55QWN0aW9uIH0gZnJvbSAncmVkdXgnXG5pbXBvcnQgeyBhbGwsIGNhbGwsIHB1dCwgcmFjZSwgdGFrZSwgdGFrZUV2ZXJ5IH0gZnJvbSAncmVkdXgtc2FnYS9lZmZlY3RzJ1xuaW1wb3J0IHsgY29kZVByb3ZpZGVyU2VydmljZSBhcyBkZWZhdWx0Q29kZVByb3ZpZGVyU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2NvZGVQcm92aWRlclNlcnZpY2UnXG5pbXBvcnQgeyB0aWNrZXRQcm92aWRlclNlcnZpY2UgYXMgZGVmYXVsdFRpY2tldFByb3ZpZGVyU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RpY2tldFByb3ZpZGVyU2VydmljZSdcbmltcG9ydCB7IHRva2VuUGVyc2lzdGVuY2VTZXJ2aWNlIGFzIGRlZmF1bHRUb2tlblBlcnNpc3RlbmNlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3Rva2VuUGVyc2lzdGVuY2VTZXJ2aWNlJ1xuaW1wb3J0IHtcblx0Q2xpZW50Q3JlZGVudGlhbHMsXG5cdENvZGVQcm92aWRlclNlcnZpY2UsXG5cdEhUVFBfU1RBVFVTX0NPREUsXG5cdE9BdXRoVG9rZW4sXG5cdE9BdXRoVG9rZW5Pck51bGwsXG5cdFRpY2tldFByb3ZpZGVyU2VydmljZSxcblx0VG9rZW5BY2Nlc3NGdW5jdGlvbixcblx0VG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2Vcbn0gZnJvbSAnLi4vLi4vdHlwZXMnXG5pbXBvcnQgeyBnZXRMb2dnZXIsIExvZ2dlciB9IGZyb20gJy4uLy4uL3V0aWxzL2xvZ2dlcidcbmltcG9ydCB7XG5cdEFVVEhfQUNUSU9OX1RZUEUsXG5cdEFVVEhfQ0FTX1YxX0xPR0lOX1JFUVVFU1RfQUNUSU9OX1RZUEUsXG5cdEFVVEhfTE9DQUxfTE9HSU5fUkVRVUVTVF9BQ1RJT05fVFlQRSxcblx0QVVUSF9UT0tFTl9BQ1RJT05fVFlQRSxcblx0QVVUSF9UT0tFTl9TVUNDRVNTX0FDVElPTl9UWVBFLFxuXHRBdXRoQWN0aW9uLFxuXHRBdXRoQ2FzVjFMb2dpblJlcXVlc3RBY3Rpb24sXG5cdEF1dGhMb2NhbExvZ2luUmVxdWVzdEFjdGlvbixcblx0QXV0aFRva2VuQWN0aW9uLFxuXHRBdXRoVG9rZW5TdWNjZXNzQWN0aW9uLFxuXHRpc1RyYW5zaWVudE1vZGVsRmV0Y2hFcnJvckFjdGlvbixcblx0aXNUcmFuc2llbnRNb2RlbEZldGNoUmVzdWx0QWN0aW9uLFxuXHRNT0RFTF9GRVRDSF9FUlJPUl9BQ1RJT05fVFlQRSxcblx0TU9ERUxfRkVUQ0hfUkVRVUVTVF9BQ1RJT05fVFlQRSxcblx0TU9ERUxfUkVNT1ZFX0tFWV9BQ1RJT05fVFlQRSxcblx0TW9kZWxGZXRjaEVycm9yQWN0aW9uLFxuXHRNb2RlbEZldGNoUmVxdWVzdEFjdGlvbixcblx0TW9kZWxGZXRjaFJlc3VsdEFjdGlvbixcblx0TW9kZWxSZW1vdmVLZXlBY3Rpb25cbn0gZnJvbSAnLi4vYWN0aW9ucydcblxuLy8jcmVnaW9uIEhlbHBlcnNcblxuZXhwb3J0IGNvbnN0IG1hdGNoZXNNb2RlbEZldGNoUmVjZWl2ZWQgPSAoYWN0aW9uOiBBbnlBY3Rpb24sIG1vZGVsTmFtZTogc3RyaW5nKSA9PlxuXHRpc1RyYW5zaWVudE1vZGVsRmV0Y2hSZXN1bHRBY3Rpb24oYWN0aW9uKSAmJiBhY3Rpb24ubW9kZWxQYXRoID09PSBtb2RlbE5hbWVcblxuZXhwb3J0IGNvbnN0IHRha2VNYXRjaGVzTW9kZWxGZXRjaFJlY2VpdmVkID0gKG1vZGVsTmFtZTogc3RyaW5nKSA9PiAoaW5jb21pbmdBY3Rpb246IEFueUFjdGlvbikgPT5cblx0bWF0Y2hlc01vZGVsRmV0Y2hSZWNlaXZlZChpbmNvbWluZ0FjdGlvbiwgbW9kZWxOYW1lKVxuXG5leHBvcnQgY29uc3QgbWF0Y2hlc01vZGVsRmV0Y2hGYWlsZWQgPSAoYWN0aW9uOiBBbnlBY3Rpb24sIG1vZGVsTmFtZTogc3RyaW5nKSA9PlxuXHRpc1RyYW5zaWVudE1vZGVsRmV0Y2hFcnJvckFjdGlvbihhY3Rpb24pICYmIGFjdGlvbi5tb2RlbFBhdGggPT09IG1vZGVsTmFtZVxuXG5leHBvcnQgY29uc3QgdGFrZU1hdGNoZXNNb2RlbEZldGNoRmFpbGVkID0gKG1vZGVsTmFtZTogc3RyaW5nKSA9PiAoaW5jb21pbmdBY3Rpb246IEFueUFjdGlvbikgPT5cblx0bWF0Y2hlc01vZGVsRmV0Y2hGYWlsZWQoaW5jb21pbmdBY3Rpb24sIG1vZGVsTmFtZSlcblxuLy8jZW5kcmVnaW9uIEhlbHBlcnNcblxuLy8jcmVnaW9uIExvY2FsIFZhcmlhYmxlc1xuXG5sZXQgY2xpZW50Q3JlZGVudGlhbHM6IENsaWVudENyZWRlbnRpYWxzXG5sZXQgb2F1dGhUb2tlbjogT0F1dGhUb2tlbk9yTnVsbCA9IG51bGxcbmxldCB0b2tlblBlcnNpc3RlbmNlU2VydmljZTogVG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2VcbmxldCByZWZyZXNoTG9jazogYm9vbGVhblxubGV0IGxvZ2dlcjogTG9nZ2VyXG5cbi8vI2VuZHJlZ2lvbiBMb2NhbCBWYXJpYWJsZXNcblxuZXhwb3J0IGZ1bmN0aW9uKiBnZXRUb2tlbkZyb21Db2RlKGNvZGU6IHN0cmluZyk6IFNhZ2FJdGVyYXRvciB7XG5cdGNvbnN0IGdldFRva2VuTW9kZWxOYW1lID0gJ2dldFRva2VuJ1xuXHQvLyBNYW51YWxseSBjcmVhdGluZyBmb3JtLXVybC1lbmNvZGVkIGJvZHkgaGVyZSBiZWNhdXNlIE5PVEhJTkcgZWxzZSB1c2VzIHRoaXMgY29udGVudC10eXBlXG5cdC8vIGJ1dCB0aGUgT0F1dGggc3BlYyByZXF1aXJlcyBpdFxuXHRjb25zdCBmb3JtQm9keSA9IFtcblx0XHQnZ3JhbnRfdHlwZT1hdXRob3JpemF0aW9uX2NvZGUnLFxuXHRcdGBjbGllbnRfaWQ9JHtjbGllbnRDcmVkZW50aWFscy5jbGllbnRfaWR9YCxcblx0XHRgY2xpZW50X3NlY3JldD0ke2NsaWVudENyZWRlbnRpYWxzLmNsaWVudF9zZWNyZXR9YCxcblx0XHRgY29kZT0ke2VuY29kZVVSSUNvbXBvbmVudChjb2RlKX1gXG5cdF1cblx0Y29uc3QgZm9ybUJvZHlTdHJpbmcgPSBmb3JtQm9keS5qb2luKCcmJylcblx0eWllbGQgcHV0PE1vZGVsRmV0Y2hSZXF1ZXN0QWN0aW9uPih7XG5cdFx0dHlwZTogTU9ERUxfRkVUQ0hfUkVRVUVTVF9BQ1RJT05fVFlQRS5GRVRDSF9SRVFVRVNULFxuXHRcdG1vZGVsTmFtZTogZ2V0VG9rZW5Nb2RlbE5hbWUsXG5cdFx0Ym9keTogZm9ybUJvZHlTdHJpbmcsXG5cdFx0bm9TdG9yZTogdHJ1ZVxuXHR9KVxuXHRjb25zdCB7XG5cdFx0ZmV0Y2hSZXN1bHRBY3Rpb24sXG5cdFx0ZmV0Y2hFcnJvckFjdGlvblxuXHR9OiB7IGZldGNoUmVzdWx0QWN0aW9uPzogTW9kZWxGZXRjaFJlc3VsdEFjdGlvbjsgZmV0Y2hFcnJvckFjdGlvbj86IE1vZGVsRmV0Y2hFcnJvckFjdGlvbiB9ID0geWllbGQgcmFjZSh7XG5cdFx0ZmV0Y2hSZXN1bHRBY3Rpb246IHRha2UodGFrZU1hdGNoZXNNb2RlbEZldGNoUmVjZWl2ZWQoZ2V0VG9rZW5Nb2RlbE5hbWUpKSxcblx0XHRmZXRjaEVycm9yQWN0aW9uOiB0YWtlKHRha2VNYXRjaGVzTW9kZWxGZXRjaEZhaWxlZChnZXRUb2tlbk1vZGVsTmFtZSkpXG5cdH0pXG5cdGlmIChmZXRjaEVycm9yQWN0aW9uIHx8ICFmZXRjaFJlc3VsdEFjdGlvbj8uZGF0YSkge1xuXHRcdHJldHVybiBudWxsXG5cdH1cblx0cmV0dXJuIGZldGNoUmVzdWx0QWN0aW9uLmRhdGFcbn1cblxuZXhwb3J0IGZ1bmN0aW9uKiBnZXRUb2tlbkZyb21SZWZyZXNoVG9rZW4ob2F1dGhUb2tlblBhcmFtOiBPQXV0aFRva2VuKTogU2FnYUl0ZXJhdG9yIHtcblx0Y29uc3QgZ2V0VG9rZW5Nb2RlbE5hbWUgPSAnZ2V0VG9rZW4nXG5cdC8vIE1hbnVhbGx5IGNyZWF0aW5nIGZvcm0tdXJsLWVuY29kZWQgYm9keSBoZXJlIGJlY2F1c2UgTk9USElORyBlbHNlIHVzZXMgdGhpcyBjb250ZW50LXR5cGVcblx0Ly8gYnV0IHRoZSBPQXV0aCBzcGVjIHJlcXVpcmVzIGl0XG5cdGNvbnN0IGZvcm1Cb2R5ID0gW1xuXHRcdCdncmFudF90eXBlPXJlZnJlc2hfdG9rZW4nLFxuXHRcdGBjbGllbnRfaWQ9JHtjbGllbnRDcmVkZW50aWFscy5jbGllbnRfaWR9YCxcblx0XHRgY2xpZW50X3NlY3JldD0ke2NsaWVudENyZWRlbnRpYWxzLmNsaWVudF9zZWNyZXR9YCxcblx0XHRgcmVmcmVzaF90b2tlbj0ke2VuY29kZVVSSUNvbXBvbmVudChvYXV0aFRva2VuUGFyYW0ucmVmcmVzaF90b2tlbil9YFxuXHRdXG5cdGNvbnN0IGZvcm1Cb2R5U3RyaW5nID0gZm9ybUJvZHkuam9pbignJicpXG5cdHlpZWxkIHB1dDxNb2RlbEZldGNoUmVxdWVzdEFjdGlvbj4oe1xuXHRcdHR5cGU6IE1PREVMX0ZFVENIX1JFUVVFU1RfQUNUSU9OX1RZUEUuRkVUQ0hfUkVRVUVTVCxcblx0XHRtb2RlbE5hbWU6IGdldFRva2VuTW9kZWxOYW1lLFxuXHRcdGJvZHk6IGZvcm1Cb2R5U3RyaW5nLFxuXHRcdG5vU3RvcmU6IHRydWVcblx0fSlcblx0Y29uc3Qge1xuXHRcdGZldGNoUmVzdWx0QWN0aW9uLFxuXHRcdGZldGNoRXJyb3JBY3Rpb25cblx0fTogeyBmZXRjaFJlc3VsdEFjdGlvbj86IE1vZGVsRmV0Y2hSZXN1bHRBY3Rpb247IGZldGNoRXJyb3JBY3Rpb24/OiBNb2RlbEZldGNoRXJyb3JBY3Rpb24gfSA9IHlpZWxkIHJhY2Uoe1xuXHRcdGZldGNoUmVzdWx0QWN0aW9uOiB0YWtlKHRha2VNYXRjaGVzTW9kZWxGZXRjaFJlY2VpdmVkKGdldFRva2VuTW9kZWxOYW1lKSksXG5cdFx0ZmV0Y2hFcnJvckFjdGlvbjogdGFrZSh0YWtlTWF0Y2hlc01vZGVsRmV0Y2hGYWlsZWQoZ2V0VG9rZW5Nb2RlbE5hbWUpKVxuXHR9KVxuXHQvLyBhbnkgZXJyb3IgcmVzcG9uc2Vcblx0aWYgKGZldGNoRXJyb3JBY3Rpb24pIHtcblx0XHQvLyBpZ25vcmUgc2VydmVyIGVycm9yc1xuXHRcdGlmIChcblx0XHRcdGZldGNoRXJyb3JBY3Rpb24uZXJyb3JEYXRhPy5zdGF0dXMgJiZcblx0XHRcdGZldGNoRXJyb3JBY3Rpb24uZXJyb3JEYXRhLnN0YXR1cyA+PSBIVFRQX1NUQVRVU19DT0RFLklOVEVSTkFMX1NFUlZFUl9FUlJPUlxuXHRcdCkge1xuXHRcdFx0cmV0dXJuIG9hdXRoVG9rZW5QYXJhbVxuXHRcdH1cblx0XHRyZXR1cm4gbnVsbFxuXHR9XG5cdC8vIGZvciBzb21lIHJlYXNvbiB0aGUgcmVzcG9uc2UgaGFkIG5vIGJvZHlcblx0aWYgKCFmZXRjaFJlc3VsdEFjdGlvbj8uZGF0YSkge1xuXHRcdHJldHVybiBudWxsXG5cdH1cblx0cmV0dXJuIGZldGNoUmVzdWx0QWN0aW9uLmRhdGFcbn1cblxuZXhwb3J0IGZ1bmN0aW9uKiBwZXJmb3JtVG9rZW5SZWZyZXNoKCk6IFNhZ2FJdGVyYXRvciB7XG5cdGlmIChyZWZyZXNoTG9jayB8fCAhb2F1dGhUb2tlbikge1xuXHRcdC8vIGFscmVhZHkgcmVmcmVzaGluZy4gd2FpdCBmb3IgdGhlIGN1cnJlbnQgcmVmcmVzaCB0byBzdWNjZWVkIG9yIGZhaWwuXG5cdFx0eWllbGQgcmFjZSh7XG5cdFx0XHRyZWZyZXNoU3VjY2VzczogdGFrZShBVVRIX1RPS0VOX1NVQ0NFU1NfQUNUSU9OX1RZUEUuVE9LRU5fUkVGUkVTSF9TVUNDRUVERUQpLFxuXHRcdFx0cmVmcmVzaEZhaWxlZDogdGFrZShBVVRIX0FDVElPTl9UWVBFLlRPS0VOX1JFRlJFU0hfRkFJTEVEKVxuXHRcdH0pXG5cdFx0cmV0dXJuXG5cdH1cblx0bG9nZ2VyLmRlYnVnKCdSZWZyZXNoaW5nIE9BdXRoIHRva2VuJylcblx0cmVmcmVzaExvY2sgPSB0cnVlXG5cdC8vIG9hdXRoVG9rZW4gd2lsbCBiZSBzZXQgdG86XG5cdC8vIDEuIG5ldyB0b2tlbiAoc3VjY2Vzcylcblx0Ly8gMi4gc2FtZSB0b2tlbiAoZmFpbGVkIGZyb20gdGltZW91dCBvciBzZXJ2ZXIgZXJyb3IpXG5cdC8vIDMuIG51bGwgKGZhaWwpXG5cdGNvbnN0IG9yaWdpbmFsQWNjZXNzVG9rZW4gPSBvYXV0aFRva2VuLmFjY2Vzc190b2tlblxuXHRvYXV0aFRva2VuID0geWllbGQgY2FsbChnZXRUb2tlbkZyb21SZWZyZXNoVG9rZW4sIG9hdXRoVG9rZW4pXG5cdGlmICghIW9hdXRoVG9rZW4gJiYgb2F1dGhUb2tlbi5hY2Nlc3NfdG9rZW4gIT09IG9yaWdpbmFsQWNjZXNzVG9rZW4pIHtcblx0XHRsb2dnZXIuZGVidWcoJ09BdXRoIHRva2VuIHJlZnJlc2hlZCcpXG5cdFx0eWllbGQgY2FsbCh0b2tlblBlcnNpc3RlbmNlU2VydmljZS5wZXJzaXN0VG9rZW4sIG9hdXRoVG9rZW4pXG5cdFx0eWllbGQgcHV0PEF1dGhUb2tlblN1Y2Nlc3NBY3Rpb24+KHsgdHlwZTogQVVUSF9UT0tFTl9TVUNDRVNTX0FDVElPTl9UWVBFLlRPS0VOX1JFRlJFU0hfU1VDQ0VFREVELCBvYXV0aFRva2VuIH0pXG5cdH0gZWxzZSBpZiAob2F1dGhUb2tlbiA9PT0gbnVsbCkge1xuXHRcdGxvZ2dlci5kZWJ1ZygnT0F1dGggdG9rZW4gZmFpbGVkIHRvIHJlZnJlc2gnKVxuXHRcdC8vIFRoaXMgc2hvdWxkIG5ldmVyIGhhcHBlbiBvdXRzaWRlIG9mIHRoZSB0b2tlbiBoYXZpbmcgYmVlbiByZXZva2VkIG9uIHRoZSBzZXJ2ZXIgc2lkZVxuXHRcdHlpZWxkIGFsbCh7XG5cdFx0XHRyZWZyZXNoRmFpbGVkOiBwdXQ8QXV0aEFjdGlvbj4oeyB0eXBlOiBBVVRIX0FDVElPTl9UWVBFLlRPS0VOX1JFRlJFU0hfRkFJTEVEIH0pLFxuXHRcdFx0bG9nT3V0OiBwdXQ8QXV0aEFjdGlvbj4oeyB0eXBlOiBBVVRIX0FDVElPTl9UWVBFLkxPR19PVVRfUkVRVUVTVEVEIH0pXG5cdFx0fSlcblx0fVxuXHRyZWZyZXNoTG9jayA9IGZhbHNlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiogbG9naW5GbG93KG1vZGVsRmV0Y2hSZXF1ZXN0QWN0aW9uOiBNb2RlbEZldGNoUmVxdWVzdEFjdGlvbik6IFNhZ2FJdGVyYXRvciB7XG5cdHlpZWxkIHB1dChtb2RlbEZldGNoUmVxdWVzdEFjdGlvbilcblx0Y29uc3Qge1xuXHRcdGZldGNoUmVzdWx0QWN0aW9uLFxuXHRcdGZldGNoRXJyb3JBY3Rpb25cblx0fTogeyBmZXRjaFJlc3VsdEFjdGlvbj86IE1vZGVsRmV0Y2hSZXN1bHRBY3Rpb247IGZldGNoRXJyb3JBY3Rpb24/OiBNb2RlbEZldGNoRXJyb3JBY3Rpb24gfSA9IHlpZWxkIHJhY2Uoe1xuXHRcdGZldGNoUmVzdWx0QWN0aW9uOiB0YWtlKHRha2VNYXRjaGVzTW9kZWxGZXRjaFJlY2VpdmVkKG1vZGVsRmV0Y2hSZXF1ZXN0QWN0aW9uLm1vZGVsTmFtZSkpLFxuXHRcdGZldGNoRXJyb3JBY3Rpb246IHRha2UodGFrZU1hdGNoZXNNb2RlbEZldGNoRmFpbGVkKG1vZGVsRmV0Y2hSZXF1ZXN0QWN0aW9uLm1vZGVsTmFtZSkpXG5cdH0pXG5cdGlmIChmZXRjaEVycm9yQWN0aW9uKSB7XG5cdFx0cmV0dXJuIG51bGxcblx0fVxuXHRjb25zdCBjb2RlOiBzdHJpbmcgfCB1bmRlZmluZWQgPSBmZXRjaFJlc3VsdEFjdGlvbj8uZGF0YT8uY29kZVxuXHRpZiAoIWNvZGUpIHtcblx0XHRyZXR1cm4gbnVsbFxuXHR9XG5cdHJldHVybiB5aWVsZCBjYWxsKGdldFRva2VuRnJvbUNvZGUsIGNvZGUpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiogY3JlZGVudGlhbHNMb2dpbkZsb3coXG5cdGFjdGlvbjogQXV0aENhc1YxTG9naW5SZXF1ZXN0QWN0aW9uIHwgQXV0aExvY2FsTG9naW5SZXF1ZXN0QWN0aW9uLFxuXHRtb2RlbE5hbWU6IHN0cmluZ1xuKTogU2FnYUl0ZXJhdG9yIHtcblx0Y29uc3QgbW9kZWxGZXRjaFJlcXVlc3RBY3Rpb246IE1vZGVsRmV0Y2hSZXF1ZXN0QWN0aW9uID0ge1xuXHRcdC8vIHNldCByZXF1aXJlZCBkZWZhdWx0c1xuXHRcdHR5cGU6IE1PREVMX0ZFVENIX1JFUVVFU1RfQUNUSU9OX1RZUEUuRkVUQ0hfUkVRVUVTVCxcblx0XHRtb2RlbE5hbWUsXG5cdFx0bm9TdG9yZTogdHJ1ZSxcblx0XHQvLyBmb3JjZSBubyByZXRyeVxuXHRcdG5vUmV0cnk6IHRydWUsXG5cdFx0Ly8gcGFzcyB0aHJ1IGJvZHlcblx0XHRib2R5OiBhY3Rpb24uYm9keVxuXHR9XG5cdHJldHVybiB5aWVsZCBjYWxsKGxvZ2luRmxvdywgbW9kZWxGZXRjaFJlcXVlc3RBY3Rpb24pXG59XG5cbmV4cG9ydCBmdW5jdGlvbiogY2FzVjFMb2dpbkZsb3coYWN0aW9uOiBBdXRoQ2FzVjFMb2dpblJlcXVlc3RBY3Rpb24pOiBTYWdhSXRlcmF0b3Ige1xuXHRyZXR1cm4geWllbGQgY2FsbChjcmVkZW50aWFsc0xvZ2luRmxvdywgYWN0aW9uLCAnY29kZUZyb21DYXNWMScpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiogbG9jYWxMb2dpbkZsb3coYWN0aW9uOiBBdXRoTG9jYWxMb2dpblJlcXVlc3RBY3Rpb24pOiBTYWdhSXRlcmF0b3Ige1xuXHRyZXR1cm4geWllbGQgY2FsbChjcmVkZW50aWFsc0xvZ2luRmxvdywgYWN0aW9uLCAnY29kZUZyb21Mb2NhbENyZWRlbnRpYWxzJylcbn1cblxuZXhwb3J0IGZ1bmN0aW9uKiBjYXNUaWNrZXRMb2dpbkZsb3codGlja2V0OiBzdHJpbmcsIHNlcnZpY2U6IHN0cmluZyk6IFNhZ2FJdGVyYXRvciB7XG5cdGNvbnN0IG1vZGVsRmV0Y2hSZXF1ZXN0QWN0aW9uOiBNb2RlbEZldGNoUmVxdWVzdEFjdGlvbiA9IHtcblx0XHR0eXBlOiBNT0RFTF9GRVRDSF9SRVFVRVNUX0FDVElPTl9UWVBFLkZFVENIX1JFUVVFU1QsXG5cdFx0bW9kZWxOYW1lOiAnY29kZUZyb21DYXNUaWNrZXQnLFxuXHRcdG5vU3RvcmU6IHRydWUsXG5cdFx0cXVlcnlQYXJhbXM6IHtcblx0XHRcdHRpY2tldCxcblx0XHRcdHNlcnZpY2Vcblx0XHR9XG5cdH1cblx0cmV0dXJuIHlpZWxkIGNhbGwobG9naW5GbG93LCBtb2RlbEZldGNoUmVxdWVzdEFjdGlvbilcbn1cblxuZXhwb3J0IGZ1bmN0aW9uKiBoYW5kbGVBdXRoRmFpbHVyZShhY3Rpb246IE1vZGVsRmV0Y2hFcnJvckFjdGlvbik6IFNhZ2FJdGVyYXRvciB7XG5cdC8vIFRoaXMgc2hvdWxkIGJlIHVubGlrZWx5IHNpbmNlIHdlIG5vcm1hbGx5IGhhdmUgYSByZWZyZXNoIHRva2VuIGxvb3AgaGFwcGVuaW5nXG5cdC8vIGJ1dCBpZiB0aGUgYXBwIGlzIGJhY2tncm91bmRlZCwgdGhlIGxvb3AgbWlnaHQgbm90IGJlIGNhdWdodCB1cCB5ZXRcblx0aWYgKG9hdXRoVG9rZW4gJiYgYWN0aW9uLmVycm9yRGF0YSAmJiBhY3Rpb24uZXJyb3JEYXRhLnN0YXR1cyA9PT0gSFRUUF9TVEFUVVNfQ09ERS5VTkFVVEhPUklaRUQpIHtcblx0XHRsb2dnZXIuZGVidWcoJ3Rva2VuIGV4cGlyZWQgLSByZWZyZXNoaW5nJylcblx0XHR5aWVsZCBjYWxsKHBlcmZvcm1Ub2tlblJlZnJlc2gpXG5cdH1cbn1cblxuZXhwb3J0IGNvbnN0IGdldE9BdXRoVG9rZW46IFRva2VuQWNjZXNzRnVuY3Rpb24gPSBmdW5jdGlvbiogKG1vZGVsTmFtZTogc3RyaW5nKSB7XG5cdC8vIERvbid0IHRyeSB0byByZWZyZXNoIHRoZSB0b2tlbiBpZiB3ZSdyZSBhbHJlYWR5IGluIGEgcmVxdWVzdCB0byByZWZyZXNoIHRoZSB0b2tlblxuXHRpZiAobW9kZWxOYW1lID09PSAnZ2V0VG9rZW4nKSB7XG5cdFx0cmV0dXJuIG51bGxcblx0fVxuXHRpZiAob2F1dGhUb2tlbiAmJiBvYXV0aFRva2VuWycuZXhwaXJlcyddKSB7XG5cdFx0Y29uc3QgdGhpcnR5U2Vjb25kc0Zyb21Ob3cgPSBuZXcgRGF0ZSgpXG5cdFx0dGhpcnR5U2Vjb25kc0Zyb21Ob3cuc2V0U2Vjb25kcyh0aGlydHlTZWNvbmRzRnJvbU5vdy5nZXRTZWNvbmRzKCkgKyAzMClcblx0XHRpZiAobmV3IERhdGUob2F1dGhUb2tlblsnLmV4cGlyZXMnXSkgPCB0aGlydHlTZWNvbmRzRnJvbU5vdykge1xuXHRcdFx0Ly8gc3RhcnQgYSB0b2tlbiByZWZyZXNoIGFuZCB3YWl0IGZvciB0aGUgc3VjY2VzcyBhY3Rpb24gaW4gY2FzZSBhbm90aGVyIHJlZnJlc2ggaXMgY3VycmVudGx5IGhhcHBlbmluZ1xuXHRcdFx0eWllbGQgY2FsbChwZXJmb3JtVG9rZW5SZWZyZXNoKVxuXHRcdFx0cmV0dXJuIG9hdXRoVG9rZW5cblx0XHR9XG5cdH1cblx0cmV0dXJuIG9hdXRoVG9rZW5cbn1cblxuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24qIGF1dGhTYWdhKFxuXHRjbGllbnRDcmVkZW50aWFsc1BhcmFtOiBDbGllbnRDcmVkZW50aWFscyxcblx0dG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2VQYXJhbTogVG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2UgPSBkZWZhdWx0VG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2UsXG5cdHRpY2tldFByb3ZpZGVyU2VydmljZTogVGlja2V0UHJvdmlkZXJTZXJ2aWNlID0gZGVmYXVsdFRpY2tldFByb3ZpZGVyU2VydmljZSxcblx0Y29kZVByb3ZpZGVyU2VydmljZTogQ29kZVByb3ZpZGVyU2VydmljZSA9IGRlZmF1bHRDb2RlUHJvdmlkZXJTZXJ2aWNlXG4pOiBTYWdhSXRlcmF0b3Ige1xuXHRsb2dnZXIgPSBnZXRMb2dnZXIoKVxuXG5cdGNsaWVudENyZWRlbnRpYWxzID0gY2xpZW50Q3JlZGVudGlhbHNQYXJhbVxuXHR0b2tlblBlcnNpc3RlbmNlU2VydmljZSA9IHRva2VuUGVyc2lzdGVuY2VTZXJ2aWNlUGFyYW1cblxuXHQvLyBUcnkgdG8gZ2V0IHBlcnNpc3RlZCB0b2tlbiAobm9ybWFsbHkgaW4gQXN5bmNTdG9yYWdlIG9yIExvY2FsU3RvcmFnZSlcblx0b2F1dGhUb2tlbiA9IHlpZWxkIGNhbGwodG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2UuZ2V0UGVyc2lzdGVkVG9rZW4pXG5cblx0Ly8gSWYgbm8gdG9rZW4sIHRyeSB0byBnZXQgQ0FTIHRpY2tldCAobm9ybWFsbHkgaW4gdGhlIFVSTCksIHVzZSBpdCB0byBnZXQgYSB0b2tlblxuXHRpZiAoIW9hdXRoVG9rZW4pIHtcblx0XHRjb25zdCBjYXNUaWNrZXQgPSB0aWNrZXRQcm92aWRlclNlcnZpY2UuZ2V0VGlja2V0KClcblx0XHR0aWNrZXRQcm92aWRlclNlcnZpY2UucmVtb3ZlVGlja2V0KClcblx0XHRjb25zdCBzZXJ2aWNlID0gdGlja2V0UHJvdmlkZXJTZXJ2aWNlLmdldEFwcFNlcnZpY2VOYW1lKClcblx0XHRpZiAoY2FzVGlja2V0ICYmIHNlcnZpY2UpIHtcblx0XHRcdG9hdXRoVG9rZW4gPSB5aWVsZCBjYWxsKGNhc1RpY2tldExvZ2luRmxvdywgY2FzVGlja2V0LCBzZXJ2aWNlKVxuXHRcdH1cblx0fVxuXG5cdC8vIElmIE9BdXRoIENvZGUgZXhpc3RzIChub3JtYWxseSBpbiB0aGUgVVJMKSwgdXNlIGl0IHRvIGdldCBhIHRva2VuXG5cdC8vIGUuZy4gTFRJLCBTaGliYm9sZXRoLCBGYWNlYm9vaywgR29vZ2xlXG5cdGNvbnN0IGNvZGUgPSBjb2RlUHJvdmlkZXJTZXJ2aWNlLmdldENvZGUoKVxuXHRpZiAoY29kZSkge1xuXHRcdC8vIExvZyBvdXQgdGhlIGN1cnJlbnQgdXNlciBpZiBhIG5ldyB0b2tlbiBpcyBhYm91dCB0byBiZSBnZW5lcmF0ZWQgZnJvbSB0aGUgT0F1dGggQ29kZVxuXHRcdGlmIChvYXV0aFRva2VuKSB7XG5cdFx0XHR5aWVsZCBhbGwoe1xuXHRcdFx0XHRjbGVhclVzZXJEYXRhOiBwdXQ8TW9kZWxSZW1vdmVLZXlBY3Rpb24+KHsgdHlwZTogTU9ERUxfUkVNT1ZFX0tFWV9BQ1RJT05fVFlQRSwgbW9kZWxQYXRoOiAndXNlcicgfSksXG5cdFx0XHRcdGNsZWFyUGVyc2lzdGVudFRva2VuOiBjYWxsKHRva2VuUGVyc2lzdGVuY2VTZXJ2aWNlLnBlcnNpc3RUb2tlbiwgbnVsbClcblx0XHRcdH0pXG5cdFx0XHRvYXV0aFRva2VuID0gbnVsbFxuXHRcdH1cblx0XHRvYXV0aFRva2VuID0geWllbGQgY2FsbChnZXRUb2tlbkZyb21Db2RlLCBjb2RlKVxuXHR9XG5cdGNvZGVQcm92aWRlclNlcnZpY2UucmVtb3ZlQ29kZSgpXG5cblx0eWllbGQgcHV0PEF1dGhUb2tlbkFjdGlvbj4oeyB0eXBlOiBBVVRIX1RPS0VOX0FDVElPTl9UWVBFLkFVVEhfSU5JVElBTElaRUQsIG9hdXRoVG9rZW4gfSlcblxuXHR5aWVsZCB0YWtlRXZlcnkoTU9ERUxfRkVUQ0hfRVJST1JfQUNUSU9OX1RZUEUuVFJZX0ZFVENIX0ZBSUxFRCwgaGFuZGxlQXV0aEZhaWx1cmUpXG5cblx0ZG8ge1xuXHRcdGlmICghb2F1dGhUb2tlbikge1xuXHRcdFx0Y29uc3Qge1xuXHRcdFx0XHRjYXNWMUFjdGlvbixcblx0XHRcdFx0bG9jYWxMb2dpbkFjdGlvblxuXHRcdFx0fToge1xuXHRcdFx0XHRjYXNWMUFjdGlvbj86IEF1dGhDYXNWMUxvZ2luUmVxdWVzdEFjdGlvblxuXHRcdFx0XHRsb2NhbExvZ2luQWN0aW9uPzogQXV0aExvY2FsTG9naW5SZXF1ZXN0QWN0aW9uXG5cdFx0XHR9ID0geWllbGQgcmFjZSh7XG5cdFx0XHRcdGNhc1YxQWN0aW9uOiB0YWtlKEFVVEhfQ0FTX1YxX0xPR0lOX1JFUVVFU1RfQUNUSU9OX1RZUEUuQ0FTX1YxX0xPR0lOX1JFUVVFU1QpLFxuXHRcdFx0XHRsb2NhbExvZ2luQWN0aW9uOiB0YWtlKEFVVEhfTE9DQUxfTE9HSU5fUkVRVUVTVF9BQ1RJT05fVFlQRS5MT0NBTF9MT0dJTl9SRVFVRVNUKVxuXHRcdFx0fSlcblxuXHRcdFx0eWllbGQgcHV0PEF1dGhBY3Rpb24+KHsgdHlwZTogQVVUSF9BQ1RJT05fVFlQRS5MT0dJTl9SRVFVRVNURUQgfSlcblx0XHRcdGlmIChjYXNWMUFjdGlvbikge1xuXHRcdFx0XHRvYXV0aFRva2VuID0geWllbGQgY2FsbChjYXNWMUxvZ2luRmxvdywgY2FzVjFBY3Rpb24pXG5cdFx0XHR9IGVsc2UgaWYgKGxvY2FsTG9naW5BY3Rpb24pIHtcblx0XHRcdFx0b2F1dGhUb2tlbiA9IHlpZWxkIGNhbGwobG9jYWxMb2dpbkZsb3csIGxvY2FsTG9naW5BY3Rpb24pXG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKG9hdXRoVG9rZW4pIHtcblx0XHRcdHlpZWxkIGNhbGwodG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2UucGVyc2lzdFRva2VuLCBvYXV0aFRva2VuKVxuXHRcdFx0eWllbGQgYWxsKHtcblx0XHRcdFx0bG9naW5TdWNjZXNzOiBwdXQ8QXV0aFRva2VuU3VjY2Vzc0FjdGlvbj4oe1xuXHRcdFx0XHRcdHR5cGU6IEFVVEhfVE9LRU5fU1VDQ0VTU19BQ1RJT05fVFlQRS5HRVRfVE9LRU5fU1VDQ0VFREVELFxuXHRcdFx0XHRcdG9hdXRoVG9rZW5cblx0XHRcdFx0fSksXG5cdFx0XHRcdGdldFVzZXJJbmZvOiBwdXQ8TW9kZWxGZXRjaFJlcXVlc3RBY3Rpb24+KHtcblx0XHRcdFx0XHR0eXBlOiBNT0RFTF9GRVRDSF9SRVFVRVNUX0FDVElPTl9UWVBFLkZFVENIX1JFUVVFU1QsXG5cdFx0XHRcdFx0bW9kZWxOYW1lOiAndXNlci51c2VySW5mbydcblx0XHRcdFx0fSksXG5cdFx0XHRcdGxvZ091dDogdGFrZShBVVRIX0FDVElPTl9UWVBFLkxPR19PVVRfUkVRVUVTVEVEKVxuXHRcdFx0fSlcblx0XHR9IGVsc2Uge1xuXHRcdFx0eWllbGQgcHV0PEF1dGhBY3Rpb24+KHsgdHlwZTogQVVUSF9BQ1RJT05fVFlQRS5MT0dJTl9GQUlMRUQgfSlcblx0XHR9XG5cblx0XHR5aWVsZCBhbGwoe1xuXHRcdFx0Y2xlYXJVc2VyRGF0YTogcHV0PE1vZGVsUmVtb3ZlS2V5QWN0aW9uPih7IHR5cGU6IE1PREVMX1JFTU9WRV9LRVlfQUNUSU9OX1RZUEUsIG1vZGVsUGF0aDogJ3VzZXInIH0pLFxuXHRcdFx0Y2xlYXJQZXJzaXN0ZW50VG9rZW46IGNhbGwodG9rZW5QZXJzaXN0ZW5jZVNlcnZpY2UucGVyc2lzdFRva2VuLCBudWxsKVxuXHRcdH0pXG5cdFx0b2F1dGhUb2tlbiA9IG51bGxcblx0fSB3aGlsZSAodHJ1ZSlcbn1cbiJdLCJtYXBwaW5ncyI6IkFBRUEsU0FBU0EsR0FBRyxFQUFFQyxJQUFJLEVBQUVDLEdBQUcsRUFBRUMsSUFBSSxFQUFFQyxJQUFJLEVBQUVDLFNBQVMsUUFBUSxvQkFBb0I7QUFDMUUsU0FBU0MsbUJBQW1CLElBQUlDLDBCQUEwQixRQUFRLG9DQUFvQztBQUN0RyxTQUFTQyxxQkFBcUIsSUFBSUMsNEJBQTRCLFFBQVEsc0NBQXNDO0FBQzVHLFNBQVNDLHVCQUF1QixJQUFJQyw4QkFBOEIsUUFBUSx3Q0FBd0M7QUFDbEgsU0FHQ0MsZ0JBQWdCLFFBTVYsYUFBYTtBQUNwQixTQUFTQyxTQUFTLFFBQWdCLG9CQUFvQjtBQUN0RCxTQUNDQyxnQkFBZ0IsRUFDaEJDLHFDQUFxQyxFQUNyQ0Msb0NBQW9DLEVBQ3BDQyxzQkFBc0IsRUFDdEJDLDhCQUE4QixFQU05QkMsZ0NBQWdDLEVBQ2hDQyxpQ0FBaUMsRUFDakNDLDZCQUE2QixFQUM3QkMsK0JBQStCLEVBQy9CQyw0QkFBNEIsUUFLdEIsWUFBWTs7QUFFbkI7O0FBRUEsT0FBTyxNQUFNQyx5QkFBeUIsR0FB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