Handle unauthorized
All checks were successful
Build Docker Images / test (map[name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m40s
Build Docker Images / test (map[name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m33s
Build Docker Images / build-and-push (map[image_suffix:morska name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m53s
Build Docker Images / build-and-push (map[image_suffix:pedrollopl name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m51s
All checks were successful
Build Docker Images / test (map[name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m40s
Build Docker Images / test (map[name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m33s
Build Docker Images / build-and-push (map[image_suffix:morska name:Morska plugin_project:DiunaBI.Plugins.Morska]) (push) Successful in 1m53s
Build Docker Images / build-and-push (map[image_suffix:pedrollopl name:PedrolloPL plugin_project:DiunaBI.Plugins.PedrolloPL]) (push) Successful in 1m51s
This commit is contained in:
@@ -5,6 +5,15 @@
|
|||||||
|
|
||||||
## RECENT CHANGES (This Session)
|
## RECENT CHANGES (This Session)
|
||||||
|
|
||||||
|
**Seq Removal - Logging Cleanup (Dec 5, 2025):**
|
||||||
|
- ✅ Removed Seq logging sink to eliminate commercial licensing concerns
|
||||||
|
- ✅ Removed `Serilog.Sinks.Seq` NuGet package from DiunaBI.API.csproj
|
||||||
|
- ✅ Removed Seq sink configuration from appsettings.Development.json
|
||||||
|
- ✅ Kept Serilog (free, open-source) with Console + File sinks for production-ready logging
|
||||||
|
- ✅ Build verified - no errors after Seq removal
|
||||||
|
- Files modified: [DiunaBI.API.csproj](DiunaBI.API/DiunaBI.API.csproj), [appsettings.Development.json](DiunaBI.API/appsettings.Development.json)
|
||||||
|
- Manual step required: Remove `seq` service from docker-compose.yml and add Docker log rotation config
|
||||||
|
|
||||||
**UI Reorganization (Dec 5, 2025):**
|
**UI Reorganization (Dec 5, 2025):**
|
||||||
- ✅ Moved pages to feature-based folders: `Pages/Layers/`, `Pages/Jobs/`, `Pages/DataInbox/`
|
- ✅ Moved pages to feature-based folders: `Pages/Layers/`, `Pages/Jobs/`, `Pages/DataInbox/`
|
||||||
- ✅ Organized components: `Components/Layout/` (MainLayout, EmptyLayout, Routes), `Components/Auth/` (AuthGuard, LoginCard)
|
- ✅ Organized components: `Components/Layout/` (MainLayout, EmptyLayout, Routes), `Components/Auth/` (AuthGuard, LoginCard)
|
||||||
@@ -27,7 +36,7 @@
|
|||||||
- UI: MudBlazor 8.0
|
- UI: MudBlazor 8.0
|
||||||
- Real-time: SignalR (EntityChangeHub)
|
- Real-time: SignalR (EntityChangeHub)
|
||||||
- Google: Sheets API, Drive API, OAuth
|
- Google: Sheets API, Drive API, OAuth
|
||||||
- Logging: Serilog (Console, File, Seq)
|
- Logging: Serilog (Console, File)
|
||||||
- Auth: JWT Bearer + Google OAuth
|
- Auth: JWT Bearer + Google OAuth
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
|
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.1" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Seq" Version="9.0.0" />
|
|
||||||
<PackageReference Include="System.Configuration.ConfigurationManager" Version="10.0.0" />
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="10.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -246,10 +246,6 @@ app.Use(async (context, next) =>
|
|||||||
logger.LogError(ex, "❌ Failed to extract UserId from JWT token");
|
logger.LogError(ex, "❌ Failed to extract UserId from JWT token");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.LogWarning("❌ No valid Bearer token found");
|
|
||||||
}
|
|
||||||
|
|
||||||
await next(context);
|
await next(context);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -37,15 +37,36 @@
|
|||||||
@_errorMessage
|
@_errorMessage
|
||||||
</MudAlert>
|
</MudAlert>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@if (_sessionExpired)
|
||||||
|
{
|
||||||
|
<MudAlert Severity="Severity.Warning" Class="mt-4" Dense="true">
|
||||||
|
Your session has expired. Please sign in again.
|
||||||
|
</MudAlert>
|
||||||
|
}
|
||||||
</MudCardContent>
|
</MudCardContent>
|
||||||
</MudCard>
|
</MudCard>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
private bool _isLoading = false;
|
private bool _isLoading = false;
|
||||||
private string _errorMessage = string.Empty;
|
private string _errorMessage = string.Empty;
|
||||||
|
private bool _sessionExpired = false;
|
||||||
private static LoginCard? _instance;
|
private static LoginCard? _instance;
|
||||||
private bool _isInitialized = false;
|
private bool _isInitialized = false;
|
||||||
|
|
||||||
|
protected override void OnInitialized()
|
||||||
|
{
|
||||||
|
// Check if sessionExpired query parameter is present
|
||||||
|
var uri = new Uri(NavigationManager.Uri);
|
||||||
|
var query = System.Web.HttpUtility.ParseQueryString(uri.Query);
|
||||||
|
_sessionExpired = query["sessionExpired"] == "true";
|
||||||
|
|
||||||
|
if (_sessionExpired)
|
||||||
|
{
|
||||||
|
Console.WriteLine("⚠️ Session expired - user redirected to login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
{
|
{
|
||||||
if (firstRender)
|
if (firstRender)
|
||||||
|
|||||||
@@ -17,14 +17,16 @@ public static class ServiceCollectionExtensions
|
|||||||
Console.WriteLine($"🔧 Configuring HttpClient with BaseAddress: {baseUri}");
|
Console.WriteLine($"🔧 Configuring HttpClient with BaseAddress: {baseUri}");
|
||||||
|
|
||||||
services.AddTransient<HttpLoggingHandler>();
|
services.AddTransient<HttpLoggingHandler>();
|
||||||
|
services.AddTransient<UnauthorizedResponseHandler>();
|
||||||
|
|
||||||
// Configure named HttpClient with logging handler
|
// Configure named HttpClient with logging and 401 handling
|
||||||
// Note: Authentication is handled by AuthService setting DefaultRequestHeaders.Authorization
|
// Note: Authentication is handled by AuthService setting DefaultRequestHeaders.Authorization
|
||||||
services.AddHttpClient("DiunaBI", client =>
|
services.AddHttpClient("DiunaBI", client =>
|
||||||
{
|
{
|
||||||
client.BaseAddress = new Uri(baseUri);
|
client.BaseAddress = new Uri(baseUri);
|
||||||
Console.WriteLine($"✅ HttpClient BaseAddress set to: {client.BaseAddress}");
|
Console.WriteLine($"✅ HttpClient BaseAddress set to: {client.BaseAddress}");
|
||||||
})
|
})
|
||||||
|
.AddHttpMessageHandler<UnauthorizedResponseHandler>()
|
||||||
.AddHttpMessageHandler<HttpLoggingHandler>();
|
.AddHttpMessageHandler<HttpLoggingHandler>();
|
||||||
|
|
||||||
// Register a scoped HttpClient factory that services will use
|
// Register a scoped HttpClient factory that services will use
|
||||||
|
|||||||
41
DiunaBI.UI.Shared/Handlers/UnauthorizedResponseHandler.cs
Normal file
41
DiunaBI.UI.Shared/Handlers/UnauthorizedResponseHandler.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using DiunaBI.UI.Shared.Services;
|
||||||
|
|
||||||
|
namespace DiunaBI.UI.Shared.Handlers;
|
||||||
|
|
||||||
|
public class UnauthorizedResponseHandler : DelegatingHandler
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
|
||||||
|
public UnauthorizedResponseHandler(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<HttpResponseMessage> SendAsync(
|
||||||
|
HttpRequestMessage request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var response = await base.SendAsync(request, cancellationToken);
|
||||||
|
|
||||||
|
// Check if response is 401 Unauthorized
|
||||||
|
if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
|
||||||
|
{
|
||||||
|
Console.WriteLine("⚠️ 401 Unauthorized response detected - clearing credentials and redirecting to login");
|
||||||
|
|
||||||
|
// Create a scope to get scoped services
|
||||||
|
using var scope = _serviceProvider.CreateScope();
|
||||||
|
var authService = scope.ServiceProvider.GetRequiredService<AuthService>();
|
||||||
|
var navigationManager = scope.ServiceProvider.GetRequiredService<NavigationManager>();
|
||||||
|
|
||||||
|
// Clear authentication
|
||||||
|
await authService.ClearAuthenticationAsync();
|
||||||
|
|
||||||
|
// Navigate to login page with session expired message
|
||||||
|
navigationManager.NavigateTo("/login?sessionExpired=true", forceLoad: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user