mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 11:44:58 +08:00
Implemented Initializing status.
This commit is contained in:
@@ -91,6 +91,7 @@
|
|||||||
<Compile Include="Providers\Builders\ContentStep.cs" />
|
<Compile Include="Providers\Builders\ContentStep.cs" />
|
||||||
<Compile Include="Providers\Builders\RecipeMetadataStep.cs" />
|
<Compile Include="Providers\Builders\RecipeMetadataStep.cs" />
|
||||||
<Compile Include="Providers\Builders\SettingsStep.cs" />
|
<Compile Include="Providers\Builders\SettingsStep.cs" />
|
||||||
|
<Compile Include="Providers\Executors\ActivateShellStep.cs" />
|
||||||
<Compile Include="Providers\Executors\ActivateSweepGeneratorStep.cs" />
|
<Compile Include="Providers\Executors\ActivateSweepGeneratorStep.cs" />
|
||||||
<Compile Include="Providers\Executors\CommandStep.cs" />
|
<Compile Include="Providers\Executors\CommandStep.cs" />
|
||||||
<Compile Include="Providers\Executors\RemoveContentStep.cs" />
|
<Compile Include="Providers\Executors\RemoveContentStep.cs" />
|
||||||
|
@@ -0,0 +1,23 @@
|
|||||||
|
using Orchard.Environment.Configuration;
|
||||||
|
using Orchard.Recipes.Models;
|
||||||
|
using Orchard.Recipes.Services;
|
||||||
|
|
||||||
|
namespace Orchard.Recipes.Providers.Executors {
|
||||||
|
public class ActivateShellStep : RecipeExecutionStep {
|
||||||
|
private readonly ShellSettings _shellSettings;
|
||||||
|
private readonly IShellSettingsManager _shellSettingsManager;
|
||||||
|
|
||||||
|
public ActivateShellStep(ShellSettings shellSettings, IShellSettingsManager shellSettingsManager, RecipeExecutionLogger logger)
|
||||||
|
: base(logger) {
|
||||||
|
_shellSettings = shellSettings;
|
||||||
|
_shellSettingsManager = shellSettingsManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string Name { get { return "ActivateShell"; } }
|
||||||
|
|
||||||
|
public override void Execute(RecipeExecutionContext context) {
|
||||||
|
_shellSettings.State = TenantState.Running;
|
||||||
|
_shellSettingsManager.SaveSettings(_shellSettings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -74,7 +74,13 @@ namespace Orchard.Recipes.Services {
|
|||||||
if (!String.IsNullOrWhiteSpace(recipeName))
|
if (!String.IsNullOrWhiteSpace(recipeName))
|
||||||
query = from record in query where record.RecipeName == recipeName select record;
|
query = from record in query where record.RecipeName == recipeName select record;
|
||||||
|
|
||||||
var stepResultRecord = query.Single();
|
var stepResultRecord = query.SingleOrDefault();
|
||||||
|
|
||||||
|
if (stepResultRecord == null)
|
||||||
|
// No step result record was created when scheduling the step, so simply ignore.
|
||||||
|
// The only reason where one would not create such a record would be Setup,
|
||||||
|
// when no database exists to store the record but still wants to schedule a recipe step (such as the "StopViewsBackgroundCompilationStep").
|
||||||
|
return;
|
||||||
|
|
||||||
stepResultRecord.IsCompleted = true;
|
stepResultRecord.IsCompleted = true;
|
||||||
stepResultRecord.IsSuccessful = isSuccessful;
|
stepResultRecord.IsSuccessful = isSuccessful;
|
||||||
|
@@ -20,10 +20,11 @@ namespace Orchard.Setup.Controllers {
|
|||||||
private const string DefaultRecipe = "Default";
|
private const string DefaultRecipe = "Default";
|
||||||
|
|
||||||
public SetupController(
|
public SetupController(
|
||||||
INotifier notifier,
|
INotifier notifier,
|
||||||
ISetupService setupService,
|
ISetupService setupService,
|
||||||
IViewsBackgroundCompilation viewsBackgroundCompilation,
|
IViewsBackgroundCompilation viewsBackgroundCompilation,
|
||||||
ShellSettings shellSettings) {
|
ShellSettings shellSettings) {
|
||||||
|
|
||||||
_viewsBackgroundCompilation = viewsBackgroundCompilation;
|
_viewsBackgroundCompilation = viewsBackgroundCompilation;
|
||||||
_shellSettings = shellSettings;
|
_shellSettings = shellSettings;
|
||||||
_notifier = notifier;
|
_notifier = notifier;
|
||||||
@@ -42,12 +43,16 @@ namespace Orchard.Setup.Controllers {
|
|||||||
|
|
||||||
public ActionResult Index() {
|
public ActionResult Index() {
|
||||||
var initialSettings = _setupService.Prime();
|
var initialSettings = _setupService.Prime();
|
||||||
|
|
||||||
|
if(initialSettings.State == TenantState.Initializing)
|
||||||
|
return View("Initializing");
|
||||||
|
|
||||||
var recipes = _setupService.Recipes().ToList();
|
var recipes = _setupService.Recipes().ToList();
|
||||||
string recipeDescription = null;
|
string recipeDescription = null;
|
||||||
if (recipes.Count > 0) {
|
if (recipes.Count > 0) {
|
||||||
recipeDescription = recipes[0].Description;
|
recipeDescription = recipes[0].Description;
|
||||||
}
|
}
|
||||||
|
|
||||||
// On the first time installation of Orchard, the user gets to the setup screen, which
|
// On the first time installation of Orchard, the user gets to the setup screen, which
|
||||||
// will take a while to finish (user inputting data and the setup process itself).
|
// will take a while to finish (user inputting data and the setup process itself).
|
||||||
// We use this opportunity to start a background task to "pre-compile" all the known
|
// We use this opportunity to start a background task to "pre-compile" all the known
|
||||||
@@ -56,10 +61,10 @@ namespace Orchard.Setup.Controllers {
|
|||||||
if (StringComparer.OrdinalIgnoreCase.Equals(initialSettings.Name, ShellSettings.DefaultName)) {
|
if (StringComparer.OrdinalIgnoreCase.Equals(initialSettings.Name, ShellSettings.DefaultName)) {
|
||||||
_viewsBackgroundCompilation.Start();
|
_viewsBackgroundCompilation.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
return IndexViewResult(new SetupViewModel {
|
return IndexViewResult(new SetupViewModel {
|
||||||
AdminUsername = "admin",
|
AdminUsername = "admin",
|
||||||
DatabaseIsPreconfigured = !string.IsNullOrEmpty(initialSettings.DataProvider),
|
DatabaseIsPreconfigured = !String.IsNullOrEmpty(initialSettings.DataProvider),
|
||||||
Recipes = recipes,
|
Recipes = recipes,
|
||||||
RecipeDescription = recipeDescription
|
RecipeDescription = recipeDescription
|
||||||
});
|
});
|
||||||
@@ -76,17 +81,17 @@ namespace Orchard.Setup.Controllers {
|
|||||||
if (model.DatabaseProvider != SetupDatabaseType.Builtin && string.IsNullOrEmpty(model.DatabaseConnectionString))
|
if (model.DatabaseProvider != SetupDatabaseType.Builtin && string.IsNullOrEmpty(model.DatabaseConnectionString))
|
||||||
ModelState.AddModelError("DatabaseConnectionString", T("A connection string is required.").Text);
|
ModelState.AddModelError("DatabaseConnectionString", T("A connection string is required.").Text);
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword ) {
|
if (!String.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword) {
|
||||||
ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match.").Text);
|
ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match.").Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model.DatabaseProvider != SetupDatabaseType.Builtin && !string.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) {
|
if (model.DatabaseProvider != SetupDatabaseType.Builtin && !string.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) {
|
||||||
model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim();
|
model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim();
|
||||||
if(!char.IsLetter(model.DatabaseTablePrefix[0])) {
|
if (!Char.IsLetter(model.DatabaseTablePrefix[0])) {
|
||||||
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter.").Text);
|
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter.").Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(model.DatabaseTablePrefix.Any(x => !Char.IsLetterOrDigit(x))) {
|
if (model.DatabaseTablePrefix.Any(x => !Char.IsLetterOrDigit(x))) {
|
||||||
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must contain letters or digits.").Text);
|
ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must contain letters or digits.").Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,16 +108,15 @@ namespace Orchard.Setup.Controllers {
|
|||||||
foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) {
|
foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) {
|
||||||
model.RecipeDescription = recipe.Description;
|
model.RecipeDescription = recipe.Description;
|
||||||
}
|
}
|
||||||
model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider);
|
model.DatabaseIsPreconfigured = !String.IsNullOrEmpty(_setupService.Prime().DataProvider);
|
||||||
|
|
||||||
return IndexViewResult(model);
|
return IndexViewResult(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
string providerName = null;
|
string providerName = null;
|
||||||
|
|
||||||
switch (model.DatabaseProvider)
|
switch (model.DatabaseProvider) {
|
||||||
{
|
|
||||||
case SetupDatabaseType.Builtin:
|
case SetupDatabaseType.Builtin:
|
||||||
providerName = "SqlCe";
|
providerName = "SqlCe";
|
||||||
break;
|
break;
|
||||||
@@ -140,11 +144,11 @@ namespace Orchard.Setup.Controllers {
|
|||||||
DatabaseProvider = providerName,
|
DatabaseProvider = providerName,
|
||||||
DatabaseConnectionString = model.DatabaseConnectionString,
|
DatabaseConnectionString = model.DatabaseConnectionString,
|
||||||
DatabaseTablePrefix = model.DatabaseTablePrefix,
|
DatabaseTablePrefix = model.DatabaseTablePrefix,
|
||||||
EnabledFeatures = null, // default list
|
EnabledFeatures = null, // Default list
|
||||||
Recipe = model.Recipe
|
Recipe = model.Recipe
|
||||||
};
|
};
|
||||||
|
|
||||||
string executionId = _setupService.Setup(setupContext);
|
var executionId = _setupService.Setup(setupContext);
|
||||||
|
|
||||||
// First time installation if finally done. Tell the background views compilation
|
// First time installation if finally done. Tell the background views compilation
|
||||||
// process to stop, so that it doesn't interfere with the user (asp.net compilation
|
// process to stop, so that it doesn't interfere with the user (asp.net compilation
|
||||||
@@ -153,7 +157,8 @@ namespace Orchard.Setup.Controllers {
|
|||||||
|
|
||||||
// Redirect to the welcome page.
|
// Redirect to the welcome page.
|
||||||
return Redirect("~/" + _shellSettings.RequestUrlPrefix);
|
return Redirect("~/" + _shellSettings.RequestUrlPrefix);
|
||||||
} catch (Exception ex) {
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
Logger.Error(ex, "Setup failed");
|
Logger.Error(ex, "Setup failed");
|
||||||
_notifier.Error(T("Setup failed: {0}", ex.Message));
|
_notifier.Error(T("Setup failed: {0}", ex.Message));
|
||||||
|
|
||||||
@@ -161,7 +166,7 @@ namespace Orchard.Setup.Controllers {
|
|||||||
foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) {
|
foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) {
|
||||||
model.RecipeDescription = recipe.Description;
|
model.RecipeDescription = recipe.Description;
|
||||||
}
|
}
|
||||||
model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider);
|
model.DatabaseIsPreconfigured = !String.IsNullOrEmpty(_setupService.Prime().DataProvider);
|
||||||
|
|
||||||
return IndexViewResult(model);
|
return IndexViewResult(model);
|
||||||
}
|
}
|
||||||
|
@@ -1,15 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Web;
|
|
||||||
|
|
||||||
namespace Orchard.Setup.Controllers
|
|
||||||
{
|
|
||||||
public enum SetupDatabaseType
|
|
||||||
{
|
|
||||||
Builtin,
|
|
||||||
SqlServer,
|
|
||||||
MySql,
|
|
||||||
PostgreSql,
|
|
||||||
}
|
|
||||||
}
|
|
@@ -25,6 +25,7 @@
|
|||||||
<IISExpressAnonymousAuthentication />
|
<IISExpressAnonymousAuthentication />
|
||||||
<IISExpressWindowsAuthentication />
|
<IISExpressWindowsAuthentication />
|
||||||
<IISExpressUseClassicPipelineMode />
|
<IISExpressUseClassicPipelineMode />
|
||||||
|
<UseGlobalApplicationHostFile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<DebugSymbols>true</DebugSymbols>
|
<DebugSymbols>true</DebugSymbols>
|
||||||
@@ -78,7 +79,7 @@
|
|||||||
<Compile Include="Annotations\StringLengthMin.cs" />
|
<Compile Include="Annotations\StringLengthMin.cs" />
|
||||||
<Compile Include="Commands\SetupCommand.cs" />
|
<Compile Include="Commands\SetupCommand.cs" />
|
||||||
<Compile Include="Controllers\SetupController.cs" />
|
<Compile Include="Controllers\SetupController.cs" />
|
||||||
<Compile Include="Controllers\SetupDatabaseType.cs" />
|
<Compile Include="ViewModels\SetupDatabaseType.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Routes.cs" />
|
<Compile Include="Routes.cs" />
|
||||||
<Compile Include="Services\ISetupService.cs" />
|
<Compile Include="Services\ISetupService.cs" />
|
||||||
@@ -136,6 +137,9 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="Views\Document.cshtml" />
|
<Content Include="Views\Document.cshtml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="Views\Setup\Initializing.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
@@ -4,8 +4,7 @@ using System.Web.Routing;
|
|||||||
using Orchard.Mvc.Routes;
|
using Orchard.Mvc.Routes;
|
||||||
|
|
||||||
namespace Orchard.Setup {
|
namespace Orchard.Setup {
|
||||||
public class Routes : IRouteProvider
|
public class Routes : IRouteProvider {
|
||||||
{
|
|
||||||
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
public void GetRoutes(ICollection<RouteDescriptor> routes) {
|
||||||
foreach (var routeDescriptor in GetRoutes())
|
foreach (var routeDescriptor in GetRoutes())
|
||||||
routes.Add(routeDescriptor);
|
routes.Add(routeDescriptor);
|
||||||
@@ -13,24 +12,24 @@ namespace Orchard.Setup {
|
|||||||
|
|
||||||
public IEnumerable<RouteDescriptor> GetRoutes() {
|
public IEnumerable<RouteDescriptor> GetRoutes() {
|
||||||
return new[] {
|
return new[] {
|
||||||
new RouteDescriptor {
|
new RouteDescriptor {
|
||||||
Route = new Route(
|
Route = new Route(
|
||||||
"{controller}/{action}",
|
"{controller}/{action}",
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Orchard.Setup"},
|
{"area", "Orchard.Setup"},
|
||||||
{"controller", "Setup"},
|
{"controller", "Setup"},
|
||||||
{"action", "Index"}
|
{"action", "Index"}
|
||||||
},
|
},
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Orchard.Setup"},
|
{"area", "Orchard.Setup"},
|
||||||
{"controller", "Setup"},
|
{"controller", "Setup"},
|
||||||
},
|
},
|
||||||
new RouteValueDictionary {
|
new RouteValueDictionary {
|
||||||
{"area", "Orchard.Setup"}
|
{"area", "Orchard.Setup"}
|
||||||
},
|
},
|
||||||
new MvcRouteHandler())
|
new MvcRouteHandler())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
using System.Xml.Linq;
|
||||||
using Orchard.ContentManagement;
|
using Orchard.ContentManagement;
|
||||||
using Orchard.Core.Settings.Models;
|
using Orchard.Core.Settings.Models;
|
||||||
using Orchard.Data;
|
using Orchard.Data;
|
||||||
@@ -16,7 +17,6 @@ using Orchard.Environment.Descriptor.Models;
|
|||||||
using Orchard.Environment.Extensions;
|
using Orchard.Environment.Extensions;
|
||||||
using Orchard.Environment.ShellBuilders;
|
using Orchard.Environment.ShellBuilders;
|
||||||
using Orchard.Environment.State;
|
using Orchard.Environment.State;
|
||||||
using Orchard.Localization;
|
|
||||||
using Orchard.Localization.Services;
|
using Orchard.Localization.Services;
|
||||||
using Orchard.Logging;
|
using Orchard.Logging;
|
||||||
using Orchard.Recipes.Models;
|
using Orchard.Recipes.Models;
|
||||||
@@ -26,7 +26,7 @@ using Orchard.Settings;
|
|||||||
using Orchard.Utility.Extensions;
|
using Orchard.Utility.Extensions;
|
||||||
|
|
||||||
namespace Orchard.Setup.Services {
|
namespace Orchard.Setup.Services {
|
||||||
public class SetupService : ISetupService {
|
public class SetupService : Component, ISetupService {
|
||||||
private readonly ShellSettings _shellSettings;
|
private readonly ShellSettings _shellSettings;
|
||||||
private readonly IOrchardHost _orchardHost;
|
private readonly IOrchardHost _orchardHost;
|
||||||
private readonly IShellSettingsManager _shellSettingsManager;
|
private readonly IShellSettingsManager _shellSettingsManager;
|
||||||
@@ -46,6 +46,7 @@ namespace Orchard.Setup.Services {
|
|||||||
IProcessingEngine processingEngine,
|
IProcessingEngine processingEngine,
|
||||||
IExtensionManager extensionManager,
|
IExtensionManager extensionManager,
|
||||||
IRecipeHarvester recipeHarvester) {
|
IRecipeHarvester recipeHarvester) {
|
||||||
|
|
||||||
_shellSettings = shellSettings;
|
_shellSettings = shellSettings;
|
||||||
_orchardHost = orchardHost;
|
_orchardHost = orchardHost;
|
||||||
_shellSettingsManager = shellSettingsManager;
|
_shellSettingsManager = shellSettingsManager;
|
||||||
@@ -54,13 +55,8 @@ namespace Orchard.Setup.Services {
|
|||||||
_processingEngine = processingEngine;
|
_processingEngine = processingEngine;
|
||||||
_extensionManager = extensionManager;
|
_extensionManager = extensionManager;
|
||||||
_recipeHarvester = recipeHarvester;
|
_recipeHarvester = recipeHarvester;
|
||||||
T = NullLocalizer.Instance;
|
|
||||||
Logger = NullLogger.Instance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Localizer T { get; set; }
|
|
||||||
public ILogger Logger { get; set; }
|
|
||||||
|
|
||||||
public ShellSettings Prime() {
|
public ShellSettings Prime() {
|
||||||
return _shellSettings;
|
return _shellSettings;
|
||||||
}
|
}
|
||||||
@@ -86,36 +82,33 @@ namespace Orchard.Setup.Services {
|
|||||||
|
|
||||||
// The vanilla Orchard distibution has the following features enabled.
|
// The vanilla Orchard distibution has the following features enabled.
|
||||||
string[] hardcoded = {
|
string[] hardcoded = {
|
||||||
// Framework
|
// Framework
|
||||||
"Orchard.Framework",
|
"Orchard.Framework",
|
||||||
// Core
|
// Core
|
||||||
"Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation","Scheduling", "Settings", "Shapes", "Title",
|
"Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation","Scheduling", "Settings", "Shapes", "Title",
|
||||||
// Modules
|
// Modules
|
||||||
"Orchard.Pages", "Orchard.ContentPicker", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules",
|
"Orchard.Pages", "Orchard.ContentPicker", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules",
|
||||||
"PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes"
|
"PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes"
|
||||||
};
|
};
|
||||||
|
|
||||||
context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList();
|
context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList();
|
||||||
|
|
||||||
var shellSettings = new ShellSettings(_shellSettings);
|
var shellSettings = new ShellSettings(_shellSettings);
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(shellSettings.DataProvider)) {
|
if (String.IsNullOrEmpty(shellSettings.DataProvider)) {
|
||||||
shellSettings.DataProvider = context.DatabaseProvider;
|
shellSettings.DataProvider = context.DatabaseProvider;
|
||||||
shellSettings.DataConnectionString = context.DatabaseConnectionString;
|
shellSettings.DataConnectionString = context.DatabaseConnectionString;
|
||||||
shellSettings.DataTablePrefix = context.DatabaseTablePrefix;
|
shellSettings.DataTablePrefix = context.DatabaseTablePrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Encryption Settings
|
|
||||||
|
|
||||||
shellSettings.EncryptionAlgorithm = "AES";
|
shellSettings.EncryptionAlgorithm = "AES";
|
||||||
// randomly generated key
|
|
||||||
|
// Randomly generated key.
|
||||||
shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString();
|
shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString();
|
||||||
|
|
||||||
shellSettings.HashAlgorithm = "HMACSHA256";
|
shellSettings.HashAlgorithm = "HMACSHA256";
|
||||||
// randomly generated key
|
|
||||||
shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString();
|
|
||||||
|
|
||||||
#endregion
|
// Randomly generated key.
|
||||||
|
shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString();
|
||||||
|
|
||||||
var shellDescriptor = new ShellDescriptor {
|
var shellDescriptor = new ShellDescriptor {
|
||||||
Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name })
|
Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name })
|
||||||
@@ -123,12 +116,12 @@ namespace Orchard.Setup.Services {
|
|||||||
|
|
||||||
var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor);
|
var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor);
|
||||||
|
|
||||||
// initialize database explicitly, and store shell descriptor
|
// Initialize database explicitly, and store shell descriptor.
|
||||||
using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) {
|
using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) {
|
||||||
|
|
||||||
using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) {
|
using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) {
|
||||||
|
|
||||||
// check if the database is already created (in case an exception occured in the second phase)
|
// Check if the database is already created (in case an exception occured in the second phase).
|
||||||
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>());
|
||||||
var installationPresent = true;
|
var installationPresent = true;
|
||||||
try {
|
try {
|
||||||
@@ -143,7 +136,7 @@ namespace Orchard.Setup.Services {
|
|||||||
throw new OrchardException(T("A previous Orchard installation was detected in this database with this table prefix."));
|
throw new OrchardException(T("A previous Orchard installation was detected in this database with this table prefix."));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make a workaround to avoid the Transaction issue for PostgreSQL
|
// Workaround to avoid some Transaction issue for PostgreSQL.
|
||||||
environment.Resolve<ITransactionManager>().RequireNew();
|
environment.Resolve<ITransactionManager>().RequireNew();
|
||||||
|
|
||||||
schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table
|
schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table
|
||||||
@@ -168,15 +161,15 @@ namespace Orchard.Setup.Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// in effect "pump messages" see PostMessage circa 1980
|
// In effect "pump messages" see PostMessage circa 1980.
|
||||||
while (_processingEngine.AreTasksPending())
|
while (_processingEngine.AreTasksPending())
|
||||||
_processingEngine.ExecuteNextTask();
|
_processingEngine.ExecuteNextTask();
|
||||||
|
|
||||||
// creating a standalone environment.
|
// Creating a standalone environment.
|
||||||
// in theory this environment can be used to resolve any normal components by interface, and those
|
// in theory this environment can be used to resolve any normal components by interface, and those
|
||||||
// components will exist entirely in isolation - no crossover between the safemode container currently in effect
|
// components will exist entirely in isolation - no crossover between the safemode container currently in effect.
|
||||||
|
|
||||||
// must mark state as Running - otherwise standalone enviro is created "for setup"
|
// Set shell state to "Running" so that the proper shell context is created.
|
||||||
shellSettings.State = TenantState.Running;
|
shellSettings.State = TenantState.Running;
|
||||||
using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) {
|
||||||
try {
|
try {
|
||||||
@@ -188,24 +181,25 @@ namespace Orchard.Setup.Services {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up.
|
||||||
|
shellSettings.State = _shellSettings.State = TenantState.Initializing;
|
||||||
_shellSettingsManager.SaveSettings(shellSettings);
|
_shellSettingsManager.SaveSettings(shellSettings);
|
||||||
|
|
||||||
return executionId;
|
return executionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CreateTenantData(SetupContext context, IWorkContextScope environment) {
|
private string CreateTenantData(SetupContext context, IWorkContextScope environment) {
|
||||||
// create superuser
|
// Create site owner.
|
||||||
var membershipService = environment.Resolve<IMembershipService>();
|
var membershipService = environment.Resolve<IMembershipService>();
|
||||||
var user =
|
var user = membershipService.CreateUser(
|
||||||
membershipService.CreateUser(new CreateUserParams(context.AdminUsername, context.AdminPassword,
|
new CreateUserParams(context.AdminUsername, context.AdminPassword,
|
||||||
String.Empty, String.Empty, String.Empty,
|
String.Empty, String.Empty, String.Empty, true));
|
||||||
true));
|
|
||||||
|
|
||||||
// set superuser as current user for request (it will be set as the owner of all content items)
|
// Set site owner as current user for request (it will be set as the owner of all content items).
|
||||||
var authenticationService = environment.Resolve<IAuthenticationService>();
|
var authenticationService = environment.Resolve<IAuthenticationService>();
|
||||||
authenticationService.SetAuthenticatedUserForRequest(user);
|
authenticationService.SetAuthenticatedUserForRequest(user);
|
||||||
|
|
||||||
// set site name and settings
|
// Set site name and settings.
|
||||||
var siteService = environment.Resolve<ISiteService>();
|
var siteService = environment.Resolve<ISiteService>();
|
||||||
var siteSettings = siteService.GetSiteSettings().As<SiteSettingsPart>();
|
var siteSettings = siteService.GetSiteSettings().As<SiteSettingsPart>();
|
||||||
siteSettings.SiteSalt = Guid.NewGuid().ToString("N");
|
siteSettings.SiteSalt = Guid.NewGuid().ToString("N");
|
||||||
@@ -213,7 +207,7 @@ namespace Orchard.Setup.Services {
|
|||||||
siteSettings.SuperUser = context.AdminUsername;
|
siteSettings.SuperUser = context.AdminUsername;
|
||||||
siteSettings.SiteCulture = "en-US";
|
siteSettings.SiteCulture = "en-US";
|
||||||
|
|
||||||
// add default culture
|
// Add default culture.
|
||||||
var cultureManager = environment.Resolve<ICultureManager>();
|
var cultureManager = environment.Resolve<ICultureManager>();
|
||||||
cultureManager.AddCulture("en-US");
|
cultureManager.AddCulture("en-US");
|
||||||
|
|
||||||
@@ -222,10 +216,22 @@ namespace Orchard.Setup.Services {
|
|||||||
|
|
||||||
if (recipe == null)
|
if (recipe == null)
|
||||||
throw new OrchardException(T("The recipe '{0}' could not be found.", context.Recipe));
|
throw new OrchardException(T("The recipe '{0}' could not be found.", context.Recipe));
|
||||||
|
|
||||||
var executionId = recipeManager.Execute(recipe);
|
var executionId = recipeManager.Execute(recipe);
|
||||||
|
|
||||||
// null check: temporary fix for running setup in command line
|
// Once the recipe has finished executing, we need to update the shell state to "Running", so add a recipe step that does exactly that.
|
||||||
|
var recipeStepQueue = environment.Resolve<IRecipeStepQueue>();
|
||||||
|
var recipeStepResultRecordRepository = environment.Resolve<IRepository<RecipeStepResultRecord>>();
|
||||||
|
var activateShellStep = new RecipeStep(Guid.NewGuid().ToString("N"), recipe.Name, "ActivateShell", new XElement("ActivateShell"));
|
||||||
|
recipeStepQueue.Enqueue(executionId, activateShellStep);
|
||||||
|
recipeStepResultRecordRepository.Create(new RecipeStepResultRecord {
|
||||||
|
ExecutionId = executionId,
|
||||||
|
RecipeName = recipe.Name,
|
||||||
|
StepId = activateShellStep.Id,
|
||||||
|
StepName = activateShellStep.Name
|
||||||
|
});
|
||||||
|
|
||||||
|
// Null check: temporary fix for running setup in command line.
|
||||||
if (HttpContext.Current != null) {
|
if (HttpContext.Current != null) {
|
||||||
authenticationService.SignIn(user, true);
|
authenticationService.SignIn(user, true);
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Web.Routing;
|
using System.Web.Routing;
|
||||||
using Autofac;
|
using Autofac;
|
||||||
using Orchard.Caching;
|
using Orchard.Caching;
|
||||||
|
@@ -0,0 +1,10 @@
|
|||||||
|
namespace Orchard.Setup.ViewModels
|
||||||
|
{
|
||||||
|
public enum SetupDatabaseType
|
||||||
|
{
|
||||||
|
Builtin,
|
||||||
|
SqlServer,
|
||||||
|
MySql,
|
||||||
|
PostgreSql,
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,6 @@
|
|||||||
@model Orchard.Setup.ViewModels.SetupViewModel
|
@model Orchard.Setup.ViewModels.SetupViewModel
|
||||||
@using Orchard.Recipes.Models;
|
@using Orchard.Recipes.Models;
|
||||||
|
@using Orchard.Setup.ViewModels
|
||||||
@{
|
@{
|
||||||
Script.Require("jQuery");
|
Script.Require("jQuery");
|
||||||
Script.Require("ShapesBase");
|
Script.Require("ShapesBase");
|
||||||
@@ -47,19 +48,19 @@ if (!Model.DatabaseIsPreconfigured) {
|
|||||||
<legend>@T("How would you like to store your data?")</legend>
|
<legend>@T("How would you like to store your data?")</legend>
|
||||||
@Html.ValidationMessage("DatabaseOptions", "Unable to setup data storage.")
|
@Html.ValidationMessage("DatabaseOptions", "Unable to setup data storage.")
|
||||||
<div>
|
<div>
|
||||||
@Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.Builtin.ToString(), new { id = "builtin" })
|
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.Builtin.ToString(), new { id = "builtin" })
|
||||||
<label for="builtin" class="forcheckbox">@T("Use built-in data storage (SQL Server Compact)")</label>
|
<label for="builtin" class="forcheckbox">@T("Use built-in data storage (SQL Server Compact)")</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.SqlServer.ToString(), new { id = "sqlserver" })
|
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.SqlServer.ToString(), new { id = "sqlserver" })
|
||||||
<label for="sqlserver" class="forcheckbox">@T("Use an existing SQL Server, SQL Express database")</label>
|
<label for="sqlserver" class="forcheckbox">@T("Use an existing SQL Server, SQL Express database")</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.MySql.ToString(), new { id = "mysql" })
|
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.MySql.ToString(), new { id = "mysql" })
|
||||||
<label for="mysql" class="forcheckbox">@T("Use an existing MySql database")</label>
|
<label for="mysql" class="forcheckbox">@T("Use an existing MySql database")</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@Html.RadioButtonFor(svm => svm.DatabaseProvider, Orchard.Setup.Controllers.SetupDatabaseType.PostgreSql.ToString(), new { id = "postgresql" })
|
@Html.RadioButtonFor(svm => svm.DatabaseProvider, SetupDatabaseType.PostgreSql.ToString(), new { id = "postgresql" })
|
||||||
<label for="postgresql" class="forcheckbox">@T("Use an existing PostgreSQL database")</label>
|
<label for="postgresql" class="forcheckbox">@T("Use an existing PostgreSQL database")</label>
|
||||||
</div>
|
</div>
|
||||||
<div data-controllerid="builtin" data-defaultstate="hidden">
|
<div data-controllerid="builtin" data-defaultstate="hidden">
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
@T("Orchard is initializing. Please check back in a few minutes.")
|
@@ -9,7 +9,7 @@ namespace Orchard.Environment.Configuration {
|
|||||||
|
|
||||||
public class ShellSettingsManager : Component, IShellSettingsManager {
|
public class ShellSettingsManager : Component, IShellSettingsManager {
|
||||||
|
|
||||||
private const string _settingsFileName = "Settings.txt";
|
private const string SettingsFileName = "Settings.txt";
|
||||||
private readonly IAppDataFolder _appDataFolder;
|
private readonly IAppDataFolder _appDataFolder;
|
||||||
private readonly IShellSettingsManagerEventHandler _events;
|
private readonly IShellSettingsManagerEventHandler _events;
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ namespace Orchard.Environment.Configuration {
|
|||||||
throw new ArgumentException("The Name property of the supplied ShellSettings object is null or empty; the settings cannot be saved.", "settings");
|
throw new ArgumentException("The Name property of the supplied ShellSettings object is null or empty; the settings cannot be saved.", "settings");
|
||||||
|
|
||||||
Logger.Information("Saving ShellSettings for tenant '{0}'...", settings.Name);
|
Logger.Information("Saving ShellSettings for tenant '{0}'...", settings.Name);
|
||||||
var filePath = Path.Combine(Path.Combine("Sites", settings.Name), _settingsFileName);
|
var filePath = Path.Combine(Path.Combine("Sites", settings.Name), SettingsFileName);
|
||||||
_appDataFolder.CreateFile(filePath, ShellSettingsSerializer.ComposeSettings(settings));
|
_appDataFolder.CreateFile(filePath, ShellSettingsSerializer.ComposeSettings(settings));
|
||||||
|
|
||||||
Logger.Information("ShellSettings saved successfully; flagging tenant '{0}' for restart.", settings.Name);
|
Logger.Information("ShellSettings saved successfully; flagging tenant '{0}' for restart.", settings.Name);
|
||||||
@@ -48,7 +48,7 @@ namespace Orchard.Environment.Configuration {
|
|||||||
var filePaths = _appDataFolder
|
var filePaths = _appDataFolder
|
||||||
.ListDirectories("Sites")
|
.ListDirectories("Sites")
|
||||||
.SelectMany(path => _appDataFolder.ListFiles(path))
|
.SelectMany(path => _appDataFolder.ListFiles(path))
|
||||||
.Where(path => String.Equals(Path.GetFileName(path), _settingsFileName, StringComparison.OrdinalIgnoreCase));
|
.Where(path => String.Equals(Path.GetFileName(path), SettingsFileName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
foreach (var filePath in filePaths) {
|
foreach (var filePath in filePaths) {
|
||||||
yield return ShellSettingsSerializer.ParseSettings(_appDataFolder.ReadFile(filePath));
|
yield return ShellSettingsSerializer.ParseSettings(_appDataFolder.ReadFile(filePath));
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
namespace Orchard.Environment.Configuration {
|
namespace Orchard.Environment.Configuration {
|
||||||
public enum TenantState {
|
public enum TenantState {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
|
Initializing,
|
||||||
Running,
|
Running,
|
||||||
Disabled,
|
Disabled,
|
||||||
Invalid
|
Invalid
|
||||||
|
@@ -128,12 +128,12 @@ namespace Orchard.Environment {
|
|||||||
void CreateAndActivateShells() {
|
void CreateAndActivateShells() {
|
||||||
Logger.Information("Start creation of shells");
|
Logger.Information("Start creation of shells");
|
||||||
|
|
||||||
// is there any tenant right now ?
|
// Is there any tenant right now?
|
||||||
var allSettings = _shellSettingsManager.LoadSettings()
|
var allSettings = _shellSettingsManager.LoadSettings()
|
||||||
.Where(settings => settings.State == TenantState.Running || settings.State == TenantState.Uninitialized)
|
.Where(settings => settings.State == TenantState.Running || settings.State == TenantState.Uninitialized || settings.State == TenantState.Initializing)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
// load all tenants, and activate their shell
|
// Load all tenants, and activate their shell.
|
||||||
if (allSettings.Any()) {
|
if (allSettings.Any()) {
|
||||||
Parallel.ForEach(allSettings, settings => {
|
Parallel.ForEach(allSettings, settings => {
|
||||||
try {
|
try {
|
||||||
@@ -145,7 +145,7 @@ namespace Orchard.Environment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// no settings, run the Setup
|
// No settings, run the Setup.
|
||||||
else {
|
else {
|
||||||
var setupContext = CreateSetupContext();
|
var setupContext = CreateSetupContext();
|
||||||
ActivateShell(setupContext);
|
ActivateShell(setupContext);
|
||||||
@@ -172,24 +172,26 @@ namespace Orchard.Environment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a transient shell for the default tenant's setup
|
/// Creates a transient shell for the default tenant's setup.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ShellContext CreateSetupContext() {
|
private ShellContext CreateSetupContext() {
|
||||||
Logger.Debug("Creating shell context for root setup");
|
Logger.Debug("Creating shell context for root setup.");
|
||||||
return _shellContextFactory.CreateSetupContext(new ShellSettings { Name = ShellSettings.DefaultName });
|
return _shellContextFactory.CreateSetupContext(new ShellSettings { Name = ShellSettings.DefaultName });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a shell context based on shell settings
|
/// Creates a shell context based on shell settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private ShellContext CreateShellContext(ShellSettings settings) {
|
private ShellContext CreateShellContext(ShellSettings settings) {
|
||||||
if (settings.State == TenantState.Uninitialized) {
|
switch (settings.State) {
|
||||||
Logger.Debug("Creating shell context for tenant {0} setup", settings.Name);
|
case TenantState.Uninitialized:
|
||||||
return _shellContextFactory.CreateSetupContext(settings);
|
case TenantState.Initializing:
|
||||||
|
Logger.Debug("Creating shell context for tenant {0} setup.", settings.Name);
|
||||||
|
return _shellContextFactory.CreateSetupContext(settings);
|
||||||
|
default:
|
||||||
|
Logger.Debug("Creating shell context for tenant {0}.", settings.Name);
|
||||||
|
return _shellContextFactory.CreateShellContext(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug("Creating shell context for tenant {0}", settings.Name);
|
|
||||||
return _shellContextFactory.CreateShellContext(settings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetupExtensions() {
|
private void SetupExtensions() {
|
||||||
|
@@ -37,6 +37,7 @@ namespace Orchard.Environment {
|
|||||||
ISweepGenerator sweepGenerator,
|
ISweepGenerator sweepGenerator,
|
||||||
IEnumerable<IOwinMiddlewareProvider> owinMiddlewareProviders,
|
IEnumerable<IOwinMiddlewareProvider> owinMiddlewareProviders,
|
||||||
ShellSettings shellSettings) {
|
ShellSettings shellSettings) {
|
||||||
|
|
||||||
_eventsFactory = eventsFactory;
|
_eventsFactory = eventsFactory;
|
||||||
_routeProviders = routeProviders;
|
_routeProviders = routeProviders;
|
||||||
_httpRouteProviders = httpRouteProviders;
|
_httpRouteProviders = httpRouteProviders;
|
||||||
|
@@ -103,7 +103,8 @@ namespace Orchard.Environment.ShellBuilders {
|
|||||||
Features = new[] {
|
Features = new[] {
|
||||||
new ShellFeature { Name = "Orchard.Setup" },
|
new ShellFeature { Name = "Orchard.Setup" },
|
||||||
new ShellFeature { Name = "Shapes" },
|
new ShellFeature { Name = "Shapes" },
|
||||||
new ShellFeature { Name = "Orchard.jQuery" },
|
new ShellFeature { Name = "Orchard.Recipes" },
|
||||||
|
new ShellFeature { Name = "Orchard.jQuery" }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user