Skip to content

Instantly share code, notes, and snippets.

@sohjsolwin
Last active March 7, 2019 22:03
Show Gist options
  • Save sohjsolwin/cbce1999dd76fd15f583c9420f531dd9 to your computer and use it in GitHub Desktop.
Save sohjsolwin/cbce1999dd76fd15f583c9420f531dd9 to your computer and use it in GitHub Desktop.
CensoredContentAttribute
using System;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Logging
{
public abstract class CensoredContentAttribute : Attribute
{
public abstract string Censor { get; }
public abstract string TruncateData(string input);
}
public class CensoredContentContractResolver<T> : DefaultContractResolver where T : CensoredContentAttribute
{
protected override IValueProvider CreateMemberValueProvider(MemberInfo member)
{
if (member.IsDefined(typeof(T)))
{
var attr = (T)Attribute.GetCustomAttribute(member, typeof(T));
return new CensorContentValueProvider(base.CreateMemberValueProvider(member), attr);
}
else
{
return base.CreateMemberValueProvider(member);
}
}
class CensorContentValueProvider : IValueProvider
{
private readonly IValueProvider _inner;
private readonly CensoredContentAttribute _censorAttr;
public CensorContentValueProvider(IValueProvider inner, CensoredContentAttribute censorAttr)
{
_censorAttr = censorAttr;
_inner = inner;
}
public object GetValue(object target)
{
var targetString = _inner.GetValue(target)?.ToString() ?? string.Empty;
return _censorAttr.TruncateData(targetString);
}
public void SetValue(object target, object value)
{
_inner.SetValue(target, value);
}
}
}
public class CensoredJsonSerializerSettings<T> : JsonSerializerSettings where T : CensoredContentAttribute
{
public CensoredJsonSerializerSettings()
{
ContractResolver = new CensoredContentContractResolver<T>();
}
}
}
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Logging
{
public class LoggingExample
{
[Redacted(ShowFirst:3, ShowLast:3)]
public string Name {get; set;} = "Richard Johnson"
public string ToSerializedString() {
return JsonConvert.SerializeObject(this, new CensoredJsonSerializerSettings<RedactedAttribute>());
// Returns "Ric***REDACTED***son"
}
}
}
namespace Logging
{
public class LargeDataAttribute : CensoredContentAttribute
{
public override string Censor { get => "***Large Data Removed***"; }
public int Threshold { get; set; }
public override string TruncateData(string input)
{
var byteLength = input?.Length ?? 0;
if (byteLength > Threshold)
{
return $"{Censor} [Length: {byteLength}]";
}
else
{
return input;
}
}
}
}
namespace Logging
{
public class RedactedAttribute : CensoredContentAttribute
{
/*
* https://piwik.pro/blog/what-is-pii-personal-data/
* Full name
* Home address
* Email address
* Social security number
* Passport number
* Driver’s license number
* Credit card numbers
* Date of birth
* Telephone number
* Log in details
*/
public override string Censor { get => "***REDACTED***"; }
public int ShowFirst { get; set; }
public int ShowLast { get; set; }
public override string TruncateData(string input)
{
var output = string.Empty;
if (ShowFirst + ShowLast >= input.Length)
{
return Censor;
}
if (ShowFirst > 0)
{
output += input?.Substring(0, ShowFirst > input.Length ? input.Length : ShowFirst) ?? string.Empty;
}
output += Censor;
if (ShowLast > 0)
{
output += input?.Substring(ShowLast > input.Length ? 0 : input.Length - ShowLast, ShowLast > input.Length ? input.Length : ShowLast) ?? string.Empty;
}
return output.Length > 0 ? output : Censor;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment