CRUD implemented
This commit is contained in:
@@ -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<PasswordStore> GetAll();
|
||||
PasswordStore? Get(uint id);
|
||||
void Edit(uint ID, PasswordStore newItem);
|
||||
void Create(PasswordStore item);
|
||||
void Delete(uint ID);
|
||||
void Delete(PasswordStore item);
|
||||
}
|
||||
172
Repository/JsonRepository.cs
Normal file
172
Repository/JsonRepository.cs
Normal file
@@ -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<PasswordStore> _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<PasswordStore>();
|
||||
|
||||
if (File.Exists(_filePath))
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(_filePath);
|
||||
items = JsonSerializer.Deserialize<List<PasswordStore>>(json) ?? new List<PasswordStore>();
|
||||
}
|
||||
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<PasswordStore> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<object>? _cache;
|
||||
private bool _cacheDirty = true;
|
||||
|
||||
public Repository(string fileName)
|
||||
{
|
||||
var 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);
|
||||
}
|
||||
|
||||
public IEnumerable ReadAll()
|
||||
{
|
||||
if (!_cacheDirty && _cache != null)
|
||||
return _cache;
|
||||
|
||||
if (!File.Exists(_filePath))
|
||||
{
|
||||
_cache = new List<object>();
|
||||
}
|
||||
else
|
||||
{
|
||||
var json = File.ReadAllText(_filePath);
|
||||
_cache = JsonSerializer.Deserialize<List<object>>(json) ?? new List<object>();
|
||||
}
|
||||
_cacheDirty = false;
|
||||
return _cache;
|
||||
}
|
||||
|
||||
public object Get(uint id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void WriteAll(IEnumerable items)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(items);
|
||||
var directory = Path.GetDirectoryName(_filePath);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory!);
|
||||
}
|
||||
File.WriteAllText(_filePath, json);
|
||||
|
||||
_cache = (List<object>)items;
|
||||
_cacheDirty = false;
|
||||
}
|
||||
}
|
||||
@@ -6,4 +6,8 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Models/Models.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user