92 lines
3.2 KiB
C#
92 lines
3.2 KiB
C#
|
|
using Elsa.Persistence.VNext.Sqlite;
|
||
|
|
using Elsa.Secrets.Models;
|
||
|
|
using Elsa.Secrets.Persistence.VNext;
|
||
|
|
using Elsa.Secrets.Persistence.VNext.Repositories;
|
||
|
|
using Microsoft.Data.Sqlite;
|
||
|
|
|
||
|
|
namespace Elsa.Persistence.VNext.UnitTests;
|
||
|
|
|
||
|
|
public class VNextSecretRepositoryTests : IAsyncDisposable
|
||
|
|
{
|
||
|
|
private readonly SqliteConnection _connection = new("Data Source=:memory:");
|
||
|
|
private readonly SqliteDocumentStore _store;
|
||
|
|
private readonly VNextSecretRepository _repository;
|
||
|
|
|
||
|
|
public VNextSecretRepositoryTests()
|
||
|
|
{
|
||
|
|
_store = new SqliteDocumentStore(_connection, new SecretPersistenceSchemaProvider().DescribeSchema());
|
||
|
|
_repository = new VNextSecretRepository(_store);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task Repository_PersistsAndListsSecretsThroughDocumentStore()
|
||
|
|
{
|
||
|
|
await ActivateAsync();
|
||
|
|
await _repository.AddAsync(CreateSecret("smtp:password", "SMTP password"));
|
||
|
|
|
||
|
|
var reloaded = await _repository.GetAsync("SMTP:PASSWORD");
|
||
|
|
Assert.NotNull(reloaded);
|
||
|
|
Assert.Equal("SMTP password", reloaded.DisplayName);
|
||
|
|
Assert.Contains("api-key", reloaded.Tags);
|
||
|
|
|
||
|
|
reloaded.DisplayName = "Updated password";
|
||
|
|
await _repository.SaveAsync(reloaded);
|
||
|
|
|
||
|
|
var listed = await _repository.ListAsync();
|
||
|
|
Assert.Single(listed);
|
||
|
|
Assert.Equal("Updated password", listed.Single().DisplayName);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Fact]
|
||
|
|
public async Task TryAddOrReplaceDeletedAsync_ReplacesOnlyDeletedSecret()
|
||
|
|
{
|
||
|
|
await ActivateAsync();
|
||
|
|
await _repository.AddAsync(CreateSecret("smtp:password", "SMTP password"));
|
||
|
|
|
||
|
|
var activeReplacementResult = await _repository.TryAddOrReplaceDeletedAsync(CreateSecret("SMTP:PASSWORD", "Active replacement"));
|
||
|
|
var deleted = CreateSecret("smtp:password", "Deleted password");
|
||
|
|
deleted.Status = SecretStatus.Deleted;
|
||
|
|
await _repository.SaveAsync(deleted);
|
||
|
|
|
||
|
|
var deletedReplacementResult = await _repository.TryAddOrReplaceDeletedAsync(CreateSecret("SMTP:PASSWORD", "Replacement password"));
|
||
|
|
var reloaded = await _repository.GetAsync("smtp:password");
|
||
|
|
|
||
|
|
Assert.False(activeReplacementResult);
|
||
|
|
Assert.True(deletedReplacementResult);
|
||
|
|
Assert.NotNull(reloaded);
|
||
|
|
Assert.Equal("Replacement password", reloaded.DisplayName);
|
||
|
|
Assert.Equal(SecretStatus.Active, reloaded.Status);
|
||
|
|
}
|
||
|
|
|
||
|
|
public async ValueTask DisposeAsync()
|
||
|
|
{
|
||
|
|
await _connection.DisposeAsync();
|
||
|
|
}
|
||
|
|
|
||
|
|
private async Task ActivateAsync()
|
||
|
|
{
|
||
|
|
await _connection.OpenAsync();
|
||
|
|
await _store.MaterializeAsync();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static Secret CreateSecret(string name, string displayName)
|
||
|
|
{
|
||
|
|
return new Secret
|
||
|
|
{
|
||
|
|
Name = name.Trim().ToLowerInvariant(),
|
||
|
|
DisplayName = displayName,
|
||
|
|
TypeName = SecretTypeNames.Text,
|
||
|
|
StoreName = SecretStoreNames.Encrypted,
|
||
|
|
Tags = ["API-Key"],
|
||
|
|
Versions =
|
||
|
|
{
|
||
|
|
new SecretVersion
|
||
|
|
{
|
||
|
|
Version = 1,
|
||
|
|
Payload = new SecretPayload { Value = "stored", Metadata = { ["protectedValue"] = "ciphertext" } }
|
||
|
|
}
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|
||
|
|
}
|