Fix W3-T3 review: attach JWT in DeleteTrackDialog, int→long TrackId, log RemoveResourceAsync failure, drop redundant {Reason} log param

This commit is contained in:
Daniel Harvey
2026-05-18 15:42:58 -04:00
parent 4a59df6baa
commit 1738d262de
4 changed files with 31 additions and 18 deletions
@@ -1,6 +1,8 @@
@using System.Net.Http @using System.Net.Http
@using System.Net.Http.Headers
@using Microsoft.AspNetCore.Components @using Microsoft.AspNetCore.Components
@inject IHttpClientFactory HttpClientFactory @inject IHttpClientFactory HttpClientFactory
@inject AuthBlocksWeb.Services.ITokenService TokenService
<MudDialog> <MudDialog>
<DialogContent> <DialogContent>
@@ -34,7 +36,7 @@
@code { @code {
[CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = default!; [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = default!;
[Parameter] public int TrackId { get; set; } [Parameter] public long TrackId { get; set; }
[Parameter] public string TrackName { get; set; } = ""; [Parameter] public string TrackName { get; set; } = "";
[Parameter] public EventCallback OnDeleted { get; set; } [Parameter] public EventCallback OnDeleted { get; set; }
@@ -48,10 +50,10 @@
try try
{ {
// "DeepDrft.API" is the named client pointing at DeepDrftWeb's own host.
// The Admin role gate on the endpoint is enforced server-side by AuthBlocks;
// the registered HTTP client/auth handler stack attaches the JWT.
var client = HttpClientFactory.CreateClient("DeepDrft.API"); var client = HttpClientFactory.CreateClient("DeepDrft.API");
var token = await TokenService.GetAccessTokenAsync();
if (!string.IsNullOrEmpty(token))
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
var response = await client.DeleteAsync($"api/cms/track/{TrackId}"); var response = await client.DeleteAsync($"api/cms/track/{TrackId}");
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
@@ -1,5 +1,6 @@
using DeepDrftContent.Services.FileDatabase.Models; using DeepDrftContent.Services.FileDatabase.Models;
using DeepDrftContent.Services.FileDatabase.Utils; using DeepDrftContent.Services.FileDatabase.Utils;
using Microsoft.Extensions.Logging;
namespace DeepDrftContent.Services.FileDatabase.Services; namespace DeepDrftContent.Services.FileDatabase.Services;
@@ -12,19 +13,20 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
private readonly StructuralMap<string, MediaVault> _vaults; private readonly StructuralMap<string, MediaVault> _vaults;
private readonly IndexWatcher _indexWatcher; private readonly IndexWatcher _indexWatcher;
private readonly IndexFactoryService _indexFactory; private readonly IndexFactoryService _indexFactory;
private readonly ILogger<FileDatabase> _logger;
private bool _disposed; private bool _disposed;
/// <summary> /// <summary>
/// Factory method to create a FileDatabase instance /// Factory method to create a FileDatabase instance
/// </summary> /// </summary>
public static async Task<FileDatabase?> FromAsync(string rootPath) public static async Task<FileDatabase?> FromAsync(string rootPath, ILogger<FileDatabase>? logger = null)
{ {
var factoryService = new IndexFactoryService(); var factoryService = new IndexFactoryService();
var rootIndex = await factoryService.LoadOrCreateDirectoryIndexAsync(rootPath); var rootIndex = await factoryService.LoadOrCreateDirectoryIndexAsync(rootPath);
if (rootIndex != null) if (rootIndex != null)
{ {
var db = new FileDatabase(rootPath, rootIndex, factoryService); var db = new FileDatabase(rootPath, rootIndex, factoryService, logger);
await db.InitVaultsAsync(); await db.InitVaultsAsync();
return db; return db;
} }
@@ -32,11 +34,12 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
return null; return null;
} }
private FileDatabase(string rootPath, IDirectoryIndex index, IndexFactoryService indexFactory) : base(rootPath, index) private FileDatabase(string rootPath, IDirectoryIndex index, IndexFactoryService indexFactory, ILogger<FileDatabase>? logger = null) : base(rootPath, index)
{ {
_vaults = new StructuralMap<string, MediaVault>(); _vaults = new StructuralMap<string, MediaVault>();
_indexWatcher = new IndexWatcher(); _indexWatcher = new IndexWatcher();
_indexFactory = indexFactory; _indexFactory = indexFactory;
_logger = logger ?? Microsoft.Extensions.Logging.Abstractions.NullLogger<FileDatabase>.Instance;
} }
/// <summary> /// <summary>
@@ -192,9 +195,9 @@ public class FileDatabase : DirectoryIndexDirectory, IDisposable
return await directoryVault.RemoveEntryAsync(entryId); return await directoryVault.RemoveEntryAsync(entryId);
} }
catch catch (Exception ex)
{ {
// Swallow exceptions and return null, matching the FileDatabase error contract. _logger.LogError(ex, "RemoveResourceAsync failed for vault {VaultName} key {Key}", vaultId, entryId);
return null; return null;
} }
} }
+13 -5
View File
@@ -5,12 +5,13 @@ using DeepDrftContent.Services.FileDatabase.Models;
using DeepDrftContent.Services.FileDatabase.Services; using DeepDrftContent.Services.FileDatabase.Services;
using DeepDrftContent.Services.Processors; using DeepDrftContent.Services.Processors;
using DeepDrftContent.Models; using DeepDrftContent.Models;
using Microsoft.Extensions.Logging;
namespace DeepDrftContent namespace DeepDrftContent
{ {
public static class Startup public static class Startup
{ {
public static async Task ConfigureDomainServices(WebApplicationBuilder builder) public static Task ConfigureDomainServices(WebApplicationBuilder builder)
{ {
// Audio services // Audio services
builder.Services.AddSingleton<WavOffsetService>(); builder.Services.AddSingleton<WavOffsetService>();
@@ -22,10 +23,17 @@ namespace DeepDrftContent
var fileDatabaseSettings = builder.Configuration.GetSection(nameof(FileDatabaseSettings)).Get<FileDatabaseSettings>(); var fileDatabaseSettings = builder.Configuration.GetSection(nameof(FileDatabaseSettings)).Get<FileDatabaseSettings>();
if (fileDatabaseSettings is null) { throw new Exception("File database settings are not configured"); } if (fileDatabaseSettings is null) { throw new Exception("File database settings are not configured"); }
var fileDatabase = await FileDatabase.FromAsync(fileDatabaseSettings.VaultPath); var vaultPath = fileDatabaseSettings.VaultPath;
if (fileDatabase is null) { throw new Exception("Unable to initialize file database"); } builder.Services.AddSingleton(sp =>
builder.Services.AddSingleton(fileDatabase); {
await InitializeTrackVault(fileDatabase); var logger = sp.GetRequiredService<ILogger<FileDatabase>>();
var db = FileDatabase.FromAsync(vaultPath, logger).GetAwaiter().GetResult();
if (db is null) throw new Exception("Unable to initialize file database");
InitializeTrackVault(db).GetAwaiter().GetResult();
return db;
});
return Task.CompletedTask;
} }
private static async Task InitializeTrackVault(FileDatabase fileDatabase) private static async Task InitializeTrackVault(FileDatabase fileDatabase)
@@ -68,16 +68,16 @@ public class CmsDeleteController : ControllerBase
if (!response.IsSuccessStatusCode) if (!response.IsSuccessStatusCode)
{ {
_logger.LogWarning( _logger.LogWarning(
"Vault delete failed after SQL delete. {TrackId} {EntryKey} {Reason} {StatusCode}", "Vault delete failed after SQL delete. {TrackId} {EntryKey} {StatusCode}",
id, entryKey, "vault delete failed after SQL delete", (int)response.StatusCode); id, entryKey, (int)response.StatusCode);
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogWarning( _logger.LogWarning(
ex, ex,
"Vault delete threw after SQL delete. {TrackId} {EntryKey} {Reason}", "Vault delete threw after SQL delete. {TrackId} {EntryKey}",
id, entryKey, "vault delete failed after SQL delete"); id, entryKey);
} }
return Ok(); return Ok();