refactor: extract interface for storage provider

This commit is contained in:
Stevan Freeborn
2026-03-29 22:01:44 -05:00
parent d57bc9f5ad
commit a843976319
2 changed files with 42 additions and 3 deletions
@@ -0,0 +1,39 @@
namespace StevanFreeborn.Extensions.Configuration.Secure.Storage;
/// <summary>
/// Defines a contract for a provider that stores and retrieves secure configuration data.
/// </summary>
public interface ISecureStorageProvider
{
/// <summary>
/// Reads the value associated with the specified key asynchronously.
/// </summary>
/// <param name="key">The key of the configuration value to read.</param>
/// <param name="ct">A cancellation token that can be used to cancel the read operation.</param>
/// <returns>A task that represents the asynchronous read operation. The task result contains the value associated with the specified key, or an empty string if the key is not found.</returns>
Task<string> ReadAsync(string key, CancellationToken ct = default);
/// <summary>
/// Reads all configuration values asynchronously.
/// </summary>
/// <param name="ct">A cancellation token that can be used to cancel the read operation.</param>
/// <returns>A task that represents the asynchronous read operation. The task result contains a dictionary of all configuration keys and their encrypted values.</returns>
Task<IDictionary<string, string>> ReadAllAsync(CancellationToken ct = default);
/// <summary>
/// Writes the specified key and encrypted data asynchronously.
/// </summary>
/// <param name="key">The key of the configuration value to write.</param>
/// <param name="encryptedData">The encrypted configuration data to write.</param>
/// <param name="ct">A cancellation token that can be used to cancel the write operation.</param>
/// <returns>A task that represents the asynchronous write operation.</returns>
Task WriteAsync(string key, string encryptedData, CancellationToken ct = default);
/// <summary>
/// Deletes the configuration value associated with the specified key asynchronously.
/// </summary>
/// <param name="key">The key of the configuration value to delete.</param>
/// <param name="ct">A cancellation token that can be used to cancel the delete operation.</param>
/// <returns>A task that represents the asynchronous delete operation. The task result contains <c>true</c> if the value was successfully deleted; otherwise, <c>false</c>.</returns>
Task<bool> DeleteAsync(string key, CancellationToken ct = default);
}
@@ -6,7 +6,7 @@ namespace StevanFreeborn.Extensions.Configuration.Secure.Storage;
/// Provides a mechanism to store and retrieve secure configuration data in a JSON file.
/// </summary>
/// <param name="options">The <see cref="JsonStorageOptions"/> configuring the storage provider, including file paths.</param>
public sealed class JsonFileStorageProvider(JsonStorageOptions options)
public sealed class JsonFileStorageProvider(JsonStorageOptions options) : ISecureStorageProvider
{
private static readonly SemaphoreSlim FileLock = new(1, 1);
private static readonly JsonSerializerOptions JsonOptions = new()
@@ -39,7 +39,7 @@ public sealed class JsonFileStorageProvider(JsonStorageOptions options)
/// </summary>
/// <param name="ct">A cancellation token that can be used to cancel the read operation.</param>
/// <returns>A task that represents the asynchronous read operation. The task result contains a dictionary of all configuration keys and their values.</returns>
public Task<Dictionary<string, string>> ReadAllAsync(CancellationToken ct = default)
public Task<IDictionary<string, string>> ReadAllAsync(CancellationToken ct = default)
{
return AcquireLockAndLoadAsync(ct);
}
@@ -95,7 +95,7 @@ public sealed class JsonFileStorageProvider(JsonStorageOptions options)
/// </summary>
/// <param name="ct">A cancellation token to observe while waiting for the lock or during the load operation.</param>
/// <returns>A dictionary containing the loaded configuration data.</returns>
private async Task<Dictionary<string, string>> AcquireLockAndLoadAsync(CancellationToken ct)
private async Task<IDictionary<string, string>> AcquireLockAndLoadAsync(CancellationToken ct)
{
await FileLock.WaitAsync(ct).ConfigureAwait(false);