@itwin/ecschema-rpcinterface-tests 5.13.0-dev.15 → 5.13.0-dev.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dist/bundled-tests.js +521 -70
- package/lib/dist/bundled-tests.js.map +1 -1
- package/package.json +16 -16
|
@@ -91445,6 +91445,8 @@ const COPYRIGHT_NOTICE = `Copyright © 2017-${new Date().getFullYear()} <a href=
|
|
|
91445
91445
|
|
|
91446
91446
|
|
|
91447
91447
|
|
|
91448
|
+
/** CSS class name applied to the notice element of a logo card created by [[IModelApp.makeLogoCard]]. */
|
|
91449
|
+
const logoCardNoticeClassName = "logo-cards";
|
|
91448
91450
|
/**
|
|
91449
91451
|
* Global singleton that connects the user interface with the iTwin.js services. There can be only one IModelApp active in a session. All
|
|
91450
91452
|
* members of IModelApp are static, and it serves as a singleton object for gaining access to session information.
|
|
@@ -91957,10 +91959,21 @@ class IModelApp {
|
|
|
91957
91959
|
}
|
|
91958
91960
|
if (undefined !== opts.notice) {
|
|
91959
91961
|
if (typeof opts.notice === "string")
|
|
91960
|
-
IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className:
|
|
91962
|
+
IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className: logoCardNoticeClassName });
|
|
91961
91963
|
else
|
|
91962
91964
|
noticeCell.appendChild(opts.notice);
|
|
91963
91965
|
}
|
|
91966
|
+
else if (undefined !== opts.noticeLines) {
|
|
91967
|
+
// A <p> cannot legally contain flow content, so use a <div> when a line is an element.
|
|
91968
|
+
const containerTag = opts.noticeLines.some((line) => typeof line !== "string") ? "div" : "p";
|
|
91969
|
+
const notice = IModelApp.makeHTMLElement(containerTag, { parent: noticeCell, className: logoCardNoticeClassName });
|
|
91970
|
+
opts.noticeLines.forEach((line, index) => {
|
|
91971
|
+
if (index > 0)
|
|
91972
|
+
notice.appendChild(IModelApp.makeHTMLElement("br"));
|
|
91973
|
+
// Strings are appended as text nodes so they are never parsed as HTML.
|
|
91974
|
+
notice.append(line);
|
|
91975
|
+
});
|
|
91976
|
+
}
|
|
91964
91977
|
return card;
|
|
91965
91978
|
}
|
|
91966
91979
|
/** Make the logo card for the library itself. This card gets placed at the top of the stack.
|
|
@@ -93527,7 +93540,9 @@ let iModelJsCss = `
|
|
|
93527
93540
|
|
|
93528
93541
|
.logo-cards {
|
|
93529
93542
|
position:relative;
|
|
93530
|
-
width:100
|
|
93543
|
+
width:100%;
|
|
93544
|
+
margin-block-start:1em;
|
|
93545
|
+
margin-block-end:1em
|
|
93531
93546
|
}
|
|
93532
93547
|
|
|
93533
93548
|
.imodeljs-modal-overlay {
|
|
@@ -93571,7 +93586,7 @@ let iModelJsCss = `
|
|
|
93571
93586
|
max-width: calc(100% - (2 * var(--width-border))) !important;
|
|
93572
93587
|
width: unset !important;
|
|
93573
93588
|
}
|
|
93574
|
-
.imodeljs-about .logo-card-message p {
|
|
93589
|
+
.imodeljs-about .logo-card-message p, .imodeljs-about .logo-card-message .logo-cards {
|
|
93575
93590
|
margin-block-end: 1em;
|
|
93576
93591
|
}
|
|
93577
93592
|
.imodeljs-about .logo-cards {
|
|
@@ -96217,9 +96232,12 @@ class Google3dTilesProvider {
|
|
|
96217
96232
|
// Order by most occurances to least
|
|
96218
96233
|
// See https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions
|
|
96219
96234
|
const sortedCopyrights = [...copyrightMap.entries()].sort((a, b) => b[1] - a[1]);
|
|
96220
|
-
|
|
96221
|
-
|
|
96222
|
-
|
|
96235
|
+
const list = document.createElement("ul");
|
|
96236
|
+
for (const [key] of sortedCopyrights) {
|
|
96237
|
+
const item = document.createElement("li");
|
|
96238
|
+
item.textContent = key;
|
|
96239
|
+
list.appendChild(item);
|
|
96240
|
+
}
|
|
96223
96241
|
const iconSrc = document.createElement("img");
|
|
96224
96242
|
iconSrc.src = `${_IModelApp__WEBPACK_IMPORTED_MODULE_8__.IModelApp.publicPath}images/GoogleMaps_Logo_Gray.svg`;
|
|
96225
96243
|
iconSrc.style.padding = "10px 10px 5px 10px";
|
|
@@ -96227,7 +96245,7 @@ class Google3dTilesProvider {
|
|
|
96227
96245
|
iconSrc,
|
|
96228
96246
|
iconWidth: 98,
|
|
96229
96247
|
heading: "Google Photorealistic 3D Tiles",
|
|
96230
|
-
|
|
96248
|
+
noticeLines: ["Data provided by:", list],
|
|
96231
96249
|
}));
|
|
96232
96250
|
}
|
|
96233
96251
|
}
|
|
@@ -116617,7 +116635,7 @@ class GoogleMapsDecorator {
|
|
|
116617
116635
|
const copyrightText = sortedCopyrights.map(([key]) => ` • ${key}`).join("");
|
|
116618
116636
|
// Create and add element, offset to leave space for i.js and Google logos
|
|
116619
116637
|
const elem = document.createElement("div");
|
|
116620
|
-
elem.
|
|
116638
|
+
elem.textContent = copyrightText;
|
|
116621
116639
|
elem.style.color = "white";
|
|
116622
116640
|
elem.style.fontSize = "11px";
|
|
116623
116641
|
elem.style.textWrap = "wrap";
|
|
@@ -153924,7 +153942,11 @@ class OrbitGtTreeReference extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.R
|
|
|
153924
153942
|
if (this._name)
|
|
153925
153943
|
strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_6__.IModelApp.localization.getLocalizedString("iModelJs:TooltipInfo.Name")} ${this._name}`);
|
|
153926
153944
|
const div = document.createElement("div");
|
|
153927
|
-
|
|
153945
|
+
strings.forEach((str, index) => {
|
|
153946
|
+
if (index > 0)
|
|
153947
|
+
div.appendChild(document.createElement("br"));
|
|
153948
|
+
div.appendChild(document.createTextNode(str));
|
|
153949
|
+
});
|
|
153928
153950
|
return div;
|
|
153929
153951
|
}
|
|
153930
153952
|
}
|
|
@@ -155688,7 +155710,11 @@ class RealityTreeReference extends RealityModelTileTree.Reference {
|
|
|
155688
155710
|
if (-1 === key.indexOf("#")) // Avoid internal cesium
|
|
155689
155711
|
strings.push(`${key}: ${JSON.stringify(batch[key])}`);
|
|
155690
155712
|
const div = document.createElement("div");
|
|
155691
|
-
|
|
155713
|
+
strings.forEach((str, index) => {
|
|
155714
|
+
if (index > 0)
|
|
155715
|
+
div.appendChild(document.createElement("br"));
|
|
155716
|
+
div.appendChild(document.createTextNode(str));
|
|
155717
|
+
});
|
|
155692
155718
|
return div;
|
|
155693
155719
|
}
|
|
155694
155720
|
/** @deprecated in 5.0 - might be removed in next major version. Use [addAttributions] instead. */
|
|
@@ -156876,7 +156902,21 @@ class ArcGisUtilities {
|
|
|
156876
156902
|
*/
|
|
156877
156903
|
static async validateSource(args) {
|
|
156878
156904
|
const { source, ignoreCache, capabilitiesFilter } = args;
|
|
156879
|
-
|
|
156905
|
+
let metadata;
|
|
156906
|
+
try {
|
|
156907
|
+
metadata = await this.getServiceJson({ url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache });
|
|
156908
|
+
}
|
|
156909
|
+
catch (err) {
|
|
156910
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError) {
|
|
156911
|
+
let blockedOrigin;
|
|
156912
|
+
try {
|
|
156913
|
+
blockedOrigin = new URL(err.url).origin;
|
|
156914
|
+
}
|
|
156915
|
+
catch { /* non-hierarchical URL */ }
|
|
156916
|
+
return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
156917
|
+
}
|
|
156918
|
+
throw err;
|
|
156919
|
+
}
|
|
156880
156920
|
const json = metadata?.content;
|
|
156881
156921
|
if (json === undefined) {
|
|
156882
156922
|
return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.InvalidUrl };
|
|
@@ -156939,6 +156979,9 @@ class ArcGisUtilities {
|
|
|
156939
156979
|
* @param password Password to use for legacy token based security
|
|
156940
156980
|
* @param ignoreCache Flag to skip cache lookup (i.e. force a new server request)
|
|
156941
156981
|
* @param requireToken Flag to indicate if a token is required
|
|
156982
|
+
* @throws [[MapLayerUntrustedOriginError]] if an NTLM/Negotiate challenge could not be answered because
|
|
156983
|
+
* the URL's origin is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]);
|
|
156984
|
+
* all other errors are caught and reported by returning `undefined`.
|
|
156942
156985
|
*/
|
|
156943
156986
|
static async getServiceJson(args) {
|
|
156944
156987
|
const { url, formatId, userName, password, queryParams, ignoreCache, requireToken } = args;
|
|
@@ -156974,8 +157017,17 @@ class ArcGisUtilities {
|
|
|
156974
157017
|
}
|
|
156975
157018
|
let response = await fetch(tmpUrl, { method: "GET" });
|
|
156976
157019
|
if (response.status === 401 && !requireToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
156977
|
-
//
|
|
156978
|
-
|
|
157020
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
157021
|
+
const challengedUrl = response.url || tmpUrl.toString();
|
|
157022
|
+
if (!_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
|
|
157023
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError(challengedUrl);
|
|
157024
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
|
|
157025
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
|
|
157026
|
+
response = await fetch(challengedUrl, {
|
|
157027
|
+
method: "GET",
|
|
157028
|
+
credentials: "include",
|
|
157029
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
157030
|
+
});
|
|
156979
157031
|
}
|
|
156980
157032
|
// Append security token when corresponding error code is returned by ArcGIS service
|
|
156981
157033
|
let errorCode = await ArcGisUtilities.checkForResponseErrorCode(response);
|
|
@@ -156997,8 +157049,10 @@ class ArcGisUtilities {
|
|
|
156997
157049
|
ArcGisUtilities._serviceCache.set(url, (errorCode === undefined ? info : undefined));
|
|
156998
157050
|
return info; // Always return json, even though it contains an error code.
|
|
156999
157051
|
}
|
|
157000
|
-
catch {
|
|
157052
|
+
catch (err) {
|
|
157001
157053
|
ArcGisUtilities._serviceCache.set(url, undefined);
|
|
157054
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError)
|
|
157055
|
+
throw err; // propagate so callers can report the blocked origin
|
|
157002
157056
|
return undefined;
|
|
157003
157057
|
}
|
|
157004
157058
|
}
|
|
@@ -157160,7 +157214,9 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
|
|
|
157160
157214
|
try {
|
|
157161
157215
|
metadata = await _tile_internal__WEBPACK_IMPORTED_MODULE_0__.ArcGisUtilities.getServiceJson({ url: this._settings.url, formatId: this._settings.formatId, userName: this._settings.userName, password: this._settings.password, queryParams: this._settings.collectQueryParams() });
|
|
157162
157216
|
}
|
|
157163
|
-
catch {
|
|
157217
|
+
catch (err) {
|
|
157218
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError)
|
|
157219
|
+
this.reportBlockedOrigin(err.url);
|
|
157164
157220
|
}
|
|
157165
157221
|
if (metadata && metadata.accessTokenRequired) {
|
|
157166
157222
|
const accessClient = _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.getAccessClient(this._settings.formatId);
|
|
@@ -157208,12 +157264,32 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
|
|
|
157208
157264
|
await this._firstRequestPromise;
|
|
157209
157265
|
let response;
|
|
157210
157266
|
try {
|
|
157211
|
-
|
|
157267
|
+
const requestUrl = urlObj.toString();
|
|
157268
|
+
const includeCredentials = this.includeUserCredentials(requestUrl);
|
|
157269
|
+
response = await fetch(urlObj, {
|
|
157270
|
+
...options,
|
|
157271
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
157272
|
+
redirect: includeCredentials ? this.credentialedRedirect : options?.redirect,
|
|
157273
|
+
});
|
|
157274
|
+
if (includeCredentials)
|
|
157275
|
+
this.checkCredentialedRedirect(requestUrl, response);
|
|
157212
157276
|
if (response.status === 401 && !this._lastAccessToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
157213
|
-
//
|
|
157214
|
-
|
|
157215
|
-
if (
|
|
157216
|
-
|
|
157277
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
157278
|
+
const challengedUrl = response.url || requestUrl;
|
|
157279
|
+
if (this.isSsoAllowed(challengedUrl)) {
|
|
157280
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
|
|
157281
|
+
this.logUntrustedOriginUse(challengedUrl);
|
|
157282
|
+
response = await fetch(challengedUrl, {
|
|
157283
|
+
...options,
|
|
157284
|
+
credentials: "include",
|
|
157285
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
157286
|
+
});
|
|
157287
|
+
if (response.status === 200) {
|
|
157288
|
+
this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
|
|
157289
|
+
}
|
|
157290
|
+
}
|
|
157291
|
+
else {
|
|
157292
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
157217
157293
|
}
|
|
157218
157294
|
}
|
|
157219
157295
|
if ((this._lastAccessToken && response.status === 400)
|
|
@@ -157426,8 +157502,12 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
157426
157502
|
}
|
|
157427
157503
|
async initialize() {
|
|
157428
157504
|
const metadata = await this.getServiceJson();
|
|
157429
|
-
if (metadata?.content === undefined)
|
|
157505
|
+
if (metadata?.content === undefined) {
|
|
157506
|
+
// By returning (i.e., not throwing), we ensure the tile tree gets created and the current provider is preserved to report status.
|
|
157507
|
+
if (this.status === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.UntrustedOrigin)
|
|
157508
|
+
return;
|
|
157430
157509
|
throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_0__.ServerError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_5__.IModelStatus.ValidationFailed, "");
|
|
157510
|
+
}
|
|
157431
157511
|
const json = metadata.content;
|
|
157432
157512
|
if (json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.TokenRequired
|
|
157433
157513
|
|| json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.InvalidToken
|
|
@@ -157512,7 +157592,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
157512
157592
|
addLogoCards(cards) {
|
|
157513
157593
|
if (!cards.dataset.arcGisLogoCard) {
|
|
157514
157594
|
cards.dataset.arcGisLogoCard = "true";
|
|
157515
|
-
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS",
|
|
157595
|
+
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS", noticeLines: [this._copyrightText] }));
|
|
157516
157596
|
}
|
|
157517
157597
|
}
|
|
157518
157598
|
async addAttributions(cards, _vp) {
|
|
@@ -157553,7 +157633,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
157553
157633
|
if (json && Array.isArray(json.results)) {
|
|
157554
157634
|
for (const result of json.results) {
|
|
157555
157635
|
if (result.attributes !== undefined && result.attributes[result.displayFieldName] !== undefined) {
|
|
157556
|
-
const thisString = `${result.displayFieldName}: ${result.attributes[result.displayFieldName]}`;
|
|
157636
|
+
const thisString = `${(0,_tile_internal__WEBPACK_IMPORTED_MODULE_2__.escapeHtml)(String(result.displayFieldName))}: ${(0,_tile_internal__WEBPACK_IMPORTED_MODULE_2__.escapeHtml)(String(result.attributes[result.displayFieldName]))}`;
|
|
157557
157637
|
if (!stringSet.has(thisString)) {
|
|
157558
157638
|
strings.push(thisString);
|
|
157559
157639
|
stringSet.add(thisString);
|
|
@@ -157869,13 +157949,7 @@ class BingMapsImageryLayerProvider extends _tile_internal__WEBPACK_IMPORTED_MODU
|
|
|
157869
157949
|
const copyrights = [];
|
|
157870
157950
|
for (const match of matchingAttributions)
|
|
157871
157951
|
copyrights.push(match.copyrightMessage);
|
|
157872
|
-
|
|
157873
|
-
for (let i = 0; i < copyrights.length; ++i) {
|
|
157874
|
-
if (i > 0)
|
|
157875
|
-
copyrightMsg += "<br>";
|
|
157876
|
-
copyrightMsg += copyrights[i];
|
|
157877
|
-
}
|
|
157878
|
-
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.makeLogoCard({ iconSrc: `${_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.publicPath}images/bing.svg`, heading: "Microsoft Bing", notice: copyrightMsg }));
|
|
157952
|
+
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.makeLogoCard({ iconSrc: `${_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.publicPath}images/bing.svg`, heading: "Microsoft Bing", noticeLines: copyrights }));
|
|
157879
157953
|
}
|
|
157880
157954
|
async addAttributions(cards, vp) {
|
|
157881
157955
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -158484,7 +158558,10 @@ class WmsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE
|
|
|
158484
158558
|
// Don't throw error if unauthorized status:
|
|
158485
158559
|
// We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
|
|
158486
158560
|
// When credentials will be provided, a new provider will be created, and initialization should be fine.
|
|
158487
|
-
if (error
|
|
158561
|
+
if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError) {
|
|
158562
|
+
this.reportBlockedOrigin(error.url);
|
|
158563
|
+
}
|
|
158564
|
+
else if (error?.status === 401) {
|
|
158488
158565
|
this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerImageryProviderStatus.RequireAuth);
|
|
158489
158566
|
}
|
|
158490
158567
|
else {
|
|
@@ -158646,7 +158723,8 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
|
|
|
158646
158723
|
}
|
|
158647
158724
|
async initialize() {
|
|
158648
158725
|
try {
|
|
158649
|
-
this.
|
|
158726
|
+
const credentials = (this._settings.userName && this._settings.password ? { user: this._settings.userName, password: this._settings.password } : undefined);
|
|
158727
|
+
this._capabilities = await _tile_internal__WEBPACK_IMPORTED_MODULE_2__.WmtsCapabilities.create(this._baseUrl, credentials);
|
|
158650
158728
|
this.initPreferredTileMatrixSet();
|
|
158651
158729
|
this.initPreferredStyle();
|
|
158652
158730
|
this.initDisplayedLayer();
|
|
@@ -158659,7 +158737,10 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
|
|
|
158659
158737
|
// Don't throw error if unauthorized status:
|
|
158660
158738
|
// We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
|
|
158661
158739
|
// When credentials will be provided, a new provider will be created, and initialization should be fine.
|
|
158662
|
-
if (error
|
|
158740
|
+
if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerUntrustedOriginError) {
|
|
158741
|
+
this.reportBlockedOrigin(error.url);
|
|
158742
|
+
}
|
|
158743
|
+
else if (error?.status === 401) {
|
|
158663
158744
|
this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.RequireAuth);
|
|
158664
158745
|
}
|
|
158665
158746
|
else {
|
|
@@ -159470,14 +159551,18 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
159470
159551
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
159471
159552
|
/* harmony export */ WmsUtilities: () => (/* binding */ WmsUtilities)
|
|
159472
159553
|
/* harmony export */ });
|
|
159473
|
-
/* harmony import */ var
|
|
159474
|
-
/* harmony import */ var
|
|
159554
|
+
/* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
|
|
159555
|
+
/* harmony import */ var _request_Request__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../request/Request */ "../../core/frontend/lib/esm/request/Request.js");
|
|
159556
|
+
/* harmony import */ var _request_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../request/utils */ "../../core/frontend/lib/esm/request/utils.js");
|
|
159557
|
+
/* harmony import */ var _tile_internal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../tile/internal */ "../../core/frontend/lib/esm/tile/internal.js");
|
|
159475
159558
|
/*---------------------------------------------------------------------------------------------
|
|
159476
159559
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
159477
159560
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
159478
159561
|
*--------------------------------------------------------------------------------------------*/
|
|
159479
159562
|
|
|
159480
159563
|
|
|
159564
|
+
|
|
159565
|
+
|
|
159481
159566
|
/** @packageDocumentation
|
|
159482
159567
|
* @module Tiles
|
|
159483
159568
|
*/
|
|
@@ -159494,16 +159579,35 @@ class WmsUtilities {
|
|
|
159494
159579
|
static async fetchXml(url, credentials) {
|
|
159495
159580
|
let headers;
|
|
159496
159581
|
if (credentials && credentials.user && credentials.password) {
|
|
159497
|
-
|
|
159498
|
-
|
|
159582
|
+
// Basic credentials are considered settings-derived credentials for this source. When the registry is
|
|
159583
|
+
// enforcing trusted origins, the source URL itself is the only implicitly trusted origin for basic auth;
|
|
159584
|
+
// opaque/custom-protocol URLs have no network origin and must therefore be treated as untrusted.
|
|
159585
|
+
const allowBasicAuth = !_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins
|
|
159586
|
+
|| _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, url);
|
|
159587
|
+
if (allowBasicAuth) {
|
|
159588
|
+
headers = new Headers();
|
|
159589
|
+
(0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.setBasicAuthorization)(headers, credentials);
|
|
159590
|
+
}
|
|
159499
159591
|
}
|
|
159500
159592
|
let response = await fetch(url, { method: "GET", headers });
|
|
159501
|
-
if (!credentials && response.status === 401
|
|
159502
|
-
|
|
159503
|
-
|
|
159593
|
+
if (!headers && credentials && credentials.user && credentials.password && (response.status === 401 || response.status === 403)) {
|
|
159594
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(url);
|
|
159595
|
+
}
|
|
159596
|
+
if (!credentials && response.status === 401 && (0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
159597
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
159598
|
+
const challengedUrl = response.url || url;
|
|
159599
|
+
if (!_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
|
|
159600
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(challengedUrl);
|
|
159601
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
|
|
159602
|
+
// We got a http 401 challenge, lets try SSO (i.e. Windows Authentication).
|
|
159603
|
+
response = await fetch(challengedUrl, {
|
|
159604
|
+
method: "GET",
|
|
159605
|
+
credentials: "include",
|
|
159606
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
159607
|
+
});
|
|
159504
159608
|
}
|
|
159505
159609
|
if (response.status !== 200)
|
|
159506
|
-
throw new
|
|
159610
|
+
throw new _request_Request__WEBPACK_IMPORTED_MODULE_1__.HttpResponseError(response.status, await response.text());
|
|
159507
159611
|
return response.text();
|
|
159508
159612
|
}
|
|
159509
159613
|
}
|
|
@@ -171917,6 +172021,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
171917
172021
|
/* harmony export */ MapLayerSourceStatus: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSourceStatus),
|
|
171918
172022
|
/* harmony export */ MapLayerSources: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSources),
|
|
171919
172023
|
/* harmony export */ MapLayerTileTreeReference: () => (/* reexport safe */ _map_MapLayerTileTreeReference__WEBPACK_IMPORTED_MODULE_64__.MapLayerTileTreeReference),
|
|
172024
|
+
/* harmony export */ MapLayerUntrustedOriginError: () => (/* reexport safe */ _map_MapLayerFormatRegistry__WEBPACK_IMPORTED_MODULE_42__.MapLayerUntrustedOriginError),
|
|
171920
172025
|
/* harmony export */ MapTile: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTile),
|
|
171921
172026
|
/* harmony export */ MapTileLoader: () => (/* reexport safe */ _internal_tile_map_MapTileLoader__WEBPACK_IMPORTED_MODULE_72__.MapTileLoader),
|
|
171922
172027
|
/* harmony export */ MapTileProjection: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTileProjection),
|
|
@@ -172012,6 +172117,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
172012
172117
|
/* harmony export */ decodeMeshoptBuffer: () => (/* reexport safe */ _internal_tile_MeshoptCompression__WEBPACK_IMPORTED_MODULE_93__.decodeMeshoptBuffer),
|
|
172013
172118
|
/* harmony export */ deflateCoordinates: () => (/* reexport safe */ _internal_tile_map_ImageryProviders_CoordinatesUtils__WEBPACK_IMPORTED_MODULE_47__.deflateCoordinates),
|
|
172014
172119
|
/* harmony export */ disposeTileTreesForGeometricModels: () => (/* reexport safe */ _internal_tile_PrimaryTileTree__WEBPACK_IMPORTED_MODULE_82__.disposeTileTreesForGeometricModels),
|
|
172120
|
+
/* harmony export */ escapeHtml: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.escapeHtml),
|
|
172015
172121
|
/* harmony export */ getCesiumAccessClient: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessClient),
|
|
172016
172122
|
/* harmony export */ getCesiumAccessTokenAndEndpointUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessTokenAndEndpointUrl),
|
|
172017
172123
|
/* harmony export */ getCesiumAssetUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAssetUrl),
|
|
@@ -172031,7 +172137,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
172031
172137
|
/* harmony export */ readImdlContent: () => (/* reexport safe */ _ImdlReader__WEBPACK_IMPORTED_MODULE_35__.readImdlContent),
|
|
172032
172138
|
/* harmony export */ readPntsColors: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPntsColors),
|
|
172033
172139
|
/* harmony export */ readPointCloudTileContent: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPointCloudTileContent),
|
|
172034
|
-
/* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic)
|
|
172140
|
+
/* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic),
|
|
172141
|
+
/* harmony export */ tryGetOrigin: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.tryGetOrigin)
|
|
172035
172142
|
/* harmony export */ });
|
|
172036
172143
|
/* harmony import */ var _internal_tile_ViewFlagOverrides__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../internal/tile/ViewFlagOverrides */ "../../core/frontend/lib/esm/internal/tile/ViewFlagOverrides.js");
|
|
172037
172144
|
/* harmony import */ var _map_MapCartoRectangle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map/MapCartoRectangle */ "../../core/frontend/lib/esm/tile/map/MapCartoRectangle.js");
|
|
@@ -173730,7 +173837,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
173730
173837
|
__webpack_require__.r(__webpack_exports__);
|
|
173731
173838
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
173732
173839
|
/* harmony export */ MapLayerFormat: () => (/* binding */ MapLayerFormat),
|
|
173733
|
-
/* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry)
|
|
173840
|
+
/* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry),
|
|
173841
|
+
/* harmony export */ MapLayerUntrustedOriginError: () => (/* binding */ MapLayerUntrustedOriginError)
|
|
173734
173842
|
/* harmony export */ });
|
|
173735
173843
|
/* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
|
|
173736
173844
|
/* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
|
|
@@ -173745,7 +173853,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
173745
173853
|
|
|
173746
173854
|
|
|
173747
173855
|
|
|
173748
|
-
const loggerCategory = "
|
|
173856
|
+
const loggerCategory = "MapLayerFormatRegistry";
|
|
173749
173857
|
/**
|
|
173750
173858
|
* Class representing a map-layer format.
|
|
173751
173859
|
* Each format has it's unique 'formatId' string, used to uniquely identify a format in the [[MapLayerFormatRegistry]].
|
|
@@ -173794,16 +173902,127 @@ class MapLayerFormat {
|
|
|
173794
173902
|
return undefined;
|
|
173795
173903
|
}
|
|
173796
173904
|
}
|
|
173905
|
+
/** Error thrown when an NTLM or Negotiate http 401 challenge could not be answered because the request
|
|
173906
|
+
* URL's origin is not listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]]
|
|
173907
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
173908
|
+
* Thrown by the static map-layer utilities (e.g. capabilities / service-metadata fetches) that have no
|
|
173909
|
+
* provider instance on which to report the blocked origin; callers convert it to
|
|
173910
|
+
* [[MapLayerImageryProviderStatus.UntrustedOrigin]] (provider initialization) or
|
|
173911
|
+
* [[MapLayerSourceStatus.UntrustedOrigin]] (source validation).
|
|
173912
|
+
* @internal
|
|
173913
|
+
*/
|
|
173914
|
+
class MapLayerUntrustedOriginError extends Error {
|
|
173915
|
+
/** The URL of the request whose authentication challenge was left unanswered. */
|
|
173916
|
+
url;
|
|
173917
|
+
constructor(url) {
|
|
173918
|
+
super(`Authentication blocked: origin of '${url}' is not listed in MapLayerFormatRegistry.trustedCredentialsOrigins`);
|
|
173919
|
+
this.url = url;
|
|
173920
|
+
}
|
|
173921
|
+
}
|
|
173797
173922
|
/**
|
|
173798
173923
|
* A registry of MapLayerFormats identified by their unique format IDs. The registry can be accessed via [[IModelApp.mapLayerFormatRegistry]].
|
|
173799
173924
|
* @public
|
|
173800
173925
|
*/
|
|
173801
173926
|
class MapLayerFormatRegistry {
|
|
173802
173927
|
_configOptions;
|
|
173928
|
+
_trustedCredentialsOrigins = [];
|
|
173929
|
+
/** Opt-in enforcement of origin restrictions on map-layer credentials.
|
|
173930
|
+
* When enabled, map layer providers:
|
|
173931
|
+
* - attach the basic-auth credentials stored in the layer settings only to requests targeting the origin
|
|
173932
|
+
* of the layer's settings URL or an origin listed in [[trustedCredentialsOrigins]];
|
|
173933
|
+
* - retry a request with browser credentials included (i.e. SSO / Windows Authentication) after an NTLM
|
|
173934
|
+
* or Negotiate http 401 challenge only for origins explicitly listed in [[trustedCredentialsOrigins]]
|
|
173935
|
+
* (the settings-URL origin is NOT implicitly trusted for SSO, since map-layer URLs may originate from
|
|
173936
|
+
* untrusted user input while SSO shares the user's ambient identity).
|
|
173937
|
+
* Default is false, preserving the legacy behavior of sending credentials to any request URL.
|
|
173938
|
+
* @beta
|
|
173939
|
+
*/
|
|
173940
|
+
restrictCredentialsToTrustedOrigins = false;
|
|
173803
173941
|
constructor(opts) {
|
|
173804
173942
|
this._configOptions = opts ?? {};
|
|
173805
173943
|
_internal__WEBPACK_IMPORTED_MODULE_2__.internalMapLayerImageryFormats.forEach((format) => this.register(format));
|
|
173806
173944
|
}
|
|
173945
|
+
/** Origins (e.g. "https://tiles.example.com") to which map layer providers may send credentials —
|
|
173946
|
+
* both the basic-auth credentials stored in the layer settings and browser credentials for
|
|
173947
|
+
* SSO (i.e. Windows Authentication) retries after an NTLM or Negotiate http 401 challenge.
|
|
173948
|
+
* Only enforced when [[restrictCredentialsToTrustedOrigins]] is enabled.
|
|
173949
|
+
* For basic-auth, the origin of each map layer's settings URL is always implicitly trusted; for SSO,
|
|
173950
|
+
* origins must be explicitly listed here.
|
|
173951
|
+
* Entries are normalized to their origin (scheme + host + port); only `http:` and `https:` URLs are accepted,
|
|
173952
|
+
* and any other entry is ignored and logged. Opaque schemes such as `file:`, `data:`, `about:` and custom
|
|
173953
|
+
* Electron protocols are rejected because they all share the same serialized origin, so trusting one would
|
|
173954
|
+
* trust every other.
|
|
173955
|
+
* @beta
|
|
173956
|
+
*/
|
|
173957
|
+
get trustedCredentialsOrigins() {
|
|
173958
|
+
return this._trustedCredentialsOrigins;
|
|
173959
|
+
}
|
|
173960
|
+
set trustedCredentialsOrigins(origins) {
|
|
173961
|
+
const normalized = [];
|
|
173962
|
+
for (const entry of origins) {
|
|
173963
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(entry);
|
|
173964
|
+
if (origin !== undefined)
|
|
173965
|
+
normalized.push(origin);
|
|
173966
|
+
else
|
|
173967
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `trustedCredentialsOrigins: ignoring '${entry}'; entries must be http or https URLs.`);
|
|
173968
|
+
}
|
|
173969
|
+
this._trustedCredentialsOrigins = normalized;
|
|
173970
|
+
}
|
|
173971
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
173972
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
173973
|
+
* Always true unless [[restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
173974
|
+
* When enabled, the URL's origin must be explicitly listed in [[trustedCredentialsOrigins]];
|
|
173975
|
+
* unlike basic-auth, the settings-URL origin is NOT implicitly trusted because SSO shares the user's
|
|
173976
|
+
* ambient identity, and map-layer URLs may originate from untrusted user input.
|
|
173977
|
+
* @internal
|
|
173978
|
+
*/
|
|
173979
|
+
isSsoAllowed(url) {
|
|
173980
|
+
if (!this.restrictCredentialsToTrustedOrigins)
|
|
173981
|
+
return true;
|
|
173982
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
|
|
173983
|
+
// Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
|
|
173984
|
+
return origin !== undefined && this._trustedCredentialsOrigins.includes(origin);
|
|
173985
|
+
}
|
|
173986
|
+
/** Returns true if the basic-auth credentials belonging to a map-layer source or settings URL may be
|
|
173987
|
+
* attached to a request to the given URL. Always true unless [[restrictCredentialsToTrustedOrigins]]
|
|
173988
|
+
* is enabled (opt-in). When enabled, the origin of `settingsUrl` is implicitly trusted (the credentials
|
|
173989
|
+
* belong to that server); any other origin must be listed in [[trustedCredentialsOrigins]].
|
|
173990
|
+
* @internal
|
|
173991
|
+
*/
|
|
173992
|
+
isCredentialsSharingAllowed(url, settingsUrl) {
|
|
173993
|
+
if (!this.restrictCredentialsToTrustedOrigins)
|
|
173994
|
+
return true;
|
|
173995
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
|
|
173996
|
+
if (origin === undefined)
|
|
173997
|
+
return false;
|
|
173998
|
+
if (origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
|
|
173999
|
+
return true;
|
|
174000
|
+
// Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
|
|
174001
|
+
return this._trustedCredentialsOrigins.includes(origin);
|
|
174002
|
+
}
|
|
174003
|
+
/** Origins for which a "credentials sent to untrusted origin" warning was already logged;
|
|
174004
|
+
* used to log the discovery warning only once per origin.
|
|
174005
|
+
*/
|
|
174006
|
+
_untrustedUseLogged = new Set();
|
|
174007
|
+
/** Logs a warning (once per origin) when credentials are sent to an origin that would be blocked
|
|
174008
|
+
* if [[restrictCredentialsToTrustedOrigins]] were enabled.
|
|
174009
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
174010
|
+
* If `settingsUrl` is supplied, requests sharing its origin are not logged, since that origin is
|
|
174011
|
+
* implicitly trusted for basic-auth.
|
|
174012
|
+
* @internal
|
|
174013
|
+
*/
|
|
174014
|
+
logUntrustedOriginUse(url, settingsUrl) {
|
|
174015
|
+
if (this.restrictCredentialsToTrustedOrigins)
|
|
174016
|
+
return; // restriction active; nothing to preview
|
|
174017
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url) ?? url;
|
|
174018
|
+
if (settingsUrl !== undefined && origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
|
|
174019
|
+
return; // implicitly trusted for basic-auth
|
|
174020
|
+
if (this._untrustedUseLogged.has(origin) || this._trustedCredentialsOrigins.includes(origin))
|
|
174021
|
+
return;
|
|
174022
|
+
this._untrustedUseLogged.add(origin);
|
|
174023
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `Credentials sent to origin '${origin}' which is not in MapLayerFormatRegistry.trustedCredentialsOrigins; `
|
|
174024
|
+
+ "this request would be blocked if restrictCredentialsToTrustedOrigins were enabled.");
|
|
174025
|
+
}
|
|
173807
174026
|
_formats = new Map();
|
|
173808
174027
|
isRegistered(formatId) { return this._formats.get(formatId) !== undefined; }
|
|
173809
174028
|
register(formatClass) {
|
|
@@ -173969,6 +174188,14 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat {
|
|
|
173969
174188
|
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
|
|
173970
174189
|
}
|
|
173971
174190
|
catch (err) {
|
|
174191
|
+
if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
|
|
174192
|
+
let blockedOrigin;
|
|
174193
|
+
try {
|
|
174194
|
+
blockedOrigin = new URL(err.url).origin;
|
|
174195
|
+
}
|
|
174196
|
+
catch { /* non-hierarchical URL */ }
|
|
174197
|
+
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
174198
|
+
}
|
|
173972
174199
|
let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
|
|
173973
174200
|
if (err?.status === 401) {
|
|
173974
174201
|
status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
|
|
@@ -174034,6 +174261,14 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat {
|
|
|
174034
174261
|
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
|
|
174035
174262
|
}
|
|
174036
174263
|
catch (err) {
|
|
174264
|
+
if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
|
|
174265
|
+
let blockedOrigin;
|
|
174266
|
+
try {
|
|
174267
|
+
blockedOrigin = new URL(err.url).origin;
|
|
174268
|
+
}
|
|
174269
|
+
catch { /* non-hierarchical URL */ }
|
|
174270
|
+
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
174271
|
+
}
|
|
174037
174272
|
let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
|
|
174038
174273
|
if (err?.status === 401) {
|
|
174039
174274
|
status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
|
|
@@ -174098,7 +174333,9 @@ const internalMapLayerImageryFormats = [WmsMapLayerFormat, WmtsMapLayerFormat, A
|
|
|
174098
174333
|
__webpack_require__.r(__webpack_exports__);
|
|
174099
174334
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
174100
174335
|
/* harmony export */ MapLayerImageryProvider: () => (/* binding */ MapLayerImageryProvider),
|
|
174101
|
-
/* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus)
|
|
174336
|
+
/* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus),
|
|
174337
|
+
/* harmony export */ escapeHtml: () => (/* binding */ escapeHtml),
|
|
174338
|
+
/* harmony export */ tryGetOrigin: () => (/* binding */ tryGetOrigin)
|
|
174102
174339
|
/* harmony export */ });
|
|
174103
174340
|
/* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
|
|
174104
174341
|
/* harmony import */ var _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @itwin/core-common */ "../../core/common/lib/esm/core-common.js");
|
|
@@ -174125,6 +174362,34 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
174125
174362
|
const tileImageSize = 256, untiledImageSize = 256;
|
|
174126
174363
|
const earthRadius = 6378137;
|
|
174127
174364
|
const doDebugToolTips = false;
|
|
174365
|
+
/** Escapes HTML metacharacters so the text renders literally when assigned to `innerHTML`.
|
|
174366
|
+
* Use for any server- or user-supplied string that ends up in the map tooltip, which is rendered
|
|
174367
|
+
* as HTML by [[MapLayerTileTreeReference.getToolTip]].
|
|
174368
|
+
* @internal
|
|
174369
|
+
*/
|
|
174370
|
+
function escapeHtml(text) {
|
|
174371
|
+
return text.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
174372
|
+
}
|
|
174373
|
+
/** Returns the origin (scheme + host + port) of the given URL, or undefined if it cannot be parsed or does
|
|
174374
|
+
* not denote a distinct network origin.
|
|
174375
|
+
*
|
|
174376
|
+
* Only `http:` and `https:` URLs yield an origin. Every other scheme is rejected because opaque URLs
|
|
174377
|
+
* — `file:`, `data:`, `about:`, `blob:null`, and the custom protocols Electron hosts commonly register —
|
|
174378
|
+
* all serialize to the literal string `"null"`. Comparing those would make unrelated URLs look same-origin,
|
|
174379
|
+
* so a single trusted entry could unlock all of them. Callers use this for credential-trust decisions, and
|
|
174380
|
+
* returning `undefined` keeps those decisions fail-closed.
|
|
174381
|
+
* @internal
|
|
174382
|
+
*/
|
|
174383
|
+
function tryGetOrigin(url) {
|
|
174384
|
+
let parsed;
|
|
174385
|
+
try {
|
|
174386
|
+
parsed = new URL(url);
|
|
174387
|
+
}
|
|
174388
|
+
catch {
|
|
174389
|
+
return undefined;
|
|
174390
|
+
}
|
|
174391
|
+
return (parsed.protocol === "http:" || parsed.protocol === "https:") ? parsed.origin : undefined;
|
|
174392
|
+
}
|
|
174128
174393
|
/** The status of the map layer imagery provider that lets you know if authentication is needed to request tiles.
|
|
174129
174394
|
* @public
|
|
174130
174395
|
*/
|
|
@@ -174132,6 +174397,12 @@ var MapLayerImageryProviderStatus;
|
|
|
174132
174397
|
(function (MapLayerImageryProviderStatus) {
|
|
174133
174398
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["Valid"] = 0] = "Valid";
|
|
174134
174399
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["RequireAuth"] = 1] = "RequireAuth";
|
|
174400
|
+
/** A request received an authentication challenge, but credentials were withheld because the request origin
|
|
174401
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
174402
|
+
* The blocked origins are available via [[MapLayerImageryProvider.blockedOrigins]].
|
|
174403
|
+
* @beta
|
|
174404
|
+
*/
|
|
174405
|
+
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["UntrustedOrigin"] = 2] = "UntrustedOrigin";
|
|
174135
174406
|
})(MapLayerImageryProviderStatus || (MapLayerImageryProviderStatus = {}));
|
|
174136
174407
|
/** Abstract class for map layer imagery providers.
|
|
174137
174408
|
* Map layer imagery providers request and provide tile images and other data. Each map layer from a separate source needs its own imagery provider object.
|
|
@@ -174149,7 +174420,41 @@ class MapLayerImageryProvider {
|
|
|
174149
174420
|
/** @internal */
|
|
174150
174421
|
_status = MapLayerImageryProviderStatus.Valid;
|
|
174151
174422
|
/** @internal */
|
|
174152
|
-
|
|
174423
|
+
_blockedOrigins = new Set();
|
|
174424
|
+
/** Origins of requests for which credentials were withheld because they are not trusted
|
|
174425
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
174426
|
+
* Populated when [[status]] transitions to [[MapLayerImageryProviderStatus.UntrustedOrigin]];
|
|
174427
|
+
* [[onStatusChanged]] is raised again each time a new origin is added. Cleared by [[resetStatus]].
|
|
174428
|
+
* @beta
|
|
174429
|
+
*/
|
|
174430
|
+
get blockedOrigins() { return [...this._blockedOrigins]; }
|
|
174431
|
+
/** Origins for which a previous SSO handshake (i.e. Windows Authentication) succeeded.
|
|
174432
|
+
* Browser credentials are only included for subsequent requests targeting these origins,
|
|
174433
|
+
* so that a successful handshake with one host does not leak credentials to other hosts
|
|
174434
|
+
* this provider may contact.
|
|
174435
|
+
* @internal
|
|
174436
|
+
*/
|
|
174437
|
+
_ssoSucceededOrigins = new Set();
|
|
174438
|
+
/** Returns true if browser credentials should be included for the given URL because a previous
|
|
174439
|
+
* SSO handshake succeeded for its origin AND the origin is still allowed by the current policy
|
|
174440
|
+
* (see [[MapLayerFormatRegistry.isSsoAllowed]]). Re-checking the policy ensures a handshake recorded
|
|
174441
|
+
* while enforcement was disabled — or before an origin was removed from
|
|
174442
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]] — does not keep latching credentials on.
|
|
174443
|
+
* @internal
|
|
174444
|
+
*/
|
|
174445
|
+
includeUserCredentials(url) {
|
|
174446
|
+
const origin = tryGetOrigin(url);
|
|
174447
|
+
return origin !== undefined && this._ssoSucceededOrigins.has(origin) && this.isSsoAllowed(url);
|
|
174448
|
+
}
|
|
174449
|
+
/** Records that an SSO handshake succeeded for the given URL's origin, so subsequent requests
|
|
174450
|
+
* to that origin include browser credentials without going through another 401 challenge.
|
|
174451
|
+
* @internal
|
|
174452
|
+
*/
|
|
174453
|
+
recordSsoSucceeded(url) {
|
|
174454
|
+
const origin = tryGetOrigin(url);
|
|
174455
|
+
if (origin !== undefined)
|
|
174456
|
+
this._ssoSucceededOrigins.add(origin);
|
|
174457
|
+
}
|
|
174153
174458
|
/** @internal */
|
|
174154
174459
|
onFirstRequestCompleted = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BeEvent();
|
|
174155
174460
|
/** @internal */
|
|
@@ -174165,7 +174470,17 @@ class MapLayerImageryProvider {
|
|
|
174165
174470
|
* @public
|
|
174166
174471
|
*/
|
|
174167
174472
|
get supportsMapFeatureInfo() { return false; }
|
|
174168
|
-
|
|
174473
|
+
/** Reset the provider's status to [[MapLayerImageryProviderStatus.Valid]] and clear the list of
|
|
174474
|
+
* [[blockedOrigins]] accumulated while in the [[MapLayerImageryProviderStatus.UntrustedOrigin]] state.
|
|
174475
|
+
* Raises [[onStatusChanged]] if the status actually changes.
|
|
174476
|
+
* Typically called after the user has provided credentials or the application has updated
|
|
174477
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]], so that subsequent requests are re-attempted.
|
|
174478
|
+
* @beta
|
|
174479
|
+
*/
|
|
174480
|
+
resetStatus() {
|
|
174481
|
+
this._blockedOrigins.clear();
|
|
174482
|
+
this.setStatus(MapLayerImageryProviderStatus.Valid);
|
|
174483
|
+
}
|
|
174169
174484
|
/** @internal */
|
|
174170
174485
|
get tileSize() { return this._usesCachedTiles ? tileImageSize : untiledImageSize; }
|
|
174171
174486
|
/** @internal */
|
|
@@ -174339,6 +174654,32 @@ class MapLayerImageryProvider {
|
|
|
174339
174654
|
(0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setBasicAuthorization)(headers, this._settings.userName, this._settings.password);
|
|
174340
174655
|
}
|
|
174341
174656
|
}
|
|
174657
|
+
/** Returns true if the given URL has the same origin as this layer's settings URL.
|
|
174658
|
+
* Used to avoid leaking credentials to third-party hosts.
|
|
174659
|
+
* @internal
|
|
174660
|
+
*/
|
|
174661
|
+
matchesSettingsUrlOrigin(url) {
|
|
174662
|
+
const origin = tryGetOrigin(url);
|
|
174663
|
+
return origin !== undefined && origin === tryGetOrigin(this._settings.url);
|
|
174664
|
+
}
|
|
174665
|
+
/** Returns true if the basic-auth credentials from the layer settings may be attached to a request to the given URL.
|
|
174666
|
+
* Always true unless [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
174667
|
+
* When enabled, the origin of this layer's settings URL is implicitly trusted (the credentials belong to that
|
|
174668
|
+
* server); other origins must be listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]].
|
|
174669
|
+
* See [[MapLayerFormatRegistry.isCredentialsSharingAllowed]].
|
|
174670
|
+
* @internal
|
|
174671
|
+
*/
|
|
174672
|
+
isCredentialsSharingAllowed(url) {
|
|
174673
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, this._settings.url);
|
|
174674
|
+
}
|
|
174675
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
174676
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
174677
|
+
* See [[MapLayerFormatRegistry.isSsoAllowed]].
|
|
174678
|
+
* @internal
|
|
174679
|
+
*/
|
|
174680
|
+
isSsoAllowed(url) {
|
|
174681
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(url);
|
|
174682
|
+
}
|
|
174342
174683
|
/** @internal */
|
|
174343
174684
|
async makeTileRequest(url, timeoutMs, authorization) {
|
|
174344
174685
|
// We want to complete the first request before letting other requests go;
|
|
@@ -174358,41 +174699,133 @@ class MapLayerImageryProvider {
|
|
|
174358
174699
|
throw new Error("fetch call failed");
|
|
174359
174700
|
return response;
|
|
174360
174701
|
}
|
|
174702
|
+
/** Records the given URL's origin and transitions the status to [[MapLayerImageryProviderStatus.UntrustedOrigin]].
|
|
174703
|
+
* Called when a request received an authentication challenge that could not be answered because the origin
|
|
174704
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
174705
|
+
* Raises [[onStatusChanged]] on the status transition, and again whenever a new origin is added.
|
|
174706
|
+
* @internal
|
|
174707
|
+
*/
|
|
174708
|
+
reportBlockedOrigin(url) {
|
|
174709
|
+
const origin = tryGetOrigin(url) ?? url;
|
|
174710
|
+
const isNewOrigin = !this._blockedOrigins.has(origin);
|
|
174711
|
+
this._blockedOrigins.add(origin);
|
|
174712
|
+
if (this._status !== MapLayerImageryProviderStatus.UntrustedOrigin)
|
|
174713
|
+
this.setStatus(MapLayerImageryProviderStatus.UntrustedOrigin);
|
|
174714
|
+
else if (isNewOrigin)
|
|
174715
|
+
this.onStatusChanged.raiseEvent(this); // status unchanged, but a new origin was blocked
|
|
174716
|
+
}
|
|
174717
|
+
/** Logs a warning (once per origin, app-wide) when credentials are sent to an origin that would be blocked
|
|
174718
|
+
* if [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] were enabled.
|
|
174719
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
174720
|
+
* See [[MapLayerFormatRegistry.logUntrustedOriginUse]].
|
|
174721
|
+
* @internal
|
|
174722
|
+
*/
|
|
174723
|
+
logUntrustedOriginUse(url) {
|
|
174724
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(url);
|
|
174725
|
+
}
|
|
174726
|
+
/** The redirect policy to apply to a request that carries browser credentials (see [[includeUserCredentials]]).
|
|
174727
|
+
*
|
|
174728
|
+
* When [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled, redirects are refused
|
|
174729
|
+
* outright (`"error"`). `fetch` cannot be asked to follow only same-origin redirects, and by the time a
|
|
174730
|
+
* followed redirect can be inspected the credentials have already been delivered to the destination — so
|
|
174731
|
+
* refusing is the only way to honour the guarantee that credentials reach none but the origins listed in
|
|
174732
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]]. Legitimate same-origin redirects fail as a result;
|
|
174733
|
+
* that is the cost of the opt-in restriction.
|
|
174734
|
+
*
|
|
174735
|
+
* When the restriction is disabled (the default), redirects are followed as before and
|
|
174736
|
+
* [[checkCredentialedRedirect]] reports the destination after the fact.
|
|
174737
|
+
* @internal
|
|
174738
|
+
*/
|
|
174739
|
+
get credentialedRedirect() {
|
|
174740
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
174741
|
+
}
|
|
174742
|
+
/** Detects that a request carrying browser credentials (see [[includeUserCredentials]]) was transparently
|
|
174743
|
+
* redirected to a different origin, and reports or logs that origin.
|
|
174744
|
+
*
|
|
174745
|
+
* This is a **best-effort, after-the-fact** signal used only while
|
|
174746
|
+
* [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is disabled, where credentialed requests
|
|
174747
|
+
* still follow redirects (see [[credentialedRedirect]]). It cannot prevent the exposure — the credentials
|
|
174748
|
+
* have already been sent — and it does not fire at all when the destination denies CORS, because `fetch`
|
|
174749
|
+
* then rejects instead of returning a `Response`. The destination origin is never latched as SSO-succeeded,
|
|
174750
|
+
* so credentials do not keep flowing to it.
|
|
174751
|
+
* @internal
|
|
174752
|
+
*/
|
|
174753
|
+
checkCredentialedRedirect(requestedUrl, response) {
|
|
174754
|
+
const finalOrigin = tryGetOrigin(response.url);
|
|
174755
|
+
if (!response.url || finalOrigin === undefined || finalOrigin === tryGetOrigin(requestedUrl))
|
|
174756
|
+
return;
|
|
174757
|
+
if (!this.isSsoAllowed(response.url))
|
|
174758
|
+
this.reportBlockedOrigin(response.url);
|
|
174759
|
+
else
|
|
174760
|
+
this.logUntrustedOriginUse(response.url); // no-op when the restriction is enabled
|
|
174761
|
+
}
|
|
174361
174762
|
/** @internal */
|
|
174362
174763
|
async makeRequest(url, timeoutMs, authorization) {
|
|
174363
174764
|
let response;
|
|
174364
174765
|
let headers;
|
|
174365
174766
|
let hasCreds = false;
|
|
174767
|
+
// Whether this request had basic-auth credentials of its own to offer. Requests carrying a caller-supplied
|
|
174768
|
+
// `authorization` are excluded: those bypass the origin policy entirely.
|
|
174769
|
+
const hasSettingsCreds = !authorization && !!this._settings.userName && !!this._settings.password;
|
|
174366
174770
|
if (authorization) {
|
|
174367
174771
|
headers = new Headers();
|
|
174368
174772
|
headers.set("Authorization", authorization);
|
|
174369
174773
|
}
|
|
174370
|
-
else if (
|
|
174371
|
-
|
|
174372
|
-
|
|
174373
|
-
|
|
174774
|
+
else if (hasSettingsCreds) {
|
|
174775
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
174776
|
+
hasCreds = true;
|
|
174777
|
+
headers = new Headers();
|
|
174778
|
+
this.setRequestAuthorization(headers);
|
|
174779
|
+
if (!this.matchesSettingsUrlOrigin(url))
|
|
174780
|
+
this.logUntrustedOriginUse(url);
|
|
174781
|
+
}
|
|
174374
174782
|
}
|
|
174783
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
174375
174784
|
const opts = {
|
|
174376
174785
|
method: "GET",
|
|
174377
174786
|
headers,
|
|
174378
|
-
credentials:
|
|
174787
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
174788
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
174379
174789
|
};
|
|
174380
174790
|
if (timeoutMs !== undefined)
|
|
174381
174791
|
(0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setRequestTimeout)(opts, timeoutMs);
|
|
174382
174792
|
response = await fetch(url, opts);
|
|
174793
|
+
if (includeCredentials)
|
|
174794
|
+
this.checkCredentialedRedirect(url, response);
|
|
174795
|
+
// fetch follows redirects transparently, so all trust decisions below target the final
|
|
174796
|
+
// (post-redirect) URL reported by the response, not the URL we asked for.
|
|
174797
|
+
const challengedUrl = response.url || url;
|
|
174383
174798
|
if (response.status === 401
|
|
174384
174799
|
&& (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])
|
|
174385
|
-
&& !
|
|
174800
|
+
&& !includeCredentials
|
|
174386
174801
|
&& !hasCreds) {
|
|
174387
|
-
|
|
174388
|
-
|
|
174389
|
-
|
|
174390
|
-
|
|
174391
|
-
|
|
174392
|
-
|
|
174393
|
-
|
|
174802
|
+
if (this.isSsoAllowed(challengedUrl)) {
|
|
174803
|
+
// Removed the previous headers and make sure "include" credentials is set
|
|
174804
|
+
opts.headers = undefined;
|
|
174805
|
+
opts.credentials = "include";
|
|
174806
|
+
// A Negotiate/NTLM handshake is normally a same-URL 401 round-trip, but in legacy mode we preserve
|
|
174807
|
+
// the previous behavior and allow the browser to follow redirects after the authenticated retry.
|
|
174808
|
+
opts.redirect = _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
174809
|
+
this.logUntrustedOriginUse(challengedUrl);
|
|
174810
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
|
|
174811
|
+
response = await fetch(challengedUrl, opts);
|
|
174812
|
+
if (response.status === 200) {
|
|
174813
|
+
this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
|
|
174814
|
+
}
|
|
174815
|
+
}
|
|
174816
|
+
else {
|
|
174817
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
174394
174818
|
}
|
|
174395
174819
|
}
|
|
174820
|
+
else if ((response.status === 401 || response.status === 403) && hasSettingsCreds && !this.isCredentialsSharingAllowed(challengedUrl)) {
|
|
174821
|
+
// Some servers answer an unauthenticated request with 403 (Forbidden) rather than a 401 challenge;
|
|
174822
|
+
// since this request could not present its credentials to the challenging origin, either status most
|
|
174823
|
+
// likely results from that. The permission is recomputed for the challenged URL rather than reusing the
|
|
174824
|
+
// decision made for the requested one: `fetch` strips the Authorization header when it follows a
|
|
174825
|
+
// cross-origin redirect, so a trusted request can still arrive unauthenticated at an untrusted origin,
|
|
174826
|
+
// and conversely a request that started out untrusted may end up at an origin that is trusted.
|
|
174827
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
174828
|
+
}
|
|
174396
174829
|
return response;
|
|
174397
174830
|
}
|
|
174398
174831
|
/** Returns a map layer tile at the specified settings. */
|
|
@@ -174423,16 +174856,28 @@ class MapLayerImageryProvider {
|
|
|
174423
174856
|
}
|
|
174424
174857
|
/** @internal */
|
|
174425
174858
|
async toolTipFromUrl(strings, url) {
|
|
174426
|
-
|
|
174427
|
-
this.
|
|
174859
|
+
let headers;
|
|
174860
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
174861
|
+
headers = new Headers();
|
|
174862
|
+
this.setRequestAuthorization(headers);
|
|
174863
|
+
}
|
|
174428
174864
|
try {
|
|
174865
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
174429
174866
|
const response = await fetch(url, {
|
|
174430
174867
|
method: "GET",
|
|
174431
174868
|
headers,
|
|
174432
|
-
credentials:
|
|
174869
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
174870
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
174433
174871
|
});
|
|
174434
|
-
|
|
174435
|
-
|
|
174872
|
+
if (includeCredentials)
|
|
174873
|
+
this.checkCredentialedRedirect(url, response);
|
|
174874
|
+
let text = await response.text();
|
|
174875
|
+
if (text) {
|
|
174876
|
+
// Tooltip content (e.g. WMS GetFeatureInfo responses) is rendered as HTML downstream and may
|
|
174877
|
+
// deliberately contain markup; text from origins not trusted for credentials is escaped.
|
|
174878
|
+
// fetch follows redirects transparently, so the text may come from a different origin than requested.
|
|
174879
|
+
if (!this.isCredentialsSharingAllowed(response.url || url))
|
|
174880
|
+
text = escapeHtml(text);
|
|
174436
174881
|
strings.push(text);
|
|
174437
174882
|
}
|
|
174438
174883
|
}
|
|
@@ -174612,6 +175057,12 @@ var MapLayerSourceStatus;
|
|
|
174612
175057
|
/** Format is not compatible with the URL provided.
|
|
174613
175058
|
*/
|
|
174614
175059
|
MapLayerSourceStatus[MapLayerSourceStatus["IncompatibleFormat"] = 7] = "IncompatibleFormat";
|
|
175060
|
+
/** Authentication could not be attempted because the source's origin is not trusted
|
|
175061
|
+
* (see [MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]($frontend)). Add the origin to
|
|
175062
|
+
* [MapLayerFormatRegistry.trustedCredentialsOrigins]($frontend) rather than prompting for credentials.
|
|
175063
|
+
* @beta
|
|
175064
|
+
*/
|
|
175065
|
+
MapLayerSourceStatus[MapLayerSourceStatus["UntrustedOrigin"] = 8] = "UntrustedOrigin";
|
|
174615
175066
|
})(MapLayerSourceStatus || (MapLayerSourceStatus = {}));
|
|
174616
175067
|
/** A source for map layers. These may be catalogued for convenient use by users or applications.
|
|
174617
175068
|
* @public
|
|
@@ -174899,10 +175350,8 @@ class MapLayerTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_3__.T
|
|
|
174899
175350
|
const tree = this.treeOwner.tileTree;
|
|
174900
175351
|
if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.sourceId)
|
|
174901
175352
|
return undefined;
|
|
174902
|
-
const strings = [];
|
|
174903
|
-
strings.push(`Map Layer: ${this._layerSettings.name}`);
|
|
174904
175353
|
const div = document.createElement("div");
|
|
174905
|
-
div.
|
|
175354
|
+
div.textContent = `Map Layer: ${this._layerSettings.name}`;
|
|
174906
175355
|
return div;
|
|
174907
175356
|
}
|
|
174908
175357
|
decorate(_context) {
|
|
@@ -176611,7 +177060,9 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
|
|
|
176611
177060
|
let carto;
|
|
176612
177061
|
const strings = [];
|
|
176613
177062
|
const getTooltipFunc = async (imageryTreeRef, quadId, cartoGraphic, imageryTree) => {
|
|
176614
|
-
|
|
177063
|
+
// innerHTML is used below because imageryLoader.getToolTip may deliberately supply markup.
|
|
177064
|
+
const layerName = (0,_internal__WEBPACK_IMPORTED_MODULE_7__.escapeHtml)(imageryTreeRef.layerSettings.name);
|
|
177065
|
+
strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${layerName}`);
|
|
176615
177066
|
carto = cartoGraphic;
|
|
176616
177067
|
await imageryTree.imageryLoader.getToolTip(strings, quadId, cartoGraphic, imageryTree);
|
|
176617
177068
|
};
|
|
@@ -334493,7 +334944,7 @@ var loadLanguages = instance.loadLanguages;
|
|
|
334493
334944
|
(module) {
|
|
334494
334945
|
|
|
334495
334946
|
"use strict";
|
|
334496
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.
|
|
334947
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.17","description":"iTwin.js frontend components","main":"lib/cjs/core-frontend.js","module":"lib/esm/core-frontend.js","typings":"lib/cjs/core-frontend","license":"MIT","scripts":{"build":"npm run -s copy:public && npm run -s build:cjs && npm run -s build:esm && npm run -s build:workers && npm run -s copy:draco","build:cjs":"npm run -s copy:js:cjs && tsc 1>&2 --outDir lib/cjs","build:esm":"npm run -s copy:js:esm && tsc 1>&2 --module ES2022 --outDir lib/esm","clean":"rimraf -g lib .rush/temp/package-deps*.json","copy:public":"cpx \\"./src/public/**/*\\" ./lib/public","copy:js:cjs":"cpx \\"./src/**/*.js\\" ./lib/cjs","copy:js:esm":"cpx \\"./src/**/*.js\\" ./lib/esm","copy:draco":"cpx \\"./node_modules/@loaders.gl/draco/dist/libs/*\\" ./lib/public/scripts","docs":"betools docs --json=../../generated-docs/core/core-frontend/file.json --tsIndexFile=./core-frontend.ts --onlyJson --excludes=webgl/**/*,**/map/*.d.ts,**/tile/*.d.ts,**/*-css.ts && npm run -s extract","extract":"betools extract --fileExt=ts --extractFrom=./src/test/example-code --recursive --out=../../generated-docs/extract","extract-api":"betools extract-api --entry=core-frontend && npm run extract-extension-api","extract-extension-api":"eslint --no-inline-config -c extraction.eslint.config.js \\"./src/**/*.ts\\" 1>&2","lint":"eslint \\"./src/**/*.ts\\" 1>&2","lint-fix":"eslint --fix -f visualstudio \\"./src/**/*.ts\\" 1>&2","lint-deprecation":"eslint --fix -f visualstudio --no-inline-config -c ../../common/config/eslint/eslint.config.deprecation-policy.js \\"./src/**/*.ts\\"","pseudolocalize":"betools pseudolocalize --englishDir ./src/public/locales/en --out ./public/locales/en-PSEUDO","test":"npm run build:test-worker && vitest --run","cover":"npm run build:test-worker && vitest --run","build:test-worker":"vite build --config ./src/test/worker/vite.config.mts 1>&2","build:workers":"rimraf lib/workers/webpack && vite build --config ./src/workers/ImdlParser/vite.config.mts 1>&2"},"repository":{"type":"git","url":"https://github.com/iTwin/itwinjs-core.git","directory":"core/frontend"},"keywords":["Bentley","BIM","iModel","digital-twin","iTwin"],"author":{"name":"Bentley Systems, Inc.","url":"http://www.bentley.com"},"peerDependencies":{"@itwin/appui-abstract":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*"},"//devDependencies":["NOTE: All peerDependencies should also be listed as devDependencies since peerDependencies are not considered by npm install","NOTE: All tools used by scripts in this package must be listed as devDependencies"],"devDependencies":{"@bentley/aec-units-schema":"^1.0.3","@bentley/formats-schema":"^1.0.0","@bentley/units-schema":"^1.0.11","@itwin/appui-abstract":"workspace:*","@itwin/build-tools":"workspace:*","@itwin/core-bentley":"workspace:*","@itwin/core-common":"workspace:*","@itwin/core-geometry":"workspace:*","@itwin/core-orbitgt":"workspace:*","@itwin/core-quantity":"workspace:*","@itwin/ecschema-metadata":"workspace:*","@itwin/ecschema-rpcinterface-common":"workspace:*","@itwin/object-storage-core":"^3.0.4","@itwin/eslint-plugin":"^6.0.0","@types/node":"~20.17.0","@types/sinon":"^17.0.2","@vitest/browser-playwright":"^4.1.10","@vitest/coverage-v8":"^4.1.10","cpx2":"^8.0.0","eslint":"^9.31.0","playwright":"~1.56.1","rimraf":"^6.0.1","sinon":"^17.0.2","typescript":"~5.6.2","vite":"^6.4.3","vitest":"^4.1.10","vite-plugin-static-copy":"2.2.0"},"//dependencies":["NOTE: these dependencies should be only for things that DO NOT APPEAR IN THE API","NOTE: core-frontend should remain UI technology agnostic, so no react/angular dependencies are allowed"],"dependencies":{"@itwin/core-i18n":"workspace:*","@itwin/webgl-compatibility":"workspace:*","@loaders.gl/core":"~4.3.4","@loaders.gl/draco":"~4.3.4","fuse.js":"^3.3.0","wms-capabilities":"0.4.0"}}');
|
|
334497
334948
|
|
|
334498
334949
|
/***/ }
|
|
334499
334950
|
|