mirror of
https://git.v0l.io/Kieran/void.cat.git
synced 2025-09-30 19:43:07 +02:00
Move metadata to provider interface
This commit is contained in:
@@ -7,9 +7,9 @@ namespace VoidCat.Controllers;
|
|||||||
[Route("d")]
|
[Route("d")]
|
||||||
public class DownloadController : Controller
|
public class DownloadController : Controller
|
||||||
{
|
{
|
||||||
private readonly IFileStorage _storage;
|
private readonly IFileStore _storage;
|
||||||
|
|
||||||
public DownloadController(IFileStorage storage)
|
public DownloadController(IFileStore storage)
|
||||||
{
|
{
|
||||||
_storage = storage;
|
_storage = storage;
|
||||||
}
|
}
|
||||||
|
@@ -10,9 +10,9 @@ namespace VoidCat.Controllers
|
|||||||
[Route("upload")]
|
[Route("upload")]
|
||||||
public class UploadController : Controller
|
public class UploadController : Controller
|
||||||
{
|
{
|
||||||
private readonly IFileStorage _storage;
|
private readonly IFileStore _storage;
|
||||||
|
|
||||||
public UploadController(IFileStorage storage)
|
public UploadController(IFileStore storage)
|
||||||
{
|
{
|
||||||
_storage = storage;
|
_storage = storage;
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,8 @@ services.AddControllers().AddNewtonsoftJson();
|
|||||||
|
|
||||||
services.AddMemoryCache();
|
services.AddMemoryCache();
|
||||||
|
|
||||||
services.AddScoped<IFileStorage, LocalDiskFileIngressFactory>();
|
services.AddScoped<IFileMetadataStore, LocalDiskFileMetadataStore>();
|
||||||
|
services.AddScoped<IFileStore, LocalDiskFileIngressFactory>();
|
||||||
services.AddScoped<IStatsCollector, InMemoryStatsCollector>();
|
services.AddScoped<IStatsCollector, InMemoryStatsCollector>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
12
VoidCat/Services/IFileMetadataStore.cs
Normal file
12
VoidCat/Services/IFileMetadataStore.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using VoidCat.Model;
|
||||||
|
|
||||||
|
namespace VoidCat.Services;
|
||||||
|
|
||||||
|
public interface IFileMetadataStore
|
||||||
|
{
|
||||||
|
Task<InternalVoidFile?> Get(Guid id);
|
||||||
|
|
||||||
|
Task Set(InternalVoidFile meta);
|
||||||
|
|
||||||
|
Task Update(VoidFile patch, Guid editSecret);
|
||||||
|
}
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace VoidCat.Services
|
namespace VoidCat.Services
|
||||||
{
|
{
|
||||||
public interface IFileStorage
|
public interface IFileStore
|
||||||
{
|
{
|
||||||
Task<VoidFile?> Get(Guid id);
|
Task<VoidFile?> Get(Guid id);
|
||||||
|
|
||||||
@@ -11,5 +11,7 @@ namespace VoidCat.Services
|
|||||||
Task Egress(Guid id, Stream outStream, CancellationToken cts);
|
Task Egress(Guid id, Stream outStream, CancellationToken cts);
|
||||||
|
|
||||||
Task UpdateInfo(VoidFile patch, Guid editSecret);
|
Task UpdateInfo(VoidFile patch, Guid editSecret);
|
||||||
|
|
||||||
|
IAsyncEnumerable<VoidFile> ListFiles();
|
||||||
}
|
}
|
||||||
}
|
}
|
55
VoidCat/Services/LocalDiskFileMetadataStore.cs
Normal file
55
VoidCat/Services/LocalDiskFileMetadataStore.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using VoidCat.Model;
|
||||||
|
using VoidCat.Model.Exceptions;
|
||||||
|
|
||||||
|
namespace VoidCat.Services;
|
||||||
|
|
||||||
|
public class LocalDiskFileMetadataStore : IFileMetadataStore
|
||||||
|
{
|
||||||
|
private const string MetadataDir = "metadata";
|
||||||
|
private readonly VoidSettings _settings;
|
||||||
|
|
||||||
|
public LocalDiskFileMetadataStore(VoidSettings settings)
|
||||||
|
{
|
||||||
|
_settings = settings;
|
||||||
|
|
||||||
|
var metaPath = Path.Combine(_settings.DataDirectory, MetadataDir);
|
||||||
|
if (!Directory.Exists(metaPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(metaPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<InternalVoidFile?> Get(Guid id)
|
||||||
|
{
|
||||||
|
var path = MapMeta(id);
|
||||||
|
if (!File.Exists(path)) throw new VoidFileNotFoundException(id);
|
||||||
|
|
||||||
|
var json = await File.ReadAllTextAsync(path);
|
||||||
|
return JsonConvert.DeserializeObject<InternalVoidFile>(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Set(InternalVoidFile meta)
|
||||||
|
{
|
||||||
|
var path = MapMeta(meta.Id);
|
||||||
|
var json = JsonConvert.SerializeObject(meta);
|
||||||
|
return File.WriteAllTextAsync(path, json);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Update(VoidFile patch, Guid editSecret)
|
||||||
|
{
|
||||||
|
var oldMeta = await Get(patch.Id);
|
||||||
|
if (oldMeta?.EditSecret != editSecret)
|
||||||
|
{
|
||||||
|
throw new VoidNotAllowedException("Edit secret incorrect");
|
||||||
|
}
|
||||||
|
|
||||||
|
// only patch metadata
|
||||||
|
oldMeta.Metadata = patch.Metadata;
|
||||||
|
|
||||||
|
await Set(oldMeta);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string MapMeta(Guid id) =>
|
||||||
|
Path.ChangeExtension(Path.Join(_settings.DataDirectory, MetadataDir, id.ToString()), ".json");
|
||||||
|
}
|
@@ -1,19 +1,21 @@
|
|||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using VoidCat.Model;
|
using VoidCat.Model;
|
||||||
using VoidCat.Model.Exceptions;
|
using VoidCat.Model.Exceptions;
|
||||||
|
|
||||||
namespace VoidCat.Services;
|
namespace VoidCat.Services;
|
||||||
|
|
||||||
public class LocalDiskFileIngressFactory : IFileStorage
|
public class LocalDiskFileIngressFactory : IFileStore
|
||||||
{
|
{
|
||||||
private readonly VoidSettings _settings;
|
private readonly VoidSettings _settings;
|
||||||
private readonly IStatsCollector _stats;
|
private readonly IStatsCollector _stats;
|
||||||
|
private readonly IFileMetadataStore _metadataStore;
|
||||||
|
|
||||||
public LocalDiskFileIngressFactory(VoidSettings settings, IStatsCollector stats)
|
public LocalDiskFileIngressFactory(VoidSettings settings, IStatsCollector stats,
|
||||||
|
IFileMetadataStore metadataStore)
|
||||||
{
|
{
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
_stats = stats;
|
_stats = stats;
|
||||||
|
_metadataStore = metadataStore;
|
||||||
|
|
||||||
if (!Directory.Exists(_settings.DataDirectory))
|
if (!Directory.Exists(_settings.DataDirectory))
|
||||||
{
|
{
|
||||||
@@ -23,11 +25,7 @@ public class LocalDiskFileIngressFactory : IFileStorage
|
|||||||
|
|
||||||
public async Task<VoidFile?> Get(Guid id)
|
public async Task<VoidFile?> Get(Guid id)
|
||||||
{
|
{
|
||||||
var path = MapMeta(id);
|
return await _metadataStore.Get(id);
|
||||||
if (!File.Exists(path)) throw new VoidFileNotFoundException(id);
|
|
||||||
|
|
||||||
var json = await File.ReadAllTextAsync(path);
|
|
||||||
return JsonConvert.DeserializeObject<VoidFile>(json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Egress(Guid id, Stream outStream, CancellationToken cts)
|
public async Task Egress(Guid id, Stream outStream, CancellationToken cts)
|
||||||
@@ -70,35 +68,30 @@ public class LocalDiskFileIngressFactory : IFileStorage
|
|||||||
EditSecret = Guid.NewGuid()
|
EditSecret = Guid.NewGuid()
|
||||||
};
|
};
|
||||||
|
|
||||||
var mPath = MapMeta(id);
|
await _metadataStore.Set(fm);
|
||||||
var json = JsonConvert.SerializeObject(fm);
|
|
||||||
await File.WriteAllTextAsync(mPath, json, cts);
|
|
||||||
return fm;
|
return fm;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateInfo(VoidFile patch, Guid editSecret)
|
public Task UpdateInfo(VoidFile patch, Guid editSecret)
|
||||||
{
|
{
|
||||||
var path = MapMeta(patch.Id);
|
return _metadataStore.Update(patch, editSecret);
|
||||||
if (!File.Exists(path)) throw new VoidFileNotFoundException(patch.Id);
|
}
|
||||||
|
|
||||||
var oldJson = await File.ReadAllTextAsync(path);
|
public async IAsyncEnumerable<VoidFile> ListFiles()
|
||||||
var oldObj = JsonConvert.DeserializeObject<InternalVoidFile>(oldJson);
|
{
|
||||||
|
foreach (var fe in Directory.EnumerateFiles(_settings.DataDirectory))
|
||||||
if (oldObj?.EditSecret != editSecret)
|
|
||||||
{
|
{
|
||||||
throw new VoidNotAllowedException("Edit secret incorrect");
|
var filename = Path.GetFileNameWithoutExtension(fe);
|
||||||
|
if (!Guid.TryParse(filename, out var id)) continue;
|
||||||
|
|
||||||
|
var meta = await _metadataStore.Get(id);
|
||||||
|
if (meta != default)
|
||||||
|
{
|
||||||
|
yield return meta;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// only patch metadata
|
|
||||||
oldObj.Metadata = patch.Metadata;
|
|
||||||
|
|
||||||
var json = JsonConvert.SerializeObject(oldObj);
|
|
||||||
await File.WriteAllTextAsync(path, json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MapPath(Guid id) =>
|
private string MapPath(Guid id) =>
|
||||||
Path.Join(_settings.DataDirectory, id.ToString());
|
Path.Join(_settings.DataDirectory, id.ToString());
|
||||||
|
|
||||||
private string MapMeta(Guid id) =>
|
|
||||||
Path.ChangeExtension(MapPath(id), ".json");
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user