@esri/solutions-components 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/cjs/calcite-shell-panel_14.cjs.entry.js +1 -1
- package/dist/cjs/solution-configuration.cjs.entry.js +1086 -2
- package/dist/cjs/solution-configuration.cjs.entry.js.map +1 -1
- package/dist/cjs/solution-contents_3.cjs.entry.js +1 -1
- package/dist/cjs/{solution-store-f0547fe7.js → solution-store-e2fc11ac.js} +6 -1
- package/dist/cjs/solution-store-e2fc11ac.js.map +1 -0
- package/dist/collection/components/solution-configuration/solution-configuration.js +5 -9
- package/dist/collection/components/solution-configuration/solution-configuration.js.map +1 -1
- package/dist/components/solution-configuration.js +1086 -2
- package/dist/components/solution-configuration.js.map +1 -1
- package/dist/components/solution-store.js +1 -1
- package/dist/components/solution-store.js.map +1 -1
- package/dist/esm/calcite-shell-panel_14.entry.js +1 -1
- package/dist/esm/solution-configuration.entry.js +1086 -2
- package/dist/esm/solution-configuration.entry.js.map +1 -1
- package/dist/esm/solution-contents_3.entry.js +1 -1
- package/dist/esm/{solution-store-c1f6173a.js → solution-store-b3c65467.js} +2 -2
- package/dist/esm/solution-store-b3c65467.js.map +1 -0
- package/dist/solutions-components/{p-0e7a0839.entry.js → p-542189bc.entry.js} +2 -2
- package/dist/solutions-components/{p-0e7a0839.entry.js.map → p-542189bc.entry.js.map} +0 -0
- package/dist/solutions-components/{p-ee9be0ef.entry.js → p-638738f2.entry.js} +2 -2
- package/dist/solutions-components/{p-ee9be0ef.entry.js.map → p-638738f2.entry.js.map} +0 -0
- package/dist/solutions-components/p-7e8985f2.entry.js +1979 -0
- package/dist/solutions-components/p-7e8985f2.entry.js.map +1 -0
- package/dist/solutions-components/{p-065830b8.js → p-b25f6ebe.js} +2 -2
- package/dist/solutions-components/p-b25f6ebe.js.map +1 -0
- package/dist/solutions-components/solutions-components.esm.js +1 -1
- package/dist/solutions-components_commit.txt +5 -6
- package/package.json +1 -1
- package/dist/cjs/solution-store-f0547fe7.js.map +0 -1
- package/dist/esm/solution-store-c1f6173a.js.map +0 -1
- package/dist/solutions-components/p-065830b8.js.map +0 -1
- package/dist/solutions-components/p-401541a5.entry.js +0 -895
- package/dist/solutions-components/p-401541a5.entry.js.map +0 -1
@@ -8,7 +8,7 @@
|
|
8
8
|
Object.defineProperty(exports, '__esModule', { value: true });
|
9
9
|
|
10
10
|
const index = require('./index-a86078a0.js');
|
11
|
-
const solutionStore = require('./solution-store-
|
11
|
+
const solutionStore = require('./solution-store-e2fc11ac.js');
|
12
12
|
const locale = require('./locale-746a095d.js');
|
13
13
|
require('./index-d7f9770d.js');
|
14
14
|
require('./interfaces-ab603e16.js');
|
@@ -356,6 +356,1090 @@ function _getTopLevelItemIds(templates) {
|
|
356
356
|
return topLevelItemCandidateIds;
|
357
357
|
}
|
358
358
|
|
359
|
+
/* Copyright (c) 2017-2020 Environmental Systems Research Institute, Inc.
|
360
|
+
* Apache-2.0 */
|
361
|
+
function decodeParam(param) {
|
362
|
+
var _a = param.split("="), key = _a[0], value = _a[1];
|
363
|
+
return { key: decodeURIComponent(key), value: decodeURIComponent(value) };
|
364
|
+
}
|
365
|
+
/**
|
366
|
+
* Decodes the passed query string as an object.
|
367
|
+
*
|
368
|
+
* @param query A string to be decoded.
|
369
|
+
* @returns A decoded query param object.
|
370
|
+
*/
|
371
|
+
function decodeQueryString(query) {
|
372
|
+
return query
|
373
|
+
.replace(/^#/, "")
|
374
|
+
.split("&")
|
375
|
+
.reduce(function (acc, entry) {
|
376
|
+
var _a = decodeParam(entry), key = _a.key, value = _a.value;
|
377
|
+
acc[key] = value;
|
378
|
+
return acc;
|
379
|
+
}, {});
|
380
|
+
}
|
381
|
+
|
382
|
+
/*! *****************************************************************************
|
383
|
+
Copyright (c) Microsoft Corporation.
|
384
|
+
|
385
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
386
|
+
purpose with or without fee is hereby granted.
|
387
|
+
|
388
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
389
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
390
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
391
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
392
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
393
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
394
|
+
PERFORMANCE OF THIS SOFTWARE.
|
395
|
+
***************************************************************************** */
|
396
|
+
|
397
|
+
var __assign = function() {
|
398
|
+
__assign = Object.assign || function __assign(t) {
|
399
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
400
|
+
s = arguments[i];
|
401
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
402
|
+
}
|
403
|
+
return t;
|
404
|
+
};
|
405
|
+
return __assign.apply(this, arguments);
|
406
|
+
};
|
407
|
+
|
408
|
+
/* Copyright (c) 2017 Environmental Systems Research Institute, Inc.
|
409
|
+
* Apache-2.0 */
|
410
|
+
function fetchToken(url, requestOptions) {
|
411
|
+
var options = requestOptions;
|
412
|
+
// we generate a response, so we can't return the raw response
|
413
|
+
options.rawResponse = false;
|
414
|
+
return solutionStore.request(url, options).then(function (response) {
|
415
|
+
var r = {
|
416
|
+
token: response.access_token,
|
417
|
+
username: response.username,
|
418
|
+
expires: new Date(
|
419
|
+
// convert seconds in response to milliseconds and add the value to the current time to calculate a static expiration timestamp
|
420
|
+
Date.now() + (response.expires_in * 1000 - 1000)),
|
421
|
+
ssl: response.ssl === true
|
422
|
+
};
|
423
|
+
if (response.refresh_token) {
|
424
|
+
r.refreshToken = response.refresh_token;
|
425
|
+
}
|
426
|
+
return r;
|
427
|
+
});
|
428
|
+
}
|
429
|
+
|
430
|
+
/* Copyright (c) 2017-2018 Environmental Systems Research Institute, Inc.
|
431
|
+
* Apache-2.0 */
|
432
|
+
function generateToken(url, requestOptions) {
|
433
|
+
var options = requestOptions;
|
434
|
+
/* istanbul ignore else */
|
435
|
+
if (typeof window !== "undefined" &&
|
436
|
+
window.location &&
|
437
|
+
window.location.host) {
|
438
|
+
options.params.referer = window.location.host;
|
439
|
+
}
|
440
|
+
else {
|
441
|
+
options.params.referer = solutionStore.NODEJS_DEFAULT_REFERER_HEADER;
|
442
|
+
}
|
443
|
+
return solutionStore.request(url, options);
|
444
|
+
}
|
445
|
+
|
446
|
+
/**
|
447
|
+
* Used to test if a URL is an ArcGIS Online URL
|
448
|
+
*/
|
449
|
+
var arcgisOnlineUrlRegex = /^https?:\/\/(\S+)\.arcgis\.com.+/;
|
450
|
+
function isOnline(url) {
|
451
|
+
return arcgisOnlineUrlRegex.test(url);
|
452
|
+
}
|
453
|
+
function normalizeOnlinePortalUrl(portalUrl) {
|
454
|
+
if (!arcgisOnlineUrlRegex.test(portalUrl)) {
|
455
|
+
return portalUrl;
|
456
|
+
}
|
457
|
+
switch (getOnlineEnvironment(portalUrl)) {
|
458
|
+
case "dev":
|
459
|
+
return "https://devext.arcgis.com/sharing/rest";
|
460
|
+
case "qa":
|
461
|
+
return "https://qaext.arcgis.com/sharing/rest";
|
462
|
+
default:
|
463
|
+
return "https://www.arcgis.com/sharing/rest";
|
464
|
+
}
|
465
|
+
}
|
466
|
+
function getOnlineEnvironment(url) {
|
467
|
+
if (!arcgisOnlineUrlRegex.test(url)) {
|
468
|
+
return null;
|
469
|
+
}
|
470
|
+
var match = url.match(arcgisOnlineUrlRegex);
|
471
|
+
var subdomain = match[1].split(".").pop();
|
472
|
+
if (subdomain.includes("dev")) {
|
473
|
+
return "dev";
|
474
|
+
}
|
475
|
+
if (subdomain.includes("qa")) {
|
476
|
+
return "qa";
|
477
|
+
}
|
478
|
+
return "production";
|
479
|
+
}
|
480
|
+
function isFederated(owningSystemUrl, portalUrl) {
|
481
|
+
var normalizedPortalUrl = solutionStore.cleanUrl(normalizeOnlinePortalUrl(portalUrl)).replace(/https?:\/\//, "");
|
482
|
+
var normalizedOwningSystemUrl = solutionStore.cleanUrl(owningSystemUrl).replace(/https?:\/\//, "");
|
483
|
+
return new RegExp(normalizedOwningSystemUrl, "i").test(normalizedPortalUrl);
|
484
|
+
}
|
485
|
+
function canUseOnlineToken(portalUrl, requestUrl) {
|
486
|
+
var portalIsOnline = isOnline(portalUrl);
|
487
|
+
var requestIsOnline = isOnline(requestUrl);
|
488
|
+
var portalEnv = getOnlineEnvironment(portalUrl);
|
489
|
+
var requestEnv = getOnlineEnvironment(requestUrl);
|
490
|
+
if (portalIsOnline && requestIsOnline && portalEnv === requestEnv) {
|
491
|
+
return true;
|
492
|
+
}
|
493
|
+
return false;
|
494
|
+
}
|
495
|
+
|
496
|
+
/* Copyright (c) 2018-2020 Environmental Systems Research Institute, Inc.
|
497
|
+
* Apache-2.0 */
|
498
|
+
/**
|
499
|
+
* Validates that the user has access to the application
|
500
|
+
* and if they user should be presented a "View Only" mode
|
501
|
+
*
|
502
|
+
* This is only needed/valid for Esri applications that are "licensed"
|
503
|
+
* and shipped in ArcGIS Online or ArcGIS Enterprise. Most custom applications
|
504
|
+
* should not need or use this.
|
505
|
+
*
|
506
|
+
* ```js
|
507
|
+
* import { validateAppAccess } from '@esri/arcgis-rest-auth';
|
508
|
+
*
|
509
|
+
* return validateAppAccess('your-token', 'theClientId')
|
510
|
+
* .then((result) => {
|
511
|
+
* if (!result.value) {
|
512
|
+
* // redirect or show some other ui
|
513
|
+
* } else {
|
514
|
+
* if (result.viewOnlyUserTypeApp) {
|
515
|
+
* // use this to inform your app to show a "View Only" mode
|
516
|
+
* }
|
517
|
+
* }
|
518
|
+
* })
|
519
|
+
* .catch((err) => {
|
520
|
+
* // two possible errors
|
521
|
+
* // invalid clientId: {"error":{"code":400,"messageCode":"GWM_0007","message":"Invalid request","details":[]}}
|
522
|
+
* // invalid token: {"error":{"code":498,"message":"Invalid token.","details":[]}}
|
523
|
+
* })
|
524
|
+
* ```
|
525
|
+
*
|
526
|
+
* Note: This is only usable by Esri applications hosted on *arcgis.com, *esri.com or within
|
527
|
+
* an ArcGIS Enterprise installation. Custom applications can not use this.
|
528
|
+
*
|
529
|
+
* @param token platform token
|
530
|
+
* @param clientId application client id
|
531
|
+
* @param portal Optional
|
532
|
+
*/
|
533
|
+
function validateAppAccess(token, clientId, portal) {
|
534
|
+
if (portal === void 0) { portal = "https://www.arcgis.com/sharing/rest"; }
|
535
|
+
var url = portal + "/oauth2/validateAppAccess";
|
536
|
+
var ro = {
|
537
|
+
method: "POST",
|
538
|
+
params: {
|
539
|
+
f: "json",
|
540
|
+
client_id: clientId,
|
541
|
+
token: token,
|
542
|
+
},
|
543
|
+
};
|
544
|
+
return solutionStore.request(url, ro);
|
545
|
+
}
|
546
|
+
|
547
|
+
/* Copyright (c) 2017-2019 Environmental Systems Research Institute, Inc.
|
548
|
+
* Apache-2.0 */
|
549
|
+
function defer() {
|
550
|
+
var deferred = {
|
551
|
+
promise: null,
|
552
|
+
resolve: null,
|
553
|
+
reject: null,
|
554
|
+
};
|
555
|
+
deferred.promise = new Promise(function (resolve, reject) {
|
556
|
+
deferred.resolve = resolve;
|
557
|
+
deferred.reject = reject;
|
558
|
+
});
|
559
|
+
return deferred;
|
560
|
+
}
|
561
|
+
/**
|
562
|
+
* ```js
|
563
|
+
* import { UserSession } from '@esri/arcgis-rest-auth';
|
564
|
+
* UserSession.beginOAuth2({
|
565
|
+
* // register an app of your own to create a unique clientId
|
566
|
+
* clientId: "abc123",
|
567
|
+
* redirectUri: 'https://yourapp.com/authenticate.html'
|
568
|
+
* })
|
569
|
+
* .then(session)
|
570
|
+
* // or
|
571
|
+
* new UserSession({
|
572
|
+
* username: "jsmith",
|
573
|
+
* password: "123456"
|
574
|
+
* })
|
575
|
+
* // or
|
576
|
+
* UserSession.deserialize(cache)
|
577
|
+
* ```
|
578
|
+
* 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.
|
579
|
+
*/
|
580
|
+
var UserSession = /** @class */ (function () {
|
581
|
+
function UserSession(options) {
|
582
|
+
this.clientId = options.clientId;
|
583
|
+
this._refreshToken = options.refreshToken;
|
584
|
+
this._refreshTokenExpires = options.refreshTokenExpires;
|
585
|
+
this.username = options.username;
|
586
|
+
this.password = options.password;
|
587
|
+
this._token = options.token;
|
588
|
+
this._tokenExpires = options.tokenExpires;
|
589
|
+
this.portal = options.portal
|
590
|
+
? solutionStore.cleanUrl(options.portal)
|
591
|
+
: "https://www.arcgis.com/sharing/rest";
|
592
|
+
this.ssl = options.ssl;
|
593
|
+
this.provider = options.provider || "arcgis";
|
594
|
+
this.tokenDuration = options.tokenDuration || 20160;
|
595
|
+
this.redirectUri = options.redirectUri;
|
596
|
+
this.refreshTokenTTL = options.refreshTokenTTL || 20160;
|
597
|
+
this.server = options.server;
|
598
|
+
this.federatedServers = {};
|
599
|
+
this.trustedDomains = [];
|
600
|
+
// if a non-federated server was passed explicitly, it should be trusted.
|
601
|
+
if (options.server) {
|
602
|
+
// if the url includes more than '/arcgis/', trim the rest
|
603
|
+
var root = this.getServerRootUrl(options.server);
|
604
|
+
this.federatedServers[root] = {
|
605
|
+
token: options.token,
|
606
|
+
expires: options.tokenExpires,
|
607
|
+
};
|
608
|
+
}
|
609
|
+
this._pendingTokenRequests = {};
|
610
|
+
}
|
611
|
+
Object.defineProperty(UserSession.prototype, "token", {
|
612
|
+
/**
|
613
|
+
* The current ArcGIS Online or ArcGIS Enterprise `token`.
|
614
|
+
*/
|
615
|
+
get: function () {
|
616
|
+
return this._token;
|
617
|
+
},
|
618
|
+
enumerable: false,
|
619
|
+
configurable: true
|
620
|
+
});
|
621
|
+
Object.defineProperty(UserSession.prototype, "tokenExpires", {
|
622
|
+
/**
|
623
|
+
* The expiration time of the current `token`.
|
624
|
+
*/
|
625
|
+
get: function () {
|
626
|
+
return this._tokenExpires;
|
627
|
+
},
|
628
|
+
enumerable: false,
|
629
|
+
configurable: true
|
630
|
+
});
|
631
|
+
Object.defineProperty(UserSession.prototype, "refreshToken", {
|
632
|
+
/**
|
633
|
+
* The current token to ArcGIS Online or ArcGIS Enterprise.
|
634
|
+
*/
|
635
|
+
get: function () {
|
636
|
+
return this._refreshToken;
|
637
|
+
},
|
638
|
+
enumerable: false,
|
639
|
+
configurable: true
|
640
|
+
});
|
641
|
+
Object.defineProperty(UserSession.prototype, "refreshTokenExpires", {
|
642
|
+
/**
|
643
|
+
* The expiration time of the current `refreshToken`.
|
644
|
+
*/
|
645
|
+
get: function () {
|
646
|
+
return this._refreshTokenExpires;
|
647
|
+
},
|
648
|
+
enumerable: false,
|
649
|
+
configurable: true
|
650
|
+
});
|
651
|
+
Object.defineProperty(UserSession.prototype, "trustedServers", {
|
652
|
+
/**
|
653
|
+
* Deprecated, use `federatedServers` instead.
|
654
|
+
*
|
655
|
+
* @deprecated
|
656
|
+
*/
|
657
|
+
get: function () {
|
658
|
+
console.log("DEPRECATED: use federatedServers instead");
|
659
|
+
return this.federatedServers;
|
660
|
+
},
|
661
|
+
enumerable: false,
|
662
|
+
configurable: true
|
663
|
+
});
|
664
|
+
/**
|
665
|
+
* Begins a new browser-based OAuth 2.0 sign in. If `options.popup` is `true` the
|
666
|
+
* authentication window will open in a new tab/window and the function will return
|
667
|
+
* Promise<UserSession>. Otherwise, the user will be redirected to the
|
668
|
+
* authorization page in their current tab/window and the function will return `undefined`.
|
669
|
+
*
|
670
|
+
* @browserOnly
|
671
|
+
*/
|
672
|
+
/* istanbul ignore next */
|
673
|
+
UserSession.beginOAuth2 = function (options, win) {
|
674
|
+
if (win === void 0) { win = window; }
|
675
|
+
if (options.duration) {
|
676
|
+
console.log("DEPRECATED: 'duration' is deprecated - use 'expiration' instead");
|
677
|
+
}
|
678
|
+
var _a = __assign({
|
679
|
+
portal: "https://www.arcgis.com/sharing/rest",
|
680
|
+
provider: "arcgis",
|
681
|
+
expiration: 20160,
|
682
|
+
popup: true,
|
683
|
+
popupWindowFeatures: "height=400,width=600,menubar=no,location=yes,resizable=yes,scrollbars=yes,status=yes",
|
684
|
+
state: options.clientId,
|
685
|
+
locale: "",
|
686
|
+
}, options), portal = _a.portal, provider = _a.provider, clientId = _a.clientId, expiration = _a.expiration, redirectUri = _a.redirectUri, popup = _a.popup, popupWindowFeatures = _a.popupWindowFeatures, state = _a.state, locale = _a.locale, params = _a.params;
|
687
|
+
var url;
|
688
|
+
if (provider === "arcgis") {
|
689
|
+
url = portal + "/oauth2/authorize?client_id=" + clientId + "&response_type=token&expiration=" + (options.duration || expiration) + "&redirect_uri=" + encodeURIComponent(redirectUri) + "&state=" + state + "&locale=" + locale;
|
690
|
+
}
|
691
|
+
else {
|
692
|
+
url = portal + "/oauth2/social/authorize?client_id=" + clientId + "&socialLoginProviderName=" + provider + "&autoAccountCreateForSocial=true&response_type=token&expiration=" + (options.duration || expiration) + "&redirect_uri=" + encodeURIComponent(redirectUri) + "&state=" + state + "&locale=" + locale;
|
693
|
+
}
|
694
|
+
// append additional params
|
695
|
+
if (params) {
|
696
|
+
url = url + "&" + solutionStore.encodeQueryString(params);
|
697
|
+
}
|
698
|
+
if (!popup) {
|
699
|
+
win.location.href = url;
|
700
|
+
return undefined;
|
701
|
+
}
|
702
|
+
var session = defer();
|
703
|
+
win["__ESRI_REST_AUTH_HANDLER_" + clientId] = function (errorString, oauthInfoString) {
|
704
|
+
if (errorString) {
|
705
|
+
var error = JSON.parse(errorString);
|
706
|
+
session.reject(new solutionStore.ArcGISAuthError(error.errorMessage, error.error));
|
707
|
+
return;
|
708
|
+
}
|
709
|
+
if (oauthInfoString) {
|
710
|
+
var oauthInfo = JSON.parse(oauthInfoString);
|
711
|
+
session.resolve(new UserSession({
|
712
|
+
clientId: clientId,
|
713
|
+
portal: portal,
|
714
|
+
ssl: oauthInfo.ssl,
|
715
|
+
token: oauthInfo.token,
|
716
|
+
tokenExpires: new Date(oauthInfo.expires),
|
717
|
+
username: oauthInfo.username,
|
718
|
+
}));
|
719
|
+
}
|
720
|
+
};
|
721
|
+
win.open(url, "oauth-window", popupWindowFeatures);
|
722
|
+
return session.promise;
|
723
|
+
};
|
724
|
+
/**
|
725
|
+
* Completes a browser-based OAuth 2.0 sign in. If `options.popup` is `true` the user
|
726
|
+
* will be returned to the previous window. Otherwise a new `UserSession`
|
727
|
+
* will be returned. You must pass the same values for `options.popup` and
|
728
|
+
* `options.portal` as you used in `beginOAuth2()`.
|
729
|
+
*
|
730
|
+
* @browserOnly
|
731
|
+
*/
|
732
|
+
/* istanbul ignore next */
|
733
|
+
UserSession.completeOAuth2 = function (options, win) {
|
734
|
+
if (win === void 0) { win = window; }
|
735
|
+
var _a = __assign({ portal: "https://www.arcgis.com/sharing/rest", popup: true }, options), portal = _a.portal, clientId = _a.clientId, popup = _a.popup;
|
736
|
+
function completeSignIn(error, oauthInfo) {
|
737
|
+
try {
|
738
|
+
var handlerFn = void 0;
|
739
|
+
var handlerFnName = "__ESRI_REST_AUTH_HANDLER_" + clientId;
|
740
|
+
if (popup) {
|
741
|
+
// Guard b/c IE does not support window.opener
|
742
|
+
if (win.opener) {
|
743
|
+
if (win.opener.parent && win.opener.parent[handlerFnName]) {
|
744
|
+
handlerFn = win.opener.parent[handlerFnName];
|
745
|
+
}
|
746
|
+
else if (win.opener && win.opener[handlerFnName]) {
|
747
|
+
// support pop-out oauth from within an iframe
|
748
|
+
handlerFn = win.opener[handlerFnName];
|
749
|
+
}
|
750
|
+
}
|
751
|
+
else {
|
752
|
+
// IE
|
753
|
+
if (win !== win.parent && win.parent && win.parent[handlerFnName]) {
|
754
|
+
handlerFn = win.parent[handlerFnName];
|
755
|
+
}
|
756
|
+
}
|
757
|
+
// if we have a handler fn, call it and close the window
|
758
|
+
if (handlerFn) {
|
759
|
+
handlerFn(error ? JSON.stringify(error) : undefined, JSON.stringify(oauthInfo));
|
760
|
+
win.close();
|
761
|
+
return undefined;
|
762
|
+
}
|
763
|
+
}
|
764
|
+
}
|
765
|
+
catch (e) {
|
766
|
+
throw new solutionStore.ArcGISAuthError("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()\".");
|
767
|
+
}
|
768
|
+
if (error) {
|
769
|
+
throw new solutionStore.ArcGISAuthError(error.errorMessage, error.error);
|
770
|
+
}
|
771
|
+
return new UserSession({
|
772
|
+
clientId: clientId,
|
773
|
+
portal: portal,
|
774
|
+
ssl: oauthInfo.ssl,
|
775
|
+
token: oauthInfo.token,
|
776
|
+
tokenExpires: oauthInfo.expires,
|
777
|
+
username: oauthInfo.username,
|
778
|
+
});
|
779
|
+
}
|
780
|
+
var params = decodeQueryString(win.location.hash);
|
781
|
+
if (!params.access_token) {
|
782
|
+
var error = void 0;
|
783
|
+
var errorMessage = "Unknown error";
|
784
|
+
if (params.error) {
|
785
|
+
error = params.error;
|
786
|
+
errorMessage = params.error_description;
|
787
|
+
}
|
788
|
+
return completeSignIn({ error: error, errorMessage: errorMessage });
|
789
|
+
}
|
790
|
+
var token = params.access_token;
|
791
|
+
var expires = new Date(Date.now() + parseInt(params.expires_in, 10) * 1000 - 60 * 1000);
|
792
|
+
var username = params.username;
|
793
|
+
var ssl = params.ssl === "true";
|
794
|
+
return completeSignIn(undefined, {
|
795
|
+
token: token,
|
796
|
+
expires: expires,
|
797
|
+
ssl: ssl,
|
798
|
+
username: username,
|
799
|
+
});
|
800
|
+
};
|
801
|
+
/**
|
802
|
+
* Request session information from the parent application
|
803
|
+
*
|
804
|
+
* When an application is embedded into another application via an IFrame, the embedded app can
|
805
|
+
* use `window.postMessage` to request credentials from the host application. This function wraps
|
806
|
+
* that behavior.
|
807
|
+
*
|
808
|
+
* The ArcGIS API for Javascript has this built into the Identity Manager as of the 4.19 release.
|
809
|
+
*
|
810
|
+
* Note: The parent application will not respond if the embedded app's origin is not:
|
811
|
+
* - the same origin as the parent or *.arcgis.com (JSAPI)
|
812
|
+
* - in the list of valid child origins (REST-JS)
|
813
|
+
*
|
814
|
+
*
|
815
|
+
* @param parentOrigin origin of the parent frame. Passed into the embedded application as `parentOrigin` query param
|
816
|
+
* @browserOnly
|
817
|
+
*/
|
818
|
+
UserSession.fromParent = function (parentOrigin, win) {
|
819
|
+
/* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
|
820
|
+
if (!win && window) {
|
821
|
+
win = window;
|
822
|
+
}
|
823
|
+
// Declare handler outside of promise scope so we can detach it
|
824
|
+
var handler;
|
825
|
+
// return a promise that will resolve when the handler receives
|
826
|
+
// session information from the correct origin
|
827
|
+
return new Promise(function (resolve, reject) {
|
828
|
+
// create an event handler that just wraps the parentMessageHandler
|
829
|
+
handler = function (event) {
|
830
|
+
// ensure we only listen to events from the parent
|
831
|
+
if (event.source === win.parent && event.data) {
|
832
|
+
try {
|
833
|
+
return resolve(UserSession.parentMessageHandler(event));
|
834
|
+
}
|
835
|
+
catch (err) {
|
836
|
+
return reject(err);
|
837
|
+
}
|
838
|
+
}
|
839
|
+
};
|
840
|
+
// add listener
|
841
|
+
win.addEventListener("message", handler, false);
|
842
|
+
win.parent.postMessage({ type: "arcgis:auth:requestCredential" }, parentOrigin);
|
843
|
+
}).then(function (session) {
|
844
|
+
win.removeEventListener("message", handler, false);
|
845
|
+
return session;
|
846
|
+
});
|
847
|
+
};
|
848
|
+
/**
|
849
|
+
* Begins a new server-based OAuth 2.0 sign in. This will redirect the user to
|
850
|
+
* the ArcGIS Online or ArcGIS Enterprise authorization page.
|
851
|
+
*
|
852
|
+
* @nodeOnly
|
853
|
+
*/
|
854
|
+
UserSession.authorize = function (options, response) {
|
855
|
+
if (options.duration) {
|
856
|
+
console.log("DEPRECATED: 'duration' is deprecated - use 'expiration' instead");
|
857
|
+
}
|
858
|
+
var _a = __assign({ portal: "https://arcgis.com/sharing/rest", expiration: 20160 }, options), portal = _a.portal, clientId = _a.clientId, expiration = _a.expiration, redirectUri = _a.redirectUri;
|
859
|
+
response.writeHead(301, {
|
860
|
+
Location: portal + "/oauth2/authorize?client_id=" + clientId + "&expiration=" + (options.duration || expiration) + "&response_type=code&redirect_uri=" + encodeURIComponent(redirectUri),
|
861
|
+
});
|
862
|
+
response.end();
|
863
|
+
};
|
864
|
+
/**
|
865
|
+
* Completes the server-based OAuth 2.0 sign in process by exchanging the `authorizationCode`
|
866
|
+
* for a `access_token`.
|
867
|
+
*
|
868
|
+
* @nodeOnly
|
869
|
+
*/
|
870
|
+
UserSession.exchangeAuthorizationCode = function (options, authorizationCode) {
|
871
|
+
var _a = __assign({
|
872
|
+
portal: "https://www.arcgis.com/sharing/rest",
|
873
|
+
refreshTokenTTL: 20160,
|
874
|
+
}, options), portal = _a.portal, clientId = _a.clientId, redirectUri = _a.redirectUri, refreshTokenTTL = _a.refreshTokenTTL;
|
875
|
+
return fetchToken(portal + "/oauth2/token", {
|
876
|
+
params: {
|
877
|
+
grant_type: "authorization_code",
|
878
|
+
client_id: clientId,
|
879
|
+
redirect_uri: redirectUri,
|
880
|
+
code: authorizationCode,
|
881
|
+
},
|
882
|
+
}).then(function (response) {
|
883
|
+
return new UserSession({
|
884
|
+
clientId: clientId,
|
885
|
+
portal: portal,
|
886
|
+
ssl: response.ssl,
|
887
|
+
redirectUri: redirectUri,
|
888
|
+
refreshToken: response.refreshToken,
|
889
|
+
refreshTokenTTL: refreshTokenTTL,
|
890
|
+
refreshTokenExpires: new Date(Date.now() + (refreshTokenTTL - 1) * 60 * 1000),
|
891
|
+
token: response.token,
|
892
|
+
tokenExpires: response.expires,
|
893
|
+
username: response.username,
|
894
|
+
});
|
895
|
+
});
|
896
|
+
};
|
897
|
+
UserSession.deserialize = function (str) {
|
898
|
+
var options = JSON.parse(str);
|
899
|
+
return new UserSession({
|
900
|
+
clientId: options.clientId,
|
901
|
+
refreshToken: options.refreshToken,
|
902
|
+
refreshTokenExpires: new Date(options.refreshTokenExpires),
|
903
|
+
username: options.username,
|
904
|
+
password: options.password,
|
905
|
+
token: options.token,
|
906
|
+
tokenExpires: new Date(options.tokenExpires),
|
907
|
+
portal: options.portal,
|
908
|
+
ssl: options.ssl,
|
909
|
+
tokenDuration: options.tokenDuration,
|
910
|
+
redirectUri: options.redirectUri,
|
911
|
+
refreshTokenTTL: options.refreshTokenTTL,
|
912
|
+
});
|
913
|
+
};
|
914
|
+
/**
|
915
|
+
* Translates authentication from the format used in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
|
916
|
+
*
|
917
|
+
* ```js
|
918
|
+
* UserSession.fromCredential({
|
919
|
+
* userId: "jsmith",
|
920
|
+
* token: "secret"
|
921
|
+
* });
|
922
|
+
* ```
|
923
|
+
*
|
924
|
+
* @returns UserSession
|
925
|
+
*/
|
926
|
+
UserSession.fromCredential = function (credential) {
|
927
|
+
// At ArcGIS Online 9.1, credentials no longer include the ssl and expires properties
|
928
|
+
// Here, we provide default values for them to cover this condition
|
929
|
+
var ssl = typeof credential.ssl !== "undefined" ? credential.ssl : true;
|
930
|
+
var expires = credential.expires || Date.now() + 7200000; /* 2 hours */
|
931
|
+
return new UserSession({
|
932
|
+
portal: credential.server.includes("sharing/rest")
|
933
|
+
? credential.server
|
934
|
+
: credential.server + "/sharing/rest",
|
935
|
+
ssl: ssl,
|
936
|
+
token: credential.token,
|
937
|
+
username: credential.userId,
|
938
|
+
tokenExpires: new Date(expires),
|
939
|
+
});
|
940
|
+
};
|
941
|
+
/**
|
942
|
+
* Handle the response from the parent
|
943
|
+
* @param event DOM Event
|
944
|
+
*/
|
945
|
+
UserSession.parentMessageHandler = function (event) {
|
946
|
+
if (event.data.type === "arcgis:auth:credential") {
|
947
|
+
return UserSession.fromCredential(event.data.credential);
|
948
|
+
}
|
949
|
+
if (event.data.type === "arcgis:auth:error") {
|
950
|
+
var err = new Error(event.data.error.message);
|
951
|
+
err.name = event.data.error.name;
|
952
|
+
throw err;
|
953
|
+
}
|
954
|
+
else {
|
955
|
+
throw new Error("Unknown message type.");
|
956
|
+
}
|
957
|
+
};
|
958
|
+
/**
|
959
|
+
* Returns authentication in a format useable in the [ArcGIS API for JavaScript](https://developers.arcgis.com/javascript/).
|
960
|
+
*
|
961
|
+
* ```js
|
962
|
+
* esriId.registerToken(session.toCredential());
|
963
|
+
* ```
|
964
|
+
*
|
965
|
+
* @returns ICredential
|
966
|
+
*/
|
967
|
+
UserSession.prototype.toCredential = function () {
|
968
|
+
return {
|
969
|
+
expires: this.tokenExpires.getTime(),
|
970
|
+
server: this.portal,
|
971
|
+
ssl: this.ssl,
|
972
|
+
token: this.token,
|
973
|
+
userId: this.username,
|
974
|
+
};
|
975
|
+
};
|
976
|
+
/**
|
977
|
+
* 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.
|
978
|
+
*
|
979
|
+
* ```js
|
980
|
+
* session.getUser()
|
981
|
+
* .then(response => {
|
982
|
+
* console.log(response.role); // "org_admin"
|
983
|
+
* })
|
984
|
+
* ```
|
985
|
+
*
|
986
|
+
* @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
|
987
|
+
* @returns A Promise that will resolve with the data from the response.
|
988
|
+
*/
|
989
|
+
UserSession.prototype.getUser = function (requestOptions) {
|
990
|
+
var _this = this;
|
991
|
+
if (this._pendingUserRequest) {
|
992
|
+
return this._pendingUserRequest;
|
993
|
+
}
|
994
|
+
else if (this._user) {
|
995
|
+
return Promise.resolve(this._user);
|
996
|
+
}
|
997
|
+
else {
|
998
|
+
var url = this.portal + "/community/self";
|
999
|
+
var options = __assign(__assign({ httpMethod: "GET", authentication: this }, requestOptions), { rawResponse: false });
|
1000
|
+
this._pendingUserRequest = solutionStore.request(url, options).then(function (response) {
|
1001
|
+
_this._user = response;
|
1002
|
+
_this._pendingUserRequest = null;
|
1003
|
+
return response;
|
1004
|
+
});
|
1005
|
+
return this._pendingUserRequest;
|
1006
|
+
}
|
1007
|
+
};
|
1008
|
+
/**
|
1009
|
+
* 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.
|
1010
|
+
*
|
1011
|
+
* ```js
|
1012
|
+
* session.getPortal()
|
1013
|
+
* .then(response => {
|
1014
|
+
* console.log(portal.name); // "City of ..."
|
1015
|
+
* })
|
1016
|
+
* ```
|
1017
|
+
*
|
1018
|
+
* @param requestOptions - Options for the request. NOTE: `rawResponse` is not supported by this operation.
|
1019
|
+
* @returns A Promise that will resolve with the data from the response.
|
1020
|
+
*/
|
1021
|
+
UserSession.prototype.getPortal = function (requestOptions) {
|
1022
|
+
var _this = this;
|
1023
|
+
if (this._pendingPortalRequest) {
|
1024
|
+
return this._pendingPortalRequest;
|
1025
|
+
}
|
1026
|
+
else if (this._portalInfo) {
|
1027
|
+
return Promise.resolve(this._portalInfo);
|
1028
|
+
}
|
1029
|
+
else {
|
1030
|
+
var url = this.portal + "/portals/self";
|
1031
|
+
var options = __assign(__assign({ httpMethod: "GET", authentication: this }, requestOptions), { rawResponse: false });
|
1032
|
+
this._pendingPortalRequest = solutionStore.request(url, options).then(function (response) {
|
1033
|
+
_this._portalInfo = response;
|
1034
|
+
_this._pendingPortalRequest = null;
|
1035
|
+
return response;
|
1036
|
+
});
|
1037
|
+
return this._pendingPortalRequest;
|
1038
|
+
}
|
1039
|
+
};
|
1040
|
+
/**
|
1041
|
+
* 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.
|
1042
|
+
*
|
1043
|
+
* * ```js
|
1044
|
+
* session.getUsername()
|
1045
|
+
* .then(response => {
|
1046
|
+
* console.log(response); // "casey_jones"
|
1047
|
+
* })
|
1048
|
+
* ```
|
1049
|
+
*/
|
1050
|
+
UserSession.prototype.getUsername = function () {
|
1051
|
+
if (this.username) {
|
1052
|
+
return Promise.resolve(this.username);
|
1053
|
+
}
|
1054
|
+
else if (this._user) {
|
1055
|
+
return Promise.resolve(this._user.username);
|
1056
|
+
}
|
1057
|
+
else {
|
1058
|
+
return this.getUser().then(function (user) {
|
1059
|
+
return user.username;
|
1060
|
+
});
|
1061
|
+
}
|
1062
|
+
};
|
1063
|
+
/**
|
1064
|
+
* Gets an appropriate token for the given URL. If `portal` is ArcGIS Online and
|
1065
|
+
* the request is to an ArcGIS Online domain `token` will be used. If the request
|
1066
|
+
* is to the current `portal` the current `token` will also be used. However if
|
1067
|
+
* the request is to an unknown server we will validate the server with a request
|
1068
|
+
* to our current `portal`.
|
1069
|
+
*/
|
1070
|
+
UserSession.prototype.getToken = function (url, requestOptions) {
|
1071
|
+
if (canUseOnlineToken(this.portal, url)) {
|
1072
|
+
return this.getFreshToken(requestOptions);
|
1073
|
+
}
|
1074
|
+
else if (new RegExp(this.portal, "i").test(url)) {
|
1075
|
+
return this.getFreshToken(requestOptions);
|
1076
|
+
}
|
1077
|
+
else {
|
1078
|
+
return this.getTokenForServer(url, requestOptions);
|
1079
|
+
}
|
1080
|
+
};
|
1081
|
+
/**
|
1082
|
+
* Get application access information for the current user
|
1083
|
+
* see `validateAppAccess` function for details
|
1084
|
+
*
|
1085
|
+
* @param clientId application client id
|
1086
|
+
*/
|
1087
|
+
UserSession.prototype.validateAppAccess = function (clientId) {
|
1088
|
+
return this.getToken(this.portal).then(function (token) {
|
1089
|
+
return validateAppAccess(token, clientId);
|
1090
|
+
});
|
1091
|
+
};
|
1092
|
+
UserSession.prototype.toJSON = function () {
|
1093
|
+
return {
|
1094
|
+
clientId: this.clientId,
|
1095
|
+
refreshToken: this.refreshToken,
|
1096
|
+
refreshTokenExpires: this.refreshTokenExpires,
|
1097
|
+
username: this.username,
|
1098
|
+
password: this.password,
|
1099
|
+
token: this.token,
|
1100
|
+
tokenExpires: this.tokenExpires,
|
1101
|
+
portal: this.portal,
|
1102
|
+
ssl: this.ssl,
|
1103
|
+
tokenDuration: this.tokenDuration,
|
1104
|
+
redirectUri: this.redirectUri,
|
1105
|
+
refreshTokenTTL: this.refreshTokenTTL,
|
1106
|
+
};
|
1107
|
+
};
|
1108
|
+
UserSession.prototype.serialize = function () {
|
1109
|
+
return JSON.stringify(this);
|
1110
|
+
};
|
1111
|
+
/**
|
1112
|
+
* For a "Host" app that embeds other platform apps via iframes, after authenticating the user
|
1113
|
+
* and creating a UserSession, the app can then enable "post message" style authentication by calling
|
1114
|
+
* this method.
|
1115
|
+
*
|
1116
|
+
* Internally this adds an event listener on window for the `message` event
|
1117
|
+
*
|
1118
|
+
* @param validChildOrigins Array of origins that are allowed to request authentication from the host app
|
1119
|
+
*/
|
1120
|
+
UserSession.prototype.enablePostMessageAuth = function (validChildOrigins, win) {
|
1121
|
+
/* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
|
1122
|
+
if (!win && window) {
|
1123
|
+
win = window;
|
1124
|
+
}
|
1125
|
+
this._hostHandler = this.createPostMessageHandler(validChildOrigins);
|
1126
|
+
win.addEventListener("message", this._hostHandler, false);
|
1127
|
+
};
|
1128
|
+
/**
|
1129
|
+
* For a "Host" app that has embedded other platform apps via iframes, when the host needs
|
1130
|
+
* to transition routes, it should call `UserSession.disablePostMessageAuth()` to remove
|
1131
|
+
* the event listener and prevent memory leaks
|
1132
|
+
*/
|
1133
|
+
UserSession.prototype.disablePostMessageAuth = function (win) {
|
1134
|
+
/* istanbul ignore next: must pass in a mockwindow for tests so we can't cover the other branch */
|
1135
|
+
if (!win && window) {
|
1136
|
+
win = window;
|
1137
|
+
}
|
1138
|
+
win.removeEventListener("message", this._hostHandler, false);
|
1139
|
+
};
|
1140
|
+
/**
|
1141
|
+
* Manually refreshes the current `token` and `tokenExpires`.
|
1142
|
+
*/
|
1143
|
+
UserSession.prototype.refreshSession = function (requestOptions) {
|
1144
|
+
// make sure subsequent calls to getUser() don't returned cached metadata
|
1145
|
+
this._user = null;
|
1146
|
+
if (this.username && this.password) {
|
1147
|
+
return this.refreshWithUsernameAndPassword(requestOptions);
|
1148
|
+
}
|
1149
|
+
if (this.clientId && this.refreshToken) {
|
1150
|
+
return this.refreshWithRefreshToken();
|
1151
|
+
}
|
1152
|
+
return Promise.reject(new solutionStore.ArcGISAuthError("Unable to refresh token."));
|
1153
|
+
};
|
1154
|
+
/**
|
1155
|
+
* Determines the root of the ArcGIS Server or Portal for a given URL.
|
1156
|
+
*
|
1157
|
+
* @param url the URl to determine the root url for.
|
1158
|
+
*/
|
1159
|
+
UserSession.prototype.getServerRootUrl = function (url) {
|
1160
|
+
var root = solutionStore.cleanUrl(url).split(/\/rest(\/admin)?\/services(?:\/|#|\?|$)/)[0];
|
1161
|
+
var _a = root.match(/(https?:\/\/)(.+)/), protocol = _a[1], domainAndPath = _a[2];
|
1162
|
+
var _b = domainAndPath.split("/"), domain = _b[0], path = _b.slice(1);
|
1163
|
+
// only the domain is lowercased because in some cases an org id might be
|
1164
|
+
// in the path which cannot be lowercased.
|
1165
|
+
return "" + protocol + domain.toLowerCase() + "/" + path.join("/");
|
1166
|
+
};
|
1167
|
+
/**
|
1168
|
+
* Returns the proper [`credentials`] option for `fetch` for a given domain.
|
1169
|
+
* See [trusted server](https://enterprise.arcgis.com/en/portal/latest/administer/windows/configure-security.htm#ESRI_SECTION1_70CC159B3540440AB325BE5D89DBE94A).
|
1170
|
+
* Used internally by underlying request methods to add support for specific security considerations.
|
1171
|
+
*
|
1172
|
+
* @param url The url of the request
|
1173
|
+
* @returns "include" or "same-origin"
|
1174
|
+
*/
|
1175
|
+
UserSession.prototype.getDomainCredentials = function (url) {
|
1176
|
+
if (!this.trustedDomains || !this.trustedDomains.length) {
|
1177
|
+
return "same-origin";
|
1178
|
+
}
|
1179
|
+
return this.trustedDomains.some(function (domainWithProtocol) {
|
1180
|
+
return url.startsWith(domainWithProtocol);
|
1181
|
+
})
|
1182
|
+
? "include"
|
1183
|
+
: "same-origin";
|
1184
|
+
};
|
1185
|
+
/**
|
1186
|
+
* Return a function that closes over the validOrigins array and
|
1187
|
+
* can be used as an event handler for the `message` event
|
1188
|
+
*
|
1189
|
+
* @param validOrigins Array of valid origins
|
1190
|
+
*/
|
1191
|
+
UserSession.prototype.createPostMessageHandler = function (validOrigins) {
|
1192
|
+
var _this = this;
|
1193
|
+
// return a function that closes over the validOrigins and
|
1194
|
+
// has access to the credential
|
1195
|
+
return function (event) {
|
1196
|
+
// Verify that the origin is valid
|
1197
|
+
// Note: do not use regex's here. validOrigins is an array so we're checking that the event's origin
|
1198
|
+
// is in the array via exact match. More info about avoiding postMessage xss issues here
|
1199
|
+
// https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html#tipsbypasses-in-postmessage-vulnerabilities
|
1200
|
+
var isValidOrigin = validOrigins.indexOf(event.origin) > -1;
|
1201
|
+
// JSAPI handles this slightly differently - instead of checking a list, it will respond if
|
1202
|
+
// event.origin === window.location.origin || event.origin.endsWith('.arcgis.com')
|
1203
|
+
// For Hub, and to enable cross domain debugging with port's in urls, we are opting to
|
1204
|
+
// use a list of valid origins
|
1205
|
+
// Ensure the message type is something we want to handle
|
1206
|
+
var isValidType = event.data.type === "arcgis:auth:requestCredential";
|
1207
|
+
var isTokenValid = _this.tokenExpires.getTime() > Date.now();
|
1208
|
+
if (isValidOrigin && isValidType) {
|
1209
|
+
var msg = {};
|
1210
|
+
if (isTokenValid) {
|
1211
|
+
var credential = _this.toCredential();
|
1212
|
+
// arcgis:auth:error with {name: "", message: ""}
|
1213
|
+
// the following line allows us to conform to our spec without changing other depended-on functionality
|
1214
|
+
// https://github.com/Esri/arcgis-rest-js/blob/master/packages/arcgis-rest-auth/post-message-auth-spec.md#arcgisauthcredential
|
1215
|
+
credential.server = credential.server.replace("/sharing/rest", "");
|
1216
|
+
msg = { type: "arcgis:auth:credential", credential: credential };
|
1217
|
+
}
|
1218
|
+
else {
|
1219
|
+
// Return an error
|
1220
|
+
msg = {
|
1221
|
+
type: "arcgis:auth:error",
|
1222
|
+
error: {
|
1223
|
+
name: "tokenExpiredError",
|
1224
|
+
message: "Session token was expired, and not returned to the child application",
|
1225
|
+
},
|
1226
|
+
};
|
1227
|
+
}
|
1228
|
+
event.source.postMessage(msg, event.origin);
|
1229
|
+
}
|
1230
|
+
};
|
1231
|
+
};
|
1232
|
+
/**
|
1233
|
+
* Validates that a given URL is properly federated with our current `portal`.
|
1234
|
+
* Attempts to use the internal `federatedServers` cache first.
|
1235
|
+
*/
|
1236
|
+
UserSession.prototype.getTokenForServer = function (url, requestOptions) {
|
1237
|
+
var _this = this;
|
1238
|
+
// requests to /rest/services/ and /rest/admin/services/ are both valid
|
1239
|
+
// Federated servers may have inconsistent casing, so lowerCase it
|
1240
|
+
var root = this.getServerRootUrl(url);
|
1241
|
+
var existingToken = this.federatedServers[root];
|
1242
|
+
if (existingToken &&
|
1243
|
+
existingToken.expires &&
|
1244
|
+
existingToken.expires.getTime() > Date.now()) {
|
1245
|
+
return Promise.resolve(existingToken.token);
|
1246
|
+
}
|
1247
|
+
if (this._pendingTokenRequests[root]) {
|
1248
|
+
return this._pendingTokenRequests[root];
|
1249
|
+
}
|
1250
|
+
this._pendingTokenRequests[root] = this.fetchAuthorizedDomains().then(function () {
|
1251
|
+
return solutionStore.request(root + "/rest/info", {
|
1252
|
+
credentials: _this.getDomainCredentials(url),
|
1253
|
+
})
|
1254
|
+
.then(function (response) {
|
1255
|
+
if (response.owningSystemUrl) {
|
1256
|
+
/**
|
1257
|
+
* if this server is not owned by this portal
|
1258
|
+
* bail out with an error since we know we wont
|
1259
|
+
* be able to generate a token
|
1260
|
+
*/
|
1261
|
+
if (!isFederated(response.owningSystemUrl, _this.portal)) {
|
1262
|
+
throw new solutionStore.ArcGISAuthError(url + " is not federated with " + _this.portal + ".", "NOT_FEDERATED");
|
1263
|
+
}
|
1264
|
+
else {
|
1265
|
+
/**
|
1266
|
+
* if the server is federated, use the relevant token endpoint.
|
1267
|
+
*/
|
1268
|
+
return solutionStore.request(response.owningSystemUrl + "/sharing/rest/info", requestOptions);
|
1269
|
+
}
|
1270
|
+
}
|
1271
|
+
else if (response.authInfo &&
|
1272
|
+
_this.federatedServers[root] !== undefined) {
|
1273
|
+
/**
|
1274
|
+
* if its a stand-alone instance of ArcGIS Server that doesn't advertise
|
1275
|
+
* federation, but the root server url is recognized, use its built in token endpoint.
|
1276
|
+
*/
|
1277
|
+
return Promise.resolve({
|
1278
|
+
authInfo: response.authInfo,
|
1279
|
+
});
|
1280
|
+
}
|
1281
|
+
else {
|
1282
|
+
throw new solutionStore.ArcGISAuthError(url + " is not federated with any portal and is not explicitly trusted.", "NOT_FEDERATED");
|
1283
|
+
}
|
1284
|
+
})
|
1285
|
+
.then(function (response) {
|
1286
|
+
return response.authInfo.tokenServicesUrl;
|
1287
|
+
})
|
1288
|
+
.then(function (tokenServicesUrl) {
|
1289
|
+
// an expired token cant be used to generate a new token
|
1290
|
+
if (_this.token && _this.tokenExpires.getTime() > Date.now()) {
|
1291
|
+
return generateToken(tokenServicesUrl, {
|
1292
|
+
params: {
|
1293
|
+
token: _this.token,
|
1294
|
+
serverUrl: url,
|
1295
|
+
expiration: _this.tokenDuration,
|
1296
|
+
client: "referer",
|
1297
|
+
},
|
1298
|
+
});
|
1299
|
+
// generate an entirely fresh token if necessary
|
1300
|
+
}
|
1301
|
+
else {
|
1302
|
+
return generateToken(tokenServicesUrl, {
|
1303
|
+
params: {
|
1304
|
+
username: _this.username,
|
1305
|
+
password: _this.password,
|
1306
|
+
expiration: _this.tokenDuration,
|
1307
|
+
client: "referer",
|
1308
|
+
},
|
1309
|
+
}).then(function (response) {
|
1310
|
+
_this._token = response.token;
|
1311
|
+
_this._tokenExpires = new Date(response.expires);
|
1312
|
+
return response;
|
1313
|
+
});
|
1314
|
+
}
|
1315
|
+
})
|
1316
|
+
.then(function (response) {
|
1317
|
+
_this.federatedServers[root] = {
|
1318
|
+
expires: new Date(response.expires),
|
1319
|
+
token: response.token,
|
1320
|
+
};
|
1321
|
+
delete _this._pendingTokenRequests[root];
|
1322
|
+
return response.token;
|
1323
|
+
});
|
1324
|
+
});
|
1325
|
+
return this._pendingTokenRequests[root];
|
1326
|
+
};
|
1327
|
+
/**
|
1328
|
+
* Returns an unexpired token for the current `portal`.
|
1329
|
+
*/
|
1330
|
+
UserSession.prototype.getFreshToken = function (requestOptions) {
|
1331
|
+
var _this = this;
|
1332
|
+
if (this.token && !this.tokenExpires) {
|
1333
|
+
return Promise.resolve(this.token);
|
1334
|
+
}
|
1335
|
+
if (this.token &&
|
1336
|
+
this.tokenExpires &&
|
1337
|
+
this.tokenExpires.getTime() > Date.now()) {
|
1338
|
+
return Promise.resolve(this.token);
|
1339
|
+
}
|
1340
|
+
if (!this._pendingTokenRequests[this.portal]) {
|
1341
|
+
this._pendingTokenRequests[this.portal] = this.refreshSession(requestOptions).then(function (session) {
|
1342
|
+
_this._pendingTokenRequests[_this.portal] = null;
|
1343
|
+
return session.token;
|
1344
|
+
});
|
1345
|
+
}
|
1346
|
+
return this._pendingTokenRequests[this.portal];
|
1347
|
+
};
|
1348
|
+
/**
|
1349
|
+
* Refreshes the current `token` and `tokenExpires` with `username` and
|
1350
|
+
* `password`.
|
1351
|
+
*/
|
1352
|
+
UserSession.prototype.refreshWithUsernameAndPassword = function (requestOptions) {
|
1353
|
+
var _this = this;
|
1354
|
+
var options = __assign({ params: {
|
1355
|
+
username: this.username,
|
1356
|
+
password: this.password,
|
1357
|
+
expiration: this.tokenDuration,
|
1358
|
+
} }, requestOptions);
|
1359
|
+
return generateToken(this.portal + "/generateToken", options).then(function (response) {
|
1360
|
+
_this._token = response.token;
|
1361
|
+
_this._tokenExpires = new Date(response.expires);
|
1362
|
+
return _this;
|
1363
|
+
});
|
1364
|
+
};
|
1365
|
+
/**
|
1366
|
+
* Refreshes the current `token` and `tokenExpires` with `refreshToken`.
|
1367
|
+
*/
|
1368
|
+
UserSession.prototype.refreshWithRefreshToken = function (requestOptions) {
|
1369
|
+
var _this = this;
|
1370
|
+
if (this.refreshToken &&
|
1371
|
+
this.refreshTokenExpires &&
|
1372
|
+
this.refreshTokenExpires.getTime() < Date.now()) {
|
1373
|
+
return this.refreshRefreshToken(requestOptions);
|
1374
|
+
}
|
1375
|
+
var options = __assign({ params: {
|
1376
|
+
client_id: this.clientId,
|
1377
|
+
refresh_token: this.refreshToken,
|
1378
|
+
grant_type: "refresh_token",
|
1379
|
+
} }, requestOptions);
|
1380
|
+
return fetchToken(this.portal + "/oauth2/token", options).then(function (response) {
|
1381
|
+
_this._token = response.token;
|
1382
|
+
_this._tokenExpires = response.expires;
|
1383
|
+
return _this;
|
1384
|
+
});
|
1385
|
+
};
|
1386
|
+
/**
|
1387
|
+
* Exchanges an unexpired `refreshToken` for a new one, also updates `token` and
|
1388
|
+
* `tokenExpires`.
|
1389
|
+
*/
|
1390
|
+
UserSession.prototype.refreshRefreshToken = function (requestOptions) {
|
1391
|
+
var _this = this;
|
1392
|
+
var options = __assign({ params: {
|
1393
|
+
client_id: this.clientId,
|
1394
|
+
refresh_token: this.refreshToken,
|
1395
|
+
redirect_uri: this.redirectUri,
|
1396
|
+
grant_type: "exchange_refresh_token",
|
1397
|
+
} }, requestOptions);
|
1398
|
+
return fetchToken(this.portal + "/oauth2/token", options).then(function (response) {
|
1399
|
+
_this._token = response.token;
|
1400
|
+
_this._tokenExpires = response.expires;
|
1401
|
+
_this._refreshToken = response.refreshToken;
|
1402
|
+
_this._refreshTokenExpires = new Date(Date.now() + (_this.refreshTokenTTL - 1) * 60 * 1000);
|
1403
|
+
return _this;
|
1404
|
+
});
|
1405
|
+
};
|
1406
|
+
/**
|
1407
|
+
* ensures that the authorizedCrossOriginDomains are obtained from the portal and cached
|
1408
|
+
* so we can check them later.
|
1409
|
+
*
|
1410
|
+
* @returns this
|
1411
|
+
*/
|
1412
|
+
UserSession.prototype.fetchAuthorizedDomains = function () {
|
1413
|
+
var _this = this;
|
1414
|
+
// if this token is for a specific server or we don't have a portal
|
1415
|
+
// don't get the portal info because we cant get the authorizedCrossOriginDomains
|
1416
|
+
if (this.server || !this.portal) {
|
1417
|
+
return Promise.resolve(this);
|
1418
|
+
}
|
1419
|
+
return this.getPortal().then(function (portalInfo) {
|
1420
|
+
/**
|
1421
|
+
* Specific domains can be configured as secure.esri.com or https://secure.esri.com this
|
1422
|
+
* normalizes to https://secure.esri.com so we can use startsWith later.
|
1423
|
+
*/
|
1424
|
+
if (portalInfo.authorizedCrossOriginDomains &&
|
1425
|
+
portalInfo.authorizedCrossOriginDomains.length) {
|
1426
|
+
_this.trustedDomains = portalInfo.authorizedCrossOriginDomains
|
1427
|
+
.filter(function (d) { return !d.startsWith("http://"); })
|
1428
|
+
.map(function (d) {
|
1429
|
+
if (d.startsWith("https://")) {
|
1430
|
+
return d;
|
1431
|
+
}
|
1432
|
+
else {
|
1433
|
+
return "https://" + d;
|
1434
|
+
}
|
1435
|
+
});
|
1436
|
+
}
|
1437
|
+
return _this;
|
1438
|
+
});
|
1439
|
+
};
|
1440
|
+
return UserSession;
|
1441
|
+
}());
|
1442
|
+
|
359
1443
|
const solutionConfigurationCss = ".configuration-container{position:relative;height:100%;width:100%}.configuration{position:absolute;top:0px;right:0px;bottom:0px;left:0px;display:flex;padding:0.5rem;border:1px #808080 solid}.config-tabs{width:100%}.config-tab{width:100%}.config-solution{position:absolute;top:3.5rem;right:-1px;bottom:-1px;left:-1px;display:flex;padding:0.5rem}.config-inventory{display:inline;max-width:-moz-min-content;max-width:min-content;flex-grow:0;overflow-y:auto}.config-inventory-hide{display:none;max-width:-moz-min-content;max-width:min-content;flex-grow:0;overflow-y:auto}.config-item{position:relative;display:inline;flex-grow:1;overflow-y:auto;-webkit-margin-start:0.5rem;margin-inline-start:0.5rem}solution-contents{position:relative;height:100%}solution-item{position:relative;height:100%}solution-spatial-ref{position:relative;height:100%;width:100%;overflow-y:auto}";
|
360
1444
|
|
361
1445
|
const SolutionConfiguration = class {
|
@@ -370,7 +1454,7 @@ const SolutionConfiguration = class {
|
|
370
1454
|
this._solutionEditorHasChanges = false;
|
371
1455
|
this._solutionEditorHasErrors = false;
|
372
1456
|
this._canSave = false;
|
373
|
-
this.authentication =
|
1457
|
+
this.authentication = new UserSession({});
|
374
1458
|
this.solutionItemId = "";
|
375
1459
|
this.showLoading = false;
|
376
1460
|
this._currentEditItemId = "";
|