From a9eb00c8facde9cb27b51c828c2663faf6620854 Mon Sep 17 00:00:00 2001 From: Daniel Stolt Date: Fri, 17 Jul 2015 13:23:21 +0100 Subject: [PATCH 1/5] #4253: Made Azure Blob Storage container names configurable. Fixes #4253 --- .../Modules/Orchard.Azure/Constants.cs | 6 ++++-- .../AzureBlobShellSettingsManager.cs | 6 +++++- .../Media/AzureBlobStorageProvider.cs | 21 +++++++++++-------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Constants.cs b/src/Orchard.Web/Modules/Orchard.Azure/Constants.cs index 406043cfa..64dd6ebf1 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Constants.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Constants.cs @@ -2,13 +2,15 @@ public class Constants { public const string ShellSettingsStorageConnectionStringSettingName = "Orchard.Azure.Settings.StorageConnectionString"; - public const string ShellSettingsContainerName = "sites"; // Container names must be lower case. + public const string ShellSettingsContainerNameSettingName = "Orchard.Azure.Settings.ContainerName"; + public const string ShellSettingsDefaultContainerName = "sites"; // Container names must be lower case. public const string ShellSettingsFileName = "Settings.txt"; public const string MediaStorageFeatureName = "Orchard.Azure.Media"; public const string MediaStorageStorageConnectionStringSettingName = "Orchard.Azure.Media.StorageConnectionString"; public const string MediaStorageRootFolderPathSettingName = "Orchard.Azure.Media.RootFolderPath"; - public const string MediaStorageContainerName = "media"; // Container names must be lower case. + public const string MediaStorageContainerNameSettingName = "Orchard.Azure.Media.ContainerName"; + public const string MediaStorageDefaultContainerName = "media"; // Container names must be lower case. public const string MediaStoragePublicHostName = "Orchard.Azure.Media.StoragePublicHostName"; public const string OutputCacheFeatureName = "Orchard.Azure.OutputCache"; diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs index 0e97198d2..5796ee592 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/Environment/Configuration/AzureBlobShellSettingsManager.cs @@ -20,7 +20,11 @@ namespace Orchard.Azure.Services.Environment.Configuration { private readonly IShellSettingsManagerEventHandler _events; public AzureBlobShellSettingsManager(IMimeTypeProvider mimeTypeProvider, IShellSettingsManagerEventHandler events) { - _fileSystem = new AzureFileSystem(CloudConfigurationManager.GetSetting(Constants.ShellSettingsStorageConnectionStringSettingName), Constants.ShellSettingsContainerName, String.Empty, true, mimeTypeProvider); + var connectionString = CloudConfigurationManager.GetSetting(Constants.ShellSettingsStorageConnectionStringSettingName); + var containerName = CloudConfigurationManager.GetSetting(Constants.ShellSettingsContainerNameSettingName); + if (String.IsNullOrEmpty(containerName)) + containerName = Constants.ShellSettingsDefaultContainerName; + _fileSystem = new AzureFileSystem(connectionString, containerName, String.Empty, true, mimeTypeProvider); _events = events; Logger = NullLogger.Instance; } diff --git a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs index 2e38b1cfa..6dd5795ba 100644 --- a/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs +++ b/src/Orchard.Web/Modules/Orchard.Azure/Services/FileSystems/Media/AzureBlobStorageProvider.cs @@ -11,12 +11,15 @@ namespace Orchard.Azure.Services.FileSystems.Media { [OrchardSuppressDependency("Orchard.FileSystems.Media.FileSystemStorageProvider")] public class AzureBlobStorageProvider : AzureFileSystem, IStorageProvider { - public AzureBlobStorageProvider(ShellSettings shellSettings, IMimeTypeProvider mimeTypeProvider, IPlatformConfigurationAccessor pca) - : this(pca.GetSetting(Constants.MediaStorageStorageConnectionStringSettingName, shellSettings.Name, null), - Constants.MediaStorageContainerName, - pca.GetSetting(Constants.MediaStorageRootFolderPathSettingName, shellSettings.Name, null) ?? shellSettings.Name, + public AzureBlobStorageProvider( + ShellSettings shellSettings, + IMimeTypeProvider mimeTypeProvider, + IPlatformConfigurationAccessor platformConfigurationAccessor) + : this(platformConfigurationAccessor.GetSetting(Constants.MediaStorageStorageConnectionStringSettingName, shellSettings.Name, null), + platformConfigurationAccessor.GetSetting(Constants.MediaStorageContainerNameSettingName, shellSettings.Name, null) ?? Constants.MediaStorageDefaultContainerName, + platformConfigurationAccessor.GetSetting(Constants.MediaStorageRootFolderPathSettingName, shellSettings.Name, null) ?? shellSettings.Name, mimeTypeProvider, - pca.GetSetting(Constants.MediaStoragePublicHostName, shellSettings.Name, null)) + platformConfigurationAccessor.GetSetting(Constants.MediaStoragePublicHostName, shellSettings.Name, null)) { } @@ -26,10 +29,10 @@ namespace Orchard.Azure.Services.FileSystems.Media { public bool TrySaveStream(string path, Stream inputStream) { try { - if (FileExists(path)) { - return false; - } - + if (FileExists(path)) { + return false; + } + SaveStream(path, inputStream); } catch { From 25c8c81382718d547ff0b34444fa93a6dc090d3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Fri, 17 Jul 2015 16:23:59 -0700 Subject: [PATCH 2/5] Adding test links in the readme.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f90457cfe..59b90d631 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,10 @@ Orchard is a free, open source, community-focused Content Management System buil [![Join the chat at https://gitter.im/OrchardCMS/Orchard](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/OrchardCMS/Orchard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +You can try it for free on [Dotnest.com](dotnest.com) or on Microsoft Azure by clicking on this button + +[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://ms.portal.azure.com/#create/OutercurveFoundation.OrchardCMS.0.5.9) + ## About The Orchard Project #### Please visit our website at http://orchardproject.net for the most current information about this project. From 56addb2629dac9adb005392c51891a8c802769e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Ros?= Date: Fri, 17 Jul 2015 16:24:58 -0700 Subject: [PATCH 3/5] Fixing urls --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 59b90d631..6c9d11e21 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,9 @@ Orchard is a free, open source, community-focused Content Management System buil [![Join the chat at https://gitter.im/OrchardCMS/Orchard](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/OrchardCMS/Orchard?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -You can try it for free on [Dotnest.com](dotnest.com) or on Microsoft Azure by clicking on this button +You can try it for free on [Dotnest.com](https://dotnest.com) or on Microsoft Azure by clicking on this button -[![Deploy to Azure](http://azuredeploy.net/deploybutton.png)](https://ms.portal.azure.com/#create/OutercurveFoundation.OrchardCMS.0.5.9) +[![Deploy to Azure](https://azuredeploy.net/deploybutton.png)](https://ms.portal.azure.com/#create/OutercurveFoundation.OrchardCMS.0.5.9) ## About The Orchard Project From 83cae5f0a0d6a3000be2e52e2fcf8e80966005b4 Mon Sep 17 00:00:00 2001 From: Daniel Stolt Date: Sat, 18 Jul 2015 22:05:39 +0100 Subject: [PATCH 4/5] #5536: Removed dependency on IContentManager from FormsAuthenticationService. FormsAuthenticationService now uses IMembershipService instead. Also introduced a NullMembershipService implementation in Orchard.Framework, used only for dependency resolution during setup. Fixes #5536. --- .../Services/MembershipService.cs | 2 + src/Orchard/Orchard.Framework.csproj | 1 + src/Orchard/Security/NullMembershipService.cs | 30 ++++++++++++++ .../Providers/FormsAuthenticationService.cs | 40 ++++++++++--------- 4 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 src/Orchard/Security/NullMembershipService.cs diff --git a/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs b/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs index 4395e0795..6d12087f2 100644 --- a/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs +++ b/src/Orchard.Web/Modules/Orchard.Users/Services/MembershipService.cs @@ -15,8 +15,10 @@ using System.Collections.Generic; using Orchard.Services; using System.Web.Helpers; using Orchard.Environment.Configuration; +using Orchard.Environment.Extensions; namespace Orchard.Users.Services { + [OrchardSuppressDependency("Orchard.Security.NullMembershipService")] public class MembershipService : IMembershipService { private const string PBKDF2 = "PBKDF2"; private const string DefaultHashAlgorithm = PBKDF2; diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 42c3bfa61..765d8e6bb 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -165,6 +165,7 @@ + diff --git a/src/Orchard/Security/NullMembershipService.cs b/src/Orchard/Security/NullMembershipService.cs new file mode 100644 index 000000000..bb3b763e8 --- /dev/null +++ b/src/Orchard/Security/NullMembershipService.cs @@ -0,0 +1,30 @@ +using System; + +namespace Orchard.Security { + /// + /// Provides a default implementation of IMembershipService used only for dependency resolution + /// in a setup context. No members on this implementation will ever be called; at the time when this + /// interface is actually used in a tenant, another implementation is assumed to have suppressed it. + /// + public class NullMembershipService : IMembershipService { + public IUser CreateUser(CreateUserParams createUserParams) { + throw new NotImplementedException(); + } + + public MembershipSettings GetSettings() { + throw new NotImplementedException(); + } + + public IUser GetUser(string username) { + throw new NotImplementedException(); + } + + public void SetPassword(IUser user, string password) { + throw new NotImplementedException(); + } + + public IUser ValidateUser(string userNameOrEmail, string password) { + throw new NotImplementedException(); + } + } +} diff --git a/src/Orchard/Security/Providers/FormsAuthenticationService.cs b/src/Orchard/Security/Providers/FormsAuthenticationService.cs index ca1a82244..346e4059a 100644 --- a/src/Orchard/Security/Providers/FormsAuthenticationService.cs +++ b/src/Orchard/Security/Providers/FormsAuthenticationService.cs @@ -3,16 +3,18 @@ using System.Web; using System.Web.Security; using Orchard.Environment.Configuration; using Orchard.Logging; -using Orchard.ContentManagement; using Orchard.Mvc; using Orchard.Mvc.Extensions; using Orchard.Services; +using Orchard.Utility.Extensions; namespace Orchard.Security.Providers { public class FormsAuthenticationService : IAuthenticationService { + private const int _cookieVersion = 3; + private readonly ShellSettings _settings; private readonly IClock _clock; - private readonly IContentManager _contentManager; + private readonly IMembershipService _membershipService; private readonly IHttpContextAccessor _httpContextAccessor; private readonly ISslSettingsProvider _sslSettingsProvider; private readonly IMembershipValidationService _membershipValidationService; @@ -23,13 +25,13 @@ namespace Orchard.Security.Providers { public FormsAuthenticationService( ShellSettings settings, IClock clock, - IContentManager contentManager, + IMembershipService membershipService, IHttpContextAccessor httpContextAccessor, ISslSettingsProvider sslSettingsProvider, IMembershipValidationService membershipValidationService) { _settings = settings; _clock = clock; - _contentManager = contentManager; + _membershipService = membershipService; _httpContextAccessor = httpContextAccessor; _sslSettingsProvider = sslSettingsProvider; _membershipValidationService = membershipValidationService; @@ -45,12 +47,13 @@ namespace Orchard.Security.Providers { public void SignIn(IUser user, bool createPersistentCookie) { var now = _clock.UtcNow.ToLocalTime(); - - // the cookie user data is {userId};{tenant} - var userData = String.Concat(Convert.ToString(user.Id), ";", _settings.Name); + + // The cookie user data is "{userName.Base64};{tenant}". + // The username is encoded to Base64 to prevent collisions with the ';' seprarator. + var userData = String.Concat(user.UserName.ToBase64(), ";", _settings.Name); var ticket = new FormsAuthenticationTicket( - 1 /*version*/, + _cookieVersion, user.UserName, now, now.Add(ExpirationTimeSpan), @@ -121,29 +124,28 @@ namespace Orchard.Security.Providers { var formsIdentity = (FormsIdentity)httpContext.User.Identity; var userData = formsIdentity.Ticket.UserData ?? ""; - // the cookie user data is {userId};{tenant} + // The cookie user data is {userName.Base64};{tenant}. var userDataSegments = userData.Split(';'); if (userDataSegments.Length < 2) { return null; } - var userDataId = userDataSegments[0]; + var userDataName = userDataSegments[0]; var userDataTenant = userDataSegments[1]; + try { + userDataName = userDataName.FromBase64(); + } + catch { + return null; + } + if (!String.Equals(userDataTenant, _settings.Name, StringComparison.Ordinal)) { return null; } - int userId; - if (!int.TryParse(userDataId, out userId)) { - Logger.Error("User id not a parsable integer"); - return null; - } - - // todo: this issues a sql query for each authenticated request - _signedInUser = _contentManager.Get(userId).As(); - + _signedInUser = _membershipService.GetUser(userDataName); if (_signedInUser == null || !_membershipValidationService.CanAuthenticateWithCookie(_signedInUser)) { return null; } From b6082325f626ee6231ca3a271f1c3a71d3e7ce33 Mon Sep 17 00:00:00 2001 From: sfmskywalker Date: Sun, 19 Jul 2015 12:55:17 +0100 Subject: [PATCH 5/5] Fixed that Default recipe was no longer selected by default on setup screen. --- .../Modules/Orchard.Setup/Scripts/setup.js | 2 +- .../Orchard.Setup/Views/Setup/Index.cshtml | 21 +++++++++++++------ src/Orchard/Mvc/Html/HtmlHelperExtensions.cs | 10 ++++++++- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Scripts/setup.js b/src/Orchard.Web/Modules/Orchard.Setup/Scripts/setup.js index 5c34f3426..1c5054cde 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Scripts/setup.js +++ b/src/Orchard.Web/Modules/Orchard.Setup/Scripts/setup.js @@ -16,7 +16,7 @@ (function($) { $(document).ready(function() { $("select.recipe").change(function() { // class="recipe" on the select element - var description = $(this).find(":selected").attr("recipedescription"); // reads the html attribute of the selected option + var description = $(this).find(":selected").data("recipe-description"); // reads the html attribute of the selected option $("#recipedescription").text(description); // make the contents of
be the escaped description string }); $(".data").find('input[name=DatabaseProvider]:checked').click(); diff --git a/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml b/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml index 8221c1997..59a1f5bc7 100644 --- a/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml +++ b/src/Orchard.Web/Modules/Orchard.Setup/Views/Setup/Index.cshtml @@ -1,4 +1,5 @@ @model Orchard.Setup.ViewModels.SetupViewModel +@using Orchard.Recipes.Models; @{ Script.Require("jQuery"); Script.Require("ShapesBase"); @@ -8,6 +9,18 @@ var groupedRecipes = Model.Recipes.Where(x => !String.IsNullOrWhiteSpace(x.Category)).GroupBy(x => x.Category); var unspecifiedCategoryRecipes = Model.Recipes.Where(x => String.IsNullOrWhiteSpace(x.Category)).ToList(); } +@helper RenderRecipeOptions(IEnumerable recipes) { + foreach (var recipe in recipes) { + var optionAttributes = new RouteValueDictionary { + { "data-recipe-description", recipe.Description } + }; + if (Model.Recipe == null && recipe.Name == "Default") { + optionAttributes["selected"] = "selected"; + } + @Html.SelectOption(Model.Recipe, recipe.Name, recipe.Name, optionAttributes) + } + } +}

