From 6d765d26d9b7d1eb33d1da623f2c346bec7a6c4d Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Tue, 17 Dec 2024 10:52:44 -0800 Subject: [PATCH 1/2] Check permissions before displaying widgets --- .../OrchardCore.Flows/Views/FlowPart.cshtml | 8 ++++++++ .../OrchardCore.Layers/Services/LayerFilter.cs | 7 ++++++- .../Drivers/WidgetsListPartDisplayDriver.cs | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml b/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml index 47f9c14bc51..7a22c99ef2c 100644 --- a/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml @@ -1,14 +1,22 @@ +@using Microsoft.AspNetCore.Authorization @using OrchardCore.ContentManagement +@using OrchardCore.Contents @using OrchardCore.Flows.Models @using OrchardCore.Flows.ViewModels @using OrchardCore.Mvc.Utilities @model FlowPartViewModel @inject OrchardCore.ContentManagement.Display.IContentItemDisplayManager ContentItemDisplayManager +@inject IAuthorizationService AuthorizationService
@foreach (var widget in Model.FlowPart.Widgets) { + if (!await AuthorizationService.AuthorizeAsync(User, CommonPermissions.ViewContent, widget)) + { + continue; + } + var widgetContent = await ContentItemDisplayManager.BuildDisplayAsync(widget, Model.BuildPartDisplayContext.Updater, Model.BuildPartDisplayContext.DisplayType, Model.BuildPartDisplayContext.GroupId); var flowMetadata = widget.As(); diff --git a/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs b/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs index 4d692f25d09..c064e7b339c 100644 --- a/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs +++ b/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs @@ -1,8 +1,10 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Caching.Memory; using OrchardCore.Admin; using OrchardCore.ContentManagement.Display; using OrchardCore.ContentManagement.Metadata; +using OrchardCore.Contents; using OrchardCore.Data.Documents; using OrchardCore.DisplayManagement.Layout; using OrchardCore.DisplayManagement.ModelBinding; @@ -27,6 +29,7 @@ public sealed class LayerFilter : IAsyncResultFilter private readonly IMemoryCache _memoryCache; private readonly IThemeManager _themeManager; private readonly IAdminThemeService _adminThemeService; + private readonly IAuthorizationService _authorizationService; private readonly ILayerService _layerService; private readonly IVolatileDocumentManager _layerStateManager; @@ -40,6 +43,7 @@ public LayerFilter( IMemoryCache memoryCache, IThemeManager themeManager, IAdminThemeService adminThemeService, + IAuthorizationService authorizationService, IVolatileDocumentManager layerStateManager) { _contentDefinitionManager = contentDefinitionManager; @@ -51,6 +55,7 @@ public LayerFilter( _memoryCache = memoryCache; _themeManager = themeManager; _adminThemeService = adminThemeService; + _authorizationService = authorizationService; _layerStateManager = layerStateManager; } @@ -114,7 +119,7 @@ public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultE continue; } - if (contentDefinitions.Any(c => c.Name == widget.ContentItem.ContentType)) + if (contentDefinitions.Any(c => c.Name == widget.ContentItem.ContentType) && await _authorizationService.AuthorizeAsync(context.HttpContext.User, CommonPermissions.ViewContent, widget.ContentItem)) { var widgetContent = await _contentItemDisplayManager.BuildDisplayAsync(widget.ContentItem, updater); diff --git a/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs index 1d6445b752d..961bd9e080b 100644 --- a/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs @@ -1,9 +1,12 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using OrchardCore.ContentManagement; using OrchardCore.ContentManagement.Display; using OrchardCore.ContentManagement.Display.ContentDisplay; using OrchardCore.ContentManagement.Display.Models; using OrchardCore.ContentManagement.Metadata; +using OrchardCore.Contents; using OrchardCore.DisplayManagement.Views; using OrchardCore.Mvc.Utilities; using OrchardCore.Widgets.Models; @@ -15,16 +18,22 @@ namespace OrchardCore.Widgets.Drivers; public sealed class WidgetsListPartDisplayDriver : ContentPartDisplayDriver { private readonly IContentDefinitionManager _contentDefinitionManager; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly IAuthorizationService _authorizationService; private readonly IContentManager _contentManager; private readonly IServiceProvider _serviceProvider; public WidgetsListPartDisplayDriver( IContentManager contentManager, IContentDefinitionManager contentDefinitionManager, + IHttpContextAccessor httpContextAccessor, + IAuthorizationService authorizationService, IServiceProvider serviceProvider ) { _contentDefinitionManager = contentDefinitionManager; + _httpContextAccessor = httpContextAccessor; + _authorizationService = authorizationService; _contentManager = contentManager; _serviceProvider = serviceProvider; } @@ -41,10 +50,17 @@ public override async Task DisplayAsync(WidgetsListPart part, Bu var contentItemDisplayManager = _serviceProvider.GetRequiredService(); + var user = _httpContextAccessor.HttpContext.User; + foreach (var zone in part.Widgets.Keys) { foreach (var widget in part.Widgets[zone]) { + if (!await _authorizationService.AuthorizeAsync(user, CommonPermissions.ViewContent, widget)) + { + continue; + } + var layerMetadata = widget.As(); if (layerMetadata != null) From 4017217af90f75180b21958ffffb7cc45ecbfd05 Mon Sep 17 00:00:00 2001 From: Mike Alhayek Date: Wed, 18 Dec 2024 05:21:20 -0800 Subject: [PATCH 2/2] definition check --- .../OrchardCore.Flows/Views/FlowPart.cshtml | 16 ++++++++++++-- .../Services/LayerFilter.cs | 7 +++++-- .../Drivers/WidgetsListPartDisplayDriver.cs | 10 ++++++++- .../TheTheme/Views/FlowPart.cshtml | 21 +++++++++++++++++++ 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml b/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml index 7a22c99ef2c..fbb4ded39d9 100644 --- a/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml +++ b/src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml @@ -1,18 +1,30 @@ @using Microsoft.AspNetCore.Authorization @using OrchardCore.ContentManagement +@using OrchardCore.ContentManagement.Metadata @using OrchardCore.Contents @using OrchardCore.Flows.Models @using OrchardCore.Flows.ViewModels @using OrchardCore.Mvc.Utilities +@using OrchardCore.ContentManagement.Metadata.Models @model FlowPartViewModel + @inject OrchardCore.ContentManagement.Display.IContentItemDisplayManager ContentItemDisplayManager @inject IAuthorizationService AuthorizationService - +@inject IContentDefinitionManager ContentDefinitionManager +@{ + var widgetDefinitions = (await ContentDefinitionManager.ListWidgetTypeDefinitionsAsync()) + .ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); +}
@foreach (var widget in Model.FlowPart.Widgets) { - if (!await AuthorizationService.AuthorizeAsync(User, CommonPermissions.ViewContent, widget)) + if (!widgetDefinitions.TryGetValue(widget.ContentType, out var definition)) + { + continue; + } + + if (definition.IsSecurable() && !await AuthorizationService.AuthorizeAsync(User, CommonPermissions.ViewContent, widget)) { continue; } diff --git a/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs b/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs index c064e7b339c..87b6af8817e 100644 --- a/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs +++ b/src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs @@ -4,6 +4,7 @@ using OrchardCore.Admin; using OrchardCore.ContentManagement.Display; using OrchardCore.ContentManagement.Metadata; +using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.Contents; using OrchardCore.Data.Documents; using OrchardCore.DisplayManagement.Layout; @@ -95,7 +96,8 @@ public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultE var updater = _modelUpdaterAccessor.ModelUpdater; var layersCache = new Dictionary(); - var contentDefinitions = await _contentDefinitionManager.ListTypeDefinitionsAsync(); + var widgetDefinitions = (await _contentDefinitionManager.ListWidgetTypeDefinitionsAsync()) + .ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); foreach (var widget in widgets) { @@ -119,7 +121,8 @@ public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultE continue; } - if (contentDefinitions.Any(c => c.Name == widget.ContentItem.ContentType) && await _authorizationService.AuthorizeAsync(context.HttpContext.User, CommonPermissions.ViewContent, widget.ContentItem)) + if (widgetDefinitions.TryGetValue(widget.ContentItem.ContentType, out var definition) && + (!definition.IsSecurable() || await _authorizationService.AuthorizeAsync(context.HttpContext.User, CommonPermissions.ViewContent, widget.ContentItem))) { var widgetContent = await _contentItemDisplayManager.BuildDisplayAsync(widget.ContentItem, updater); diff --git a/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs b/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs index 961bd9e080b..00706672ce8 100644 --- a/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs +++ b/src/OrchardCore.Modules/OrchardCore.Widgets/Drivers/WidgetsListPartDisplayDriver.cs @@ -6,6 +6,7 @@ using OrchardCore.ContentManagement.Display.ContentDisplay; using OrchardCore.ContentManagement.Display.Models; using OrchardCore.ContentManagement.Metadata; +using OrchardCore.ContentManagement.Metadata.Models; using OrchardCore.Contents; using OrchardCore.DisplayManagement.Views; using OrchardCore.Mvc.Utilities; @@ -51,12 +52,19 @@ public override async Task DisplayAsync(WidgetsListPart part, Bu var contentItemDisplayManager = _serviceProvider.GetRequiredService(); var user = _httpContextAccessor.HttpContext.User; + var widgetDefinitions = (await _contentDefinitionManager.ListWidgetTypeDefinitionsAsync()) + .ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); foreach (var zone in part.Widgets.Keys) { foreach (var widget in part.Widgets[zone]) { - if (!await _authorizationService.AuthorizeAsync(user, CommonPermissions.ViewContent, widget)) + if (!widgetDefinitions.TryGetValue(widget.ContentType, out var definition)) + { + continue; + } + + if (definition.IsSecurable() && !await _authorizationService.AuthorizeAsync(user, CommonPermissions.ViewContent, widget)) { continue; } diff --git a/src/OrchardCore.Themes/TheTheme/Views/FlowPart.cshtml b/src/OrchardCore.Themes/TheTheme/Views/FlowPart.cshtml index 6da45176ea2..a3b8103cdc0 100644 --- a/src/OrchardCore.Themes/TheTheme/Views/FlowPart.cshtml +++ b/src/OrchardCore.Themes/TheTheme/Views/FlowPart.cshtml @@ -1,14 +1,35 @@ +@using Microsoft.AspNetCore.Authorization @using OrchardCore.ContentManagement +@using OrchardCore.ContentManagement.Metadata +@using OrchardCore.Contents @using OrchardCore.Flows.Models @using OrchardCore.Flows.ViewModels @using OrchardCore.Mvc.Utilities +@using OrchardCore.ContentManagement.Metadata.Models @model FlowPartViewModel + @inject OrchardCore.ContentManagement.Display.IContentItemDisplayManager ContentItemDisplayManager +@inject IAuthorizationService AuthorizationService +@inject IContentDefinitionManager ContentDefinitionManager +@{ + var widgetDefinitions = (await ContentDefinitionManager.ListWidgetTypeDefinitionsAsync()) + .ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase); +}
@foreach (var widget in Model.FlowPart.Widgets) { + if (!widgetDefinitions.TryGetValue(widget.ContentType, out var definition)) + { + continue; + } + + if (definition.IsSecurable() && !await AuthorizationService.AuthorizeAsync(User, CommonPermissions.ViewContent, widget)) + { + continue; + } + var widgetContent = await ContentItemDisplayManager.BuildDisplayAsync(widget, Model.BuildPartDisplayContext.Updater, Model.BuildPartDisplayContext.DisplayType, Model.BuildPartDisplayContext.GroupId); var flowMetadata = widget.As();