-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/dev' into issue/OSOE-893
- Loading branch information
Showing
5 changed files
with
222 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
Lombiq.HelpfulLibraries.AspNetCore/Extensions/ConfigurationSectionExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
namespace Microsoft.Extensions.Configuration; | ||
|
||
/// <summary> | ||
/// Shortcuts for <see cref="IConfigurationSection"/> operations. | ||
/// </summary> | ||
public static class ConfigurationSectionExtensions | ||
{ | ||
/// <summary> | ||
/// Adds a value to a configuration section if the key doesn't exist yet. | ||
/// </summary> | ||
/// <param name="key">The key of the configuration.</param> | ||
/// <param name="value">The value of the configuration.</param> | ||
public static IConfigurationSection AddValueIfKeyNotExists( | ||
this IConfigurationSection configurationSection, | ||
string key, | ||
string value) | ||
{ | ||
configurationSection[key] ??= value; | ||
return configurationSection; | ||
} | ||
} |
6 changes: 4 additions & 2 deletions
6
...mon/Extensions/ConfigurationExtensions.cs → ...xtensions/AzureConfigurationExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,14 @@ | ||
namespace Microsoft.Extensions.Configuration; | ||
|
||
public static class ConfigurationExtensions | ||
public static class AzureConfigurationExtensions | ||
{ | ||
public const string IsAzureHostingKey = "IsAzureHosting"; | ||
|
||
/// <summary> | ||
/// Retrieves a value indicating whether the <c>OrchardCore:IsAzureHosting</c> configuration key is set to <see | ||
/// langword="true"/>. | ||
/// </summary> | ||
public static bool IsAzureHosting( | ||
this IConfiguration configuration) => | ||
configuration.GetValue<bool>("OrchardCore:IsAzureHosting"); | ||
configuration.GetValue<bool>("OrchardCore:" + IsAzureHostingKey); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
195 changes: 195 additions & 0 deletions
195
...q.HelpfulLibraries.OrchardCore/Environment/HostingDefaultsOrchardCoreBuilderExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Hosting; | ||
|
||
namespace Microsoft.Extensions.DependencyInjection; | ||
|
||
public static class HostingDefaultsOrchardCoreBuilderExtensions | ||
{ | ||
/// <summary> | ||
/// Lombiq-recommended opinionated default configuration for features of a standard Orchard Core application. If | ||
/// any of the configuration values exist, they won't be overridden, so e.g. appsettings.json configuration will | ||
/// take precedence. | ||
/// </summary> | ||
/// <param name="webApplicationBuilder">The <see cref="WebApplicationBuilder"/> instance of the app.</param> | ||
/// <param name="hostingConfiguration">Configuration for the hosting defaults.</param> | ||
public static OrchardCoreBuilder ConfigureHostingDefaults( | ||
this OrchardCoreBuilder builder, | ||
WebApplicationBuilder webApplicationBuilder, | ||
HostingConfiguration hostingConfiguration = null) | ||
{ | ||
hostingConfiguration ??= new HostingConfiguration(); | ||
|
||
// Not using static type references for the names here because those practically never change, but we'd need to | ||
// add project/package references to all the affected projects. | ||
|
||
var ocSection = webApplicationBuilder.Configuration.GetSection("OrchardCore"); | ||
|
||
ocSection.GetSection("OrchardCore_Tenants").AddValueIfKeyNotExists("TenantRemovalAllowed", "true"); | ||
|
||
ocSection.GetSection("OrchardCore_Localization_CultureOptions").AddValueIfKeyNotExists("IgnoreSystemSettings", "true"); | ||
|
||
var shellsDatabaseSection = ocSection.GetSection("OrchardCore_Shells_Database"); | ||
|
||
shellsDatabaseSection.AddValueIfKeyNotExists("DatabaseProvider", "SqlConnection"); | ||
shellsDatabaseSection.AddValueIfKeyNotExists("TablePrefix", "Shells"); | ||
|
||
ocSection.GetSection("OrchardCore_Tenants").AddValueIfKeyNotExists("TenantRemovalAllowed", "true"); | ||
|
||
var logLevelSection = webApplicationBuilder.Configuration.GetSection("Logging:LogLevel"); | ||
var elasticSearchSection = ocSection.GetSection("OrchardCore_Elasticsearch"); | ||
|
||
if (webApplicationBuilder.Environment.IsDevelopment()) | ||
{ | ||
logLevelSection | ||
.AddValueIfKeyNotExists("Default", "Debug") | ||
.AddValueIfKeyNotExists("System", "Information") | ||
.AddValueIfKeyNotExists("Microsoft", "Information"); | ||
|
||
// Orchard Core 1.8 and prior, this can be removed after an Orchard Core upgrade to 2.0. | ||
// OrchardCore_Email_Smtp below is 2.0+. | ||
var oc18SmtpSection = ocSection.GetSection("SmtpSettings"); | ||
|
||
if (oc18SmtpSection["Host"] == null) | ||
{ | ||
oc18SmtpSection["Host"] = "127.0.0.1"; | ||
oc18SmtpSection["RequireCredentials"] = "false"; | ||
oc18SmtpSection["Port"] = "25"; | ||
} | ||
|
||
oc18SmtpSection.AddValueIfKeyNotExists("DefaultSender", "[email protected]"); | ||
|
||
var smtpSection = ocSection.GetSection("OrchardCore_Email_Smtp"); | ||
|
||
if (smtpSection["Host"] == null) | ||
{ | ||
smtpSection["Host"] = "127.0.0.1"; | ||
smtpSection["RequireCredentials"] = "false"; | ||
smtpSection["Port"] = "25"; | ||
} | ||
|
||
smtpSection.AddValueIfKeyNotExists("DefaultSender", "[email protected]"); | ||
|
||
if (elasticSearchSection["Url"] == null) | ||
{ | ||
elasticSearchSection["ConnectionType"] = "SingleNodeConnectionPool"; | ||
elasticSearchSection["Url"] = "http://localhost"; | ||
elasticSearchSection["Ports:0"] = "9200"; | ||
elasticSearchSection["Username"] = "admin"; | ||
elasticSearchSection["Password"] = "admin"; | ||
} | ||
} | ||
else | ||
{ | ||
logLevelSection | ||
.AddValueIfKeyNotExists("Default", "Warning") | ||
.AddValueIfKeyNotExists("Microsoft.AspNetCore", "Warning"); | ||
|
||
ocSection.AddValueIfKeyNotExists("DatabaseProvider", "SqlConnection"); | ||
|
||
// Elastic Cloud configuration if none is provided. The Url and Password are still needed. | ||
if (elasticSearchSection["ConnectionType"] == null && | ||
elasticSearchSection["Ports"] == null && | ||
elasticSearchSection["Username"] == null) | ||
{ | ||
elasticSearchSection["ConnectionType"] = "CloudConnectionPool"; | ||
elasticSearchSection["Ports:0"] = "9243"; | ||
elasticSearchSection["Username"] = "elastic"; | ||
} | ||
} | ||
|
||
if (hostingConfiguration.AlwaysEnableHealthChecksInProduction && webApplicationBuilder.Environment.IsProduction()) | ||
{ | ||
builder.AddTenantFeatures("OrchardCore.HealthChecks"); | ||
} | ||
|
||
builder | ||
.AddDatabaseShellsConfigurationIfAvailable(webApplicationBuilder.Configuration) | ||
.ConfigureSmtpSettings(overrideAdminSettings: false) | ||
.ConfigureSecurityDefaultsWithStaticFiles(allowInlineStyle: true); | ||
|
||
return builder; | ||
} | ||
|
||
/// <summary> | ||
/// Lombiq-recommended opinionated default configuration for features of an Orchard Core application hosted in | ||
/// Azure. If any of the configuration values exist, they won't be overridden, so e.g. appsettings.json | ||
/// configuration will take precedence. | ||
/// </summary> | ||
/// <param name="webApplicationBuilder">The <see cref="WebApplicationBuilder"/> instance of the app.</param> | ||
/// <param name="hostingConfiguration">Configuration for the hosting defaults.</param> | ||
public static OrchardCoreBuilder ConfigureAzureHostingDefaults( | ||
this OrchardCoreBuilder builder, | ||
WebApplicationBuilder webApplicationBuilder, | ||
AzureHostingConfiguration hostingConfiguration = null) | ||
{ | ||
hostingConfiguration ??= new AzureHostingConfiguration(); | ||
|
||
builder.ConfigureHostingDefaults(webApplicationBuilder, hostingConfiguration); | ||
|
||
var ocSection = webApplicationBuilder.Configuration.GetSection("OrchardCore"); | ||
|
||
if (!webApplicationBuilder.Environment.IsDevelopment()) | ||
{ | ||
ocSection.AddValueIfKeyNotExists(AzureConfigurationExtensions.IsAzureHostingKey, "true"); | ||
} | ||
|
||
if (webApplicationBuilder.Configuration.IsAzureHosting()) | ||
{ | ||
builder | ||
.AddTenantFeatures( | ||
"OrchardCore.DataProtection.Azure", | ||
"Lombiq.Hosting.BuildVersionDisplay") | ||
.DisableResourceDebugMode(); | ||
|
||
if (hostingConfiguration.AlwaysEnableAzureMediaStorage) | ||
{ | ||
// Azure Media Storage and its dependencies. Keep this updated with Orchard upgrades. | ||
builder.AddTenantFeatures( | ||
"OrchardCore.Contents", | ||
"OrchardCore.ContentTypes", | ||
"OrchardCore.Liquid", | ||
"OrchardCore.Media", | ||
"OrchardCore.Media.Azure.Storage", | ||
"OrchardCore.Media.Cache", | ||
"OrchardCore.Settings"); | ||
} | ||
} | ||
|
||
var mediaSection = ocSection.GetSection("OrchardCore_Media_Azure"); | ||
|
||
mediaSection.AddValueIfKeyNotExists("ContainerName", "media"); | ||
mediaSection.AddValueIfKeyNotExists("BasePath", "{{ ShellSettings.Name }}"); | ||
|
||
if (webApplicationBuilder.Environment.IsDevelopment()) | ||
{ | ||
var dataProtectionSection = ocSection.GetSection("OrchardCore_DataProtection_Azure"); | ||
|
||
dataProtectionSection.AddValueIfKeyNotExists("CreateContainer", "true"); | ||
dataProtectionSection.AddValueIfKeyNotExists("ConnectionString", "UseDevelopmentStorage=true"); | ||
|
||
mediaSection.AddValueIfKeyNotExists("CreateContainer", "true"); | ||
mediaSection.AddValueIfKeyNotExists("ConnectionString", "UseDevelopmentStorage=true"); | ||
} | ||
|
||
return builder; | ||
} | ||
} | ||
|
||
public class HostingConfiguration | ||
{ | ||
/// <summary> | ||
/// Gets or sets a value indicating whether to always enable <c>OrchardCore.HealthChecks</c> and its dependencies in | ||
/// the Production environment, for all tenants, without the ability to turn them off. | ||
/// </summary> | ||
public bool AlwaysEnableHealthChecksInProduction { get; set; } = true; | ||
} | ||
|
||
public class AzureHostingConfiguration : HostingConfiguration | ||
{ | ||
/// <summary> | ||
/// Gets or sets a value indicating whether to always enable <c>OrchardCore.Media.Azure.Storage</c> and its | ||
/// dependencies when hosted in Azure, for all tenants, without the ability to turn them off. | ||
/// </summary> | ||
public bool AlwaysEnableAzureMediaStorage { get; set; } = true; | ||
} |