fix switch club and RefreshSign

This commit is contained in:
beo3000 2026-01-02 22:48:00 +01:00
parent 7a5580e57d
commit 3b65f9f1cd
6 changed files with 106 additions and 16 deletions

View File

@ -52,6 +52,15 @@ namespace Koogle.Application.DTOs
public string ConfirmPassword { get; set; } = "";
}
/// <summary>
/// From DTO for switching session from one club to another
/// </summary>
public class SwitchClubFormDto
{
public Guid UserProfileId { get; set; }
public Guid ClubId { get; set; }
}
/// <summary>
/// DTO for user registration.
/// </summary>

View File

@ -709,6 +709,22 @@ public class UserService : IUserService
profile.CurrentClubId = clubId;
await _appDb.SaveChangesAsync(ct);
// Refresh signin to update claims with new club
var identityUser = await _userManager.FindByIdAsync(profile.IdentityUserId.ToString());
if (identityUser != null)
{
try
{
await _signInManager.RefreshSignInAsync(identityUser);
}
catch (Exception e)
{
throw;
}
}
return true;
}

View File

@ -1,10 +1,16 @@
@using System.Net
@using Fluxor
@using Koogle.Application.DTOs
@using Koogle.Web.Store.AuthState
@using Koogle.Application.Interfaces
@inject IState<AuthState> AuthState
@inject NavigationManager NavigationManager
@inject IUserService UserService
@inject HttpClient HttpClient;
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Antiforgery
@inject IHttpContextAccessor HttpContextAccessor
@inject IDispatcher Dispatcher
@inherits Fluxor.Blazor.Web.Components.FluxorComponent
@ -22,10 +28,10 @@
@foreach (var club in AuthState.Value.AvailableClubs)
{
<MudMenuItem OnClick="@(() => SwitchClubAsync(club.ClubId))"
Disabled="@(club.ClubId == AuthState.Value.CurrentClub?.ClubId)">
Disabled="@(club.ClubId == AuthState.Value.CurrentClub?.ClubId)">
@if (club.ClubId == AuthState.Value.CurrentClub?.ClubId)
{
<MudIcon Icon="@Icons.Material.Filled.Check" Size="Size.Small" Class="mr-2" />
<MudIcon Icon="@Icons.Material.Filled.Check" Size="Size.Small" Class="mr-2"/>
}
@club.ClubName
</MudMenuItem>
@ -47,23 +53,64 @@ else if (AuthState.Value.IsAuthenticated && AuthState.Value.HasNoClub)
}
@code {
private string _antiToken;
protected override void OnAfterRender(bool firstRender)
{
if (firstRender)
{
var http = HttpContextAccessor.HttpContext!;
var tokens = Antiforgery.GetAndStoreTokens(http);
_antiToken = tokens.RequestToken!;
}
}
private async Task SwitchClubAsync(Guid clubId)
{
if (AuthState.Value.CurrentUser == null)
return;
var model = new SwitchClubFormDto()
{
ClubId = clubId,
UserProfileId = AuthState.Value.CurrentUser.ProfileId
};
try
{
var success = await UserService.SwitchClubAsync(AuthState.Value.CurrentUser.ProfileId, clubId);
if (success)
{
// Force page reload to refresh claims
NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
}
HttpClient.DefaultRequestHeaders.Remove("RequestVerificationToken");
HttpClient.DefaultRequestHeaders.Add(
"RequestVerificationToken",
_antiToken
);
var basepath = NavigationManager.BaseUri;
var url = $"{basepath}auth/switch-club";
await HttpClient.PostAsJsonAsync(url, model);
// Dispatcher.Dispatch(new AuthState.InitializeAuthSuccessAction(model.UserProfileId, model.ClubId, roles));
NavigationManager.NavigateTo("/dashboard", forceLoad: true);
}
catch (Exception ex)
catch (Exception e)
{
Console.WriteLine($"Club switch failed: {ex.Message}");
Console.WriteLine(e);
throw;
}
// try
// {
// var success = await UserService.SwitchClubAsync(AuthState.Value.CurrentUser.ProfileId, clubId);
// if (success)
// {
// // Force page reload to refresh claims
// NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
// }
// }
// catch (Exception ex)
// {
// Console.WriteLine($"Club switch failed: {ex.Message}");
// }
}
}

