Refactor sender page and auth service logic
- Added project reference to `EnvelopeGenerator.Application` in the client project. - Updated imports and injected services in `EnvelopeSenderPage.razor`. - Improved null handling for `EnvelopeReceivers` and updated email display logic. - Replaced `CheckSenderAsync` with `CheckSenderAccessAsync` for authorization. - Refactored `GetStatusInfo` to use `EnvelopeStatus` enum directly. - Added `CheckSenderAccessAsync` and `LogoutSenderAsync` methods in `AuthService`. - Simplified `Logout` logic in `AuthController` to remove redundant checks.
This commit is contained in:
@@ -29,6 +29,10 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.11" PrivateAssets="all" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="PredefinedReports\Report.cs">
|
||||
<SubType>XtraReport</SubType>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
@attribute [Microsoft.AspNetCore.Authorization.Authorize(Policy = "Sender")]
|
||||
|
||||
@using System.Text.Json
|
||||
@using EnvelopeGenerator.Domain.Constants
|
||||
@using EnvelopeGenerator.Server.Client.Models
|
||||
@using DevExpress.Blazor
|
||||
@using EnvelopeGenerator.Server.Client.Services
|
||||
@@ -10,6 +11,12 @@
|
||||
@inject NavigationManager Navigation
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject AppVersionService AppVersion
|
||||
@using EnvelopeGenerator.Application.Common.Dto
|
||||
@inject EnvelopeGenerator.Server.Client.Services.EnvelopeService EnvelopeService
|
||||
@inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService
|
||||
@inject NavigationManager Navigation
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject AppVersionService AppVersion
|
||||
|
||||
<link href="_content/DevExpress.Blazor.Themes/blazing-berry.bs5.min.css" rel="stylesheet" />
|
||||
<link href="@AppVersion.GetVersionedUrl("css/envelope-viewer.css")" rel="stylesheet" />
|
||||
@@ -161,7 +168,7 @@
|
||||
@{
|
||||
var envelope = cellContext.DataItem as EnvelopeDto;
|
||||
if (envelope != null) {
|
||||
var receivers = envelope.EnvelopeReceivers ?? new List<EnvelopeReceiverSimpleDto>();
|
||||
var receivers = envelope.EnvelopeReceivers?.ToList() ?? [];
|
||||
var signed = receivers.Count(r => r.Signed);
|
||||
var total = receivers.Count;
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||||
@@ -204,7 +211,7 @@
|
||||
</span>
|
||||
<div style="flex: 1; font-size: 0.875rem;">
|
||||
<strong style="color: #1f2937;">@receiver.Name</strong>
|
||||
<span style="color: #6b7280; margin-left: 0.5rem;">@receiver.Email</span>
|
||||
<span style="color: #6b7280; margin-left: 0.5rem;">@receiver.Receiver?.EmailAddress</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -257,7 +264,7 @@
|
||||
@{
|
||||
var envelope = cellContext.DataItem as EnvelopeDto;
|
||||
if (envelope != null) {
|
||||
var receivers = envelope.EnvelopeReceivers ?? new List<EnvelopeReceiverSimpleDto>();
|
||||
var receivers = envelope.EnvelopeReceivers?.ToList() ?? [];
|
||||
var signed = receivers.Count(r => r.Signed);
|
||||
var total = receivers.Count;
|
||||
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
||||
@@ -300,7 +307,7 @@
|
||||
</span>
|
||||
<div style="flex: 1; font-size: 0.875rem;">
|
||||
<strong style="color: #1f2937;">@receiver.Name</strong>
|
||||
<span style="color: #6b7280; margin-left: 0.5rem;">@receiver.Email</span>
|
||||
<span style="color: #6b7280; margin-left: 0.5rem;">@receiver.Receiver?.EmailAddress</span>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -333,7 +340,7 @@
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var hasAccess = await AuthService.CheckSenderAsync();
|
||||
var hasAccess = await AuthService.CheckSenderAccessAsync();
|
||||
if (!hasAccess)
|
||||
{
|
||||
Navigation.NavigateTo($"/sender/login");
|
||||
@@ -411,9 +418,8 @@
|
||||
return status >= EnvelopeStatus.EnvelopeQueued;
|
||||
}
|
||||
|
||||
(string Label, string CssClass, string DotColor) GetStatusInfo(int statusCode)
|
||||
(string Label, string CssClass, string DotColor) GetStatusInfo(EnvelopeStatus status)
|
||||
{
|
||||
var status = (EnvelopeStatus)statusCode;
|
||||
return status switch
|
||||
{
|
||||
EnvelopeStatus.EnvelopePartlySigned => ("Teilweise unterschrieben", "partly-signed", "green"),
|
||||
|
||||
@@ -22,6 +22,17 @@ public class AuthService(IHttpClientFactory httpClientFactory)
|
||||
return response.StatusCode == HttpStatusCode.OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the current user holds a valid receiver token for the given envelope key.
|
||||
/// Calls GET /api/auth/check/envelope/{envelopeKey}.
|
||||
/// </summary>
|
||||
public async Task<bool> CheckSenderAccessAsync(CancellationToken cancel = default)
|
||||
{
|
||||
using var http = CreateDefaultClient();
|
||||
var response = await http.GetAsync($"/api/auth/check", cancel);
|
||||
return response.StatusCode == HttpStatusCode.OK;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Submits the access code for the given envelope key.
|
||||
/// Calls POST /api/Auth/envelope-receiver/{key} with multipart/form-data.
|
||||
@@ -61,6 +72,19 @@ public class AuthService(IHttpClientFactory httpClientFactory)
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes the per-envelope receiver cookie for the given envelope key.
|
||||
/// Calls POST /api/auth/logout/envelope/{envelopeKey}.
|
||||
/// </summary>
|
||||
public async Task<bool> LogoutSenderAsync(CancellationToken cancel = default)
|
||||
{
|
||||
using var http = CreateDefaultClient();
|
||||
var response = await http.PostAsync(
|
||||
$"/api/auth/logout",
|
||||
null, cancel);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Authenticates a sender user with username and password.
|
||||
/// Calls POST /api/auth?cookie=true with JSON body.
|
||||
|
||||
@@ -40,17 +40,11 @@ public partial class AuthController(IOptions<AuthTokenKeys> authTokenKeyOptions,
|
||||
/// <response code="401">Wenn es kein zugelassenes Cookie gibt, wird „nicht zugelassen“ zurückgegeben.</response>
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(typeof(void), StatusCodes.Status401Unauthorized)]
|
||||
[Authorize(Policy = AuthPolicy.SenderOrReceiver)]
|
||||
[Authorize(Policy = AuthPolicy.Sender)]
|
||||
[HttpPost("logout")]
|
||||
public async Task<IActionResult> Logout()
|
||||
public IActionResult Logout()
|
||||
{
|
||||
if (await this.IsUserInPolicyAsync(AuthPolicy.Sender))
|
||||
Response.Cookies.Delete(authTokenKeys.Cookie);
|
||||
else if (await this.IsUserInPolicyAsync(AuthPolicy.ReceiverOrReceiverTFA))
|
||||
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
|
||||
else
|
||||
return Unauthorized();
|
||||
|
||||
Response.Cookies.Delete(authTokenKeys.Cookie);
|
||||
return Ok();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user