Skip to content

Commit

Permalink
login refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
joao4all committed Apr 19, 2024
1 parent 35d2634 commit f81d7ce
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 84 deletions.
17 changes: 8 additions & 9 deletions COMET.Web.Common.Tests/Components/LoginTestFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace COMET.Web.Common.Tests.Components
using COMET.Web.Common.Test.Helpers;
using COMET.Web.Common.ViewModels.Components;

using FluentResults;

using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.DependencyInjection;
Expand Down Expand Up @@ -143,8 +145,7 @@ public async Task VerifyPerformLogin()
var renderer = this.context.RenderComponent<Login>();
var editForm = renderer.FindComponent<EditForm>();

this.authenticationService.Setup(x => x.Login(It.IsAny<AuthenticationDto>()))
.ReturnsAsync(AuthenticationStateKind.ServerFail);
this.authenticationService.Setup(x => x.Login(It.IsAny<AuthenticationDto>())).ReturnsAsync(Result.Ok);

Assert.That(renderer.Instance.FieldsFocusedStatus, Is.EqualTo(new Dictionary<string, bool>()
{
Expand All @@ -158,22 +159,20 @@ public async Task VerifyPerformLogin()
Assert.Multiple(() =>
{
Assert.That(renderer.Instance.LoginButtonDisplayText, Is.EqualTo("Retry"));
Assert.That(renderer.Instance.ErrorMessage, Is.Not.Null);
Assert.That(renderer.Instance.ErrorMessages, Is.Not.Null);
});

this.authenticationService.Setup(x => x.Login(It.IsAny<AuthenticationDto>()))
.ReturnsAsync(AuthenticationStateKind.Fail);
this.authenticationService.Setup(x => x.Login(It.IsAny<AuthenticationDto>())).ReturnsAsync(Result.Ok);

await renderer.InvokeAsync(editForm.Instance.OnValidSubmit.InvokeAsync);

Assert.Multiple(() =>
{
Assert.That(renderer.Instance.LoginButtonDisplayText, Is.EqualTo("Retry"));
Assert.That(renderer.Instance.ErrorMessage, Is.Not.Null);
Assert.That(renderer.Instance.ErrorMessages, Is.Not.Null);
});

this.authenticationService.Setup(x => x.Login(It.IsAny<AuthenticationDto>()))
.ReturnsAsync(AuthenticationStateKind.Success);
this.authenticationService.Setup(x => x.Login(It.IsAny<AuthenticationDto>())).ReturnsAsync(Result.Ok);

this.viewModel.AuthenticationDto.SourceAddress = "http://localhost.com";
this.viewModel.AuthenticationDto.UserName = "user";
Expand All @@ -184,7 +183,7 @@ public async Task VerifyPerformLogin()
Assert.Multiple(() =>
{
Assert.That(renderer.Instance.LoginButtonDisplayText, Is.EqualTo("Connecting"));
Assert.That(renderer.Instance.ErrorMessage, Is.Empty);
Assert.That(renderer.Instance.ErrorMessages, Is.Empty);
});
}
}
Expand Down
13 changes: 9 additions & 4 deletions COMET.Web.Common/Components/Login.razor
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,16 @@
}
</ul>

@if (!string.IsNullOrEmpty(this.ErrorMessage))
@if (this.ErrorMessages.Any())
{
<div class="form-group row m-top-10px">
<label class="text-danger">@this.ErrorMessage</label>
</div>
<div class="form-group row m-top-10px text-danger">
<ul>
@foreach (var errrorMessage in this.ErrorMessages)
{
<li>@errrorMessage</li>
}
</ul>
</div>
}

<div class="modal-footer">
Expand Down
25 changes: 10 additions & 15 deletions COMET.Web.Common/Components/Login.razor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ public partial class Login
public string LoginButtonDisplayText { get; private set; }

/// <summary>
/// An error message to display after a login failure
/// The error messages to display after a login failure
/// </summary>
public string ErrorMessage { get; private set; }
public IEnumerable<string> ErrorMessages { get; private set; }

/// <summary>
/// Value indicating if the login button is enabled or not
Expand All @@ -97,8 +97,8 @@ protected override void OnInitialized()
{ "Password", false }
};

this.Disposables.Add(this.WhenAnyValue(x => x.ViewModel.AuthenticationState)
.Subscribe(_ => this.ComputeDisplayProperties()));
this.Disposables.Add(this.WhenAnyValue(x => x.ViewModel.AuthenticationResult).Subscribe(_ => this.ComputeDisplayProperties()));
this.Disposables.Add(this.WhenAnyValue(x => x.ViewModel.IsLoading).Subscribe(_ => this.ComputeDisplayProperties()));
}

/// <summary>
Expand All @@ -113,24 +113,19 @@ protected override void OnParametersSet()
}

