sintfacilis 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (461) hide show
  1. package/.env.example +2 -0
  2. package/.eslintrc.js +20 -0
  3. package/.github/workflows/deploy-docs.yml +27 -0
  4. package/.github/workflows/pre-release-tests.yml +45 -0
  5. package/.github/workflows/pull-request-tests.yml +45 -0
  6. package/.prettierignore +2 -0
  7. package/.prettierrc +19 -0
  8. package/.vscode/launch.json +24 -0
  9. package/.vscode/settings.json +3 -0
  10. package/codecov.yml +7 -0
  11. package/demos/.eslintrc.js +13 -0
  12. package/demos/ago-node-cli/README.md +29 -0
  13. package/demos/ago-node-cli/ago.js +33 -0
  14. package/demos/ago-node-cli/index.js +11 -0
  15. package/demos/ago-node-cli/lib/item-export-command.js +48 -0
  16. package/demos/ago-node-cli/lib/item-search-command.js +35 -0
  17. package/demos/ago-node-cli/package-lock.json +430 -0
  18. package/demos/ago-node-cli/package.json +30 -0
  19. package/demos/attachments/README.md +5 -0
  20. package/demos/attachments/index.html +165 -0
  21. package/demos/attachments/package-lock.json +543 -0
  22. package/demos/attachments/package.json +18 -0
  23. package/demos/batch-geocoder-node/NYC_Restaurant_Inspection_Results.csv +100 -0
  24. package/demos/batch-geocoder-node/README.md +15 -0
  25. package/demos/batch-geocoder-node/batch-geocode.js +115 -0
  26. package/demos/batch-geocoder-node/config-template.js +18 -0
  27. package/demos/batch-geocoder-node/package-lock.json +336 -0
  28. package/demos/batch-geocoder-node/package.json +37 -0
  29. package/demos/express/README.md +15 -0
  30. package/demos/express/config.json.template +3 -0
  31. package/demos/express/package-lock.json +1008 -0
  32. package/demos/express/package.json +18 -0
  33. package/demos/express/server.js +33 -0
  34. package/demos/feature-service-browser/README.md +6 -0
  35. package/demos/feature-service-browser/index.html +122 -0
  36. package/demos/feature-service-browser/package-lock.json +543 -0
  37. package/demos/feature-service-browser/package.json +18 -0
  38. package/demos/geocoder-browser/README.md +10 -0
  39. package/demos/geocoder-browser/config.js.template +1 -0
  40. package/demos/geocoder-browser/index.html +131 -0
  41. package/demos/geocoder-browser/package-lock.json +610 -0
  42. package/demos/geocoder-browser/package.json +19 -0
  43. package/demos/geocoder-browser/post-sign-in.html +25 -0
  44. package/demos/jsapi-integration/README.md +25 -0
  45. package/demos/jsapi-integration/config.js +6 -0
  46. package/demos/jsapi-integration/index.html +93 -0
  47. package/demos/jsapi-integration/package-lock.json +247 -0
  48. package/demos/jsapi-integration/package.json +19 -0
  49. package/demos/node-cli-item-management/README.md +10 -0
  50. package/demos/node-cli-item-management/index.js +238 -0
  51. package/demos/node-cli-item-management/package-lock.json +432 -0
  52. package/demos/node-cli-item-management/package.json +27 -0
  53. package/demos/node-cli-item-management/screenshot.png +0 -0
  54. package/demos/oauth2-browser/README.md +14 -0
  55. package/demos/oauth2-browser/authenticate.html +30 -0
  56. package/demos/oauth2-browser/config.js.template +6 -0
  57. package/demos/oauth2-browser/index.html +211 -0
  58. package/demos/oauth2-browser/logo.svg +4 -0
  59. package/demos/oauth2-browser/package-lock.json +474 -0
  60. package/demos/oauth2-browser/package.json +18 -0
  61. package/demos/oauth2-browser/style.css +36 -0
  62. package/demos/oauth2-browser-retry/README.md +25 -0
  63. package/demos/oauth2-browser-retry/authenticate.html +22 -0
  64. package/demos/oauth2-browser-retry/index.html +116 -0
  65. package/demos/oauth2-browser-retry/logo.svg +4 -0
  66. package/demos/stream-response-to-file/README.md +7 -0
  67. package/demos/stream-response-to-file/index.js +36 -0
  68. package/demos/stream-response-to-file/output/.gitkeep +0 -0
  69. package/demos/stream-response-to-file/package-lock.json +227 -0
  70. package/demos/stream-response-to-file/package.json +33 -0
  71. package/demos/tree-shaking-rollup/.babelrc +3 -0
  72. package/demos/tree-shaking-rollup/README.md +9 -0
  73. package/demos/tree-shaking-rollup/index.html +11 -0
  74. package/demos/tree-shaking-rollup/package-lock.json +5646 -0
  75. package/demos/tree-shaking-rollup/package.json +25 -0
  76. package/demos/tree-shaking-rollup/rollup.config.js +17 -0
  77. package/demos/tree-shaking-rollup/src/index.js +8 -0
  78. package/demos/tree-shaking-webpack/README.md +8 -0
  79. package/demos/tree-shaking-webpack/index.html +11 -0
  80. package/demos/tree-shaking-webpack/package-lock.json +11455 -0
  81. package/demos/tree-shaking-webpack/package.json +24 -0
  82. package/demos/tree-shaking-webpack/src/index.js +10 -0
  83. package/demos/tree-shaking-webpack/webpack.config.js +27 -0
  84. package/demos/vue/.env.example +11 -0
  85. package/demos/vue/.eslintrc.js +17 -0
  86. package/demos/vue/.postcssrc.js +5 -0
  87. package/demos/vue/README.md +17 -0
  88. package/demos/vue/babel.config.js +3 -0
  89. package/demos/vue/package-lock.json +28044 -0
  90. package/demos/vue/package.json +33 -0
  91. package/demos/vue/public/favicon.ico +0 -0
  92. package/demos/vue/public/index.html +24 -0
  93. package/demos/vue/src/assets/logo.svg +29 -0
  94. package/demos/vue/src/components/App.vue +305 -0
  95. package/demos/vue/src/components/Authenticate.vue +65 -0
  96. package/demos/vue/src/components/Loader.vue +230 -0
  97. package/demos/vue/src/main.js +92 -0
  98. package/demos/webmap-checker-sapper/.env.example +5 -0
  99. package/demos/webmap-checker-sapper/README.md +123 -0
  100. package/demos/webmap-checker-sapper/appveyor.yml +18 -0
  101. package/demos/webmap-checker-sapper/cypress/fixtures/example.json +5 -0
  102. package/demos/webmap-checker-sapper/cypress/integration/spec.js +19 -0
  103. package/demos/webmap-checker-sapper/cypress/plugins/index.js +17 -0
  104. package/demos/webmap-checker-sapper/cypress/support/commands.js +25 -0
  105. package/demos/webmap-checker-sapper/cypress/support/index.js +20 -0
  106. package/demos/webmap-checker-sapper/cypress.json +4 -0
  107. package/demos/webmap-checker-sapper/package-lock.json +9622 -0
  108. package/demos/webmap-checker-sapper/package.json +50 -0
  109. package/demos/webmap-checker-sapper/rollup.config.js +87 -0
  110. package/demos/webmap-checker-sapper/src/client.js +20 -0
  111. package/demos/webmap-checker-sapper/src/components/LayerStatus.html +108 -0
  112. package/demos/webmap-checker-sapper/src/components/Nav.html +21 -0
  113. package/demos/webmap-checker-sapper/src/components/WebMap.html +62 -0
  114. package/demos/webmap-checker-sapper/src/routes/_error.html +41 -0
  115. package/demos/webmap-checker-sapper/src/routes/_layout.html +21 -0
  116. package/demos/webmap-checker-sapper/src/routes/auth/authorize.js +18 -0
  117. package/demos/webmap-checker-sapper/src/routes/auth/exchange-token.js +20 -0
  118. package/demos/webmap-checker-sapper/src/routes/auth/post-sign-in.js +24 -0
  119. package/demos/webmap-checker-sapper/src/routes/auth/sign-out.js +10 -0
  120. package/demos/webmap-checker-sapper/src/routes/index.html +20 -0
  121. package/demos/webmap-checker-sapper/src/routes/webmaps/[webmapId].html +83 -0
  122. package/demos/webmap-checker-sapper/src/routes/webmaps/index.html +59 -0
  123. package/demos/webmap-checker-sapper/src/server.js +101 -0
  124. package/demos/webmap-checker-sapper/src/service-worker.js +82 -0
  125. package/demos/webmap-checker-sapper/src/template.html +33 -0
  126. package/demos/webmap-checker-sapper/src/userInfoMiddleware.js +21 -0
  127. package/demos/webmap-checker-sapper/src/utils.js +33 -0
  128. package/demos/webmap-checker-sapper/static/favicon.png +0 -0
  129. package/demos/webmap-checker-sapper/static/global.css +36 -0
  130. package/demos/webmap-checker-sapper/static/manifest.json +20 -0
  131. package/demos/webmap-checker-sapper/static/svelte-logo-192.png +0 -0
  132. package/demos/webmap-checker-sapper/static/svelte-logo-512.png +0 -0
  133. package/docs/.eslintrc.js +12 -0
  134. package/docs/FAQ.md +48 -0
  135. package/docs/HISTORY.md +62 -0
  136. package/docs/acetate.config.js +262 -0
  137. package/docs/build-typedoc.js +434 -0
  138. package/docs/generate-srihashes.js +53 -0
  139. package/docs/src/_layout.html +86 -0
  140. package/docs/src/api/_declaration.html +600 -0
  141. package/docs/src/api/_layout.html +204 -0
  142. package/docs/src/api/_package.html +38 -0
  143. package/docs/src/api/index.html +16 -0
  144. package/docs/src/guides/_layout.html +24 -0
  145. package/docs/src/guides/amd-requirejs-dojo.md +40 -0
  146. package/docs/src/guides/browser-authentication.md +39 -0
  147. package/docs/src/guides/bundlers.md +52 -0
  148. package/docs/src/guides/cli-authentication.md +9 -0
  149. package/docs/src/guides/client-server-authentication.md +9 -0
  150. package/docs/src/guides/embedded-apps.md +106 -0
  151. package/docs/src/guides/from-a-cdn.md +38 -0
  152. package/docs/src/guides/index.md +59 -0
  153. package/docs/src/guides/node.md +104 -0
  154. package/docs/src/guides/package-overview.md +111 -0
  155. package/docs/src/guides/server-authentication.md +9 -0
  156. package/docs/src/guides/whats-new-v2-0.md +305 -0
  157. package/docs/src/img/icons.png +0 -0
  158. package/docs/src/img/icons@2x.png +0 -0
  159. package/docs/src/img/oauth-browser.png +0 -0
  160. package/docs/src/index.html +12 -0
  161. package/docs/src/js/api-search.js +112 -0
  162. package/docs/src/js/nav-toggle.js +41 -0
  163. package/docs/src/sass/_highlight.scss +96 -0
  164. package/docs/src/sass/_icons.scss +157 -0
  165. package/docs/src/sass/style.scss +242 -0
  166. package/docs/src/srihashes.json +12 -0
  167. package/jasmine.json +7 -0
  168. package/jasmine.live.json +7 -0
  169. package/karma.conf.js +107 -0
  170. package/lerna.json +8 -0
  171. package/notes/README.md +68 -0
  172. package/package.json +141 -0
  173. package/packages/arcgis-rest-auth/README.md +71 -0
  174. package/packages/arcgis-rest-auth/package.json +69 -0
  175. package/packages/arcgis-rest-auth/post-message-auth-spec.md +70 -0
  176. package/packages/arcgis-rest-auth/src/ApiKey.ts +41 -0
  177. package/packages/arcgis-rest-auth/src/ApplicationSession.ts +122 -0
  178. package/packages/arcgis-rest-auth/src/UserSession.ts +1355 -0
  179. package/packages/arcgis-rest-auth/src/app-tokens.ts +131 -0
  180. package/packages/arcgis-rest-auth/src/authenticated-request-options.ts +24 -0
  181. package/packages/arcgis-rest-auth/src/federation-utils.ts +85 -0
  182. package/packages/arcgis-rest-auth/src/fetch-token.ts +50 -0
  183. package/packages/arcgis-rest-auth/src/generate-token.ts +35 -0
  184. package/packages/arcgis-rest-auth/src/index.ts +13 -0
  185. package/packages/arcgis-rest-auth/src/validate-app-access.ts +68 -0
  186. package/packages/arcgis-rest-auth/test/ApiKey.test.ts +35 -0
  187. package/packages/arcgis-rest-auth/test/ApplicationSession.test.ts +124 -0
  188. package/packages/arcgis-rest-auth/test/UserSession.test.ts +2377 -0
  189. package/packages/arcgis-rest-auth/test/app-tokens.test.ts +95 -0
  190. package/packages/arcgis-rest-auth/test/federation-utils.test.ts +323 -0
  191. package/packages/arcgis-rest-auth/test/fetchToken.test.ts +112 -0
  192. package/packages/arcgis-rest-auth/test/generateToken.test.ts +102 -0
  193. package/packages/arcgis-rest-auth/test/utils.ts +14 -0
  194. package/packages/arcgis-rest-auth/test/validate-app-access.test.ts +46 -0
  195. package/packages/arcgis-rest-auth/tsconfig.json +6 -0
  196. package/packages/arcgis-rest-demographics/README.md +75 -0
  197. package/packages/arcgis-rest-demographics/package.json +69 -0
  198. package/packages/arcgis-rest-demographics/src/getAvailableCountries.ts +113 -0
  199. package/packages/arcgis-rest-demographics/src/getAvailableDataCollections.ts +166 -0
  200. package/packages/arcgis-rest-demographics/src/getAvailableGeographyLevels.ts +88 -0
  201. package/packages/arcgis-rest-demographics/src/getGeography.ts +152 -0
  202. package/packages/arcgis-rest-demographics/src/helpers.ts +28 -0
  203. package/packages/arcgis-rest-demographics/src/index.ts +8 -0
  204. package/packages/arcgis-rest-demographics/src/queryDemographicData.ts +106 -0
  205. package/packages/arcgis-rest-demographics/test/getAvailableCountries.test.ts +92 -0
  206. package/packages/arcgis-rest-demographics/test/getAvailableDataCollections.test.ts +115 -0
  207. package/packages/arcgis-rest-demographics/test/getAvailableGeographyLevels.test.ts +72 -0
  208. package/packages/arcgis-rest-demographics/test/getGeography.test.ts +141 -0
  209. package/packages/arcgis-rest-demographics/test/mocks/responses.ts +4 -0
  210. package/packages/arcgis-rest-demographics/test/queryDemographicData.test.live.ts +42 -0
  211. package/packages/arcgis-rest-demographics/test/queryDemographicData.test.ts +113 -0
  212. package/packages/arcgis-rest-demographics/tsconfig.json +6 -0
  213. package/packages/arcgis-rest-feature-layer/README.md +77 -0
  214. package/packages/arcgis-rest-feature-layer/package.json +64 -0
  215. package/packages/arcgis-rest-feature-layer/src/add.ts +56 -0
  216. package/packages/arcgis-rest-feature-layer/src/addAttachment.ts +53 -0
  217. package/packages/arcgis-rest-feature-layer/src/applyEdits.ts +95 -0
  218. package/packages/arcgis-rest-feature-layer/src/decodeValues.ts +122 -0
  219. package/packages/arcgis-rest-feature-layer/src/delete.ts +61 -0
  220. package/packages/arcgis-rest-feature-layer/src/deleteAttachments.ts +52 -0
  221. package/packages/arcgis-rest-feature-layer/src/getAllLayersAndTables.ts +30 -0
  222. package/packages/arcgis-rest-feature-layer/src/getAttachments.ts +55 -0
  223. package/packages/arcgis-rest-feature-layer/src/getLayer.ts +24 -0
  224. package/packages/arcgis-rest-feature-layer/src/getService.ts +26 -0
  225. package/packages/arcgis-rest-feature-layer/src/helpers.ts +97 -0
  226. package/packages/arcgis-rest-feature-layer/src/index.ts +32 -0
  227. package/packages/arcgis-rest-feature-layer/src/query.ts +204 -0
  228. package/packages/arcgis-rest-feature-layer/src/queryRelated.ts +89 -0
  229. package/packages/arcgis-rest-feature-layer/src/update.ts +60 -0
  230. package/packages/arcgis-rest-feature-layer/src/updateAttachment.ts +59 -0
  231. package/packages/arcgis-rest-feature-layer/test/attachments.test.ts +200 -0
  232. package/packages/arcgis-rest-feature-layer/test/crud.test.ts +197 -0
  233. package/packages/arcgis-rest-feature-layer/test/decodeValues.test.ts +67 -0
  234. package/packages/arcgis-rest-feature-layer/test/getAllLayersAndTables.test.ts +28 -0
  235. package/packages/arcgis-rest-feature-layer/test/getLayer.test.ts +31 -0
  236. package/packages/arcgis-rest-feature-layer/test/getService.test.ts +31 -0
  237. package/packages/arcgis-rest-feature-layer/test/helpers.test.ts +25 -0
  238. package/packages/arcgis-rest-feature-layer/test/mocks/allLayersAndTablesResponse.ts +906 -0
  239. package/packages/arcgis-rest-feature-layer/test/mocks/cvdQueryResponse.ts +225 -0
  240. package/packages/arcgis-rest-feature-layer/test/mocks/feature.ts +302 -0
  241. package/packages/arcgis-rest-feature-layer/test/mocks/fields.ts +779 -0
  242. package/packages/arcgis-rest-feature-layer/test/mocks/foo.txt +1 -0
  243. package/packages/arcgis-rest-feature-layer/test/mocks/service.ts +398 -0
  244. package/packages/arcgis-rest-feature-layer/test/query.test.ts +167 -0
  245. package/packages/arcgis-rest-feature-layer/tsconfig.json +6 -0
  246. package/packages/arcgis-rest-geocoding/README.md +86 -0
  247. package/packages/arcgis-rest-geocoding/package.json +66 -0
  248. package/packages/arcgis-rest-geocoding/src/bulk.ts +104 -0
  249. package/packages/arcgis-rest-geocoding/src/geocode.ts +166 -0
  250. package/packages/arcgis-rest-geocoding/src/helpers.ts +56 -0
  251. package/packages/arcgis-rest-geocoding/src/index.ts +15 -0
  252. package/packages/arcgis-rest-geocoding/src/reverse.ts +84 -0
  253. package/packages/arcgis-rest-geocoding/src/suggest.ts +45 -0
  254. package/packages/arcgis-rest-geocoding/test/bulk.test.ts +194 -0
  255. package/packages/arcgis-rest-geocoding/test/geocode.test.ts +253 -0
  256. package/packages/arcgis-rest-geocoding/test/helpers.test.ts +85 -0
  257. package/packages/arcgis-rest-geocoding/test/mocks/responses.ts +591 -0
  258. package/packages/arcgis-rest-geocoding/test/reverse.test.ts +126 -0
  259. package/packages/arcgis-rest-geocoding/test/suggest.test.ts +53 -0
  260. package/packages/arcgis-rest-geocoding/tsconfig.json +6 -0
  261. package/packages/arcgis-rest-portal/README.md +73 -0
  262. package/packages/arcgis-rest-portal/package.json +64 -0
  263. package/packages/arcgis-rest-portal/src/groups/add-users.ts +140 -0
  264. package/packages/arcgis-rest-portal/src/groups/create.ts +43 -0
  265. package/packages/arcgis-rest-portal/src/groups/get.ts +184 -0
  266. package/packages/arcgis-rest-portal/src/groups/helpers.ts +14 -0
  267. package/packages/arcgis-rest-portal/src/groups/invite-users.ts +127 -0
  268. package/packages/arcgis-rest-portal/src/groups/join.ts +57 -0
  269. package/packages/arcgis-rest-portal/src/groups/notification.ts +77 -0
  270. package/packages/arcgis-rest-portal/src/groups/protect.ts +56 -0
  271. package/packages/arcgis-rest-portal/src/groups/remove-users.ts +76 -0
  272. package/packages/arcgis-rest-portal/src/groups/remove.ts +32 -0
  273. package/packages/arcgis-rest-portal/src/groups/search.ts +47 -0
  274. package/packages/arcgis-rest-portal/src/groups/update-user-membership.ts +63 -0
  275. package/packages/arcgis-rest-portal/src/groups/update.ts +39 -0
  276. package/packages/arcgis-rest-portal/src/index.ts +69 -0
  277. package/packages/arcgis-rest-portal/src/items/add.ts +138 -0
  278. package/packages/arcgis-rest-portal/src/items/content.ts +67 -0
  279. package/packages/arcgis-rest-portal/src/items/create.ts +150 -0
  280. package/packages/arcgis-rest-portal/src/items/export.ts +80 -0
  281. package/packages/arcgis-rest-portal/src/items/get.ts +437 -0
  282. package/packages/arcgis-rest-portal/src/items/helpers.ts +292 -0
  283. package/packages/arcgis-rest-portal/src/items/protect.ts +41 -0
  284. package/packages/arcgis-rest-portal/src/items/reassign.ts +61 -0
  285. package/packages/arcgis-rest-portal/src/items/remove.ts +141 -0
  286. package/packages/arcgis-rest-portal/src/items/search.ts +25 -0
  287. package/packages/arcgis-rest-portal/src/items/update.ts +185 -0
  288. package/packages/arcgis-rest-portal/src/items/upload.ts +125 -0
  289. package/packages/arcgis-rest-portal/src/orgs/notification.ts +131 -0
  290. package/packages/arcgis-rest-portal/src/services/get-unique-service-name.ts +35 -0
  291. package/packages/arcgis-rest-portal/src/services/is-service-name-available.ts +30 -0
  292. package/packages/arcgis-rest-portal/src/sharing/access.ts +84 -0
  293. package/packages/arcgis-rest-portal/src/sharing/helpers.ts +81 -0
  294. package/packages/arcgis-rest-portal/src/sharing/is-item-shared-with-group.ts +42 -0
  295. package/packages/arcgis-rest-portal/src/sharing/share-item-with-group.ts +336 -0
  296. package/packages/arcgis-rest-portal/src/sharing/unshare-item-with-group.ts +105 -0
  297. package/packages/arcgis-rest-portal/src/users/get-user-tags.ts +52 -0
  298. package/packages/arcgis-rest-portal/src/users/get-user-url.ts +18 -0
  299. package/packages/arcgis-rest-portal/src/users/get-user.ts +58 -0
  300. package/packages/arcgis-rest-portal/src/users/invitation.ts +156 -0
  301. package/packages/arcgis-rest-portal/src/users/notification.ts +68 -0
  302. package/packages/arcgis-rest-portal/src/users/search-users.ts +37 -0
  303. package/packages/arcgis-rest-portal/src/users/update.ts +66 -0
  304. package/packages/arcgis-rest-portal/src/util/SearchQueryBuilder.ts +391 -0
  305. package/packages/arcgis-rest-portal/src/util/array.ts +16 -0
  306. package/packages/arcgis-rest-portal/src/util/generic-search.ts +99 -0
  307. package/packages/arcgis-rest-portal/src/util/get-portal-settings.ts +45 -0
  308. package/packages/arcgis-rest-portal/src/util/get-portal-url.ts +28 -0
  309. package/packages/arcgis-rest-portal/src/util/get-portal.ts +53 -0
  310. package/packages/arcgis-rest-portal/src/util/get-subscription-info.ts +43 -0
  311. package/packages/arcgis-rest-portal/src/util/scrub-control-chars.ts +13 -0
  312. package/packages/arcgis-rest-portal/src/util/search.ts +42 -0
  313. package/packages/arcgis-rest-portal/test/groups/add-users.test.ts +239 -0
  314. package/packages/arcgis-rest-portal/test/groups/crud.test.ts +180 -0
  315. package/packages/arcgis-rest-portal/test/groups/get.test.ts +176 -0
  316. package/packages/arcgis-rest-portal/test/groups/invite-users.test.ts +146 -0
  317. package/packages/arcgis-rest-portal/test/groups/join.test.ts +72 -0
  318. package/packages/arcgis-rest-portal/test/groups/notification.test.ts +112 -0
  319. package/packages/arcgis-rest-portal/test/groups/protect.test.ts +72 -0
  320. package/packages/arcgis-rest-portal/test/groups/remove-users.test.ts +140 -0
  321. package/packages/arcgis-rest-portal/test/groups/search.test.ts +151 -0
  322. package/packages/arcgis-rest-portal/test/groups/update-user-membership.test.ts +62 -0
  323. package/packages/arcgis-rest-portal/test/items/add.test.ts +323 -0
  324. package/packages/arcgis-rest-portal/test/items/content.test.ts +156 -0
  325. package/packages/arcgis-rest-portal/test/items/create.test.ts +400 -0
  326. package/packages/arcgis-rest-portal/test/items/export.test.ts +122 -0
  327. package/packages/arcgis-rest-portal/test/items/get.test.ts +583 -0
  328. package/packages/arcgis-rest-portal/test/items/helpers.test.ts +60 -0
  329. package/packages/arcgis-rest-portal/test/items/protect.test.ts +122 -0
  330. package/packages/arcgis-rest-portal/test/items/reassign.test.ts +131 -0
  331. package/packages/arcgis-rest-portal/test/items/remove.test.ts +261 -0
  332. package/packages/arcgis-rest-portal/test/items/search.test.ts +275 -0
  333. package/packages/arcgis-rest-portal/test/items/update.test.ts +556 -0
  334. package/packages/arcgis-rest-portal/test/items/upload.test.ts +282 -0
  335. package/packages/arcgis-rest-portal/test/mocks/groups/responses.ts +208 -0
  336. package/packages/arcgis-rest-portal/test/mocks/items/foo.zip +0 -0
  337. package/packages/arcgis-rest-portal/test/mocks/items/item.ts +526 -0
  338. package/packages/arcgis-rest-portal/test/mocks/items/resources.ts +38 -0
  339. package/packages/arcgis-rest-portal/test/mocks/items/search.ts +121 -0
  340. package/packages/arcgis-rest-portal/test/mocks/portal/response.ts +126 -0
  341. package/packages/arcgis-rest-portal/test/mocks/portal/settings-response.ts +56 -0
  342. package/packages/arcgis-rest-portal/test/mocks/sharing/sharing.ts +18 -0
  343. package/packages/arcgis-rest-portal/test/mocks/users/invitation.ts +70 -0
  344. package/packages/arcgis-rest-portal/test/mocks/users/notification.ts +34 -0
  345. package/packages/arcgis-rest-portal/test/mocks/users/user-search.ts +388 -0
  346. package/packages/arcgis-rest-portal/test/mocks/users/user-tags.ts +5 -0
  347. package/packages/arcgis-rest-portal/test/mocks/users/user.ts +174 -0
  348. package/packages/arcgis-rest-portal/test/orgs/notification.test.ts +144 -0
  349. package/packages/arcgis-rest-portal/test/services/get-unique-service-name.test.ts +59 -0
  350. package/packages/arcgis-rest-portal/test/services/is-service-name-available.test.ts +46 -0
  351. package/packages/arcgis-rest-portal/test/sharing/access.test.ts +162 -0
  352. package/packages/arcgis-rest-portal/test/sharing/helpers.test.ts +55 -0
  353. package/packages/arcgis-rest-portal/test/sharing/share-item-with-group.test.ts +1328 -0
  354. package/packages/arcgis-rest-portal/test/sharing/unshare-item-with-group.test.ts +288 -0
  355. package/packages/arcgis-rest-portal/test/users/get-user-tags.test.ts +71 -0
  356. package/packages/arcgis-rest-portal/test/users/get-user-url.test.ts +40 -0
  357. package/packages/arcgis-rest-portal/test/users/get-user.test.ts +90 -0
  358. package/packages/arcgis-rest-portal/test/users/invitation.test.ts +127 -0
  359. package/packages/arcgis-rest-portal/test/users/notification.test.ts +77 -0
  360. package/packages/arcgis-rest-portal/test/users/search.test.ts +42 -0
  361. package/packages/arcgis-rest-portal/test/users/update.test.ts +151 -0
  362. package/packages/arcgis-rest-portal/test/util/SearchQueryBuilder.test.ts +340 -0
  363. package/packages/arcgis-rest-portal/test/util/array.test.ts +30 -0
  364. package/packages/arcgis-rest-portal/test/util/get-portal-settings.test.ts +68 -0
  365. package/packages/arcgis-rest-portal/test/util/get-portal-url.test.ts +37 -0
  366. package/packages/arcgis-rest-portal/test/util/portal.test.ts +148 -0
  367. package/packages/arcgis-rest-portal/test/util/scrub-control-chars.test.ts +22 -0
  368. package/packages/arcgis-rest-portal/tsconfig.json +6 -0
  369. package/packages/arcgis-rest-request/README.md +72 -0
  370. package/packages/arcgis-rest-request/package.json +60 -0
  371. package/packages/arcgis-rest-request/src/index.ts +25 -0
  372. package/packages/arcgis-rest-request/src/request.ts +433 -0
  373. package/packages/arcgis-rest-request/src/utils/ArcGISRequestError.ts +76 -0
  374. package/packages/arcgis-rest-request/src/utils/ErrorTypes.ts +29 -0
  375. package/packages/arcgis-rest-request/src/utils/GrantTypes.ts +5 -0
  376. package/packages/arcgis-rest-request/src/utils/HTTPMethods.ts +6 -0
  377. package/packages/arcgis-rest-request/src/utils/IAuthenticationManager.ts +22 -0
  378. package/packages/arcgis-rest-request/src/utils/IFetchTokenParams.ts +11 -0
  379. package/packages/arcgis-rest-request/src/utils/IGenerateTokenParams.ts +9 -0
  380. package/packages/arcgis-rest-request/src/utils/IParamBuilder.ts +3 -0
  381. package/packages/arcgis-rest-request/src/utils/IParams.ts +6 -0
  382. package/packages/arcgis-rest-request/src/utils/IParamsBuilder.ts +5 -0
  383. package/packages/arcgis-rest-request/src/utils/IRequestOptions.ts +54 -0
  384. package/packages/arcgis-rest-request/src/utils/ITokenRequestOptions.ts +9 -0
  385. package/packages/arcgis-rest-request/src/utils/ResponseFormats.ts +10 -0
  386. package/packages/arcgis-rest-request/src/utils/append-custom-params.ts +49 -0
  387. package/packages/arcgis-rest-request/src/utils/clean-url.ts +20 -0
  388. package/packages/arcgis-rest-request/src/utils/decode-query-string.ts +27 -0
  389. package/packages/arcgis-rest-request/src/utils/encode-form-data.ts +38 -0
  390. package/packages/arcgis-rest-request/src/utils/encode-query-string.ts +35 -0
  391. package/packages/arcgis-rest-request/src/utils/process-params.ts +109 -0
  392. package/packages/arcgis-rest-request/src/utils/retryAuthError.ts +10 -0
  393. package/packages/arcgis-rest-request/src/utils/warn.ts +11 -0
  394. package/packages/arcgis-rest-request/src/utils/with-options.ts +48 -0
  395. package/packages/arcgis-rest-request/test/mocks/errors.ts +76 -0
  396. package/packages/arcgis-rest-request/test/mocks/geojson-feature-collection.ts +13 -0
  397. package/packages/arcgis-rest-request/test/mocks/param-builder.ts +7 -0
  398. package/packages/arcgis-rest-request/test/mocks/sharing-rest-info.ts +41 -0
  399. package/packages/arcgis-rest-request/test/mocks/webmap.ts +41 -0
  400. package/packages/arcgis-rest-request/test/request.test.ts +621 -0
  401. package/packages/arcgis-rest-request/test/utils/ArcGISAuthError.test.ts +191 -0
  402. package/packages/arcgis-rest-request/test/utils/ArcGISRequestError.test.ts +51 -0
  403. package/packages/arcgis-rest-request/test/utils/check-for-errors.test.ts +111 -0
  404. package/packages/arcgis-rest-request/test/utils/clean-url.test.ts +50 -0
  405. package/packages/arcgis-rest-request/test/utils/encode-form-data.test.ts +133 -0
  406. package/packages/arcgis-rest-request/test/utils/encode-query-string.test.ts +18 -0
  407. package/packages/arcgis-rest-request/test/utils/process-params.test.ts +205 -0
  408. package/packages/arcgis-rest-request/test/utils/with-options.test.ts +133 -0
  409. package/packages/arcgis-rest-request/tsconfig.json +4 -0
  410. package/packages/arcgis-rest-routing/README.md +75 -0
  411. package/packages/arcgis-rest-routing/package.json +65 -0
  412. package/packages/arcgis-rest-routing/src/closestFacility.ts +225 -0
  413. package/packages/arcgis-rest-routing/src/helpers.ts +104 -0
  414. package/packages/arcgis-rest-routing/src/index.ts +14 -0
  415. package/packages/arcgis-rest-routing/src/originDestinationMatrix.ts +223 -0
  416. package/packages/arcgis-rest-routing/src/serviceArea.ts +173 -0
  417. package/packages/arcgis-rest-routing/src/solveRoute.ts +180 -0
  418. package/packages/arcgis-rest-routing/test/closestFacility.test.ts +683 -0
  419. package/packages/arcgis-rest-routing/test/mocks/inputs.ts +132 -0
  420. package/packages/arcgis-rest-routing/test/mocks/responses.ts +13316 -0
  421. package/packages/arcgis-rest-routing/test/originDestinationMatrix.test.ts +795 -0
  422. package/packages/arcgis-rest-routing/test/serviceArea.test.ts +601 -0
  423. package/packages/arcgis-rest-routing/test/solveRoute.test.ts +677 -0
  424. package/packages/arcgis-rest-routing/tsconfig.json +6 -0
  425. package/packages/arcgis-rest-service-admin/README.md +73 -0
  426. package/packages/arcgis-rest-service-admin/package.json +65 -0
  427. package/packages/arcgis-rest-service-admin/src/addTo.ts +70 -0
  428. package/packages/arcgis-rest-service-admin/src/create.ts +189 -0
  429. package/packages/arcgis-rest-service-admin/src/get-service-admin-info.ts +34 -0
  430. package/packages/arcgis-rest-service-admin/src/get-view-sources.ts +20 -0
  431. package/packages/arcgis-rest-service-admin/src/index.ts +14 -0
  432. package/packages/arcgis-rest-service-admin/src/update.ts +50 -0
  433. package/packages/arcgis-rest-service-admin/test/addTo.test.ts +350 -0
  434. package/packages/arcgis-rest-service-admin/test/create.test.ts +294 -0
  435. package/packages/arcgis-rest-service-admin/test/get-service-admin-info.test.ts +37 -0
  436. package/packages/arcgis-rest-service-admin/test/get-view-sources.test.ts +40 -0
  437. package/packages/arcgis-rest-service-admin/test/mocks/layerDefinition.ts +79 -0
  438. package/packages/arcgis-rest-service-admin/test/mocks/service.ts +81 -0
  439. package/packages/arcgis-rest-service-admin/test/update.test.ts +115 -0
  440. package/packages/arcgis-rest-service-admin/tsconfig.json +5 -0
  441. package/packages/arcgis-rest-types/README.md +66 -0
  442. package/packages/arcgis-rest-types/package.json +54 -0
  443. package/packages/arcgis-rest-types/src/feature.ts +42 -0
  444. package/packages/arcgis-rest-types/src/geometry.ts +272 -0
  445. package/packages/arcgis-rest-types/src/group.ts +72 -0
  446. package/packages/arcgis-rest-types/src/index.ts +9 -0
  447. package/packages/arcgis-rest-types/src/item.ts +81 -0
  448. package/packages/arcgis-rest-types/src/service.ts +156 -0
  449. package/packages/arcgis-rest-types/src/statisticDefinition.ts +33 -0
  450. package/packages/arcgis-rest-types/src/symbol.ts +170 -0
  451. package/packages/arcgis-rest-types/src/user.ts +49 -0
  452. package/packages/arcgis-rest-types/src/webmap.ts +1405 -0
  453. package/packages/arcgis-rest-types/tsconfig.json +10 -0
  454. package/support/changelog.js +393 -0
  455. package/support/deploy-doc-site.js +16 -0
  456. package/support/dev.sh +6 -0
  457. package/support/publish.sh +47 -0
  458. package/support/test-helpers.js +9 -0
  459. package/tsconfig.json +63 -0
  460. package/umd-base-profile.js +81 -0
  461. package/umd-production-profile.js +13 -0
