encyption wip
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
@@ -55,14 +54,25 @@ public partial class App : Application
|
||||
{
|
||||
args.AddServices(services =>
|
||||
{
|
||||
services.AddTransient<IEncryptor, AesEncryptor>();
|
||||
services.AddTransient<IDecryptor, AesDecryptor>();
|
||||
|
||||
services.AddTransient<IPasswordHasher, PasswordHasher>();
|
||||
services.AddTransient<IKeyDeriver, KeyDeriver>();
|
||||
|
||||
services.AddDbContextFactory<VaultDbContext>(args =>
|
||||
{
|
||||
args.UseSqlite();
|
||||
});
|
||||
|
||||
services.AddDbContextFactory<VaultDbContext>();
|
||||
services.AddHandler<VaultStorageHandler>();
|
||||
|
||||
services.AddHandler<OpenVaultHandler>();
|
||||
|
||||
services.AddHandler<CreateVaultStorageHandler>();
|
||||
services.AddHandler<OpenVaultStorageHandler>();
|
||||
|
||||
services.AddTemplate<VaultNavigationViewModel, VaultNavigationView>();
|
||||
services.AddTemplate<AllNavigationViewModel, AllNavigationView>();
|
||||
services.AddTemplate<StarredNavigationViewModel, StarredNavigationView>();
|
||||
services.AddTemplate<CategoriesNavigationViewModel, CategoriesNavigationView>();
|
||||
@@ -74,15 +84,13 @@ public partial class App : Application
|
||||
})!);
|
||||
|
||||
services.AddSingleton<IVaultHostCollection, VaultHostCollection>();
|
||||
services.AddHandler<VaultHandler>();
|
||||
services.AddHandler<CreateVaultHandler>();
|
||||
|
||||
//services.AddInitializer<VaultsInitializer>();
|
||||
services.AddInitializer<VaultCollectionInitializer>();
|
||||
|
||||
services.AddTemplate<MainViewModel, MainView>("Main");
|
||||
|
||||
services.AddTemplate<VaultNavigationViewModel, VaultNavigationView>();
|
||||
services.AddHandler<VaultNavigationViewModelHandler>();
|
||||
|
||||
services.AddTransient<FooterViewModel>();
|
||||
|
||||
services.AddTemplate<ManageNavigationViewModel, ManageNavigationView>();
|
||||
|
||||
@@ -12,7 +12,15 @@
|
||||
Margin="0,0,0,18"
|
||||
Text="{Binding Name}"
|
||||
Watermark="Enter vault name" />
|
||||
<TextBox Margin="0,0,0,18" Watermark="Enter password" />
|
||||
<TextBox Watermark="Confirm password" />
|
||||
<TextBox
|
||||
Margin="0,0,0,18"
|
||||
Classes="revealPasswordButton"
|
||||
PasswordChar="●"
|
||||
Text="{Binding Password}"
|
||||
Watermark="Enter password" />
|
||||
<TextBox
|
||||
Classes="revealPasswordButton"
|
||||
PasswordChar="●"
|
||||
Watermark="Confirm password" />
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
<UserControl
|
||||
x:Class="Bitvault.Avalonia.LockView"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:vm="using:Bitvault"
|
||||
x:DataType="vm:LockViewModel">
|
||||
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<TextBox
|
||||
Width="300"
|
||||
Classes="revealPasswordButton"
|
||||
PasswordChar="●">
|
||||
PasswordChar="●"
|
||||
Text="{Binding Password}">
|
||||
<Interaction.Behaviors>
|
||||
<KeyBindingTriggerBehavior Gesture="Enter">
|
||||
<NavigateAction Context="Main" Route="Vault" />
|
||||
</KeyBindingTriggerBehavior>
|
||||
<KeyBindingTriggerBehavior Gesture="Enter">
|
||||
<InvokeCommandAction Command="{Binding UnlockCommand}" />
|
||||
</KeyBindingTriggerBehavior>
|
||||
</Interaction.Behaviors>
|
||||
</TextBox>
|
||||
</StackPanel>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class AesDecryptor :
|
||||
IDecryptor
|
||||
{
|
||||
private const int IvSize = 16;
|
||||
|
||||
public string Decrypt(string cipherText, byte[] key)
|
||||
{
|
||||
byte[] cipherData = Convert.FromBase64String(cipherText);
|
||||
|
||||
byte[] iv = new byte[IvSize];
|
||||
Array.Copy(cipherData, 0, iv, 0, IvSize); // Extract the IV from the start of the cipher data
|
||||
|
||||
using var aes = Aes.Create();
|
||||
aes.Key = key;
|
||||
aes.IV = iv;
|
||||
|
||||
using var memoryStream = new MemoryStream(cipherData, IvSize, cipherData.Length - IvSize);
|
||||
using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
|
||||
using (var streamReader = new StreamReader(cryptoStream))
|
||||
{
|
||||
return streamReader.ReadToEnd(); // Return the decrypted text
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class AesEncryptor : IEncryptor
|
||||
{
|
||||
public string Encrypt(string plainText, byte[] key)
|
||||
{
|
||||
const int IvSize = 16;
|
||||
|
||||
using var aes = Aes.Create();
|
||||
aes.Key = key;
|
||||
aes.GenerateIV();
|
||||
|
||||
byte[] iv = aes.IV;
|
||||
|
||||
using var memoryStream = new MemoryStream();
|
||||
memoryStream.Write(iv, 0, IvSize); // Store IV at the start of the stream
|
||||
|
||||
using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
|
||||
using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
|
||||
using (var streamWriter = new StreamWriter(cryptoStream))
|
||||
{
|
||||
streamWriter.Write(plainText);
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(memoryStream.ToArray()); // Return the encrypted data in base64
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class CreateVaultHandler(IComponentFactory componentFactory) :
|
||||
IHandler<Create<Vault>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(Create<Vault> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is Vault vault)
|
||||
{
|
||||
if (vault.Name is { Length: > 0 } name && vault.Password is { Length: > 0 } password)
|
||||
{
|
||||
if (componentFactory.Create<IVaultComponent, VaultConfiguration>($"Vault:{name}", new VaultConfiguration { Name = name }) is IComponentHost host)
|
||||
{
|
||||
if (host.Services.GetRequiredService<IMediator>() is IMediator mediator)
|
||||
{
|
||||
if (await mediator.Handle<Create<VaultStorage>, bool>(Create.As(new VaultStorage(name, password)), cancellationToken))
|
||||
{
|
||||
await host.StartAsync(cancellationToken);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Security.Cryptography;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class CreateVaultStorageHandler(IHostEnvironment environment,
|
||||
IKeyDeriver deriver,
|
||||
IEncryptor encryptor,
|
||||
IDecryptor decryptor,
|
||||
IDbContextFactory<VaultDbContext> dbContextFactory) : IHandler<Create<VaultStorage>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(Create<VaultStorage> args, CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is VaultStorage vault)
|
||||
{
|
||||
if (vault.Name is { Length: > 0 } name && vault.Password is { Length: > 0 } password)
|
||||
{
|
||||
byte[] salt = new byte[16];
|
||||
RandomNumberGenerator.Fill(salt);
|
||||
|
||||
byte[] key = new byte[32];
|
||||
RandomNumberGenerator.Fill(key);
|
||||
|
||||
byte[] derivedKey = deriver.DeriveKey(password, salt);
|
||||
string? encryptedKey = encryptor.Encrypt(Convert.ToBase64String(key), derivedKey);
|
||||
|
||||
|
||||
byte[] derivedKey2 = deriver.DeriveKey(password, salt);
|
||||
var dod = decryptor.Decrypt(encryptedKey, derivedKey2);
|
||||
|
||||
// Derive the key for encryption
|
||||
|
||||
//byte[] encryptionKey = deriver.DeriveKey(password, salt);
|
||||
|
||||
//// Derive the key for decryption
|
||||
//byte[] decryptionKey = deriver.DeriveKey(password, salt);
|
||||
|
||||
//// Compare keys to ensure they're the same
|
||||
//bool areKeysEqual = encryptionKey.SequenceEqual(decryptionKey);
|
||||
|
||||
////byte[] derivedKey = deriver.DeriveKey(password, salt);
|
||||
//string? encrypted = encryptor.Encrypt(password, derivedKey);
|
||||
|
||||
//var storedSalt = Convert.ToBase64String(salt);
|
||||
|
||||
|
||||
//byte[] derivedKey2 = deriver.DeriveKey(password, salt);
|
||||
|
||||
//var d = decryptor.Decrypt(encrypted, derivedKey2);
|
||||
|
||||
// Generate a hash
|
||||
//string hash = hasher.HashPassword(password);
|
||||
|
||||
//string[] parts = hash.Split(':');
|
||||
|
||||
//// Store the salt only
|
||||
//string storedSalt = parts[0];
|
||||
|
||||
//// Use the hash as the password
|
||||
//string storedHash = parts[1];
|
||||
|
||||
//context.Database.SetConnectionString($"Data Source={Path.Combine(environment.ContentRootPath, name)}.vault;Mode=ReadWriteCreate;Password={storedHash}");
|
||||
//await context.Database.EnsureCreatedAsync();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,12 @@ public partial class CreateVaultViewModel(IServiceProvider provider,
|
||||
[ObservableProperty]
|
||||
private string name;
|
||||
|
||||
[MaybeNull]
|
||||
[ObservableProperty]
|
||||
private string password;
|
||||
|
||||
public async Task<bool> Confirm()
|
||||
{
|
||||
return await Mediator.Handle<Create<Vault>, bool>(Create.As(new Vault(Name, "")));
|
||||
return await Mediator.Handle<Create<Vault>, bool>(Create.As(new Vault(Name, Password)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Bitvault
|
||||
{
|
||||
public interface IDecryptor
|
||||
{
|
||||
string? Decrypt(string cipherText, byte[] key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Bitvault
|
||||
{
|
||||
public interface IEncryptor
|
||||
{
|
||||
|
||||
string? Encrypt(string plainText, byte[] key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public interface IKeyDeriver
|
||||
{
|
||||
byte[] DeriveKey(string password, byte[] salt, int keySize = 32, int iterations = 10000);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public interface IPasswordHasher
|
||||
{
|
||||
string HashPassword(string password, int iterations = 10000);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Bitvault
|
||||
{
|
||||
public interface IVaultConnectionPersistence
|
||||
{
|
||||
void Dispose();
|
||||
string? Get(string key);
|
||||
void Set(string key, string connection);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault
|
||||
{
|
||||
public interface IVaultFactory
|
||||
{
|
||||
IComponentHost? Create(string name,
|
||||
string password,
|
||||
VaultConfiguration configuration);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class KeyDeriver :
|
||||
IKeyDeriver
|
||||
{
|
||||
public byte[] DeriveKey(string password, byte[] salt, int keySize = 32, int iterations = 100000)
|
||||
{
|
||||
using Rfc2898DeriveBytes pbkdf2 = new(password, salt, iterations, HashAlgorithmName.SHA256);
|
||||
return pbkdf2.GetBytes(keySize);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,26 @@
|
||||
using Toolkit.Foundation;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class LockViewModel(IServiceProvider provider,
|
||||
public partial class LockViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
[ObservableProperty]
|
||||
private string? password;
|
||||
|
||||
[RelayCommand]
|
||||
private void Unlock()
|
||||
{
|
||||
if (Password is { Length: > 0 })
|
||||
{
|
||||
Mediator.Handle<Open<Vault>, bool>(Open.As(new Vault(Password)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class OpenVaultHandler(IMediator mediator) :
|
||||
IHandler<Open<Vault>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(Open<Vault> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is Vault vault)
|
||||
{
|
||||
if (vault.Password is { Length: > 0 } password)
|
||||
{
|
||||
if (await mediator.Handle<Open<VaultStorage>, bool>(Open.As(new VaultStorage("Personal", password)), cancellationToken))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class OpenVaultStorageHandler(IHostEnvironment environment,
|
||||
IDbContextFactory<VaultDbContext> dbContextFactory) : IHandler<Open<VaultStorage>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(Open<VaultStorage> args, CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is VaultStorage vault)
|
||||
{
|
||||
if (vault.Name is { Length: > 0 } name && vault.Password is { Length: > 0 } password)
|
||||
{
|
||||
using VaultDbContext context = dbContextFactory.CreateDbContext();
|
||||
var d = context.Database.GetDbConnection().ConnectionString;
|
||||
context.Database.SetConnectionString($"Data Source={Path.Combine(environment.ContentRootPath, name)}.vault;Mode=ReadWriteCreate;Password={password}");
|
||||
|
||||
bool isOpen = false;
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
await context.Database.OpenConnectionAsync();
|
||||
isOpen = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// We are ignoring this exception as it is either a go, or not.
|
||||
}
|
||||
|
||||
}, cancellationToken);
|
||||
|
||||
return isOpen;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class PasswordHasher :
|
||||
IPasswordHasher
|
||||
{
|
||||
private const int SaltSize = 16;
|
||||
|
||||
public string HashPassword(string password, int iterations = 10000)
|
||||
{
|
||||
using Rfc2898DeriveBytes pbkdf2 = new(password, SaltSize, iterations, HashAlgorithmName.SHA256);
|
||||
|
||||
byte[] salt = pbkdf2.Salt;
|
||||
byte[] hash = pbkdf2.GetBytes(32);
|
||||
|
||||
return $"{Convert.ToBase64String(salt)}:{Convert.ToBase64String(hash)}";
|
||||
}
|
||||
}
|
||||
+28
-2
@@ -1,3 +1,29 @@
|
||||
namespace Bitvault;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
public record Vault(string Name, string Password);
|
||||
namespace Bitvault;
|
||||
|
||||
public record Vault
|
||||
{
|
||||
public Vault(string name, string password)
|
||||
{
|
||||
Name = name;
|
||||
Password = password;
|
||||
}
|
||||
|
||||
public Vault(string password)
|
||||
{
|
||||
Password = password;
|
||||
}
|
||||
|
||||
|
||||
public Vault()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[MaybeNull]
|
||||
public string Name { get; }
|
||||
|
||||
[MaybeNull]
|
||||
public string? Password { get; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class VaultCollectionInitializer(IEnumerable<IConfigurationDescriptor<VaultConfiguration>> configurations,
|
||||
IComponentFactory componentFactory,
|
||||
IVaultHostCollection vaults) : IInitializer
|
||||
{
|
||||
public async Task Initialize()
|
||||
{
|
||||
foreach (IConfigurationDescriptor<VaultConfiguration> configuration in configurations)
|
||||
{
|
||||
if (componentFactory.Create<IVaultComponent, VaultConfiguration>(configuration.Section, configuration.Value) is IComponentHost host)
|
||||
{
|
||||
vaults.Add(host);
|
||||
await host.StartAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Bitvault;
|
||||
|
||||
public class VaultConnectionPersistence :
|
||||
IVaultConnectionPersistence,
|
||||
IDisposable
|
||||
{
|
||||
private string? connection;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
connection = null;
|
||||
}
|
||||
|
||||
public string? Get(string key)
|
||||
{
|
||||
return connection;
|
||||
}
|
||||
|
||||
public void Set(string key,
|
||||
string connection)
|
||||
{
|
||||
this.connection = connection;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
|
||||
public class VaultHandler(IComponentFactory factory) :
|
||||
IHandler<Create<Vault>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(Create<Vault> args,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is Vault vault)
|
||||
{
|
||||
if (factory.Create<IVaultComponent>($"Vault:{vault.Name}", new VaultConfiguration { Name = vault.Name }) is IComponentHost host)
|
||||
{
|
||||
if (host.Services.GetRequiredService<IMediator>() is IMediator mediator)
|
||||
{
|
||||
if (await mediator.Handle<Create<VaultStorage>, bool>(Create.As(new VaultStorage(vault.Name, vault.Password)), cancellationToken))
|
||||
{
|
||||
await host.StartAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class VaultInitializer(IServiceProvider provider,
|
||||
IProxyService<IPublisher> publisher) : IInitializer
|
||||
{
|
||||
public async Task Initialize()
|
||||
{
|
||||
if (provider.GetService<IComponentHost>() is IComponentHost vault)
|
||||
{
|
||||
if (vault.Services.GetRequiredService<VaultConfiguration>() is VaultConfiguration configuration)
|
||||
{
|
||||
if (vault.Services.GetRequiredService<IServiceFactory>() is IServiceFactory factory)
|
||||
{
|
||||
if (factory.Create<VaultNavigationViewModel>(configuration.Name) is VaultNavigationViewModel viewModel)
|
||||
{
|
||||
await publisher.Proxy.Publish(new Create<IMainNavigationViewModel>(viewModel),
|
||||
nameof(MainViewModel));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,27 @@
|
||||
using Toolkit.Foundation;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class VaultNavigationViewModelHandler(IPublisher publisher,
|
||||
IServiceFactory factory,
|
||||
IEnumerable<IConfigurationDescriptor<VaultConfiguration>> descriptors) :
|
||||
IVaultHostCollection vaults) :
|
||||
INotificationHandler<Enumerate<IMainNavigationViewModel>>
|
||||
{
|
||||
public async Task Handle(Enumerate<IMainNavigationViewModel> args,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
foreach (IConfigurationDescriptor<VaultConfiguration> descriptor in descriptors)
|
||||
foreach (IComponentHost vault in vaults)
|
||||
{
|
||||
if (factory.Create<VaultNavigationViewModel>(descriptor.Value.Name) is VaultNavigationViewModel viewModel)
|
||||
if (vault.Services.GetRequiredService<VaultConfiguration>() is VaultConfiguration configuration)
|
||||
{
|
||||
await publisher.Publish(new Create<IMainNavigationViewModel>(viewModel),
|
||||
nameof(MainViewModel), cancellationToken);
|
||||
if (vault.Services.GetRequiredService<IServiceFactory>() is IServiceFactory factory)
|
||||
{
|
||||
if (factory.Create<VaultNavigationViewModel>(configuration.Name) is VaultNavigationViewModel viewModel)
|
||||
{
|
||||
await publisher.Publish(new Create<IMainNavigationViewModel>(viewModel),
|
||||
nameof(MainViewModel), cancellationToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class VaultStorageHandler(IHostEnvironment environment,
|
||||
IDbContextFactory<VaultDbContext> dbContextFactory) :
|
||||
IHandler<Create<VaultStorage>, bool>
|
||||
{
|
||||
public async Task<bool> Handle(Create<VaultStorage> args, CancellationToken cancellationToken)
|
||||
{
|
||||
if (args.Value is VaultStorage storage)
|
||||
{
|
||||
using VaultDbContext context = dbContextFactory.CreateDbContext();
|
||||
await Task.Run(async () =>
|
||||
{
|
||||
context.Database.SetConnectionString($"Data Source={Path.Combine(environment.ContentRootPath, storage.Name)}.vault;Mode=ReadWriteCreate;Password={storage.Password}");
|
||||
await context.Database.EnsureCreatedAsync(cancellationToken);
|
||||
}, cancellationToken);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
using Toolkit.Foundation;
|
||||
|
||||
namespace Bitvault;
|
||||
|
||||
public class VaultsInitializer(IEnumerable<IConfigurationDescriptor<VaultConfiguration>> configurations,
|
||||
IVaultFactory factory) : IInitializer
|
||||
{
|
||||
public async Task Initialize()
|
||||
{
|
||||
foreach (IConfigurationDescriptor<VaultConfiguration> configuration in configurations)
|
||||
{
|
||||
//if (factory.Create(configuration.Section, configuration.Value) is IComponentHost host)
|
||||
//{
|
||||
// await host.StartAsync();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user