Last active
August 20, 2020 05:33
-
-
Save Lachee/c4143fa45d5be27403c12efff32de26b to your computer and use it in GitHub Desktop.
LazyKey is a class that allows for JSON configuration files that utilise separate files for secret tokens. I use this a lot with my bots so I can have a universal configuration, but gitignore .key. It keeps the pattern matching between the Config.cs and the Config.json, by allowing implicit conversion from a string filename. There was the potent…
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Config | |
{ | |
public string Project { get; set; } = "AProject"; | |
public string Repository { get; set; } = "ARepo"; | |
public string Organization { get; set; } = "https://dev.azure.com/org"; | |
public LazyKey Credentials { get; set; } = "devops.key"; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"Project": "AProject", | |
"Repository": "ARepo", | |
"Organization": "https://dev.azure.com/org", | |
"Credentials": "devops.key" | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[Newtonsoft.Json.JsonConverter(typeof(LazyKey.Converter))] | |
public class LazyKey | |
{ | |
/// <summary> | |
/// The file path to load the key from | |
/// </summary> | |
public string FilePath { get; set; } | |
/// <summary> | |
/// Should the value be cached in memory. This should be enabled if the value is used a lot throughout the application. | |
/// </summary> | |
public bool Cache { get => _cache; set { _cache = value; if (!value) _cachedValue = null; } } | |
private bool _cache = false; | |
private string _cachedValue = null; | |
/// <summary> | |
/// Gets the key value. | |
/// <seealso cref="LoadSecret"/> | |
/// </summary> | |
public string Secret | |
{ | |
get | |
{ | |
if (Cache && !string.IsNullOrEmpty(_cachedValue)) return _cachedValue; | |
return LoadSecret(); | |
} | |
set | |
{ | |
StoreSecret(value); | |
} | |
} | |
/// <summary> | |
/// Creates a new instance | |
/// </summary> | |
/// <param name="filePath">The filePath that the secret is located in</param> | |
/// <param name="cache">Cache the secret?</param> | |
public LazyKey(string filePath, bool cache = true) | |
{ | |
FilePath = filePath; | |
Cache = cache; | |
_cachedValue = null; | |
} | |
/// <summary> | |
/// Lazy Loads the key | |
/// </summary> | |
/// <param name="ignoreCache">Should the cache be ignored and reloaded.</param> | |
/// <returns>string key</returns> | |
public string LoadSecret() | |
{ | |
//Otherwise load it and store the cache if we can | |
string value = FilePath != null ? System.IO.File.ReadAllText(FilePath) : null; | |
if (Cache) _cachedValue = value; | |
return value; | |
} | |
/// <summary> | |
/// Writes the secret to the file path | |
/// </summary> | |
/// <param name="secret"></param> | |
public void StoreSecret(string secret) | |
{ | |
if (FilePath == null) throw new System.InvalidOperationException("Cannot store the secret as there is no FilePath."); | |
System.IO.File.WriteAllText(FilePath, secret); | |
if (Cache) _cachedValue = secret; | |
} | |
public override string ToString() { return FilePath; } | |
//The string implicits should not differ from each other. Using LazyKey lk = (string)(new LazyKey("s")); should return the same lazy key. | |
//public static implicit operator string(LazyKey key) { return key.GetSecret(); } | |
[System.Obsolete("Use ToString instead")] public static implicit operator string(LazyKey key) { return key.FilePath; } | |
/** [System.Obsolete("Use the constructor instead")] */ public static implicit operator LazyKey(string filePath) { return new LazyKey(filePath); } | |
private class Converter : Newtonsoft.Json.JsonConverter | |
{ | |
public override bool CanConvert(System.Type objectType) { return objectType == typeof(LazyKey); } | |
public override bool CanRead => true; | |
public override bool CanWrite => true; | |
public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) { writer.WriteValue(((LazyKey)value).FilePath); } | |
public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) | |
{ | |
if (existingValue == null) return new LazyKey(reader.Value?.ToString()); | |
((LazyKey)existingValue).FilePath = reader.Value?.ToString(); | |
return existingValue; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment