only allow essential cookies when cookie consent not granted.

This commit is contained in:
Ben 2025-02-26 19:41:58 +08:00
parent b47bf40e8f
commit 6dddd8eff8
10 changed files with 101 additions and 34 deletions

View File

@ -126,6 +126,15 @@
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="cookieconsent" HelpText="Specify if cookie consent is enabled on this site" ResourceKey="CookieConsent">Cookie Consent: </Label>
<div class="col-sm-9">
<select id="cookieconsent" class="form-select" @bind="@_cookieconsent">
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
</div>
</Section>
<Section Name="Functionality" Heading="Functionality" ResourceKey="Functionality">
@ -415,6 +424,7 @@
private string _themetype = "";
private string _containertype = "";
private string _admincontainertype = "";
private string _cookieconsent = "False";
private Dictionary<string, string> _textEditors = new Dictionary<string, string>();
private string _textEditor = "";
@ -505,6 +515,7 @@
_containers = ThemeService.GetContainerControls(PageState.Site.Themes, _themetype);
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
_cookieconsent = SettingService.GetSetting(settings, "CookieConsent", "False");
// functionality
var textEditors = ServiceProvider.GetServices<ITextEditor>();
@ -716,6 +727,9 @@
settings = SettingService.SetSetting(settings, "SMTPEnabled", _smtpenabled, true);
settings = SettingService.SetSetting(settings, "SiteGuid", _siteguid, true);
settings = SettingService.SetSetting(settings, "NotificationRetention", _retention.ToString(), true);
//cookie consent
settings = SettingService.SetSetting(settings, "CookieConsent", _cookieconsent);
// functionality
settings = SettingService.SetSetting(settings, "TextEditor", _textEditor);

View File

@ -426,4 +426,10 @@
<data name="System" xml:space="preserve">
<value>System</value>
</data>
<data name="CookieConsent.HelpText" xml:space="preserve">
<value>Specify if cookie consent is enabled on this site</value>
</data>
<data name="CookieConsent.Text" xml:space="preserve">
<value>Cookie Consent:</value>
</data>
</root>

View File

@ -147,10 +147,4 @@
<data name="Site" xml:space="preserve">
<value>Site</value>
</data>
<data name="DisplayCookieConsent.HelpText" xml:space="preserve">
<value>Specify whether display the cookie consent bar.</value>
</data>
<data name="DisplayCookieConsent.Text" xml:space="preserve">
<value>Display Cookie Consent?</value>
</data>
</root>

View File

@ -26,7 +26,7 @@
<div class="container">
<div class="row px-4">
<Pane Name="@PaneNames.Admin" />
<CookieConsent Enabled="true" />
<CookieConsent />
</div>
</div>
</div>

View File

