public override bool RequiresExecution(object model)
        {
            // If it's properly configured (i.e. the versions match) then no upgrade necessary
            if (_runtime.Level == RuntimeLevel.Run)
            {
                return(false);
            }

            // This step relies on the previous one completed - because it has stored some information we need
            InstallTrackingItem[] installSteps = InstallStatusTracker.GetStatus().ToArray();
            if (installSteps.Any(x => x.Name == "DatabaseInstall" && x.AdditionalData.ContainsKey("upgrade")) == false)
            {
                return(false);
            }

            if (_connectionStrings.CurrentValue.IsConnectionStringConfigured())
            {
                // A connection string was present, determine whether this is an install/upgrade
                // Return true (upgrade) if there is an installed version, else false (install)
                DatabaseSchemaResult?result = _databaseBuilder.ValidateSchema();
                return(result?.DetermineHasInstalledVersion() ?? false);
            }

            // No connection string configured, probably a fresh install
            return(false);
        }
Beispiel #2
0
        public override bool RequiresExecution(object model)
        {
            //if it's properly configured (i.e. the versions match) then no upgrade necessary
            if (_runtime.Level == RuntimeLevel.Run)
            {
                return(false);
            }

            var installSteps = InstallStatusTracker.GetStatus().ToArray();

            //this step relies on the previous one completed - because it has stored some information we need
            if (installSteps.Any(x => x.Name == "DatabaseInstall" && x.AdditionalData.ContainsKey("upgrade")) == false)
            {
                return(false);
            }

            var databaseSettings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName];

            if (_databaseBuilder.IsConnectionStringConfigured(databaseSettings))
            {
                // a connection string was present, determine whether this is an install/upgrade
                // return true (upgrade) if there is an installed version, else false (install)
                var result = _databaseBuilder.ValidateSchema();
                return(result.DetermineHasInstalledVersion());
            }

            //no connection string configured, probably a fresh install
            return(false);
        }
        public override Task <InstallSetupResult> ExecuteAsync(object model)
        {
            var installSteps = InstallStatusTracker.GetStatus().ToArray();
            var previousStep = installSteps.Single(x => x.Name == "DatabaseInstall");
            var upgrade      = previousStep.AdditionalData.ContainsKey("upgrade");

            if (upgrade)
            {
                _logger.Info <DatabaseUpgradeStep>("Running 'Upgrade' service");

                var plan = new UmbracoPlan();
                plan.AddPostMigration <ClearCsrfCookies>(); // needed when running installer (back-office)

                var result = _databaseBuilder.UpgradeSchemaAndData(plan);

                if (result.Success == false)
                {
                    throw new InstallException("The database failed to upgrade. ERROR: " + result.Message);
                }

                DatabaseInstallStep.HandleConnectionStrings(_logger);
            }

            return(Task.FromResult <InstallSetupResult>(null));
        }
        public override Task <InstallSetupResult> ExecuteAsync(object model)
        {
            var installSteps = InstallStatusTracker.GetStatus().ToArray();
            var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload");
            var packageId    = Convert.ToInt32(previousStep.AdditionalData["packageId"]);
            var packageFile  = (string)previousStep.AdditionalData["packageFile"];

            CleanupInstallation(packageId, packageFile);

            return(Task.FromResult <InstallSetupResult>(null));
        }
        public override bool RequiresExecution(object model)
        {
            var installSteps = InstallStatusTracker.GetStatus().ToArray();

            //this step relies on the previous one completed - because it has stored some information we need
            if (installSteps.Any(x => x.Name == "StarterKitDownload" && x.AdditionalData.ContainsKey("packageId")) == false)
            {
                return(false);
            }

            return(true);
        }
        public override Task <InstallSetupResult> ExecuteAsync(object model)
        {
            var installSteps = InstallStatusTracker.GetStatus().ToArray();
            var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload");
            var packageId    = Convert.ToInt32(previousStep.AdditionalData["packageId"]);

            InstallBusinessLogic(packageId);

            UmbracoApplication.Restart(_httContext);

            return(Task.FromResult <InstallSetupResult>(null));
        }
Beispiel #7
0
        public override InstallSetupResult Execute(object model)
        {
            var installSteps = InstallStatusTracker.GetStatus().ToArray();
            var previousStep = installSteps.Single(x => x.Name == "StarterKitDownload");
            var manifestId   = Convert.ToInt32(previousStep.AdditionalData["manifestId"]);
            var packageFile  = (string)previousStep.AdditionalData["packageFile"];

            InstallBusinessLogic(manifestId, packageFile);

            Current.RestartAppPool(_httContext);

            return(null);
        }