View File

@ -7,6 +7,7 @@ using Koogle.Web.Store.AuthState;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using static QRCoder.PayloadGenerator;
namespace Koogle.Web.Controllers
{
@ -18,7 +19,8 @@ namespace Koogle.Web.Controllers
/// Aus dem Grund werden Login/Logout Aktionen hier im MVC Controller mit einem "normalen" Post-Request abgewickelt.
/// </remarks>
[Microsoft.AspNetCore.Mvc.Route("auth")]
public class AuthController(IDispatcher dispatcher, IUserService userService, IEmailService emailService) : Controller
public class AuthController(IDispatcher dispatcher, IUserService userService, IEmailService emailService)
: Controller
{
private readonly IDispatcher _dispatcher = dispatcher;
private readonly IUserService _userService = userService;
@ -37,6 +39,7 @@ namespace Koogle.Web.Controllers
// (club-setup if no clubs, dashboard otherwise)
return LocalRedirect(result.RedirectUrl ?? "/dashboard");
}
return LocalRedirect("/account/login?error=true");
}
@ -67,8 +70,10 @@ namespace Koogle.Web.Controllers
// If invite token was provided, redirect to join page
if (!string.IsNullOrWhiteSpace(input.InviteToken))
{
return LocalRedirect($"/account/login?registered=true&invite={Uri.EscapeDataString(input.InviteToken)}");
return LocalRedirect(
$"/account/login?registered=true&invite={Uri.EscapeDataString(input.InviteToken)}");
}
return LocalRedirect("/account/login?registered=true");
}
@ -93,7 +98,8 @@ namespace Koogle.Web.Controllers
if (token != null)
{
var baseUrl = $"{Request.Scheme}://{Request.Host}";
var resetUrl = $"{baseUrl}/account/reset-password?email={Uri.EscapeDataString(email)}&token={Uri.EscapeDataString(token)}";
var resetUrl =
$"{baseUrl}/account/reset-password?email={Uri.EscapeDataString(email)}&token={Uri.EscapeDataString(token)}";
await _emailService.SendPasswordResetEmailAsync(email, resetUrl);
}
@ -110,7 +116,8 @@ namespace Koogle.Web.Controllers
// Validate password confirmation
if (input.NewPassword != input.ConfirmPassword)
{
return LocalRedirect($"/account/reset-password?email={Uri.EscapeDataString(input.Email)}&token={Uri.EscapeDataString(input.Token)}&error=PasswordMismatch");
return LocalRedirect(
$"/account/reset-password?email={Uri.EscapeDataString(input.Email)}&token={Uri.EscapeDataString(input.Token)}&error=PasswordMismatch");
}
var dto = new ResetPasswordDto
@ -127,9 +134,20 @@ namespace Koogle.Web.Controllers
}
var errors = string.Join(",", result.Errors.Select(e => e.Code));
return LocalRedirect($"/account/reset-password?email={Uri.EscapeDataString(input.Email)}&token={Uri.EscapeDataString(input.Token)}&error={errors}");
return LocalRedirect(
$"/account/reset-password?email={Uri.EscapeDataString(input.Email)}&token={Uri.EscapeDataString(input.Token)}&error={errors}");
}
/// <summary>
/// Handles switch club.
/// </summary>
[HttpPost("switch-club")]
//[ValidateAntiForgeryToken]
public async Task<IActionResult> SwitchClub([FromBody] SwitchClubFormDto input)
{
await _userService.SwitchClubAsync(input.UserProfileId, input.ClubId);
return LocalRedirect($"/dashboard");
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1016 KiB