From 495e3cecb64751bf726292f68b3bdeaf675b9cec Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 14:20:59 +0200 Subject: [PATCH 01/22] Adding new project --- .../License.md | 15 +++++ ...iq.Hosting.Tenants.SearchBotBlocker.csproj | 54 ++++++++++++++++++ .../Manifest.cs | 18 ++++++ .../NuGetIcon.png | Bin 0 -> 4657 bytes .../Readme.md | 1 + .../Startup.cs | 22 +++++++ 6 files changed, 110 insertions(+) create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/License.md create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/Lombiq.Hosting.Tenants.SearchBotBlocker.csproj create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/NuGetIcon.png create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/License.md b/Lombiq.Hosting.Tenants.SearchBotBlocker/License.md new file mode 100644 index 00000000..d3963d62 --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/License.md @@ -0,0 +1,15 @@ +Copyright © 2022, [Lombiq Technologies Ltd.](https://lombiq.com) + +All rights reserved. + +For more information and requests about licensing please [contact us through our website](https://lombiq.com/contact-us). + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +- Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Lombiq.Hosting.Tenants.SearchBotBlocker.csproj b/Lombiq.Hosting.Tenants.SearchBotBlocker/Lombiq.Hosting.Tenants.SearchBotBlocker.csproj new file mode 100644 index 00000000..3d77f4b5 --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Lombiq.Hosting.Tenants.SearchBotBlocker.csproj @@ -0,0 +1,54 @@ + + + + net6.0 + true + $(DefaultItemExcludes);.git*;node_modules\** + + + + Lombiq Hosting - Tenants SearchBotBlocker for Orchard Core + Lombiq Technologies + Copyright © 2022, Lombiq Technologies Ltd. + SearchBotBlockerModule for Orchard Core: This module contains the SearchBotBlocker feature, which prevents search bots from indexing non-production environments by adding a noindex, nofollow meta tag. + NuGetIcon.png + OrchardCore;Lombiq;AspNetCore;Multitenancy;SaaS + https://github.com/Lombiq/Hosting-Tenants + https://github.com/Lombiq/Hosting-Tenants/blob/dev/Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md + License.md + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs new file mode 100644 index 00000000..f1e62efa --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs @@ -0,0 +1,18 @@ +using Lombiq.Hosting.Tenants.FeaturesGuard.Constants; +using OrchardCore.Modules.Manifest; + +[assembly: Module( + Name = "Lombiq Hosting - Tenants - Search Bot Blocker", + Author = "Lombiq Technologies", + Website = "https://github.com/Lombiq/Hosting-Tenants", + Version = "0.0.1", + Description = "Prevents search bots from indexing non-production environments by adding a noindex, nofollow meta tag.", + Category = "Hosting" +)] + +[assembly: Feature( + Id = FeatureNames.SearchBotBlocker, + Name = "Lombiq Hosting - Tenants - Search Bot Blocker", + Category = "Hosting", + IsAlwaysEnabled = true +)] diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/NuGetIcon.png b/Lombiq.Hosting.Tenants.SearchBotBlocker/NuGetIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..162a00508d8041833604d427216238c1b23b2d47 GIT binary patch literal 4657 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 literal 0 HcmV?d00001 diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md b/Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md new file mode 100644 index 00000000..87dbe128 --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md @@ -0,0 +1 @@ +# Lombiq Hosting - Tenants Search Bot Blocker for Orchard Core diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs new file mode 100644 index 00000000..da9c3d61 --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs @@ -0,0 +1,22 @@ +using Lombiq.Hosting.Tenants.SearchBotBlocker.Constants; +using Lombiq.Hosting.Tenants.SearchBotBlocker.Middlewares; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.Configuration; +using OrchardCore.Environment.Shell.Configuration; +using OrchardCore.Modules; +using System; + +namespace Lombiq.Hosting.Tenants.FeaturesGuard; + +[Feature(FeatureNames.SearchBotBlocker)] +public class Startup : StartupBase +{ + private readonly IShellConfiguration _shellConfiguration; + + public Startup(IConfiguration configuration, IShellConfiguration shellConfiguration) => + _shellConfiguration = shellConfiguration; + + public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) => + app.UseMiddleware(); +} From 3bd4cc8e511d79196bb47bc47e0034e35725127b Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 15:36:55 +0200 Subject: [PATCH 02/22] Adding the middleware --- .../Constants/FeatureNames.cs | 10 +++++ .../Manifest.cs | 2 +- .../Middlewares/SearchBotBlockerMiddleware.cs | 37 +++++++++++++++++++ .../Models/SearchBotBlockerOptions.cs | 16 ++++++++ 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/Constants/FeatureNames.cs create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs create mode 100644 Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Constants/FeatureNames.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Constants/FeatureNames.cs new file mode 100644 index 00000000..a67d5bcd --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Constants/FeatureNames.cs @@ -0,0 +1,10 @@ +namespace Lombiq.Hosting.Tenants.SearchBotBlocker.Constants; + +public static class FeatureNames +{ + public const string Module = "Lombiq.Hosting"; + + public const string Tenants = Module + "." + nameof(Tenants); + + public const string SearchBotBlocker = Tenants + "." + nameof(SearchBotBlocker); +} diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs index f1e62efa..278816d4 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs @@ -1,4 +1,4 @@ -using Lombiq.Hosting.Tenants.FeaturesGuard.Constants; +using Lombiq.Hosting.Tenants.SearchBotBlocker.Constants; using OrchardCore.Modules.Manifest; [assembly: Module( diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs new file mode 100644 index 00000000..b1753e44 --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs @@ -0,0 +1,37 @@ +using Lombiq.Hosting.Tenants.SearchBotBlocker.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using System.Threading.Tasks; + +namespace Lombiq.Hosting.Tenants.SearchBotBlocker.Middlewares; + +public class SearchBotBlockerMiddleware +{ + private readonly RequestDelegate _next; + private readonly IHostEnvironment _hostEnvironment; + private readonly IOptions _options; + + public SearchBotBlockerMiddleware( + RequestDelegate next, + IHostEnvironment hostEnvironment, + IOptions options) + { + _next = next; + _hostEnvironment = hostEnvironment; + _options = options; + } + + public Task InvokeAsync(HttpContext context) + { + bool isProduction = _options.Value.IsProduction ?? _hostEnvironment.IsProduction(); + + if (!isProduction) + { + context.Response.Headers.Add("X-Robots-Tag", "noindex, nofollow"); + } + + return _next(context); + } +} diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs new file mode 100644 index 00000000..ddce100d --- /dev/null +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs @@ -0,0 +1,16 @@ +using Microsoft.Extensions.Hosting; + +namespace Lombiq.Hosting.Tenants.SearchBotBlocker.Models; + +/// +/// Further configuration options for the module. +/// +public class SearchBotBlockerOptions +{ + /// + /// Gets or sets a value indicating whether to add a noindex, nofollow meta tag when the app is not running in a + /// production environment. It adds the tags when is . When set to + /// it overrides 's result. + /// + public bool? IsProduction { get; set; } +} From 6d60184b3778d8a76545831f3fb906b42000d1fa Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 15:41:31 +0200 Subject: [PATCH 03/22] Refactoring middleware and Startup.cs --- .../Middlewares/SearchBotBlockerMiddleware.cs | 9 +++++++-- Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs | 13 ++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs index b1753e44..a9d52a26 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs @@ -25,9 +25,14 @@ public SearchBotBlockerMiddleware( public Task InvokeAsync(HttpContext context) { - bool isProduction = _options.Value.IsProduction ?? _hostEnvironment.IsProduction(); + bool? isProduction = _options.Value.IsProduction; - if (!isProduction) + if (!isProduction.HasValue) + { + isProduction = _hostEnvironment.IsProduction(); + } + + if (!isProduction.Value) { context.Response.Headers.Add("X-Robots-Tag", "noindex, nofollow"); } diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs index da9c3d61..896dcbdb 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs @@ -1,8 +1,10 @@ using Lombiq.Hosting.Tenants.SearchBotBlocker.Constants; using Lombiq.Hosting.Tenants.SearchBotBlocker.Middlewares; +using Lombiq.Hosting.Tenants.SearchBotBlocker.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using OrchardCore.Environment.Shell.Configuration; using OrchardCore.Modules; using System; @@ -14,9 +16,18 @@ public class Startup : StartupBase { private readonly IShellConfiguration _shellConfiguration; - public Startup(IConfiguration configuration, IShellConfiguration shellConfiguration) => + public Startup(IShellConfiguration shellConfiguration) => _shellConfiguration = shellConfiguration; + public override void ConfigureServices(IServiceCollection services) + { + var options = new SearchBotBlockerOptions(); + var configSection = _shellConfiguration + .GetSection("Lombiq_Hosting_Tenants_SearchBotBlocker:SearchBotBlockerOptions"); + configSection.Bind(options); + services.Configure(configSection); + } + public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) => app.UseMiddleware(); } From 5faa718bce70e8869c7fc2307f97f9cada10683f Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 15:41:56 +0200 Subject: [PATCH 04/22] Simplifying middleware --- .../Middlewares/SearchBotBlockerMiddleware.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs b/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs index a9d52a26..b1753e44 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs +++ b/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs @@ -25,14 +25,9 @@ public SearchBotBlockerMiddleware( public Task InvokeAsync(HttpContext context) { - bool? isProduction = _options.Value.IsProduction; + bool isProduction = _options.Value.IsProduction ?? _hostEnvironment.IsProduction(); - if (!isProduction.HasValue) - { - isProduction = _hostEnvironment.IsProduction(); - } - - if (!isProduction.Value) + if (!isProduction) { context.Response.Headers.Add("X-Robots-Tag", "noindex, nofollow"); } From 6fb7e02ec75af8c7bf8c9a87d1740b3614acbcc8 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 16:58:07 +0200 Subject: [PATCH 05/22] Renaming module to EnvironmentRobots --- .../Constants/FeatureNames.cs | 4 ++-- .../License.md | 0 ...biq.Hosting.Tenants.EnvironmentRobots.csproj | 0 .../Manifest.cs | 8 ++++---- .../Middlewares/EnvironmentRobotsMiddleware.cs | 12 ++++++------ .../Models/EnvironmentRobotsOptions.cs | 4 ++-- .../NuGetIcon.png | Bin .../Readme.md | 0 .../Startup.cs | 16 ++++++++-------- 9 files changed, 22 insertions(+), 22 deletions(-) rename {Lombiq.Hosting.Tenants.SearchBotBlocker => Lombiq.Hosting.Tenants.EnvironmentRobots}/Constants/FeatureNames.cs (51%) rename {Lombiq.Hosting.Tenants.SearchBotBlocker => Lombiq.Hosting.Tenants.EnvironmentRobots}/License.md (100%) rename Lombiq.Hosting.Tenants.SearchBotBlocker/Lombiq.Hosting.Tenants.SearchBotBlocker.csproj => Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj (100%) rename {Lombiq.Hosting.Tenants.SearchBotBlocker => Lombiq.Hosting.Tenants.EnvironmentRobots}/Manifest.cs (64%) rename Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs => Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs (70%) rename Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs => Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs (84%) rename {Lombiq.Hosting.Tenants.SearchBotBlocker => Lombiq.Hosting.Tenants.EnvironmentRobots}/NuGetIcon.png (100%) rename {Lombiq.Hosting.Tenants.SearchBotBlocker => Lombiq.Hosting.Tenants.EnvironmentRobots}/Readme.md (100%) rename {Lombiq.Hosting.Tenants.SearchBotBlocker => Lombiq.Hosting.Tenants.EnvironmentRobots}/Startup.cs (62%) diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Constants/FeatureNames.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Constants/FeatureNames.cs similarity index 51% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/Constants/FeatureNames.cs rename to Lombiq.Hosting.Tenants.EnvironmentRobots/Constants/FeatureNames.cs index a67d5bcd..eb045d32 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Constants/FeatureNames.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Constants/FeatureNames.cs @@ -1,4 +1,4 @@ -namespace Lombiq.Hosting.Tenants.SearchBotBlocker.Constants; +namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Constants; public static class FeatureNames { @@ -6,5 +6,5 @@ public static class FeatureNames public const string Tenants = Module + "." + nameof(Tenants); - public const string SearchBotBlocker = Tenants + "." + nameof(SearchBotBlocker); + public const string EnvironmentRobots = Tenants + "." + nameof(EnvironmentRobots); } diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/License.md b/Lombiq.Hosting.Tenants.EnvironmentRobots/License.md similarity index 100% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/License.md rename to Lombiq.Hosting.Tenants.EnvironmentRobots/License.md diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Lombiq.Hosting.Tenants.SearchBotBlocker.csproj b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj similarity index 100% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/Lombiq.Hosting.Tenants.SearchBotBlocker.csproj rename to Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs similarity index 64% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs rename to Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs index 278816d4..25dd648b 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Manifest.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs @@ -1,8 +1,8 @@ -using Lombiq.Hosting.Tenants.SearchBotBlocker.Constants; +using Lombiq.Hosting.Tenants.EnvironmentRobots.Constants; using OrchardCore.Modules.Manifest; [assembly: Module( - Name = "Lombiq Hosting - Tenants - Search Bot Blocker", + Name = "Lombiq Hosting - Tenants - Environment Robots", Author = "Lombiq Technologies", Website = "https://github.com/Lombiq/Hosting-Tenants", Version = "0.0.1", @@ -11,8 +11,8 @@ )] [assembly: Feature( - Id = FeatureNames.SearchBotBlocker, - Name = "Lombiq Hosting - Tenants - Search Bot Blocker", + Id = FeatureNames.EnvironmentRobots, + Name = "Lombiq Hosting - Tenants - Environment Robots", Category = "Hosting", IsAlwaysEnabled = true )] diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs similarity index 70% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs rename to Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs index b1753e44..ef9c0c44 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Middlewares/SearchBotBlockerMiddleware.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs @@ -1,22 +1,22 @@ -using Lombiq.Hosting.Tenants.SearchBotBlocker.Models; +using Lombiq.Hosting.Tenants.EnvironmentRobots.Models; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using System.Threading.Tasks; -namespace Lombiq.Hosting.Tenants.SearchBotBlocker.Middlewares; +namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Middlewares; -public class SearchBotBlockerMiddleware +public class EnvironmentRobotsMiddleware { private readonly RequestDelegate _next; private readonly IHostEnvironment _hostEnvironment; - private readonly IOptions _options; + private readonly IOptions _options; - public SearchBotBlockerMiddleware( + public EnvironmentRobotsMiddleware( RequestDelegate next, IHostEnvironment hostEnvironment, - IOptions options) + IOptions options) { _next = next; _hostEnvironment = hostEnvironment; diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs similarity index 84% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs rename to Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs index ddce100d..330c6cf6 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Models/SearchBotBlockerOptions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs @@ -1,11 +1,11 @@ using Microsoft.Extensions.Hosting; -namespace Lombiq.Hosting.Tenants.SearchBotBlocker.Models; +namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Models; /// /// Further configuration options for the module. /// -public class SearchBotBlockerOptions +public class EnvironmentRobotsOptions { /// /// Gets or sets a value indicating whether to add a noindex, nofollow meta tag when the app is not running in a diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/NuGetIcon.png b/Lombiq.Hosting.Tenants.EnvironmentRobots/NuGetIcon.png similarity index 100% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/NuGetIcon.png rename to Lombiq.Hosting.Tenants.EnvironmentRobots/NuGetIcon.png diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md similarity index 100% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md rename to Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md diff --git a/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Startup.cs similarity index 62% rename from Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs rename to Lombiq.Hosting.Tenants.EnvironmentRobots/Startup.cs index 896dcbdb..a0b0bd66 100644 --- a/Lombiq.Hosting.Tenants.SearchBotBlocker/Startup.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Startup.cs @@ -1,6 +1,6 @@ -using Lombiq.Hosting.Tenants.SearchBotBlocker.Constants; -using Lombiq.Hosting.Tenants.SearchBotBlocker.Middlewares; -using Lombiq.Hosting.Tenants.SearchBotBlocker.Models; +using Lombiq.Hosting.Tenants.EnvironmentRobots.Constants; +using Lombiq.Hosting.Tenants.EnvironmentRobots.Middlewares; +using Lombiq.Hosting.Tenants.EnvironmentRobots.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.Configuration; @@ -11,7 +11,7 @@ namespace Lombiq.Hosting.Tenants.FeaturesGuard; -[Feature(FeatureNames.SearchBotBlocker)] +[Feature(FeatureNames.EnvironmentRobots)] public class Startup : StartupBase { private readonly IShellConfiguration _shellConfiguration; @@ -21,13 +21,13 @@ public Startup(IShellConfiguration shellConfiguration) => public override void ConfigureServices(IServiceCollection services) { - var options = new SearchBotBlockerOptions(); + var options = new EnvironmentRobotsOptions(); var configSection = _shellConfiguration - .GetSection("Lombiq_Hosting_Tenants_SearchBotBlocker:SearchBotBlockerOptions"); + .GetSection("Lombiq_Hosting_Tenants_EnvironmentRobots:EnvironmentRobotsOptions"); configSection.Bind(options); - services.Configure(configSection); + services.Configure(configSection); } public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) => - app.UseMiddleware(); + app.UseMiddleware(); } From 4807ebb90b79b7bcf2005c41eb5d5d55bb22d3fd Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 18:10:02 +0200 Subject: [PATCH 06/22] Refactoring module by also adding meta filter --- ...tEnvironmentEnvironmentRobotsExtensions.cs | 12 ++++++ .../Filters/EnvironmentRobotsMetaTagFilter.cs | 43 +++++++++++++++++++ ...q.Hosting.Tenants.EnvironmentRobots.csproj | 21 ++------- .../EnvironmentRobotsMiddleware.cs | 6 +-- .../Models/EnvironmentRobotsOptions.cs | 4 +- .../Startup.cs | 5 ++- 6 files changed, 67 insertions(+), 24 deletions(-) create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs new file mode 100644 index 00000000..2ccba517 --- /dev/null +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs @@ -0,0 +1,12 @@ +using Lombiq.Hosting.Tenants.EnvironmentRobots.Models; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; + +namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Extensions; +public static class IHostEnvironmentEnvironmentRobotsExtensions +{ + public static bool IsProductionWithConfiguration( + this IHostEnvironment hostEnvironment, + IOptions options) => + options.Value.IsProduction ?? hostEnvironment.IsProduction(); +} diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs new file mode 100644 index 00000000..42141617 --- /dev/null +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs @@ -0,0 +1,43 @@ +using Lombiq.Hosting.Tenants.EnvironmentRobots.Extensions; +using Lombiq.Hosting.Tenants.EnvironmentRobots.Models; +using Microsoft.AspNetCore.Mvc.Filters; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Options; +using OrchardCore.ResourceManagement; + +namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Filters; + +public class EnvironmentRobotsMetaTagFilter : IResultFilter +{ + private readonly IHostEnvironment _hostEnvironment; + private readonly IOptions _options; + private readonly IResourceManager _resourceManager; + + public EnvironmentRobotsMetaTagFilter( + IHostEnvironment hostEnvironment, + IOptions options, + IResourceManager resourceManager) + { + _hostEnvironment = hostEnvironment; + _options = options; + _resourceManager = resourceManager; + } + + public void OnResultExecuting(ResultExecutingContext context) + { + if (!_hostEnvironment.IsProductionWithConfiguration(_options)) + { + _resourceManager.RegisterMeta(new MetaEntry + { + Name = "robots", + Content = "noindex, nofollow", + }); + } + } + + public void OnResultExecuted(ResultExecutedContext context) + { + // Intentionally left empty, we don't need the function, but we need to add it because of the interface + // implementation. + } +} diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj index 3d77f4b5..43eb3c3a 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj @@ -7,14 +7,14 @@ - Lombiq Hosting - Tenants SearchBotBlocker for Orchard Core + Lombiq Hosting - Tenants EnvironmentRobots for Orchard Core Lombiq Technologies Copyright © 2022, Lombiq Technologies Ltd. - SearchBotBlockerModule for Orchard Core: This module contains the SearchBotBlocker feature, which prevents search bots from indexing non-production environments by adding a noindex, nofollow meta tag. + EnvironmentRobots for Orchard Core: This module contains the EnvironmentRobots feature, which prevents search bots from indexing non-production environments by adding a noindex, nofollow meta tag. NuGetIcon.png OrchardCore;Lombiq;AspNetCore;Multitenancy;SaaS https://github.com/Lombiq/Hosting-Tenants - https://github.com/Lombiq/Hosting-Tenants/blob/dev/Lombiq.Hosting.Tenants.SearchBotBlocker/Readme.md + https://github.com/Lombiq/Hosting-Tenants/blob/dev/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md License.md @@ -36,19 +36,6 @@ - - - + - - - - - - - - - - - diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs index ef9c0c44..85605523 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs @@ -1,6 +1,6 @@ +using Lombiq.Hosting.Tenants.EnvironmentRobots.Extensions; using Lombiq.Hosting.Tenants.EnvironmentRobots.Models; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using System.Threading.Tasks; @@ -25,9 +25,7 @@ public EnvironmentRobotsMiddleware( public Task InvokeAsync(HttpContext context) { - bool isProduction = _options.Value.IsProduction ?? _hostEnvironment.IsProduction(); - - if (!isProduction) + if (!_hostEnvironment.IsProductionWithConfiguration(_options)) { context.Response.Headers.Add("X-Robots-Tag", "noindex, nofollow"); } diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs index 330c6cf6..8c2e0eb9 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs @@ -9,8 +9,8 @@ public class EnvironmentRobotsOptions { /// /// Gets or sets a value indicating whether to add a noindex, nofollow meta tag when the app is not running in a - /// production environment. It adds the tags when is . When set to - /// it overrides 's result. + /// production environment. It adds the tags when is . When set + /// it overrides 's result. /// public bool? IsProduction { get; set; } } diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Startup.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Startup.cs index a0b0bd66..d978e6e7 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Startup.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Startup.cs @@ -1,4 +1,5 @@ using Lombiq.Hosting.Tenants.EnvironmentRobots.Constants; +using Lombiq.Hosting.Tenants.EnvironmentRobots.Filters; using Lombiq.Hosting.Tenants.EnvironmentRobots.Middlewares; using Lombiq.Hosting.Tenants.EnvironmentRobots.Models; using Microsoft.AspNetCore.Builder; @@ -9,7 +10,7 @@ using OrchardCore.Modules; using System; -namespace Lombiq.Hosting.Tenants.FeaturesGuard; +namespace Lombiq.Hosting.Tenants.EnvironmentRobots; [Feature(FeatureNames.EnvironmentRobots)] public class Startup : StartupBase @@ -26,6 +27,8 @@ public override void ConfigureServices(IServiceCollection services) .GetSection("Lombiq_Hosting_Tenants_EnvironmentRobots:EnvironmentRobotsOptions"); configSection.Bind(options); services.Configure(configSection); + + services.AddMvc(options => options.Filters.Add(typeof(EnvironmentRobotsMetaTagFilter))); } public override void Configure(IApplicationBuilder app, IEndpointRouteBuilder routes, IServiceProvider serviceProvider) => From bc76da6199fc57d2c7847e3446348fe2308f7796 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 18:10:14 +0200 Subject: [PATCH 07/22] Adding Readme.md --- .../Readme.md | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md index 87dbe128..12ec7f12 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md @@ -1 +1,33 @@ -# Lombiq Hosting - Tenants Search Bot Blocker for Orchard Core +# Lombiq Hosting - Tenants Environment Robots for Orchard Core + +[![Lombiq.Hosting.Tenants.EnvironmentRobots NuGet](https://img.shields.io/nuget/v/Lombiq.Hosting.Tenants.EnvironmentRobots?label=Lombiq.Hosting.Tenants.EnvironmentRobots)](https://www.nuget.org/packages/Lombiq.Hosting.Tenants.EnvironmentRobots/) + +## About + +A module that prevents search bots from indexing non-production environments. + +## Documentation + +This module contains the feature below. + +### `Lombiq.Hosting.Tenants.EnvironmentRobots` + +The module works by adding a `X-Robots-Tag` header with the value `noindex`, `nofollow` to the HTTP response of non-production tenants. This instructs search engines not to index or follow the links on these pages. Additionally, the module also adds a `` tag to the HTML head of non-production tenants for the same purpose. + +The module determines whether a tenant is non-production based on the `IsProduction` option in the `EnvironmentRobotsOptions` class. By default, this option is set to `null`, which means the module will use the `IHostEnvironment.IsProduction()` method to check the environment name. However, you can override this option for each tenant by setting it to `true` or `false` in the `appsettings.json` file under the `Lombiq_Hosting_Tenants_EnvironmentRobots:EnvironmentRobotsOptions:IsProduction` section as follows: +```json +"OrchardCore": { + "Lombiq_Hosting_Tenants_EnvironmentRobots": { + "EnvironmentRobotsOptions": { + "IsProduction": true + } + } +} +``` + +To use the module, follow these steps: + +- Enable the `Lombiq.Hosting.Tenants.EnvironmentRobots` feature from the admin dashboard. +- Optionally, configure the `IsProduction` option for each tenant as described above. + + From bf9bf8ad8d154ed91790a198f547e08e388244c2 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 18:19:47 +0200 Subject: [PATCH 08/22] Updating Readme --- Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md index 12ec7f12..e07d97d3 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md @@ -12,9 +12,9 @@ This module contains the feature below. ### `Lombiq.Hosting.Tenants.EnvironmentRobots` -The module works by adding a `X-Robots-Tag` header with the value `noindex`, `nofollow` to the HTTP response of non-production tenants. This instructs search engines not to index or follow the links on these pages. Additionally, the module also adds a `` tag to the HTML head of non-production tenants for the same purpose. +The module works by adding a `X-Robots-Tag` header with the value `noindex`, `nofollow` to the HTTP response of non-production apps. This instructs search engines not to index or follow the links on these pages. Additionally, the module also adds a `` tag to the HTML head of non-production apps for the same purpose. -The module determines whether a tenant is non-production based on the `IsProduction` option in the `EnvironmentRobotsOptions` class. By default, this option is set to `null`, which means the module will use the `IHostEnvironment.IsProduction()` method to check the environment name. However, you can override this option for each tenant by setting it to `true` or `false` in the `appsettings.json` file under the `Lombiq_Hosting_Tenants_EnvironmentRobots:EnvironmentRobotsOptions:IsProduction` section as follows: +The module determines whether a app is non-production based on the `IsProduction` option in the `EnvironmentRobotsOptions` class. By default, this option is set to `null`, which means the module will use the `IHostEnvironment.IsProduction()` method to check the environment name. However, you can override this option by setting it to `true` or `false` in the `appsettings.json` file under the `Lombiq_Hosting_Tenants_EnvironmentRobots:EnvironmentRobotsOptions:IsProduction` section as follows: ```json "OrchardCore": { "Lombiq_Hosting_Tenants_EnvironmentRobots": { From 782b3040c1b95fd285f24f288758a85a55db17ff Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 18:32:02 +0200 Subject: [PATCH 09/22] Fixing Readme errors --- Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md index e07d97d3..9e02b511 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md @@ -15,6 +15,7 @@ This module contains the feature below. The module works by adding a `X-Robots-Tag` header with the value `noindex`, `nofollow` to the HTTP response of non-production apps. This instructs search engines not to index or follow the links on these pages. Additionally, the module also adds a `` tag to the HTML head of non-production apps for the same purpose. The module determines whether a app is non-production based on the `IsProduction` option in the `EnvironmentRobotsOptions` class. By default, this option is set to `null`, which means the module will use the `IHostEnvironment.IsProduction()` method to check the environment name. However, you can override this option by setting it to `true` or `false` in the `appsettings.json` file under the `Lombiq_Hosting_Tenants_EnvironmentRobots:EnvironmentRobotsOptions:IsProduction` section as follows: + ```json "OrchardCore": { "Lombiq_Hosting_Tenants_EnvironmentRobots": { @@ -29,5 +30,3 @@ To use the module, follow these steps: - Enable the `Lombiq.Hosting.Tenants.EnvironmentRobots` feature from the admin dashboard. - Optionally, configure the `IsProduction` option for each tenant as described above. - - From f0c589180fd4b36ecbf442d6b1a8dd47b2347781 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Thu, 18 May 2023 18:48:12 +0200 Subject: [PATCH 10/22] Tweaking documentation --- .../Lombiq.Hosting.Tenants.EnvironmentRobots.csproj | 2 +- .../Models/EnvironmentRobotsOptions.cs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj index 43eb3c3a..6d029f0f 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj @@ -10,7 +10,7 @@ Lombiq Hosting - Tenants EnvironmentRobots for Orchard Core Lombiq Technologies Copyright © 2022, Lombiq Technologies Ltd. - EnvironmentRobots for Orchard Core: This module contains the EnvironmentRobots feature, which prevents search bots from indexing non-production environments by adding a noindex, nofollow meta tag. + EnvironmentRobots for Orchard Core: This module contains the EnvironmentRobots feature, which prevents search bots from indexing non-production environments by adding a meta tag and a respone header with noindex, nofollow values. NuGetIcon.png OrchardCore;Lombiq;AspNetCore;Multitenancy;SaaS https://github.com/Lombiq/Hosting-Tenants diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs index 8c2e0eb9..0195a6e7 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Models/EnvironmentRobotsOptions.cs @@ -8,9 +8,10 @@ namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Models; public class EnvironmentRobotsOptions { /// - /// Gets or sets a value indicating whether to add a noindex, nofollow meta tag when the app is not running in a - /// production environment. It adds the tags when is . When set - /// it overrides 's result. + /// Gets or sets a value indicating whether to add a meta tag and response header with noindex, nofollow values when + /// the app is not running in a production environment. It adds the tags when is . When set it overrides 's result, + /// which the module is using by default. /// public bool? IsProduction { get; set; } } From e77e942be0b34cd25ecaf95895713676597e662a Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Fri, 19 May 2023 19:45:41 +0200 Subject: [PATCH 11/22] Adding EnvironmentRobots Test project --- .../License.md | 13 +++++++ ....Tenants.EnvironmentRobots.Tests.UI.csproj | 33 ++++++++++++++++++ .../NuGetIcon.png | Bin 0 -> 4657 bytes .../Readme.md | 7 ++++ ...q.Hosting.Tenants.EnvironmentRobots.csproj | 2 +- 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/License.md create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/NuGetIcon.png create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/License.md b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/License.md new file mode 100644 index 00000000..d57e1305 --- /dev/null +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/License.md @@ -0,0 +1,13 @@ +Copyright © 2021, [Lombiq Technologies Ltd.](https://lombiq.com) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +- Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj new file mode 100644 index 00000000..3beb960b --- /dev/null +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj @@ -0,0 +1,33 @@ + + + + net6.0 + + + + Lombiq Hosting - Tenants EnvironmentRobots for Orchard Core - UI Test Extensions + Lombiq Technologies + Copyright © 2023, Lombiq Technologies Ltd. + Extension methods that test various features in Lombiq Hosting - Tenants EnvironmentRobots, with the help of Lombiq UI Testing Toolbox for Orchard Core. See the project website for detailed documentation. + NuGetIcon.png + OrchardCore;Lombiq;AspNetCore;Multitenancy;SaaS + https://github.com/Lombiq/Hosting-Tenants + https://github.com/Lombiq/Hosting-Tenants/blob/dev/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Readme.md + License.md + + + + + + + + + + + + + + + + + diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/NuGetIcon.png b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/NuGetIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..162a00508d8041833604d427216238c1b23b2d47 GIT binary patch literal 4657 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 literal 0 HcmV?d00001 diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md new file mode 100644 index 00000000..4c2c6dca --- /dev/null +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md @@ -0,0 +1,7 @@ +# Lombiq Hosting - Tenants EnvironmentRobots for Orchard Core - UI Test Extensions + +## About + +Extension methods that tests features in Lombiq Hosting - Tenants EnvironmentRobots, with the help of [Lombiq UI Testing Toolbox for Orchard Core](https://github.com/Lombiq/UI-Testing-Toolbox). + +Call these from a UI test project to verify the module's basic features; as seen in [Open-Source Orchard Core Extensions](https://github.com/Lombiq/Open-Source-Orchard-Core-Extensions). diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj index 6d029f0f..11077891 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj @@ -9,7 +9,7 @@ Lombiq Hosting - Tenants EnvironmentRobots for Orchard Core Lombiq Technologies - Copyright © 2022, Lombiq Technologies Ltd. + Copyright © 2023, Lombiq Technologies Ltd. EnvironmentRobots for Orchard Core: This module contains the EnvironmentRobots feature, which prevents search bots from indexing non-production environments by adding a meta tag and a respone header with noindex, nofollow values. NuGetIcon.png OrchardCore;Lombiq;AspNetCore;Multitenancy;SaaS From ee378b1225d09baaf4915cd01513e2b2b676bdc3 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Fri, 19 May 2023 19:45:57 +0200 Subject: [PATCH 12/22] Adding TestCaseUITestContextExtensions and ConfigurationExtensions --- .../Extensions/ConfigurationExtensions.cs | 21 ++++++++++ .../TestCaseUITestContextExtensions.cs | 41 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/ConfigurationExtensions.cs create mode 100644 Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/ConfigurationExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/ConfigurationExtensions.cs new file mode 100644 index 00000000..e3f0091a --- /dev/null +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/ConfigurationExtensions.cs @@ -0,0 +1,21 @@ +using Lombiq.Tests.UI.Services; +using System.Threading.Tasks; + +namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.Extensions; + +public static class ConfigurationExtensions +{ + public static void SetEnvironmentRobotsOptionsConfiguration( + this OrchardCoreUITestExecutorConfiguration configuration, + bool isProduction) => + configuration.OrchardCoreConfiguration.BeforeAppStart += + (_, argumentsBuilder) => + { + argumentsBuilder + .AddWithValue( + "OrchardCore:Lombiq_Hosting_Tenants_EnvironmentRobots:EnvironmentRobotsOptions:IsProduction", + value: isProduction); + + return Task.CompletedTask; + }; +} diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs new file mode 100644 index 00000000..a8359917 --- /dev/null +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs @@ -0,0 +1,41 @@ +using Atata; +using Lombiq.Tests.UI.Extensions; +using Lombiq.Tests.UI.Services; +using OpenQA.Selenium; +using Shouldly; +using System.Threading.Tasks; + +namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.Extensions; + +public static class TestCaseUITestContextExtensions +{ + public static async Task TestRobotMetaTagIsMissingAsync(this UITestContext context, bool shouldBeMissing) + { + var metaTagXPath = By.XPath($"//meta[@name='robots' and @content='noindex, nofollow']").OfAnyVisibility(); + + await context.SignInDirectlyAsync(); + await context.GoToHomePageAsync(); + + // Checking the response header with JavaScript. + var isXRobotsInHeader = context.Driver.ExecuteAsyncScript(@" + var callback = arguments[arguments.length - 1]; + var xhr = new XMLHttpRequest(); + xhr.open('GET', window.location.href); + xhr.send(); + xhr.onload = function() { + var xRobotsTag = xhr.getResponseHeader('X-Robots-Tag') ?? ''; + callback(xRobotsTag.includes ('noindex, nofollow')); + };"); + + if (missing) + { + context.Missing(metaTagXPath); + isXRobotsInHeader.ShouldBe(expected: false); + } + else + { + context.Exists(metaTagXPath); + isXRobotsInHeader.ShouldBe(expected: true); + } + } +} From b7da742b21c15d10f222892018a9d477fb18b985 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Fri, 19 May 2023 19:47:07 +0200 Subject: [PATCH 13/22] Typo --- .../Extensions/TestCaseUITestContextExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs index a8359917..1c939ef1 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs @@ -27,7 +27,7 @@ public static async Task TestRobotMetaTagIsMissingAsync(this UITestContext conte callback(xRobotsTag.includes ('noindex, nofollow')); };"); - if (missing) + if (shouldBeMissing) { context.Missing(metaTagXPath); isXRobotsInHeader.ShouldBe(expected: false); From b6ad7ec7c79dd273767714f87724c380eae6f520 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Fri, 19 May 2023 19:50:36 +0200 Subject: [PATCH 14/22] Renaming variable in TestCaseUITestContextExtensions --- .../Extensions/TestCaseUITestContextExtensions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs index 1c939ef1..eb45a569 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs @@ -17,7 +17,7 @@ public static async Task TestRobotMetaTagIsMissingAsync(this UITestContext conte await context.GoToHomePageAsync(); // Checking the response header with JavaScript. - var isXRobotsInHeader = context.Driver.ExecuteAsyncScript(@" + var isHeaderPresent = context.Driver.ExecuteAsyncScript(@" var callback = arguments[arguments.length - 1]; var xhr = new XMLHttpRequest(); xhr.open('GET', window.location.href); @@ -30,12 +30,12 @@ public static async Task TestRobotMetaTagIsMissingAsync(this UITestContext conte if (shouldBeMissing) { context.Missing(metaTagXPath); - isXRobotsInHeader.ShouldBe(expected: false); + isHeaderPresent.ShouldBe(expected: false); } else { context.Exists(metaTagXPath); - isXRobotsInHeader.ShouldBe(expected: true); + isHeaderPresent.ShouldBe(expected: true); } } } From 387ef035e17462a5f9139ecab740097b587ac795 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Fri, 19 May 2023 19:56:15 +0200 Subject: [PATCH 15/22] Correcting Readme link --- .../Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj index 3beb960b..9214240f 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI.csproj @@ -12,7 +12,7 @@ NuGetIcon.png OrchardCore;Lombiq;AspNetCore;Multitenancy;SaaS https://github.com/Lombiq/Hosting-Tenants - https://github.com/Lombiq/Hosting-Tenants/blob/dev/Lombiq.Hosting.Tenants.Maintenance.Tests.UI/Readme.md + https://github.com/Lombiq/Hosting-Tenants/blob/dev/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md License.md From aa5731cefe043d3733659249c97921c5ce60cfdf Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Fri, 19 May 2023 20:12:33 +0200 Subject: [PATCH 16/22] Typo --- .../Lombiq.Hosting.Tenants.EnvironmentRobots.csproj | 2 +- Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj index 11077891..b4bfd8ab 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Lombiq.Hosting.Tenants.EnvironmentRobots.csproj @@ -10,7 +10,7 @@ Lombiq Hosting - Tenants EnvironmentRobots for Orchard Core Lombiq Technologies Copyright © 2023, Lombiq Technologies Ltd. - EnvironmentRobots for Orchard Core: This module contains the EnvironmentRobots feature, which prevents search bots from indexing non-production environments by adding a meta tag and a respone header with noindex, nofollow values. + EnvironmentRobots for Orchard Core: This module contains the EnvironmentRobots feature, which prevents search bots from indexing non-production environments by adding a meta tag and a response header with noindex, nofollow values. NuGetIcon.png OrchardCore;Lombiq;AspNetCore;Multitenancy;SaaS https://github.com/Lombiq/Hosting-Tenants diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs index 25dd648b..2d22ed72 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Manifest.cs @@ -6,7 +6,7 @@ Author = "Lombiq Technologies", Website = "https://github.com/Lombiq/Hosting-Tenants", Version = "0.0.1", - Description = "Prevents search bots from indexing non-production environments by adding a noindex, nofollow meta tag.", + Description = "Prevents search bots from indexing non-production environments by adding a meta tag and a response header with noindex, nofollow values.", Category = "Hosting" )] From 857941b410af2590bffce850d6de3590f81f6ea2 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Fri, 19 May 2023 20:52:41 +0200 Subject: [PATCH 17/22] Refactoring middleware so it respects existing X Robots Tag --- .../Middlewares/EnvironmentRobotsMiddleware.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs index 85605523..a73f342f 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs @@ -3,6 +3,8 @@ using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; namespace Lombiq.Hosting.Tenants.EnvironmentRobots.Middlewares; @@ -27,7 +29,17 @@ public Task InvokeAsync(HttpContext context) { if (!_hostEnvironment.IsProductionWithConfiguration(_options)) { - context.Response.Headers.Add("X-Robots-Tag", "noindex, nofollow"); + var headerValue = context.Response.Headers["X-Robots-Tag"].FirstOrDefault() ?? string.Empty; + + var directives = new List(); + + if (!headerValue.Contains("noindex")) directives.Add("noindex"); + if (!headerValue.Contains("nofollow")) directives.Add("nofollow"); + + if (directives.Any()) + { + context.Response.Headers["X-Robots-Tag"] = $"{headerValue}, {string.Join(", ", directives)}"; + } } return _next(context); From f8b672b97ce7b3bbe32ae396ad9d78cda0a3fe08 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme <80963259+DemeSzabolcs@users.noreply.github.com> Date: Sun, 21 May 2023 18:48:14 +0200 Subject: [PATCH 18/22] Correcting Readme.md --- Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md index 9e02b511..3a1e254b 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Readme.md @@ -29,4 +29,4 @@ The module determines whether a app is non-production based on the `IsProduction To use the module, follow these steps: - Enable the `Lombiq.Hosting.Tenants.EnvironmentRobots` feature from the admin dashboard. -- Optionally, configure the `IsProduction` option for each tenant as described above. +- Optionally, configure the `IsProduction` option as described above. From efe494287918c0bf551a990fb31ab8b829e2e273 Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Sun, 21 May 2023 21:52:01 +0200 Subject: [PATCH 19/22] Minor refactorings --- .../Extensions/TestCaseUITestContextExtensions.cs | 10 +++++----- .../IHostEnvironmentEnvironmentRobotsExtensions.cs | 2 +- .../Filters/EnvironmentRobotsMetaTagFilter.cs | 3 +-- .../Middlewares/EnvironmentRobotsMiddleware.cs | 11 +++++++++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs index eb45a569..cc913f50 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Extensions/TestCaseUITestContextExtensions.cs @@ -16,15 +16,15 @@ public static async Task TestRobotMetaTagIsMissingAsync(this UITestContext conte await context.SignInDirectlyAsync(); await context.GoToHomePageAsync(); - // Checking the response header with JavaScript. + // The easiest way to check the response header during UI testing is with JavaScript by sending a GET request. var isHeaderPresent = context.Driver.ExecuteAsyncScript(@" - var callback = arguments[arguments.length - 1]; - var xhr = new XMLHttpRequest(); + const callback = arguments[arguments.length - 1]; + const xhr = new XMLHttpRequest(); xhr.open('GET', window.location.href); xhr.send(); xhr.onload = function() { - var xRobotsTag = xhr.getResponseHeader('X-Robots-Tag') ?? ''; - callback(xRobotsTag.includes ('noindex, nofollow')); + const xRobotsTag = xhr.getResponseHeader('X-Robots-Tag') ?? ''; + callback(xRobotsTag.includes('noindex, nofollow')); };"); if (shouldBeMissing) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs index 2ccba517..f3c434c4 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs @@ -8,5 +8,5 @@ public static class IHostEnvironmentEnvironmentRobotsExtensions public static bool IsProductionWithConfiguration( this IHostEnvironment hostEnvironment, IOptions options) => - options.Value.IsProduction ?? hostEnvironment.IsProduction(); + options.Value.IsProduction ?? hostEnvironment.IsProduction(); } diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs index 42141617..ee924d8a 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Filters/EnvironmentRobotsMetaTagFilter.cs @@ -37,7 +37,6 @@ public void OnResultExecuting(ResultExecutingContext context) public void OnResultExecuted(ResultExecutedContext context) { - // Intentionally left empty, we don't need the function, but we need to add it because of the interface - // implementation. + // Intentionally empty. Required by interface implementation only. } } diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs index a73f342f..98927d4b 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs @@ -33,8 +33,15 @@ public Task InvokeAsync(HttpContext context) var directives = new List(); - if (!headerValue.Contains("noindex")) directives.Add("noindex"); - if (!headerValue.Contains("nofollow")) directives.Add("nofollow"); + if (!headerValue.Contains("noindex")) + { + directives.Add("noindex"); + } + + if (!headerValue.Contains("nofollow")) + { + directives.Add("nofollow"); + } if (directives.Any()) { From 2579c4db2323911ec2177345f2223cae6cc9b7cf Mon Sep 17 00:00:00 2001 From: Szabolcs Deme <80963259+DemeSzabolcs@users.noreply.github.com> Date: Mon, 22 May 2023 13:51:32 +0200 Subject: [PATCH 20/22] Update Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md Co-authored-by: 0liver <0liver@users.noreply.github.com> --- Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md index 4c2c6dca..3f0f39da 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots.Tests.UI/Readme.md @@ -2,6 +2,6 @@ ## About -Extension methods that tests features in Lombiq Hosting - Tenants EnvironmentRobots, with the help of [Lombiq UI Testing Toolbox for Orchard Core](https://github.com/Lombiq/UI-Testing-Toolbox). +Extension methods that test features in Lombiq Hosting - Tenants EnvironmentRobots, with the help of [Lombiq UI Testing Toolbox for Orchard Core](https://github.com/Lombiq/UI-Testing-Toolbox). Call these from a UI test project to verify the module's basic features; as seen in [Open-Source Orchard Core Extensions](https://github.com/Lombiq/Open-Source-Orchard-Core-Extensions). From 4a2a9ca10c767b4fff84ba2bf78c9291eee4b25d Mon Sep 17 00:00:00 2001 From: Szabolcs Deme <80963259+DemeSzabolcs@users.noreply.github.com> Date: Mon, 22 May 2023 13:59:57 +0200 Subject: [PATCH 21/22] Update Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs Co-authored-by: 0liver <0liver@users.noreply.github.com> --- .../Middlewares/EnvironmentRobotsMiddleware.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs index 98927d4b..b584cb0e 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs @@ -45,7 +45,7 @@ public Task InvokeAsync(HttpContext context) if (directives.Any()) { - context.Response.Headers["X-Robots-Tag"] = $"{headerValue}, {string.Join(", ", directives)}"; + context.Response.Headers["X-Robots-Tag"] = $"{string.Join(", ", directives)}"; } } From 5b7d5ef3b6bb4a7b39179feddd3f519c671a179a Mon Sep 17 00:00:00 2001 From: Szabolcs Deme Date: Mon, 22 May 2023 14:00:59 +0200 Subject: [PATCH 22/22] Minor refactorings --- .../Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs | 2 +- .../Middlewares/EnvironmentRobotsMiddleware.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs index f3c434c4..2ccba517 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Extensions/IHostEnvironmentEnvironmentRobotsExtensions.cs @@ -8,5 +8,5 @@ public static class IHostEnvironmentEnvironmentRobotsExtensions public static bool IsProductionWithConfiguration( this IHostEnvironment hostEnvironment, IOptions options) => - options.Value.IsProduction ?? hostEnvironment.IsProduction(); + options.Value.IsProduction ?? hostEnvironment.IsProduction(); } diff --git a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs index b584cb0e..f47ce198 100644 --- a/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs +++ b/Lombiq.Hosting.Tenants.EnvironmentRobots/Middlewares/EnvironmentRobotsMiddleware.cs @@ -31,7 +31,7 @@ public Task InvokeAsync(HttpContext context) { var headerValue = context.Response.Headers["X-Robots-Tag"].FirstOrDefault() ?? string.Empty; - var directives = new List(); + var directives = new List { headerValue }; if (!headerValue.Contains("noindex")) { @@ -43,7 +43,7 @@ public Task InvokeAsync(HttpContext context) directives.Add("nofollow"); } - if (directives.Any()) + if (directives.Count > 1) { context.Response.Headers["X-Robots-Tag"] = $"{string.Join(", ", directives)}"; }