Beispiel #8
0
        /// <summary>
        /// Gets the install setup.
        /// </summary>
        public InstallSetup GetSetup()
        {
            var setup = new InstallSetup();

            // TODO: Check for user/site token

            var steps = new List <InstallSetupStep>();

            var installSteps = _installSteps.GetStepsForCurrentInstallType().ToArray();

            //only get the steps that are targeting the current install type
            steps.AddRange(installSteps);
            setup.Steps = steps;

            InstallStatusTracker.Initialize(setup.InstallId, installSteps);

            return(setup);
        }
Beispiel #9
0
        /// <summary>
        /// We'll peek ahead and check if it's RequiresExecution is returning true. If it
        /// is not, we'll dequeue that step and peek ahead again (recurse)
        /// </summary>
        /// <param name="current"></param>
        /// <param name="queue"></param>
        /// <param name="installId"></param>
        /// <param name="installModel"></param>
        /// <returns></returns>
        private string IterateNextRequiredStep(InstallSetupStep current, Queue <InstallTrackingItem> queue, Guid installId, InstallInstructions installModel)
        {
            if (queue.Count > 0)
            {
                var next = queue.Peek();
                var step = InstallHelper.GetAllSteps().Single(x => x.Name == next.Name);

                //If the current step restarts the app pool then we must simply return the next one in the queue,
                // we cannot peek ahead as the next step might rely on the app restart and therefore RequiresExecution
                // will rely on that too.
                if (current.PerformsAppRestart)
                {
                    return(step.Name);
                }

                JToken instruction = null;
                //If this step has any instructions then extract them
                if (installModel.Instructions.Any(x => x.Key == step.Name))
                {
                    instruction = installModel.Instructions[step.Name];
                }

                //if the step requires execution then return it's name
                if (StepRequiresExecution(step, instruction))
                {
                    return(step.Name);
                }

                //this step no longer requires execution, this could be due to a new config change during installation,
                // so we'll dequeue this one from the queue and recurse
                queue.Dequeue();

                //set this as complete
                InstallStatusTracker.SetComplete(installId, step.Name, null);

                //recurse
                return(IterateNextRequiredStep(step, queue, installId, installModel));
            }

            //there is no more steps
            return(string.Empty);
        }
Beispiel #10
0
 public InstallApiController(
     DatabaseBuilder databaseBuilder,
     IProfilingLogger proflog,
     ILogger <InstallApiController> logger,
     InstallHelper installHelper,
     InstallStepCollection installSteps,
     InstallStatusTracker installStatusTracker,
     IRuntime runtime,
     IBackOfficeUserManager backOfficeUserManager,
     IBackOfficeSignInManager backOfficeSignInManager)
 {
     _databaseBuilder         = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder));
     _proflog                 = proflog ?? throw new ArgumentNullException(nameof(proflog));
     _installSteps            = installSteps;
     _installStatusTracker    = installStatusTracker;
     _runtime                 = runtime;
     _backOfficeUserManager   = backOfficeUserManager;
     _backOfficeSignInManager = backOfficeSignInManager;
     InstallHelper            = installHelper;
     _logger = logger;
 }
Beispiel #11
0
        public override InstallSetupResult Execute(object model)
        {
            var installSteps = InstallStatusTracker.GetStatus().ToArray();
            var previousStep = installSteps.Single(x => x.Name == "DatabaseInstall");
            var upgrade      = previousStep.AdditionalData.ContainsKey("upgrade");

            if (upgrade)
            {
                LogHelper.Info <DatabaseUpgradeStep>("Running 'Upgrade' service");

                var result = _applicationContext.DatabaseContext.UpgradeSchemaAndData(_applicationContext.Services.MigrationEntryService);

                if (result.Success == false)
                {
                    throw new InstallException("The database failed to upgrade. ERROR: " + result.Message);
                }

                DatabaseInstallStep.HandleConnectionStrings();
            }

            return(null);
        }
