Files
EnvelopeGenerator/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Services/AuthService.cs
TekH 940d129c11 Add read-only sharing and viewing functionality
Introduced the ability to share envelopes in read-only mode and view them via a dedicated page. Added `ShareEnvelopeReadOnlyAsync` in `AuthService.cs` to handle sharing logic. Updated `ReceiverPage.razor` with a "Share" button, popup UI, and validation for sharing inputs. Created `ReceiverReadOnlyPage.razor` for read-only document viewing with error handling and lifecycle management.

Added `EnvelopeKeyRedirectController.cs` to support legacy link redirection. Enhanced `ReadOnlyController.cs` to support envelope sharing with improved logging and `IMediator` integration. Improved state management, validation, and error handling across components. Performed general code cleanup and UI enhancements for better user experience.
2026-09-28 14:42:52 +02:00

136 lines
5.4 KiB
C#

using System.Net;
using System.Net.Http.Json;
namespace EnvelopeGenerator.Server.Client.Services;
public enum EnvelopeLoginResult { Success, InvalidCode, NotFound, Error }
public enum SenderLoginResult { Success, InvalidCredentials, Error }
public class AuthService(IHttpClientFactory httpClientFactory)
{
private HttpClient CreateDefaultClient() => httpClientFactory.CreateClient("EnvelopeGenerator.Server");
/// <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> CheckEnvelopeAccessAsync(string envelopeKey, CancellationToken cancel = default)
{
using var http = CreateDefaultClient();
var response = await http.GetAsync($"/api/auth/check/envelope/{Uri.EscapeDataString(envelopeKey)}", cancel);
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>
/// Triggers access code e-mail request flow for the receiver login page.
/// Calls POST /api/Auth/envelope-receiver/{key}/request-access-code.
/// </summary>
public async Task<bool> RequestEnvelopeReceiverAccessCodeAsync(string envelopeKey, CancellationToken cancel = default)
{
using var http = CreateDefaultClient();
var response = await http.PostAsync(
$"/api/Auth/envelope-receiver/{Uri.EscapeDataString(envelopeKey)}/request-access-code",
null,
cancel);
return response.IsSuccessStatusCode;
}
/// <summary>
/// Submits the access code for the given envelope key.
/// Calls POST /api/Auth/envelope-receiver/{key} with multipart/form-data.
/// On success the API sets an authentication cookie automatically.
/// </summary>
public async Task<EnvelopeLoginResult> LoginEnvelopeReceiverAsync(string envelopeKey, string accessCode, CancellationToken cancel = default)
{
using var http = CreateDefaultClient();
var form = new MultipartFormDataContent
{
{ new StringContent(accessCode), "AccessCode" }
};
var response = await http.PostAsync(
$"/api/Auth/envelope-receiver/{Uri.EscapeDataString(envelopeKey)}",
form, cancel);
return response.StatusCode switch
{
HttpStatusCode.OK => EnvelopeLoginResult.Success,
HttpStatusCode.Unauthorized => EnvelopeLoginResult.InvalidCode,
HttpStatusCode.NotFound => EnvelopeLoginResult.NotFound,
_ => EnvelopeLoginResult.Error
};
}
/// <summary>
/// Removes the per-envelope receiver cookie for the given envelope key.
/// Calls POST /api/auth/logout/envelope/{envelopeKey}.
/// </summary>
public async Task<bool> LogoutEnvelopeReceiverAsync(string envelopeKey, CancellationToken cancel = default)
{
using var http = CreateDefaultClient();
var response = await http.PostAsync(
$"/api/auth/logout/envelope/{Uri.EscapeDataString(envelopeKey)}",
null, cancel);
return response.IsSuccessStatusCode;
}
/// <summary>
/// Shares the current envelope in read-only mode for the specified receiver and expiration date.
/// Calls POST /api/readonly/{envelopeKey}.
/// </summary>
public async Task<bool> ShareEnvelopeReadOnlyAsync(string envelopeKey, string receiverMail, DateTime dateValid, CancellationToken cancel = default)
{
using var http = CreateDefaultClient();
var payload = new { receiverMail, dateValid };
var response = await http.PostAsJsonAsync($"/api/readonly/{Uri.EscapeDataString(envelopeKey)}", payload, cancel);
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.
/// On success the API sets an authentication cookie automatically.
/// </summary>
public async Task<SenderLoginResult> LoginSenderAsync(string username, string password, CancellationToken cancel = default)
{
using var http = CreateDefaultClient();
var requestBody = new { username, password };
var response = await http.PostAsJsonAsync(
$"/api/auth?cookie=true",
requestBody, cancel);
return response.StatusCode switch
{
HttpStatusCode.OK => SenderLoginResult.Success,
HttpStatusCode.Unauthorized => SenderLoginResult.InvalidCredentials,
_ => SenderLoginResult.Error
};
}
}