@ -1,10 +1,11 @@
@namespace Oqtane.Themes.Controls
@inherits ThemeControlBase
@inject ISettingService SettingService
@inject ICookieConsentService CookieConsentService
@inject IJSRuntime JSRuntime
@inject IStringLocalizer<CookieConsent> Localizer
@if (Enabled && showBanner)
@if (_enabled && !Hidden && showBanner)
{
<form method="post" @formname="CookieConsentForm" @onsubmit="async () => await AcceptPolicy()" data-enhance>
<input type="hidden" name="@Constants.RequestVerificationToken" value="@SiteState.AntiForgeryToken" />
@ -27,9 +28,10 @@
}
@code {
private bool showBanner;
private bool _enabled;
[Parameter]
public bool Enabled { get; set; }
public bool Hidden { get; set; }
[Parameter]
public bool ShowPrivacyLink { get; set; } = true;
@ -37,6 +39,7 @@
protected override async Task OnInitializedAsync()
{
showBanner = !(await CookieConsentService.CanTrackAsync());
_enabled = bool.Parse(SettingService.GetSetting(PageState.Site.Settings, "CookieConsent", "False"));
}
private async Task AcceptPolicy()

View File

@ -107,7 +107,7 @@
{
<Pane Name="Footer" />
}
<CookieConsent Enabled="@_displayCookieConsent" />
<CookieConsent />
</div>
</main>
@ -119,7 +119,6 @@
private bool _login = true;
private bool _register = true;
private bool _footer = false;
private bool _displayCookieConsent = false;
protected override void OnParametersSet()
{
@ -129,7 +128,6 @@
_login = bool.Parse(SettingService.GetSetting(settings, GetType().Namespace + ":Login", "true"));
_register = bool.Parse(SettingService.GetSetting(settings, GetType().Namespace + ":Register", "true"));
_footer = bool.Parse(SettingService.GetSetting(settings, GetType().Namespace + ":Footer", "false"));
_displayCookieConsent = bool.Parse(SettingService.GetSetting(settings, GetType().Namespace + ":DisplayCookieConsent", "false"));
}
catch
{

View File

@ -49,16 +49,6 @@
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="displayCookieConsent" ResourceKey="DisplayCookieConsent" ResourceType="@resourceType" HelpText="Specify whether display the cookie consent bar.">Display Cookie Consent?</Label>
<div class="col-sm-9">
<select id="footer" class="form-select" @bind="@_displayCookieConsent">
<option value="-">&lt;@SharedLocalizer["Not Specified"]&gt;</option>
<option value="true">@SharedLocalizer["Yes"]</option>
<option value="false">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
</div>
@code {
@ -68,7 +58,6 @@
private string _login = "-";
private string _register = "-";
private string _footer = "-";
private string _displayCookieConsent = "-";
protected override async Task OnInitializedAsync()
{
@ -96,7 +85,6 @@
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "true");
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "true");
_footer = SettingService.GetSetting(settings, GetType().Namespace + ":Footer", "false");
_displayCookieConsent = SettingService.GetSetting(settings, GetType().Namespace + ":DisplayCookieConsent", "false");
}
else
{
@ -105,7 +93,6 @@
_login = SettingService.GetSetting(settings, GetType().Namespace + ":Login", "-");
_register = SettingService.GetSetting(settings, GetType().Namespace + ":Register", "-");
_footer = SettingService.GetSetting(settings, GetType().Namespace + ":Footer", "-");
_displayCookieConsent = SettingService.GetSetting(settings, GetType().Namespace + ":DisplayCookieConsent", "-");
}
await Task.Yield();
}
@ -144,11 +131,6 @@
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer);
}
if (_displayCookieConsent != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":DisplayCookieConsent", _displayCookieConsent);
}
await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
}
else
@ -166,10 +148,6 @@
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":Footer", _footer);
}
if (_displayCookieConsent != "-")
{
settings = SettingService.SetSetting(settings, GetType().Namespace + ":DisplayCookieConsent", _displayCookieConsent);
}
await SettingService.UpdatePageSettingsAsync(settings, pageId);
}
}

View File

@ -56,5 +56,7 @@ namespace Oqtane.Extensions
public static IApplicationBuilder UseExceptionMiddleWare(this IApplicationBuilder builder)
=> builder.UseMiddleware<ExceptionMiddleware>();
public static IApplicationBuilder UseCookieConsent(this IApplicationBuilder builder)
=> builder.UseMiddleware<CookieConsentMiddleware>();
}
}

View File

@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Oqtane.Services;
using Oqtane.Shared;
namespace Oqtane.Infrastructure
{
internal class CookieConsentMiddleware
{
private readonly IList<string> _defaultEssentialCookies = new List<string>
{
".AspNetCore.Culture",
"X-XSRF-TOKEN-COOKIE",
".AspNetCore.Identity.Application"
};
private readonly RequestDelegate _next;
public CookieConsentMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// check if framework is installed
var config = context.RequestServices.GetService(typeof(IConfigManager)) as IConfigManager;
var settingService = context.RequestServices.GetService(typeof(ISettingService)) as ISettingService;
var cookieConsentService = context.RequestServices.GetService(typeof(ICookieConsentService)) as ICookieConsentService;
string path = context.Request.Path.ToString();
if (config.IsInstalled())
{
try
{
var settings = (Dictionary<string, string>)context.Items[Constants.HttpContextSiteSettingsKey];
if (settings != null)
{
var cookieConsentEnabled = bool.Parse(settingService.GetSetting(settings, "CookieConsent", "False"));
if (cookieConsentEnabled && !await cookieConsentService.CanTrackAsync())
{
//only allow essential cookies when consent is not granted
var loginCookieName = settingService.GetSetting(settings, "LoginOptions:CookieName", ".AspNetCore.Identity.Application");
var cookiesSetting = settingService.GetSetting(settings, "EssentialCookies", string.Empty);
var essentialCookies = !string.IsNullOrEmpty(cookiesSetting) ? cookiesSetting.Split(",").ToList() : _defaultEssentialCookies;
foreach (var cookie in context.Request.Cookies)
{
if (cookie.Key != loginCookieName && !essentialCookies.Contains(cookie.Key))
{
context.Response.Cookies.Delete(cookie.Key);
}
}
}
}
}
catch(Exception ex)
{
}
}
// continue processing
if (_next != null) await _next(context);
}
}
}

View File

@ -233,6 +233,7 @@ namespace Oqtane
app.UseAuthorization();
app.UseAntiforgery();
app.UseCookiePolicy();
app.UseCookieConsent();
if (_useSwagger)
{