From d66290269d4709fe2d909284801f31669aa26f74 Mon Sep 17 00:00:00 2001 From: vnugent Date: Thu, 31 Aug 2023 22:17:50 -0400 Subject: pre tag updates --- back-end/src/CMNextEntry.cs | 4 +- back-end/src/Content.Publishing.Blog.Admin.csproj | 5 +- back-end/src/Endpoints/ChannelEndpoint.cs | 5 ++ back-end/src/Model/ChannelManager.cs | 4 +- back-end/src/Model/ContentManager.cs | 4 +- back-end/src/Model/PostManager.cs | 19 +++++- back-end/src/Storage/FtpStorageManager.cs | 3 +- back-end/src/Storage/IStorageFacade.cs | 71 ----------------------- back-end/src/Storage/ManagedStorage.cs | 10 ++-- back-end/src/Storage/MinioClientManager.cs | 5 +- back-end/src/Storage/StorageBase.cs | 6 +- back-end/src/StorageExtensions.cs | 23 ++++---- 12 files changed, 54 insertions(+), 105 deletions(-) delete mode 100644 back-end/src/Storage/IStorageFacade.cs (limited to 'back-end/src') diff --git a/back-end/src/CMNextEntry.cs b/back-end/src/CMNextEntry.cs index 2800c08..4041122 100644 --- a/back-end/src/CMNextEntry.cs +++ b/back-end/src/CMNextEntry.cs @@ -75,8 +75,8 @@ namespace Content.Publishing.Blog.Admin Your server is now running at the following locations: {0} -****************************************************************************** -"; +******************************************************************************"; + string[] interfaces = HostConfig.GetProperty("virtual_hosts") .EnumerateArray() .Select(e => diff --git a/back-end/src/Content.Publishing.Blog.Admin.csproj b/back-end/src/Content.Publishing.Blog.Admin.csproj index 1a0a365..19839b7 100644 --- a/back-end/src/Content.Publishing.Blog.Admin.csproj +++ b/back-end/src/Content.Publishing.Blog.Admin.csproj @@ -7,7 +7,6 @@ README.md Content.Publishing.Blog.Admin CMNext - 0.1.1 @@ -34,8 +33,8 @@ - - + + diff --git a/back-end/src/Endpoints/ChannelEndpoint.cs b/back-end/src/Endpoints/ChannelEndpoint.cs index c63d093..d51ad3a 100644 --- a/back-end/src/Endpoints/ChannelEndpoint.cs +++ b/back-end/src/Endpoints/ChannelEndpoint.cs @@ -45,6 +45,7 @@ namespace Content.Publishing.Blog.Admin.Endpoints private static readonly IValidator FeedValidator = FeedMeta.GetValidator(); private readonly IChannelContextManager ContentManager; + private readonly PostManager PostManager; public ChannelEndpoint(PluginBase plugin, IConfigScope config) @@ -54,6 +55,7 @@ namespace Content.Publishing.Blog.Admin.Endpoints InitPathAndLog(path, plugin.Log); ContentManager = plugin.GetOrCreateSingleton(); + PostManager = plugin.GetOrCreateSingleton(); } protected override async ValueTask GetAsync(HttpEntity entity) @@ -172,6 +174,9 @@ namespace Content.Publishing.Blog.Admin.Endpoints return VfReturnType.VirtualSkip; } + //Update post feeds + await PostManager.UpdateFeedForChannelAsync(channel, entity.EventCancellation); + //Return the new blog context to the client entity.CloseResponse(HttpStatusCode.Created); return VfReturnType.VirtualSkip; diff --git a/back-end/src/Model/ChannelManager.cs b/back-end/src/Model/ChannelManager.cs index adcc3b2..22dbab9 100644 --- a/back-end/src/Model/ChannelManager.cs +++ b/back-end/src/Model/ChannelManager.cs @@ -26,19 +26,21 @@ using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; +using VNLib.Utils.IO; using VNLib.Hashing; using VNLib.Plugins; using VNLib.Plugins.Extensions.Loading; using Content.Publishing.Blog.Admin.Storage; + namespace Content.Publishing.Blog.Admin.Model { [ConfigurationName("blog_channels")] internal sealed class ChannelManager : IChannelContextManager { - private readonly IStorageFacade Storage; + private readonly ISimpleFilesystem Storage; private readonly string _indexPath; diff --git a/back-end/src/Model/ContentManager.cs b/back-end/src/Model/ContentManager.cs index a0ed94f..b5fc385 100644 --- a/back-end/src/Model/ContentManager.cs +++ b/back-end/src/Model/ContentManager.cs @@ -28,18 +28,18 @@ using System.Threading.Tasks; using Content.Publishing.Blog.Admin.Storage; using VNLib.Hashing; +using VNLib.Utils.IO; using VNLib.Net.Http; using VNLib.Plugins; using VNLib.Plugins.Extensions.Loading; - namespace Content.Publishing.Blog.Admin.Model { internal sealed class ContentManager { private const string ContentIndex = "content.json"; - private readonly IStorageFacade Storage; + private readonly ISimpleFilesystem Storage; public ContentManager(PluginBase plugin) { diff --git a/back-end/src/Model/PostManager.cs b/back-end/src/Model/PostManager.cs index 22e3682..922fba4 100644 --- a/back-end/src/Model/PostManager.cs +++ b/back-end/src/Model/PostManager.cs @@ -42,7 +42,7 @@ namespace Content.Publishing.Blog.Admin.Model internal sealed class PostManager : IBlogPostManager { - private readonly IStorageFacade Storage; + private readonly ISimpleFilesystem Storage; private readonly IRssFeedGenerator FeedGenerator; private readonly ContentManager ContentMan; @@ -166,6 +166,23 @@ namespace Content.Publishing.Blog.Admin.Model return true; } + /// + /// Updates the index and feed for all posts for the given channel. + /// + /// The channel context to update the feed for + /// A token to cancel the operatio + /// A task that completes when the channel feed has been updated + /// + public async Task UpdateFeedForChannelAsync(IChannelContext context, CancellationToken cancellation) + { + _ = context ?? throw new ArgumentNullException(nameof(context)); + + //Get the index + IRecordDb db = await GetPostIndexAsync(context, cancellation); + + //Update the index and feed after post update + await UpdateIndexAndFeed(context, db, cancellation); + } private async Task UpdateIndexAndFeed(IChannelContext context, IRecordDb index, CancellationToken cancellation) { diff --git a/back-end/src/Storage/FtpStorageManager.cs b/back-end/src/Storage/FtpStorageManager.cs index abcf5e1..d64d4ea 100644 --- a/back-end/src/Storage/FtpStorageManager.cs +++ b/back-end/src/Storage/FtpStorageManager.cs @@ -29,7 +29,6 @@ using System.Collections.Generic; using FluentFTP; using FluentFTP.Exceptions; -using VNLib.Net.Http; using VNLib.Utils.Logging; using VNLib.Utils.Resources; using VNLib.Plugins; @@ -102,7 +101,7 @@ namespace Content.Publishing.Blog.Admin.Storage } /// - public override async Task SetFileAsync(string filePath, Stream data, ContentType ct, CancellationToken cancellation) + public override async Task WriteFileAsync(string filePath, Stream data, string ct, CancellationToken cancellation) { //Upload the file to the server FtpStatus status = await _client.UploadStream(data, GetExternalFilePath(filePath), FtpRemoteExists.Overwrite, true, token: cancellation); diff --git a/back-end/src/Storage/IStorageFacade.cs b/back-end/src/Storage/IStorageFacade.cs deleted file mode 100644 index 703394b..0000000 --- a/back-end/src/Storage/IStorageFacade.cs +++ /dev/null @@ -1,71 +0,0 @@ -/* -* Copyright (c) 2023 Vaughn Nugent -* -* Library: CMNext -* Package: Content.Publishing.Blog.Admin -* File: IStorageFacade.cs -* -* CMNext is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as -* published by the Free Software Foundation, either version 3 of the -* License, or (at your option) any later version. -* -* CMNext is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU Affero General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see https://www.gnu.org/licenses/. -*/ - -using System; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -using VNLib.Net.Http; - -namespace Content.Publishing.Blog.Admin.Storage -{ - /// - /// Represents an opaque storage interface that abstracts simple storage operations - /// ignorant of the underlying storage system. - /// - internal interface IStorageFacade - { - /// - /// Gets the full public file path for the given relative file path - /// - /// The relative file path of the item to get the full path for - /// The full relative file path - string GetExternalFilePath(string filePath); - - /// - /// Deletes a file from the storage system asynchronously - /// - /// The path to the file to delete - /// A token to cancel the operation - /// A task that represents and asynchronous work - Task DeleteFileAsync(string filePath, CancellationToken cancellation); - - /// - /// Writes a file from the stream to the given file location - /// - /// The path to the file to write to - /// The file data to stream - /// The content type of the file to write - /// A token to cancel the operation - /// A task that represents and asynchronous work - Task SetFileAsync(string filePath, Stream data, ContentType ct, CancellationToken cancellation); - - /// - /// Reads a file from the storage system at the given path asynchronously - /// - /// The file to read - /// The stream to write the file output to - /// A token to cancel the operation - /// The number of bytes read, -1 if the operation failed - Task ReadFileAsync(string filePath, Stream output, CancellationToken cancellation); - } -} diff --git a/back-end/src/Storage/ManagedStorage.cs b/back-end/src/Storage/ManagedStorage.cs index 654695f..19e208c 100644 --- a/back-end/src/Storage/ManagedStorage.cs +++ b/back-end/src/Storage/ManagedStorage.cs @@ -24,15 +24,15 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -using VNLib.Net.Http; +using VNLib.Utils.IO; using VNLib.Plugins; using VNLib.Plugins.Extensions.Loading; namespace Content.Publishing.Blog.Admin.Storage { - internal sealed class ManagedStorage : IStorageFacade + internal sealed class ManagedStorage : ISimpleFilesystem { - private readonly IStorageFacade _backingStorage; + private readonly ISimpleFilesystem _backingStorage; public ManagedStorage(PluginBase plugin) { @@ -81,7 +81,7 @@ namespace Content.Publishing.Blog.Admin.Storage } /// - public Task SetFileAsync(string filePath, Stream data, ContentType ct, CancellationToken cancellation) + public Task WriteFileAsync(string filePath, Stream data, string ct, CancellationToken cancellation) { //Try to reset the stream if allowed if (data.CanSeek) @@ -90,7 +90,7 @@ namespace Content.Publishing.Blog.Admin.Storage data.Seek(0, SeekOrigin.Begin); } - return _backingStorage.SetFileAsync(filePath, data, ct, cancellation); + return _backingStorage.WriteFileAsync(filePath, data, ct, cancellation); } } } diff --git a/back-end/src/Storage/MinioClientManager.cs b/back-end/src/Storage/MinioClientManager.cs index e9f7c9a..6dd0f5c 100644 --- a/back-end/src/Storage/MinioClientManager.cs +++ b/back-end/src/Storage/MinioClientManager.cs @@ -26,7 +26,6 @@ using System.Threading.Tasks; using Minio; using Minio.DataModel; -using VNLib.Net.Http; using VNLib.Utils.Memory; using VNLib.Utils.Extensions; using VNLib.Plugins; @@ -94,11 +93,11 @@ namespace Content.Publishing.Blog.Admin.Storage } /// - public override Task SetFileAsync(string filePath, Stream data, ContentType ct, CancellationToken cancellation) + public override Task WriteFileAsync(string filePath, Stream data, string ct, CancellationToken cancellation) { PutObjectArgs args = new(); args.WithBucket(Config.BaseBucket) - .WithContentType(HttpHelpers.GetContentTypeString(ct)) + .WithContentType(ct) .WithObject(filePath) .WithObjectSize(data.Length) .WithStreamData(data); diff --git a/back-end/src/Storage/StorageBase.cs b/back-end/src/Storage/StorageBase.cs index b33d6f1..fe11c39 100644 --- a/back-end/src/Storage/StorageBase.cs +++ b/back-end/src/Storage/StorageBase.cs @@ -23,13 +23,13 @@ using System.IO; using System.Threading; using System.Threading.Tasks; -using VNLib.Net.Http; using VNLib.Plugins; +using VNLib.Utils.IO; using VNLib.Plugins.Extensions.Loading; namespace Content.Publishing.Blog.Admin.Storage { - internal abstract class StorageBase : IAsyncConfigurable, IStorageFacade + internal abstract class StorageBase : IAsyncConfigurable, ISimpleFilesystem { /// /// The base file path within the remote file system to use for external urls @@ -46,7 +46,7 @@ namespace Content.Publishing.Blog.Admin.Storage public abstract Task ReadFileAsync(string filePath, Stream output, CancellationToken cancellation); /// - public abstract Task SetFileAsync(string filePath, Stream data, ContentType ct, CancellationToken cancellation); + public abstract Task WriteFileAsync(string filePath, Stream data, string ct, CancellationToken cancellation); /// public virtual string GetExternalFilePath(string filePath) diff --git a/back-end/src/StorageExtensions.cs b/back-end/src/StorageExtensions.cs index cb4ba5a..8acb26e 100644 --- a/back-end/src/StorageExtensions.cs +++ b/back-end/src/StorageExtensions.cs @@ -27,7 +27,6 @@ using VNLib.Utils.IO; using VNLib.Net.Http; using Content.Publishing.Blog.Admin.Model; -using Content.Publishing.Blog.Admin.Storage; namespace Content.Publishing.Blog.Admin { @@ -43,9 +42,9 @@ namespace Content.Publishing.Blog.Admin /// The file content type /// A token to cancel the operation /// A task that completes when the file data has been written to the storage layer - public static Task SetObjectDataAsync(this IStorageFacade storage, IChannelContext context, Stream data, string path, ContentType ct, CancellationToken cancellation) + public static Task SetObjectDataAsync(this ISimpleFilesystem storage, IChannelContext context, Stream data, string path, ContentType ct, CancellationToken cancellation) { - return storage.SetFileAsync($"{context.BaseDir}/{path}", data, ct, cancellation); + return storage.WriteFileAsync($"{context.BaseDir}/{path}", data, HttpHelpers.GetContentTypeString(ct), cancellation); } /// @@ -56,7 +55,7 @@ namespace Content.Publishing.Blog.Admin /// The item path within the channel to delete /// A token to cancel the operation /// A task that completes when the deletion operation has completed - public static Task RemoveObjectAsync(this IStorageFacade storage, IChannelContext context, string path, CancellationToken cancellation) + public static Task RemoveObjectAsync(this ISimpleFilesystem storage, IChannelContext context, string path, CancellationToken cancellation) { return storage.DeleteFileAsync($"{context.BaseDir}/{path}", cancellation); } @@ -71,7 +70,7 @@ namespace Content.Publishing.Blog.Admin /// The relative path inside the channel to load the database from /// A token to cancel the operation /// A task that resolves the new from file - public static Task> LoadDbAsync(this IStorageFacade storage, IChannelContext context, string fileName, CancellationToken cancellation) where T : IRecord + public static Task> LoadDbAsync(this ISimpleFilesystem storage, IChannelContext context, string fileName, CancellationToken cancellation) where T : IRecord { return storage.LoadDbAsync($"{context.BaseDir}/{fileName}", cancellation); } @@ -86,7 +85,7 @@ namespace Content.Publishing.Blog.Admin /// The database to capture the file data from /// A token to cancel the operation /// A task that completes when the database has been stored - public static Task StoreAsync(this IStorageFacade storage, IChannelContext context, string fileName, IRecordDb store, CancellationToken cancellation) + public static Task StoreAsync(this ISimpleFilesystem storage, IChannelContext context, string fileName, IRecordDb store, CancellationToken cancellation) { return storage.StoreAsync($"{context.BaseDir}/{fileName}", store, cancellation); } @@ -101,7 +100,7 @@ namespace Content.Publishing.Blog.Admin /// The stream to write the file data to from the storage layer /// A token to cancel the operation /// A task that resolves the number of bytes read into the output stream - public static Task ReadFileAsync(this IStorageFacade storage, IChannelContext context, string fileName, Stream stream, CancellationToken cancellation) + public static Task ReadFileAsync(this ISimpleFilesystem storage, IChannelContext context, string fileName, Stream stream, CancellationToken cancellation) { return storage.ReadFileAsync($"{context.BaseDir}/{fileName}", stream, cancellation); } @@ -113,7 +112,7 @@ namespace Content.Publishing.Blog.Admin /// The channel context that contains the item /// The realtive path inside the channel to the item to get the path for /// The full external path of the item - public static string GetExternalFilePath(this IStorageFacade storage, IChannelContext context, string path) + public static string GetExternalFilePath(this ISimpleFilesystem storage, IChannelContext context, string path) { return storage.GetExternalFilePath($"{context.BaseDir}/{path}"); } @@ -127,7 +126,7 @@ namespace Content.Publishing.Blog.Admin /// The file path to store the record at /// A token to cancel the operation /// A task that completes when the operation has completed - public static async Task StoreAsync(this IStorageFacade storage, string path, IRecordDb store, CancellationToken cancellation) + public static async Task StoreAsync(this ISimpleFilesystem storage, string path, IRecordDb store, CancellationToken cancellation) { //Alloc ms to write records to using VnMemoryStream ms = new(); @@ -135,7 +134,7 @@ namespace Content.Publishing.Blog.Admin //Write the records to the stream store.Store(ms); - await storage.SetFileAsync(path, ms, ContentType.Json, cancellation); + await storage.WriteFileAsync(path, ms, HttpHelpers.GetContentTypeString(ContentType.Json), cancellation); } /// @@ -147,7 +146,7 @@ namespace Content.Publishing.Blog.Admin /// The path to the stored database file /// A token to cancel the operation /// The populated , if loading fails (file not found etc) the store will be returned empty - public static async Task> LoadDbAsync(this IStorageFacade storage, string objPath, CancellationToken cancellation) where T : IRecord + public static async Task> LoadDbAsync(this ISimpleFilesystem storage, string objPath, CancellationToken cancellation) where T : IRecord { //Create the db IRecordDb db = JsonRecordDb.Create(); @@ -166,7 +165,7 @@ namespace Content.Publishing.Blog.Admin /// The record database store ready to accept the database content /// A token to cancel the operation /// A task that completes when the database has been populated - public static async Task LoadDbAsync(this IStorageFacade storage, string objPath, IRecordDb db, CancellationToken cancellation) where T : IRecord + public static async Task LoadDbAsync(this ISimpleFilesystem storage, string objPath, IRecordDb db, CancellationToken cancellation) where T : IRecord { //Mem stream to read the object into using VnMemoryStream ms = new(); -- cgit