Beispiel #12
0
        /// <summary>
        /// We'll peek ahead and check if it's RequiresExecution is returning true. If it
        /// is not, we'll dequeue that step and peek ahead again (recurse)
        /// </summary>
        /// <param name="current"></param>
        /// <param name="queue"></param>
        /// <param name="installId"></param>
        /// <param name="installModel"></param>
        /// <returns></returns>
        private string IterateSteps(InstallSetupStep current, Queue <InstallTrackingItem> queue, Guid installId, InstallInstructions installModel)
        {
            while (queue.Count > 0)
            {
                var item = queue.Peek();

                // if the current step restarts the app pool then we must simply return the next one in the queue,
                // we cannot peek ahead as the next step might rely on the app restart and therefore RequiresExecution
                // will rely on that too.
                if (current.PerformsAppRestart)
                {
                    return(item.Name);
                }

                var step = _installSteps.GetAllSteps().Single(x => x.Name == item.Name);

                // if this step has any instructions then extract them
                JToken instruction;
                installModel.Instructions.TryGetValue(item.Name, out instruction); // else null

                // if the step requires execution then return its name
                if (StepRequiresExecution(step, instruction))
                {
                    return(step.Name);
                }

                // no longer requires execution, could be due to a new config change during installation
                // dequeue
                queue.Dequeue();

                // complete
                InstallStatusTracker.SetComplete(installId, step.Name);

                // and continue
                current = step;
            }

            return(string.Empty);
        }
        public override Task <InstallSetupResult?> ExecuteAsync(object model)
        {
            InstallTrackingItem[] installSteps = InstallStatusTracker.GetStatus().ToArray();
            InstallTrackingItem   previousStep = installSteps.Single(x => x.Name == "DatabaseInstall");
            var upgrade = previousStep.AdditionalData.ContainsKey("upgrade");

            if (upgrade)
            {
                _logger.LogInformation("Running 'Upgrade' service");

                var plan = new UmbracoPlan(_umbracoVersion);
                plan.AddPostMigration <ClearCsrfCookies>(); // needed when running installer (back-office)

                DatabaseBuilder.Result?result = _databaseBuilder.UpgradeSchemaAndData(plan);

                if (result?.Success == false)
                {
                    throw new InstallException("The database failed to upgrade. ERROR: " + result.Message);
                }
            }

            return(Task.FromResult((InstallSetupResult?)null));
        }
Beispiel #14
0
        public override bool RequiresExecution(object model)
        {
            //if it's properly configured (i.e. the versions match) then no upgrade necessary
            if (_applicationContext.IsConfigured)
            {
                return(false);
            }

            var installSteps = InstallStatusTracker.GetStatus().ToArray();

            //this step relies on the previous one completed - because it has stored some information we need
            if (installSteps.Any(x => x.Name == "DatabaseInstall" && x.AdditionalData.ContainsKey("upgrade")) == false)
            {
                return(false);
            }

            var databaseSettings = ConfigurationManager.ConnectionStrings[Constants.System.UmbracoConnectionName];

            if (_applicationContext.DatabaseContext.IsConnectionStringConfigured(databaseSettings))
            {
                //Since a connection string was present we verify whether this is an upgrade or an empty db
                var result = _applicationContext.DatabaseContext.ValidateDatabaseSchema();

                var determinedVersion = result.DetermineInstalledVersion();
                if (determinedVersion.Equals(new Version(0, 0, 0)))
                {
                    //Fresh install
                    return(false);
                }

                //Upgrade
                return(true);
            }

            //no connection string configured, probably a fresh install
            return(false);
        }
