Skip to content

A library to formally validate and sanitize assumptions for your code and data.

License

Notifications You must be signed in to change notification settings

TylerKendrick/Hygiene

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hygiene

Provides sanitizers for developers to write hygienic, secure, clean code.

Quality Gate Status Build Status Nuget GitHub Net Standard

Purpose

Hygiene sanitizers allow for configurable components to handle your sanitization logic.

//Creates a sanitizer.
var sanitizer = Sanitizer.Create<string>(
    input => input.Replace("not", "").Trim());

var valueToSanitize = "not correct";
//Executes the sanitization logic.
sanitizer.Sanitize(ref valueToSanitize);

Console.WriteLine(valueToSanitize); //Outputs "correct".

By integrating the sanitizers into your codebase, you can easily identify where code isn't covered by sanitization and decouple this logic from your codebase, keeping your code clean and cohesive.

The CWE/SANS Institute's top 25 most dangerous software errors lists improper input validations to be the number one cause of software issues. In order to avoid these issues, a Monster Mitigation list was created to instruct developers, architects, and engineers in best practices to reduce or eliminate the severity of these issues on software systems. To assist in these mitigation processes, Hygiene provides an isolated component that can be easily identified to handle input sanitization as a singular responsibility.

Quickstart

You need to first configure Hygiene to be aware of the types you are supporting. You can create an instance for one-off types without a configuration provider, using a static factory method from the non-generic Sanitizer object.

var sanitizer = Sanitizer.Create<string>(instance => instance.Replace(' ', ''));

To use a sanitizer, simply pass the object by reference and invoke the sanitizer.

var phoneNumber = "1- 555-555-5555";
stringSanitizer.Sanitize(ref phoneNumber);

Alternatively, to create multiple sanitizer configurations for reuse, use a configuration provider.

var configuration = new SanitizerConfigurationProvider(builder => 
{
    //storing the builder configuration allows you to use it later.
    var localSanitizer = builder
        // You may also use the type configuration to change the ref instance.
        .ForType<string>((ref string value) =>
        {
            //Using the pass-by-ref transformer allows conditional assignment.
            if(value != null) value = value.Trim();
        });
    
    //Typed builders can be converted into Visitor delegate instances.
    builder.ForType<Bar>(typeBuilder => typeBuilder
        .Property(instance => instance.FooBar)
        //Using the sanitizer overload for transform allows reuse of sanitizers.
        .Transform(localSanitizer));
        
    //Non-primitive type builders allow for property mutations.
    builder.ForType<Foo>(typeBuilder => typeBuilder
        .Property(instance => instance.Bar)
        //Using the mutator overload for transform uses implicit reassignment.
        .Transform(bar => bar.Trim()));
});

// use DI or create the sanitizer yourself
var fooSanitizer = configuration.CreateSanitizer<Foo>();
var barSanitizer = configuration.CreateSanitizer<Bar>();
var stringSanitizer = configuration.CreateSanitizer<string>();

Extending the sanitizers

To add new builder operations for your custom types, you can create extension classes to implement your custom behaviors.

public static class CustomExtensions
{
    //Demonstrates an extension for a non-primitive type.
    public static ISanitizerTypeBuilder<Foo> CustomLogic(
        this ISanitizerTypeBuilder<Foo> self,
        //Define custom parameters here.
        Bar extensionParameter) => self
        .Transform((ref instance) =>
            //Implement custom sanitization logic
            instance.Bar = extensionParameter.Normalize());
}

//Use the extension when configuring your sanitizers.
var foo = new Foo();
var bar = new Bar();
var sanitizer = Sanitizer.Create<Foo>(
    //Can now call the extension during configuration.
    x => x.CustomLogic(bar));

sanitizer.Sanitize(ref foo);
//foo.Bar == bar

Another more practical example would be for encryption.

public static class SanitizerBuilderExtensions
{
    public static ISanitizerTypeBuilder<string> Encrypt(
        this ISanitizerTypeBuilder<string> self,
        RijndaelManaged algorithm) => self
        .Transform(instance =>
        {
            var iv = algorithm.IV;
            var length = iv.Length;
            var encryptor = algorithm.CreateEncryptor(algorithm.Key, iv);
            using (var memoryStream = new MemoryStream())
            {
                memoryStream.Write(BitConverter.GetBytes(length), 0, sizeof(int));
                memoryStream.Write(iv, 0, length);
                using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                using (var streamWriter = new StreamWriter(cryptoStream))
                    streamWriter.Write(instance);
                // This implicitly sets the referenced variable.
                return Convert.ToBase64String(memoryStream.ToArray());
            }
        });
}

Where to get it

Install from nuget

> dotnet add package Hygiene --version 1.0.0

Or download from the release page.

API Design Inspirations

Resources and Recommended Readings

About

A library to formally validate and sanitize assumptions for your code and data.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages