138 lines
5.0 KiB
C#
138 lines
5.0 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
|
|
using Shogi.UI.Pages.Home.Api;
|
|
using Shogi.UI.Shared;
|
|
|
|
namespace Shogi.UI.Pages.Home.Account;
|
|
|
|
public class AccountManager
|
|
{
|
|
private readonly AccountState accountState;
|
|
private readonly IShogiApi shogiApi;
|
|
private readonly ILocalStorage localStorage;
|
|
private readonly AuthenticationStateProvider authState;
|
|
private readonly NavigationManager navigation;
|
|
private readonly ShogiSocket shogiSocket;
|
|
|
|
public AccountManager(
|
|
AccountState accountState,
|
|
IShogiApi unauthenticatedClient,
|
|
AuthenticationStateProvider authState,
|
|
ILocalStorage localStorage,
|
|
NavigationManager navigation,
|
|
ShogiSocket shogiSocket)
|
|
{
|
|
this.accountState = accountState;
|
|
this.shogiApi = unauthenticatedClient;
|
|
this.authState = authState;
|
|
this.localStorage = localStorage;
|
|
this.navigation = navigation;
|
|
this.shogiSocket = shogiSocket;
|
|
}
|
|
|
|
private Task SetUser(User user) => accountState.SetUser(user);
|
|
|
|
|
|
public async Task LoginWithGuestAccount()
|
|
{
|
|
var response = await shogiApi.GetToken(WhichAccountPlatform.Guest);
|
|
if (response != null)
|
|
{
|
|
await SetUser(new User
|
|
{
|
|
DisplayName = response.DisplayName,
|
|
Id = response.UserId,
|
|
WhichAccountPlatform = WhichAccountPlatform.Guest
|
|
});
|
|
await localStorage.SetAccountPlatform(WhichAccountPlatform.Guest);
|
|
// TODO: OpenAsync() sometimes doesn't return, probably because of the fire'n'forget task inside it. Figure that out.
|
|
await shogiSocket.OpenAsync(response.OneTimeToken.ToString());
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Failed to get token from server during guest login.");
|
|
}
|
|
}
|
|
|
|
public async Task LoginWithMicrosoftAccount()
|
|
{
|
|
var state = await authState.GetAuthenticationStateAsync();
|
|
|
|
if (state?.User?.Identity?.Name == null || state.User?.Identity?.IsAuthenticated == false)
|
|
{
|
|
// Set the login platform so that we know to log in with microsoft after being redirected away from the UI.
|
|
await localStorage.SetAccountPlatform(WhichAccountPlatform.Microsoft);
|
|
navigation.NavigateToLogin("authentication/login");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Try to log in with the account used from the previous browser session.
|
|
/// </summary>
|
|
/// <returns>True if login succeeded.</returns>
|
|
public async Task<bool> TryLoginSilentAsync()
|
|
{
|
|
var platform = await localStorage.GetAccountPlatform();
|
|
Console.WriteLine($"Try Login Silent - {platform}");
|
|
if (platform == WhichAccountPlatform.Guest)
|
|
{
|
|
var response = await shogiApi.GetToken(WhichAccountPlatform.Guest);
|
|
if (response != null)
|
|
{
|
|
await accountState.SetUser(new User(
|
|
Id: response.UserId,
|
|
DisplayName: response.DisplayName,
|
|
WhichAccountPlatform: WhichAccountPlatform.Guest));
|
|
await shogiSocket.OpenAsync(response.OneTimeToken.ToString());
|
|
return true;
|
|
}
|
|
}
|
|
else if (platform == WhichAccountPlatform.Microsoft)
|
|
{
|
|
var state = await authState.GetAuthenticationStateAsync();
|
|
if (state.User?.Identity?.Name != null)
|
|
{
|
|
var response = await shogiApi.GetToken(WhichAccountPlatform.Microsoft);
|
|
if (response == null)
|
|
{
|
|
// Login failed, so reset local storage to avoid putting the user in a broken state.
|
|
await localStorage.DeleteAccountPlatform();
|
|
return false;
|
|
}
|
|
var id = state.User.Claims.Single(claim => claim.Type == "oid").Value;
|
|
var displayName = state.User.Identity.Name;
|
|
await accountState.SetUser(new User(
|
|
Id: id,
|
|
DisplayName: displayName,
|
|
WhichAccountPlatform: WhichAccountPlatform.Microsoft));
|
|
await shogiSocket.OpenAsync(response.OneTimeToken.ToString());
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public async Task LogoutAsync()
|
|
{
|
|
var platform = await localStorage.GetAccountPlatform();
|
|
await localStorage.DeleteAccountPlatform();
|
|
await accountState.SetUser(null);
|
|
|
|
if (platform == WhichAccountPlatform.Guest)
|
|
{
|
|
await shogiApi.GuestLogout();
|
|
}
|
|
else if (platform == WhichAccountPlatform.Microsoft)
|
|
{
|
|
navigation.NavigateToLogout("authentication/logout");
|
|
}
|
|
else
|
|
{
|
|
throw new InvalidOperationException("Tried to logout without a valid account platform.");
|
|
}
|
|
}
|
|
}
|