Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ The `OrchardCoreContrib.Modules` repository consists of the following modules:
| [Data Localization Module](src/OrchardCoreContrib.DataLocalization/README.md) | `OrchardCoreContrib.DataLocalization` | [![NuGet](https://img.shields.io/nuget/v/OrchardCoreContrib.DataLocalization.svg)](https://www.nuget.org/packages/OrchardCoreContrib.DataLocalization) |
| [Elm Diagnostics Module](src/OrchardCoreContrib.Diagnostics.Elm/README.md) | `OrchardCoreContrib.Diagnostics.Elm` | [![NuGet](https://img.shields.io/nuget/v/OrchardCoreContrib.Diagnostics.Elm.svg)](https://www.nuget.org/packages/OrchardCoreContrib.Diagnostics.Elm) |
| [Gmail Module](src/OrchardCoreContrib.Email.Gmail/README.md) | `OrchardCoreContrib.Email.Gmail` | [![NuGet](https://img.shields.io/nuget/v/OrchardCoreContrib.Email.Gmail.svg)](https://www.nuget.org/packages/OrchardCoreContrib.Email.Gmail) |
| [GDPR Module](src/OrchardCoreContrib.Gdpr/README.md) | `OrchardCoreContrib.Gdpr` | [![NuGet](https://img.shields.io/nuget/v/OrchardCoreContrib.Gdpr.svg)](https://www.nuget.org/packages/OrchardCoreContrib.Gdpr) |
| [Hotmail Module](src/OrchardCoreContrib.Email.Hotmail/README.md) | `OrchardCoreContrib.Email.Hotmail` | [![NuGet](https://img.shields.io/nuget/v/OrchardCoreContrib.Email.Hotmail.svg)](https://www.nuget.org/packages/OrchardCoreContrib.Email.Hotmail) |
| [SendGrid Module](src/OrchardCoreContrib.Email.SendGrid/README.md) | `OrchardCoreContrib.Email.SendGrid` | [![NuGet](https://img.shields.io/nuget/v/OrchardCoreContrib.Email.SendGrid.svg)](https://www.nuget.org/packages/OrchardCoreContrib.Email.SendGrid) |
| [Yahoo Module](src/OrchardCoreContrib.Email.Yahoo/README.md) | `OrchardCoreContrib.Email.Yahoo` | [![NuGet](https://img.shields.io/nuget/v/OrchardCoreContrib.Email.Yahoo.svg)](https://www.nuget.org/packages/OrchardCoreContrib.Email.Yahoo) |
Expand Down
63 changes: 30 additions & 33 deletions src/OrchardCoreContrib.Gdpr/AdminMenu.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,38 @@
using Microsoft.Extensions.Localization;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Localization;
using OrchardCore.Navigation;
using OrchardCoreContrib.Gdpr.Drivers;
using System;
using System.Threading.Tasks;

namespace OrchardCoreContrib.Gdpr
{
using OrchardCoreContrib.Navigation;
namespace OrchardCoreContrib.Gdpr;

/// <summary>
/// Represents an admin menu for GDPR module.
/// </summary>
public class AdminMenu : AdminNavigationProvider
{
private readonly IStringLocalizer S;
using OrchardCoreContrib.Navigation;

/// <summary>
/// Initializes a new instance of <see cref="AdminMenu"/>.
/// </summary>
/// <param name="stringLocalizer">The <see cref="IStringLocalizer{AdminMenu}"/>.</param>
public AdminMenu(IStringLocalizer<AdminMenu> stringLocalizer)
{
S = stringLocalizer;
}
/// <summary>
/// Represents an admin menu for GDPR module.
/// </summary>
/// <remarks>
/// Initializes a new instance of <see cref="AdminMenu"/>.
/// </remarks>
/// <param name="stringLocalizer">The <see cref="IStringLocalizer{AdminMenu}"/>.</param>
public class AdminMenu(IStringLocalizer<AdminMenu> S) : AdminNavigationProvider
{
private static readonly RouteValueDictionary _routeValues = new()
{
{ "area", "OrchardCore.Settings" },
{ "groupId", GdprSettingsDisplayDriver.GroupId },
};

/// <inheritdoc/>
public override void BuildNavigation(NavigationBuilder builder)
{
builder
.Add(S["Configuration"], configuration => configuration
.Add(S["Settings"], settings => settings
.Add(S["GDPR"], S["GDPR"].PrefixPosition(), entry => entry
.AddClass("gdpr").Id("gdpr")
.Action("Index", "Admin", new { area = "OrchardCore.Settings", groupId = GdprSettingsDisplayDriver.GroupId })
.Permission(Permissions.ManageGdprSettings)
.LocalNav()
)));
}
/// <inheritdoc/>
public override void BuildNavigation(NavigationBuilder builder)
{
builder
.Add(S["Configuration"], configuration => configuration
.Add(S["Settings"], settings => settings
.Add(S["GDPR"], S["GDPR"].PrefixPosition(), entry => entry
.AddClass("gdpr").Id("gdpr")
.Action("Index", "Admin", _routeValues)
.Permission(GdprPermissions.ManageGdprSettings)
.LocalNav()
)));
}
}
20 changes: 7 additions & 13 deletions src/OrchardCoreContrib.Gdpr/Controllers/HomeController.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
using Microsoft.AspNetCore.Mvc;
using OrchardCore.Entities;
using OrchardCore.Settings;

namespace OrchardCoreContrib.Gdpr.Controllers
namespace OrchardCoreContrib.Gdpr.Controllers;

public class HomeController(ISiteService site) : Controller
{
public class HomeController : Controller
[HttpGet]
public async Task<IActionResult> Privacy()
{
private readonly GdprSettings _gdprSettings;

public HomeController(ISiteService site)
{
_gdprSettings = site.GetSiteSettingsAsync()
.GetAwaiter().GetResult()
.As<GdprSettings>();
}
var gdprSettings = (await site.GetSiteSettingsAsync()).As<GdprSettings>();

[HttpGet]
public IActionResult Privacy() => View(_gdprSettings);
return View(gdprSettings);
}
}
66 changes: 25 additions & 41 deletions src/OrchardCoreContrib.Gdpr/CookieConsentFilter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,39 @@
using OrchardCore.Admin;
using OrchardCore.DisplayManagement;
using OrchardCore.DisplayManagement.Layout;
using System;
using System.Threading.Tasks;

namespace OrchardCoreContrib.Gdpr
namespace OrchardCoreContrib.Gdpr;

/// <summary>
/// Represents a filter that inject a cookie consent shape into the layout.
/// </summary>
public class CookieConsentFilter(
IOptions<AdminOptions> adminOptions,
ILayoutAccessor layoutAccessor,
IShapeFactory shapeFactory) : IAsyncResultFilter
{
/// <summary>
/// Represents a filter that inject a cookie consent shape into the layout.
/// </summary>
public class CookieConsentFilter : IAsyncResultFilter
{
private readonly string _adminUrlPrefix;
private readonly ILayoutAccessor _layoutAccessor;
private readonly IShapeFactory _shapeFactory;
private readonly string _adminUrlPrefix = adminOptions.Value.AdminUrlPrefix;

/// <summary>
/// Initializes a new instance of <see cref="CookieConsentFilter"/>.
/// </summary>
/// <param name="adminOptions">The <see cref="IOptions{AdminOptions}"/>.</param>
/// <param name="layoutAccessor">The <see cref="ILayoutAccessor"/>,</param>
/// <param name="shapeFactory">The <see cref="IShapeFactory"/>.</param>
public CookieConsentFilter(
IOptions<AdminOptions> adminOptions,
ILayoutAccessor layoutAccessor,
IShapeFactory shapeFactory)
/// <inheritdoc/>
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (context.HttpContext.Request.Path.Value.Contains(_adminUrlPrefix, StringComparison.OrdinalIgnoreCase))
{
_adminUrlPrefix = adminOptions.Value.AdminUrlPrefix;
_layoutAccessor = layoutAccessor;
_shapeFactory = shapeFactory;
await next();

return;
}

/// <inheritdoc/>
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
var consentFeature = context.HttpContext.Features.Get<ITrackingConsentFeature>();
if (!consentFeature?.CanTrack ?? false)
{
if (context.HttpContext.Request.Path.Value.Contains(_adminUrlPrefix, StringComparison.OrdinalIgnoreCase))
{
await next();
var layout = await layoutAccessor.GetLayoutAsync();

var contentZone = layout.Zones["Content"];

return;
}

var consentFeature = context.HttpContext.Features.Get<ITrackingConsentFeature>();
if (!consentFeature?.CanTrack ?? false)
{
dynamic layout = await _layoutAccessor.GetLayoutAsync();
var contentZone = layout.Zones["Content"];
contentZone.Add(await _shapeFactory.New.CookieConsent());
}

await next();
await contentZone.AddAsync((object)await shapeFactory.New.CookieConsent());
}

await next();
}
}
103 changes: 36 additions & 67 deletions src/OrchardCoreContrib.Gdpr/Drivers/GdprSettingsDisplayDriver.cs
Original file line number Diff line number Diff line change
@@ -1,91 +1,60 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using OrchardCore.DisplayManagement.Entities;
using OrchardCore.DisplayManagement.Handlers;
using OrchardCore.DisplayManagement.Views;
using OrchardCore.Environment.Shell;
using OrchardCore.Settings;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace OrchardCoreContrib.Gdpr.Drivers
namespace OrchardCoreContrib.Gdpr.Drivers;

/// <summary>
/// Represents a display driver for <see cref="GdprSettings"/>.
/// </summary>
public class GdprSettingsDisplayDriver(
IShellHost shellHost,
ShellSettings shellSettings,
IHttpContextAccessor httpContextAccessor,
IAuthorizationService authorizationService) : SectionDisplayDriver<ISite, GdprSettings>
{
/// <summary>
/// Represents a display driver for <see cref="GdprSettings"/>.
/// </summary>
public class GdprSettingsDisplayDriver : SectionDisplayDriver<ISite, GdprSettings>
{
public const string GroupId = "gdpr";
public const string GroupId = "gdpr";

/// <inheritdoc/>

private readonly IDataProtectionProvider _dataProtectionProvider;
private readonly IShellHost _shellHost;
private readonly ShellSettings _shellSettings;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IAuthorizationService _authorizationService;
public override async Task<IDisplayResult> EditAsync(ISite model, GdprSettings section, BuildEditorContext context)
{
var user = httpContextAccessor.HttpContext?.User;

/// <summary>
/// Initializes a new instance of <see cref="GdprSettingsDisplayDriver"/>.
/// </summary>
/// <param name="dataProtectionProvider">The <see cref="IDataProtectionProvider"/>.</param>
/// <param name="shellHost">The <see cref="IShellHost"/>.</param>
/// <param name="shellSettings">The <see cref="ShellSettings"/>.</param>
/// <param name="httpContextAccessor">The <see cref="IHttpContextAccessor"/>.</param>
/// <param name="authorizationService">The <see cref="IAuthorizationService"/>.</param>
public GdprSettingsDisplayDriver(
IDataProtectionProvider dataProtectionProvider,
IShellHost shellHost,
ShellSettings shellSettings,
IHttpContextAccessor httpContextAccessor,
IAuthorizationService authorizationService)
if (!await authorizationService.AuthorizeAsync(user, GdprPermissions.ManageGdprSettings))
{
_dataProtectionProvider = dataProtectionProvider;
_shellHost = shellHost;
_shellSettings = shellSettings;
_httpContextAccessor = httpContextAccessor;
_authorizationService = authorizationService;
return null;
}

/// <inheritdoc/>

public override async Task<IDisplayResult> EditAsync(ISite model, GdprSettings section, BuildEditorContext context)
return Initialize<GdprSettings>("GdprSettings_Edit", model =>
{
var user = _httpContextAccessor.HttpContext?.User;

if (!await _authorizationService.AuthorizeAsync(user, Permissions.ManageGdprSettings))
{
return null;
}
model.Summary = section.Summary;
model.Detail = section.Detail;
}).Location("Content:5")
.OnGroup(GroupId);
}

var shapes = new List<IDisplayResult>
{
Initialize<GdprSettings>("GdprSettings_Edit", model =>
{
model.Summary = section.Summary;
model.Detail = section.Detail;
}).Location("Content:5").OnGroup(GroupId)
};
/// <inheritdoc/>
public override async Task<IDisplayResult> UpdateAsync(ISite model, GdprSettings section, UpdateEditorContext context)
{
var user = httpContextAccessor.HttpContext?.User;

return Combine(shapes);
if (!await authorizationService.AuthorizeAsync(user, GdprPermissions.ManageGdprSettings))
{
return null;
}

/// <inheritdoc/>
public override async Task<IDisplayResult> UpdateAsync(ISite model, GdprSettings section, UpdateEditorContext context)
if (context.GroupId == GroupId)
{
var user = _httpContextAccessor.HttpContext?.User;

if (!await _authorizationService.AuthorizeAsync(user, Permissions.ManageGdprSettings))
{
return null;
}
await context.Updater.TryUpdateModelAsync(section, Prefix);

if (context.GroupId == GroupId)
{
await context.Updater.TryUpdateModelAsync(section, Prefix);
await _shellHost.ReleaseShellContextAsync(_shellSettings);
}

return await EditAsync(model, section, context);
await shellHost.ReleaseShellContextAsync(shellSettings);
}

return await EditAsync(model, section, context);
}
}
14 changes: 14 additions & 0 deletions src/OrchardCoreContrib.Gdpr/GdprPermissions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using OrchardCore.Security.Permissions;

namespace OrchardCoreContrib.Gdpr;

/// <summary>
/// Provides predefined permissions related to the GDPR module.
/// </summary>
public class GdprPermissions
{
/// <summary>
/// Gets a permission for managing a GDPR settings.
/// </summary>
public static readonly Permission ManageGdprSettings = new("ManageGdprSettings", "Manage GDPR Settings");
}
33 changes: 16 additions & 17 deletions src/OrchardCoreContrib.Gdpr/GdprSettings.cs
Original file line number Diff line number Diff line change
@@ -1,22 +1,21 @@
namespace OrchardCoreContrib.Gdpr
namespace OrchardCoreContrib.Gdpr;

/// <summary>
/// Represents a GDPR settings
/// </summary>
public class GdprSettings
{
/// <summary>
/// Represents a GDPR settings
/// </summary>
public class GdprSettings
{
private static readonly string DefaultSummary = "Use this page to summarize your privacy and cookie use policy.";
private static readonly string DefaultSummary = "Use this page to summarize your privacy and cookie use policy.";

private static readonly string DefaultDetail = "Use this page to detail your site's privacy policy.";
private static readonly string DefaultDetail = "Use this page to detail your site's privacy policy.";

/// <summary>
/// Gets or sets a summary that will be used in the cookie consent UI.
/// </summary>
public string Summary { get; set; } = DefaultSummary;
/// <summary>
/// Gets or sets a summary that will be used in the cookie consent UI.
/// </summary>
public string Summary { get; set; } = DefaultSummary;

/// <summary>
/// Gets or sets a detail that will be used in the privacy policy page.
/// </summary>
public string Detail { get; set; } = DefaultDetail;
}
/// <summary>
/// Gets or sets a detail that will be used in the privacy policy page.
/// </summary>
public string Detail { get; set; } = DefaultDetail;
}
8 changes: 0 additions & 8 deletions src/OrchardCoreContrib.Gdpr/Manifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,5 @@
Website = ManifestConstants.Website,
Version = "1.0.0",
Description = "Supports EU General Data Protection Regulation (GDPR).",
Dependencies = new string[] { "OrchardCore.Gdpr" },
Category = "Security"
)]

[assembly: Feature(
Id = "OrchardCoreContrib.Gdpr",
Name = "GDPR",
Description = "Supports EU General Data Protection Regulation (GDPR).",
Category = "Security"
)]
Loading
Loading