@@ -0,0 +1,1355 @@
1
+ /* Copyright (c) 2017-2019 Environmental Systems Research Institute, Inc.
2
+ * Apache-2.0 */
3
+
4
+ /**
5
+ * /generateToken returns a token that cannot be refreshed.
6
+ *
7
+ * oauth2/token can return a token *and* a refreshToken.
8
+ * up until the refreshToken expires, you can use it (and a clientId)
9
+ * to fetch fresh credentials without a username and password.
10
+ *
11
+ * the catch is that this 'authorization_code' flow is only utilized
12
+ * by server based OAuth 2 Node.js applications that call /authorize first.
13
+ */
14
+
15
+ import * as http from "http";
16
+ import {
17
+ request,
18
+ IRequestOptions,
19
+ ArcGISAuthError,
20
+ IAuthenticationManager,
21
+ ITokenRequestOptions,
22
+ cleanUrl,
23
+ encodeQueryString,
24
+ decodeQueryString,
25
+ } from "@esri/arcgis-rest-request";
26
+ import { IUser } from "@esri/arcgis-rest-types";
27
+ import { generateToken } from "./generate-token";
28
+ import { fetchToken, IFetchTokenResponse } from "./fetch-token";
29
+ import { canUseOnlineToken, isFederated } from "./federation-utils";
30
+ import { IAppAccess, validateAppAccess } from "./validate-app-access";
31
+
32
+ /**
33
+ * Internal utility for resolving a Promise from outside its constructor.
34
+ *
35
+ * See: http://lea.verou.me/2016/12/resolve-promises-externally-with-this-one-weird-trick/
36
+ */
37
+ interface IDeferred<T> {
38
+ promise: Promise<T>;
39
+ resolve: (v: T) => void;
40
+ reject: (v: any) => void;
41
+ }
42
+
43
+ export type AuthenticationProvider =
44
+ | "arcgis"
45
+ | "facebook"
46
+ | "google"
47
+ | "github"
48
+ | "apple";
49
+
50
+ /**
51
+ * Represents a [credential](https://developers.arcgis.com/javascript/latest/api-reference/esri-identity-Credential.html)
52
+ * object used to access a secure ArcGIS resource.
53
+ */
54
+ export interface ICredential {
55
+ expires: number;
56
+ server: string;
57
+ ssl: boolean;
58
+ token: string;
59
+ userId: string;
60
+ }
61
+
62
+ function defer<T>(): IDeferred<T> {
63
+ const deferred: any = {
64
+ promise: null,
65
+ resolve: null,
66
+ reject: null,
67
+ };
68
+
69
+ deferred.promise = new Promise((resolve, reject) => {
70
+ deferred.resolve = resolve;
71
+ deferred.reject = reject;
72
+ });
73
+
74
+ return deferred as IDeferred<T>;
75
+ }
76
+
77
+ /**
78
+ * Options for static OAuth 2.0 helper methods on `UserSession`.
79
+ */
80
+ export interface IOAuth2Options {
81
+ /**
82
+ * Client ID of your application. Can be obtained by registering an application
83
+ * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
84
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
85
+ */
86
+ clientId: string;
87
+
88
+ /**
89
+ * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
90
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
91
+ */
92
+ redirectUri: string;
93
+
94
+ /**
95
+ * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal.
96
+ */
97
+ portal?: string;
98
+
99
+ /**
100
+ * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page.
101
+ */
102
+
103
+ provider?: AuthenticationProvider;
104
+
105
+ /**
106
+ * The requested validity in minutes for a token. Defaults to 20160 (two weeks).
107
+ */
108
+ expiration?: number;
109
+
110
+ /**
111
+ * Duration (in minutes) that a token will be valid. Defaults to 20160 (two weeks).
112
+ *
113
+ * @deprecated use 'expiration' instead
114
+ */
115
+ duration?: number;
116
+
117
+ /**
118
+ * Determines whether to open the authorization window in a new tab/window or in the current window.
119
+ *
120
+ * @browserOnly
121
+ */
122
+ popup?: boolean;
123
+
124
+ /**
125
+ * The window features passed to [window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) when `popup` is true. Defaults to `height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes`
126
+ *
127
+ * @browserOnly
128
+ */
129
+ popupWindowFeatures?: string;
130
+
131
+ /**
132
+ * Duration (in minutes) that a refresh token will be valid.
133
+ *
134
+ * @nodeOnly
135
+ */
136
+ refreshTokenTTL?: number;
137
+
138
+ /**
139
+ * The locale assumed to render the login page.
140
+ *
141
+ * @browserOnly
142
+ */
143
+ locale?: string;
144
+
145
+ /**
146
+ * Applications can specify an opaque value for this parameter to correlate the authorization request sent with the received response. By default, clientId is used.
147
+ *
148
+ * @browserOnly
149
+ */
150
+ state?: string;
151
+
152
+ [key: string]: any;
153
+ }
154
+
155
+ /**
156
+ * Options for the `UserSession` constructor.
157
+ */
158
+ export interface IUserSessionOptions {
159
+ /**
160
+ * Client ID of your application. Can be obtained by registering an application
161
+ * on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
162
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
163
+ */
164
+ clientId?: string;
165
+
166
+ /**
167
+ * A valid URL to redirect to after a user authorizes your application. Can be set on [ArcGIS for Developers](https://developers.arcgis.com/documentation/core-concepts/security-and-authentication/signing-in-arcgis-online-users/#registering-your-application),
168
+ * [ArcGIS Online](http://doc.arcgis.com/en/arcgis-online/share-maps/add-items.htm#ESRI_SECTION1_0D1B620254F745AE84F394289F8AF44B) or on your instance of ArcGIS Enterprise.
169
+ */
170
+ redirectUri?: string;
171
+
172
+ /**
173
+ * OAuth 2.0 refresh token from a previous user session.
174
+ */
175
+ refreshToken?: string;
176
+
177
+ /**
178
+ * Expiration date of the `refreshToken`
179
+ */
180
+ refreshTokenExpires?: Date;
181
+
182
+ /**
183
+ * The authenticated user's username. Guaranteed to be unique across ArcGIS Online or your instance of ArcGIS Enterprise.
184
+ */
185
+ username?: string;
186
+
187
+ /**
188
+ * Password for this user. Used in CLI apps where users cannot do OAuth 2.0.
189
+ */
190
+ password?: string;
191
+
192
+ /**
193
+ * OAuth 2.0 access token from a previous user session.
194
+ */
195
+ token?: string;
196
+
197
+ /**
198
+ * Expiration date for the `token`
199
+ */
200
+ tokenExpires?: Date;
201
+
202
+ /**
203
+ * The ArcGIS Online or ArcGIS Enterprise portal you want to use for authentication. Defaults to `https://www.arcgis.com/sharing/rest` for the ArcGIS Online portal.
204
+ */
205
+ portal?: string;
206
+
207
+ /**
208
+ * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https.
209
+ */
210
+ ssl?: boolean;
211
+
212
+ /**
213
+ * ArcGIS Authentication is used by default. Specifying an alternative will take users directly to the corresponding provider's OAuth page.
214
+ */
215
+ provider?: AuthenticationProvider;
216
+
217
+ /**
218
+ * Duration of requested token validity in minutes. Used when requesting tokens with `username` and `password` or when validating the identity of unknown servers. Defaults to two weeks.
219
+ */
220
+ tokenDuration?: number;
221
+
222
+ /**
223
+ * Duration (in minutes) that a refresh token will be valid.
224
+ */
225
+ refreshTokenTTL?: number;
226
+
227
+ /**
228
+ * An unfederated ArcGIS Server instance known to recognize credentials supplied manually.
229
+ * ```js
230
+ * {
231
+ * server: "https://sampleserver6.arcgisonline.com/arcgis",
232
+ * token: "SOSlV3v..",
233
+ * tokenExpires: new Date(1545415669763)
234
+ * }
235
+ * ```
236
+ */
237
+ server?: string;
238
+ }
239
+
240
+ /**
241
+ * ```js
242
+ * import { UserSession } from '@esri/arcgis-rest-auth';
243
+ * UserSession.beginOAuth2({
244
+ * // register an app of your own to create a unique clientId
245
+ * clientId: "abc123",
246
+ * redirectUri: 'https://yourapp.com/authenticate.html'
247
+ * })
248
+ * .then(session)
249
+ * // or
250
+ * new UserSession({
251
+ * username: "jsmith",
252
+ * password: "123456"
253
+ * })
254
+ * // or
255
+ * UserSession.deserialize(cache)
256
+ * ```
257
+ * Used to authenticate both ArcGIS Online and ArcGIS Enterprise users. `UserSession` includes helper methods for [OAuth 2.0](/arcgis-rest-js/guides/browser-authentication/) in both browser and server applications.
258
+ */
259
+ export class UserSession implements IAuthenticationManager {
260
+ /**
261
+ * The current ArcGIS Online or ArcGIS Enterprise `token`.
262
+ */
263
+ get token() {
264
+ return this._token;
265
+ }
266
+
267
+ /**
268
+ * The expiration time of the current `token`.
269
+ */
270
+ get tokenExpires() {
271
+ return this._tokenExpires;
272
+ }
273
+
274
+ /**
275
+ * The current token to ArcGIS Online or ArcGIS Enterprise.
276
+ */
277
+ get refreshToken() {
278
+ return this._refreshToken;
279
+ }
280
+
281
+ /**
282
+ * The expiration time of the current `refreshToken`.
283
+ */
284
+ get refreshTokenExpires() {
285
+ return this._refreshTokenExpires;
286
+ }
287
+
288
+ /**
289
+ * Deprecated, use `federatedServers` instead.
290
+ *
291
+ * @deprecated
292
+ */
293
+ get trustedServers() {
294
+ console.log("DEPRECATED: use federatedServers instead");
295
+ return this.federatedServers;
296
+ }
297
+
298
+ /**
299
+ * Begins a new browser-based OAuth 2.0 sign in. If `options.popup` is `true` the
300
+ * authentication window will open in a new tab/window and the function will return
301
+ * Promise&lt;UserSession&gt;. Otherwise, the user will be redirected to the
302
+ * authorization page in their current tab/window and the function will return `undefined`.
303
+ *
304
+ * @browserOnly
305
+ */
306
+ /* istanbul ignore next */
307
+ public static beginOAuth2(options: IOAuth2Options, win: any = window): Promise<UserSession> | undefined {
308
+
309
+ if(options.duration) {
310
+ console.log("DEPRECATED: 'duration' is deprecated - use 'expiration' instead");
311
+ }
312
+
313
+ const {
314
+ portal,
315
+ provider,
316
+ clientId,
317
+ expiration,
318
+ redirectUri,
319
+ popup,
320
+ popupWindowFeatures,
321
+ state,
322
+ locale,
323
+ params,
324
+ }: IOAuth2Options = {
325
+ ...{
326
+ portal: "https://www.arcgis.com/sharing/rest",
327
+ provider: "arcgis",
328
+ expiration: 20160,
329
+ popup: true,
330
+ popupWindowFeatures:
331
+ "height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes",
332
+ state: options.clientId,
333
+ locale: "",
334
+ },
335
+ ...options,
336
+ };
337
+ let url: string;
338
+ if (provider === "arcgis") {
339
+ url = `${portal}/oauth2/authorize?client_id=${clientId}&response_type=token&expiration=${options.duration || expiration}&redirect_uri=${encodeURIComponent(
340
+ redirectUri
341
+ )}&state=${state}&locale=${locale}`;
342
+ } else {
343
+ url = `${portal}/oauth2/social/authorize?client_id=${clientId}&socialLoginProviderName=${provider}&autoAccountCreateForSocial=true&response_type=token&expiration=${options.duration || expiration}&redirect_uri=${encodeURIComponent(
344
+ redirectUri
345
+ )}&state=${state}&locale=${locale}`;
346
+ }
347
+
348
+ // append additional params
349
+ if (params) {
350
+ url = `${url}&${encodeQueryString(params)}`;
351
+ }
352
+
353
+ if (!popup) {
354
+ win.location.href = url;
355
+ return undefined;
356
+ }
357
+
358
+ const session = defer<UserSession>();
359
+
360
+ win[`__ESRI_REST_AUTH_HANDLER_${clientId}`] = function(
361
+ errorString: any,
362
+ oauthInfoString: string
363
+ ) {
364
+ if (errorString) {
365
+ const error = JSON.parse(errorString);
366
+ session.reject(new ArcGISAuthError(error.errorMessage, error.error));
367
+ return;
368
+ }
369
+
370
+ if (oauthInfoString) {
371
+ const oauthInfo = JSON.parse(oauthInfoString);
372
+ session.resolve(
373
+ new UserSession({
374
+ clientId,
375
+ portal,
376
+ ssl: oauthInfo.ssl,
377
+ token: oauthInfo.token,
378
+ tokenExpires: new Date(oauthInfo.expires),
379
+ username: oauthInfo.username,
380
+ })
381
+ );
382
+ }
383
+ };
384
+
385
+ win.open(url, "oauth-window", popupWindowFeatures);
386
+
387
+ return session.promise;
388
+ }
389
+
390
+ /**
391
+ * Completes a browser-based OAuth 2.0 sign in. If `options.popup` is `true` the user
392
+ * will be returned to the previous window. Otherwise a new `UserSession`
393
+ * will be returned. You must pass the same values for `options.popup` and
394
+ * `options.portal` as you used in `beginOAuth2()`.
395
+ *
396
+ * @browserOnly
397
+ */
398
+ /* istanbul ignore next */
399
+ public static completeOAuth2(options: IOAuth2Options, win: any = window) {
400
+ const { portal, clientId, popup }: IOAuth2Options = {
401
+ ...{ portal: "https://www.arcgis.com/sharing/rest", popup: true },
402
+ ...options,
403
+ };
404
+
405
+ function completeSignIn(error: any, oauthInfo?: IFetchTokenResponse) {
406
+ try {
407
+ let handlerFn;
408
+ const handlerFnName = `__ESRI_REST_AUTH_HANDLER_${clientId}`;
409
+
410
+ if (popup) {
411
+ // Guard b/c IE does not support window.opener
412
+ if (win.opener) {
413
+ if (win.opener.parent && win.opener.parent[handlerFnName]) {
414
+ handlerFn = win.opener.parent[handlerFnName];
415
+ } else if (win.opener && win.opener[handlerFnName]) {
416
+ // support pop-out oauth from within an iframe
417
+ handlerFn = win.opener[handlerFnName];
418
+ }
419
+ } else {
420
+ // IE
421
+ if (win !== win.parent && win.parent && win.parent[handlerFnName]) {
422
+ handlerFn = win.parent[handlerFnName];
423
+ }
424
+ }
425
+ // if we have a handler fn, call it and close the window
426
+ if (handlerFn) {
427
+ handlerFn(
428
+ error ? JSON.stringify(error) : undefined,
429
+ JSON.stringify(oauthInfo)
430
+ );
431
+ win.close();
432
+ return undefined;
433
+ }
434
+ }
435
+ } catch (e) {
436
+ throw new ArcGISAuthError(
437
+ `Unable to complete authentication. It's possible you specified popup based oAuth2 but no handler from "beginOAuth2()" present. This generally happens because the "popup" option differs between "beginOAuth2()" and "completeOAuth2()".`
438
+ );
439
+ }
440
+
441
+ if (error) {
442
+ throw new ArcGISAuthError(error.errorMessage, error.error);
443
+ }
444
+
445
+ return new UserSession({
446
+ clientId,
447
+ portal,
448
+ ssl: oauthInfo.ssl,
449
+ token: oauthInfo.token,
450
+ tokenExpires: oauthInfo.expires,
451
+ username: oauthInfo.username,
452
+ });
453
+ }
454
+
455
+ const params = decodeQueryString(win.location.hash);
456
+
457
+ if (!params.access_token) {
458
+ let error;
459
+ let errorMessage = "Unknown error";
460
+
461
+ if (params.error) {
462
+ error = params.error;
463
+ errorMessage = params.error_description;
464
+ }
465
+
466
+ return completeSignIn({ error, errorMessage });
467
+ }
468
+
469
+ const token = params.access_token;
470
+ const expires = new Date(
471
+ Date.now() + parseInt(params.expires_in, 10) * 1000 - 60 * 1000
472
+ );
473
+ const username = params.username;
474
+ const ssl = params.ssl === "true";
475
+
476
+ return completeSignIn(undefined, {
477
+ token,
478
+ expires,
479
+ ssl,
480
+ username,
481
+ });
482
+ }
483
+
484
+ /**
485
+ * Request session information from the parent application
486
+ *
487
+ * When an application is embedded into another application via an IFrame, the embedded app can
488
+ * use `window.postMessage` to request credentials from the host application. This function wraps
489
+ * that behavior.
490
+ *
491
+ * The ArcGIS API for Javascript has this built into the Identity Manager as of the 4.19 release.
492
+ *
493
+ * Note: The parent application will not respond if the embedded app's origin is not:
494
+ * - the same origin as the parent or *.arcgis.com (JSAPI)
495
+ * - in the list of valid child origins (REST-JS)
496
+ *
497
+ *
498
+ * @param parentOrigin origin of the parent frame. Passed into the embedded application as `parentOrigin` query param
499
+ * @browserOnly
500
+ */
501
+ public static fromParent(parentOrigin: string, win?: any): Promise<any> {
502
+ /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
503
+ if (!win && window) {
504
+ win = window;
505
+ }
506
+ // Declare handler outside of promise scope so we can detach it
507
+ let handler: (event: any) => void;
508
+ // return a promise that will resolve when the handler receives
509
+ // session information from the correct origin
510
+ return new Promise((resolve, reject) => {
511
+ // create an event handler that just wraps the parentMessageHandler
512
+ handler = (event: any) => {
513
+ // ensure we only listen to events from the parent
514
+ if (event.source === win.parent && event.data) {
515
+ try {
516
+ return resolve(UserSession.parentMessageHandler(event));
517
+ } catch (err) {
518
+ return reject(err);
519
+ }
520
+ }
521
+ };
522
+ // add listener
523
+ win.addEventListener("message", handler, false);
524
+ win.parent.postMessage(
525
+ { type: "arcgis:auth:requestCredential" },
526
+ parentOrigin
527
+ );
528
+ }).then((session) => {
529
+ win.removeEventListener("message", handler, false);
530
+ return session;
531
+ });
532
+ }
533
+
534
+ /**
535
+ * Begins a new server-based OAuth 2.0 sign in. This will redirect the user to
536
+ * the ArcGIS Online or ArcGIS Enterprise authorization page.
537
+ *
538
+ * @nodeOnly
539
+ */
540
+ public static authorize(
541
+ options: IOAuth2Options,
542
+ response: http.ServerResponse
543
+ ) {
544
+ if(options.duration) {
545
+ console.log("DEPRECATED: 'duration' is deprecated - use 'expiration' instead");
546
+ }
547
+ const { portal, clientId, expiration, redirectUri }: IOAuth2Options = {
548
+ ...{ portal: "https://arcgis.com/sharing/rest", expiration: 20160 },
549
+ ...options,
550
+ };
551
+
552
+ response.writeHead(301, {
553
+ Location: `${portal}/oauth2/authorize?client_id=${clientId}&expiration=${options.duration || expiration}&response_type=code&redirect_uri=${encodeURIComponent(
554
+ redirectUri
555
+ )}`,
556
+ });
557
+
558
+ response.end();
559
+ }
560
+
561
+ /**
562
+ * Completes the server-based OAuth 2.0 sign in process by exchanging the `authorizationCode`
563
+ * for a `access_token`.
564
+ *
565
+ * @nodeOnly
566
+ */
567
+ public static exchangeAuthorizationCode(
568
+ options: IOAuth2Options,
569
+ authorizationCode: string
570
+ ): Promise<UserSession> {
571
+ const { portal, clientId, redirectUri, refreshTokenTTL }: IOAuth2Options = {
572
+ ...{
573
+ portal: "https://www.arcgis.com/sharing/rest",
574
+ refreshTokenTTL: 20160,
575
+ },
576
+ ...options,
577
+ };
578
+
579
+ return fetchToken(`${portal}/oauth2/token`, {
580
+ params: {
581
+ grant_type: "authorization_code",
582
+ client_id: clientId,
583
+ redirect_uri: redirectUri,
584
+ code: authorizationCode,
585
+ },
586
+ }).then((response) => {
587
+ return new UserSession({
588
+ clientId,
589
+ portal,
590
+ ssl: response.ssl,
591
+ redirectUri,
592
+ refreshToken: response.refreshToken,
593
+ refreshTokenTTL,
594
+ refreshTokenExpires: new Date(
595
+ Date.now() + (refreshTokenTTL - 1) * 60 * 1000
596
+ ),
597
+ token: response.token,
598
+ tokenExpires: response.expires,
599
+ username: response.username,
600
+ });
601
+ });
602
+ }
603
+
604
+ public static deserialize(str: string) {
605
+ const options = JSON.parse(str);
606
+ return new UserSession({
607
+ clientId: options.clientId,
608
+ refreshToken: options.refreshToken,
609
+ refreshTokenExpires: new Date(options.refreshTokenExpires),
610
+ username: options.username,
611
+ password: options.password,
612
+ token: options.token,
613
+ tokenExpires: new Date(options.tokenExpires),
614
+ portal: options.portal,
615
+ ssl: options.ssl,
616
+ tokenDuration: options.tokenDuration,
617
+ redirectUri: options.redirectUri,
618
+ refreshTokenTTL: options.refreshTokenTTL,
619
+ });
620
+ }
621
+
622
+ /**
623
+ * Translates authentication from the format used in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
624
+ *
625
+ * ```js
626
+ * UserSession.fromCredential({
627
+ * userId: "jsmith",
628
+ * token: "secret"
629
+ * });
630
+ * ```
631
+ *
632
+ * @returns UserSession
633
+ */
634
+ public static fromCredential(credential: ICredential) {
635
+ // At ArcGIS Online 9.1, credentials no longer include the ssl and expires properties
636
+ // Here, we provide default values for them to cover this condition
637
+ const ssl = typeof credential.ssl !== "undefined" ? credential.ssl : true;
638
+ const expires = credential.expires || Date.now() + 7200000 /* 2 hours */;
639
+
640
+ return new UserSession({
641
+ portal: credential.server.includes("sharing/rest")
642
+ ? credential.server
643
+ : credential.server + `/sharing/rest`,
644
+ ssl,
645
+ token: credential.token,
646
+ username: credential.userId,
647
+ tokenExpires: new Date(expires),
648
+ });
649
+ }
650
+
651
+ /**
652
+ * Handle the response from the parent
653
+ * @param event DOM Event
654
+ */
655
+ private static parentMessageHandler(event: any): UserSession {
656
+ if (event.data.type === "arcgis:auth:credential") {
657
+ return UserSession.fromCredential(event.data.credential);
658
+ }
659
+ if (event.data.type === "arcgis:auth:error") {
660
+ const err = new Error(event.data.error.message);
661
+ err.name = event.data.error.name;
662
+ throw err;
663
+ } else {
664
+ throw new Error("Unknown message type.");
665
+ }
666
+ }
667
+
668
+ /**
669
+ * Client ID being used for authentication if provided in the `constructor`.
670
+ */
671
+ public readonly clientId: string;
672
+
673
+ /**
674
+ * The currently authenticated user if provided in the `constructor`.
675
+ */
676
+ public readonly username: string;
677
+
678
+ /**
679
+ * The currently authenticated user's password if provided in the `constructor`.
680
+ */
681
+ public readonly password: string;
682
+
683
+ /**
684
+ * The current portal the user is authenticated with.
685
+ */
686
+ public readonly portal: string;
687
+
688
+ /**
689
+ * This value is set to true automatically if the ArcGIS Organization requires that requests be made over https.
690
+ */
691
+ public readonly ssl: boolean;
692
+
693
+ /**
694
+ * The authentication provider to use.
695
+ */
696
+ public readonly provider: AuthenticationProvider;
697
+
698
+ /**
699
+ * Determines how long new tokens requested are valid.
700
+ */
701
+ public readonly tokenDuration: number;
702
+
703
+ /**
704
+ * A valid redirect URI for this application if provided in the `constructor`.
705
+ */
706
+ public readonly redirectUri: string;
707
+
708
+ /**
709
+ * Duration of new OAuth 2.0 refresh token validity (in minutes).
710
+ */
711
+ public readonly refreshTokenTTL: number;
712
+
713
+ /**
714
+ * An unfederated ArcGIS Server instance known to recognize credentials supplied manually.
715
+ * ```js
716
+ * {
717
+ * server: "https://sampleserver6.arcgisonline.com/arcgis",
718
+ * token: "SOSlV3v..",
719
+ * tokenExpires: new Date(1545415669763)
720
+ * }
721
+ * ```
722
+ */
723
+ public readonly server: string;
724
+
725
+ /**
726
+ * Hydrated by a call to [getUser()](#getUser-summary).
727
+ */
728
+ private _user: IUser;
729
+
730
+ /**
731
+ * Hydrated by a call to [getPortal()](#getPortal-summary).
732
+ */
733
+ private _portalInfo: any;
734
+
735
+ private _token: string;
736
+ private _tokenExpires: Date;
737
+ private _refreshToken: string;
738
+ private _refreshTokenExpires: Date;
739
+ private _pendingUserRequest: Promise<IUser>;
740
+ private _pendingPortalRequest: Promise<any>;
741
+
742
+ /**
743
+ * Internal object to keep track of pending token requests. Used to prevent
744
+ * duplicate token requests.
745
+ */
746
+ private _pendingTokenRequests: {
747
+ [key: string]: Promise<string>;
748
+ };
749
+
750
+ /**
751
+ * Internal list of tokens to 3rd party servers (federated servers) that have
752
+ * been created via `generateToken`. The object key is the root URL of the server.
753
+ */
754
+ private federatedServers: {
755
+ [key: string]: {
756
+ token: string;
757
+ expires: Date;
758
+ };
759
+ };
760
+
761
+ /**
762
+ * Internal list of 3rd party domains that should receive all cookies (credentials: "include").
763
+ * Used to for PKI and IWA workflows in high security environments.
764
+ */
765
+ private trustedDomains: string[];
766
+
767
+ private _hostHandler: any;
768
+
769
+ constructor(options: IUserSessionOptions) {
770
+ this.clientId = options.clientId;
771
+ this._refreshToken = options.refreshToken;
772
+ this._refreshTokenExpires = options.refreshTokenExpires;
773
+ this.username = options.username;
774
+ this.password = options.password;
775
+ this._token = options.token;
776
+ this._tokenExpires = options.tokenExpires;
777
+ this.portal = options.portal
778
+ ? cleanUrl(options.portal)
779
+ : "https://www.arcgis.com/sharing/rest";
780
+ this.ssl = options.ssl;
781
+ this.provider = options.provider || "arcgis";
782
+ this.tokenDuration = options.tokenDuration || 20160;
783
+ this.redirectUri = options.redirectUri;
784
+ this.refreshTokenTTL = options.refreshTokenTTL || 20160;
785
+ this.server = options.server;
786
+
787
+ this.federatedServers = {};
788
+ this.trustedDomains = [];
789
+
790
+ // if a non-federated server was passed explicitly, it should be trusted.
791
+ if (options.server) {
792
+ // if the url includes more than '/arcgis/', trim the rest
793
+ const root = this.getServerRootUrl(options.server);
794
+
795
+ this.federatedServers[root] = {
796
+ token: options.token,
797
+ expires: options.tokenExpires,
798
+ };
799
+ }
800
+ this._pendingTokenRequests = {};
801
+ }
802
+
803
+ /**
804
+ * Returns authentication in a format useable in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
805
+ *
806
+ * ```js
807
+ * esriId.registerToken(session.toCredential());
808
+ * ```
809
+ *
810
+ * @returns ICredential
811
+ */
812
+ public toCredential(): ICredential {
813
+ return {
814
+ expires: this.tokenExpires.getTime(),
815
+ server: this.portal,
816
+ ssl: this.ssl,
817
+ token: this.token,
818
+ userId: this.username,
819
+ };
820
+ }
821
+
822
+ /**
823
+ * Returns information about the currently logged in [user](https://developers.arcgis.com/rest/users-groups-and-items/user.htm). Subsequent calls will *not* result in additional web traffic.
824
+ *
825
+ * ```js
826
+ * session.getUser()
827
+ * .then(response => {
828
+ * console.log(response.role); // "org_admin"
829
+ * })
830
+ * ```
831
+ *
832
+ * @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
833
+ * @returns A Promise that will resolve with the data from the response.
834
+ */
835
+ public getUser(requestOptions?: IRequestOptions): Promise<IUser> {
836
+ if (this._pendingUserRequest) {
837
+ return this._pendingUserRequest;
838
+ } else if (this._user) {
839
+ return Promise.resolve(this._user);
840
+ } else {
841
+ const url = `${this.portal}/community/self`;
842
+
843
+ const options = {
844
+ httpMethod: "GET",
845
+ authentication: this,
846
+ ...requestOptions,
847
+ rawResponse: false,
848
+ } as IRequestOptions;
849
+
850
+ this._pendingUserRequest = request(url, options).then((response) => {
851
+ this._user = response;
852
+ this._pendingUserRequest = null;
853
+ return response;
854
+ });
855
+
856
+ return this._pendingUserRequest;
857
+ }
858
+ }
859
+
860
+ /**
861
+ * Returns information about the currently logged in user's [portal](https://developers.arcgis.com/rest/users-groups-and-items/portal-self.htm). Subsequent calls will *not* result in additional web traffic.
862
+ *
863
+ * ```js
864
+ * session.getPortal()
865
+ * .then(response => {
866
+ * console.log(portal.name); // "City of ..."
867
+ * })
868
+ * ```
869
+ *
870
+ * @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
871
+ * @returns A Promise that will resolve with the data from the response.
872
+ */
873
+ public getPortal(requestOptions?: IRequestOptions): Promise<any> {
874
+ if (this._pendingPortalRequest) {
875
+ return this._pendingPortalRequest;
876
+ } else if (this._portalInfo) {
877
+ return Promise.resolve(this._portalInfo);
878
+ } else {
879
+ const url = `${this.portal}/portals/self`;
880
+
881
+ const options = {
882
+ httpMethod: "GET",
883
+ authentication: this,
884
+ ...requestOptions,
885
+ rawResponse: false,
886
+ } as IRequestOptions;
887
+
888
+ this._pendingPortalRequest = request(url, options).then((response) => {
889
+ this._portalInfo = response;
890
+ this._pendingPortalRequest = null;
891
+ return response;
892
+ });
893
+
894
+ return this._pendingPortalRequest;
895
+ }
896
+ }
897
+
898
+ /**
899
+ * Returns the username for the currently logged in [user](https://developers.arcgis.com/rest/users-groups-and-items/user.htm). Subsequent calls will *not* result in additional web traffic. This is also used internally when a username is required for some requests but is not present in the options.
900
+ *
901
+ * * ```js
902
+ * session.getUsername()
903
+ * .then(response => {
904
+ * console.log(response); // "casey_jones"
905
+ * })
906
+ * ```
907
+ */
908
+ public getUsername() {
909
+ if (this.username) {
910
+ return Promise.resolve(this.username);
911
+ } else if (this._user) {
912
+ return Promise.resolve(this._user.username);
913
+ } else {
914
+ return this.getUser().then((user) => {
915
+ return user.username;
916
+ });
917
+ }
918
+ }
919
+
920
+ /**
921
+ * Gets an appropriate token for the given URL. If `portal` is ArcGIS Online and
922
+ * the request is to an ArcGIS Online domain `token` will be used. If the request
923
+ * is to the current `portal` the current `token` will also be used. However if
924
+ * the request is to an unknown server we will validate the server with a request
925
+ * to our current `portal`.
926
+ */
927
+ public getToken(url: string, requestOptions?: ITokenRequestOptions) {
928
+ if (canUseOnlineToken(this.portal, url)) {
929
+ return this.getFreshToken(requestOptions);
930
+ } else if (new RegExp(this.portal, "i").test(url)) {
931
+ return this.getFreshToken(requestOptions);
932
+ } else {
933
+ return this.getTokenForServer(url, requestOptions);
934
+ }
935
+ }
936
+
937
+ /**
938
+ * Get application access information for the current user
939
+ * see `validateAppAccess` function for details
940
+ *
941
+ * @param clientId application client id
942
+ */
943
+ public validateAppAccess(clientId: string): Promise<IAppAccess> {
944
+ return this.getToken(this.portal).then((token) => {
945
+ return validateAppAccess(token, clientId);
946
+ });
947
+ }
948
+
949
+ public toJSON(): IUserSessionOptions {
950
+ return {
951
+ clientId: this.clientId,
952
+ refreshToken: this.refreshToken,
953
+ refreshTokenExpires: this.refreshTokenExpires,
954
+ username: this.username,
955
+ password: this.password,
956
+ token: this.token,
957
+ tokenExpires: this.tokenExpires,
958
+ portal: this.portal,
959
+ ssl: this.ssl,
960
+ tokenDuration: this.tokenDuration,
961
+ redirectUri: this.redirectUri,
962
+ refreshTokenTTL: this.refreshTokenTTL,
963
+ };
964
+ }
965
+
966
+ public serialize() {
967
+ return JSON.stringify(this);
968
+ }
969
+ /**
970
+ * For a "Host" app that embeds other platform apps via iframes, after authenticating the user
971
+ * and creating a UserSession, the app can then enable "post message" style authentication by calling
972
+ * this method.
973
+ *
974
+ * Internally this adds an event listener on window for the `message` event
975
+ *
976
+ * @param validChildOrigins Array of origins that are allowed to request authentication from the host app
977
+ */
978
+ public enablePostMessageAuth(validChildOrigins: string[], win?: any): any {
979
+ /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
980
+ if (!win && window) {
981
+ win = window;
982
+ }
983
+ this._hostHandler = this.createPostMessageHandler(validChildOrigins);
984
+ win.addEventListener("message", this._hostHandler, false);
985
+ }
986
+
987
+ /**
988
+ * For a "Host" app that has embedded other platform apps via iframes, when the host needs
989
+ * to transition routes, it should call `UserSession.disablePostMessageAuth()` to remove
990
+ * the event listener and prevent memory leaks
991
+ */
992
+ public disablePostMessageAuth(win?: any) {
993
+ /* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
994
+ if (!win && window) {
995
+ win = window;
996
+ }
997
+ win.removeEventListener("message", this._hostHandler, false);
998
+ }
999
+
1000
+ /**
1001
+ * Manually refreshes the current `token` and `tokenExpires`.
1002
+ */
1003
+ public refreshSession(
1004
+ requestOptions?: ITokenRequestOptions
1005
+ ): Promise<UserSession> {
1006
+ // make sure subsequent calls to getUser() don't returned cached metadata
1007
+ this._user = null;
1008
+
1009
+ if (this.username && this.password) {
1010
+ return this.refreshWithUsernameAndPassword(requestOptions);
1011
+ }
1012
+
1013
+ if (this.clientId && this.refreshToken) {
1014
+ return this.refreshWithRefreshToken();
1015
+ }
1016
+
1017
+ return Promise.reject(new ArcGISAuthError("Unable to refresh token."));
1018
+ }
1019
+
1020
+ /**
1021
+ * Determines the root of the ArcGIS Server or Portal for a given URL.
1022
+ *
1023
+ * @param url the URl to determine the root url for.
1024
+ */
1025
+ public getServerRootUrl(url: string) {
1026
+ const [root] = cleanUrl(url).split(
1027
+ /\/rest(\/admin)?\/services(?:\/|#|\?|$)/
1028
+ );
1029
+ const [match, protocol, domainAndPath] = root.match(/(https?:\/\/)(.+)/);
1030
+ const [domain, ...path] = domainAndPath.split("/");
1031
+
1032
+ // only the domain is lowercased because in some cases an org id might be
1033
+ // in the path which cannot be lowercased.
1034
+ return `${protocol}${domain.toLowerCase()}/${path.join("/")}`;
1035
+ }
1036
+
1037
+ /**
1038
+ * Returns the proper [`credentials`] option for `fetch` for a given domain.
1039
+ * See [trusted server](https://enterprise.arcgis.com/en/portal/latest/administer/windows/configure-security.htm#ESRI_SECTION1_70CC159B3540440AB325BE5D89DBE94A).
1040
+ * Used internally by underlying request methods to add support for specific security considerations.
1041
+ *
1042
+ * @param url The url of the request
1043
+ * @returns "include" or "same-origin"
1044
+ */
1045
+ public getDomainCredentials(url: string): RequestCredentials {
1046
+ if (!this.trustedDomains || !this.trustedDomains.length) {
1047
+ return "same-origin";
1048
+ }
1049
+
1050
+ return this.trustedDomains.some((domainWithProtocol) => {
1051
+ return url.startsWith(domainWithProtocol);
1052
+ })
1053
+ ? "include"
1054
+ : "same-origin";
1055
+ }
1056
+
1057
+ /**
1058
+ * Return a function that closes over the validOrigins array and
1059
+ * can be used as an event handler for the `message` event
1060
+ *
1061
+ * @param validOrigins Array of valid origins
1062
+ */
1063
+ private createPostMessageHandler(
1064
+ validOrigins: string[]
1065
+ ): (event: any) => void {
1066
+ // return a function that closes over the validOrigins and
1067
+ // has access to the credential
1068
+ return (event: any) => {
1069
+ // Verify that the origin is valid
1070
+ // Note: do not use regex's here. validOrigins is an array so we're checking that the event's origin
1071
+ // is in the array via exact match. More info about avoiding postMessage xss issues here
1072
+ // https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html#tipsbypasses-in-postmessage-vulnerabilities
1073
+ const isValidOrigin = validOrigins.indexOf(event.origin) > -1;
1074
+ // JSAPI handles this slightly differently - instead of checking a list, it will respond if
1075
+ // event.origin === window.location.origin || event.origin.endsWith('.arcgis.com')
1076
+ // For Hub, and to enable cross domain debugging with port's in urls, we are opting to
1077
+ // use a list of valid origins
1078
+
1079
+ // Ensure the message type is something we want to handle
1080
+ const isValidType = event.data.type === "arcgis:auth:requestCredential";
1081
+
1082
+ if (isValidOrigin && isValidType) {
1083
+ const credential = this.toCredential();
1084
+ // the following line allows us to conform to our spec without changing other depended-on functionality
1085
+ // https://github.com/Esri/arcgis-rest-js/blob/master/packages/arcgis-rest-auth/post-message-auth-spec.md#arcgisauthcredential
1086
+ credential.server = credential.server.replace("/sharing/rest", "");
1087
+ event.source.postMessage(
1088
+ {
1089
+ type: "arcgis:auth:credential",
1090
+ credential,
1091
+ },
1092
+ event.origin
1093
+ );
1094
+ }
1095
+ };
1096
+ }
1097
+
1098
+ /**
1099
+ * Validates that a given URL is properly federated with our current `portal`.
1100
+ * Attempts to use the internal `federatedServers` cache first.
1101
+ */
1102
+ private getTokenForServer(
1103
+ url: string,
1104
+ requestOptions?: ITokenRequestOptions
1105
+ ) {
1106
+ // requests to /rest/services/ and /rest/admin/services/ are both valid
1107
+ // Federated servers may have inconsistent casing, so lowerCase it
1108
+ const root = this.getServerRootUrl(url);
1109
+ const existingToken = this.federatedServers[root];
1110
+
1111
+ if (
1112
+ existingToken &&
1113
+ existingToken.expires &&
1114
+ existingToken.expires.getTime() > Date.now()
1115
+ ) {
1116
+ return Promise.resolve(existingToken.token);
1117
+ }
1118
+
1119
+ if (this._pendingTokenRequests[root]) {
1120
+ return this._pendingTokenRequests[root];
1121
+ }
1122
+
1123
+ this._pendingTokenRequests[root] = this.fetchAuthorizedDomains().then(
1124
+ () => {
1125
+ return request(`${root}/rest/info`, {
1126
+ credentials: this.getDomainCredentials(url),
1127
+ })
1128
+ .then((response) => {
1129
+ if (response.owningSystemUrl) {
1130
+ /**
1131
+ * if this server is not owned by this portal
1132
+ * bail out with an error since we know we wont
1133
+ * be able to generate a token
1134
+ */
1135
+ if (!isFederated(response.owningSystemUrl, this.portal)) {
1136
+ throw new ArcGISAuthError(
1137
+ `${url} is not federated with ${this.portal}.`,
1138
+ "NOT_FEDERATED"
1139
+ );
1140
+ } else {
1141
+ /**
1142
+ * if the server is federated, use the relevant token endpoint.
1143
+ */
1144
+ return request(
1145
+ `${response.owningSystemUrl}/sharing/rest/info`,
1146
+ requestOptions
1147
+ );
1148
+ }
1149
+ } else if (
1150
+ response.authInfo &&
1151
+ this.federatedServers[root] !== undefined
1152
+ ) {
1153
+ /**
1154
+ * if its a stand-alone instance of ArcGIS Server that doesn't advertise
1155
+ * federation, but the root server url is recognized, use its built in token endpoint.
1156
+ */
1157
+ return Promise.resolve({
1158
+ authInfo: response.authInfo,
1159
+ });
1160
+ } else {
1161
+ throw new ArcGISAuthError(
1162
+ `${url} is not federated with any portal and is not explicitly trusted.`,
1163
+ "NOT_FEDERATED"
1164
+ );
1165
+ }
1166
+ })
1167
+ .then((response: any) => {
1168
+ return response.authInfo.tokenServicesUrl;
1169
+ })
1170
+ .then((tokenServicesUrl: string) => {
1171
+ // an expired token cant be used to generate a new token
1172
+ if (this.token && this.tokenExpires.getTime() > Date.now()) {
1173
+ return generateToken(tokenServicesUrl, {
1174
+ params: {
1175
+ token: this.token,
1176
+ serverUrl: url,
1177
+ expiration: this.tokenDuration,
1178
+ client: "referer",
1179
+ },
1180
+ });
1181
+ // generate an entirely fresh token if necessary
1182
+ } else {
1183
+ return generateToken(tokenServicesUrl, {
1184
+ params: {
1185
+ username: this.username,
1186
+ password: this.password,
1187
+ expiration: this.tokenDuration,
1188
+ client: "referer",
1189
+ },
1190
+ }).then((response: any) => {
1191
+ this._token = response.token;
1192
+ this._tokenExpires = new Date(response.expires);
1193
+ return response;
1194
+ });
1195
+ }
1196
+ })
1197
+ .then((response) => {
1198
+ this.federatedServers[root] = {
1199
+ expires: new Date(response.expires),
1200
+ token: response.token,
1201
+ };
1202
+ delete this._pendingTokenRequests[root];
1203
+ return response.token;
1204
+ });
1205
+ }
1206
+ );
1207
+
1208
+ return this._pendingTokenRequests[root];
1209
+ }
1210
+
1211
+ /**
1212
+ * Returns an unexpired token for the current `portal`.
1213
+ */
1214
+ private getFreshToken(requestOptions?: ITokenRequestOptions) {
1215
+ if (this.token && !this.tokenExpires) {
1216
+ return Promise.resolve(this.token);
1217
+ }
1218
+
1219
+ if (
1220
+ this.token &&
1221
+ this.tokenExpires &&
1222
+ this.tokenExpires.getTime() > Date.now()
1223
+ ) {
1224
+ return Promise.resolve(this.token);
1225
+ }
1226
+
1227
+ if (!this._pendingTokenRequests[this.portal]) {
1228
+ this._pendingTokenRequests[this.portal] = this.refreshSession(
1229
+ requestOptions
1230
+ ).then((session) => {
1231
+ this._pendingTokenRequests[this.portal] = null;
1232
+ return session.token;
1233
+ });
1234
+ }
1235
+
1236
+ return this._pendingTokenRequests[this.portal];
1237
+ }
1238
+
1239
+ /**
1240
+ * Refreshes the current `token` and `tokenExpires` with `username` and
1241
+ * `password`.
1242
+ */
1243
+ private refreshWithUsernameAndPassword(
1244
+ requestOptions?: ITokenRequestOptions
1245
+ ) {
1246
+ const options = {
1247
+ params: {
1248
+ username: this.username,
1249
+ password: this.password,
1250
+ expiration: this.tokenDuration,
1251
+ },
1252
+ ...requestOptions,
1253
+ };
1254
+ return generateToken(`${this.portal}/generateToken`, options).then(
1255
+ (response: any) => {
1256
+ this._token = response.token;
1257
+ this._tokenExpires = new Date(response.expires);
1258
+ return this;
1259
+ }
1260
+ );
1261
+ }
1262
+
1263
+ /**
1264
+ * Refreshes the current `token` and `tokenExpires` with `refreshToken`.
1265
+ */
1266
+ private refreshWithRefreshToken(requestOptions?: ITokenRequestOptions) {
1267
+ if (
1268
+ this.refreshToken &&
1269
+ this.refreshTokenExpires &&
1270
+ this.refreshTokenExpires.getTime() < Date.now()
1271
+ ) {
1272
+ return this.refreshRefreshToken(requestOptions);
1273
+ }
1274
+
1275
+ const options: ITokenRequestOptions = {
1276
+ params: {
1277
+ client_id: this.clientId,
1278
+ refresh_token: this.refreshToken,
1279
+ grant_type: "refresh_token",
1280
+ },
1281
+ ...requestOptions,
1282
+ };
1283
+ return fetchToken(`${this.portal}/oauth2/token`, options).then(
1284
+ (response) => {
1285
+ this._token = response.token;
1286
+ this._tokenExpires = response.expires;
1287
+ return this;
1288
+ }
1289
+ );
1290
+ }
1291
+
1292
+ /**
1293
+ * Exchanges an unexpired `refreshToken` for a new one, also updates `token` and
1294
+ * `tokenExpires`.
1295
+ */
1296
+ private refreshRefreshToken(requestOptions?: ITokenRequestOptions) {
1297
+ const options: ITokenRequestOptions = {
1298
+ params: {
1299
+ client_id: this.clientId,
1300
+ refresh_token: this.refreshToken,
1301
+ redirect_uri: this.redirectUri,
1302
+ grant_type: "exchange_refresh_token",
1303
+ },
1304
+ ...requestOptions,
1305
+ };
1306
+
1307
+ return fetchToken(`${this.portal}/oauth2/token`, options).then(
1308
+ (response) => {
1309
+ this._token = response.token;
1310
+ this._tokenExpires = response.expires;
1311
+ this._refreshToken = response.refreshToken;
1312
+ this._refreshTokenExpires = new Date(
1313
+ Date.now() + (this.refreshTokenTTL - 1) * 60 * 1000
1314
+ );
1315
+ return this;
1316
+ }
1317
+ );
1318
+ }
1319
+
1320
+ /**
1321
+ * ensures that the authorizedCrossOriginDomains are obtained from the portal and cached
1322
+ * so we can check them later.
1323
+ *
1324
+ * @returns this
1325
+ */
1326
+ private fetchAuthorizedDomains() {
1327
+ // if this token is for a specific server or we don't have a portal
1328
+ // don't get the portal info because we cant get the authorizedCrossOriginDomains
1329
+ if (this.server || !this.portal) {
1330
+ return Promise.resolve(this);
1331
+ }
1332
+
1333
+ return this.getPortal().then((portalInfo) => {
1334
+ /**
1335
+ * Specific domains can be configured as secure.esri.com or https://secure.esri.com this
1336
+ * normalizes to https://secure.esri.com so we can use startsWith later.
1337
+ */
1338
+ if (
1339
+ portalInfo.authorizedCrossOriginDomains &&
1340
+ portalInfo.authorizedCrossOriginDomains.length
1341
+ ) {
1342
+ this.trustedDomains = portalInfo.authorizedCrossOriginDomains
1343
+ .filter((d: string) => !d.startsWith("http://"))
1344
+ .map((d: string) => {
1345
+ if (d.startsWith("https://")) {
1346
+ return d;
1347
+ } else {
1348
+ return `https://${d}`;
1349
+ }
1350
+ });
1351
+ }
1352
+ return this;
1353
+ });
1354
+ }
1355
+ }