Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
54bca09
Add .NET 10 migration build workflow
magiccodingman Jul 24, 2026
ee37edf
Run migration build for pull requests
magiccodingman Jul 24, 2026
b7fdea3
Update CI validation for .NET 10
magiccodingman Jul 24, 2026
64159d2
Capture complete .NET 10 build diagnostics
magiccodingman Jul 24, 2026
2278b01
Migrate metrics charts to MudBlazor 9
magiccodingman Jul 24, 2026
e260818
Automate the next MudBlazor migration fixes
magiccodingman Jul 24, 2026
df5c3b5
Fix MudBlazor 9 chart, dialog, and grid APIs
github-actions[bot] Jul 24, 2026
d86c43f
Run migration patches against the repair branch
magiccodingman Jul 24, 2026
aff0a36
Capture complete .NET 10 test diagnostics
magiccodingman Jul 24, 2026
081c453
Retarget TLS tests to .NET 10
magiccodingman Jul 24, 2026
00ef468
Migrate domain backup file upload to MudBlazor 9
magiccodingman Jul 24, 2026
74cbeb3
Apply remaining MudBlazor 9 component migrations
magiccodingman Jul 24, 2026
c7986e8
Add temporary compiler-driven migration script
magiccodingman Jul 24, 2026
1a6726c
Run migration fixes from a standalone script
magiccodingman Jul 24, 2026
db4d5c8
Finish MudBlazor 9 form and component migrations
github-actions[bot] Jul 24, 2026
190af2f
Update .NET 10 test host packages
magiccodingman Jul 24, 2026
19b9840
Add .NET 10 test-host diagnostics
magiccodingman Jul 24, 2026
cbc586d
Restore TLS test project explicitly
magiccodingman Jul 24, 2026
cf00904
Migrate add-ban validation to async MudForm APIs
magiccodingman Jul 24, 2026
362294c
Migrate add-user validation to async MudForm APIs
magiccodingman Jul 24, 2026
baec649
Migrate password validation to async MudForm APIs
magiccodingman Jul 24, 2026
9018aff
Migrate domain validation to async MudForm APIs
magiccodingman Jul 24, 2026
10596be
Pin patched SQLite native bundle
magiccodingman Jul 24, 2026
0b3fb9a
Finalize .NET 10 TLS validation workflow
magiccodingman Jul 24, 2026
2b4b2e0
Remove temporary migration build workflow
magiccodingman Jul 24, 2026
c36e6a5
Remove temporary migration helper script
magiccodingman Jul 24, 2026
39adf11
Document explicit TLS test restore
magiccodingman Jul 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 18 additions & 37 deletions .github/workflows/tls-lifecycle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,13 @@ name: TLS lifecycle tests
on:
pull_request:
paths:
- "TruthGate-Web/TruthGate-Web/Configuration/**"
- "TruthGate-Web/TruthGate-Web/Services/ConfigWatchAndIssueService.cs"
- "TruthGate-Web/TruthGate-Web.Tests/**"
- "TruthGate-Web/**"
- ".github/workflows/tls-lifecycle.yml"
push:
branches:
- master
paths:
- "TruthGate-Web/TruthGate-Web/Configuration/**"
- "TruthGate-Web/TruthGate-Web/Services/ConfigWatchAndIssueService.cs"
- "TruthGate-Web/TruthGate-Web.Tests/**"
- "TruthGate-Web/**"
- ".github/workflows/tls-lifecycle.yml"

jobs:
Expand All @@ -25,37 +21,22 @@ jobs:

- uses: actions/setup-dotnet@v4
with:
dotnet-version: "9.0.x"
dotnet-version: "10.0.x"

- name: Restore
- name: Restore solution
run: dotnet restore TruthGate-IPFS.sln

# This test project is intentionally outside TruthGate-IPFS.sln, so restore it explicitly.
- name: Restore TLS tests
run: dotnet restore TruthGate-Web/TruthGate-Web.Tests/TruthGate-Web.Tests.csproj

- name: Test
id: test
shell: bash
run: |
set +e
dotnet test \
TruthGate-Web/TruthGate-Web.Tests/TruthGate-Web.Tests.csproj \
--no-restore \
--configuration Release \
--logger "console;verbosity=normal" \
> tls-test-output.log 2>&1
status=$?
echo "status=$status" >> "$GITHUB_OUTPUT"
exit 0

- name: Upload test diagnostics
if: always()
uses: actions/upload-artifact@v4
with:
name: tls-test-output
path: tls-test-output.log
if-no-files-found: error

- name: Report failure
if: steps.test.outputs.status != '0'
shell: bash
run: |
echo "TLS lifecycle tests failed. Download the tls-test-output artifact for the complete compiler/test diagnostics."
exit 1
- name: Build solution
run: dotnet build TruthGate-IPFS.sln --no-restore --configuration Release

