@itwin/rpcinterface-full-stack-tests 5.13.0-dev.16 → 5.13.0-dev.18
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 +592 -97
- package/lib/dist/bundled-tests.js.map +1 -1
- package/lib/dist/core_frontend_lib_esm_ApproximateTerrainHeightsProps_js.bundled-tests.js.map +1 -1
- package/lib/dist/vendors-common_temp_node_modules_pnpm_cross-fetch_4_1_0_node_modules_cross-fetch_dist_browser-44272f.bundled-tests.js.map +1 -1
- package/lib/dist/vendors-common_temp_node_modules_pnpm_loaders_gl_draco_4_3_4__loaders_gl_core_4_3_4_node_modu-4c1fc9.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";
|
|
@@ -173470,6 +173488,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
173470
173488
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
173471
173489
|
/* harmony export */ OrbitGtTileTree: () => (/* binding */ OrbitGtTileTree),
|
|
173472
173490
|
/* harmony export */ OrbitGtTreeReference: () => (/* binding */ OrbitGtTreeReference),
|
|
173491
|
+
/* harmony export */ computeOrthometricVerticalShift: () => (/* binding */ computeOrthometricVerticalShift),
|
|
173473
173492
|
/* harmony export */ createOrbitGtTileTreeReference: () => (/* binding */ createOrbitGtTileTreeReference)
|
|
173474
173493
|
/* harmony export */ });
|
|
173475
173494
|
/* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
|
|
@@ -173477,11 +173496,12 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
173477
173496
|
/* harmony import */ var _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @itwin/core-geometry */ "../../core/geometry/lib/esm/core-geometry.js");
|
|
173478
173497
|
/* harmony import */ var _itwin_core_orbitgt__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @itwin/core-orbitgt */ "../../core/orbitgt/lib/esm/core-orbitgt.js");
|
|
173479
173498
|
/* harmony import */ var _BackgroundMapGeometry__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../../BackgroundMapGeometry */ "../../core/frontend/lib/esm/BackgroundMapGeometry.js");
|
|
173480
|
-
/* harmony import */ var
|
|
173481
|
-
/* harmony import */ var
|
|
173482
|
-
/* harmony import */ var
|
|
173483
|
-
/* harmony import */ var
|
|
173484
|
-
/* harmony import */ var
|
|
173499
|
+
/* harmony import */ var _common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../common/FrontendLoggerCategory */ "../../core/frontend/lib/esm/common/FrontendLoggerCategory.js");
|
|
173500
|
+
/* harmony import */ var _DisplayStyleState__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../DisplayStyleState */ "../../core/frontend/lib/esm/DisplayStyleState.js");
|
|
173501
|
+
/* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
|
|
173502
|
+
/* harmony import */ var _RealityDataSource__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../../RealityDataSource */ "../../core/frontend/lib/esm/RealityDataSource.js");
|
|
173503
|
+
/* harmony import */ var _common_internal_render_MeshPrimitives__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../common/internal/render/MeshPrimitives */ "../../core/frontend/lib/esm/common/internal/render/MeshPrimitives.js");
|
|
173504
|
+
/* harmony import */ var _tile_internal__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../../tile/internal */ "../../core/frontend/lib/esm/tile/internal.js");
|
|
173485
173505
|
/*---------------------------------------------------------------------------------------------
|
|
173486
173506
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
173487
173507
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -173499,6 +173519,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
173499
173519
|
|
|
173500
173520
|
|
|
173501
173521
|
|
|
173522
|
+
|
|
173502
173523
|
const scratchRange = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Range3d.create();
|
|
173503
173524
|
const scratchWorldFrustum = new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.Frustum();
|
|
173504
173525
|
function compareSourceKeys(lhs, rhs) {
|
|
@@ -173562,7 +173583,7 @@ class OrbitGtTileTreeParams {
|
|
|
173562
173583
|
id;
|
|
173563
173584
|
modelId;
|
|
173564
173585
|
iModel;
|
|
173565
|
-
get priority() { return
|
|
173586
|
+
get priority() { return _tile_internal__WEBPACK_IMPORTED_MODULE_10__.TileLoadPriority.Context; }
|
|
173566
173587
|
constructor(rdSourceKey, iModel, modelId, location) {
|
|
173567
173588
|
this.location = location;
|
|
173568
173589
|
const key = rdSourceKey;
|
|
@@ -173571,10 +173592,10 @@ class OrbitGtTileTreeParams {
|
|
|
173571
173592
|
this.iModel = iModel;
|
|
173572
173593
|
}
|
|
173573
173594
|
}
|
|
173574
|
-
class OrbitGtRootTile extends
|
|
173595
|
+
class OrbitGtRootTile extends _tile_internal__WEBPACK_IMPORTED_MODULE_10__.Tile {
|
|
173575
173596
|
_loadChildren(_resolve, _reject) { }
|
|
173576
173597
|
async requestContent(_isCanceled) { return undefined; }
|
|
173577
|
-
get channel() { return
|
|
173598
|
+
get channel() { return _IModelApp__WEBPACK_IMPORTED_MODULE_7__.IModelApp.tileAdmin.channels.getForHttp("itwinjs-orbitgit"); }
|
|
173578
173599
|
async readContent(_data, _system, _isCanceled) { return {}; }
|
|
173579
173600
|
freeMemory() { }
|
|
173580
173601
|
constructor(params, tree) { super(params, tree); }
|
|
@@ -173644,7 +173665,7 @@ class TileSortProjector {
|
|
|
173644
173665
|
coordinate.z = point.z;
|
|
173645
173666
|
}
|
|
173646
173667
|
}
|
|
173647
|
-
class OrbitGtTileGraphic extends
|
|
173668
|
+
class OrbitGtTileGraphic extends _tile_internal__WEBPACK_IMPORTED_MODULE_10__.TileUsageMarker {
|
|
173648
173669
|
graphic;
|
|
173649
173670
|
constructor(graphic, viewport, time) {
|
|
173650
173671
|
super();
|
|
@@ -173655,7 +173676,7 @@ class OrbitGtTileGraphic extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.Til
|
|
|
173655
173676
|
this.graphic[Symbol.dispose]();
|
|
173656
173677
|
}
|
|
173657
173678
|
}
|
|
173658
|
-
class OrbitGtTileTree extends
|
|
173679
|
+
class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_10__.TileTree {
|
|
173659
173680
|
_dataManager;
|
|
173660
173681
|
_centerOffset;
|
|
173661
173682
|
_ecefTransform;
|
|
@@ -173671,7 +173692,7 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173671
173692
|
this._dataManager = _dataManager;
|
|
173672
173693
|
this._centerOffset = _centerOffset;
|
|
173673
173694
|
this._ecefTransform = _ecefTransform;
|
|
173674
|
-
this._layerHandler = new
|
|
173695
|
+
this._layerHandler = new _tile_internal__WEBPACK_IMPORTED_MODULE_10__.LayerTileTreeHandler(this);
|
|
173675
173696
|
this._tileParams = { contentId: "0", range: cloudRange, maximumSize: 256 };
|
|
173676
173697
|
this.rootTile = new OrbitGtRootTile(this._tileParams, this);
|
|
173677
173698
|
}
|
|
@@ -173720,7 +173741,7 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173720
173741
|
let totalPointCount = 0;
|
|
173721
173742
|
const tileCount = frameData.tilesToRender.size();
|
|
173722
173743
|
// Inform TileAdmin about tiles we are handling ourselves...
|
|
173723
|
-
|
|
173744
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_7__.IModelApp.tileAdmin.addExternalTilesForUser(args.context.viewport, { requested: frameData.tilesToLoad.size() + (frameData.hasMissingData() ? 1 : 0), selected: tileCount, ready: tileCount });
|
|
173724
173745
|
if (debugBuilder)
|
|
173725
173746
|
debugBuilder.setSymbology(_itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.ColorDef.red, _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.ColorDef.red, 1);
|
|
173726
173747
|
let minLevel = 100, maxLevel = -100;
|
|
@@ -173741,8 +173762,8 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173741
173762
|
range.high.addInPlace(this._centerOffset);
|
|
173742
173763
|
const qParams = _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.QParams3d.fromRange(range, undefined, (tile.points8 != null) ? _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.Quantization.rangeScale8 : _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.Quantization.rangeScale16);
|
|
173743
173764
|
const featureTable = new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.FeatureTable(1, this.modelId, _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.BatchType.Primary);
|
|
173744
|
-
const features = new
|
|
173745
|
-
const system =
|
|
173765
|
+
const features = new _common_internal_render_MeshPrimitives__WEBPACK_IMPORTED_MODULE_9__.Mesh.Features(featureTable);
|
|
173766
|
+
const system = _IModelApp__WEBPACK_IMPORTED_MODULE_7__.IModelApp.renderSystem;
|
|
173746
173767
|
const voxelSize = (range.high.x - range.low.x) / 64;
|
|
173747
173768
|
features.add(new _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.Feature(this.modelId), 1);
|
|
173748
173769
|
const tilePoints = (tile.points8 != null) ? tile.points8.toNativeBuffer() : tile.points16.toNativeBuffer();
|
|
@@ -173769,8 +173790,34 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173769
173790
|
}
|
|
173770
173791
|
args.drawGraphics();
|
|
173771
173792
|
if (frameData.hasMissingData()) {
|
|
173772
|
-
this._dataManager.loadData(frameData).then(() =>
|
|
173793
|
+
this._dataManager.loadData(frameData).then(() => _IModelApp__WEBPACK_IMPORTED_MODULE_7__.IModelApp.tileAdmin.onTileLoad.raiseEvent(this.rootTile)).catch((_err) => undefined);
|
|
173794
|
+
}
|
|
173795
|
+
}
|
|
173796
|
+
}
|
|
173797
|
+
/** Computes the vertical shift, in meters along geodetic up, to correctly place a point cloud whose CRS does not
|
|
173798
|
+
* define a vertical datum, assuming its heights are orthometric (relative to the geoid).
|
|
173799
|
+
*
|
|
173800
|
+
* The shift is the difference between converting the point cloud's origin with its height treated as orthometric
|
|
173801
|
+
* versus ellipsoidal (`heightAsEllipsoidalDbZ`, already computed by the caller). Returns zero if the shift cannot
|
|
173802
|
+
* be computed or the iModel's converter makes no distinction between the two.
|
|
173803
|
+
* Exported strictly for tests.
|
|
173804
|
+
* @internal
|
|
173805
|
+
*/
|
|
173806
|
+
async function computeOrthometricVerticalShift(geoOrigin, heightAsEllipsoidalDbZ, iModel) {
|
|
173807
|
+
const geoidConverter = iModel.noGcsDefined ? undefined : iModel.geoServices.getConverter({ horizontalCRS: { epsg: 4326 }, verticalCRS: { id: "GEOID" } });
|
|
173808
|
+
if (undefined === geoidConverter)
|
|
173809
|
+
return 0;
|
|
173810
|
+
try {
|
|
173811
|
+
const response = await geoidConverter.getIModelCoordinatesFromGeoCoordinates([geoOrigin]);
|
|
173812
|
+
if (response.iModelCoords[0].s !== _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.GeoCoordStatus.Success) {
|
|
173813
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(_common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_5__.FrontendLoggerCategory.RealityData, `Failed to compute orthometric height correction for point cloud (status ${response.iModelCoords[0].s}); heights will be treated as ellipsoidal`);
|
|
173814
|
+
return 0;
|
|
173773
173815
|
}
|
|
173816
|
+
return _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Point3d.fromJSON(response.iModelCoords[0].p).z - heightAsEllipsoidalDbZ;
|
|
173817
|
+
}
|
|
173818
|
+
catch (err) {
|
|
173819
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logError(_common_FrontendLoggerCategory__WEBPACK_IMPORTED_MODULE_5__.FrontendLoggerCategory.RealityData, err);
|
|
173820
|
+
return 0;
|
|
173774
173821
|
}
|
|
173775
173822
|
}
|
|
173776
173823
|
(function (OrbitGtTileTree) {
|
|
@@ -173796,7 +173843,7 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173796
173843
|
return isValidSASToken(props.sasToken);
|
|
173797
173844
|
}
|
|
173798
173845
|
async function createOrbitGtTileTree(rdSourceKey, iModel, modelId) {
|
|
173799
|
-
const rdSource = await
|
|
173846
|
+
const rdSource = await _RealityDataSource__WEBPACK_IMPORTED_MODULE_8__.RealityDataSource.fromKey(rdSourceKey, iModel.iTwinId);
|
|
173800
173847
|
const isContextShare = rdSourceKey.provider === _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.RealityDataProvider.ContextShare;
|
|
173801
173848
|
const isTilestUrl = rdSourceKey.provider === _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.RealityDataProvider.TilesetUrl;
|
|
173802
173849
|
let blobStringUrl;
|
|
@@ -173807,7 +173854,7 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173807
173854
|
const docRootName = realityData.rootDocument;
|
|
173808
173855
|
if (!docRootName)
|
|
173809
173856
|
return undefined;
|
|
173810
|
-
const token = await
|
|
173857
|
+
const token = await _IModelApp__WEBPACK_IMPORTED_MODULE_7__.IModelApp.getAccessToken();
|
|
173811
173858
|
const blobUrl = await realityData.getBlobUrl(token, docRootName);
|
|
173812
173859
|
blobStringUrl = blobUrl.toString();
|
|
173813
173860
|
}
|
|
@@ -173815,7 +173862,7 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173815
173862
|
blobStringUrl = rdSourceKey.id;
|
|
173816
173863
|
}
|
|
173817
173864
|
else {
|
|
173818
|
-
const orbitGtBlobProps =
|
|
173865
|
+
const orbitGtBlobProps = _RealityDataSource__WEBPACK_IMPORTED_MODULE_8__.RealityDataSource.createOrbitGtBlobPropsFromKey(rdSourceKey);
|
|
173819
173866
|
if (orbitGtBlobProps === undefined)
|
|
173820
173867
|
return undefined;
|
|
173821
173868
|
if (!isValidOrbitGtBlobProps(orbitGtBlobProps))
|
|
@@ -173850,7 +173897,7 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173850
173897
|
const wgs84CRS = "4978";
|
|
173851
173898
|
await _itwin_core_orbitgt__WEBPACK_IMPORTED_MODULE_3__.CRSManager.ENGINE.prepareForArea(wgs84CRS, new _itwin_core_orbitgt__WEBPACK_IMPORTED_MODULE_3__.OrbitGtBounds());
|
|
173852
173899
|
const pointCloudToEcef = transformFromOrbitGt(_itwin_core_orbitgt__WEBPACK_IMPORTED_MODULE_3__.CRSManager.createTransform(pointCloudCRS, new _itwin_core_orbitgt__WEBPACK_IMPORTED_MODULE_3__.OrbitGtCoordinate(pointCloudCenter.x, pointCloudCenter.y, pointCloudCenter.z), wgs84CRS));
|
|
173853
|
-
|
|
173900
|
+
let pointCloudCenterToEcef = pointCloudToEcef.multiplyTransformTransform(addCloudCenter);
|
|
173854
173901
|
ecefTransform.setFrom(pointCloudCenterToEcef);
|
|
173855
173902
|
let ecefToDb = iModel.getMapEcefToDb(0);
|
|
173856
173903
|
// In initial publishing version the iModel ecef Transform was used to locate the reality model.
|
|
@@ -173870,7 +173917,21 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173870
173917
|
const geoOrigin = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Point3d.create(cartographicOrigin.longitudeDegrees, cartographicOrigin.latitudeDegrees, cartographicOrigin.height);
|
|
173871
173918
|
const response = await geoConverter.getIModelCoordinatesFromGeoCoordinates([geoOrigin]);
|
|
173872
173919
|
if (response.iModelCoords[0].s === _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.GeoCoordStatus.Success) {
|
|
173873
|
-
const
|
|
173920
|
+
const dbOriginFromGcs = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Point3d.fromJSON(response.iModelCoords[0].p);
|
|
173921
|
+
// A projected CRS defines no vertical datum, so the point cloud's heights are conventionally orthometric -
|
|
173922
|
+
// but pointCloudToEcef above treated them as ellipsoidal. Correct the placement by the difference.
|
|
173923
|
+
// (A compound CRS also takes this path; that stays correct unless orbitgt gains a geoid model.)
|
|
173924
|
+
if (_itwin_core_orbitgt__WEBPACK_IMPORTED_MODULE_3__.CRSManager.ENGINE.isProjectedCRS(pointCloudCRS)) {
|
|
173925
|
+
const verticalShift = await computeOrthometricVerticalShift(geoOrigin, dbOriginFromGcs.z, iModel);
|
|
173926
|
+
if (0 !== verticalShift) {
|
|
173927
|
+
const upVector = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Vector3d.createStartEnd(cartographicOrigin.toEcef(), _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.Cartographic.fromRadians({ longitude: cartographicOrigin.longitude, latitude: cartographicOrigin.latitude, height: cartographicOrigin.height + 1 }).toEcef()).normalize();
|
|
173928
|
+
if (undefined !== upVector) {
|
|
173929
|
+
pointCloudCenterToEcef = _itwin_core_geometry__WEBPACK_IMPORTED_MODULE_2__.Transform.createTranslation(upVector.scale(verticalShift)).multiplyTransformTransform(pointCloudCenterToEcef);
|
|
173930
|
+
ecefTransform.setFrom(pointCloudCenterToEcef);
|
|
173931
|
+
}
|
|
173932
|
+
}
|
|
173933
|
+
}
|
|
173934
|
+
const ecefToDbOrigin = await (0,_BackgroundMapGeometry__WEBPACK_IMPORTED_MODULE_4__.calculateEcefToDbTransformAtLocation)(dbOriginFromGcs, iModel);
|
|
173874
173935
|
if (ecefToDbOrigin)
|
|
173875
173936
|
ecefToDb = ecefToDbOrigin;
|
|
173876
173937
|
}
|
|
@@ -173890,7 +173951,7 @@ class OrbitGtTileTree extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.TileTr
|
|
|
173890
173951
|
/** Supplies a reality data [[TileTree]] from a URL. May be associated with a persistent [[GeometricModelState]], or attached at run-time via a [[ContextOrbitGtState]].
|
|
173891
173952
|
* Exported strictly for tests.
|
|
173892
173953
|
*/
|
|
173893
|
-
class OrbitGtTreeReference extends
|
|
173954
|
+
class OrbitGtTreeReference extends _tile_internal__WEBPACK_IMPORTED_MODULE_10__.RealityModelTileTree.Reference {
|
|
173894
173955
|
treeOwner;
|
|
173895
173956
|
_rdSourceKey;
|
|
173896
173957
|
_modelId;
|
|
@@ -173903,15 +173964,15 @@ class OrbitGtTreeReference extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.R
|
|
|
173903
173964
|
this._rdSourceKey = props.rdSourceKey;
|
|
173904
173965
|
}
|
|
173905
173966
|
else if (props.orbitGtBlob) {
|
|
173906
|
-
this._rdSourceKey =
|
|
173967
|
+
this._rdSourceKey = _RealityDataSource__WEBPACK_IMPORTED_MODULE_8__.RealityDataSource.createKeyFromOrbitGtBlobProps(props.orbitGtBlob);
|
|
173907
173968
|
}
|
|
173908
173969
|
else {
|
|
173909
173970
|
// TODO: Maybe we should throw an exception
|
|
173910
|
-
this._rdSourceKey =
|
|
173971
|
+
this._rdSourceKey = _RealityDataSource__WEBPACK_IMPORTED_MODULE_8__.RealityDataSource.createKeyFromBlobUrl("", _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.RealityDataProvider.OrbitGtBlob, _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__.RealityDataFormat.OPC);
|
|
173911
173972
|
}
|
|
173912
173973
|
// ###TODO find compatible model Id
|
|
173913
173974
|
let modelId = props.modelId;
|
|
173914
|
-
if (undefined === modelId && this._source instanceof
|
|
173975
|
+
if (undefined === modelId && this._source instanceof _DisplayStyleState__WEBPACK_IMPORTED_MODULE_6__.DisplayStyleState)
|
|
173915
173976
|
modelId = orbitGtTreeSupplier.findCompatibleContextRealityModelId(this._rdSourceKey, this._source);
|
|
173916
173977
|
this._modelId = modelId ?? props.iModel.transientIds.getNext();
|
|
173917
173978
|
const ogtTreeId = { rdSourceKey: this._rdSourceKey, modelId: this.modelId };
|
|
@@ -173926,11 +173987,15 @@ class OrbitGtTreeReference extends _tile_internal__WEBPACK_IMPORTED_MODULE_9__.R
|
|
|
173926
173987
|
if (undefined === tree || hit.iModel !== tree.iModel)
|
|
173927
173988
|
return undefined;
|
|
173928
173989
|
const strings = [];
|
|
173929
|
-
strings.push(
|
|
173990
|
+
strings.push(_IModelApp__WEBPACK_IMPORTED_MODULE_7__.IModelApp.localization.getLocalizedString("iModelJs:RealityModelTypes.OrbitGTPointCloud"));
|
|
173930
173991
|
if (this._name)
|
|
173931
|
-
strings.push(`${
|
|
173992
|
+
strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_7__.IModelApp.localization.getLocalizedString("iModelJs:TooltipInfo.Name")} ${this._name}`);
|
|
173932
173993
|
const div = document.createElement("div");
|
|
173933
|
-
|
|
173994
|
+
strings.forEach((str, index) => {
|
|
173995
|
+
if (index > 0)
|
|
173996
|
+
div.appendChild(document.createElement("br"));
|
|
173997
|
+
div.appendChild(document.createTextNode(str));
|
|
173998
|
+
});
|
|
173934
173999
|
return div;
|
|
173935
174000
|
}
|
|
173936
174001
|
}
|
|
@@ -175694,7 +175759,11 @@ class RealityTreeReference extends RealityModelTileTree.Reference {
|
|
|
175694
175759
|
if (-1 === key.indexOf("#")) // Avoid internal cesium
|
|
175695
175760
|
strings.push(`${key}: ${JSON.stringify(batch[key])}`);
|
|
175696
175761
|
const div = document.createElement("div");
|
|
175697
|
-
|
|
175762
|
+
strings.forEach((str, index) => {
|
|
175763
|
+
if (index > 0)
|
|
175764
|
+
div.appendChild(document.createElement("br"));
|
|
175765
|
+
div.appendChild(document.createTextNode(str));
|
|
175766
|
+
});
|
|
175698
175767
|
return div;
|
|
175699
175768
|
}
|
|
175700
175769
|
/** @deprecated in 5.0 - might be removed in next major version. Use [addAttributions] instead. */
|
|
@@ -176882,7 +176951,21 @@ class ArcGisUtilities {
|
|
|
176882
176951
|
*/
|
|
176883
176952
|
static async validateSource(args) {
|
|
176884
176953
|
const { source, ignoreCache, capabilitiesFilter } = args;
|
|
176885
|
-
|
|
176954
|
+
let metadata;
|
|
176955
|
+
try {
|
|
176956
|
+
metadata = await this.getServiceJson({ url: source.url, formatId: source.formatId, userName: source.userName, password: source.password, queryParams: source.collectQueryParams(), ignoreCache });
|
|
176957
|
+
}
|
|
176958
|
+
catch (err) {
|
|
176959
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError) {
|
|
176960
|
+
let blockedOrigin;
|
|
176961
|
+
try {
|
|
176962
|
+
blockedOrigin = new URL(err.url).origin;
|
|
176963
|
+
}
|
|
176964
|
+
catch { /* non-hierarchical URL */ }
|
|
176965
|
+
return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
176966
|
+
}
|
|
176967
|
+
throw err;
|
|
176968
|
+
}
|
|
176886
176969
|
const json = metadata?.content;
|
|
176887
176970
|
if (json === undefined) {
|
|
176888
176971
|
return { status: _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerSourceStatus.InvalidUrl };
|
|
@@ -176945,6 +177028,9 @@ class ArcGisUtilities {
|
|
|
176945
177028
|
* @param password Password to use for legacy token based security
|
|
176946
177029
|
* @param ignoreCache Flag to skip cache lookup (i.e. force a new server request)
|
|
176947
177030
|
* @param requireToken Flag to indicate if a token is required
|
|
177031
|
+
* @throws [[MapLayerUntrustedOriginError]] if an NTLM/Negotiate challenge could not be answered because
|
|
177032
|
+
* the URL's origin is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]);
|
|
177033
|
+
* all other errors are caught and reported by returning `undefined`.
|
|
176948
177034
|
*/
|
|
176949
177035
|
static async getServiceJson(args) {
|
|
176950
177036
|
const { url, formatId, userName, password, queryParams, ignoreCache, requireToken } = args;
|
|
@@ -176980,8 +177066,17 @@ class ArcGisUtilities {
|
|
|
176980
177066
|
}
|
|
176981
177067
|
let response = await fetch(tmpUrl, { method: "GET" });
|
|
176982
177068
|
if (response.status === 401 && !requireToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
176983
|
-
//
|
|
176984
|
-
|
|
177069
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
177070
|
+
const challengedUrl = response.url || tmpUrl.toString();
|
|
177071
|
+
if (!_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
|
|
177072
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError(challengedUrl);
|
|
177073
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
|
|
177074
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
|
|
177075
|
+
response = await fetch(challengedUrl, {
|
|
177076
|
+
method: "GET",
|
|
177077
|
+
credentials: "include",
|
|
177078
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_2__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
177079
|
+
});
|
|
176985
177080
|
}
|
|
176986
177081
|
// Append security token when corresponding error code is returned by ArcGIS service
|
|
176987
177082
|
let errorCode = await ArcGisUtilities.checkForResponseErrorCode(response);
|
|
@@ -177003,8 +177098,10 @@ class ArcGisUtilities {
|
|
|
177003
177098
|
ArcGisUtilities._serviceCache.set(url, (errorCode === undefined ? info : undefined));
|
|
177004
177099
|
return info; // Always return json, even though it contains an error code.
|
|
177005
177100
|
}
|
|
177006
|
-
catch {
|
|
177101
|
+
catch (err) {
|
|
177007
177102
|
ArcGisUtilities._serviceCache.set(url, undefined);
|
|
177103
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_1__.MapLayerUntrustedOriginError)
|
|
177104
|
+
throw err; // propagate so callers can report the blocked origin
|
|
177008
177105
|
return undefined;
|
|
177009
177106
|
}
|
|
177010
177107
|
}
|
|
@@ -177166,7 +177263,9 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
|
|
|
177166
177263
|
try {
|
|
177167
177264
|
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
177265
|
}
|
|
177169
|
-
catch {
|
|
177266
|
+
catch (err) {
|
|
177267
|
+
if (err instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError)
|
|
177268
|
+
this.reportBlockedOrigin(err.url);
|
|
177170
177269
|
}
|
|
177171
177270
|
if (metadata && metadata.accessTokenRequired) {
|
|
177172
177271
|
const accessClient = _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.getAccessClient(this._settings.formatId);
|
|
@@ -177214,12 +177313,32 @@ class ArcGISImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE_0__.
|
|
|
177214
177313
|
await this._firstRequestPromise;
|
|
177215
177314
|
let response;
|
|
177216
177315
|
try {
|
|
177217
|
-
|
|
177316
|
+
const requestUrl = urlObj.toString();
|
|
177317
|
+
const includeCredentials = this.includeUserCredentials(requestUrl);
|
|
177318
|
+
response = await fetch(urlObj, {
|
|
177319
|
+
...options,
|
|
177320
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
177321
|
+
redirect: includeCredentials ? this.credentialedRedirect : options?.redirect,
|
|
177322
|
+
});
|
|
177323
|
+
if (includeCredentials)
|
|
177324
|
+
this.checkCredentialedRedirect(requestUrl, response);
|
|
177218
177325
|
if (response.status === 401 && !this._lastAccessToken && (0,_request_utils__WEBPACK_IMPORTED_MODULE_3__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
177219
|
-
//
|
|
177220
|
-
|
|
177221
|
-
if (
|
|
177222
|
-
|
|
177326
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
177327
|
+
const challengedUrl = response.url || requestUrl;
|
|
177328
|
+
if (this.isSsoAllowed(challengedUrl)) {
|
|
177329
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication).
|
|
177330
|
+
this.logUntrustedOriginUse(challengedUrl);
|
|
177331
|
+
response = await fetch(challengedUrl, {
|
|
177332
|
+
...options,
|
|
177333
|
+
credentials: "include",
|
|
177334
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
177335
|
+
});
|
|
177336
|
+
if (response.status === 200) {
|
|
177337
|
+
this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
|
|
177338
|
+
}
|
|
177339
|
+
}
|
|
177340
|
+
else {
|
|
177341
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
177223
177342
|
}
|
|
177224
177343
|
}
|
|
177225
177344
|
if ((this._lastAccessToken && response.status === 400)
|
|
@@ -177432,8 +177551,12 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
177432
177551
|
}
|
|
177433
177552
|
async initialize() {
|
|
177434
177553
|
const metadata = await this.getServiceJson();
|
|
177435
|
-
if (metadata?.content === undefined)
|
|
177554
|
+
if (metadata?.content === undefined) {
|
|
177555
|
+
// By returning (i.e., not throwing), we ensure the tile tree gets created and the current provider is preserved to report status.
|
|
177556
|
+
if (this.status === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.UntrustedOrigin)
|
|
177557
|
+
return;
|
|
177436
177558
|
throw new _itwin_core_common__WEBPACK_IMPORTED_MODULE_0__.ServerError(_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_5__.IModelStatus.ValidationFailed, "");
|
|
177559
|
+
}
|
|
177437
177560
|
const json = metadata.content;
|
|
177438
177561
|
if (json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.TokenRequired
|
|
177439
177562
|
|| json?.error?.code === _tile_internal__WEBPACK_IMPORTED_MODULE_2__.ArcGisErrorCode.InvalidToken
|
|
@@ -177518,7 +177641,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
177518
177641
|
addLogoCards(cards) {
|
|
177519
177642
|
if (!cards.dataset.arcGisLogoCard) {
|
|
177520
177643
|
cards.dataset.arcGisLogoCard = "true";
|
|
177521
|
-
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS",
|
|
177644
|
+
cards.appendChild(_IModelApp__WEBPACK_IMPORTED_MODULE_1__.IModelApp.makeLogoCard({ heading: "ArcGIS", noticeLines: [this._copyrightText] }));
|
|
177522
177645
|
}
|
|
177523
177646
|
}
|
|
177524
177647
|
async addAttributions(cards, _vp) {
|
|
@@ -177559,7 +177682,7 @@ class ArcGISMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MOD
|
|
|
177559
177682
|
if (json && Array.isArray(json.results)) {
|
|
177560
177683
|
for (const result of json.results) {
|
|
177561
177684
|
if (result.attributes !== undefined && result.attributes[result.displayFieldName] !== undefined) {
|
|
177562
|
-
const thisString = `${result.displayFieldName}: ${result.attributes[result.displayFieldName]}`;
|
|
177685
|
+
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
177686
|
if (!stringSet.has(thisString)) {
|
|
177564
177687
|
strings.push(thisString);
|
|
177565
177688
|
stringSet.add(thisString);
|
|
@@ -177875,13 +177998,7 @@ class BingMapsImageryLayerProvider extends _tile_internal__WEBPACK_IMPORTED_MODU
|
|
|
177875
177998
|
const copyrights = [];
|
|
177876
177999
|
for (const match of matchingAttributions)
|
|
177877
178000
|
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 }));
|
|
178001
|
+
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
178002
|
}
|
|
177886
178003
|
async addAttributions(cards, vp) {
|
|
177887
178004
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
@@ -178490,7 +178607,10 @@ class WmsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODULE
|
|
|
178490
178607
|
// Don't throw error if unauthorized status:
|
|
178491
178608
|
// We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
|
|
178492
178609
|
// When credentials will be provided, a new provider will be created, and initialization should be fine.
|
|
178493
|
-
if (error
|
|
178610
|
+
if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError) {
|
|
178611
|
+
this.reportBlockedOrigin(error.url);
|
|
178612
|
+
}
|
|
178613
|
+
else if (error?.status === 401) {
|
|
178494
178614
|
this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerImageryProviderStatus.RequireAuth);
|
|
178495
178615
|
}
|
|
178496
178616
|
else {
|
|
@@ -178652,7 +178772,8 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
|
|
|
178652
178772
|
}
|
|
178653
178773
|
async initialize() {
|
|
178654
178774
|
try {
|
|
178655
|
-
this.
|
|
178775
|
+
const credentials = (this._settings.userName && this._settings.password ? { user: this._settings.userName, password: this._settings.password } : undefined);
|
|
178776
|
+
this._capabilities = await _tile_internal__WEBPACK_IMPORTED_MODULE_2__.WmtsCapabilities.create(this._baseUrl, credentials);
|
|
178656
178777
|
this.initPreferredTileMatrixSet();
|
|
178657
178778
|
this.initPreferredStyle();
|
|
178658
178779
|
this.initDisplayedLayer();
|
|
@@ -178665,7 +178786,10 @@ class WmtsMapLayerImageryProvider extends _tile_internal__WEBPACK_IMPORTED_MODUL
|
|
|
178665
178786
|
// Don't throw error if unauthorized status:
|
|
178666
178787
|
// We want the tile tree to be created, so that end-user can get feedback on which layer is missing credentials.
|
|
178667
178788
|
// When credentials will be provided, a new provider will be created, and initialization should be fine.
|
|
178668
|
-
if (error
|
|
178789
|
+
if (error instanceof _tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerUntrustedOriginError) {
|
|
178790
|
+
this.reportBlockedOrigin(error.url);
|
|
178791
|
+
}
|
|
178792
|
+
else if (error?.status === 401) {
|
|
178669
178793
|
this.setStatus(_tile_internal__WEBPACK_IMPORTED_MODULE_2__.MapLayerImageryProviderStatus.RequireAuth);
|
|
178670
178794
|
}
|
|
178671
178795
|
else {
|
|
@@ -179476,14 +179600,18 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
179476
179600
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
179477
179601
|
/* harmony export */ WmsUtilities: () => (/* binding */ WmsUtilities)
|
|
179478
179602
|
/* harmony export */ });
|
|
179479
|
-
/* harmony import */ var
|
|
179480
|
-
/* harmony import */ var
|
|
179603
|
+
/* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
|
|
179604
|
+
/* harmony import */ var _request_Request__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../request/Request */ "../../core/frontend/lib/esm/request/Request.js");
|
|
179605
|
+
/* harmony import */ var _request_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../request/utils */ "../../core/frontend/lib/esm/request/utils.js");
|
|
179606
|
+
/* harmony import */ var _tile_internal__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../../tile/internal */ "../../core/frontend/lib/esm/tile/internal.js");
|
|
179481
179607
|
/*---------------------------------------------------------------------------------------------
|
|
179482
179608
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
179483
179609
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
179484
179610
|
*--------------------------------------------------------------------------------------------*/
|
|
179485
179611
|
|
|
179486
179612
|
|
|
179613
|
+
|
|
179614
|
+
|
|
179487
179615
|
/** @packageDocumentation
|
|
179488
179616
|
* @module Tiles
|
|
179489
179617
|
*/
|
|
@@ -179500,16 +179628,35 @@ class WmsUtilities {
|
|
|
179500
179628
|
static async fetchXml(url, credentials) {
|
|
179501
179629
|
let headers;
|
|
179502
179630
|
if (credentials && credentials.user && credentials.password) {
|
|
179503
|
-
|
|
179504
|
-
|
|
179631
|
+
// Basic credentials are considered settings-derived credentials for this source. When the registry is
|
|
179632
|
+
// enforcing trusted origins, the source URL itself is the only implicitly trusted origin for basic auth;
|
|
179633
|
+
// opaque/custom-protocol URLs have no network origin and must therefore be treated as untrusted.
|
|
179634
|
+
const allowBasicAuth = !_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins
|
|
179635
|
+
|| _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, url);
|
|
179636
|
+
if (allowBasicAuth) {
|
|
179637
|
+
headers = new Headers();
|
|
179638
|
+
(0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.setBasicAuthorization)(headers, credentials);
|
|
179639
|
+
}
|
|
179505
179640
|
}
|
|
179506
179641
|
let response = await fetch(url, { method: "GET", headers });
|
|
179507
|
-
if (!credentials && response.status === 401
|
|
179508
|
-
|
|
179509
|
-
|
|
179642
|
+
if (!headers && credentials && credentials.user && credentials.password && (response.status === 401 || response.status === 403)) {
|
|
179643
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(url);
|
|
179644
|
+
}
|
|
179645
|
+
if (!credentials && response.status === 401 && (0,_request_utils__WEBPACK_IMPORTED_MODULE_2__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])) {
|
|
179646
|
+
// fetch follows redirects transparently, so trust decisions target the final (post-redirect) URL.
|
|
179647
|
+
const challengedUrl = response.url || url;
|
|
179648
|
+
if (!_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(challengedUrl))
|
|
179649
|
+
throw new _tile_internal__WEBPACK_IMPORTED_MODULE_3__.MapLayerUntrustedOriginError(challengedUrl);
|
|
179650
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(challengedUrl);
|
|
179651
|
+
// We got a http 401 challenge, lets try SSO (i.e. Windows Authentication).
|
|
179652
|
+
response = await fetch(challengedUrl, {
|
|
179653
|
+
method: "GET",
|
|
179654
|
+
credentials: "include",
|
|
179655
|
+
redirect: _IModelApp__WEBPACK_IMPORTED_MODULE_0__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined,
|
|
179656
|
+
});
|
|
179510
179657
|
}
|
|
179511
179658
|
if (response.status !== 200)
|
|
179512
|
-
throw new
|
|
179659
|
+
throw new _request_Request__WEBPACK_IMPORTED_MODULE_1__.HttpResponseError(response.status, await response.text());
|
|
179513
179660
|
return response.text();
|
|
179514
179661
|
}
|
|
179515
179662
|
}
|
|
@@ -191923,6 +192070,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
191923
192070
|
/* harmony export */ MapLayerSourceStatus: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSourceStatus),
|
|
191924
192071
|
/* harmony export */ MapLayerSources: () => (/* reexport safe */ _map_MapLayerSources__WEBPACK_IMPORTED_MODULE_86__.MapLayerSources),
|
|
191925
192072
|
/* harmony export */ MapLayerTileTreeReference: () => (/* reexport safe */ _map_MapLayerTileTreeReference__WEBPACK_IMPORTED_MODULE_64__.MapLayerTileTreeReference),
|
|
192073
|
+
/* harmony export */ MapLayerUntrustedOriginError: () => (/* reexport safe */ _map_MapLayerFormatRegistry__WEBPACK_IMPORTED_MODULE_42__.MapLayerUntrustedOriginError),
|
|
191926
192074
|
/* harmony export */ MapTile: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTile),
|
|
191927
192075
|
/* harmony export */ MapTileLoader: () => (/* reexport safe */ _internal_tile_map_MapTileLoader__WEBPACK_IMPORTED_MODULE_72__.MapTileLoader),
|
|
191928
192076
|
/* harmony export */ MapTileProjection: () => (/* reexport safe */ _map_MapTile__WEBPACK_IMPORTED_MODULE_70__.MapTileProjection),
|
|
@@ -192002,6 +192150,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
192002
192150
|
/* harmony export */ collectMaskRefs: () => (/* reexport safe */ _internal_tile_PrimaryTileTree__WEBPACK_IMPORTED_MODULE_82__.collectMaskRefs),
|
|
192003
192151
|
/* harmony export */ compareMapLayer: () => (/* reexport safe */ _internal_render_webgl_MapLayerParams__WEBPACK_IMPORTED_MODULE_94__.compareMapLayer),
|
|
192004
192152
|
/* harmony export */ computeCesiumTokenTimeoutInterval: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.computeCesiumTokenTimeoutInterval),
|
|
192153
|
+
/* harmony export */ computeOrthometricVerticalShift: () => (/* reexport safe */ _internal_tile_OrbitGtTileTree__WEBPACK_IMPORTED_MODULE_84__.computeOrthometricVerticalShift),
|
|
192005
192154
|
/* harmony export */ createClassifierTileTreeReference: () => (/* reexport safe */ _internal_tile_ClassifierTileTree__WEBPACK_IMPORTED_MODULE_83__.createClassifierTileTreeReference),
|
|
192006
192155
|
/* harmony export */ createDefaultViewFlagOverrides: () => (/* reexport safe */ _internal_tile_ViewFlagOverrides__WEBPACK_IMPORTED_MODULE_0__.createDefaultViewFlagOverrides),
|
|
192007
192156
|
/* harmony export */ createGraphicFromDescription: () => (/* reexport safe */ _internal_tile_ImdlGraphicsCreator__WEBPACK_IMPORTED_MODULE_37__.createGraphicFromDescription),
|
|
@@ -192018,6 +192167,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
192018
192167
|
/* harmony export */ decodeMeshoptBuffer: () => (/* reexport safe */ _internal_tile_MeshoptCompression__WEBPACK_IMPORTED_MODULE_93__.decodeMeshoptBuffer),
|
|
192019
192168
|
/* harmony export */ deflateCoordinates: () => (/* reexport safe */ _internal_tile_map_ImageryProviders_CoordinatesUtils__WEBPACK_IMPORTED_MODULE_47__.deflateCoordinates),
|
|
192020
192169
|
/* harmony export */ disposeTileTreesForGeometricModels: () => (/* reexport safe */ _internal_tile_PrimaryTileTree__WEBPACK_IMPORTED_MODULE_82__.disposeTileTreesForGeometricModels),
|
|
192170
|
+
/* harmony export */ escapeHtml: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.escapeHtml),
|
|
192021
192171
|
/* harmony export */ getCesiumAccessClient: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessClient),
|
|
192022
192172
|
/* harmony export */ getCesiumAccessTokenAndEndpointUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAccessTokenAndEndpointUrl),
|
|
192023
192173
|
/* harmony export */ getCesiumAssetUrl: () => (/* reexport safe */ _map_CesiumTerrainProvider__WEBPACK_IMPORTED_MODULE_68__.getCesiumAssetUrl),
|
|
@@ -192037,7 +192187,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
192037
192187
|
/* harmony export */ readImdlContent: () => (/* reexport safe */ _ImdlReader__WEBPACK_IMPORTED_MODULE_35__.readImdlContent),
|
|
192038
192188
|
/* harmony export */ readPntsColors: () => (/* reexport safe */ _internal_tile_PntsReader__WEBPACK_IMPORTED_MODULE_76__.readPntsColors),
|
|
192039
192189
|
/* 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)
|
|
192190
|
+
/* harmony export */ tileTreeReferenceFromRenderGraphic: () => (/* reexport safe */ _RenderGraphicTileTree__WEBPACK_IMPORTED_MODULE_78__.tileTreeReferenceFromRenderGraphic),
|
|
192191
|
+
/* harmony export */ tryGetOrigin: () => (/* reexport safe */ _map_MapLayerImageryProvider__WEBPACK_IMPORTED_MODULE_49__.tryGetOrigin)
|
|
192041
192192
|
/* harmony export */ });
|
|
192042
192193
|
/* harmony import */ var _internal_tile_ViewFlagOverrides__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../internal/tile/ViewFlagOverrides */ "../../core/frontend/lib/esm/internal/tile/ViewFlagOverrides.js");
|
|
192043
192194
|
/* harmony import */ var _map_MapCartoRectangle__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./map/MapCartoRectangle */ "../../core/frontend/lib/esm/tile/map/MapCartoRectangle.js");
|
|
@@ -193736,7 +193887,8 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
193736
193887
|
__webpack_require__.r(__webpack_exports__);
|
|
193737
193888
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
193738
193889
|
/* harmony export */ MapLayerFormat: () => (/* binding */ MapLayerFormat),
|
|
193739
|
-
/* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry)
|
|
193890
|
+
/* harmony export */ MapLayerFormatRegistry: () => (/* binding */ MapLayerFormatRegistry),
|
|
193891
|
+
/* harmony export */ MapLayerUntrustedOriginError: () => (/* binding */ MapLayerUntrustedOriginError)
|
|
193740
193892
|
/* harmony export */ });
|
|
193741
193893
|
/* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
|
|
193742
193894
|
/* harmony import */ var _IModelApp__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../IModelApp */ "../../core/frontend/lib/esm/IModelApp.js");
|
|
@@ -193751,7 +193903,7 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
193751
193903
|
|
|
193752
193904
|
|
|
193753
193905
|
|
|
193754
|
-
const loggerCategory = "
|
|
193906
|
+
const loggerCategory = "MapLayerFormatRegistry";
|
|
193755
193907
|
/**
|
|
193756
193908
|
* Class representing a map-layer format.
|
|
193757
193909
|
* Each format has it's unique 'formatId' string, used to uniquely identify a format in the [[MapLayerFormatRegistry]].
|
|
@@ -193800,16 +193952,127 @@ class MapLayerFormat {
|
|
|
193800
193952
|
return undefined;
|
|
193801
193953
|
}
|
|
193802
193954
|
}
|
|
193955
|
+
/** Error thrown when an NTLM or Negotiate http 401 challenge could not be answered because the request
|
|
193956
|
+
* URL's origin is not listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]]
|
|
193957
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
193958
|
+
* Thrown by the static map-layer utilities (e.g. capabilities / service-metadata fetches) that have no
|
|
193959
|
+
* provider instance on which to report the blocked origin; callers convert it to
|
|
193960
|
+
* [[MapLayerImageryProviderStatus.UntrustedOrigin]] (provider initialization) or
|
|
193961
|
+
* [[MapLayerSourceStatus.UntrustedOrigin]] (source validation).
|
|
193962
|
+
* @internal
|
|
193963
|
+
*/
|
|
193964
|
+
class MapLayerUntrustedOriginError extends Error {
|
|
193965
|
+
/** The URL of the request whose authentication challenge was left unanswered. */
|
|
193966
|
+
url;
|
|
193967
|
+
constructor(url) {
|
|
193968
|
+
super(`Authentication blocked: origin of '${url}' is not listed in MapLayerFormatRegistry.trustedCredentialsOrigins`);
|
|
193969
|
+
this.url = url;
|
|
193970
|
+
}
|
|
193971
|
+
}
|
|
193803
193972
|
/**
|
|
193804
193973
|
* A registry of MapLayerFormats identified by their unique format IDs. The registry can be accessed via [[IModelApp.mapLayerFormatRegistry]].
|
|
193805
193974
|
* @public
|
|
193806
193975
|
*/
|
|
193807
193976
|
class MapLayerFormatRegistry {
|
|
193808
193977
|
_configOptions;
|
|
193978
|
+
_trustedCredentialsOrigins = [];
|
|
193979
|
+
/** Opt-in enforcement of origin restrictions on map-layer credentials.
|
|
193980
|
+
* When enabled, map layer providers:
|
|
193981
|
+
* - attach the basic-auth credentials stored in the layer settings only to requests targeting the origin
|
|
193982
|
+
* of the layer's settings URL or an origin listed in [[trustedCredentialsOrigins]];
|
|
193983
|
+
* - retry a request with browser credentials included (i.e. SSO / Windows Authentication) after an NTLM
|
|
193984
|
+
* or Negotiate http 401 challenge only for origins explicitly listed in [[trustedCredentialsOrigins]]
|
|
193985
|
+
* (the settings-URL origin is NOT implicitly trusted for SSO, since map-layer URLs may originate from
|
|
193986
|
+
* untrusted user input while SSO shares the user's ambient identity).
|
|
193987
|
+
* Default is false, preserving the legacy behavior of sending credentials to any request URL.
|
|
193988
|
+
* @beta
|
|
193989
|
+
*/
|
|
193990
|
+
restrictCredentialsToTrustedOrigins = false;
|
|
193809
193991
|
constructor(opts) {
|
|
193810
193992
|
this._configOptions = opts ?? {};
|
|
193811
193993
|
_internal__WEBPACK_IMPORTED_MODULE_2__.internalMapLayerImageryFormats.forEach((format) => this.register(format));
|
|
193812
193994
|
}
|
|
193995
|
+
/** Origins (e.g. "https://tiles.example.com") to which map layer providers may send credentials —
|
|
193996
|
+
* both the basic-auth credentials stored in the layer settings and browser credentials for
|
|
193997
|
+
* SSO (i.e. Windows Authentication) retries after an NTLM or Negotiate http 401 challenge.
|
|
193998
|
+
* Only enforced when [[restrictCredentialsToTrustedOrigins]] is enabled.
|
|
193999
|
+
* For basic-auth, the origin of each map layer's settings URL is always implicitly trusted; for SSO,
|
|
194000
|
+
* origins must be explicitly listed here.
|
|
194001
|
+
* Entries are normalized to their origin (scheme + host + port); only `http:` and `https:` URLs are accepted,
|
|
194002
|
+
* and any other entry is ignored and logged. Opaque schemes such as `file:`, `data:`, `about:` and custom
|
|
194003
|
+
* Electron protocols are rejected because they all share the same serialized origin, so trusting one would
|
|
194004
|
+
* trust every other.
|
|
194005
|
+
* @beta
|
|
194006
|
+
*/
|
|
194007
|
+
get trustedCredentialsOrigins() {
|
|
194008
|
+
return this._trustedCredentialsOrigins;
|
|
194009
|
+
}
|
|
194010
|
+
set trustedCredentialsOrigins(origins) {
|
|
194011
|
+
const normalized = [];
|
|
194012
|
+
for (const entry of origins) {
|
|
194013
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(entry);
|
|
194014
|
+
if (origin !== undefined)
|
|
194015
|
+
normalized.push(origin);
|
|
194016
|
+
else
|
|
194017
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `trustedCredentialsOrigins: ignoring '${entry}'; entries must be http or https URLs.`);
|
|
194018
|
+
}
|
|
194019
|
+
this._trustedCredentialsOrigins = normalized;
|
|
194020
|
+
}
|
|
194021
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
194022
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
194023
|
+
* Always true unless [[restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
194024
|
+
* When enabled, the URL's origin must be explicitly listed in [[trustedCredentialsOrigins]];
|
|
194025
|
+
* unlike basic-auth, the settings-URL origin is NOT implicitly trusted because SSO shares the user's
|
|
194026
|
+
* ambient identity, and map-layer URLs may originate from untrusted user input.
|
|
194027
|
+
* @internal
|
|
194028
|
+
*/
|
|
194029
|
+
isSsoAllowed(url) {
|
|
194030
|
+
if (!this.restrictCredentialsToTrustedOrigins)
|
|
194031
|
+
return true;
|
|
194032
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
|
|
194033
|
+
// Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
|
|
194034
|
+
return origin !== undefined && this._trustedCredentialsOrigins.includes(origin);
|
|
194035
|
+
}
|
|
194036
|
+
/** Returns true if the basic-auth credentials belonging to a map-layer source or settings URL may be
|
|
194037
|
+
* attached to a request to the given URL. Always true unless [[restrictCredentialsToTrustedOrigins]]
|
|
194038
|
+
* is enabled (opt-in). When enabled, the origin of `settingsUrl` is implicitly trusted (the credentials
|
|
194039
|
+
* belong to that server); any other origin must be listed in [[trustedCredentialsOrigins]].
|
|
194040
|
+
* @internal
|
|
194041
|
+
*/
|
|
194042
|
+
isCredentialsSharingAllowed(url, settingsUrl) {
|
|
194043
|
+
if (!this.restrictCredentialsToTrustedOrigins)
|
|
194044
|
+
return true;
|
|
194045
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url);
|
|
194046
|
+
if (origin === undefined)
|
|
194047
|
+
return false;
|
|
194048
|
+
if (origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
|
|
194049
|
+
return true;
|
|
194050
|
+
// Entries are normalized to their origin by the [[trustedCredentialsOrigins]] setter.
|
|
194051
|
+
return this._trustedCredentialsOrigins.includes(origin);
|
|
194052
|
+
}
|
|
194053
|
+
/** Origins for which a "credentials sent to untrusted origin" warning was already logged;
|
|
194054
|
+
* used to log the discovery warning only once per origin.
|
|
194055
|
+
*/
|
|
194056
|
+
_untrustedUseLogged = new Set();
|
|
194057
|
+
/** Logs a warning (once per origin) when credentials are sent to an origin that would be blocked
|
|
194058
|
+
* if [[restrictCredentialsToTrustedOrigins]] were enabled.
|
|
194059
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
194060
|
+
* If `settingsUrl` is supplied, requests sharing its origin are not logged, since that origin is
|
|
194061
|
+
* implicitly trusted for basic-auth.
|
|
194062
|
+
* @internal
|
|
194063
|
+
*/
|
|
194064
|
+
logUntrustedOriginUse(url, settingsUrl) {
|
|
194065
|
+
if (this.restrictCredentialsToTrustedOrigins)
|
|
194066
|
+
return; // restriction active; nothing to preview
|
|
194067
|
+
const origin = (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(url) ?? url;
|
|
194068
|
+
if (settingsUrl !== undefined && origin === (0,_internal__WEBPACK_IMPORTED_MODULE_2__.tryGetOrigin)(settingsUrl))
|
|
194069
|
+
return; // implicitly trusted for basic-auth
|
|
194070
|
+
if (this._untrustedUseLogged.has(origin) || this._trustedCredentialsOrigins.includes(origin))
|
|
194071
|
+
return;
|
|
194072
|
+
this._untrustedUseLogged.add(origin);
|
|
194073
|
+
_itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.Logger.logWarning(loggerCategory, `Credentials sent to origin '${origin}' which is not in MapLayerFormatRegistry.trustedCredentialsOrigins; `
|
|
194074
|
+
+ "this request would be blocked if restrictCredentialsToTrustedOrigins were enabled.");
|
|
194075
|
+
}
|
|
193813
194076
|
_formats = new Map();
|
|
193814
194077
|
isRegistered(formatId) { return this._formats.get(formatId) !== undefined; }
|
|
193815
194078
|
register(formatClass) {
|
|
@@ -193975,6 +194238,14 @@ class WmsMapLayerFormat extends ImageryMapLayerFormat {
|
|
|
193975
194238
|
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
|
|
193976
194239
|
}
|
|
193977
194240
|
catch (err) {
|
|
194241
|
+
if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
|
|
194242
|
+
let blockedOrigin;
|
|
194243
|
+
try {
|
|
194244
|
+
blockedOrigin = new URL(err.url).origin;
|
|
194245
|
+
}
|
|
194246
|
+
catch { /* non-hierarchical URL */ }
|
|
194247
|
+
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
194248
|
+
}
|
|
193978
194249
|
let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
|
|
193979
194250
|
if (err?.status === 401) {
|
|
193980
194251
|
status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
|
|
@@ -194040,6 +194311,14 @@ class WmtsMapLayerFormat extends ImageryMapLayerFormat {
|
|
|
194040
194311
|
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.Valid, subLayers };
|
|
194041
194312
|
}
|
|
194042
194313
|
catch (err) {
|
|
194314
|
+
if (err instanceof _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerUntrustedOriginError) {
|
|
194315
|
+
let blockedOrigin;
|
|
194316
|
+
try {
|
|
194317
|
+
blockedOrigin = new URL(err.url).origin;
|
|
194318
|
+
}
|
|
194319
|
+
catch { /* non-hierarchical URL */ }
|
|
194320
|
+
return { status: _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.UntrustedOrigin, blockedOrigin };
|
|
194321
|
+
}
|
|
194043
194322
|
let status = _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidUrl;
|
|
194044
194323
|
if (err?.status === 401) {
|
|
194045
194324
|
status = ((userName && password) ? _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.InvalidCredentials : _internal__WEBPACK_IMPORTED_MODULE_0__.MapLayerSourceStatus.RequireAuth);
|
|
@@ -194104,7 +194383,9 @@ const internalMapLayerImageryFormats = [WmsMapLayerFormat, WmtsMapLayerFormat, A
|
|
|
194104
194383
|
__webpack_require__.r(__webpack_exports__);
|
|
194105
194384
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
194106
194385
|
/* harmony export */ MapLayerImageryProvider: () => (/* binding */ MapLayerImageryProvider),
|
|
194107
|
-
/* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus)
|
|
194386
|
+
/* harmony export */ MapLayerImageryProviderStatus: () => (/* binding */ MapLayerImageryProviderStatus),
|
|
194387
|
+
/* harmony export */ escapeHtml: () => (/* binding */ escapeHtml),
|
|
194388
|
+
/* harmony export */ tryGetOrigin: () => (/* binding */ tryGetOrigin)
|
|
194108
194389
|
/* harmony export */ });
|
|
194109
194390
|
/* harmony import */ var _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @itwin/core-bentley */ "../../core/bentley/lib/esm/core-bentley.js");
|
|
194110
194391
|
/* harmony import */ var _itwin_core_common__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @itwin/core-common */ "../../core/common/lib/esm/core-common.js");
|
|
@@ -194131,6 +194412,34 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
194131
194412
|
const tileImageSize = 256, untiledImageSize = 256;
|
|
194132
194413
|
const earthRadius = 6378137;
|
|
194133
194414
|
const doDebugToolTips = false;
|
|
194415
|
+
/** Escapes HTML metacharacters so the text renders literally when assigned to `innerHTML`.
|
|
194416
|
+
* Use for any server- or user-supplied string that ends up in the map tooltip, which is rendered
|
|
194417
|
+
* as HTML by [[MapLayerTileTreeReference.getToolTip]].
|
|
194418
|
+
* @internal
|
|
194419
|
+
*/
|
|
194420
|
+
function escapeHtml(text) {
|
|
194421
|
+
return text.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
194422
|
+
}
|
|
194423
|
+
/** Returns the origin (scheme + host + port) of the given URL, or undefined if it cannot be parsed or does
|
|
194424
|
+
* not denote a distinct network origin.
|
|
194425
|
+
*
|
|
194426
|
+
* Only `http:` and `https:` URLs yield an origin. Every other scheme is rejected because opaque URLs
|
|
194427
|
+
* — `file:`, `data:`, `about:`, `blob:null`, and the custom protocols Electron hosts commonly register —
|
|
194428
|
+
* all serialize to the literal string `"null"`. Comparing those would make unrelated URLs look same-origin,
|
|
194429
|
+
* so a single trusted entry could unlock all of them. Callers use this for credential-trust decisions, and
|
|
194430
|
+
* returning `undefined` keeps those decisions fail-closed.
|
|
194431
|
+
* @internal
|
|
194432
|
+
*/
|
|
194433
|
+
function tryGetOrigin(url) {
|
|
194434
|
+
let parsed;
|
|
194435
|
+
try {
|
|
194436
|
+
parsed = new URL(url);
|
|
194437
|
+
}
|
|
194438
|
+
catch {
|
|
194439
|
+
return undefined;
|
|
194440
|
+
}
|
|
194441
|
+
return (parsed.protocol === "http:" || parsed.protocol === "https:") ? parsed.origin : undefined;
|
|
194442
|
+
}
|
|
194134
194443
|
/** The status of the map layer imagery provider that lets you know if authentication is needed to request tiles.
|
|
194135
194444
|
* @public
|
|
194136
194445
|
*/
|
|
@@ -194138,6 +194447,12 @@ var MapLayerImageryProviderStatus;
|
|
|
194138
194447
|
(function (MapLayerImageryProviderStatus) {
|
|
194139
194448
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["Valid"] = 0] = "Valid";
|
|
194140
194449
|
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["RequireAuth"] = 1] = "RequireAuth";
|
|
194450
|
+
/** A request received an authentication challenge, but credentials were withheld because the request origin
|
|
194451
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
194452
|
+
* The blocked origins are available via [[MapLayerImageryProvider.blockedOrigins]].
|
|
194453
|
+
* @beta
|
|
194454
|
+
*/
|
|
194455
|
+
MapLayerImageryProviderStatus[MapLayerImageryProviderStatus["UntrustedOrigin"] = 2] = "UntrustedOrigin";
|
|
194141
194456
|
})(MapLayerImageryProviderStatus || (MapLayerImageryProviderStatus = {}));
|
|
194142
194457
|
/** Abstract class for map layer imagery providers.
|
|
194143
194458
|
* 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 +194470,41 @@ class MapLayerImageryProvider {
|
|
|
194155
194470
|
/** @internal */
|
|
194156
194471
|
_status = MapLayerImageryProviderStatus.Valid;
|
|
194157
194472
|
/** @internal */
|
|
194158
|
-
|
|
194473
|
+
_blockedOrigins = new Set();
|
|
194474
|
+
/** Origins of requests for which credentials were withheld because they are not trusted
|
|
194475
|
+
* (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
194476
|
+
* Populated when [[status]] transitions to [[MapLayerImageryProviderStatus.UntrustedOrigin]];
|
|
194477
|
+
* [[onStatusChanged]] is raised again each time a new origin is added. Cleared by [[resetStatus]].
|
|
194478
|
+
* @beta
|
|
194479
|
+
*/
|
|
194480
|
+
get blockedOrigins() { return [...this._blockedOrigins]; }
|
|
194481
|
+
/** Origins for which a previous SSO handshake (i.e. Windows Authentication) succeeded.
|
|
194482
|
+
* Browser credentials are only included for subsequent requests targeting these origins,
|
|
194483
|
+
* so that a successful handshake with one host does not leak credentials to other hosts
|
|
194484
|
+
* this provider may contact.
|
|
194485
|
+
* @internal
|
|
194486
|
+
*/
|
|
194487
|
+
_ssoSucceededOrigins = new Set();
|
|
194488
|
+
/** Returns true if browser credentials should be included for the given URL because a previous
|
|
194489
|
+
* SSO handshake succeeded for its origin AND the origin is still allowed by the current policy
|
|
194490
|
+
* (see [[MapLayerFormatRegistry.isSsoAllowed]]). Re-checking the policy ensures a handshake recorded
|
|
194491
|
+
* while enforcement was disabled — or before an origin was removed from
|
|
194492
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]] — does not keep latching credentials on.
|
|
194493
|
+
* @internal
|
|
194494
|
+
*/
|
|
194495
|
+
includeUserCredentials(url) {
|
|
194496
|
+
const origin = tryGetOrigin(url);
|
|
194497
|
+
return origin !== undefined && this._ssoSucceededOrigins.has(origin) && this.isSsoAllowed(url);
|
|
194498
|
+
}
|
|
194499
|
+
/** Records that an SSO handshake succeeded for the given URL's origin, so subsequent requests
|
|
194500
|
+
* to that origin include browser credentials without going through another 401 challenge.
|
|
194501
|
+
* @internal
|
|
194502
|
+
*/
|
|
194503
|
+
recordSsoSucceeded(url) {
|
|
194504
|
+
const origin = tryGetOrigin(url);
|
|
194505
|
+
if (origin !== undefined)
|
|
194506
|
+
this._ssoSucceededOrigins.add(origin);
|
|
194507
|
+
}
|
|
194159
194508
|
/** @internal */
|
|
194160
194509
|
onFirstRequestCompleted = new _itwin_core_bentley__WEBPACK_IMPORTED_MODULE_0__.BeEvent();
|
|
194161
194510
|
/** @internal */
|
|
@@ -194171,7 +194520,17 @@ class MapLayerImageryProvider {
|
|
|
194171
194520
|
* @public
|
|
194172
194521
|
*/
|
|
194173
194522
|
get supportsMapFeatureInfo() { return false; }
|
|
194174
|
-
|
|
194523
|
+
/** Reset the provider's status to [[MapLayerImageryProviderStatus.Valid]] and clear the list of
|
|
194524
|
+
* [[blockedOrigins]] accumulated while in the [[MapLayerImageryProviderStatus.UntrustedOrigin]] state.
|
|
194525
|
+
* Raises [[onStatusChanged]] if the status actually changes.
|
|
194526
|
+
* Typically called after the user has provided credentials or the application has updated
|
|
194527
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]], so that subsequent requests are re-attempted.
|
|
194528
|
+
* @beta
|
|
194529
|
+
*/
|
|
194530
|
+
resetStatus() {
|
|
194531
|
+
this._blockedOrigins.clear();
|
|
194532
|
+
this.setStatus(MapLayerImageryProviderStatus.Valid);
|
|
194533
|
+
}
|
|
194175
194534
|
/** @internal */
|
|
194176
194535
|
get tileSize() { return this._usesCachedTiles ? tileImageSize : untiledImageSize; }
|
|
194177
194536
|
/** @internal */
|
|
@@ -194345,6 +194704,32 @@ class MapLayerImageryProvider {
|
|
|
194345
194704
|
(0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setBasicAuthorization)(headers, this._settings.userName, this._settings.password);
|
|
194346
194705
|
}
|
|
194347
194706
|
}
|
|
194707
|
+
/** Returns true if the given URL has the same origin as this layer's settings URL.
|
|
194708
|
+
* Used to avoid leaking credentials to third-party hosts.
|
|
194709
|
+
* @internal
|
|
194710
|
+
*/
|
|
194711
|
+
matchesSettingsUrlOrigin(url) {
|
|
194712
|
+
const origin = tryGetOrigin(url);
|
|
194713
|
+
return origin !== undefined && origin === tryGetOrigin(this._settings.url);
|
|
194714
|
+
}
|
|
194715
|
+
/** Returns true if the basic-auth credentials from the layer settings may be attached to a request to the given URL.
|
|
194716
|
+
* Always true unless [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled (opt-in).
|
|
194717
|
+
* When enabled, the origin of this layer's settings URL is implicitly trusted (the credentials belong to that
|
|
194718
|
+
* server); other origins must be listed in [[MapLayerFormatRegistry.trustedCredentialsOrigins]].
|
|
194719
|
+
* See [[MapLayerFormatRegistry.isCredentialsSharingAllowed]].
|
|
194720
|
+
* @internal
|
|
194721
|
+
*/
|
|
194722
|
+
isCredentialsSharingAllowed(url) {
|
|
194723
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isCredentialsSharingAllowed(url, this._settings.url);
|
|
194724
|
+
}
|
|
194725
|
+
/** Returns true if a request to the given URL may be retried with browser credentials included
|
|
194726
|
+
* (i.e. SSO / Windows Authentication) after an NTLM or Negotiate http 401 challenge.
|
|
194727
|
+
* See [[MapLayerFormatRegistry.isSsoAllowed]].
|
|
194728
|
+
* @internal
|
|
194729
|
+
*/
|
|
194730
|
+
isSsoAllowed(url) {
|
|
194731
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.isSsoAllowed(url);
|
|
194732
|
+
}
|
|
194348
194733
|
/** @internal */
|
|
194349
194734
|
async makeTileRequest(url, timeoutMs, authorization) {
|
|
194350
194735
|
// We want to complete the first request before letting other requests go;
|
|
@@ -194364,40 +194749,132 @@ class MapLayerImageryProvider {
|
|
|
194364
194749
|
throw new Error("fetch call failed");
|
|
194365
194750
|
return response;
|
|
194366
194751
|
}
|
|
194752
|
+
/** Records the given URL's origin and transitions the status to [[MapLayerImageryProviderStatus.UntrustedOrigin]].
|
|
194753
|
+
* Called when a request received an authentication challenge that could not be answered because the origin
|
|
194754
|
+
* is not trusted (see [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]]).
|
|
194755
|
+
* Raises [[onStatusChanged]] on the status transition, and again whenever a new origin is added.
|
|
194756
|
+
* @internal
|
|
194757
|
+
*/
|
|
194758
|
+
reportBlockedOrigin(url) {
|
|
194759
|
+
const origin = tryGetOrigin(url) ?? url;
|
|
194760
|
+
const isNewOrigin = !this._blockedOrigins.has(origin);
|
|
194761
|
+
this._blockedOrigins.add(origin);
|
|
194762
|
+
if (this._status !== MapLayerImageryProviderStatus.UntrustedOrigin)
|
|
194763
|
+
this.setStatus(MapLayerImageryProviderStatus.UntrustedOrigin);
|
|
194764
|
+
else if (isNewOrigin)
|
|
194765
|
+
this.onStatusChanged.raiseEvent(this); // status unchanged, but a new origin was blocked
|
|
194766
|
+
}
|
|
194767
|
+
/** Logs a warning (once per origin, app-wide) when credentials are sent to an origin that would be blocked
|
|
194768
|
+
* if [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] were enabled.
|
|
194769
|
+
* Helps applications discover the origins they need to whitelist before opting in to the restriction.
|
|
194770
|
+
* See [[MapLayerFormatRegistry.logUntrustedOriginUse]].
|
|
194771
|
+
* @internal
|
|
194772
|
+
*/
|
|
194773
|
+
logUntrustedOriginUse(url) {
|
|
194774
|
+
_IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.logUntrustedOriginUse(url);
|
|
194775
|
+
}
|
|
194776
|
+
/** The redirect policy to apply to a request that carries browser credentials (see [[includeUserCredentials]]).
|
|
194777
|
+
*
|
|
194778
|
+
* When [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is enabled, redirects are refused
|
|
194779
|
+
* outright (`"error"`). `fetch` cannot be asked to follow only same-origin redirects, and by the time a
|
|
194780
|
+
* followed redirect can be inspected the credentials have already been delivered to the destination — so
|
|
194781
|
+
* refusing is the only way to honour the guarantee that credentials reach none but the origins listed in
|
|
194782
|
+
* [[MapLayerFormatRegistry.trustedCredentialsOrigins]]. Legitimate same-origin redirects fail as a result;
|
|
194783
|
+
* that is the cost of the opt-in restriction.
|
|
194784
|
+
*
|
|
194785
|
+
* When the restriction is disabled (the default), redirects are followed as before and
|
|
194786
|
+
* [[checkCredentialedRedirect]] reports the destination after the fact.
|
|
194787
|
+
* @internal
|
|
194788
|
+
*/
|
|
194789
|
+
get credentialedRedirect() {
|
|
194790
|
+
return _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
194791
|
+
}
|
|
194792
|
+
/** Detects that a request carrying browser credentials (see [[includeUserCredentials]]) was transparently
|
|
194793
|
+
* redirected to a different origin, and reports or logs that origin.
|
|
194794
|
+
*
|
|
194795
|
+
* This is a **best-effort, after-the-fact** signal used only while
|
|
194796
|
+
* [[MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]] is disabled, where credentialed requests
|
|
194797
|
+
* still follow redirects (see [[credentialedRedirect]]). It cannot prevent the exposure — the credentials
|
|
194798
|
+
* have already been sent — and it does not fire at all when the destination denies CORS, because `fetch`
|
|
194799
|
+
* then rejects instead of returning a `Response`. The destination origin is never latched as SSO-succeeded,
|
|
194800
|
+
* so credentials do not keep flowing to it.
|
|
194801
|
+
* @internal
|
|
194802
|
+
*/
|
|
194803
|
+
checkCredentialedRedirect(requestedUrl, response) {
|
|
194804
|
+
const finalOrigin = tryGetOrigin(response.url);
|
|
194805
|
+
if (!response.url || finalOrigin === undefined || finalOrigin === tryGetOrigin(requestedUrl))
|
|
194806
|
+
return;
|
|
194807
|
+
if (!this.isSsoAllowed(response.url))
|
|
194808
|
+
this.reportBlockedOrigin(response.url);
|
|
194809
|
+
else
|
|
194810
|
+
this.logUntrustedOriginUse(response.url); // no-op when the restriction is enabled
|
|
194811
|
+
}
|
|
194367
194812
|
/** @internal */
|
|
194368
194813
|
async makeRequest(url, timeoutMs, authorization) {
|
|
194369
194814
|
let response;
|
|
194370
194815
|
let headers;
|
|
194371
194816
|
let hasCreds = false;
|
|
194817
|
+
// Whether this request had basic-auth credentials of its own to offer. Requests carrying a caller-supplied
|
|
194818
|
+
// `authorization` are excluded: those bypass the origin policy entirely.
|
|
194819
|
+
const hasSettingsCreds = !authorization && !!this._settings.userName && !!this._settings.password;
|
|
194372
194820
|
if (authorization) {
|
|
194373
194821
|
headers = new Headers();
|
|
194374
194822
|
headers.set("Authorization", authorization);
|
|
194375
194823
|
}
|
|
194376
|
-
else if (
|
|
194377
|
-
|
|
194378
|
-
|
|
194379
|
-
|
|
194824
|
+
else if (hasSettingsCreds) {
|
|
194825
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
194826
|
+
hasCreds = true;
|
|
194827
|
+
headers = new Headers();
|
|
194828
|
+
this.setRequestAuthorization(headers);
|
|
194829
|
+
if (!this.matchesSettingsUrlOrigin(url))
|
|
194830
|
+
this.logUntrustedOriginUse(url);
|
|
194831
|
+
}
|
|
194380
194832
|
}
|
|
194833
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
194381
194834
|
const opts = {
|
|
194382
194835
|
method: "GET",
|
|
194383
194836
|
headers,
|
|
194384
|
-
credentials:
|
|
194837
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
194838
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
194385
194839
|
};
|
|
194386
194840
|
if (timeoutMs !== undefined)
|
|
194387
194841
|
(0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.setRequestTimeout)(opts, timeoutMs);
|
|
194388
194842
|
response = await fetch(url, opts);
|
|
194843
|
+
if (includeCredentials)
|
|
194844
|
+
this.checkCredentialedRedirect(url, response);
|
|
194845
|
+
// fetch follows redirects transparently, so all trust decisions below target the final
|
|
194846
|
+
// (post-redirect) URL reported by the response, not the URL we asked for.
|
|
194847
|
+
const challengedUrl = response.url || url;
|
|
194389
194848
|
if (response.status === 401
|
|
194390
194849
|
&& (0,_request_utils__WEBPACK_IMPORTED_MODULE_6__.headersIncludeAuthMethod)(response.headers, ["ntlm", "negotiate"])
|
|
194391
|
-
&& !
|
|
194850
|
+
&& !includeCredentials
|
|
194392
194851
|
&& !hasCreds) {
|
|
194393
|
-
|
|
194394
|
-
|
|
194395
|
-
|
|
194396
|
-
|
|
194397
|
-
|
|
194398
|
-
|
|
194399
|
-
|
|
194852
|
+
if (this.isSsoAllowed(challengedUrl)) {
|
|
194853
|
+
// Removed the previous headers and make sure "include" credentials is set
|
|
194854
|
+
opts.headers = undefined;
|
|
194855
|
+
opts.credentials = "include";
|
|
194856
|
+
// A Negotiate/NTLM handshake is normally a same-URL 401 round-trip, but in legacy mode we preserve
|
|
194857
|
+
// the previous behavior and allow the browser to follow redirects after the authenticated retry.
|
|
194858
|
+
opts.redirect = _IModelApp__WEBPACK_IMPORTED_MODULE_3__.IModelApp.mapLayerFormatRegistry.restrictCredentialsToTrustedOrigins ? "error" : undefined;
|
|
194859
|
+
this.logUntrustedOriginUse(challengedUrl);
|
|
194860
|
+
// We got a http 401 challenge, lets try again with SSO enabled (i.e. Windows Authentication)
|
|
194861
|
+
response = await fetch(challengedUrl, opts);
|
|
194862
|
+
if (response.status === 200) {
|
|
194863
|
+
this.recordSsoSucceeded(challengedUrl); // avoid going through 401 challenges over and over for this origin
|
|
194864
|
+
}
|
|
194400
194865
|
}
|
|
194866
|
+
else {
|
|
194867
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
194868
|
+
}
|
|
194869
|
+
}
|
|
194870
|
+
else if ((response.status === 401 || response.status === 403) && hasSettingsCreds && !this.isCredentialsSharingAllowed(challengedUrl)) {
|
|
194871
|
+
// Some servers answer an unauthenticated request with 403 (Forbidden) rather than a 401 challenge;
|
|
194872
|
+
// since this request could not present its credentials to the challenging origin, either status most
|
|
194873
|
+
// likely results from that. The permission is recomputed for the challenged URL rather than reusing the
|
|
194874
|
+
// decision made for the requested one: `fetch` strips the Authorization header when it follows a
|
|
194875
|
+
// cross-origin redirect, so a trusted request can still arrive unauthenticated at an untrusted origin,
|
|
194876
|
+
// and conversely a request that started out untrusted may end up at an origin that is trusted.
|
|
194877
|
+
this.reportBlockedOrigin(challengedUrl);
|
|
194401
194878
|
}
|
|
194402
194879
|
return response;
|
|
194403
194880
|
}
|
|
@@ -194429,16 +194906,28 @@ class MapLayerImageryProvider {
|
|
|
194429
194906
|
}
|
|
194430
194907
|
/** @internal */
|
|
194431
194908
|
async toolTipFromUrl(strings, url) {
|
|
194432
|
-
|
|
194433
|
-
this.
|
|
194909
|
+
let headers;
|
|
194910
|
+
if (this.isCredentialsSharingAllowed(url)) {
|
|
194911
|
+
headers = new Headers();
|
|
194912
|
+
this.setRequestAuthorization(headers);
|
|
194913
|
+
}
|
|
194434
194914
|
try {
|
|
194915
|
+
const includeCredentials = this.includeUserCredentials(url);
|
|
194435
194916
|
const response = await fetch(url, {
|
|
194436
194917
|
method: "GET",
|
|
194437
194918
|
headers,
|
|
194438
|
-
credentials:
|
|
194919
|
+
credentials: includeCredentials ? "include" : undefined,
|
|
194920
|
+
redirect: includeCredentials ? this.credentialedRedirect : undefined,
|
|
194439
194921
|
});
|
|
194440
|
-
|
|
194441
|
-
|
|
194922
|
+
if (includeCredentials)
|
|
194923
|
+
this.checkCredentialedRedirect(url, response);
|
|
194924
|
+
let text = await response.text();
|
|
194925
|
+
if (text) {
|
|
194926
|
+
// Tooltip content (e.g. WMS GetFeatureInfo responses) is rendered as HTML downstream and may
|
|
194927
|
+
// deliberately contain markup; text from origins not trusted for credentials is escaped.
|
|
194928
|
+
// fetch follows redirects transparently, so the text may come from a different origin than requested.
|
|
194929
|
+
if (!this.isCredentialsSharingAllowed(response.url || url))
|
|
194930
|
+
text = escapeHtml(text);
|
|
194442
194931
|
strings.push(text);
|
|
194443
194932
|
}
|
|
194444
194933
|
}
|
|
@@ -194618,6 +195107,12 @@ var MapLayerSourceStatus;
|
|
|
194618
195107
|
/** Format is not compatible with the URL provided.
|
|
194619
195108
|
*/
|
|
194620
195109
|
MapLayerSourceStatus[MapLayerSourceStatus["IncompatibleFormat"] = 7] = "IncompatibleFormat";
|
|
195110
|
+
/** Authentication could not be attempted because the source's origin is not trusted
|
|
195111
|
+
* (see [MapLayerFormatRegistry.restrictCredentialsToTrustedOrigins]($frontend)). Add the origin to
|
|
195112
|
+
* [MapLayerFormatRegistry.trustedCredentialsOrigins]($frontend) rather than prompting for credentials.
|
|
195113
|
+
* @beta
|
|
195114
|
+
*/
|
|
195115
|
+
MapLayerSourceStatus[MapLayerSourceStatus["UntrustedOrigin"] = 8] = "UntrustedOrigin";
|
|
194621
195116
|
})(MapLayerSourceStatus || (MapLayerSourceStatus = {}));
|
|
194622
195117
|
/** A source for map layers. These may be catalogued for convenient use by users or applications.
|
|
194623
195118
|
* @public
|
|
@@ -194905,10 +195400,8 @@ class MapLayerTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_3__.T
|
|
|
194905
195400
|
const tree = this.treeOwner.tileTree;
|
|
194906
195401
|
if (undefined === tree || hit.iModel !== tree.iModel || tree.modelId !== hit.sourceId)
|
|
194907
195402
|
return undefined;
|
|
194908
|
-
const strings = [];
|
|
194909
|
-
strings.push(`Map Layer: ${this._layerSettings.name}`);
|
|
194910
195403
|
const div = document.createElement("div");
|
|
194911
|
-
div.
|
|
195404
|
+
div.textContent = `Map Layer: ${this._layerSettings.name}`;
|
|
194912
195405
|
return div;
|
|
194913
195406
|
}
|
|
194914
195407
|
decorate(_context) {
|
|
@@ -196617,7 +197110,9 @@ class MapTileTreeReference extends _internal__WEBPACK_IMPORTED_MODULE_7__.TileTr
|
|
|
196617
197110
|
let carto;
|
|
196618
197111
|
const strings = [];
|
|
196619
197112
|
const getTooltipFunc = async (imageryTreeRef, quadId, cartoGraphic, imageryTree) => {
|
|
196620
|
-
|
|
197113
|
+
// innerHTML is used below because imageryLoader.getToolTip may deliberately supply markup.
|
|
197114
|
+
const layerName = (0,_internal__WEBPACK_IMPORTED_MODULE_7__.escapeHtml)(imageryTreeRef.layerSettings.name);
|
|
197115
|
+
strings.push(`${_IModelApp__WEBPACK_IMPORTED_MODULE_4__.IModelApp.localization.getLocalizedString("iModelJs:MapLayers.ImageryLayer")}: ${layerName}`);
|
|
196621
197116
|
carto = cartoGraphic;
|
|
196622
197117
|
await imageryTree.imageryLoader.getToolTip(strings, quadId, cartoGraphic, imageryTree);
|
|
196623
197118
|
};
|
|
@@ -342457,7 +342952,7 @@ class TestContext {
|
|
|
342457
342952
|
this.initializeRpcInterfaces({ title: this.settings.Backend.name, version: this.settings.Backend.version });
|
|
342458
342953
|
const iModelClient = new imodels_client_management_1.IModelsClient({ api: { baseUrl: `https://${process.env.IMJS_URL_PREFIX ?? ""}api.bentley.com/imodels` } });
|
|
342459
342954
|
await core_frontend_1.NoRenderApp.startup({
|
|
342460
|
-
applicationVersion: "5.13.0-dev.
|
|
342955
|
+
applicationVersion: "5.13.0-dev.18",
|
|
342461
342956
|
applicationId: this.settings.gprid,
|
|
342462
342957
|
authorizationClient: new frontend_1.TestFrontendAuthorizationClient(this.serviceAuthToken),
|
|
342463
342958
|
hubAccess: new imodels_access_frontend_1.FrontendIModelsAccess(iModelClient),
|
|
@@ -367652,7 +368147,7 @@ var loadLanguages = instance.loadLanguages;
|
|
|
367652
368147
|
(module) {
|
|
367653
368148
|
|
|
367654
368149
|
"use strict";
|
|
367655
|
-
module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.
|
|
368150
|
+
module.exports = /*#__PURE__*/JSON.parse('{"name":"@itwin/core-frontend","version":"5.13.0-dev.18","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
368151
|
|
|
367657
368152
|
/***/ },
|
|
367658
368153
|
|