From 39a22deb6a232356bf7b2ef8386679bc8ea2f697 Mon Sep 17 00:00:00 2001 From: vnugent Date: Fri, 10 Nov 2023 22:40:35 -0500 Subject: much needed QOL updates --- back-end/src/Content.Publishing.Blog.Admin.csproj | 2 +- back-end/src/Endpoints/ContentEndpoint.cs | 62 +++++++++++++++++++---- back-end/src/Storage/ManagedStorage.cs | 14 ++++- 3 files changed, 66 insertions(+), 12 deletions(-) (limited to 'back-end/src') diff --git a/back-end/src/Content.Publishing.Blog.Admin.csproj b/back-end/src/Content.Publishing.Blog.Admin.csproj index 97a575f..8c923f0 100644 --- a/back-end/src/Content.Publishing.Blog.Admin.csproj +++ b/back-end/src/Content.Publishing.Blog.Admin.csproj @@ -34,7 +34,7 @@ - + diff --git a/back-end/src/Endpoints/ContentEndpoint.cs b/back-end/src/Endpoints/ContentEndpoint.cs index 2427cf0..92aee3b 100644 --- a/back-end/src/Endpoints/ContentEndpoint.cs +++ b/back-end/src/Endpoints/ContentEndpoint.cs @@ -22,6 +22,7 @@ using System; using System.IO; using System.Net; +using System.Linq; using System.Threading.Tasks; using FluentValidation; @@ -45,6 +46,7 @@ namespace Content.Publishing.Blog.Admin.Endpoints internal sealed class ContentEndpoint : ProtectedWebEndpoint { private static readonly IValidator MetaValidator = ContentMeta.GetValidator(); + private static readonly IValidator MultiDeleteValidator = GetMultiDeleteValidator(); private readonly ContentManager _content; private readonly IChannelContextManager _blogContextManager; @@ -312,12 +314,6 @@ namespace Content.Publishing.Blog.Admin.Endpoints return VfReturnType.BadRequest; } - //get the content id - if (!entity.QueryArgs.TryGetNonEmptyValue("id", out string? contentId)) - { - return VfReturnType.BadRequest; - } - //Get channel IChannelContext? channel = await _blogContextManager.GetChannelAsync(channelId, entity.EventCancellation); if (channel == null) @@ -325,11 +321,59 @@ namespace Content.Publishing.Blog.Admin.Endpoints return VfReturnType.NotFound; } - //Try to delete the content - bool deleted = await _content.DeleteContentAsync(channel, contentId, entity.EventCancellation); + //get the single content id + if (entity.QueryArgs.TryGetNonEmptyValue("id", out string? contentId)) + { + //Try to delete the content + bool deleted = await _content.DeleteContentAsync(channel, contentId, entity.EventCancellation); + + return deleted ? VirtualOk(entity) : VfReturnType.NotFound; + } + + //Check for bulk delete + if (entity.QueryArgs.TryGetNonEmptyValue("ids", out string? multiIds)) + { + ValErrWebMessage webm = new(); - return deleted ? VirtualOk(entity) : VfReturnType.NotFound; + string[] allIds = multiIds.Split(','); + + //validate the ids + if (!MultiDeleteValidator.Validate(allIds, webm)) + { + return VirtualClose(entity, webm, HttpStatusCode.UnprocessableEntity); + } + + //Delete all async at the same time, then filter out the nulls + Task[] deleted = allIds.Select(async id => + { + return await _content.DeleteContentAsync(channel, id, entity.EventCancellation) ? id : null; + + }).Where(id => id != null).ToArray()!; + + //Get the deleted ids + string[] deletedIds = await Task.WhenAll(deleted); + + webm.Result = deletedIds; + webm.Success = true; + + return VirtualOk(entity, webm); + } + + return VfReturnType.BadRequest; + } + + static IValidator GetMultiDeleteValidator() + { + InlineValidator val = new(); + + val.RuleForEach(p => p) + .NotEmpty() + .Length(0, 64) + .AlphaNumericOnly(); + + return val; + } } } diff --git a/back-end/src/Storage/ManagedStorage.cs b/back-end/src/Storage/ManagedStorage.cs index 19e208c..66e9a4a 100644 --- a/back-end/src/Storage/ManagedStorage.cs +++ b/back-end/src/Storage/ManagedStorage.cs @@ -30,13 +30,23 @@ using VNLib.Plugins.Extensions.Loading; namespace Content.Publishing.Blog.Admin.Storage { + [ConfigurationName("storage", Required = false)] internal sealed class ManagedStorage : ISimpleFilesystem { private readonly ISimpleFilesystem _backingStorage; - public ManagedStorage(PluginBase plugin) + public ManagedStorage(PluginBase plugin) : this(plugin, null) + { } + + public ManagedStorage(PluginBase plugin, IConfigScope? config) { - if (plugin.HasConfigForType()) + //try to get custom storage assembly + if (config != null && config.ContainsKey("custom_storage_assembly")) + { + string storageAssembly = config.GetRequiredProperty("custom_storage_assembly", p => p.GetString()!); + _backingStorage = plugin.CreateServiceExternal(storageAssembly); + } + else if (plugin.HasConfigForType()) { //Use minio storage _backingStorage = plugin.GetOrCreateSingleton(); -- cgit