- name: Test TLS lifecycle
run: >-
dotnet test
TruthGate-Web/TruthGate-Web.Tests/TruthGate-Web.Tests.csproj
--no-restore
--configuration Release
--logger "console;verbosity=normal"
8 changes: 4 additions & 4 deletions TruthGate-Web/TruthGate-Web.Tests/TruthGate-Web.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@page "/keys"
@page "/keys"
@using TruthGate_Web.Components.Pages.Settings.Shared
@using TruthGate_Web.Models
@using TruthGate_Web.Utils
Expand Down Expand Up @@ -71,10 +71,10 @@
{ x => x.ExistingNames, _keys.Select(k => k.Name).ToList() }
};

var dialog = await Dialogs.ShowAsync("Add API Key", p, new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true });
var dialog = await Dialogs.ShowAsync<AddApiKeyDialog>("Add API Key", p, new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true });
var result = await dialog.Result;

if (result.Canceled || result.Data is not AddApiKeyDialog.AddApiKeyResult r) return;
if (result is null || result.Canceled || result.Data is not AddApiKeyDialog.AddApiKeyResult r) return;

// Final uniqueness check (server-side)
if (_keys.Any(k => string.Equals(k.Name, r.Name, StringComparison.OrdinalIgnoreCase)))
Expand Down Expand Up @@ -106,7 +106,7 @@
var dialog = await Dialogs.ShowAsync<ConfirmDeleteDialog>("Confirm Delete", p);
var result = await dialog.Result;

if (result.Canceled || result.Data is not bool yes || !yes) return;
if (result is null || result.Canceled || result.Data is not bool yes || !yes) return;

