Skip to content

Commit 417576b

Browse files
Content picker search with start node configured not taking user start nodes into account (#19871)
* Content picker search with start node configured not taking user start nodes into account (#19800) * Fix users being able to see nodes they don't have access to when using the picker search * Readability and naming improvements * Additional fixes * Adjust tests * Additional fixes * Small improvement * Replaced the root ids with constants * Update src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs Co-authored-by: Andy Butland <[email protected]> --------- Co-authored-by: Andy Butland <[email protected]> # Conflicts: # src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs # src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs # src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs # src/Umbraco.Web.BackOffice/Trees/MemberTreeController.cs # tests/Umbraco.Tests.Integration/Umbraco.Examine.Lucene/UmbracoExamine/BackOfficeExamineSearcherTests.cs * Add new constructor without unused and obsolete parameters * Use non obsolete constructor in tests * Add `dataTypeId` as parameter in document and media search endpoints to get `ignoreUserStartNodes` value * Update backend API generated typed client * Updated picker search to pass in data type unique * Move data type retrieval to UmbPickerContext * Adjust the controller constructors to make it non breaking * Adjust controller methods to make non-breaking. --------- Co-authored-by: Andy Butland <[email protected]>
1 parent 2289493 commit 417576b

File tree

17 files changed

+354
-89
lines changed

17 files changed

+354
-89
lines changed

src/Umbraco.Cms.Api.Management/Controllers/Document/Item/SearchDocumentItemController.cs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using Asp.Versioning;
22
using Microsoft.AspNetCore.Http;
33
using Microsoft.AspNetCore.Mvc;
4+
using Microsoft.Extensions.DependencyInjection;
45
using Umbraco.Cms.Api.Management.Factories;
56
using Umbraco.Cms.Api.Management.ViewModels.Document.Item;
7+
using Umbraco.Cms.Core.DependencyInjection;
68
using Umbraco.Cms.Core.Models;
79
using Umbraco.Cms.Core.Models.Entities;
810
using Umbraco.Cms.Core.Services;
11+
using Umbraco.Extensions;
912

1013
namespace Umbraco.Cms.Api.Management.Controllers.Document.Item;
1114

@@ -14,13 +17,52 @@ public class SearchDocumentItemController : DocumentItemControllerBase
1417
{
1518
private readonly IIndexedEntitySearchService _indexedEntitySearchService;
1619
private readonly IDocumentPresentationFactory _documentPresentationFactory;
20+
private readonly IDataTypeService _dataTypeService;
1721

18-
public SearchDocumentItemController(IIndexedEntitySearchService indexedEntitySearchService, IDocumentPresentationFactory documentPresentationFactory)
22+
[ActivatorUtilitiesConstructor]
23+
public SearchDocumentItemController(
24+
IIndexedEntitySearchService indexedEntitySearchService,
25+
IDocumentPresentationFactory documentPresentationFactory,
26+
IDataTypeService dataTypeService)
1927
{
2028
_indexedEntitySearchService = indexedEntitySearchService;
2129
_documentPresentationFactory = documentPresentationFactory;
30+
_dataTypeService = dataTypeService;
2231
}
2332

33+
[Obsolete("Use the non-obsolete constructor instead, will be removed in v18")]
34+
public SearchDocumentItemController(
35+
IIndexedEntitySearchService indexedEntitySearchService,
36+
IDocumentPresentationFactory documentPresentationFactory)
37+
: this(
38+
indexedEntitySearchService,
39+
documentPresentationFactory,
40+
StaticServiceProvider.Instance.GetRequiredService<IDataTypeService>())
41+
{
42+
}
43+
44+
[Obsolete("Please use the overload taking all parameters. Scheduled for removal in Umbraco 18.")]
45+
[ApiExplorerSettings(IgnoreApi = true)]
46+
public async Task<IActionResult> SearchWithTrashed(
47+
CancellationToken cancellationToken,
48+
string query,
49+
bool? trashed = null,
50+
string? culture = null,
51+
int skip = 0,
52+
int take = 100,
53+
Guid? parentId = null,
54+
[FromQuery] IEnumerable<Guid>? allowedDocumentTypes = null)
55+
=> await SearchWithTrashed(
56+
cancellationToken,
57+
query,
58+
trashed,
59+
culture,
60+
skip,
61+
take,
62+
parentId,
63+
allowedDocumentTypes,
64+
null);
65+
2466
[HttpGet("search")]
2567
[MapToApiVersion("1.0")]
2668
[ProducesResponseType(typeof(PagedModel<DocumentItemResponseModel>), StatusCodes.Status200OK)]
@@ -32,9 +74,21 @@ public async Task<IActionResult> SearchWithTrashed(
3274
int skip = 0,
3375
int take = 100,
3476
Guid? parentId = null,
35-
[FromQuery] IEnumerable<Guid>? allowedDocumentTypes = null)
77+
[FromQuery] IEnumerable<Guid>? allowedDocumentTypes = null,
78+
Guid? dataTypeId = null)
3679
{
37-
PagedModel<IEntitySlim> searchResult = await _indexedEntitySearchService.SearchAsync(UmbracoObjectTypes.Document, query, parentId, allowedDocumentTypes, trashed, culture, skip, take);
80+
var ignoreUserStartNodes = await IgnoreUserStartNodes(dataTypeId);
81+
PagedModel<IEntitySlim> searchResult = await _indexedEntitySearchService.SearchAsync(
82+
UmbracoObjectTypes.Document,
83+
query,
84+
parentId,
85+
allowedDocumentTypes,
86+
trashed,
87+
culture,
88+
skip,
89+
take,
90+
ignoreUserStartNodes);
91+
3892
var result = new PagedModel<DocumentItemResponseModel>
3993
{
4094
Items = searchResult.Items.OfType<IDocumentEntitySlim>().Select(_documentPresentationFactory.CreateItemResponseModel),
@@ -43,4 +97,7 @@ public async Task<IActionResult> SearchWithTrashed(
4397

4498
return Ok(result);
4599
}
100+
101+
private async Task<bool> IgnoreUserStartNodes(Guid? dataTypeKey) =>
102+
dataTypeKey is not null && await _dataTypeService.IsDataTypeIgnoringUserStartNodesAsync(dataTypeKey.Value);
46103
}

src/Umbraco.Cms.Api.Management/Controllers/Document/Tree/ChildrenDocumentTreeController.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ public ChildrenDocumentTreeController(
3636
[HttpGet("children")]
3737
[MapToApiVersion("1.0")]
3838
[ProducesResponseType(typeof(PagedViewModel<DocumentTreeItemResponseModel>), StatusCodes.Status200OK)]
39-
public async Task<ActionResult<PagedViewModel<DocumentTreeItemResponseModel>>> Children(CancellationToken cancellationToken, Guid parentId, int skip = 0, int take = 100, Guid? dataTypeId = null)
39+
public async Task<ActionResult<PagedViewModel<DocumentTreeItemResponseModel>>> Children(
40+
CancellationToken cancellationToken,
41+
Guid parentId,
42+
int skip = 0,
43+
int take = 100,
44+
Guid? dataTypeId = null)
4045
{
4146
IgnoreUserStartNodesForDataType(dataTypeId);
4247
return await GetChildren(parentId, skip, take);

src/Umbraco.Cms.Api.Management/Controllers/Media/Item/SearchMediaItemController.cs

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
using Asp.Versioning;
22
using Microsoft.AspNetCore.Http;
33
using Microsoft.AspNetCore.Mvc;
4+
using Microsoft.Extensions.DependencyInjection;
45
using Umbraco.Cms.Api.Management.Factories;
56
using Umbraco.Cms.Api.Management.ViewModels.Media.Item;
7+
using Umbraco.Cms.Core.DependencyInjection;
68
using Umbraco.Cms.Core.Models;
79
using Umbraco.Cms.Core.Models.Entities;
810
using Umbraco.Cms.Core.Services;
11+
using Umbraco.Extensions;
912

1013
namespace Umbraco.Cms.Api.Management.Controllers.Media.Item;
1114

@@ -14,13 +17,52 @@ public class SearchMediaItemController : MediaItemControllerBase
1417
{
1518
private readonly IIndexedEntitySearchService _indexedEntitySearchService;
1619
private readonly IMediaPresentationFactory _mediaPresentationFactory;
20+
private readonly IDataTypeService _dataTypeService;
1721

18-
public SearchMediaItemController(IIndexedEntitySearchService indexedEntitySearchService, IMediaPresentationFactory mediaPresentationFactory)
22+
[ActivatorUtilitiesConstructor]
23+
public SearchMediaItemController(
24+
IIndexedEntitySearchService indexedEntitySearchService,
25+
IMediaPresentationFactory mediaPresentationFactory,
26+
IDataTypeService dataTypeService)
1927
{
2028
_indexedEntitySearchService = indexedEntitySearchService;
2129
_mediaPresentationFactory = mediaPresentationFactory;
30+
_dataTypeService = dataTypeService;
2231
}
2332

33+
[Obsolete("Use the non-obsolete constructor instead, will be removed in Umbraco 18.")]
34+
public SearchMediaItemController(
35+
IIndexedEntitySearchService indexedEntitySearchService,
36+
IMediaPresentationFactory mediaPresentationFactory)
37+
: this(
38+
indexedEntitySearchService,
39+
mediaPresentationFactory,
40+
StaticServiceProvider.Instance.GetRequiredService<IDataTypeService>())
41+
{
42+
}
43+
44+
[Obsolete("Please use the overload taking all parameters. Scheduled for removal in Umbraco 18.")]
45+
[ApiExplorerSettings(IgnoreApi = true)]
46+
public async Task<IActionResult> SearchFromParentWithAllowedTypes(
47+
CancellationToken cancellationToken,
48+
string query,
49+
bool? trashed = null,
50+
string? culture = null,
51+
int skip = 0,
52+
int take = 100,
53+
Guid? parentId = null,
54+
[FromQuery] IEnumerable<Guid>? allowedMediaTypes = null)
55+
=> await SearchFromParentWithAllowedTypes(
56+
cancellationToken,
57+
query,
58+
trashed,
59+
culture,
60+
skip,
61+
take,
62+
parentId,
63+
allowedMediaTypes,
64+
null);
65+
2466
[HttpGet("search")]
2567
[MapToApiVersion("1.0")]
2668
[ProducesResponseType(typeof(PagedModel<MediaItemResponseModel>), StatusCodes.Status200OK)]
@@ -32,9 +74,20 @@ public async Task<IActionResult> SearchFromParentWithAllowedTypes(
3274
int skip = 0,
3375
int take = 100,
3476
Guid? parentId = null,
35-
[FromQuery]IEnumerable<Guid>? allowedMediaTypes = null)
77+
[FromQuery] IEnumerable<Guid>? allowedMediaTypes = null,
78+
Guid? dataTypeId = null)
3679
{
37-
PagedModel<IEntitySlim> searchResult = await _indexedEntitySearchService.SearchAsync(UmbracoObjectTypes.Media, query, parentId, allowedMediaTypes, trashed, culture, skip, take);
80+
var ignoreUserStartNodes = await IgnoreUserStartNodes(dataTypeId);
81+
PagedModel<IEntitySlim> searchResult = await _indexedEntitySearchService.SearchAsync(
82+
UmbracoObjectTypes.Media,
83+
query,
84+
parentId,
85+
allowedMediaTypes,
86+
trashed,
87+
culture,
88+
skip,
89+
take,
90+
ignoreUserStartNodes);
3891
var result = new PagedModel<MediaItemResponseModel>
3992
{
4093
Items = searchResult.Items.OfType<IMediaEntitySlim>().Select(_mediaPresentationFactory.CreateItemResponseModel),
@@ -43,4 +96,7 @@ public async Task<IActionResult> SearchFromParentWithAllowedTypes(
4396

4497
return Ok(result);
4598
}
99+
100+
private async Task<bool> IgnoreUserStartNodes(Guid? dataTypeKey) =>
101+
dataTypeKey is not null && await _dataTypeService.IsDataTypeIgnoringUserStartNodesAsync(dataTypeKey.Value);
46102
}

src/Umbraco.Cms.Api.Management/OpenApi.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10385,6 +10385,14 @@
1038510385
"format": "uuid"
1038610386
}
1038710387
}
10388+
},
10389+
{
10390+
"name": "dataTypeId",
10391+
"in": "query",
10392+
"schema": {
10393+
"type": "string",
10394+
"format": "uuid"
10395+
}
1038810396
}
1038910397
],
1039010398
"responses": {
@@ -16281,6 +16289,14 @@
1628116289
"format": "uuid"
1628216290
}
1628316291
}
16292+
},
16293+
{
16294+
"name": "dataTypeId",
16295+
"in": "query",
16296+
"schema": {
16297+
"type": "string",
16298+
"format": "uuid"
16299+
}
1628416300
}
1628516301
],
1628616302
"responses": {

src/Umbraco.Core/Services/DateTypeServiceExtensions.cs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,11 @@ namespace Umbraco.Extensions;
77
public static class DateTypeServiceExtensions
88
{
99
public static bool IsDataTypeIgnoringUserStartNodes(this IDataTypeService dataTypeService, Guid key)
10-
{
11-
IDataType? dataType = dataTypeService.GetAsync(key).GetAwaiter().GetResult();
12-
13-
if (dataType != null && dataType.ConfigurationObject is IIgnoreUserStartNodesConfig ignoreStartNodesConfig)
14-
{
15-
return ignoreStartNodesConfig.IgnoreUserStartNodes;
16-
}
10+
=> dataTypeService.IsDataTypeIgnoringUserStartNodesAsync(key).GetAwaiter().GetResult();
1711

18-
return false;
12+
public static async Task<bool> IsDataTypeIgnoringUserStartNodesAsync(this IDataTypeService dataTypeService, Guid key)
13+
{
14+
IDataType? dataType = await dataTypeService.GetAsync(key);
15+
return dataType is { ConfigurationObject: IIgnoreUserStartNodesConfig { IgnoreUserStartNodes: true } };
1916
}
2017
}

0 commit comments

Comments
 (0)