/// <summary>
/// Compute display properties based on the <see cref="ILoginViewModel.AuthenticationState" />
/// Compute display properties based on the <see cref="ILoginViewModel.AuthenticationResult" />
/// </summary>
private void ComputeDisplayProperties()
{
this.LoginButtonDisplayText = this.ViewModel.AuthenticationState switch
this.LoginButtonDisplayText = this.ViewModel.IsLoading switch
{
AuthenticationStateKind.None => "Connect",
AuthenticationStateKind.Authenticating => "Connecting",
AuthenticationStateKind.ServerFail or AuthenticationStateKind.Fail => "Retry",
true => "Connecting",
false when this.ViewModel.AuthenticationResult.IsSuccess => "Connect",
false when this.ViewModel.AuthenticationResult.IsFailed => "Retry",
_ => this.LoginButtonDisplayText
};

this.ErrorMessage = this.ViewModel.AuthenticationState switch
{
AuthenticationStateKind.ServerFail => "The server could not be reached",
AuthenticationStateKind.Fail => "Login failed.",
_ => string.Empty
};
this.ErrorMessages = this.ViewModel.AuthenticationResult.Errors.Select(x => x.Message);

this.InvokeAsync(this.StateHasChanged);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@ namespace COMET.Web.Common.Services.SessionManagement
{
using CDP4Dal;
using CDP4Dal.DAL;
using CDP4Dal.Exceptions;

using CDP4ServicesDal;
using CDP4Web.Extensions;

using COMET.Web.Common.Enumerations;
using COMET.Web.Common.Model.DTO;

using FluentResults;

using Microsoft.AspNetCore.Components.Authorization;
using System.Net;

/// <summary>
/// The purpose of the <see cref="AuthenticationService" /> is to authenticate against
Expand All @@ -52,11 +53,6 @@ public class AuthenticationService : IAuthenticationService
/// </summary>
private readonly ISessionService sessionService;

/// <summary>
/// Gets the injected <see cref="ICDPMessageBus"/>
/// </summary>
private readonly ICDPMessageBus messageBus;

/// <summary>
/// Initializes a new instance of the <see cref="AuthenticationService" /> class.
/// </summary>
Expand All @@ -66,10 +62,8 @@ public class AuthenticationService : IAuthenticationService
/// <param name="authenticationStateProvider">
/// The (injected) <see cref="AuthenticationStateProvider" />
/// </param>
/// <param name="messageBus">The <see cref="ICDPMessageBus"/></param>
public AuthenticationService(ISessionService sessionService, AuthenticationStateProvider authenticationStateProvider, ICDPMessageBus messageBus)
public AuthenticationService(ISessionService sessionService, AuthenticationStateProvider authenticationStateProvider)
{
this.messageBus = messageBus;
this.authStateProvider = authenticationStateProvider;
this.sessionService = sessionService;
}
Expand All @@ -81,41 +75,23 @@ public AuthenticationService(ISessionService sessionService, AuthenticationState
/// The authentication information with data source, username and password
/// </param>
/// <returns>
/// <see cref="AuthenticationStateKind.Success" /> when the authentication is done and the ISession opened
/// The <see cref="Result"/> of the request
/// </returns>
public async Task<AuthenticationStateKind> Login(AuthenticationDto authenticationDto)
public async Task<Result> Login(AuthenticationDto authenticationDto)
{
if (authenticationDto.SourceAddress != null)
{
var uri = new Uri(authenticationDto.SourceAddress);
var dal = new CdpServicesDal();
var credentials = new Credentials(authenticationDto.UserName, authenticationDto.Password, uri);
var result = new Result();

this.sessionService.Session = new Session(dal, credentials, this.messageBus);
}
else
if (authenticationDto.SourceAddress == null)
{
return AuthenticationStateKind.Fail;
result.Reasons.Add(new Error("The source address should not be empty").AddReasonIdentifier(HttpStatusCode.BadRequest));
return result;
}

try
{
await this.sessionService.Session.Open();
this.sessionService.IsSessionOpen = this.sessionService.GetSiteDirectory() != null;
((CometWebAuthStateProvider)this.authStateProvider).NotifyAuthenticationStateChanged();
var uri = new Uri(authenticationDto.SourceAddress);
var credentials = new Credentials(authenticationDto.UserName, authenticationDto.Password, uri);
result = await this.sessionService.OpenSession(credentials);

return this.sessionService.IsSessionOpen ? AuthenticationStateKind.Success : AuthenticationStateKind.Fail;
}
catch (DalReadException)
{
this.sessionService.IsSessionOpen = false;
return AuthenticationStateKind.Fail;
}
catch (HttpRequestException)
{
this.sessionService.IsSessionOpen = false;
return AuthenticationStateKind.ServerFail;
}
return result;
}

/// <summary>
Expand All @@ -128,7 +104,7 @@ public async Task Logout()
{
if (this.sessionService.Session != null)
{
await this.sessionService.Close();
await this.sessionService.CloseSession();
}

((CometWebAuthStateProvider)this.authStateProvider).NotifyAuthenticationStateChanged();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@

namespace COMET.Web.Common.Services.SessionManagement
{
using COMET.Web.Common.Enumerations;
using COMET.Web.Common.Model.DTO;

using FluentResults;

/// <summary>
/// The purpose of the <see cref="IAuthenticationService" /> is to authenticate against
/// a E-TM-10-25 Annex C.2 data source
Expand All @@ -41,9 +42,9 @@ public interface IAuthenticationService
/// The authentication information with data source, username and password
/// </param>
/// <returns>
/// True when the authentication is done
/// The <see cref="Result"/> of the request
/// </returns>
Task<AuthenticationStateKind> Login(AuthenticationDto authenticationDto);
Task<Result> Login(AuthenticationDto authenticationDto);

/// <summary>
/// Logout from the data source
Expand Down
12 changes: 9 additions & 3 deletions COMET.Web.Common/ViewModels/Components/ILoginViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@

namespace COMET.Web.Common.ViewModels.Components
{
using COMET.Web.Common.Enumerations;
using COMET.Web.Common.Model.DTO;
using COMET.Web.Common.Services.ConfigurationService;

using FluentResults;

/// <summary>
/// View Model that enables the user to login against a COMET Server
/// </summary>
Expand All @@ -40,9 +41,14 @@ public interface ILoginViewModel
IConfigurationService serverConnectionService { get; }

/// <summary>
/// Gets or sets the <see cref="AuthenticationStateKind" />
/// Gets or sets the loading state
/// </summary>
bool IsLoading { get; }

/// <summary>
/// Gets or sets the <see cref="Result" /> of an authentication
/// </summary>
AuthenticationStateKind AuthenticationState { get; set; }
Result AuthenticationResult { get; }

/// <summary>
/// The <see cref="AuthenticationDto" /> used for perfoming a login
Expand Down
38 changes: 28 additions & 10 deletions COMET.Web.Common/ViewModels/Components/LoginViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@

namespace COMET.Web.Common.ViewModels.Components
{
using COMET.Web.Common.Enumerations;
using COMET.Web.Common.Model.DTO;
using COMET.Web.Common.Services.ConfigurationService;
using COMET.Web.Common.Services.SessionManagement;

using FluentResults;

using ReactiveUI;

/// <summary>
Expand All @@ -47,9 +49,14 @@ public class LoginViewModel : ReactiveObject, ILoginViewModel
public IConfigurationService serverConnectionService { get; }

/// <summary>
/// Backing field for <see cref="AuthenticationState" />
/// Backing field for <see cref="isLoading" />
/// </summary>
private bool isLoading;

/// <summary>
/// Backing field for <see cref="AuthenticationResult" />
/// </summary>
private AuthenticationStateKind authenticationState;
private Result authenticationResult;

/// <summary>
/// Initializes a new instance of the <see cref="LoginViewModel" /> class.
Expand All @@ -63,12 +70,21 @@ public LoginViewModel(IAuthenticationService authenticationService, IConfigurati
}

/// <summary>
/// Gets or sets the <see cref="AuthenticationStateKind" />
/// Gets or sets the loading state
/// </summary>
public AuthenticationStateKind AuthenticationState
public bool IsLoading
{
get => this.authenticationState;
set => this.RaiseAndSetIfChanged(ref this.authenticationState, value);
get => this.isLoading;
set => this.RaiseAndSetIfChanged(ref this.isLoading, value);
}

/// <summary>
/// Gets or sets the <see cref="Result" /> of an authentication
/// </summary>
public Result AuthenticationResult
{
get => this.authenticationResult;
set => this.RaiseAndSetIfChanged(ref this.authenticationResult, value);
}

/// <summary>
Expand All @@ -82,19 +98,21 @@ public AuthenticationStateKind AuthenticationState
/// <returns>A <see cref="Task" /></returns>
public async Task ExecuteLogin()
{
this.AuthenticationState = AuthenticationStateKind.Authenticating;
this.IsLoading = true;

if(!string.IsNullOrEmpty(this.serverConnectionService.ServerConfiguration.ServerAddress))
{
this.AuthenticationDto.SourceAddress = this.serverConnectionService.ServerConfiguration.ServerAddress;
}

this.AuthenticationState = await this.authenticationService.Login(this.AuthenticationDto);
this.AuthenticationResult = await this.authenticationService.Login(this.AuthenticationDto);

if (this.authenticationState == AuthenticationStateKind.Success)
if (this.AuthenticationResult.IsSuccess)
{
this.AuthenticationDto = new AuthenticationDto();
}

this.IsLoading = false;
}
}
}

0 comments on commit f81d7ce

Please sign in to comment.