diff --git a/Oqtane.Client/Modules/Admin/Site/Index.razor b/Oqtane.Client/Modules/Admin/Site/Index.razor index c23f9732..b034ae76 100644 --- a/Oqtane.Client/Modules/Admin/Site/Index.razor +++ b/Oqtane.Client/Modules/Admin/Site/Index.razor @@ -126,6 +126,15 @@ +
+ +
+ +
+
@@ -415,6 +424,7 @@ private string _themetype = ""; private string _containertype = ""; private string _admincontainertype = ""; + private string _cookieconsent = "False"; private Dictionary _textEditors = new Dictionary(); 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(); @@ -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); diff --git a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx index 0551fb8f..3e371f76 100644 --- a/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx +++ b/Oqtane.Client/Resources/Modules/Admin/Site/Index.resx @@ -426,4 +426,10 @@ System + + Specify if cookie consent is enabled on this site + + + Cookie Consent: + \ No newline at end of file diff --git a/Oqtane.Client/Resources/Themes/OqtaneTheme/ThemeSettings.resx b/Oqtane.Client/Resources/Themes/OqtaneTheme/ThemeSettings.resx index ec0c9bbb..fce3db5d 100644 --- a/Oqtane.Client/Resources/Themes/OqtaneTheme/ThemeSettings.resx +++ b/Oqtane.Client/Resources/Themes/OqtaneTheme/ThemeSettings.resx @@ -147,10 +147,4 @@ Site - - Specify whether display the cookie consent bar. - - - Display Cookie Consent? - \ No newline at end of file diff --git a/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor b/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor index 084dfc95..0dcf974a 100644 --- a/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor +++ b/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor @@ -26,7 +26,7 @@
- +
diff --git a/Oqtane.Client/Themes/Controls/Theme/CookieConsent.razor b/Oqtane.Client/Themes/Controls/Theme/CookieConsent.razor index 0138cc4d..40e0f643 100644 --- a/Oqtane.Client/Themes/Controls/Theme/CookieConsent.razor +++ b/Oqtane.Client/Themes/Controls/Theme/CookieConsent.razor @@ -1,10 +1,11 @@ @namespace Oqtane.Themes.Controls @inherits ThemeControlBase +@inject ISettingService SettingService @inject ICookieConsentService CookieConsentService @inject IJSRuntime JSRuntime @inject IStringLocalizer Localizer -@if (Enabled && showBanner) +@if (_enabled && !Hidden && showBanner) {
@@ -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() diff --git a/Oqtane.Client/Themes/OqtaneTheme/Themes/Default.razor b/Oqtane.Client/Themes/OqtaneTheme/Themes/Default.razor index 3d4cf265..5032499a 100644 --- a/Oqtane.Client/Themes/OqtaneTheme/Themes/Default.razor +++ b/Oqtane.Client/Themes/OqtaneTheme/Themes/Default.razor @@ -107,7 +107,7 @@ { } - + @@ -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 { diff --git a/Oqtane.Client/Themes/OqtaneTheme/Themes/ThemeSettings.razor b/Oqtane.Client/Themes/OqtaneTheme/Themes/ThemeSettings.razor index ecb9fe79..c30d4e88 100644 --- a/Oqtane.Client/Themes/OqtaneTheme/Themes/ThemeSettings.razor +++ b/Oqtane.Client/Themes/OqtaneTheme/Themes/ThemeSettings.razor @@ -49,16 +49,6 @@ -
- -
- -
-
@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); } } diff --git a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs index 4225f0b8..355c23a2 100644 --- a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs @@ -56,5 +56,7 @@ namespace Oqtane.Extensions public static IApplicationBuilder UseExceptionMiddleWare(this IApplicationBuilder builder) => builder.UseMiddleware(); + public static IApplicationBuilder UseCookieConsent(this IApplicationBuilder builder) + => builder.UseMiddleware(); } } diff --git a/Oqtane.Server/Infrastructure/Middleware/CookieConsentMiddleware.cs b/Oqtane.Server/Infrastructure/Middleware/CookieConsentMiddleware.cs new file mode 100644 index 00000000..5e784e6d --- /dev/null +++ b/Oqtane.Server/Infrastructure/Middleware/CookieConsentMiddleware.cs @@ -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 _defaultEssentialCookies = new List + { + ".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)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); + } + } +} diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs index b2ad5487..baa320de 100644 --- a/Oqtane.Server/Startup.cs +++ b/Oqtane.Server/Startup.cs @@ -233,6 +233,7 @@ namespace Oqtane app.UseAuthorization(); app.UseAntiforgery(); app.UseCookiePolicy(); + app.UseCookieConsent(); if (_useSwagger) {