* Started moving to JSON instead of config. Mild refactoring but overall keeping it the same, except for injecting IConfiguration and JSON parsing instead of XML Tests currently unaffected, need to increase coverage * Moved to constants for appsettings keys Moved from IConfiguration to global settings - later to be replaced with IOptions Updated translation messages Installed IOptions ready for new PR Updated to new interface, IConfigurationService * Post-merge fix * Namespace move from Umbraco.Web to Umbraco.Core where appropriate * Renamed abstractsettings (from abstractconfig) Moving out of configservice into the POCO config check * Made the IIsCustomErrors healthcheck as obsolete, as no web.config setting). Investigate reintroducing this check in the .NET Core way (UseDevelopment). Reducing use of abstractsettings as not needed - we don't need a config service to read the config settings anymore as they're all explicit POCOs. Consolidated health-checks in project. * Removed test views that weren't meant to be added * Returned to use of abstractsettings with different use * Moved more health checks into correct folder/namespace, and enum into their own file * Correct namespace * Git history/compare lost due to file move, temporarily moving back to original folder. Will do another PR to move after this * Use existing GetStatus in abstract check for Debug mode * Updating to return to previous logic and putting files back into line * Macro errors returned to previous logic * Reuse abstractsettings class * Swapped order to assist with reviewing PR * Updated to include itempath * Not implemented comment to avoid confusion Implemented NotificationEmailCheck * Changed to IOptionsMonitor as per PR comments. Removed configurationservice as we need to rethink the fixing strategy. Updated logger. Needs to show fix message instead of fixing. Temporary fix for IIS version * Switched to IOptionsMonitor for all * No longer attempts to actually fix header in config. Still need to show suggestions. Co-authored-by: Elitsa Marinovska <elm@umbraco.dk>
123 lines
4.3 KiB
C#
123 lines
4.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using Umbraco.Core.Models;
|
|
using Umbraco.Core.Services;
|
|
|
|
namespace Umbraco.Core.HealthCheck.Checks.Data
|
|
{
|
|
[HealthCheck(
|
|
"73DD0C1C-E0CA-4C31-9564-1DCA509788AF",
|
|
"Database data integrity check",
|
|
Description = "Checks for various data integrity issues in the Umbraco database.",
|
|
Group = "Data Integrity")]
|
|
public class DatabaseIntegrityCheck : HealthCheck
|
|
{
|
|
private readonly IContentService _contentService;
|
|
private readonly IMediaService _mediaService;
|
|
private const string _fixMediaPaths = "fixMediaPaths";
|
|
private const string _fixContentPaths = "fixContentPaths";
|
|
private const string _fixMediaPathsTitle = "Fix media paths";
|
|
private const string _fixContentPathsTitle = "Fix content paths";
|
|
|
|
public DatabaseIntegrityCheck(IContentService contentService, IMediaService mediaService)
|
|
{
|
|
_contentService = contentService;
|
|
_mediaService = mediaService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the status for this health check
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override IEnumerable<HealthCheckStatus> GetStatus()
|
|
{
|
|
//return the statuses
|
|
return new[]
|
|
{
|
|
CheckDocuments(false),
|
|
CheckMedia(false)
|
|
};
|
|
}
|
|
|
|
private HealthCheckStatus CheckMedia(bool fix)
|
|
{
|
|
return CheckPaths(_fixMediaPaths, _fixMediaPathsTitle, Core.Constants.UdiEntityType.Media, fix,
|
|
() => _mediaService.CheckDataIntegrity(new ContentDataIntegrityReportOptions {FixIssues = fix}));
|
|
}
|
|
|
|
private HealthCheckStatus CheckDocuments(bool fix)
|
|
{
|
|
return CheckPaths(_fixContentPaths, _fixContentPathsTitle, Core.Constants.UdiEntityType.Document, fix,
|
|
() => _contentService.CheckDataIntegrity(new ContentDataIntegrityReportOptions {FixIssues = fix}));
|
|
}
|
|
|
|
private HealthCheckStatus CheckPaths(string actionAlias, string actionName, string entityType, bool detailedReport, Func<ContentDataIntegrityReport> doCheck)
|
|
{
|
|
var report = doCheck();
|
|
|
|
var actions = new List<HealthCheckAction>();
|
|
if (!report.Ok)
|
|
{
|
|
actions.Add(new HealthCheckAction(actionAlias, Id)
|
|
{
|
|
Name = actionName
|
|
});
|
|
}
|
|
|
|
return new HealthCheckStatus(GetReport(report, entityType, detailedReport))
|
|
{
|
|
ResultType = report.Ok ? StatusResultType.Success : StatusResultType.Error,
|
|
Actions = actions
|
|
};
|
|
}
|
|
|
|
private static string GetReport(ContentDataIntegrityReport report, string entityType, bool detailed)
|
|
{
|
|
var sb = new StringBuilder();
|
|
|
|
if (report.Ok)
|
|
{
|
|
sb.AppendLine($"<p>All {entityType} paths are valid</p>");
|
|
|
|
if (!detailed)
|
|
return sb.ToString();
|
|
}
|
|
else
|
|
{
|
|
sb.AppendLine($"<p>{report.DetectedIssues.Count} invalid {entityType} paths detected.</p>");
|
|
}
|
|
|
|
if (detailed && report.DetectedIssues.Count > 0)
|
|
{
|
|
sb.AppendLine("<ul>");
|
|
foreach (var issueGroup in report.DetectedIssues.GroupBy(x => x.Value.IssueType))
|
|
{
|
|
var countByGroup = issueGroup.Count();
|
|
var fixedByGroup = issueGroup.Count(x => x.Value.Fixed);
|
|
sb.AppendLine("<li>");
|
|
sb.AppendLine($"{countByGroup} issues of type <code>{issueGroup.Key}</code> ... {fixedByGroup} fixed");
|
|
sb.AppendLine("</li>");
|
|
}
|
|
sb.AppendLine("</ul>");
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
public override HealthCheckStatus ExecuteAction(HealthCheckAction action)
|
|
{
|
|
switch (action.Alias)
|
|
{
|
|
case _fixContentPaths:
|
|
return CheckDocuments(true);
|
|
case _fixMediaPaths:
|
|
return CheckMedia(true);
|
|
default:
|
|
throw new InvalidOperationException("Action not supported");
|
|
}
|
|
}
|
|
}
|
|
}
|