@itwin/rpcinterface-full-stack-tests 5.13.0-dev.16 → 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 +522 -71
- package/lib/dist/bundled-tests.js.map +1 -1
- package/package.json +14 -14
|
@@ -111451,6 +111451,8 @@ const COPYRIGHT_NOTICE = `Copyright © 2017-${new Date().getFullYear()} <a href=
|
|
|
111451
111451
|
|
|
111452
111452
|
|
|
111453
111453
|
|
|
111454
|
+
/** CSS class name applied to the notice element of a logo card created by [[IModelApp.makeLogoCard]]. */
|
|
111455
|
+
const logoCardNoticeClassName = "logo-cards";
|
|
111454
111456
|
/**
|
|
111455
111457
|
* Global singleton that connects the user interface with the iTwin.js services. There can be only one IModelApp active in a session. All
|
|
111456
111458
|
* members of IModelApp are static, and it serves as a singleton object for gaining access to session information.
|
|
@@ -111963,10 +111965,21 @@ class IModelApp {
|
|
|
111963
111965
|
}
|
|
111964
111966
|
if (undefined !== opts.notice) {
|
|
111965
111967
|
if (typeof opts.notice === "string")
|
|
111966
|
-
IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className:
|
|
111968
|
+
IModelApp.makeHTMLElement("p", { parent: noticeCell, innerHTML: opts.notice, className: logoCardNoticeClassName });
|
|
111967
111969
|
else
|
|
111968
111970
|
noticeCell.appendChild(opts.notice);
|
|
111969
111971
|
}
|
|
111972
|
+
else if (undefined !== opts.noticeLines) {
|
|
111973
|
+
// A <p> cannot legally contain flow content, so use a <div> when a line is an element.
|
|
111974
|
+
const containerTag = opts.noticeLines.some((line) => typeof line !== "string") ? "div" : "p";
|
|
111975
|
+
const notice = IModelApp.makeHTMLElement(containerTag, { parent: noticeCell, className: logoCardNoticeClassName });
|
|
111976
|
+
opts.noticeLines.forEach((line, index) => {
|
|
111977
|
+
if (index > 0)
|
|
111978
|
+
notice.appendChild(IModelApp.makeHTMLElement("br"));
|
|
111979
|
+
// Strings are appended as text nodes so they are never parsed as HTML.
|
|
111980
|
+
notice.append(line);
|
|
111981
|
+
});
|
|
111982
|
+
}
|
|
111970
111983
|
return card;
|
|
111971
111984
|
}
|
|
111972
111985
|
/** Make the logo card for the library itself. This card gets placed at the top of the stack.
|
|
@@ -113533,7 +113546,9 @@ let iModelJsCss = `
|
|
|
113533
113546
|
|
|
113534
113547
|
.logo-cards {
|
|
113535
113548
|
position:relative;
|
|
113536
|
-
width:100
|
|
113549
|
+
width:100%;
|
|
113550
|
+
margin-block-start:1em;
|
|
113551
|
+
margin-block-end:1em
|
|
113537
113552
|
}
|
|
113538
113553
|
|
|
113539
113554
|
.imodeljs-modal-overlay {
|
|
@@ -113577,7 +113592,7 @@ let iModelJsCss = `
|
|
|
113577
113592
|
max-width: calc(100% - (2 * var(--width-border))) !important;
|
|
113578
113593
|
width: unset !important;
|
|
113579
113594
|
}
|
|
113580
|
-
.imodeljs-about .logo-card-message p {
|
|
113595
|
+
.imodeljs-about .logo-card-message p, .imodeljs-about .logo-card-message .logo-cards {
|
|
113581
113596
|
margin-block-end: 1em;
|
|
113582
113597
|
}
|
|
113583
113598
|
.imodeljs-about .logo-cards {
|
|
@@ -116223,9 +116238,12 @@ class Google3dTilesProvider {
|
|
|
116223
116238
|
// Order by most occurances to least
|
|
116224
116239
|
// See https://developers.google.com/maps/documentation/tile/create-renderer#display-attributions
|
|
116225
116240
|
const sortedCopyrights = [...copyrightMap.entries()].sort((a, b) => b[1] - a[1]);
|
|
116226
|
-
|
|
116227
|
-
|
|
116228
|
-
|
|
116241
|
+
const list = document.createElement("ul");
|
|
116242
|
+
for (const [key] of sortedCopyrights) {
|
|
116243
|
+
const item = document.createElement("li");
|
|
116244
|
+
item.textContent = key;
|
|
116245
|
+
list.appendChild(item);
|
|
116246
|
+
}
|
|
116229
116247
|
const iconSrc = document.createElement("img");
|
|
116230
116248
|
iconSrc.src = `${_IModelApp__WEBPACK_IMPORTED_MODULE_8__.IModelApp.publicPath}images/GoogleMaps_Logo_Gray.svg`;
|
|
116231
116249
|
iconSrc.style.padding = "10px 10px 5px 10px";
|
|
@@ -116233,7 +116251,7 @@ class Google3dTilesProvider {
|
|
|
116233
116251
|
iconSrc,
|
|
116234
116252
|
iconWidth: 98,
|
|
116235
116253
|
heading: "Google Photorealistic 3D Tiles",
|
|
116236
|
-
|
|
116254
|
+
noticeLines: ["Data provided by:", list],
|
|
116237
116255
|
}));
|
|
116238
116256
|
}
|
|
116239
116257
|
}
|
|
@@ -136623,7 +136641,7 @@ class GoogleMapsDecorator {
|
|
|
136623
136641
|
const copyrightText = sortedCopyrights.map(([key]) => ` • ${key}`).join("");
|
|
136624
136642
|
// Create and add element, offset to leave space for i.js and Google logos
|
|
136625
136643
|
const elem = document.createElement("div");
|
|
136626
|
-
elem.
|
|
136644
|
+
elem.textContent = copyrightText;
|
|
136627
136645
|
elem.style.color = "white";
|
|
136628
136646
|
elem.style.fontSize = "11px";
|
|
136629
136647
|
elem.style.textWrap = "wrap";
|
|
@@ -173930,7 +173948,11 @@ class OrbitGtTreeReference extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.R
|
|
|
173930
173948
|
if (this._name)
|
|
173931
173949
|
strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_6__.IModelApp.localization.getLocalizedString("iModelJs:TooltipInfo.Name")} ${this._name}`);
|
|
173932
173950
|
const div = document.createElement("div");
|
|
173933
|
-
|
|
173951
|
+
strings.forEach((str, index) => {
|
|
173952
|
+
if (index > 0)
|
|
173953
|
+
div.appendChild(document.createElement("br"));
|
|
173954
|
+
div.appendChild(document.createTextNode(str));
|
|
173955
|
+
});
|
|
173934
173956
|
return div;
|
|
173935
173957
|
}
|
|
173936
173958
|
}
|
|
@@ -175694,7 +175716,11 @@ class RealityTreeReference extends RealityModelTileTree.Reference {
|
|
|
175694
175716
|
if (-1 === key.indexOf("#")) // Avoid internal cesium
|
|
175695
175717
|
strings.push(`${key}: ${JSON.stringify(batch[key])}`);
|
|
175696
175718
|
const div = document.createElement("div");
|
|
175697
|
-
|
|
175719
|
+
strings.forEach((str, index) => {
|
|
175720
|
+
if (index > 0)
|
|
175721
|
+
div.appendChild(document.createElement("br"));
|
|
175722
|
+
div.appendChild(document.createTextNode(str));
|
|
175723
|
+
});
|
|
175698
175724
|
return div;
|
|
175699
175725
|
}
|
|
175700
175726
|
/** @deprecated in 5.0 - might be removed in next major version. Use [addAttributions] instead. */
|
|
@@ -176882,7 +176908,21 @@ class ArcGisUtilities {
|
|
|
176882
176908
|
*/
|
|
176883
176909
|
static async validateSource(args) {
|
|
176884
176910
|
const { source, ignoreCache, capabilitiesFilter } = args;
|
|
176885
|
-
|
|
176911
|
+
let metadata;
|
|
176912
|
+
try {
|
|
176913
|
+
metadata = await this.getServiceJson({ url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache });
|
|
176914
|
+
}
|
|
176915
|
+
catch (err) {
|
|
176916
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError) {
|
|
176917
|
+
let blockedOrigin;
|
|
176918
|
+
try {
|
|
176919
|
+
blockedOrigin = new URL(err.url).origin;
|
|
176920
|
+
}
|
|
176921
|
+
catch { /* non-hierarchical URL */ }
|
|
176922
|
+
return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
176923
|
+
}
|
|
176924
|
+
throw err;
|
|
176925
|
+
}
|
|
176886
176926
|
const json = metadata?.content;
|
|
176887
176927
|
if (json === undefined) {
|
|
176888
176928
|
return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.InvalidUrl };
|
|
@@ -176945,6 +176985,9 @@ class ArcGisUtilities {
|
|
|
176945
176985
|
* @param password Password to use for legacy token based security
|
|
176946
176986
|
* @param ignoreCache Flag to skip cache lookup (i.e. force a new server request)
|
|
176947
176987
|
* @param requireToken Flag to indicate if a token is required
|
|
176988
|
+
* @throws [[MapLayerUntrustedOriginError]] if an NTLM/Negotiate challenge could not be answered because
|
|
176989
|
+
* the URL's origin is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]);
|
|
176990
|
+
* all other errors are caught and reported by returning `undefined`.
|
|
176948
176991
|
*/
|
|
176949
176992
|
static async getServiceJson(args) {
|
|
176950
176993
|
const { url, formatId, userName, password, queryParams, ignoreCache, requireToken } = args;
|
|
@@ -176980,8 +177023,17 @@ class ArcGisUtilities {
|
|
|
176980
177023
|
}
|
|
176981
177024
|
let response = await fetch(tmpUrl, { method: "GET" });
|
|
176982
177025
|
if (response.status === 401 && !requireToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
176983
|
-
//
|
|
176984
|
-
|
|
177026
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
177027
|
+
const challengedUrl = response.url || tmpUrl.toString();
|
|
177028
|
+
if (!_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
|
|
177029
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError(challengedUrl);
|
|
177030
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
|
|
177031
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
|
|
177032
|
+
response = await fetch(challengedUrl, {
|
|
177033
|
+
method: "GET",
|
|
177034
|
+
credentials: "include",
|
|
177035
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
177036
|
+
});
|
|
176985
177037
|
}
|
|
176986
177038
|
// Append security token when corresponding error code is returned by ArcGIS service
|
|
176987
177039
|
let errorCode = await ArcGisUtilities.checkForResponseErrorCode(response);
|
|
@@ -177003,8 +177055,10 @@ class ArcGisUtilities {
|
|
|
177003
177055
|
ArcGisUtilities._serviceCache.set(url, (errorCode === undefined ? info : undefined));
|
|
177004
177056
|
return info; // Always return json, even though it contains an error code.
|
|
177005
177057
|
}
|
|
177006
|
-
catch {
|
|
177058
|
+
catch (err) {
|
|
177007
177059
|
ArcGisUtilities._serviceCache.set(url, undefined);
|
|
177060
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError)
|
|
177061
|
+
throw err; // propagate so callers can report the blocked origin
|
|
177008
177062
|
return undefined;
|
|
177009
177063
|
}
|
|
177010
177064
|
}
|
|
@@ -177166,7 +177220,9 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
|
|
|
177166
177220
|
try {
|
|
177167
177221
|
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() });
|
|
177168
177222
|
}
|
|
177169
|
-
catch {
|
|
177223
|
+
catch (err) {
|
|
177224
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError)
|
|
177225
|
+
this.reportBlockedOrigin(err.url);
|
|
177170
177226
|
}
|
|
177171
177227
|
if (metadata && metadata.accessTokenRequired) {
|
|
177172
177228
|
const accessClient = _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.getAccessClient(this._settings.formatId);
|
|
@@ -177214,12 +177270,32 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
|
|
|
177214
177270
|
await this._firstRequestPromise;
|
|
177215
177271
|
let response;
|
|
177216
177272
|
try {
|
|
177217
|
-
|
|
177273
|
+
const requestUrl = urlObj.toString();
|
|
177274
|
+
const includeCredentials = this.includeUserCredentials(requestUrl);
|
|
177275
|
+
response = await fetch(urlObj, {
|
|
177276
|
+
...options,
|
|
177277
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
177278
|
+
redirect: includeCredentials ? this.credentialedRedirect : options?.redirect,
|
|
177279
|
+
});
|
|
177280
|
+
if (includeCredentials)
|
|
177281
|
+
this.checkCredentialedRedirect(requestUrl, response);
|
|
177218
177282
|
if (response.status === 401 && !this._lastAccessToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
177219
|
-
//
|
|
177220
|
-
|
|
177221
|
-
if (
|
|
177222
|
-
|
|
177283
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
177284
|
+
const challengedUrl = response.url || requestUrl;
|
|
177285
|
+
if (this.isSsoAllowed(challengedUrl)) {
|
|
177286
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
|
|
177287
|
+
this.logUntrustedOriginUse(challengedUrl);
|
|
177288
|
+
response = await fetch(challengedUrl, {
|
|
177289
|
+
...options,
|
|
177290
|
+
credentials: "include",
|
|
177291
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
177292
|
+
});
|
|
177293
|
+
if (response.status === 200) {
|
|
177294
|
+
this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
|
|
177295
|
+
}
|
|
177296
|
+
}
|
|
177297
|
+
else {
|
|
177298
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
177223
177299
|
}
|
|
177224
177300
|
}
|
|
177225
177301
|
if ((this._lastAccessToken && response.status === 400)
|
|
@@ -177432,8 +177508,12 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
177432
177508
|
}
|
|
177433
177509
|
async initialize() {
|
|
177434
177510
|
const metadata = await this.getServiceJson();
|
|
177435
|
-
if (metadata?.content === undefined)
|
|
177511
|
+
if (metadata?.content === undefined) {
|
|
177512
|
+
// By returning (i.e., not throwing), we ensure the tile tree gets created and the current provider is preserved to report status.
|
|
177513
|
+
if (this.status === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.UntrustedOrigin)
|
|
177514
|
+
return;
|
|
177436
177515
|
throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_0__.ServerError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_5__.IModelStatus.ValidationFailed, "");
|
|
177516
|
+
}
|
|
177437
177517
|
const json = metadata.content;
|
|
177438
177518
|
if (json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.TokenRequired
|
|
177439
177519
|
|| json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.InvalidToken
|
|
@@ -177518,7 +177598,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
177518
177598
|
addLogoCards(cards) {
|
|
177519
177599
|
if (!cards.dataset.arcGisLogoCard) {
|
|
177520
177600
|
cards.dataset.arcGisLogoCard = "true";
|
|
177521
|
-
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS",
|
|
177601
|
+
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS", noticeLines: [this._copyrightText] }));
|
|
177522
177602
|
}
|
|
177523
177603
|
}
|
|
177524
177604
|
async addAttributions(cards, _vp) {
|
|
@@ -177559,7 +177639,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
177559
177639
|
if (json && Array.isArray(json.results)) {
|
|
177560
177640
|
for (const result of json.results) {
|
|
177561
177641
|
if (result.attributes !== undefined && result.attributes[result.displayFieldName] !== undefined) {
|
|
177562
|
-
const thisString = `${result.displayFieldName}: ${result.attributes[result.displayFieldName]}`;
|
|
177642
|
+
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]))}`;
|
|
177563
177643
|
if (!stringSet.has(thisString)) {
|
|
177564
177644
|
strings.push(thisString);
|
|
177565
177645
|
stringSet.add(thisString);
|
|
@@ -177875,13 +177955,7 @@ class BingMapsImageryLayerProvider extends _tile_internal__WEBPACK_IMPORTED_MODU
|
|
|
177875
177955
|
const copyrights = [];
|
|
177876
177956
|
for (const match of matchingAttributions)
|
|
177877
177957
|
copyrights.push(match.copyrightMessage);
|
|
177878
|
-
|
|
177879
|
-
for (let i = 0; i < copyrights.length; ++i) {
|
|
177880
|
-
if (i > 0)
|
|
177881
|
-
copyrightMsg += "<br>";
|
|
177882
|
-
copyrightMsg += copyrights[i];
|
|
177883
|
-
}
|
|
177884
|
-
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 }));
|
|
177958
|
+
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 }));
|
|
177885
177959
|
}
|
|
177886
177960
|
async addAttributions(cards, vp) {
|
|
177887
177961
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -178490,7 +178564,10 @@ class WmsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE
|
|
|
178490
178564
|
// Don't throw error if unauthorized status:
|
|
178491
178565
|
// We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
|
|
178492
178566
|
// When credentials will be provided, a new provider will be created, and initialization should be fine.
|
|
178493
|
-
if (error
|
|
178567
|
+
if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError) {
|
|
178568
|
+
this.reportBlockedOrigin(error.url);
|
|
178569
|
+
}
|
|
178570
|
+
else if (error?.status === 401) {
|
|
178494
178571
|
this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerImageryProviderStatus.RequireAuth);
|
|
178495
178572
|
}
|
|
178496
178573
|
else {
|
|
@@ -178652,7 +178729,8 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
|
|
|
178652
178729
|
}
|
|
178653
178730
|
async initialize() {
|
|
178654
178731
|
try {
|
|
178655
|
-
this.
|
|
178732
|
+
const credentials = (this._settings.userName && this._settings.password ? { user: this._settings.userName, password: this._settings.password } : undefined);
|
|
178733
|
+
this._capabilities = await _tile_internal__WEBPACK_IMPORTED_MODULE_2__.WmtsCapabilities.create(this._baseUrl, credentials);
|
|
178656
178734
|
this.initPreferredTileMatrixSet();
|
|
178657
178735
|
this.initPreferredStyle();
|
|
178658
178736
|
this.initDisplayedLayer();
|
|
@@ -178665,7 +178743,10 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
|
|
|
178665
178743
|
// Don't throw error if unauthorized status:
|
|
178666
178744
|
// We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
|
|
178667
178745
|
// When credentials will be provided, a new provider will be created, and initialization should be fine.
|
|
178668
|
-
if (error
|
|
178746
|
+
if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerUntrustedOriginError) {
|
|
178747
|
+
this.reportBlockedOrigin(error.url);
|
|
178748
|
+
}
|
|
178749
|
+
else if (error?.status === 401) {
|
|
178669
178750
|
this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.RequireAuth);
|
|
178670
178751
|
}
|
|
178671
178752
|
else {
|
|
@@ -179476,14 +179557,18 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
179476
179557
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
179477
179558
|
/* harmony export */ WmsUtilities: () => (/* binding */ WmsUtilities)
|
|
179478
179559
|
/* harmony export */ });
|
|
179479
|
-
/* harmony import */ var
|
|
179480
|
-
/* harmony import */ var
|
|
179560
|
+
/* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
|
|
179561
|
+
/* harmony import */ var _request_Request__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../request/Request */ "../../core/frontend/lib/esm/request/Request.js");
|
|
179562
|
+
/* harmony import */ var _request_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../request/utils */ "../../core/frontend/lib/esm/request/utils.js");
|
|
179563
|
+
/* harmony import */ var _tile_internal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../tile/internal */ "../../core/frontend/lib/esm/tile/internal.js");
|
|
179481
179564
|
/*---------------------------------------------------------------------------------------------
|
|
179482
179565
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
179483
179566
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
179484
179567
|
*--------------------------------------------------------------------------------------------*/
|
|
179485
179568
|
|
|
179486
179569
|
|
|
179570
|
+
|
|
179571
|
+
|
|
179487
179572
|
/** @packageDocumentation
|
|
179488
179573
|
* @module Tiles
|
|
179489
179574
|
*/
|
|
@@ -179500,16 +179585,35 @@ class WmsUtilities {
|
|
|
179500
179585
|
static async fetchXml(url, credentials) {
|
|
179501
179586
|
let headers;
|
|
179502
179587
|
if (credentials && credentials.user && credentials.password) {
|
|
179503
|
-
|
|
179504
|
-
|
|
179588
|
+
// Basic credentials are considered settings-derived credentials for this source. When the registry is
|
|
179589
|
+
// enforcing trusted origins, the source URL itself is the only implicitly trusted origin for basic auth;
|
|
179590
|
+
// opaque/custom-protocol URLs have no network origin and must therefore be treated as untrusted.
|
|
179591
|
+
const allowBasicAuth = !_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins
|
|
179592
|
+
|| _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, url);
|
|
179593
|
+
if (allowBasicAuth) {
|
|
179594
|
+
headers = new Headers();
|
|
179595
|
+
(0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.setBasicAuthorization)(headers, credentials);
|
|
179596
|
+
}
|
|
179505
179597
|
}
|
|
179506
179598
|
let response = await fetch(url, { method: "GET", headers });
|
|
179507
|
-
if (!credentials && response.status === 401
|
|
179508
|
-
|
|
179509
|
-
|
|
179599
|
+
if (!headers && credentials && credentials.user && credentials.password && (response.status === 401 || response.status === 403)) {
|
|
179600
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(url);
|
|
179601
|
+
}
|
|
179602
|
+
if (!credentials && response.status === 401 && (0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
179603
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
179604
|
+
const challengedUrl = response.url || url;
|
|
179605
|
+
if (!_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
|
|
179606
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(challengedUrl);
|
|
179607
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
|
|
179608
|
+
// We got a http 401 challenge, lets try SSO (i.e. Windows Authentication).
|
|
179609
|
+
response = await fetch(challengedUrl, {
|
|
179610
|
+
method: "GET",
|
|
179611
|
+
credentials: "include",
|
|
179612
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
179613
|
+
});
|
|
179510
179614
|
}
|
|
179511
179615
|
if (response.status !== 200)
|
|
179512
|
-
throw new
|
|
179616
|
+
throw new _request_Request__WEBPACK_IMPORTED_MODULE_1__.HttpResponseError(response.status, await response.text());
|
|
179513
179617
|
return response.text();
|
|
179514
179618
|
}
|
|
179515
179619
|
}
|
|
@@ -191923,6 +192027,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
191923
192027
|
/* harmony export */ MapLayerSourceStatus: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSourceStatus),
|
|
191924
192028
|
/* harmony export */ MapLayerSources: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSources),
|
|
191925
192029
|
/* harmony export */ MapLayerTileTreeReference: () => (/* reexport safe */ _map_MapLayerTileTreeReference__WEBPACK_IMPORTED_MODULE_64__.MapLayerTileTreeReference),
|
|
192030
|
+
/* harmony export */ MapLayerUntrustedOriginError: () => (/* reexport safe */ _map_MapLayerFormatRegistry__WEBPACK_IMPORTED_MODULE_42__.MapLayerUntrustedOriginError),
|
|
191926
192031
|
/* harmony export */ MapTile: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTile),
|
|
191927
192032
|
/* harmony export */ MapTileLoader: () => (/* reexport safe */ _internal_tile_map_MapTileLoader__WEBPACK_IMPORTED_MODULE_72__.MapTileLoader),
|
|
191928
192033
|
/* harmony export */ MapTileProjection: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTileProjection),
|
|
@@ -192018,6 +192123,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
192018
192123
|
/* harmony export */ decodeMeshoptBuffer: () => (/* reexport safe */ _internal_tile_MeshoptCompression__WEBPACK_IMPORTED_MODULE_93__.decodeMeshoptBuffer),
|
|
192019
192124
|
/* harmony export */ deflateCoordinates: () => (/* reexport safe */ _internal_tile_map_ImageryProviders_CoordinatesUtils__WEBPACK_IMPORTED_MODULE_47__.deflateCoordinates),
|
|
192020
192125
|
/* harmony export */ disposeTileTreesForGeometricModels: () => (/* reexport safe */ _internal_tile_PrimaryTileTree__WEBPACK_IMPORTED_MODULE_82__.disposeTileTreesForGeometricModels),
|
|
192126
|
+
/* harmony export */ escapeHtml: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.escapeHtml),
|
|
192021
192127
|
/* harmony export */ getCesiumAccessClient: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessClient),
|
|
192022
192128
|
/* harmony export */ getCesiumAccessTokenAndEndpointUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessTokenAndEndpointUrl),
|
|
192023
192129
|
/* harmony export */ getCesiumAssetUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAssetUrl),
|
|
@@ -192037,7 +192143,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
192037
192143
|
/* harmony export */ readImdlContent: () => (/* reexport safe */ _ImdlReader__WEBPACK_IMPORTED_MODULE_35__.readImdlContent),
|
|
192038
192144
|
/* harmony export */ readPntsColors: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPntsColors),
|
|
192039
192145
|
/* harmony export */ readPointCloudTileContent: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPointCloudTileContent),
|
|
192040
|
-
/* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic)
|
|
192146
|
+
/* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic),
|
|
192147
|
+
/* harmony export */ tryGetOrigin: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.tryGetOrigin)
|
|
192041
192148
|
/* harmony export */ });
|
|
192042
192149
|
/* harmony import */ var _internal_tile_ViewFlagOverrides__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../internal/tile/ViewFlagOverrides */ "../../core/frontend/lib/esm/internal/tile/ViewFlagOverrides.js");
|
|
192043
192150
|
/* harmony import */ var _map_MapCartoRectangle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map/MapCartoRectangle */ "../../core/frontend/lib/esm/tile/map/MapCartoRectangle.js");
|
|
@@ -193736,7 +193843,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
193736
193843
|
__webpack_require__.r(__webpack_exports__);
|
|
193737
193844
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
193738
193845
|
/* harmony export */ MapLayerFormat: () => (/* binding */ MapLayerFormat),
|
|
193739
|
-
/* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry)
|
|
193846
|
+
/* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry),
|
|
193847
|
+
/* harmony export */ MapLayerUntrustedOriginError: () => (/* binding */ MapLayerUntrustedOriginError)
|
|
193740
193848
|
/* harmony export */ });
|
|
193741
193849
|
/* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
|
|
193742
193850
|
/* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
|
|
@@ -193751,7 +193859,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
193751
193859
|
|
|
193752
193860
|
|
|
193753
193861
|
|
|
193754
|
-
const loggerCategory = "
|
|
193862
|
+
const loggerCategory = "MapLayerFormatRegistry";
|
|
193755
193863
|
/**
|
|
193756
193864
|
* Class representing a map-layer format.
|
|
193757
193865
|
* Each format has it's unique 'formatId' string, used to uniquely identify a format in the [[MapLayerFormatRegistry]].
|
|
@@ -193800,16 +193908,127 @@ class MapLayerFormat {
|
|
|
193800
193908
|
return undefined;
|
|
193801
193909
|
}
|
|
193802
193910
|
}
|
|
193911
|
+
/** Error thrown when an NTLM or Negotiate http 401 challenge could not be answered because the request
|
|
193912
|
+
* URL's origin is not listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]]
|
|
193913
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
193914
|
+
* Thrown by the static map-layer utilities (e.g. capabilities / service-metadata fetches) that have no
|
|
193915
|
+
* provider instance on which to report the blocked origin; callers convert it to
|
|
193916
|
+
* [[MapLayerImageryProviderStatus.UntrustedOrigin]] (provider initialization) or
|
|
193917
|
+
* [[MapLayerSourceStatus.UntrustedOrigin]] (source validation).
|
|
193918
|
+
* @internal
|
|
193919
|
+
*/
|
|
193920
|
+
class MapLayerUntrustedOriginError extends Error {
|
|
193921
|
+
/** The URL of the request whose authentication challenge was left unanswered. */
|
|
193922
|
+
url;
|
|
193923
|
+
constructor(url) {
|
|
193924
|
+
super(`Authentication blocked: origin of '${url}' is not listed in MapLayerFormatRegistry.trustedCredentialsOrigins`);
|
|
193925
|
+
this.url = url;
|
|
193926
|
+
}
|
|
193927
|
+
}
|
|
193803
193928
|
/**
|
|
193804
193929
|
* A registry of MapLayerFormats identified by their unique format IDs. The registry can be accessed via [[IModelApp.mapLayerFormatRegistry]].
|
|
193805
193930
|
* @public
|
|
193806
193931
|
*/
|
|
193807
193932
|
class MapLayerFormatRegistry {
|
|
193808
193933
|
_configOptions;
|
|
193934
|
+
_trustedCredentialsOrigins = [];
|
|
193935
|
+
/** Opt-in enforcement of origin restrictions on map-layer credentials.
|
|
193936
|
+
* When enabled, map layer providers:
|
|
193937
|
+
* - attach the basic-auth credentials stored in the layer settings only to requests targeting the origin
|
|
193938
|
+
* of the layer's settings URL or an origin listed in [[trustedCredentialsOrigins]];
|
|
193939
|
+
* - retry a request with browser credentials included (i.e. SSO / Windows Authentication) after an NTLM
|
|
193940
|
+
* or Negotiate http 401 challenge only for origins explicitly listed in [[trustedCredentialsOrigins]]
|
|
193941
|
+
* (the settings-URL origin is NOT implicitly trusted for SSO, since map-layer URLs may originate from
|
|
193942
|
+
* untrusted user input while SSO shares the user's ambient identity).
|
|
193943
|
+
* Default is false, preserving the legacy behavior of sending credentials to any request URL.
|
|
193944
|
+
* @beta
|
|
193945
|
+
*/
|
|
193946
|
+
restrictCredentialsToTrustedOrigins = false;
|
|
193809
193947
|
constructor(opts) {
|
|
193810
193948
|
this._configOptions = opts ?? {};
|
|
193811
193949
|
_internal__WEBPACK_IMPORTED_MODULE_2__.internalMapLayerImageryFormats.forEach((format) => this.register(format));
|
|
193812
193950
|
}
|
|
193951
|
+
/** Origins (e.g. "https://tiles.example.com") to which map layer providers may send credentials —
|
|
193952
|
+
* both the basic-auth credentials stored in the layer settings and browser credentials for
|
|
193953
|
+
* SSO (i.e. Windows Authentication) retries after an NTLM or Negotiate http 401 challenge.
|
|
193954
|
+
* Only enforced when [[restrictCredentialsToTrustedOrigins]] is enabled.
|
|
193955
|
+
* For basic-auth, the origin of each map layer's settings URL is always implicitly trusted; for SSO,
|
|
193956
|
+
* origins must be explicitly listed here.
|
|
193957
|
+
* Entries are normalized to their origin (scheme + host + port); only `http:` and `https:` URLs are accepted,
|
|
193958
|
+
* and any other entry is ignored and logged. Opaque schemes such as `file:`, `data:`, `about:` and custom
|
|
193959
|
+
* Electron protocols are rejected because they all share the same serialized origin, so trusting one would
|
|
193960
|
+
* trust every other.
|
|
193961
|
+
* @beta
|
|
193962
|
+
*/
|
|
193963
|
+
get trustedCredentialsOrigins() {
|
|
193964
|
+
return this._trustedCredentialsOrigins;
|
|
193965
|
+
}
|
|
193966
|
+
set trustedCredentialsOrigins(origins) {
|
|
193967
|
+
const normalized = [];
|
|
193968
|
+
for (const entry of origins) {
|
|
193969
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(entry);
|
|
193970
|
+
if (origin !== undefined)
|
|
193971
|
+
normalized.push(origin);
|
|
193972
|
+
else
|
|
193973
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `trustedCredentialsOrigins: ignoring '${entry}'; entries must be http or https URLs.`);
|
|
193974
|
+
}
|
|
193975
|
+
this._trustedCredentialsOrigins = normalized;
|
|
193976
|
+
}
|
|
193977
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
193978
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
193979
|
+
* Always true unless [[restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
193980
|
+
* When enabled, the URL's origin must be explicitly listed in [[trustedCredentialsOrigins]];
|
|
193981
|
+
* unlike basic-auth, the settings-URL origin is NOT implicitly trusted because SSO shares the user's
|
|
193982
|
+
* ambient identity, and map-layer URLs may originate from untrusted user input.
|
|
193983
|
+
* @internal
|
|
193984
|
+
*/
|
|
193985
|
+
isSsoAllowed(url) {
|
|
193986
|
+
if (!this.restrictCredentialsToTrustedOrigins)
|
|
193987
|
+
return true;
|
|
193988
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
|
|
193989
|
+
// Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
|
|
193990
|
+
return origin !== undefined && this._trustedCredentialsOrigins.includes(origin);
|
|
193991
|
+
}
|
|
193992
|
+
/** Returns true if the basic-auth credentials belonging to a map-layer source or settings URL may be
|
|
193993
|
+
* attached to a request to the given URL. Always true unless [[restrictCredentialsToTrustedOrigins]]
|
|
193994
|
+
* is enabled (opt-in). When enabled, the origin of `settingsUrl` is implicitly trusted (the credentials
|
|
193995
|
+
* belong to that server); any other origin must be listed in [[trustedCredentialsOrigins]].
|
|
193996
|
+
* @internal
|
|
193997
|
+
*/
|
|
193998
|
+
isCredentialsSharingAllowed(url, settingsUrl) {
|
|
193999
|
+
if (!this.restrictCredentialsToTrustedOrigins)
|
|
194000
|
+
return true;
|
|
194001
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
|
|
194002
|
+
if (origin === undefined)
|
|
194003
|
+
return false;
|
|
194004
|
+
if (origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
|
|
194005
|
+
return true;
|
|
194006
|
+
// Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
|
|
194007
|
+
return this._trustedCredentialsOrigins.includes(origin);
|
|
194008
|
+
}
|
|
194009
|
+
/** Origins for which a "credentials sent to untrusted origin" warning was already logged;
|
|
194010
|
+
* used to log the discovery warning only once per origin.
|
|
194011
|
+
*/
|
|
194012
|
+
_untrustedUseLogged = new Set();
|
|
194013
|
+
/** Logs a warning (once per origin) when credentials are sent to an origin that would be blocked
|
|
194014
|
+
* if [[restrictCredentialsToTrustedOrigins]] were enabled.
|
|
194015
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
194016
|
+
* If `settingsUrl` is supplied, requests sharing its origin are not logged, since that origin is
|
|
194017
|
+
* implicitly trusted for basic-auth.
|
|
194018
|
+
* @internal
|
|
194019
|
+
*/
|
|
194020
|
+
logUntrustedOriginUse(url, settingsUrl) {
|
|
194021
|
+
if (this.restrictCredentialsToTrustedOrigins)
|
|
194022
|
+
return; // restriction active; nothing to preview
|
|
194023
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url) ?? url;
|
|
194024
|
+
if (settingsUrl !== undefined && origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
|
|
194025
|
+
return; // implicitly trusted for basic-auth
|
|
194026
|
+
if (this._untrustedUseLogged.has(origin) || this._trustedCredentialsOrigins.includes(origin))
|
|
194027
|
+
return;
|
|
194028
|
+
this._untrustedUseLogged.add(origin);
|
|
194029
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `Credentials sent to origin '${origin}' which is not in MapLayerFormatRegistry.trustedCredentialsOrigins; `
|
|
194030
|
+
+ "this request would be blocked if restrictCredentialsToTrustedOrigins were enabled.");
|
|
194031
|
+
}
|
|
193813
194032
|
_formats = new Map();
|
|
193814
194033
|
isRegistered(formatId) { return this._formats.get(formatId) !== undefined; }
|
|
193815
194034
|
register(formatClass) {
|
|
@@ -193975,6 +194194,14 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat {
|
|
|
193975
194194
|
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
|
|
193976
194195
|
}
|
|
193977
194196
|
catch (err) {
|
|
194197
|
+
if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
|
|
194198
|
+
let blockedOrigin;
|
|
194199
|
+
try {
|
|
194200
|
+
blockedOrigin = new URL(err.url).origin;
|
|
194201
|
+
}
|
|
194202
|
+
catch { /* non-hierarchical URL */ }
|
|
194203
|
+
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
194204
|
+
}
|
|
193978
194205
|
let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
|
|
193979
194206
|
if (err?.status === 401) {
|
|
193980
194207
|
status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
|
|
@@ -194040,6 +194267,14 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat {
|
|
|
194040
194267
|
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
|
|
194041
194268
|
}
|
|
194042
194269
|
catch (err) {
|
|
194270
|
+
if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
|
|
194271
|
+
let blockedOrigin;
|
|
194272
|
+
try {
|
|
194273
|
+
blockedOrigin = new URL(err.url).origin;
|
|
194274
|
+
}
|
|
194275
|
+
catch { /* non-hierarchical URL */ }
|
|
194276
|
+
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
194277
|
+
}
|
|
194043
194278
|
let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
|
|
194044
194279
|
if (err?.status === 401) {
|
|
194045
194280
|
status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
|
|
@@ -194104,7 +194339,9 @@ const internalMapLayerImageryFormats = [WmsMapLayerFormat, WmtsMapLayerFormat, A
|
|
|
194104
194339
|
__webpack_require__.r(__webpack_exports__);
|
|
194105
194340
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
194106
194341
|
/* harmony export */ MapLayerImageryProvider: () => (/* binding */ MapLayerImageryProvider),
|
|
194107
|
-
/* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus)
|
|
194342
|
+
/* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus),
|
|
194343
|
+
/* harmony export */ escapeHtml: () => (/* binding */ escapeHtml),
|
|
194344
|
+
/* harmony export */ tryGetOrigin: () => (/* binding */ tryGetOrigin)
|
|
194108
194345
|
/* harmony export */ });
|
|
194109
194346
|
/* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
|
|
194110
194347
|
/* harmony import */ var _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @itwin/core-common */ "../../core/common/lib/esm/core-common.js");
|
|
@@ -194131,6 +194368,34 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
194131
194368
|
const tileImageSize = 256, untiledImageSize = 256;
|
|
194132
194369
|
const earthRadius = 6378137;
|
|
194133
194370
|
const doDebugToolTips = false;
|
|
194371
|
+
/** Escapes HTML metacharacters so the text renders literally when assigned to `innerHTML`.
|
|
194372
|
+
* Use for any server- or user-supplied string that ends up in the map tooltip, which is rendered
|
|
194373
|
+
* as HTML by [[MapLayerTileTreeReference.getToolTip]].
|
|
194374
|
+
* @internal
|
|
194375
|
+
*/
|
|
194376
|
+
function escapeHtml(text) {
|
|
194377
|
+
return text.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
194378
|
+
}
|
|
194379
|
+
/** Returns the origin (scheme + host + port) of the given URL, or undefined if it cannot be parsed or does
|
|
194380
|
+
* not denote a distinct network origin.
|
|
194381
|
+
*
|
|
194382
|
+
* Only `http:` and `https:` URLs yield an origin. Every other scheme is rejected because opaque URLs
|
|
194383
|
+
* — `file:`, `data:`, `about:`, `blob:null`, and the custom protocols Electron hosts commonly register —
|
|
194384
|
+
* all serialize to the literal string `"null"`. Comparing those would make unrelated URLs look same-origin,
|
|
194385
|
+
* so a single trusted entry could unlock all of them. Callers use this for credential-trust decisions, and
|
|
194386
|
+
* returning `undefined` keeps those decisions fail-closed.
|
|
194387
|
+
* @internal
|
|
194388
|
+
*/
|
|
194389
|
+
function tryGetOrigin(url) {
|
|
194390
|
+
let parsed;
|
|
194391
|
+
try {
|
|
194392
|
+
parsed = new URL(url);
|
|
194393
|
+
}
|
|
194394
|
+
catch {
|
|
194395
|
+
return undefined;
|
|
194396
|
+
}
|
|
194397
|
+
return (parsed.protocol === "http:" || parsed.protocol === "https:") ? parsed.origin : undefined;
|
|
194398
|
+
}
|
|
194134
194399
|
/** The status of the map layer imagery provider that lets you know if authentication is needed to request tiles.
|
|
194135
194400
|
* @public
|
|
194136
194401
|
*/
|
|
@@ -194138,6 +194403,12 @@ var MapLayerImageryProviderStatus;
|
|
|
194138
194403
|
(function (MapLayerImageryProviderStatus) {
|
|
194139
194404
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["Valid"] = 0] = "Valid";
|
|
194140
194405
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["RequireAuth"] = 1] = "RequireAuth";
|
|
194406
|
+
/** A request received an authentication challenge, but credentials were withheld because the request origin
|
|
194407
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
194408
|
+
* The blocked origins are available via [[MapLayerImageryProvider.blockedOrigins]].
|
|
194409
|
+
* @beta
|
|
194410
|
+
*/
|
|
194411
|
+
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["UntrustedOrigin"] = 2] = "UntrustedOrigin";
|
|
194141
194412
|
})(MapLayerImageryProviderStatus || (MapLayerImageryProviderStatus = {}));
|
|
194142
194413
|
/** Abstract class for map layer imagery providers.
|
|
194143
194414
|
* 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.
|
|
@@ -194155,7 +194426,41 @@ class MapLayerImageryProvider {
|
|
|
194155
194426
|
/** @internal */
|
|
194156
194427
|
_status = MapLayerImageryProviderStatus.Valid;
|
|
194157
194428
|
/** @internal */
|
|
194158
|
-
|
|
194429
|
+
_blockedOrigins = new Set();
|
|
194430
|
+
/** Origins of requests for which credentials were withheld because they are not trusted
|
|
194431
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
194432
|
+
* Populated when [[status]] transitions to [[MapLayerImageryProviderStatus.UntrustedOrigin]];
|
|
194433
|
+
* [[onStatusChanged]] is raised again each time a new origin is added. Cleared by [[resetStatus]].
|
|
194434
|
+
* @beta
|
|
194435
|
+
*/
|
|
194436
|
+
get blockedOrigins() { return [...this._blockedOrigins]; }
|
|
194437
|
+
/** Origins for which a previous SSO handshake (i.e. Windows Authentication) succeeded.
|
|
194438
|
+
* Browser credentials are only included for subsequent requests targeting these origins,
|
|
194439
|
+
* so that a successful handshake with one host does not leak credentials to other hosts
|
|
194440
|
+
* this provider may contact.
|
|
194441
|
+
* @internal
|
|
194442
|
+
*/
|
|
194443
|
+
_ssoSucceededOrigins = new Set();
|
|
194444
|
+
/** Returns true if browser credentials should be included for the given URL because a previous
|
|
194445
|
+
* SSO handshake succeeded for its origin AND the origin is still allowed by the current policy
|
|
194446
|
+
* (see [[MapLayerFormatRegistry.isSsoAllowed]]). Re-checking the policy ensures a handshake recorded
|
|
194447
|
+
* while enforcement was disabled — or before an origin was removed from
|
|
194448
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]] — does not keep latching credentials on.
|
|
194449
|
+
* @internal
|
|
194450
|
+
*/
|
|
194451
|
+
includeUserCredentials(url) {
|
|
194452
|
+
const origin = tryGetOrigin(url);
|
|
194453
|
+
return origin !== undefined && this._ssoSucceededOrigins.has(origin) && this.isSsoAllowed(url);
|
|
194454
|
+
}
|
|
194455
|
+
/** Records that an SSO handshake succeeded for the given URL's origin, so subsequent requests
|
|
194456
|
+
* to that origin include browser credentials without going through another 401 challenge.
|
|
194457
|
+
* @internal
|
|
194458
|
+
*/
|
|
194459
|
+
recordSsoSucceeded(url) {
|
|
194460
|
+
const origin = tryGetOrigin(url);
|
|
194461
|
+
if (origin !== undefined)
|
|
194462
|
+
this._ssoSucceededOrigins.add(origin);
|
|
194463
|
+
}
|
|
194159
194464
|
/** @internal */
|
|
194160
194465
|
onFirstRequestCompleted = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BeEvent();
|
|
194161
194466
|
/** @internal */
|
|
@@ -194171,7 +194476,17 @@ class MapLayerImageryProvider {
|
|
|
194171
194476
|
* @public
|
|
194172
194477
|
*/
|
|
194173
194478
|
get supportsMapFeatureInfo() { return false; }
|
|
194174
|
-
|
|
194479
|
+
/** Reset the provider's status to [[MapLayerImageryProviderStatus.Valid]] and clear the list of
|
|
194480
|
+
* [[blockedOrigins]] accumulated while in the [[MapLayerImageryProviderStatus.UntrustedOrigin]] state.
|
|
194481
|
+
* Raises [[onStatusChanged]] if the status actually changes.
|
|
194482
|
+
* Typically called after the user has provided credentials or the application has updated
|
|
194483
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]], so that subsequent requests are re-attempted.
|
|
194484
|
+
* @beta
|
|
194485
|
+
*/
|
|
194486
|
+
resetStatus() {
|
|
194487
|
+
this._blockedOrigins.clear();
|
|
194488
|
+
this.setStatus(MapLayerImageryProviderStatus.Valid);
|
|
194489
|
+
}
|
|
194175
194490
|
/** @internal */
|
|
194176
194491
|
get tileSize() { return this._usesCachedTiles ? tileImageSize : untiledImageSize; }
|
|
194177
194492
|
/** @internal */
|
|
@@ -194345,6 +194660,32 @@ class MapLayerImageryProvider {
|
|
|
194345
194660
|
(0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setBasicAuthorization)(headers, this._settings.userName, this._settings.password);
|
|
194346
194661
|
}
|
|
194347
194662
|
}
|
|
194663
|
+
/** Returns true if the given URL has the same origin as this layer's settings URL.
|
|
194664
|
+
* Used to avoid leaking credentials to third-party hosts.
|
|
194665
|
+
* @internal
|
|
194666
|
+
*/
|
|
194667
|
+
matchesSettingsUrlOrigin(url) {
|
|
194668
|
+
const origin = tryGetOrigin(url);
|
|
194669
|
+
return origin !== undefined && origin === tryGetOrigin(this._settings.url);
|
|
194670
|
+
}
|
|
194671
|
+
/** Returns true if the basic-auth credentials from the layer settings may be attached to a request to the given URL.
|
|
194672
|
+
* Always true unless [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
194673
|
+
* When enabled, the origin of this layer's settings URL is implicitly trusted (the credentials belong to that
|
|
194674
|
+
* server); other origins must be listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]].
|
|
194675
|
+
* See [[MapLayerFormatRegistry.isCredentialsSharingAllowed]].
|
|
194676
|
+
* @internal
|
|
194677
|
+
*/
|
|
194678
|
+
isCredentialsSharingAllowed(url) {
|
|
194679
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, this._settings.url);
|
|
194680
|
+
}
|
|
194681
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
194682
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
194683
|
+
* See [[MapLayerFormatRegistry.isSsoAllowed]].
|
|
194684
|
+
* @internal
|
|
194685
|
+
*/
|
|
194686
|
+
isSsoAllowed(url) {
|
|
194687
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(url);
|
|
194688
|
+
}
|
|
194348
194689
|
/** @internal */
|
|
194349
194690
|
async makeTileRequest(url, timeoutMs, authorization) {
|
|
194350
194691
|
// We want to complete the first request before letting other requests go;
|
|
@@ -194364,41 +194705,133 @@ class MapLayerImageryProvider {
|
|
|
194364
194705
|
throw new Error("fetch call failed");
|
|
194365
194706
|
return response;
|
|
194366
194707
|
}
|
|
194708
|
+
/** Records the given URL's origin and transitions the status to [[MapLayerImageryProviderStatus.UntrustedOrigin]].
|
|
194709
|
+
* Called when a request received an authentication challenge that could not be answered because the origin
|
|
194710
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
194711
|
+
* Raises [[onStatusChanged]] on the status transition, and again whenever a new origin is added.
|
|
194712
|
+
* @internal
|
|
194713
|
+
*/
|
|
194714
|
+
reportBlockedOrigin(url) {
|
|
194715
|
+
const origin = tryGetOrigin(url) ?? url;
|
|
194716
|
+
const isNewOrigin = !this._blockedOrigins.has(origin);
|
|
194717
|
+
this._blockedOrigins.add(origin);
|
|
194718
|
+
if (this._status !== MapLayerImageryProviderStatus.UntrustedOrigin)
|
|
194719
|
+
this.setStatus(MapLayerImageryProviderStatus.UntrustedOrigin);
|
|
194720
|
+
else if (isNewOrigin)
|
|
194721
|
+
this.onStatusChanged.raiseEvent(this); // status unchanged, but a new origin was blocked
|
|
194722
|
+
}
|
|
194723
|
+
/** Logs a warning (once per origin, app-wide) when credentials are sent to an origin that would be blocked
|
|
194724
|
+
* if [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] were enabled.
|
|
194725
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
194726
|
+
* See [[MapLayerFormatRegistry.logUntrustedOriginUse]].
|
|
194727
|
+
* @internal
|
|
194728
|
+
*/
|
|
194729
|
+
logUntrustedOriginUse(url) {
|
|
194730
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(url);
|
|
194731
|
+
}
|
|
194732
|
+
/** The redirect policy to apply to a request that carries browser credentials (see [[includeUserCredentials]]).
|
|
194733
|
+
*
|
|
194734
|
+
* When [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled, redirects are refused
|
|
194735
|
+
* outright (`"error"`). `fetch` cannot be asked to follow only same-origin redirects, and by the time a
|
|
194736
|
+
* followed redirect can be inspected the credentials have already been delivered to the destination — so
|
|
194737
|
+
* refusing is the only way to honour the guarantee that credentials reach none but the origins listed in
|
|
194738
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]]. Legitimate same-origin redirects fail as a result;
|
|
194739
|
+
* that is the cost of the opt-in restriction.
|
|
194740
|
+
*
|
|
194741
|
+
* When the restriction is disabled (the default), redirects are followed as before and
|
|
194742
|
+
* [[checkCredentialedRedirect]] reports the destination after the fact.
|
|
194743
|
+
* @internal
|
|
194744
|
+
*/
|
|
194745
|
+
get credentialedRedirect() {
|
|
194746
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
194747
|
+
}
|
|
194748
|
+
/** Detects that a request carrying browser credentials (see [[includeUserCredentials]]) was transparently
|
|
194749
|
+
* redirected to a different origin, and reports or logs that origin.
|
|
194750
|
+
*
|
|
194751
|
+
* This is a **best-effort, after-the-fact** signal used only while
|
|
194752
|
+
* [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is disabled, where credentialed requests
|
|
194753
|
+
* still follow redirects (see [[credentialedRedirect]]). It cannot prevent the exposure — the credentials
|
|
194754
|
+
* have already been sent — and it does not fire at all when the destination denies CORS, because `fetch`
|
|
194755
|
+
* then rejects instead of returning a `Response`. The destination origin is never latched as SSO-succeeded,
|
|
194756
|
+
* so credentials do not keep flowing to it.
|
|
194757
|
+
* @internal
|
|
194758
|
+
*/
|
|
194759
|
+
checkCredentialedRedirect(requestedUrl, response) {
|
|
194760
|
+
const finalOrigin = tryGetOrigin(response.url);
|
|
194761
|
+
if (!response.url || finalOrigin === undefined || finalOrigin === tryGetOrigin(requestedUrl))
|
|
194762
|
+
return;
|
|
194763
|
+
if (!this.isSsoAllowed(response.url))
|
|
194764
|
+
this.reportBlockedOrigin(response.url);
|
|
194765
|
+
else
|
|
194766
|
+
this.logUntrustedOriginUse(response.url); // no-op when the restriction is enabled
|
|
194767
|
+
}
|
|
194367
194768
|
/** @internal */
|
|
194368
194769
|
async makeRequest(url, timeoutMs, authorization) {
|
|
194369
194770
|
let response;
|
|
194370
194771
|
let headers;
|
|
194371
194772
|
let hasCreds = false;
|
|
194773
|
+
// Whether this request had basic-auth credentials of its own to offer. Requests carrying a caller-supplied
|
|
194774
|
+
// `authorization` are excluded: those bypass the origin policy entirely.
|
|
194775
|
+
const hasSettingsCreds = !authorization && !!this._settings.userName && !!this._settings.password;
|
|
194372
194776
|
if (authorization) {
|
|
194373
194777
|
headers = new Headers();
|
|
194374
194778
|
headers.set("Authorization", authorization);
|
|
194375
194779
|
}
|
|
194376
|
-
else if (
|
|
194377
|
-
|
|
194378
|
-
|
|
194379
|
-
|
|
194780
|
+
else if (hasSettingsCreds) {
|
|
194781
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
194782
|
+
hasCreds = true;
|
|
194783
|
+
headers = new Headers();
|
|
194784
|
+
this.setRequestAuthorization(headers);
|
|
194785
|
+
if (!this.matchesSettingsUrlOrigin(url))
|
|
194786
|
+
this.logUntrustedOriginUse(url);
|
|
194787
|
+
}
|
|
194380
194788
|
}
|
|
194789
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
194381
194790
|
const opts = {
|
|
194382
194791
|
method: "GET",
|
|
194383
194792
|
headers,
|
|
194384
|
-
credentials:
|
|
194793
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
194794
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
194385
194795
|
};
|
|
194386
194796
|
if (timeoutMs !== undefined)
|
|
194387
194797
|
(0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setRequestTimeout)(opts, timeoutMs);
|
|
194388
194798
|
response = await fetch(url, opts);
|
|
194799
|
+
if (includeCredentials)
|
|
194800
|
+
this.checkCredentialedRedirect(url, response);
|
|
194801
|
+
// fetch follows redirects transparently, so all trust decisions below target the final
|
|
194802
|
+
// (post-redirect) URL reported by the response, not the URL we asked for.
|
|
194803
|
+
const challengedUrl = response.url || url;
|
|
194389
194804
|
if (response.status === 401
|
|
194390
194805
|
&& (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])
|
|
194391
|
-
&& !
|
|
194806
|
+
&& !includeCredentials
|
|
194392
194807
|
&& !hasCreds) {
|
|
194393
|
-
|
|
194394
|
-
|
|
194395
|
-
|
|
194396
|
-
|
|
194397
|
-
|
|
194398
|
-
|
|
194399
|
-
|
|
194808
|
+
if (this.isSsoAllowed(challengedUrl)) {
|
|
194809
|
+
// Removed the previous headers and make sure "include" credentials is set
|
|
194810
|
+
opts.headers = undefined;
|
|
194811
|
+
opts.credentials = "include";
|
|
194812
|
+
// A Negotiate/NTLM handshake is normally a same-URL 401 round-trip, but in legacy mode we preserve
|
|
194813
|
+
// the previous behavior and allow the browser to follow redirects after the authenticated retry.
|
|
194814
|
+
opts.redirect = _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
194815
|
+
this.logUntrustedOriginUse(challengedUrl);
|
|
194816
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
|
|
194817
|
+
response = await fetch(challengedUrl, opts);
|
|
194818
|
+
if (response.status === 200) {
|
|
194819
|
+
this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
|
|
194820
|
+
}
|
|
194821
|
+
}
|
|
194822
|
+
else {
|
|
194823
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
194400
194824
|
}
|
|
194401
194825
|
}
|
|
194826
|
+
else if ((response.status === 401 || response.status === 403) && hasSettingsCreds && !this.isCredentialsSharingAllowed(challengedUrl)) {
|
|
194827
|
+
// Some servers answer an unauthenticated request with 403 (Forbidden) rather than a 401 challenge;
|
|
194828
|
+
// since this request could not present its credentials to the challenging origin, either status most
|
|
194829
|
+
// likely results from that. The permission is recomputed for the challenged URL rather than reusing the
|
|
194830
|
+
// decision made for the requested one: `fetch` strips the Authorization header when it follows a
|
|
194831
|
+
// cross-origin redirect, so a trusted request can still arrive unauthenticated at an untrusted origin,
|
|
194832
|
+
// and conversely a request that started out untrusted may end up at an origin that is trusted.
|
|
194833
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
194834
|
+
}
|
|
194402
194835
|
return response;
|
|
194403
194836
|
}
|
|
194404
194837
|
/** Returns a map layer tile at the specified settings. */
|
|
@@ -194429,16 +194862,28 @@ class MapLayerImageryProvider {
|
|
|
194429
194862
|
}
|
|
194430
194863
|
/** @internal */
|
|
194431
194864
|
async toolTipFromUrl(strings, url) {
|
|
194432
|
-
|
|
194433
|
-
this.
|
|
194865
|
+
let headers;
|
|
194866
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
194867
|
+
headers = new Headers();
|
|
194868
|
+
this.setRequestAuthorization(headers);
|
|
194869
|
+
}
|
|
194434
194870
|
try {
|
|
194871
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
194435
194872
|
const response = await fetch(url, {
|
|
194436
194873
|
method: "GET",
|
|
194437
194874
|
headers,
|
|
194438
|
-
credentials:
|
|
194875
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
194876
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
194439
194877
|
});
|
|
194440
|
-
|
|
194441
|
-
|
|
194878
|
+
if (includeCredentials)
|
|
194879
|
+
this.checkCredentialedRedirect(url, response);
|
|
194880
|
+
let text = await response.text();
|
|
194881
|
+
if (text) {
|
|
194882
|
+
// Tooltip content (e.g. WMS GetFeatureInfo responses) is rendered as HTML downstream and may
|
|
194883
|
+
// deliberately contain markup; text from origins not trusted for credentials is escaped.
|
|
194884
|
+
// fetch follows redirects transparently, so the text may come from a different origin than requested.
|
|
194885
|
+
if (!this.isCredentialsSharingAllowed(response.url || url))
|
|
194886
|
+
text = escapeHtml(text);
|
|
194442
194887
|
strings.push(text);
|
|
194443
194888
|
}
|
|
194444
194889
|
}
|
|
@@ -194618,6 +195063,12 @@ var MapLayerSourceStatus;
|
|
|
194618
195063
|
/** Format is not compatible with the URL provided.
|
|
194619
195064
|
*/
|
|
194620
195065
|
MapLayerSourceStatus[MapLayerSourceStatus["IncompatibleFormat"] = 7] = "IncompatibleFormat";
|
|
195066
|
+
/** Authentication could not be attempted because the source's origin is not trusted
|
|
195067
|
+
* (see [MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]($frontend)). Add the origin to
|
|
195068
|
+
* [MapLayerFormatRegistry.trustedCredentialsOrigins]($frontend) rather than prompting for credentials.
|
|
195069
|
+
* @beta
|
|
195070
|
+
*/
|
|
195071
|
+
MapLayerSourceStatus[MapLayerSourceStatus["UntrustedOrigin"] = 8] = "UntrustedOrigin";
|
|
194621
195072
|
})(MapLayerSourceStatus || (MapLayerSourceStatus = {}));
|
|
194622
195073
|
/** A source for map layers. These may be catalogued for convenient use by users or applications.
|
|
194623
195074
|
* @public
|
|
@@ -194905,10 +195356,8 @@ class MapLayerTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_3__.T
|
|
|
194905
195356
|
const tree = this.treeOwner.tileTree;
|
|
194906
195357
|
if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.sourceId)
|
|
194907
195358
|
return undefined;
|
|
194908
|
-
const strings = [];
|
|
194909
|
-
strings.push(`Map Layer: ${this._layerSettings.name}`);
|
|
194910
195359
|
const div = document.createElement("div");
|
|
194911
|
-
div.
|
|
195360
|
+
div.textContent = `Map Layer: ${this._layerSettings.name}`;
|
|
194912
195361
|
return div;
|
|
194913
195362
|
}
|
|
194914
195363
|
decorate(_context) {
|
|
@@ -196617,7 +197066,9 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
|
|
|
196617
197066
|
let carto;
|
|
196618
197067
|
const strings = [];
|
|
196619
197068
|
const getTooltipFunc = async (imageryTreeRef, quadId, cartoGraphic, imageryTree) => {
|
|
196620
|
-
|
|
197069
|
+
// innerHTML is used below because imageryLoader.getToolTip may deliberately supply markup.
|
|
197070
|
+
const layerName = (0,_internal__WEBPACK_IMPORTED_MODULE_7__.escapeHtml)(imageryTreeRef.layerSettings.name);
|
|
197071
|
+
strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${layerName}`);
|
|
196621
197072
|
carto = cartoGraphic;
|
|
196622
197073
|
await imageryTree.imageryLoader.getToolTip(strings, quadId, cartoGraphic, imageryTree);
|
|
196623
197074
|
};
|
|
@@ -342457,7 +342908,7 @@ class TestContext {
|
|
|
342457
342908
|
this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
|
|
342458
342909
|
const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } });
|
|
342459
342910
|
await core_frontend_1.NoRenderApp.startup({
|
|
342460
|
-
applicationVersion: "5.13.0-dev.
|
|
342911
|
+
applicationVersion: "5.13.0-dev.17",
|
|
342461
342912
|
applicationId: this.settings.gprid,
|
|
342462
342913
|
authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.serviceAuthToken),
|
|
342463
342914
|
hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
|
|
@@ -367652,7 +368103,7 @@ var loadLanguages = instance.loadLanguages;
|
|
|
367652
368103
|
(module) {
|
|
367653
368104
|
|
|
367654
368105
|
"use strict";
|
|
367655
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.
|
|
368106
|
+
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"}}');
|
|
367656
368107
|
|
|
367657
368108
|
/***/ },
|
|
367658
368109
|
|