Auth and error handling components
This commit is contained in:
@@ -1,12 +1,16 @@
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
@using BlazorWebAssemblyVisaApiClient.ErrorHandling
|
||||
|
||||
<GlobalErrorHandler >
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"/>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/>
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
</GlobalErrorHandler>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
namespace BlazorWebAssemblyVisaApiClient.Common
|
||||
{
|
||||
public class BlazorClientException(string message) : Exception(message);
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
@using System.Net
|
||||
@using BlazorWebAssemblyVisaApiClient.Components.Auth.Exceptions
|
||||
@using BlazorWebAssemblyVisaApiClient.ErrorHandling
|
||||
@using VisaApiClient
|
||||
|
||||
@code {
|
||||
public static bool LoggedIn;
|
||||
private static AuthData savedData = null!;
|
||||
|
||||
[CascadingParameter] private GlobalErrorHandler ErrorHandler { get; set; } = null!;
|
||||
|
||||
[CascadingParameter] private Status? Status { get; set; }
|
||||
|
||||
[Inject] private Client Client { get; set; } = null!;
|
||||
|
||||
[Inject] private NavigationManager Nav { get; set; } = null!;
|
||||
|
||||
///Authorize with email and password
|
||||
/// <returns>Message to user</returns>
|
||||
public async Task TryAuthorize(AuthData authData)
|
||||
{
|
||||
Status?.SetMessage("Wait...");
|
||||
try
|
||||
{
|
||||
var token = await Client.LoginAsync(authData.Email, authData.Password);
|
||||
Client.SetAuthToken(token);
|
||||
savedData = authData;
|
||||
|
||||
Status?.SetSucces("Logged in successfully.");
|
||||
}
|
||||
catch (ApiException<ProblemDetails> e)
|
||||
{
|
||||
if (e.Result.Status == (int)HttpStatusCode.Forbidden)
|
||||
{
|
||||
Status?.SetError(e.Result.Detail!);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status?.SetError("Error occured");
|
||||
ErrorHandler.Handle(e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Status?.SetError("Error occured");
|
||||
ErrorHandler.Handle(e);
|
||||
}
|
||||
}
|
||||
|
||||
///Re-auth if token expired or something
|
||||
public async Task ReAuthenticate(bool redirectOnFailure = true)
|
||||
{
|
||||
if (!LoggedIn)
|
||||
{
|
||||
if (redirectOnFailure)
|
||||
{
|
||||
Nav.NavigateTo("/");
|
||||
return;
|
||||
}
|
||||
|
||||
throw new NotLoggedInException();
|
||||
}
|
||||
|
||||
await TryAuthorize(savedData);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
using BlazorWebAssemblyVisaApiClient.Common;
|
||||
using VisaApiClient;
|
||||
|
||||
namespace BlazorWebAssemblyVisaApiClient.Components.Auth.Exceptions
|
||||
{
|
||||
public class NotLoggedInException() : BlazorClientException("User is not logged in");
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
@using BlazorWebAssemblyVisaApiClient.ErrorHandling
|
||||
@using VisaApiClient
|
||||
|
||||
@code
|
||||
{
|
||||
[CascadingParameter] protected GlobalErrorHandler ErrorHandler { get; set; } = null!;
|
||||
|
||||
[Inject] protected Client Client { get; set; } = null!;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<p class="@statusClass">@((MarkupString)StatusText)</p>
|
||||
<CascadingValue Value="this">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
|
||||
@code {
|
||||
private string statusClass = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
|
||||
public string StatusText { get; set; } = string.Empty;
|
||||
|
||||
public void SetMessage(string message)
|
||||
{
|
||||
statusClass = string.Empty;
|
||||
StatusText = message;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void SetError(string message)
|
||||
{
|
||||
statusClass = "validation-message";
|
||||
StatusText = message;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public void SetSucces(string message)
|
||||
{
|
||||
statusClass = "text-success";
|
||||
StatusText = message;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<CascadingValue Value="this">
|
||||
@ChildContent
|
||||
</CascadingValue>
|
||||
|
||||
@code
|
||||
{
|
||||
[Parameter]
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
|
||||
public void Handle(Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
@page "/"
|
||||
@using System.Net
|
||||
@using BlazorWebAssemblyVisaApiClient.Components.Auth
|
||||
@using VisaApiClient
|
||||
@using BlazorWebAssemblyVisaApiClient.Components.FormComponents.Applicants
|
||||
@using BlazorWebAssemblyVisaApiClient.Components
|
||||
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
||||
|
||||
<PageTitle>Authentication</PageTitle>
|
||||
|
||||
@@ -13,30 +17,17 @@
|
||||
<input class="btn-outline-primary rounded" type="submit" value="Login"/>
|
||||
or
|
||||
<NavLink href="register">Register</NavLink >
|
||||
<p>@loginResult</p>
|
||||
<Status><AuthComponent @ref="auth"/></Status>
|
||||
</EditForm>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
private AuthData loginData = new();
|
||||
private string loginResult = string.Empty;
|
||||
|
||||
[Inject] private Client Client { get; set; } = null!;
|
||||
private AuthComponent auth = null!;
|
||||
|
||||
private async Task TryLogin()
|
||||
{
|
||||
loginResult = "Wait...";
|
||||
StateHasChanged();
|
||||
try
|
||||
{
|
||||
var token = await Client.LoginAsync(loginData.Email, loginData.Password);
|
||||
Client.SetAuthToken(token);
|
||||
loginResult = "Logged in successfully.";
|
||||
}
|
||||
catch (ApiException<ProblemDetails> e)
|
||||
{
|
||||
loginResult = e.Result.Detail!;
|
||||
}
|
||||
await auth.TryAuthorize(loginData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
@using global::FluentValidation
|
||||
@using Newtonsoft.Json
|
||||
@using Newtonsoft.Json.Linq
|
||||
@using BlazorWebAssemblyVisaApiClient.Components
|
||||
@inherits BlazorWebAssemblyVisaApiClient.Components.Base.VisaClientComponentBase
|
||||
|
||||
<PageTitle>Registration</PageTitle>
|
||||
|
||||
@@ -122,17 +124,14 @@
|
||||
</div><br/>
|
||||
|
||||
<input type="submit" class="btn-outline-primary" value="Register"/>
|
||||
<p class="@requestResultClass">@((MarkupString)requestResult)</p>
|
||||
<Status @ref="status"/>
|
||||
</EditForm>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
private RegisterApplicantRequestModel requestModel = new();
|
||||
private string requestResult = string.Empty;
|
||||
private string requestResultClass = string.Empty;
|
||||
|
||||
[Inject] public Client Client { get; set; } = null!;
|
||||
private Status status = null!;
|
||||
|
||||
[Inject] IValidator<RegisterApplicantRequestModel> RegisterApplicantRequestValidator { get; set; } = null!;
|
||||
|
||||
@@ -145,27 +144,6 @@
|
||||
requestModel.BirthDate = DateTime.Now;
|
||||
}
|
||||
|
||||
private void SetRequestResultMessage(string message)
|
||||
{
|
||||
requestResult = message;
|
||||
requestResultClass = string.Empty;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void SetRequestResultSuccess(string message)
|
||||
{
|
||||
requestResult = message;
|
||||
requestResultClass = "text-success";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void SetRequestResultError(string message)
|
||||
{
|
||||
requestResult = message;
|
||||
requestResultClass = "validation-message";
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private string ErrorsToString(IEnumerable<string> errors)
|
||||
{
|
||||
var stringBuilder = new StringBuilder();
|
||||
@@ -183,18 +161,18 @@
|
||||
if (!validationResult.IsValid)
|
||||
{
|
||||
var errorsString = ErrorsToString(validationResult.Errors.Select(e => e.ErrorMessage));
|
||||
SetRequestResultError(errorsString);
|
||||
status.SetError(errorsString);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SetRequestResultMessage("Wait...");
|
||||
status.SetMessage("Wait...");
|
||||
|
||||
var request = Mapper.Map<RegisterApplicantRequest>(requestModel);
|
||||
try
|
||||
{
|
||||
await Client.RegisterAsync(request);
|
||||
SetRequestResultSuccess("Register successful. Now log in.");
|
||||
status.SetSucces("Register successful. Now log in.");
|
||||
}
|
||||
catch (ApiException<ProblemDetails> e)
|
||||
{
|
||||
@@ -204,15 +182,21 @@
|
||||
var errorsList = ((JArray)errors).ToObject<List<string>>();
|
||||
if (errorsList is null)
|
||||
{
|
||||
throw new JsonException();
|
||||
ErrorHandler.Handle(new JsonException("Can't convert validation errors to list"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
SetRequestResultError(ErrorsToString(errorsList));
|
||||
status.SetError(ErrorsToString(errorsList));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetRequestResultError(e.Result.Detail!);
|
||||
ErrorHandler.Handle(e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ErrorHandler.Handle(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user