public void Setup() { IEnumerable<string> enabledFeatures = null; if (!string.IsNullOrEmpty(EnabledFeatures)) { enabledFeatures = EnabledFeatures .Split(',') .Select(s => s.Trim()) .Where(s => !string.IsNullOrEmpty(s)); } Recipe = String.IsNullOrEmpty(Recipe) ? "Default" : Recipe; var setupContext = new SetupContext { SiteName = SiteName, AdminUsername = AdminUsername, AdminPassword = AdminPassword, DatabaseProvider = DatabaseProvider, DatabaseConnectionString = DatabaseConnectionString, DatabaseTablePrefix = DatabaseTablePrefix, EnabledFeatures = enabledFeatures, Recipe = Recipe, }; _setupService.Setup(setupContext); Context.Output.WriteLine(T("Site \"{0}\" successfully setup to run data provider \"{1}\" (with table prefix \"{2}\") and configured by recipe \"{3}\"", setupContext.SiteName, setupContext.DatabaseProvider, setupContext.DatabaseTablePrefix, setupContext.Recipe)); }
public async Task<ActionResult> IndexPOST(SetupViewModel model) { if (!ModelState.IsValid) { return IndexViewResult(model); } var setupContext = new SetupContext { SiteName = model.SiteName, DatabaseProvider = model.DatabaseProvider, DatabaseConnectionString = model.ConnectionString, DatabaseTablePrefix = model.TablePrefix, EnabledFeatures = null, // default list, AdminUsername = model.AdminUserName, AdminEmail = model.AdminEmail, AdminPassword = model.Password }; var executionId = await _setupService.SetupAsync(setupContext); var urlPrefix = ""; if (!String.IsNullOrWhiteSpace(_shellSettings.RequestUrlPrefix)) { urlPrefix = _shellSettings.RequestUrlPrefix + "/"; } // Redirect to the welcome page. // TODO: Redirect on the home page once we don't rely on Orchard.Demo return Redirect("~/" + urlPrefix + "home/index"); }
public ActionResult IndexPOST(SetupViewModel model) { //HACK: (erikpo) Couldn't get a custom ValidationAttribute to validate two properties if (!model.DatabaseOptions && string.IsNullOrEmpty(model.DatabaseConnectionString)) ModelState.AddModelError("DatabaseConnectionString", "A SQL connection string is required"); if (!ModelState.IsValid) { return IndexViewResult(model); } try { var setupContext = new SetupContext { SiteName = model.SiteName, AdminUsername = model.AdminUsername, AdminPassword = model.AdminPassword, DatabaseProvider = model.DatabaseOptions ? "SQLite" : "SqlServer", DatabaseConnectionString = model.DatabaseConnectionString, DatabaseTablePrefix = model.DatabaseTablePrefix, EnabledFeatures = null // default list }; _setupService.Setup(setupContext); // redirect to the welcome page. return Redirect("~/"); } catch (Exception exception) { _notifier.Error(T("Setup failed:")); for (var scan = exception; scan != null; scan = scan.InnerException) { _notifier.Error(scan.Message); } return IndexViewResult(model); } }
public void Setup() { IEnumerable<string> enabledFeatures = null; if (!string.IsNullOrEmpty(this.EnabledFeatures)) { enabledFeatures = this.EnabledFeatures .Split(',') .Select(s => s.Trim()) .Where(s => !string.IsNullOrEmpty(s)); } var setupContext = new SetupContext { SiteName = this.SiteName, AdminUsername = this.AdminUsername, AdminPassword = this.AdminPassword, DatabaseProvider = this.DatabaseProvider, DatabaseConnectionString = this.DatabaseConnectionString, DatabaseTablePrefix = this.DatabaseTablePrefix, EnabledFeatures = enabledFeatures }; _setupService.Setup(setupContext); Context.Output.WriteLine(T("Site \"{0}\" sucessfully setup to run data provider \"{1}\" (with table prefix \"{2}\").", setupContext.SiteName, setupContext.DatabaseProvider, setupContext.DatabaseTablePrefix)); }
public string SetupInternal(SetupContext context) { string executionId; _logger.LogInformation("Running setup for tenant '{0}'.", _shellSettings.Name); // The vanilla Orchard distibution has the following features enabled. string[] hardcoded = { // Framework "Orchard.Hosting", // Core "Settings", // Test Modules "Orchard.Demo", "Orchard.Test1" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); shellSettings.DatabaseProvider = context.DatabaseProvider; shellSettings.ConnectionString = context.DatabaseConnectionString; shellSettings.TablePrefix = context.DatabaseTablePrefix; //if (shellSettings.DataProviders.Any()) { // DataProvider provider = new DataProvider(); //shellSettings.DataProvider = context.DatabaseProvider; //shellSettings.DataConnectionString = context.DatabaseConnectionString; //shellSettings.DataTablePrefix = context.DatabaseTablePrefix; //} // TODO: Add Encryption Settings in var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }).ToList() }; // creating a standalone environment. // 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 using (var environment = _orchardHost.CreateShellContext(shellSettings)) { executionId = CreateTenantData(context, environment); using (var store = (IStore)environment.ServiceProvider.GetService(typeof(IStore))) { store.InitializeAsync(); } } shellSettings.State = TenantState.Running; _orchardHost.UpdateShellSettings(shellSettings); return executionId; }
public string Setup(SetupContext context) { var initialState = _shellSettings.State; try { return SetupInternal(context); } catch { _shellSettings.State = initialState; throw; } }
public async Task<string> SetupAsync(SetupContext context) { var initialState = _shellSettings.State; try { return await SetupInternalAsync(context); } catch { _shellSettings.State = initialState; throw; } }
public string Setup(SetupContext context) { string executionId = Guid.NewGuid().ToString(); // The vanilla Orchard distibution has the following features enabled. string[] hardcoded = { // Framework "Orchard.Hosting", // Core "Settings", // Test Modules "Orchard.Demo", "Orchard.Test1" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList(); var shellSettings = new ShellSettings(); shellSettings.Name = context.SiteName; //if (shellSettings.DataProviders.Any()) { // DataProvider provider = new DataProvider(); //shellSettings.DataProvider = context.DatabaseProvider; //shellSettings.DataConnectionString = context.DatabaseConnectionString; //shellSettings.DataTablePrefix = context.DatabaseTablePrefix; //} // TODO: Add Encryption Settings in var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }) }; // creating a standalone environment. // 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 // must mark state as Running - otherwise standalone enviro is created "for setup" shellSettings.State = TenantState.Running; // TODO: Remove and mirror Orchard Setup shellSettings.RequestUrlHost = _httpContextAccessor.HttpContext.Request.Host.Value; shellSettings.RequestUrlPrefix = string.Empty; //shellSettings.DataProvider = "InMemory"; _shellSettingsManager.SaveSettings(shellSettings); return executionId; }
public ActionResult IndexPOST(SetupViewModel model) { if (!ModelState.IsValid) { return IndexViewResult(model); } var setupContext = new SetupContext { SiteName = model.SiteName, EnabledFeatures = null, // default list }; var executionId = _setupService.Setup(setupContext); // redirect to the welcome page. return Redirect("~/" + _shellSettings.RequestUrlPrefix + "home/index"); }
public async Task<ActionResult> IndexPOST(SetupViewModel model) { model.DatabaseProviders = GetDatabaseProviders(); model.Recipes = await _setupService.GetSetupRecipesAsync(); var selectedProvider = model.DatabaseProviders.FirstOrDefault(x => x.Value == model.DatabaseProvider); if (selectedProvider != null && selectedProvider.HasConnectionString && String.IsNullOrWhiteSpace(model.ConnectionString)) { ModelState.AddModelError("ConnectionString", T["The connection string is mandatory for this provider"]); } if (String.IsNullOrEmpty(model.Password)) { ModelState.AddModelError(nameof(model.Password), T["The password is required"]); } if (model.Password != model.PasswordConfirmation) { ModelState.AddModelError(nameof(model.PasswordConfirmation), T["The password confirmation doesn't match the password."]); } RecipeDescriptor selectedRecipe = null; if (String.IsNullOrEmpty(model.RecipeName) || (selectedRecipe = model.Recipes.FirstOrDefault(x => x.Name == model.RecipeName)) == null) { ModelState.AddModelError(nameof(model.RecipeName), T["Invalid recipe."]); } if (!ModelState.IsValid) { return View(model); } var setupContext = new SetupContext { SiteName = model.SiteName, DatabaseProvider = model.DatabaseProvider, DatabaseConnectionString = model.ConnectionString, DatabaseTablePrefix = model.TablePrefix, EnabledFeatures = null, // default list, AdminUsername = model.AdminUserName, AdminEmail = model.AdminEmail, AdminPassword = model.Password, Errors = new Dictionary<string, string>(), Recipe = selectedRecipe }; var executionId = await _setupService.SetupAsync(setupContext); // Check if a component in the Setup failed if (setupContext.Errors.Any()) { foreach (var error in setupContext.Errors) { ModelState.AddModelError(error.Key, error.Value); } return View(model); } var urlPrefix = ""; if (!String.IsNullOrWhiteSpace(_shellSettings.RequestUrlPrefix)) { urlPrefix = _shellSettings.RequestUrlPrefix + "/"; } return Redirect("~/" + urlPrefix); }
public ActionResult IndexPOST(SetupViewModel model) { var recipes = OrderRecipes(_setupService.Recipes()); // if no builtin provider, a connection string is mandatory if (model.DatabaseProvider != SetupDatabaseType.Builtin && string.IsNullOrEmpty(model.DatabaseConnectionString)) ModelState.AddModelError("DatabaseConnectionString", "قربون، رشته اتصال لازمه ها!"); if (!String.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword ) { ModelState.AddModelError("ConfirmPassword", "قربونت برم، رمزهای عبوری که وارد کردی مثل هم نیستن."); } if (model.DatabaseProvider != SetupDatabaseType.Builtin && !String.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) { model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim(); if(!Char.IsLetter(model.DatabaseTablePrefix[0])) { ModelState.AddModelError("DatabaseTablePrefix", "شرمنده، ولی پیشوندهای جدول ها باید حتما با حرف شروع بشه"); } if(model.DatabaseTablePrefix.Any(x => !Char.IsLetterOrDigit(x))) { ModelState.AddModelError("DatabaseTablePrefix", "قربونت برم، پیشوندهای جدول ها فقط میتونه حرف یا عدد باشه، چیز دیگه نمیشه"); } } if (model.Recipe == null) { if (!(recipes.Select(r => r.Name).Contains(DefaultRecipe))) { ModelState.AddModelError("Recipe", "دستور پخت ها رو توی ماژول Setup پیدا نکردم. ببینم، ارچاردفا رو دستکاری کردی؟"); } else { model.Recipe = DefaultRecipe; } } if (!ModelState.IsValid) { model.Recipes = recipes; foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); return IndexViewResult(model); } try { string providerName = null; switch (model.DatabaseProvider) { case SetupDatabaseType.Builtin: providerName = "SqlCe"; break; case SetupDatabaseType.SqlServer: providerName = "SqlServer"; break; case SetupDatabaseType.MySql: providerName = "MySql"; break; default: throw new ApplicationException("Unknown database type: " + model.DatabaseProvider); } var setupContext = new SetupContext { SiteName = model.SiteName, AdminUsername = model.AdminUsername, AdminPassword = model.AdminPassword, DatabaseProvider = providerName, DatabaseConnectionString = model.DatabaseConnectionString, DatabaseTablePrefix = model.DatabaseTablePrefix, EnabledFeatures = null, // default list Recipe = model.Recipe }; string executionId = _setupService.Setup(setupContext); // 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 // uses a "single lock" mechanism for compiling views). _viewsBackgroundCompilation.Stop(); // redirect to the welcome page. return Redirect("~/" + _shellSettings.RequestUrlPrefix); } catch (Exception ex) { Logger.Error(ex, "Setup failed"); _notifier.Error(new LocalizedString(string.Format("اوخیش، راه اندازی به خطا خورد: {0}", ex.Message))); model.Recipes = recipes; foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); return IndexViewResult(model); } }
public string SetupInternal(SetupContext context) { string executionId; _logger.LogInformation("Running setup for tenant '{0}'.", _shellSettings.Name); // The vanilla Orchard distibution has the following features enabled. string[] hardcoded = { // Framework "Orchard.Hosting", // Core "Settings", // Test Modules "Orchard.Demo", "Orchard.Test1" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty <string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); shellSettings.DatabaseProvider = context.DatabaseProvider; shellSettings.ConnectionString = context.DatabaseConnectionString; shellSettings.TablePrefix = context.DatabaseTablePrefix; //if (shellSettings.DataProviders.Any()) { // DataProvider provider = new DataProvider(); //shellSettings.DataProvider = context.DatabaseProvider; //shellSettings.DataConnectionString = context.DatabaseConnectionString; //shellSettings.DataTablePrefix = context.DatabaseTablePrefix; //} // TODO: Add Encryption Settings in var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }).ToList() }; // creating a standalone environment. // 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 using (var environment = _orchardHost.CreateShellContext(shellSettings)) { executionId = CreateTenantData(context, environment); using (var store = (IStore)environment.ServiceProvider.GetService(typeof(IStore))) { store.InitializeAsync(); } } shellSettings.State = TenantState.Running; _orchardHost.UpdateShellSettings(shellSettings); return(executionId); }
private string Setup(XDocument recipeDocument) { // Prepare Setup. var setupContext = new SetupContext { Recipe = _recipeParser.ParseRecipe(recipeDocument), AdminPassword = SuperUserPassword, AdminUsername = _orchardServices.WorkContext.CurrentSite.SuperUser, DatabaseConnectionString = _shellSettings.DataConnectionString, DatabaseProvider = _shellSettings.DataProvider, DatabaseTablePrefix = _shellSettings.DataTablePrefix, SiteName = _orchardServices.WorkContext.CurrentSite.SiteName, EnabledFeatures = Enumerable.Empty<string>() }; // Delete the tenant tables. DropTenantDatabaseTables(); // Execute Setup. var executionId = _setupService.Setup(setupContext); return executionId; }
private string CreateTenantData(SetupContext context, IWorkContextScope environment) { // create superuser var membershipService = environment.Resolve<IMembershipService>(); var user = membershipService.CreateUser(new CreateUserParams(context.AdminUsername, context.AdminPassword, String.Empty, String.Empty, String.Empty, true)); // set superuser as current user for request (it will be set as the owner of all content items) var authenticationService = environment.Resolve<IAuthenticationService>(); authenticationService.SetAuthenticatedUserForRequest(user); // set site name and settings var siteService = environment.Resolve<ISiteService>(); var siteSettings = siteService.GetSiteSettings().As<SiteSettingsPart>(); siteSettings.Record.SiteSalt = Guid.NewGuid().ToString("N"); siteSettings.Record.SiteName = context.SiteName; siteSettings.Record.SuperUser = context.AdminUsername; siteSettings.Record.SiteCulture = "en-US"; // add default culture var cultureManager = environment.Resolve<ICultureManager>(); cultureManager.AddCulture("en-US"); var recipeManager = environment.Resolve<IRecipeManager>(); string executionId = recipeManager.Execute(Recipes().FirstOrDefault(r => r.Name.Equals(context.Recipe, StringComparison.OrdinalIgnoreCase))); // null check: temporary fix for running setup in command line if (HttpContext.Current != null) { authenticationService.SignIn(user, true); } return executionId; }
private string CreateTenantData(SetupContext context, ShellContext shellContext) { // Must mark state as Running - otherwise standalone enviro is created "for setup" return(Guid.NewGuid().ToString()); }
public async Task<string> SetupInternalAsync(SetupContext context) { string executionId; if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Running setup for tenant '{0}'.", _shellSettings.Name); } // Features to enable for Setup string[] hardcoded = { "Orchard.Hosting" // shortcut for built-in features }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DatabaseProvider)) { shellSettings.DatabaseProvider = context.DatabaseProvider; shellSettings.ConnectionString = context.DatabaseConnectionString; shellSettings.TablePrefix = context.DatabaseTablePrefix; } // Creating a standalone environment based on a "minimum shell descriptor". // 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 // It is used to initialize the database before the recipe is run. using (var shellContext = _orchardHost.CreateShellContext(shellSettings)) { using (var scope = shellContext.CreateServiceScope()) { executionId = CreateTenantData(context, shellContext); var store = scope.ServiceProvider.GetRequiredService<IStore>(); await store.InitializeAsync(); // Create the "minimum shell descriptor" await scope .ServiceProvider .GetService<IShellDescriptorManager>() .UpdateShellDescriptorAsync( 0, shellContext.Blueprint.Descriptor.Features, shellContext.Blueprint.Descriptor.Parameters); // Apply all migrations for the newly initialized tenant var dataMigrationManager = scope.ServiceProvider.GetService<IDataMigrationManager>(); await dataMigrationManager.UpdateAllFeaturesAsync(); var deferredTaskEngine = scope.ServiceProvider.GetService<IDeferredTaskEngine>(); if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks) { var taskContext = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(taskContext); } // Invoke modules to react to the setup event var eventBus = scope.ServiceProvider.GetService<IEventBus>(); await eventBus.NotifyAsync<ISetupEventHandler>(x => x.Setup( context.SiteName, context.AdminUsername, context.AdminEmail, context.AdminPassword, context.DatabaseProvider, context.DatabaseConnectionString, context.DatabaseTablePrefix) ); if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks) { var taskContext = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(taskContext); } } } shellSettings.State = TenantState.Running; _orchardHost.UpdateShellSettings(shellSettings); return executionId; }
public async Task<string> SetupInternalAsync(SetupContext context) { string executionId; if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Running setup for tenant '{0}'.", _shellSettings.Name); } // Features to enable for Setup string[] hardcoded = { "Orchard.Hosting", // shortcut for built-in features "Orchard.Modules", "Orchard.Recipes" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DatabaseProvider)) { shellSettings.DatabaseProvider = context.DatabaseProvider; shellSettings.ConnectionString = context.DatabaseConnectionString; shellSettings.TablePrefix = context.DatabaseTablePrefix; } // Creating a standalone environment based on a "minimum shell descriptor". // 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 // It is used to initialize the database before the recipe is run. var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }).ToList() }; using (var shellContext = _shellContextFactory.CreateDescribedContext(shellSettings, shellDescriptor)) { using (var scope = shellContext.CreateServiceScope()) { var store = scope.ServiceProvider.GetRequiredService<IStore>(); try { await store.InitializeAsync(); } catch { // Tables already exist or database was not found // The issue is that the user creation needs the tables to be present, // if the user information is not valid, the next POST will try to recreate the // tables. The tables should be rollbacked if one of the steps is invalid, // unless the recipe is executing? } // Create the "minimum shell descriptor" await scope .ServiceProvider .GetService<IShellDescriptorManager>() .UpdateShellDescriptorAsync(0, shellContext.Blueprint.Descriptor.Features, shellContext.Blueprint.Descriptor.Parameters); // Apply all migrations for the newly initialized tenant var dataMigrationManager = scope.ServiceProvider.GetService<IDataMigrationManager>(); await dataMigrationManager.UpdateAllFeaturesAsync(); var deferredTaskEngine = scope.ServiceProvider.GetService<IDeferredTaskEngine>(); if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks) { var taskContext = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(taskContext); } } _orchardHost.UpdateShellSettings(shellSettings); executionId = Guid.NewGuid().ToString("n"); // Create a new scope for the recipe thread to prevent race issues with other scoped // services from the request. using (var scope = shellContext.CreateServiceScope()) { var recipeExecutor = scope.ServiceProvider.GetService<IRecipeExecutor>(); // Right now we run the recipe in the same thread, later use polling from the setup screen // to query the current execution. //await Task.Run(async () => //{ await recipeExecutor.ExecuteAsync(executionId, context.Recipe); //}); } } // Reloading the shell context as the recipe has probably updated its features using (var shellContext = _orchardHost.CreateShellContext(shellSettings)) { using (var scope = shellContext.CreateServiceScope()) { // Apply all migrations for the newly initialized tenant var dataMigrationManager = scope.ServiceProvider.GetService<IDataMigrationManager>(); await dataMigrationManager.UpdateAllFeaturesAsync(); bool hasErrors = false; Action<string, string> reportError = (key, message) => { hasErrors = true; context.Errors[key] = message; }; // Invoke modules to react to the setup event var eventBus = scope.ServiceProvider.GetService<IEventBus>(); await eventBus.NotifyAsync<ISetupEventHandler>(x => x.Setup( context.SiteName, context.AdminUsername, context.AdminEmail, context.AdminPassword, context.DatabaseProvider, context.DatabaseConnectionString, context.DatabaseTablePrefix, reportError )); if (hasErrors) { // TODO: check why the tables creation is not reverted var session = scope.ServiceProvider.GetService<YesSql.Core.Services.ISession>(); session.Cancel(); return executionId; } var deferredTaskEngine = scope.ServiceProvider.GetService<IDeferredTaskEngine>(); if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks) { var taskContext = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(taskContext); } } // Update the shell state shellSettings.State = TenantState.Running; _orchardHost.UpdateShellSettings(shellSettings); } return executionId; }
public string Setup(SetupContext context) { string executionId; // The vanilla Orchard distibution has the following features enabled. string[] hardcoded = { // Framework "Orchard.Framework", // Core "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation", "Reports", "Scheduling", "Settings", "Shapes", "Title", // Modules "Orchard.Pages", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules", "PackagingServices","Orchard.Packaging", "Gallery", "Orchard.Recipes" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty <string>()).Distinct().ToList(); var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DataProvider)) { shellSettings.DataProvider = context.DatabaseProvider; shellSettings.DataConnectionString = context.DatabaseConnectionString; shellSettings.DataTablePrefix = context.DatabaseTablePrefix; } #region Encryption Settings shellSettings.EncryptionAlgorithm = "AES"; // randomly generated key shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString(); shellSettings.HashAlgorithm = "HMACSHA256"; // randomly generated key shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString(); #endregion var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }) }; var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor); // initialize database explicitly, and store shell descriptor using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) { using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) { // check if the database is already created (in case an exception occured in the second phase) var shellDescriptorRepository = environment.Resolve <IRepository <ShellDescriptorRecord> >(); try { shellDescriptorRepository.Get(x => true); } catch { var schemaBuilder = new SchemaBuilder(environment.Resolve <IDataMigrationInterpreter>()); var reportsCoordinator = environment.Resolve <IReportsCoordinator>(); reportsCoordinator.Register("Data Migration", "Setup", "Orchard installation"); schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table .Column <int>("Id", column => column.PrimaryKey().Identity()) .Column <string>("DataMigrationClass") .Column <int>("Version")); var dataMigrationManager = environment.Resolve <IDataMigrationManager>(); dataMigrationManager.Update("Settings"); foreach (var feature in context.EnabledFeatures) { dataMigrationManager.Update(feature); } environment.Resolve <IShellDescriptorManager>().UpdateShellDescriptor( 0, shellDescriptor.Features, shellDescriptor.Parameters); } } } // in effect "pump messages" see PostMessage circa 1980 while (_processingEngine.AreTasksPending()) { _processingEngine.ExecuteNextTask(); } // creating a standalone environment. // 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 // must mark state as Running - otherwise standalone enviro is created "for setup" shellSettings.State = new TenantState("Running"); using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) { try { executionId = CreateTenantData(context, environment); } catch { environment.Resolve <ITransactionManager>().Cancel(); throw; } } _shellSettingsManager.SaveSettings(shellSettings); return(executionId); }
public async Task <string> SetupInternalAsync(SetupContext context) { string executionId; if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Running setup for tenant '{0}'.", _shellSettings.Name); } // Features to enable for Setup string[] hardcoded = { "Orchard.Commons", "Orchard.Modules", "Orchard.Recipes", "Orchard.Scripting" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty <string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DatabaseProvider)) { shellSettings.DatabaseProvider = context.DatabaseProvider; shellSettings.ConnectionString = context.DatabaseConnectionString; shellSettings.TablePrefix = context.DatabaseTablePrefix; } // Creating a standalone environment based on a "minimum shell descriptor". // 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 // It is used to initialize the database before the recipe is run. var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(id => new ShellFeature { Id = id }).ToList() }; using (var shellContext = await _shellContextFactory.CreateDescribedContextAsync(shellSettings, shellDescriptor)) { using (var scope = shellContext.CreateServiceScope()) { var store = scope.ServiceProvider.GetRequiredService <IStore>(); try { await store.InitializeAsync(); } catch (Exception e) { // Tables already exist or database was not found // The issue is that the user creation needs the tables to be present, // if the user information is not valid, the next POST will try to recreate the // tables. The tables should be rolled back if one of the steps is invalid, // unless the recipe is executing? _logger.LogError("An error occurred while initializing the datastore.", e); context.Errors.Add("DatabaseProvider", T["An error occurred while initializing the datastore: {0}", e.Message]); return(null); } // Create the "minimum shell descriptor" await scope .ServiceProvider .GetService <IShellDescriptorManager>() .UpdateShellDescriptorAsync(0, shellContext.Blueprint.Descriptor.Features, shellContext.Blueprint.Descriptor.Parameters); var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>(); if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks) { var taskContext = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(taskContext); } } executionId = Guid.NewGuid().ToString("n"); // Create a new scope for the recipe thread to prevent race issues with other scoped // services from the request. using (var scope = shellContext.CreateServiceScope()) { var recipeExecutor = scope.ServiceProvider.GetService <IRecipeExecutor>(); // Right now we run the recipe in the same thread, later use polling from the setup screen // to query the current execution. //await Task.Run(async () => //{ await recipeExecutor.ExecuteAsync(executionId, context.Recipe, new { SiteName = context.SiteName, AdminUsername = context.AdminUsername, AdminEmail = context.AdminEmail, AdminPassword = context.AdminPassword, DatabaseProvider = context.DatabaseProvider, DatabaseConnectionString = context.DatabaseConnectionString, DatabaseTablePrefix = context.DatabaseTablePrefix }); //}); } } // Reloading the shell context as the recipe has probably updated its features using (var shellContext = await _orchardHost.CreateShellContextAsync(shellSettings)) { using (var scope = shellContext.CreateServiceScope()) { bool hasErrors = false; Action <string, string> reportError = (key, message) => { hasErrors = true; context.Errors[key] = message; }; // Invoke modules to react to the setup event var eventBus = scope.ServiceProvider.GetService <IEventBus>(); await eventBus.NotifyAsync <ISetupEventHandler>(x => x.Setup( context.SiteName, context.AdminUsername, context.AdminEmail, context.AdminPassword, context.DatabaseProvider, context.DatabaseConnectionString, context.DatabaseTablePrefix, reportError )); if (hasErrors) { return(executionId); } var deferredTaskEngine = scope.ServiceProvider.GetService <IDeferredTaskEngine>(); if (deferredTaskEngine != null && deferredTaskEngine.HasPendingTasks) { var taskContext = new DeferredTaskContext(scope.ServiceProvider); await deferredTaskEngine.ExecuteTasksAsync(taskContext); } } } // Update the shell state shellSettings.State = TenantState.Running; _orchardHost.UpdateShellSettings(shellSettings); return(executionId); }
public async Task <string> SetupInternalAsync(SetupContext context) { string executionId; if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Running setup for tenant '{0}'.", _shellSettings.Name); } // Features to enable for Setup string[] hardcoded = { "Orchard.Hosting", "Orchard.Settings", }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty <string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DatabaseProvider)) { shellSettings.DatabaseProvider = context.DatabaseProvider; shellSettings.ConnectionString = context.DatabaseConnectionString; shellSettings.TablePrefix = context.DatabaseTablePrefix; } // TODO: Add Encryption Settings in // Creating a standalone environment based on a "minimum shell descriptor". // 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 // It is used to initialize the database before the recipe is run. using (var environment = _orchardHost.CreateShellContext(shellSettings)) { using (var scope = environment.CreateServiceScope()) { executionId = CreateTenantData(context, environment); var store = scope.ServiceProvider.GetRequiredService <IStore>(); await store.InitializeAsync(); // Create the "minimum shell descriptor" await scope .ServiceProvider .GetService <IShellDescriptorManager>() .UpdateShellDescriptorAsync( 0, environment.Blueprint.Descriptor.Features, environment.Blueprint.Descriptor.Parameters); } using (var scope = environment.CreateServiceScope()) { // Apply all migrations for the newly initialized tenant var dataMigrationManager = scope.ServiceProvider.GetService <IDataMigrationManager>(); await dataMigrationManager.UpdateAllFeaturesAsync(); // Invoke modules to react to the setup event var eventBus = scope.ServiceProvider.GetService <IEventBus>(); await eventBus.NotifyAsync <ISetupEventHandler>(x => x.Setup( context.SiteName, context.AdminUsername, context.AdminEmail, context.AdminPassword, context.DatabaseProvider, context.DatabaseConnectionString, context.DatabaseTablePrefix) ); } } shellSettings.State = TenantState.Running; _runningShellRouterTable.Remove(shellSettings.Name); _orchardHost.UpdateShellSettings(shellSettings); return(executionId); }
public string SetupInternal(SetupContext context) { string executionId; if (_logger.IsEnabled(LogLevel.Information)) { _logger.LogInformation("Running setup for tenant '{0}'.", _shellSettings.Name); } // Features to enable for Setup string[] hardcoded = { // Framework "Orchard.Hosting", // Core "Settings" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DatabaseProvider)) { shellSettings.DatabaseProvider = context.DatabaseProvider; shellSettings.ConnectionString = context.DatabaseConnectionString; shellSettings.TablePrefix = context.DatabaseTablePrefix; } // TODO: Add Encryption Settings in // Creating a standalone environment based on a "minimum shell descriptor". // 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 // It is used to initialize the database before the recipe is run. using (var environment = _orchardHost.CreateShellContext(shellSettings)) { using (var scope = environment.CreateServiceScope()) { executionId = CreateTenantData(context, environment); var store = scope.ServiceProvider.GetRequiredService<IStore>(); store.InitializeAsync(); // Create the "minimum shell descriptor" scope .ServiceProvider .GetService<IShellDescriptorManager>() .UpdateShellDescriptorAsync( 0, environment.Blueprint.Descriptor.Features, environment.Blueprint.Descriptor.Parameters).Wait(); } } shellSettings.State = TenantState.Running; _runningShellRouterTable.Remove(shellSettings.Name); _orchardHost.UpdateShellSettings(shellSettings); return executionId; }
public void Setup(SetupContext context) { // The vanilla Orchard distibution has the following features enabled. if (context.EnabledFeatures == null || context.EnabledFeatures.Count() == 0) { string[] hardcoded = { "Orchard.Framework", "Common", "Dashboard", "Feeds", "HomePage", "Navigation", "Scheduling", "Settings", "XmlRpc", "Orchard.Users", "Orchard.Roles", "TinyMce", "Orchard.Modules", "Orchard.Themes", "Orchard.Pages", "Orchard.Blogs", "Orchard.Comments", "Orchard.Tags", "Orchard.Media", "Futures.Widgets"}; context.EnabledFeatures = hardcoded; } var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DataProvider)) { shellSettings.DataProvider = context.DatabaseProvider; shellSettings.DataConnectionString = context.DatabaseConnectionString; shellSettings.DataTablePrefix = context.DatabaseTablePrefix; } var shellDescriptor = new ShellDescriptor { EnabledFeatures = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }) }; var shellToplogy = _compositionStrategy.Compose(shellSettings, shellDescriptor); // initialize database explicitly, and store shell descriptor var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellToplogy); using (var environment = new StandaloneEnvironment(bootstrapLifetimeScope)) { environment.Resolve<ISessionFactoryHolder>().CreateDatabase(); environment.Resolve<IShellDescriptorManager>().UpdateShellDescriptor( 0, shellDescriptor.EnabledFeatures, shellDescriptor.Parameters); } // creating a standalone environment. // 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 // must mark state as Running - otherwise standalone enviro is created "for setup" shellSettings.State = new TenantState("Running"); using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) { try { // create superuser var membershipService = environment.Resolve<IMembershipService>(); var user = membershipService.CreateUser(new CreateUserParams(context.AdminUsername, context.AdminPassword, String.Empty, String.Empty, String.Empty, true)); // set site name and settings var siteService = environment.Resolve<ISiteService>(); var siteSettings = siteService.GetSiteSettings().As<SiteSettings>(); siteSettings.Record.SiteSalt = Guid.NewGuid().ToString("N"); siteSettings.Record.SiteName = context.SiteName; siteSettings.Record.SuperUser = context.AdminUsername; siteSettings.Record.PageTitleSeparator = " - "; // set site theme var themeService = environment.Resolve<IThemeService>(); themeService.SetSiteTheme("Classic"); var contentManager = environment.Resolve<IContentManager>(); // simulate installation-time module activation events var hackInstallationGenerator = environment.Resolve<IHackInstallationGenerator>(); hackInstallationGenerator.GenerateInstallEvents(); // create home page as a CMS page var page = contentManager.Create("page", VersionOptions.Draft); page.As<BodyAspect>().Text = "<p>Welcome to Orchard!</p><p>Congratulations, you've successfully set-up your Orchard site.</p><p>This is the home page of your new site. We've taken the liberty to write here about a few things you could look at next in order to get familiar with the application. Once you feel confident you don't need this anymore, just click <a href=\"Admin/Pages/Edit/3\">Edit</a> to go into edit mode and replace this with whatever you want on your home page to make it your own.</p><p>One thing you could do (but you don't have to) is go into <a href=\"Admin/Settings\">Manage Settings</a> (follow the <a href=\"Admin\">Admin</a> link and then look for it under \"Settings\" in the menu on the left) and check that everything is configured the way you want.</p><p>You probably want to make the site your own. One of the ways you can do that is by clicking <a href=\"Admin/Themes\">Manage Themes</a> in the admin menu. A theme is a packaged look and feel that affects the whole site.</p><p>Next, you can start playing with the content types that we installed. For example, go ahead and click <a href=\"Admin/Pages/Create\">Add New Page</a> in the admin menu and create an \"about\" page. Then, add it to the navigation menu by going to <a href=\"Admin/Navigation\">Manage Menu</a>. You can also click <a href=\"Admin/Blogs/Create\">Add New Blog</a> and start posting by clicking \"Add New Post\".</p><p>Finally, Orchard has been designed to be extended. It comes with a few built-in modules such as pages and blogs or themes. You can install new themes by going to <a href=\"Admin/Themes\">Manage Themes</a> and clicking <a href=\"Admin/Themes/Install\">Install a new Theme</a>. Like for themes, modules are created by other users of Orchard just like you so if you feel up to it, please <a href=\"http://www.orchardproject.net/\">consider participating</a>.</p><p>--The Orchard Crew</p>"; page.As<RoutableAspect>().Slug = "home"; page.As<RoutableAspect>().Title = T("Home").ToString(); page.As<CommonAspect>().Owner = user; if (page.Has<HasComments>()) { page.As<HasComments>().CommentsShown = false; } contentManager.Publish(page); siteSettings.Record.HomePage = "PageHomePageProvider;" + page.Id; // add a menu item for the shiny new home page var menuItem = contentManager.Create("menuitem"); menuItem.As<MenuPart>().MenuPosition = "1"; menuItem.As<MenuPart>().MenuText = T("Home").ToString(); menuItem.As<MenuPart>().OnMainMenu = true; menuItem.As<MenuItem>().Url = ""; //Temporary fix for running setup on command line if (HttpContext.Current != null) { var authenticationService = environment.Resolve<IAuthenticationService>(); authenticationService.SignIn(user, true); } //Add ContentType mappings var contentTypeService = environment.Resolve<IContentTypeService>(); //Add ContentTypePartNames to MetaData contentTypeService.AddContentTypePartNameToMetaData("HasComments"); contentTypeService.AddContentTypePartNameToMetaData("HasTags"); //Add mappings from ContentTypes to ContentParts to MetaData contentTypeService.MapContentTypeToContentPart("blogpost","HasComments"); contentTypeService.MapContentTypeToContentPart("page", "HasComments"); contentTypeService.MapContentTypeToContentPart("sandboxpage", "HasComments"); contentTypeService.MapContentTypeToContentPart("blogpost", "HasTags"); contentTypeService.MapContentTypeToContentPart("page", "HasTags"); contentTypeService.MapContentTypeToContentPart("sandboxpage", "HasTags"); } catch { environment.Resolve<ITransactionManager>().Cancel(); throw; } } _shellSettingsManager.SaveSettings(shellSettings); }
private string SetupInternal(SetupContext context) { string executionId; Logger.Information("Running setup for tenant '{0}'.", _shellSettings.Name); // The vanilla Orchard distibution has the following features enabled. string[] hardcoded = { // Framework "Orchard.Framework", // Core "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation","Scheduling", "Settings", "Shapes", "Title", // Modules "Orchard.Pages", "Orchard.ContentPicker", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules", "PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList(); // Set shell state to "Initializing" so that subsequent HTTP requests are responded to with "Service Unavailable" while Orchard is setting up. _shellSettings.State = TenantState.Initializing; var shellSettings = new ShellSettings(_shellSettings); if (String.IsNullOrEmpty(shellSettings.DataProvider)) { shellSettings.DataProvider = context.DatabaseProvider; shellSettings.DataConnectionString = context.DatabaseConnectionString; shellSettings.DataTablePrefix = context.DatabaseTablePrefix; } shellSettings.EncryptionAlgorithm = "AES"; // Randomly generated key. shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString(); shellSettings.HashAlgorithm = "HMACSHA256"; // Randomly generated key. shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString(); var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }) }; var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor); // Initialize database explicitly, and store shell descriptor. using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) { using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) { // Check if the database is already created (in case an exception occured in the second phase). var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>()); var installationPresent = true; try { var tablePrefix = String.IsNullOrEmpty(shellSettings.DataTablePrefix) ? "" : shellSettings.DataTablePrefix + "_"; schemaBuilder.ExecuteSql("SELECT * FROM " + tablePrefix + "Settings_ShellDescriptorRecord"); } catch { installationPresent = false; } if (installationPresent) { throw new OrchardException(T("A previous Orchard installation was detected in this database with this table prefix.")); } // Workaround to avoid some Transaction issue for PostgreSQL. environment.Resolve<ITransactionManager>().RequireNew(); schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table .Column<int>("Id", column => column.PrimaryKey().Identity()) .Column<string>("DataMigrationClass") .Column<int>("Version")); schemaBuilder.AlterTable("Orchard_Framework_DataMigrationRecord", table => table.AddUniqueConstraint("UC_DMR_DataMigrationClass_Version", "DataMigrationClass", "Version")); var dataMigrationManager = environment.Resolve<IDataMigrationManager>(); dataMigrationManager.Update("Settings"); foreach (var feature in context.EnabledFeatures) { dataMigrationManager.Update(feature); } environment.Resolve<IShellDescriptorManager>().UpdateShellDescriptor( 0, shellDescriptor.Features, shellDescriptor.Parameters); } } // In effect "pump messages" see PostMessage circa 1980. while (_processingEngine.AreTasksPending()) _processingEngine.ExecuteNextTask(); // Creating a standalone environment. // 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. using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) { try { executionId = CreateTenantData(context, environment); } catch { environment.Resolve<ITransactionManager>().Cancel(); throw; } } _shellSettingsManager.SaveSettings(shellSettings); return executionId; }
private string CreateTenantData(SetupContext context, IWorkContextScope environment) { // Create site owner. var membershipService = environment.Resolve<IMembershipService>(); var user = membershipService.CreateUser( new CreateUserParams(context.AdminUsername, context.AdminPassword, String.Empty, String.Empty, String.Empty, true)); // Set site owner as current user for request (it will be set as the owner of all content items). var authenticationService = environment.Resolve<IAuthenticationService>(); authenticationService.SetAuthenticatedUserForRequest(user); // Set site name and settings. var siteService = environment.Resolve<ISiteService>(); var siteSettings = siteService.GetSiteSettings().As<SiteSettingsPart>(); siteSettings.SiteSalt = Guid.NewGuid().ToString("N"); siteSettings.SiteName = context.SiteName; siteSettings.SuperUser = context.AdminUsername; siteSettings.SiteCulture = "en-US"; // Add default culture. var cultureManager = environment.Resolve<ICultureManager>(); cultureManager.AddCulture("en-US"); var recipeManager = environment.Resolve<IRecipeManager>(); var recipe = context.Recipe; var executionId = recipeManager.Execute(recipe); // 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) { authenticationService.SignIn(user, true); } return executionId; }
private string CreateTenantData(SetupContext context, ShellContext shellContext) { // must mark state as Running - otherwise standalone enviro is created "for setup" return Guid.NewGuid().ToString(); }
public ActionResult IndexPOST(SetupViewModel model) { var recipes = OrderRecipes(_setupService.Recipes()); //TODO: Couldn't get a custom ValidationAttribute to validate two properties if (!model.DatabaseOptions && string.IsNullOrEmpty(model.DatabaseConnectionString)) ModelState.AddModelError("DatabaseConnectionString", T("A SQL connection string is required").Text); if (!String.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword ) { ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match").Text); } if(!model.DatabaseOptions && !String.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) { model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim(); if(!Char.IsLetter(model.DatabaseTablePrefix[0])) { ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter").Text); } } if (model.Recipe == null) { if (!(recipes.Select(r => r.Name).Contains(DefaultRecipe))) { ModelState.AddModelError("Recipe", T("No recipes were found in the Setup module").Text); } else { model.Recipe = DefaultRecipe; } } if (!ModelState.IsValid) { model.Recipes = recipes; foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); return IndexViewResult(model); } try { var setupContext = new SetupContext { SiteName = model.SiteName, AdminUsername = model.AdminUsername, AdminPassword = model.AdminPassword, DatabaseProvider = model.DatabaseOptions ? "SqlCe" : "SqlServer", DatabaseConnectionString = model.DatabaseConnectionString, DatabaseTablePrefix = model.DatabaseTablePrefix, EnabledFeatures = null, // default list Recipe = model.Recipe }; string executionId = _setupService.Setup(setupContext); // 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 // uses a "single lock" mechanism for compiling views). _viewsBackgroundCompilation.Stop(); // redirect to the welcome page. return Redirect("~/"); } catch (Exception exception) { this.Error(exception, T("Setup failed:"), Logger, _notifier); model.Recipes = recipes; foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); return IndexViewResult(model); } }
public ActionResult IndexPOST(SetupViewModel model) { var recipes = OrderRecipes(_setupService.Recipes()); // if no builtin provider, a connection string is mandatory if (model.DatabaseProvider != SetupDatabaseType.Builtin && string.IsNullOrEmpty(model.DatabaseConnectionString)) ModelState.AddModelError("DatabaseConnectionString", T("A connection string is required").Text); if (!String.IsNullOrWhiteSpace(model.ConfirmPassword) && model.AdminPassword != model.ConfirmPassword ) { ModelState.AddModelError("ConfirmPassword", T("Password confirmation must match").Text); } if (model.DatabaseProvider != SetupDatabaseType.Builtin && !String.IsNullOrWhiteSpace(model.DatabaseTablePrefix)) { model.DatabaseTablePrefix = model.DatabaseTablePrefix.Trim(); if(!Char.IsLetter(model.DatabaseTablePrefix[0])) { ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must begin with a letter").Text); } if(model.DatabaseTablePrefix.Any(x => !Char.IsLetterOrDigit(x))) { ModelState.AddModelError("DatabaseTablePrefix", T("The table prefix must contain letters or digits").Text); } } if (model.Recipe == null) { if (!(recipes.Select(r => r.Name).Contains(DefaultRecipe))) { ModelState.AddModelError("Recipe", T("No recipes were found in the Setup module").Text); } else { model.Recipe = DefaultRecipe; } } if (!ModelState.IsValid) { model.Recipes = recipes; foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); return IndexViewResult(model); } try { string providerName = null; switch (model.DatabaseProvider) { case SetupDatabaseType.Builtin: providerName = "SqlCe"; break; case SetupDatabaseType.SqlServer: providerName = "SqlServer"; break; case SetupDatabaseType.MySql: providerName = "MySql"; break; default: throw new ApplicationException("Unknown database type: " + model.DatabaseProvider); } var setupContext = new SetupContext { SiteName = model.SiteName, AdminUsername = model.AdminUsername, AdminPassword = model.AdminPassword, DatabaseProvider = providerName, DatabaseConnectionString = model.DatabaseConnectionString, DatabaseTablePrefix = model.DatabaseTablePrefix, EnabledFeatures = null, // default list Recipe = model.Recipe }; string executionId = _setupService.Setup(setupContext); // 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 // uses a "single lock" mechanism for compiling views). _viewsBackgroundCompilation.Stop(); // redirect to the welcome page. return Redirect("~/" + _shellSettings.RequestUrlPrefix); } catch (Exception ex) { Logger.Error(ex, "Setup failed"); _notifier.Error(T("Setup failed: {0}", ex.Message)); model.Recipes = recipes; foreach (var recipe in recipes.Where(recipe => recipe.Name == model.Recipe)) { model.RecipeDescription = recipe.Description; } model.DatabaseIsPreconfigured = !string.IsNullOrEmpty(_setupService.Prime().DataProvider); return IndexViewResult(model); } }
private void CreateTenantData(SetupContext context, IWorkContextScope environment) { // create superuser var membershipService = environment.Resolve<IMembershipService>(); var user = membershipService.CreateUser(new CreateUserParams(context.AdminUsername, context.AdminPassword, String.Empty, true)); // set superuser as current user for request (it will be set as the owner of all content items) var authenticationService = environment.Resolve<IAuthenticationService>(); authenticationService.SetAuthenticatedUserForRequest(user); // set site name and settings var siteService = environment.Resolve<ISiteService>(); var siteSettings = (SiteSettings)siteService.GetSiteSettings(); siteSettings.SiteSalt = Guid.NewGuid().ToString("N"); siteSettings.SiteName = context.SiteName; siteSettings.SuperUser = context.AdminUsername; var settingService = environment.Resolve<ISettingService>(); settingService.SaveSetting(siteSettings); // null check: temporary fix for running setup in command line if (HttpContext.Current != null) { authenticationService.SignIn(user, true); } }
public string Setup(SetupContext context) { string executionId; // The vanilla Orchard distibution has the following features enabled. string[] hardcoded = { // Framework "Orchard.Framework", // Core "Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation", "Reports", "Scheduling", "Settings", "Shapes", "Title", // Modules "Orchard.Pages", "Orchard.Themes", "Orchard.Users", "Orchard.Roles", "Orchard.Modules", "PackagingServices", "Orchard.Packaging", "Gallery", "Orchard.Recipes" }; context.EnabledFeatures = hardcoded.Union(context.EnabledFeatures ?? Enumerable.Empty<string>()).Distinct().ToList(); var shellSettings = new ShellSettings(_shellSettings); if (string.IsNullOrEmpty(shellSettings.DataProvider)) { shellSettings.DataProvider = context.DatabaseProvider; shellSettings.DataConnectionString = context.DatabaseConnectionString; shellSettings.DataTablePrefix = context.DatabaseTablePrefix; } #region Encryption Settings shellSettings.EncryptionAlgorithm = "AES"; // randomly generated key shellSettings.EncryptionKey = SymmetricAlgorithm.Create(shellSettings.EncryptionAlgorithm).Key.ToHexString(); shellSettings.HashAlgorithm = "HMACSHA256"; // randomly generated key shellSettings.HashKey = HMAC.Create(shellSettings.HashAlgorithm).Key.ToHexString(); #endregion var shellDescriptor = new ShellDescriptor { Features = context.EnabledFeatures.Select(name => new ShellFeature { Name = name }) }; var shellBlueprint = _compositionStrategy.Compose(shellSettings, shellDescriptor); // initialize database explicitly, and store shell descriptor using (var bootstrapLifetimeScope = _shellContainerFactory.CreateContainer(shellSettings, shellBlueprint)) { using (var environment = bootstrapLifetimeScope.CreateWorkContextScope()) { // check if the database is already created (in case an exception occured in the second phase) var schemaBuilder = new SchemaBuilder(environment.Resolve<IDataMigrationInterpreter>()); try { var tablePrefix = String.IsNullOrEmpty(_shellSettings.DataTablePrefix) ? "" : _shellSettings.DataTablePrefix + "_"; schemaBuilder.ExecuteSql("SELECT * FROM " + tablePrefix + "Settings_ShellDescriptorRecord"); } catch { var reportsCoordinator = environment.Resolve<IReportsCoordinator>(); reportsCoordinator.Register("Data Migration", "Setup", "Orchard installation"); schemaBuilder.CreateTable("Orchard_Framework_DataMigrationRecord", table => table .Column<int>("Id", column => column.PrimaryKey().Identity()) .Column<string>("DataMigrationClass") .Column<int>("Version")); var dataMigrationManager = environment.Resolve<IDataMigrationManager>(); dataMigrationManager.Update("Settings"); foreach (var feature in context.EnabledFeatures) { dataMigrationManager.Update(feature); } environment.Resolve<IShellDescriptorManager>().UpdateShellDescriptor( 0, shellDescriptor.Features, shellDescriptor.Parameters); } } } // in effect "pump messages" see PostMessage circa 1980 while ( _processingEngine.AreTasksPending() ) _processingEngine.ExecuteNextTask(); // creating a standalone environment. // 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 // must mark state as Running - otherwise standalone enviro is created "for setup" shellSettings.State = new TenantState("Running"); using (var environment = _orchardHost.CreateStandaloneEnvironment(shellSettings)) { try { executionId = CreateTenantData(context, environment); } catch { environment.Resolve<ITransactionManager>().Cancel(); throw; } } _shellSettingsManager.SaveSettings(shellSettings); return executionId; }
public void Setup() { IEnumerable<string> enabledFeatures = null; if (!String.IsNullOrEmpty(EnabledFeatures)) { enabledFeatures = EnabledFeatures .Split(',') .Select(s => s.Trim()) .Where(s => !String.IsNullOrEmpty(s)); } Recipe = String.IsNullOrEmpty(Recipe) ? "Default" : Recipe; var recipe = _setupService.Recipes().GetRecipeByName(Recipe); var setupContext = new SetupContext { SiteName = SiteName, AdminUsername = AdminUsername, AdminPassword = AdminPassword, DatabaseProvider = DatabaseProvider, DatabaseConnectionString = DatabaseConnectionString, DatabaseTablePrefix = DatabaseTablePrefix, EnabledFeatures = enabledFeatures, Recipe = recipe, }; var executionId = _setupService.Setup(setupContext); Context.Output.WriteLine(T("Setup of site '{0}' was started with recipe execution ID {1}. Use the 'recipes result' command to check the result of the execution.", setupContext.SiteName, executionId)); }