Beispiel #15
0
        /// <summary>
        ///     Installs.
        /// </summary>
        public async Task <ActionResult <InstallProgressResultModel> > PostPerformInstall(InstallInstructions installModel)
        {
            if (installModel == null)
            {
                throw new ArgumentNullException(nameof(installModel));
            }

            var status = InstallStatusTracker.GetStatus().ToArray();

            //there won't be any statuses returned if the app pool has restarted so we need to re-read from file.
            if (status.Any() == false)
            {
                status = _installStatusTracker.InitializeFromFile(installModel.InstallId).ToArray();
            }

            //create a new queue of the non-finished ones
            var queue = new Queue <InstallTrackingItem>(status.Where(x => x.IsComplete == false));

            while (queue.Count > 0)
            {
                var item = queue.Dequeue();
                var step = _installSteps.GetAllSteps().Single(x => x.Name == item.Name);

                // if this step has any instructions then extract them
                var instruction = GetInstruction(installModel, item, step);

                // if this step doesn't require execution then continue to the next one, this is just a fail-safe check.
                if (StepRequiresExecution(step, instruction) == false)
                {
                    // set this as complete and continue
                    _installStatusTracker.SetComplete(installModel.InstallId, item.Name);
                    continue;
                }

                try
                {
                    var setupData = await ExecuteStepAsync(step, instruction);

                    // update the status
                    _installStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData?.SavedStepData);

                    // determine's the next step in the queue and dequeue's any items that don't need to execute
                    var nextStep = IterateSteps(step, queue, installModel.InstallId, installModel);

                    // check if there's a custom view to return for this step
                    if (setupData != null && setupData.View.IsNullOrWhiteSpace() == false)
                    {
                        return(new InstallProgressResultModel(false, step.Name, nextStep, setupData.View,
                                                              setupData.ViewModel));
                    }

                    return(new InstallProgressResultModel(false, step.Name, nextStep));
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "An error occurred during installation step {Step}",
                                     step.Name);

                    if (ex is TargetInvocationException && ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }

                    var installException = ex as InstallException;
                    if (installException != null)
                    {
                        return(new ValidationErrorResult(new
                        {
                            view = installException.View,
                            model = installException.ViewModel,
                            message = installException.Message
                        }));
                    }

                    return(new ValidationErrorResult(new
                    {
                        step = step.Name,
                        view = "error",
                        message = ex.Message
                    }));
                }
            }

            _installStatusTracker.Reset();
            return(new InstallProgressResultModel(true, "", ""));
        }
Beispiel #16
0
        /// <summary>
        /// Does the install
        /// </summary>
        /// <returns></returns>
        public InstallProgressResultModel PostPerformInstall(InstallInstructions installModel)
        {
            if (installModel == null)
            {
                throw new ArgumentNullException("installModel");
            }

            var status = InstallStatusTracker.GetStatus().ToArray();

            //there won't be any statuses returned if the app pool has restarted so we need to re-read from file.
            if (status.Any() == false)
            {
                status = InstallStatusTracker.InitializeFromFile(installModel.InstallId).ToArray();
            }

            //create a new queue of the non-finished ones
            var queue = new Queue <InstallTrackingItem>(status.Where(x => x.IsComplete == false));

            while (queue.Count > 0)
            {
                var stepStatus = queue.Dequeue();

                var step = InstallHelper.GetAllSteps().Single(x => x.Name == stepStatus.Name);

                JToken instruction = null;
                //If this step has any instructions then extract them
                if (installModel.Instructions.Any(x => x.Key == step.Name))
                {
                    instruction = installModel.Instructions[step.Name];
                }

                //If this step doesn't require execution then continue to the next one, this is just a fail-safe check.
                if (StepRequiresExecution(step, instruction) == false)
                {
                    //set this as complete and continue
                    InstallStatusTracker.SetComplete(installModel.InstallId, stepStatus.Name, null);
                    continue;
                }

                try
                {
                    var setupData = ExecuteStep(step, instruction);

                    //update the status
                    InstallStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData != null ? setupData.SavedStepData : null);

                    //Determine's the next step in the queue and dequeue's any items that don't need to execute
                    var nextStep = IterateNextRequiredStep(step, queue, installModel.InstallId, installModel);

                    //check if there's a custom view to return for this step
                    if (setupData != null && setupData.View.IsNullOrWhiteSpace() == false)
                    {
                        return(new InstallProgressResultModel(false, step.Name, nextStep, setupData.View, setupData.ViewModel));
                    }

                    return(new InstallProgressResultModel(false, step.Name, nextStep));
                }
                catch (Exception ex)
                {
                    LogHelper.Error <InstallApiController>("An error occurred during installation step " + step.Name, ex);

                    if (ex is TargetInvocationException && ex.InnerException != null)
                    {
                        ex = ex.InnerException;
                    }

                    var installException = ex as InstallException;
                    if (installException != null)
                    {
                        throw new HttpResponseException(Request.CreateValidationErrorResponse(new
                        {
                            view    = installException.View,
                            model   = installException.ViewModel,
                            message = installException.Message
                        }));
                    }

                    throw new HttpResponseException(Request.CreateValidationErrorResponse(new
                    {
                        step    = step.Name,
                        view    = "error",
                        message = ex.Message
                    }));
                }
            }

            InstallStatusTracker.Reset();
            return(new InstallProgressResultModel(true, "", ""));
        }