await ConfigSvc.UpdateAsync(cfg =>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@page "/domains"
@page "/domains"
@using System.Globalization
@using System.Text.RegularExpressions
@using MudBlazor
Expand Down Expand Up @@ -47,7 +47,7 @@
@context.Domain
@if (!string.IsNullOrWhiteSpace(context.RedirectUrl))
{
<MudText Typo="Typo.caption" Class="truncate-text" Title="@context.RedirectUrl">
<MudText Typo="Typo.caption" Class="truncate-text" title="@context.RedirectUrl">
@{
var u = context.RedirectUrl ?? string.Empty;
}
Expand All @@ -60,7 +60,7 @@

<MudStack Row="true" Spacing="1" Class="mt-1">
<MudTooltip Text="@($"{GetLabel(context)}.{_wildcardHost}")">
<MudChip T="string" Color="Color.Primary" Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Link">
<MudChip T="string" Color="Color.Primary" Variant="Variant.Outlined" Icon="@Icons.Material.Filled.Link">
@($"{GetIpnsHost(context, useShort: true)}")
</MudChip>
</MudTooltip>
Expand Down Expand Up @@ -88,7 +88,7 @@
@context.IpnsKeyName
</MudChip> *@
<MudTooltip Text="@context.IpnsPeerId">
<MudChip T="string" Color="Color.Primary" Variant="Variant.Outlined" StartIcon="@Icons.Material.Filled.Fingerprint">
<MudChip T="string" Color="Color.Primary" Variant="Variant.Outlined" Icon="@Icons.Material.Filled.Fingerprint">
IPNS: @Short(context.IpnsPeerId)
</MudChip>
</MudTooltip>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@page "/ip-bans"
@page "/ip-bans"
@using Microsoft.EntityFrameworkCore
@using System.Net
@using TruthGate_Web.Components.Pages.Settings.Shared
Expand Down Expand Up @@ -52,7 +52,7 @@
Hover="true"
Dense="true"
Bordered="true"
Sortable="false"
SortMode="SortMode.None"
Filterable="false"
RowsPerPage="20">
<Columns>
Expand Down Expand Up @@ -118,7 +118,7 @@
Hover="true"
Dense="true"
Bordered="true"
Sortable="false"
SortMode="SortMode.None"
Filterable="false"
RowsPerPage="20">
<Columns>
Expand Down Expand Up @@ -164,7 +164,7 @@
Hover="true"
Dense="true"
Bordered="true"
Sortable="false"
SortMode="SortMode.None"
Filterable="false"
RowsPerPage="20">
<Columns>
Expand Down Expand Up @@ -212,7 +212,7 @@
}
private BanFilters _banFilters = new();

private async Task<GridData<BanDto>> LoadBansGridAsync(GridState<BanDto> state)
private async Task<GridData<BanDto>> LoadBansGridAsync(GridState<BanDto> state, CancellationToken cancellationToken)
{
var page = state.Page + 1; // Mud uses 0-based; your API is 1-based
var pageSize = state.PageSize;
Expand All @@ -237,7 +237,7 @@

private async Task ConfirmUnbanById(Guid id)
{
var res = await Dialogs.ShowMessageBox("Confirm", "Unban this entry?", yesText: "Unban", cancelText: "Cancel");
var res = await Dialogs.ShowMessageBoxAsync("Confirm", "Unban this entry?", yesText: "Unban", cancelText: "Cancel");
if (res == true)
{
var ok = await RateSvc.UnbanByIdAsync(id);
Expand All @@ -248,7 +248,7 @@

private async Task ConfirmUnbanIp(string ip)
{
var res = await Dialogs.ShowMessageBox("Confirm", $"Unban IP {ip} ?", yesText: "Unban", cancelText: "Cancel");
var res = await Dialogs.ShowMessageBoxAsync("Confirm", $"Unban IP {ip} ?", yesText: "Unban", cancelText: "Cancel");
if (res == true)
{
var ok = await RateSvc.UnbanIpAsync(ip);
Expand All @@ -259,7 +259,7 @@

private async Task ConfirmUnbanPrefix(string pfx)
{
var res = await Dialogs.ShowMessageBox("Confirm", $"Unban prefix {pfx} ?", yesText: "Unban", cancelText: "Cancel");
var res = await Dialogs.ShowMessageBoxAsync("Confirm", $"Unban prefix {pfx} ?", yesText: "Unban", cancelText: "Cancel");
if (res == true)
{
var ok = await RateSvc.UnbanIpv6PrefixAsync(pfx);
Expand All @@ -272,13 +272,15 @@
private async Task OpenSearchDialog()
{
var parameters = new DialogParameters<SearchDialogCtx> { { x => x.InitialIp, _banFilters.IpFilter } };
await Dialogs.ShowAsync<SearchIpDialog>("Search IP", parameters, new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small }).Result;
var dialog = await Dialogs.ShowAsync<SearchIpDialog>("Search IP", parameters, new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small });
await dialog.Result;
}

// -------------------- ADD BAN DIALOG --------------------
private async Task OpenAddBanDialog()
{
await Dialogs.ShowAsync<AddBanDialog>("Add Ban", new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small }).Result;
var dialog = await Dialogs.ShowAsync<AddBanDialog>("Add Ban", new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small });
await dialog.Result;
await ReloadBans();
}

Expand All @@ -289,9 +291,9 @@
private string? _newWhitelistReason;
private int? _newWhitelistExpireHours;

private async Task<GridData<Whitelist>> LoadWhitelistIpGridAsync(GridState<Whitelist> state)
private async Task<GridData<Whitelist>> LoadWhitelistIpGridAsync(GridState<Whitelist> state, CancellationToken cancellationToken)
{
await using var db = await DbFactory.CreateDbContextAsync();
await using var db = await DbFactory.CreateDbContextAsync(cancellationToken);
var q = db.Whitelists.AsNoTracking().Where(x => x.Ip != null);

if (!string.IsNullOrWhiteSpace(_wlIpSearch))
Expand All @@ -300,12 +302,12 @@
q = q.Where(x => x.Ip!.Contains(s));
}

var total = await q.CountAsync();
var total = await q.CountAsync(cancellationToken);
var items = await q
.OrderByDescending(x => x.CreatedUtc)
.Skip(state.Page * state.PageSize)
.Take(state.PageSize)
.ToListAsync();
.ToListAsync(cancellationToken);

return new GridData<Whitelist> { Items = items, TotalItems = total };
}
Expand All @@ -331,7 +333,7 @@

private async Task RemoveWhitelistIp(string ip)
{
var res = await Dialogs.ShowMessageBox("Confirm", $"Remove {ip} from whitelist?", yesText: "Remove", cancelText: "Cancel");
var res = await Dialogs.ShowMessageBoxAsync("Confirm", $"Remove {ip} from whitelist?", yesText: "Remove", cancelText: "Cancel");
if (res == true)
{
var ok = await RateSvc.RemoveWhitelistIpAsync(ip);
Expand All @@ -347,9 +349,9 @@
private string? _newWhitelistReasonPfx;
private int? _newWhitelistExpireHoursPfx;

private async Task<GridData<Whitelist>> LoadWhitelistPrefixGridAsync(GridState<Whitelist> state)
private async Task<GridData<Whitelist>> LoadWhitelistPrefixGridAsync(GridState<Whitelist> state, CancellationToken cancellationToken)
{
await using var db = await DbFactory.CreateDbContextAsync();
await using var db = await DbFactory.CreateDbContextAsync(cancellationToken);
var q = db.Whitelists.AsNoTracking().Where(x => x.Ipv6Prefix != null);

if (!string.IsNullOrWhiteSpace(_wlPfxSearch))
Expand All @@ -358,12 +360,12 @@
q = q.Where(x => x.Ipv6Prefix!.Contains(s));
}

var total = await q.CountAsync();
var total = await q.CountAsync(cancellationToken);
var items = await q
.OrderByDescending(x => x.CreatedUtc)
.Skip(state.Page * state.PageSize)
.Take(state.PageSize)
.ToListAsync();
.ToListAsync(cancellationToken);

return new GridData<Whitelist> { Items = items, TotalItems = total };
}
Expand All @@ -389,7 +391,7 @@

private async Task RemoveWhitelistPrefix(string pfx)
{
var res = await Dialogs.ShowMessageBox("Confirm", $"Remove {pfx} from whitelist?", yesText: "Remove", cancelText: "Cancel");
var res = await Dialogs.ShowMessageBoxAsync("Confirm", $"Remove {pfx} from whitelist?", yesText: "Remove", cancelText: "Cancel");
if (res == true)
{
var ok = await RateSvc.RemoveWhitelistIpv6PrefixAsync(pfx);
Expand Down
Loading
Loading