diff --git a/App/Keychain.csproj b/App/Keychain.csproj
index 415ac19..d30f67a 100644
--- a/App/Keychain.csproj
+++ b/App/Keychain.csproj
@@ -19,6 +19,7 @@
+
diff --git a/App/Program.cs b/App/Program.cs
index ecd4b5d..4d00e40 100644
--- a/App/Program.cs
+++ b/App/Program.cs
@@ -1,5 +1,6 @@
using Microsoft.Extensions.DependencyInjection;
using Logic;
+using Repository;
namespace Keychain;
@@ -25,8 +26,8 @@ class Program
private static ServiceProvider SetupServices()
{
var services = new ServiceCollection();
- //services.AddTransient();
services.AddSingleton();
+ services.AddSingleton();
return services.BuildServiceProvider();
}
}
\ No newline at end of file
diff --git a/App/UI/MainWindow/MainWindow.cs b/App/UI/MainWindow/MainWindow.cs
index c35dfa4..fece2e9 100644
--- a/App/UI/MainWindow/MainWindow.cs
+++ b/App/UI/MainWindow/MainWindow.cs
@@ -1,5 +1,5 @@
using Adw;
-using Keychain.UI.ViewModels;
+using Keychain.ViewModels;
namespace Keychain.UI;
diff --git a/App/ViewModels/PasswordStoreShortcut.cs b/App/ViewModels/PasswordStoreShortcut.cs
index 242cd2f..6437ae0 100644
--- a/App/ViewModels/PasswordStoreShortcut.cs
+++ b/App/ViewModels/PasswordStoreShortcut.cs
@@ -5,16 +5,9 @@ namespace Keychain.ViewModels;
public class PasswordStoreShortcut : INotifyPropertyChanged
{
- private IPasswordService passwordService;
+ private IPasswordStoreService passwordService;
public event PropertyChangedEventHandler? PropertyChanged;
- private string displayName;
- private bool displayNameSet = false;
- private string? iconName;
- private string path;
- public bool DisplayNameSet { get => displayNameSet; }
-
-
public string DisplayName
{
get => displayName;
diff --git a/Logic/IPasswordStoreService.cs b/Logic/IPasswordStoreService.cs
index 7ceb3f3..74b5969 100644
--- a/Logic/IPasswordStoreService.cs
+++ b/Logic/IPasswordStoreService.cs
@@ -6,9 +6,8 @@ public interface IPasswordStoreService
{
IEnumerable GetAll();
PasswordStore Get(uint ID);
- int Delete(uint ID);
- int Delete(PasswordStore item);
- int Create(string path, string? displayName = null, string? iconName = null);
- int Create(PasswordStore item);
- int Edit(uint ID, PasswordStore newItem);
+ void Delete(uint ID);
+ void Delete(PasswordStore item);
+ void Create(PasswordStore item);
+ void Edit(uint ID, PasswordStore newItem);
}
diff --git a/Logic/PasswordStoreService.cs b/Logic/PasswordStoreService.cs
index f0407d4..df7bb02 100644
--- a/Logic/PasswordStoreService.cs
+++ b/Logic/PasswordStoreService.cs
@@ -7,38 +7,33 @@ public class PasswordStoreService : IPasswordStoreService
{
private readonly IRepository repository;
- public int Create(string path, string? displayName = null, string? iconName = null)
+ public void Create(PasswordStore item)
+ {
+ Create(item);
+ }
+
+ public void Delete(uint ID)
{
throw new NotImplementedException();
}
- public int Create(PasswordStore item)
+ public void Delete(PasswordStore item)
{
- return Create(item.Path, item.DisplayName, item.IconName);
+ Delete(item.ID);
}
- public int Delete(uint ID)
- {
- throw new NotImplementedException();
- }
-
- public int Delete(PasswordStore item)
- {
- return Delete(item.ID);
- }
-
- public int Edit(uint ID, PasswordStore newItem)
+ public void Edit(uint ID, PasswordStore newItem)
{
throw new NotImplementedException();
}
public PasswordStore Get(uint ID)
{
- return repository.ReadAll().Where(item => item.ID.Equals(ID)).First();
+ return repository.Get(ID);
}
public IEnumerable GetAll()
{
- return (IEnumerable)repository.ReadAll();
+ return (IEnumerable)repository.GetAll();
}
}
diff --git a/Models/PasswordStore.cs b/Models/PasswordStore.cs
index 36243b7..28f6517 100644
--- a/Models/PasswordStore.cs
+++ b/Models/PasswordStore.cs
@@ -2,8 +2,8 @@
public class PasswordStore
{
- public uint ID;
- public string Path;
- public string? DisplayName;
- public string? IconName;
+ public uint ID { get; set; }
+ public string Path { get; set; }
+ public string? DisplayName { get; set; }
+ public string? IconName { get; set; }
}
\ No newline at end of file
diff --git a/Repository/IRepository.cs b/Repository/IRepository.cs
index af02874..5f2ddd4 100644
--- a/Repository/IRepository.cs
+++ b/Repository/IRepository.cs
@@ -1,10 +1,14 @@
using System.Collections;
+using Models;
namespace Repository;
public interface IRepository
{
- IEnumerable ReadAll();
- void WriteAll(IEnumerable items);
- object Get(uint id);
+ List GetAll();
+ PasswordStore? Get(uint id);
+ void Edit(uint ID, PasswordStore newItem);
+ void Create(PasswordStore item);
+ void Delete(uint ID);
+ void Delete(PasswordStore item);
}
\ No newline at end of file
diff --git a/Repository/JsonRepository.cs b/Repository/JsonRepository.cs
new file mode 100644
index 0000000..d28602f
--- /dev/null
+++ b/Repository/JsonRepository.cs
@@ -0,0 +1,172 @@
+using System.Text.Json;
+using Models;
+
+namespace Repository;
+
+public class JsonRepository : IRepository, IDisposable
+{
+ private const string _appName = "Keychain";
+
+ private uint _autoIncrementedId;
+ private readonly string _filePath;
+ private List _cache;
+ private bool _cacheAhead;
+
+ public JsonRepository(string fileName)
+ {
+ string? xdgDataHome = Environment.GetEnvironmentVariable("XDG_DATA_HOME");
+ string dataHome;
+ if (!string.IsNullOrEmpty(xdgDataHome))
+ {
+ dataHome = Path.Combine(xdgDataHome, _appName);
+ }
+ else
+ {
+ dataHome = Path.Combine(
+ Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"),
+ _appName
+ );
+ }
+ _filePath = Path.Combine(dataHome, fileName);
+
+ ReadAllFromFile();
+
+ var lastItem = _cache.OrderBy(item => item.ID).LastOrDefault();
+ _autoIncrementedId = lastItem != null ? lastItem.ID : 0;
+ }
+
+ private void ReadAllFromFile()
+ {
+ var items = new List();
+
+ if (File.Exists(_filePath))
+ {
+ try
+ {
+ string json = File.ReadAllText(_filePath);
+ items = JsonSerializer.Deserialize>(json) ?? new List();
+ }
+ catch (JsonException e)
+ {
+ WriteToStdErr($"JSON error: {e.Message}");
+ }
+ catch (IOException e)
+ {
+ WriteToStdErr($"File I/O error: {e.Message}");
+ }
+ catch (Exception e)
+ {
+ WriteToStdErr($"Unexpected error: {e.Message}");
+ }
+ }
+
+ _cache = items;
+ _cacheAhead = false;
+ }
+
+ public List GetAll()
+ {
+ return _cache;
+ }
+
+ public PasswordStore? Get(uint id)
+ {
+ try
+ {
+ return _cache.First(item => item.ID.Equals(id));
+ }
+ catch (InvalidOperationException)
+ {
+ // Not found
+ return null;
+ }
+ catch (Exception e)
+ {
+ WriteToStdErr($"Unexpected error: {e.Message}");
+ return null;
+ }
+ }
+
+ public void Dispose()
+ {
+ if (_cacheAhead)
+ {
+ try
+ {
+ string json = JsonSerializer.Serialize(_cache);
+ string? directory = Path.GetDirectoryName(_filePath);
+ if (!Directory.Exists(directory))
+ {
+ Directory.CreateDirectory(directory!);
+ }
+ File.WriteAllText(_filePath, json);
+ }
+ catch (IOException e)
+ {
+ WriteToStdErr($"File I/O error: {e.Message}");
+ }
+ catch (Exception e)
+ {
+ WriteToStdErr($"Unexpected error: {e.Message}");
+ }
+
+ ReadAllFromFile();
+ }
+ }
+
+ public void Edit(uint ID, PasswordStore newItem)
+ {
+ try
+ {
+ PasswordStore item = _cache.First(item => item.ID.Equals(ID));
+ item.DisplayName = newItem.DisplayName;
+ item.IconName = newItem.IconName;
+ item.Path = newItem.Path;
+ _cacheAhead = true;
+ }
+ catch (InvalidOperationException)
+ {
+ WriteToStdErr($"Edit error: Item with ID {ID} not found.");
+ }
+ catch (Exception e)
+ {
+ WriteToStdErr($"Unexpected error: {e.Message}");
+ }
+ }
+
+ public void Create(PasswordStore item)
+ {
+ item.ID = ++_autoIncrementedId;
+ _cache.Add(item);
+ _cacheAhead = true;
+ }
+
+ public void Delete(PasswordStore item)
+ {
+ Delete(item.ID);
+ }
+
+ public void Delete(uint id)
+ {
+ try
+ {
+ var item = _cache.First(item => item.ID.Equals(id));
+ _cache.Remove(item);
+ _cacheAhead = true;
+ }
+ catch (InvalidOperationException)
+ {
+ WriteToStdErr($"Delete error: Item with ID {id} not found.");
+ }
+ catch (Exception e)
+ {
+ WriteToStdErr($"Unexpected error: {e.Message}");
+ }
+ }
+
+ private void WriteToStdErr(string message)
+ {
+ using var sw = new StreamWriter(Console.OpenStandardError());
+ sw.WriteLine(message);
+ }
+}
\ No newline at end of file
diff --git a/Repository/Repository.cs b/Repository/Repository.cs
deleted file mode 100644
index 7df8078..0000000
--- a/Repository/Repository.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-using System.Collections;
-using System.Text.Json;
-
-namespace Repository;
-
-public class Repository : IRepository
-{
- private const string _appName = "Keychain";
- private readonly string _filePath;
- private List