Skip to content

Commit

Permalink
Check permissions before displaying widgets (#17252)
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeAlhayek authored Dec 19, 2024
1 parent 4d46493 commit 7aedc1e
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 3 deletions.
22 changes: 21 additions & 1 deletion src/OrchardCore.Modules/OrchardCore.Flows/Views/FlowPart.cshtml
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
@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 OrchardCore.ContentManagement.Display.IContentItemDisplayManager ContentItemDisplayManager
@inject IAuthorizationService AuthorizationService
@inject IContentDefinitionManager ContentDefinitionManager
@{
var widgetDefinitions = (await ContentDefinitionManager.ListWidgetTypeDefinitionsAsync())
.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);
}
<section class="flow">
@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<FlowMetadata>();

Expand Down
12 changes: 10 additions & 2 deletions src/OrchardCore.Modules/OrchardCore.Layers/Services/LayerFilter.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
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.ContentManagement.Metadata.Models;
using OrchardCore.Contents;
using OrchardCore.Data.Documents;
using OrchardCore.DisplayManagement.Layout;
using OrchardCore.DisplayManagement.ModelBinding;
Expand All @@ -27,6 +30,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<LayerState> _layerStateManager;

Expand All @@ -40,6 +44,7 @@ public LayerFilter(
IMemoryCache memoryCache,
IThemeManager themeManager,
IAdminThemeService adminThemeService,
IAuthorizationService authorizationService,
IVolatileDocumentManager<LayerState> layerStateManager)
{
_contentDefinitionManager = contentDefinitionManager;
Expand All @@ -51,6 +56,7 @@ public LayerFilter(
_memoryCache = memoryCache;
_themeManager = themeManager;
_adminThemeService = adminThemeService;
_authorizationService = authorizationService;
_layerStateManager = layerStateManager;
}

Expand Down Expand Up @@ -90,7 +96,8 @@ public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultE
var updater = _modelUpdaterAccessor.ModelUpdater;

var layersCache = new Dictionary<string, bool>();
var contentDefinitions = await _contentDefinitionManager.ListTypeDefinitionsAsync();
var widgetDefinitions = (await _contentDefinitionManager.ListWidgetTypeDefinitionsAsync())
.ToDictionary(x => x.Name, StringComparer.OrdinalIgnoreCase);

foreach (var widget in widgets)
{
Expand All @@ -114,7 +121,8 @@ public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultE
continue;
}

if (contentDefinitions.Any(c => c.Name == widget.ContentItem.ContentType))
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);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
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.ContentManagement.Metadata.Models;
using OrchardCore.Contents;
using OrchardCore.DisplayManagement.Views;
using OrchardCore.Mvc.Utilities;
using OrchardCore.Widgets.Models;
Expand All @@ -15,16 +19,22 @@ namespace OrchardCore.Widgets.Drivers;
public sealed class WidgetsListPartDisplayDriver : ContentPartDisplayDriver<WidgetsListPart>
{
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;
}
Expand All @@ -41,10 +51,24 @@ public override async Task<IDisplayResult> DisplayAsync(WidgetsListPart part, Bu

var contentItemDisplayManager = _serviceProvider.GetRequiredService<IContentItemDisplayManager>();

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 (!widgetDefinitions.TryGetValue(widget.ContentType, out var definition))
{
continue;
}

if (definition.IsSecurable() && !await _authorizationService.AuthorizeAsync(user, CommonPermissions.ViewContent, widget))
{
continue;
}

var layerMetadata = widget.As<WidgetMetadata>();

if (layerMetadata != null)
Expand Down
21 changes: 21 additions & 0 deletions src/OrchardCore.Themes/TheTheme/Views/FlowPart.cshtml
Original file line number Diff line number Diff line change
@@ -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);
}
<section class="flow row">
@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<FlowMetadata>();

Expand Down

0 comments on commit 7aedc1e

Please sign in to comment.