@Html.TitleForPage(T("Get Started").ToString())

@using (Html.BeginFormAntiForgeryPost()) { @@ -83,17 +96,13 @@ if (!Model.DatabaseIsPreconfigured) { if (groupedRecipes.Count() > 1) { } - foreach (var recipe in recipeGroup.OrderBy(x => x.Name)) { - @Html.SelectOption(Model.Recipe, recipe.Name, recipe.Name, new { recipedescription = recipe.Description }) - } + @RenderRecipeOptions(recipeGroup.OrderBy(x => x.Name)) } @if (unspecifiedCategoryRecipes.Any()) { if (groupedRecipes.Any()) { } - foreach (var recipe in unspecifiedCategoryRecipes.OrderBy(x => x.Name)) { - @Html.SelectOption(Model.Recipe, recipe.Name, recipe.Name, new { recipedescription = recipe.Description }) - } + @RenderRecipeOptions(unspecifiedCategoryRecipes.OrderBy(x => x.Name)) } diff --git a/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs b/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs index ac3d1d948..0e5571ff4 100644 --- a/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs +++ b/src/Orchard/Mvc/Html/HtmlHelperExtensions.cs @@ -52,6 +52,10 @@ namespace Orchard.Mvc.Html { } public static MvcHtmlString SelectOption(this HtmlHelper html, T currentValue, T optionValue, string text, object htmlAttributes) { + return SelectOption(html, optionValue, object.Equals(optionValue, currentValue), text, new RouteValueDictionary(htmlAttributes)); + } + + public static MvcHtmlString SelectOption(this HtmlHelper html, T currentValue, T optionValue, string text, RouteValueDictionary htmlAttributes) { return SelectOption(html, optionValue, object.Equals(optionValue, currentValue), text, htmlAttributes); } @@ -60,6 +64,10 @@ namespace Orchard.Mvc.Html { } public static MvcHtmlString SelectOption(this HtmlHelper html, object optionValue, bool selected, string text, object htmlAttributes) { + return SelectOption(html, optionValue, selected, text, new RouteValueDictionary(htmlAttributes)); + } + + public static MvcHtmlString SelectOption(this HtmlHelper html, object optionValue, bool selected, string text, RouteValueDictionary htmlAttributes) { var builder = new TagBuilder("option"); if (optionValue != null) @@ -71,7 +79,7 @@ namespace Orchard.Mvc.Html { builder.SetInnerText(text); if (htmlAttributes != null) { - builder.MergeAttributes(new RouteValueDictionary(htmlAttributes)); + builder.MergeAttributes(htmlAttributes); } return MvcHtmlString.Create(builder.ToString(TagRenderMode.Normal));