Files
Umbraco-CMS/src/Umbraco.Web/HealthCheck/Checks/Config/AbstractConfigCheck.cs

239 lines
8.8 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Umbraco.Core.IO;
using Umbraco.Core.Services;
namespace Umbraco.Web.HealthCheck.Checks.Config
{
public abstract class AbstractConfigCheck : HealthCheck
{
private readonly ConfigurationService _configurationService;
private readonly ILocalizedTextService _textService;
/// <summary>
/// Gets the config file path.
/// </summary>
public abstract string FilePath { get; }
/// <summary>
/// Gets XPath statement to the config element to check.
/// </summary>
public abstract string XPath { get; }
/// <summary>
/// Gets the values to compare against.
/// </summary>
public abstract IEnumerable<AcceptableConfiguration> Values { get; }
/// <summary>
/// Gets the current value
/// </summary>
public string CurrentValue { get; set; }
/// <summary>
/// Gets the provided value
/// </summary>
public string ProvidedValue { get; set; }
/// <summary>
/// Gets the comparison type for checking the value.
/// </summary>
public abstract ValueComparisonType ValueComparisonType { get; }
/// <summary>
/// Gets the flag indicating if the check is considered successful if the config value is missing (defaults to false - an error - if missing)
/// </summary>
public virtual bool ValidIfConfigMissing
{
get { return false; }
}
protected AbstractConfigCheck(HealthCheckContext healthCheckContext) : base(healthCheckContext)
{
_textService = healthCheckContext.ApplicationContext.Services.TextService;
_configurationService = new ConfigurationService(AbsoluteFilePath, XPath);
}
/// <summary>
/// Gets the name of the file.
/// </summary>
private string FileName
{
get { return Path.GetFileName(FilePath); }
}
/// <summary>
/// Gets the absolute file path.
/// </summary>
private string AbsoluteFilePath
{
get { return IOHelper.MapPath(FilePath); }
}
/// <summary>
/// Gets the message for when the check has succeeded.
/// </summary>
public virtual string CheckSuccessMessage
{
get
{
return _textService.Localize("healthcheck/checkSuccessMessage",
new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, XPath, AbsoluteFilePath });
}
}
/// <summary>
/// Gets the message for when the check has failed.
/// </summary>
public virtual string CheckErrorMessage
{
get
{
return ValueComparisonType == ValueComparisonType.ShouldEqual
? _textService.Localize("healthcheck/checkErrorMessageDifferentExpectedValue",
new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, XPath, AbsoluteFilePath })
: _textService.Localize("healthcheck/checkErrorMessageUnexpectedValue",
new[] { CurrentValue, Values.First(v => v.IsRecommended).Value, XPath, AbsoluteFilePath });
}
}
/// <summary>
/// Gets the rectify success message.
/// </summary>
public virtual string RectifySuccessMessage
{
get
{
var recommendedValue = Values.FirstOrDefault(v => v.IsRecommended);
var rectifiedValue = recommendedValue != null
? recommendedValue.Value
: ProvidedValue;
return _textService.Localize("healthcheck/rectifySuccessMessage",
new[]
{
CurrentValue,
rectifiedValue,
XPath,
AbsoluteFilePath
});
}
}
/// <summary>
/// Gets a value indicating whether this check can be rectified automatically.
/// </summary>
public virtual bool CanRectify
{
get { return ValueComparisonType == ValueComparisonType.ShouldEqual; }
}
/// <summary>
/// Gets a value indicating whether this check can be rectified automatically if a value is provided.
/// </summary>
public virtual bool CanRectifyWithValue
{
get { return ValueComparisonType == ValueComparisonType.ShouldNotEqual; }
}
public override IEnumerable<HealthCheckStatus> GetStatus()
{
var successMessage = string.Format(CheckSuccessMessage, FileName, XPath, Values);
var configValue = _configurationService.GetConfigurationValue();
if (configValue.Success == false)
{
if (ValidIfConfigMissing)
{
return new[] { new HealthCheckStatus(successMessage) { ResultType = StatusResultType.Success } };
}
var errorMessage = configValue.Result;
return new[] { new HealthCheckStatus(errorMessage) { ResultType = StatusResultType.Error } };
}
CurrentValue = configValue.Result;
// need to update the successMessage with the CurrentValue
successMessage = string.Format(CheckSuccessMessage, FileName, XPath, Values, CurrentValue);
var valueFound = Values.Any(value => string.Equals(CurrentValue, value.Value, StringComparison.InvariantCultureIgnoreCase));
if (ValueComparisonType == ValueComparisonType.ShouldEqual && valueFound || ValueComparisonType == ValueComparisonType.ShouldNotEqual && valueFound == false)
{
return new[] { new HealthCheckStatus(successMessage) { ResultType = StatusResultType.Success } };
}
// Declare the action for rectifying the config value
var rectifyAction = new HealthCheckAction("rectify", Id)
{
Name = _textService.Localize("healthcheck/rectifyButton"),
ValueRequired = CanRectifyWithValue,
};
var resultMessage = string.Format(CheckErrorMessage, FileName, XPath, Values, CurrentValue);
return new[]
{
new HealthCheckStatus(resultMessage)
{
ResultType = StatusResultType.Error,
Actions = CanRectify || CanRectifyWithValue ? new[] { rectifyAction } : new HealthCheckAction[0]
}
};
}
/// <summary>
/// Rectifies this check.
/// </summary>
/// <returns></returns>
public virtual HealthCheckStatus Rectify()
{
if (ValueComparisonType == ValueComparisonType.ShouldNotEqual)
throw new InvalidOperationException(_textService.Localize("healthcheck/cannotRectifyShouldNotEqual"));
var recommendedValue = Values.First(v => v.IsRecommended).Value;
return UpdateConfigurationValue(recommendedValue);
}
/// <summary>
/// Rectifies this check with a provided value.
/// </summary>
/// <param name="value">Value provided</param>
/// <returns></returns>
public virtual HealthCheckStatus Rectify(string value)
{
if (ValueComparisonType == ValueComparisonType.ShouldEqual)
throw new InvalidOperationException(_textService.Localize("healthcheck/cannotRectifyShouldEqualWithValue"));
if (string.IsNullOrWhiteSpace(value))
throw new InvalidOperationException(_textService.Localize("healthcheck/valueToRectifyNotProvided"));
// Need to track provided value in order to correctly put together the rectify message
ProvidedValue = value;
return UpdateConfigurationValue(value);
}
private HealthCheckStatus UpdateConfigurationValue(string value)
{
var updateConfigFile = _configurationService.UpdateConfigFile(value);
if (updateConfigFile.Success == false)
{
var message = updateConfigFile.Result;
return new HealthCheckStatus(message) { ResultType = StatusResultType.Error };
}
var resultMessage = string.Format(RectifySuccessMessage, FileName, XPath, Values);
return new HealthCheckStatus(resultMessage) { ResultType = StatusResultType.Success };
}
public override HealthCheckStatus ExecuteAction(HealthCheckAction action)
{
return string.IsNullOrEmpty(action.ProvidedValue)
? Rectify()
: Rectify(action.ProvidedValue);
}
}
}