< Summary

Information
Class: ProjectTemplate.Infrastructure.Data.Auditing.ApplicationAuditValueProtector
Assembly: ProjectTemplate.Infrastructure
File(s): /home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Infrastructure/Data/Auditing/ApplicationAuditValueProtector.cs
Line coverage
92%
Covered lines: 24
Uncovered lines: 2
Coverable lines: 26
Total lines: 66
Line coverage: 92.3%
Branch coverage
63%
Covered branches: 14
Total branches: 22
Branch coverage: 63.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
TryProtect(...)80%101094.11%
Hash(...)50%22100%
Truncate(...)50%101083.33%

File(s)

/home/runner/work/NetCoreApplicationTemplate/NetCoreApplicationTemplate/src/ProjectTemplate.Infrastructure/Data/Auditing/ApplicationAuditValueProtector.cs

#LineLine coverage
 1using System.Globalization;
 2using System.Security.Cryptography;
 3using System.Text;
 4
 5namespace ProjectTemplate.Infrastructure.Data.Auditing;
 6
 7internal static class ApplicationAuditValueProtector
 8{
 9    private const string _maskedValue = "***";
 10
 11    internal static bool TryProtect(
 12        IApplicationAuditValuePolicy policy,
 13        Type entityType,
 14        string propertyName,
 15        object? value,
 16        out object protectedValue)
 17    {
 65218        ArgumentNullException.ThrowIfNull(policy);
 65219        ArgumentNullException.ThrowIfNull(entityType);
 65220        ArgumentException.ThrowIfNullOrWhiteSpace(propertyName);
 21
 65222        ApplicationAuditValueDecision decision = policy.Evaluate(entityType, propertyName, value)
 65223            ?? throw new InvalidOperationException("The application audit value policy returned no decision.");
 24
 65225        switch (decision.Disposition)
 26        {
 27            case ApplicationAuditValueDisposition.Include:
 63628                protectedValue = value ?? string.Empty;
 63629                return true;
 30            case ApplicationAuditValueDisposition.Mask:
 431                protectedValue = _maskedValue;
 432                return true;
 33            case ApplicationAuditValueDisposition.Hash:
 434                protectedValue = Hash(value);
 435                return true;
 36            case ApplicationAuditValueDisposition.Omit:
 437                protectedValue = string.Empty;
 438                return false;
 39            case ApplicationAuditValueDisposition.Truncate:
 440                protectedValue = Truncate(value, decision.MaximumLength);
 441                return true;
 42            default:
 043                throw new InvalidOperationException($"Unsupported audit value disposition '{decision.Disposition}'.");
 44        }
 45    }
 46
 47    private static string Hash(object? value)
 48    {
 449        string canonicalValue = Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty;
 450        byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes(canonicalValue));
 451        return Convert.ToHexString(hash);
 52    }
 53
 54    private static string Truncate(object? value, int? maximumLength)
 55    {
 456        if (maximumLength is null or <= 0)
 57        {
 058            throw new InvalidOperationException("Truncated audit values require a positive maximum length.");
 59        }
 60
 461        string text = Convert.ToString(value, CultureInfo.InvariantCulture) ?? string.Empty;
 462        return text.Length <= maximumLength.Value
 463            ? text
 464            : text[..maximumLength.Value];
 65    }
 66}