Skip to content

Commit

Permalink
Merge pull request #134 from martinjonsson01/120-user-logout
Browse files Browse the repository at this point in the history
120 user logout
  • Loading branch information
martinjonsson01 authored May 11, 2022
2 parents 649abc3 + e7be995 commit b2c4bf3
Show file tree
Hide file tree
Showing 15 changed files with 111 additions and 40 deletions.
4 changes: 3 additions & 1 deletion src/Client/Pages/Contracts/RecentlyViewed.razor
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
@using Application.Contracts
@using System.Collections.ObjectModel
@inject HttpClient _http
@inject ISessionService _session
@inherits AuthenticatedView

<FetchData TData="Contract[]"
Url="/api/v1/contracts/recent"
Context="recents"
ShouldShowErrors="@false">
ShouldShowErrors="@_session.IsAuthenticated">

<!-- No loading indicator. -->
<LoadingIndicator></LoadingIndicator>
Expand Down
6 changes: 6 additions & 0 deletions src/Client/Services/Authentication/ISessionService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ public interface ISessionService
/// <returns>A task that represents the asynchronous operation.</returns>
Task BeginAsync(AuthenticateResponse authentication);

/// <summary>
/// Ends the current authenticated user session.
/// </summary>
/// <returns>A task that represents the asynchronous operation.</returns>
Task EndAsync();

/// <summary>
/// Tries to resume a user session from the already available data.
/// </summary>
Expand Down
21 changes: 20 additions & 1 deletion src/Client/Services/Authentication/SessionManagerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

using Blazored.SessionStorage;

using Microsoft.AspNetCore.Components;

namespace Client.Services.Authentication;

/// <summary>
Expand All @@ -13,16 +15,19 @@ internal class SessionManagerService : ISessionService
{
private readonly ISessionStorageService _storage;
private readonly HttpClient _http;
private readonly NavigationManager _navigationManager;

/// <summary>
/// Initializes a new instance of the <see cref="SessionManagerService"/> class.
/// </summary>
/// <param name="storage">A way to store session data.</param>
/// <param name="http">The client to add authentication tokens to.</param>
public SessionManagerService(ISessionStorageService storage, HttpClient http)
/// <param name="navigationManager">The window navigation controller.</param>
public SessionManagerService(ISessionStorageService storage, HttpClient http, NavigationManager navigationManager)
{
_storage = storage;
_http = http;
_navigationManager = navigationManager;
}

/// <inheritdoc/>
Expand All @@ -42,6 +47,20 @@ public async Task BeginAsync(AuthenticateResponse authentication)
Authenticate(authentication);
}

/// <inheritdoc/>
public async Task EndAsync()
{
await _storage.RemoveItemAsync("user").ConfigureAwait(true);

_http.DefaultRequestHeaders.Authorization = null;

IsAuthenticated = false;
Username = null;

AuthenticationStateChanged?.Invoke(this, new AuthenticationEventArgs { State = null, });
_navigationManager.NavigateTo("/");
}

/// <inheritdoc/>
public async Task<bool> TryResumeAsync()
{
Expand Down
2 changes: 1 addition & 1 deletion src/Client/Shared/FetchData.razor
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ else
/// <inheritdoc />
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (Data is null)
if (Data is null && _errorMessage is null)
await Fetch(Url);
}

Expand Down
13 changes: 0 additions & 13 deletions src/Client/Shared/LogInButton.razor

This file was deleted.

33 changes: 33 additions & 0 deletions src/Client/Shared/Login/Login.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@using Blazorise.Extensions
@using System.Net.Http.Headers
@inject IJSRuntime Js
@inject ISessionService Session
@inherits AuthenticatedView

@if (Session.IsAuthenticated)
{
<div class="d-flex flex-row align-items-center">
<p id="logged-in" class="text-center m-0">
Inloggad som: @Session.Username
</p>
<button id="logout-button" class="btn btn-link" @onclick="@(async () => await Session.EndAsync())">Logga ut</button>
</div>
}
else
{
<button id="login-button"
class="btn btn-primary"
data-bs-toggle="modal"
data-bs-target="#log-in"
@onclick="FocusUsernameField">
Logga in
</button>
}
@code {

private async Task FocusUsernameField()
{
// Focuses the username text input element.
await Js.InvokeVoidAsync("focusElement", "#username");
}
}
3 changes: 3 additions & 0 deletions src/Client/Shared/Login/Login.razor.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#logged-in {
color: var(--prodigo-white);
}
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion src/Client/Shared/MainLayout.razor
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@using Application.Users
@using Application.Users
@using Client.Services.Authentication
@inherits LayoutComponentBase
@inject ISessionService _session
Expand Down
13 changes: 1 addition & 12 deletions src/Client/Shared/NavMenu.razor
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,7 @@
</li>
}
</ul>
<div>
@if (!_session.IsAuthenticated)
{
<LogInButton />
}
else
{
<p id="logged-in" class="text-center m-0">
Inloggad som: @_session?.Username
</p>
}
</div>
<Login />
</div>
</div>
</nav>
4 changes: 0 additions & 4 deletions src/Client/Shared/NavMenu.razor.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,3 @@
.navbar {
padding: 1rem 0;
}

#logged-in {
color: var(--prodigo-white);
}
1 change: 1 addition & 0 deletions src/Client/_Imports.razor
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@
@using Client.Shared
@using Client.Shared.Accordion
@using Client.Shared.Lists
@using Client.Shared.Login
@using Client.Pages.Contracts
@using Client.Services.Authentication
28 changes: 28 additions & 0 deletions tests/Client.Tests/Shared/Login/LoginTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Threading.Tasks;

using Application.Users;

using Client.Shared;

using Microsoft.AspNetCore.Components.Web;

namespace Client.Tests.Shared.Login;

public class LoginTests : UITestFixture
{
[Fact]
public async Task PressLogout_EndsSession_WhenUserWasAuthenticated()
{
// Arrange
MockSession.Setup(session => session.IsAuthenticated).Returns(true);
await SessionStorage.SetItemAsync("user", new AuthenticateResponse(LoggedInUser, FakeToken));

IRenderedComponent<NavMenu> cut = Context.RenderComponent<NavMenu>();

// Act
await cut.Find("#logout-button").ClickAsync(new MouseEventArgs());

// Assert
MockSession.Verify(session => session.EndAsync(), Times.Once);
}
}
21 changes: 14 additions & 7 deletions tests/Client.Tests/Shared/NavMenuTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,8 @@

using Application.Users;

using Blazored.SessionStorage;

using Client.Services.Authentication;
using Client.Shared;

using Domain.Users;

using Microsoft.Extensions.DependencyInjection;

namespace Client.Tests.Shared;

public class NavMenuTests : UITestFixture
Expand All @@ -29,6 +22,20 @@ public async Task NavMenu_DisplaysLoginButton_WhenUserNotLoggedIn()
cut.Find("#login-button").Should().NotBeNull();
}

[Fact]
public async Task NavMenu_DisplaysLogoutButton_WhenUserLoggedIn()
{
// Arrange
MockSession.Setup(session => session.IsAuthenticated).Returns(true);
await SessionStorage.SetItemAsync("user", new AuthenticateResponse(LoggedInUser, FakeToken));

// Act
IRenderedComponent<NavMenu> cut = Context.RenderComponent<NavMenu>();

// Assert
cut.Find("#logout-button").Should().NotBeNull();
}

[Fact]
public async Task NavMenu_DisplaysLoginText_WhenUserLoggedIn()
{
Expand Down

0 comments on commit b2c4bf3

Please sign in to comment.