using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Web.Http; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Logging; using Umbraco.Core.Persistence; using Umbraco.Web.Install.Models; using Umbraco.Web.WebApi; namespace Umbraco.Web.Install.Controllers { [AngularJsonOnlyConfiguration] [HttpInstallAuthorize] public class InstallApiController : ApiController { protected InstallApiController() : this(UmbracoContext.Current) { } protected InstallApiController(UmbracoContext umbracoContext) { if (umbracoContext == null) throw new ArgumentNullException("umbracoContext"); UmbracoContext = umbracoContext; } /// /// Returns the current UmbracoContext /// public UmbracoContext UmbracoContext { get; private set; } public ApplicationContext ApplicationContext { get { return UmbracoContext.Application; } } /// /// Gets the install setup /// /// public InstallSetup GetSetup() { var helper = new InstallHelper(UmbracoContext); var setup = new InstallSetup() { Status = helper.GetStatus() }; //TODO: Check for user/site token var steps = new List(); steps.AddRange(helper.GetSteps()); setup.Steps = steps; return setup; } /// /// Checks if the db can be connected to /// /// public HttpResponseMessage PostCheckDbConnection() { throw new NotImplementedException(); } /// /// Checks if the db credentials are correct /// /// public HttpResponseMessage PostCheckDbCredentials() { throw new NotImplementedException(); } public IEnumerable GetPackages() { var r = new org.umbraco.our.Repository(); var modules = r.Modules(); List retval = new List(); foreach (var package in modules) retval.Add(new Package() { Id = package.RepoGuid, Name = package.Text, Thumbnail = package.Thumbnail }); return retval; } /// /// Does the install /// /// public HttpResponseMessage PostPerformInstall(IDictionary instructions) { if (instructions == null) throw new ArgumentNullException("instructions"); var steps = GetSetup().Steps.OrderBy(x => x.ServerOrder).ToArray(); var status = InstallStatusTracker.GetStatus(); if (status.Count == 0) { status = InstallStatusTracker.Initialize(steps); } foreach (var step in steps) { var step1 = step; var stepStatus = status.Single(x => x.Key == step1.Name); //if it is not complete, then we need to execute it if (stepStatus.Value.IsComplete == false) { JToken instruction = null; if (step.HasUIElement) { //Since this is a UI instruction, we will extract the model from it if (instructions.Any(x => x.Key == step.Name) == false) { return Request.CreateValidationErrorResponse("No instruction defined for step: " + step.Name); } instruction = instructions[step.Name]; } //If this step doesn't require execution then continue to the next one. if (step.RequiresExecution() == false) { continue; } try { var setupData = ExecuteStep(step, instruction); //update the status InstallStatusTracker.SetComplete(step.Name, setupData.SavedStepData); return Json(new { complete = false, stepCompleted = step.Name }, HttpStatusCode.OK); } catch (InstallException iex) { return Json(iex.Result, HttpStatusCode.BadRequest); } catch (Exception ex) { return Request.CreateValidationErrorResponse("An error occurred executing the step: " + step.Name + ". Error: " + ex.Message); } } } InstallStatusTracker.Reset(); return Json(new { complete = true }, HttpStatusCode.OK); } internal InstallSetupResult ExecuteStep(InstallSetupStep step, JToken instruction) { var model = instruction == null ? null : instruction.ToObject(step.StepType); var genericStepType = typeof(InstallSetupStep<>); Type[] typeArgs = { step.StepType }; var typedStepType = genericStepType.MakeGenericType(typeArgs); try { var method = typedStepType.GetMethods().Single(x => x.Name == "Execute"); return (InstallSetupResult)method.Invoke(step, new object[] { model }); } catch (Exception ex) { LogHelper.Error("Installation step " + step.Name + " failed.", ex); throw; } } private HttpResponseMessage Json(object jsonObject, HttpStatusCode status) { var response = Request.CreateResponse(status); var json = JObject.FromObject(jsonObject); response.Content = new StringContent(json.ToString(), Encoding.UTF8, "application/json"); return response; } } }