forked from Kieran/void.cat
Move metadata to provider interface
This commit is contained in:
parent
6d37b42d11
commit
3321e93478
@ -7,9 +7,9 @@ namespace VoidCat.Controllers;
|
||||
[Route("d")]
|
||||
public class DownloadController : Controller
|
||||
{
|
||||
private readonly IFileStorage _storage;
|
||||
private readonly IFileStore _storage;
|
||||
|
||||
public DownloadController(IFileStorage storage)
|
||||
public DownloadController(IFileStore storage)
|
||||
{
|
||||
_storage = storage;
|
||||
}
|
||||
|
@ -10,9 +10,9 @@ namespace VoidCat.Controllers
|
||||
[Route("upload")]
|
||||
public class UploadController : Controller
|
||||
{
|
||||
private readonly IFileStorage _storage;
|
||||
private readonly IFileStore _storage;
|
||||
|
||||
public UploadController(IFileStorage storage)
|
||||
public UploadController(IFileStore storage)
|
||||
{
|
||||
_storage = storage;
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ services.AddControllers().AddNewtonsoftJson();
|
||||
|
||||
services.AddMemoryCache();
|
||||
|
||||
services.AddScoped<IFileStorage, LocalDiskFileIngressFactory>();
|
||||
services.AddScoped<IFileMetadataStore, LocalDiskFileMetadataStore>();
|
||||
services.AddScoped<IFileStore, LocalDiskFileIngressFactory>();
|
||||
services.AddScoped<IStatsCollector, InMemoryStatsCollector>();
|
||||
|
||||
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
|
||||
{
|
||||
public interface IFileStorage
|
||||
public interface IFileStore
|
||||
{
|
||||
Task<VoidFile?> Get(Guid id);
|
||||
|
||||
@ -11,5 +11,7 @@ namespace VoidCat.Services
|
||||
Task Egress(Guid id, Stream outStream, CancellationToken cts);
|
||||
|
||||
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 Newtonsoft.Json;
|
||||
using VoidCat.Model;
|
||||
using VoidCat.Model.Exceptions;
|
||||
|
||||
namespace VoidCat.Services;
|
||||
|
||||
public class LocalDiskFileIngressFactory : IFileStorage
|
||||
public class LocalDiskFileIngressFactory : IFileStore
|
||||
{
|
||||
private readonly VoidSettings _settings;
|
||||
private readonly IStatsCollector _stats;
|
||||
private readonly IFileMetadataStore _metadataStore;
|
||||
|
||||
public LocalDiskFileIngressFactory(VoidSettings settings, IStatsCollector stats)
|
||||
public LocalDiskFileIngressFactory(VoidSettings settings, IStatsCollector stats,
|
||||
IFileMetadataStore metadataStore)
|
||||
{
|
||||
_settings = settings;
|
||||
_stats = stats;
|
||||
_metadataStore = metadataStore;
|
||||
|
||||
if (!Directory.Exists(_settings.DataDirectory))
|
||||
{
|
||||
@ -23,11 +25,7 @@ public class LocalDiskFileIngressFactory : IFileStorage
|
||||
|
||||
public async Task<VoidFile?> Get(Guid id)
|
||||
{
|
||||
var path = MapMeta(id);
|
||||
if (!File.Exists(path)) throw new VoidFileNotFoundException(id);
|
||||
|
||||
var json = await File.ReadAllTextAsync(path);
|
||||
return JsonConvert.DeserializeObject<VoidFile>(json);
|
||||
return await _metadataStore.Get(id);
|
||||
}
|
||||
|
||||
public async Task Egress(Guid id, Stream outStream, CancellationToken cts)
|
||||
@ -69,36 +67,31 @@ public class LocalDiskFileIngressFactory : IFileStorage
|
||||
Uploaded = DateTimeOffset.UtcNow,
|
||||
EditSecret = Guid.NewGuid()
|
||||
};
|
||||
|
||||
var mPath = MapMeta(id);
|
||||
var json = JsonConvert.SerializeObject(fm);
|
||||
await File.WriteAllTextAsync(mPath, json, cts);
|
||||
|
||||
await _metadataStore.Set(fm);
|
||||
return fm;
|
||||
}
|
||||
|
||||
public async Task UpdateInfo(VoidFile patch, Guid editSecret)
|
||||
public Task UpdateInfo(VoidFile patch, Guid editSecret)
|
||||
{
|
||||
var path = MapMeta(patch.Id);
|
||||
if (!File.Exists(path)) throw new VoidFileNotFoundException(patch.Id);
|
||||
|
||||
var oldJson = await File.ReadAllTextAsync(path);
|
||||
var oldObj = JsonConvert.DeserializeObject<InternalVoidFile>(oldJson);
|
||||
|
||||
if (oldObj?.EditSecret != editSecret)
|
||||
return _metadataStore.Update(patch, editSecret);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<VoidFile> ListFiles()
|
||||
{
|
||||
foreach (var fe in Directory.EnumerateFiles(_settings.DataDirectory))
|
||||
{
|
||||
throw new VoidNotAllowedException("Edit secret incorrect");
|
||||
}
|
||||
var filename = Path.GetFileNameWithoutExtension(fe);
|
||||
if (!Guid.TryParse(filename, out var id)) continue;
|
||||
|
||||
// only patch metadata
|
||||
oldObj.Metadata = patch.Metadata;
|
||||
|
||||
var json = JsonConvert.SerializeObject(oldObj);
|
||||
await File.WriteAllTextAsync(path, json);
|
||||
var meta = await _metadataStore.Get(id);
|
||||
if (meta != default)
|
||||
{
|
||||
yield return meta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string MapPath(Guid id) =>
|
||||
Path.Join(_settings.DataDirectory, id.ToString());
|
||||
|
||||
private string MapMeta(Guid id) =>
|
||||
Path.ChangeExtension(MapPath(id), ".json");
|
||||
}
|
Loading…
Reference in New Issue
Block a user