yep
This commit is contained in:
@@ -176,7 +176,7 @@ namespace Gameboard.ShogiUI.Sockets.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public async Task<GetSessionsResponse> GetSessions()
|
public async Task<ActionResult<GetSessionsResponse>> GetSessions()
|
||||||
{
|
{
|
||||||
var user = await ReadUserOrThrow();
|
var user = await ReadUserOrThrow();
|
||||||
var sessions = await gameboardRepository.ReadSessionMetadatas();
|
var sessions = await gameboardRepository.ReadSessionMetadatas();
|
||||||
@@ -190,11 +190,11 @@ namespace Gameboard.ShogiUI.Sockets.Controllers
|
|||||||
.Select(s => mapper.Map(s))
|
.Select(s => mapper.Map(s))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
return new GetSessionsResponse
|
return Ok(new GetSessionsResponse
|
||||||
{
|
{
|
||||||
PlayerHasJoinedSessions = sessionsJoinedByUser,
|
PlayerHasJoinedSessions = sessionsJoinedByUser,
|
||||||
AllOtherSessions = sessionsNotJoinedByUser
|
AllOtherSessions = sessionsNotJoinedByUser
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPut("{gameName}")]
|
[HttpPut("{gameName}")]
|
||||||
|
|||||||
@@ -1,28 +1,29 @@
|
|||||||
using System.Linq;
|
using System.Security.Claims;
|
||||||
using System.Security.Claims;
|
|
||||||
|
|
||||||
namespace Gameboard.ShogiUI.Sockets.Extensions
|
namespace Gameboard.ShogiUI.Sockets.Extensions
|
||||||
{
|
{
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
public static string? UserId(this ClaimsPrincipal self)
|
private static readonly string MsalUsernameClaim = "preferred_username";
|
||||||
{
|
|
||||||
return self.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string? DisplayName(this ClaimsPrincipal self)
|
public static string? UserId(this ClaimsPrincipal self)
|
||||||
{
|
{
|
||||||
return self.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
|
return self.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool IsGuest(this ClaimsPrincipal self)
|
public static string? DisplayName(this ClaimsPrincipal self)
|
||||||
{
|
{
|
||||||
return self.HasClaim(c => c.Type == ClaimTypes.Role && c.Value == "Guest");
|
return self.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string ToCamelCase(this string self)
|
public static bool IsMicrosoft(this ClaimsPrincipal self)
|
||||||
{
|
{
|
||||||
return char.ToLowerInvariant(self[0]) + self[1..];
|
return self.HasClaim(c => c.Type == MsalUsernameClaim);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static string ChangeFirstCharacterToLowerCase(this string self)
|
||||||
|
{
|
||||||
|
return char.ToLowerInvariant(self[0]) + self[1..];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ namespace Gameboard.ShogiUI.Sockets.Managers
|
|||||||
throw new InvalidOperationException("Cannot create user from given claims.");
|
throw new InvalidOperationException("Cannot create user from given claims.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var user = principal.IsGuest()
|
var user = principal.IsMicrosoft()
|
||||||
? User.CreateGuestUser(id)
|
? User.CreateMsalUser(id)
|
||||||
: User.CreateMsalUser(id);
|
: User.CreateGuestUser(id);
|
||||||
|
|
||||||
await repository.CreateUser(user);
|
await repository.CreateUser(user);
|
||||||
return user;
|
return user;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using Gameboard.ShogiUI.Sockets.Repositories.CouchModels;
|
using Gameboard.ShogiUI.Sockets.Repositories.CouchModels;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
|
||||||
@@ -62,7 +60,6 @@ namespace Gameboard.ShogiUI.Sockets.Models
|
|||||||
new Claim(ClaimTypes.NameIdentifier, Id),
|
new Claim(ClaimTypes.NameIdentifier, Id),
|
||||||
new Claim(ClaimTypes.Name, DisplayName),
|
new Claim(ClaimTypes.Name, DisplayName),
|
||||||
new Claim(ClaimTypes.Role, "Guest"),
|
new Claim(ClaimTypes.Role, "Guest"),
|
||||||
new Claim(ClaimTypes.Role, "Shogi") // The Shogi role grants access to api controllers.
|
|
||||||
};
|
};
|
||||||
return new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
return new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
|
||||||
}
|
}
|
||||||
@@ -72,7 +69,6 @@ namespace Gameboard.ShogiUI.Sockets.Models
|
|||||||
{
|
{
|
||||||
new Claim(ClaimTypes.NameIdentifier, Id),
|
new Claim(ClaimTypes.NameIdentifier, Id),
|
||||||
new Claim(ClaimTypes.Name, DisplayName),
|
new Claim(ClaimTypes.Name, DisplayName),
|
||||||
new Claim(ClaimTypes.Role, "Shogi") // The Shogi role grants access to api controllers.
|
|
||||||
};
|
};
|
||||||
return new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme);
|
return new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ namespace Gameboard.ShogiUI.Sockets
|
|||||||
services.AddSingleton<IValidator<JoinGameRequest>, JoinGameRequestValidator>();
|
services.AddSingleton<IValidator<JoinGameRequest>, JoinGameRequestValidator>();
|
||||||
services.AddSingleton<ISocketService, SocketService>();
|
services.AddSingleton<ISocketService, SocketService>();
|
||||||
services.AddTransient<IGameboardRepository, GameboardRepository>();
|
services.AddTransient<IGameboardRepository, GameboardRepository>();
|
||||||
services.AddSingleton<IClaimsTransformation, ShogiUserClaimsTransformer>();
|
services.AddTransient<IClaimsTransformation, ShogiUserClaimsTransformer>();
|
||||||
services.AddHttpClient("couchdb", c =>
|
services.AddHttpClient("couchdb", c =>
|
||||||
{
|
{
|
||||||
var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes("admin:admin"));
|
var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes("admin:admin"));
|
||||||
|
|||||||
@@ -1,43 +1,44 @@
|
|||||||
using Gameboard.ShogiUI.Sockets.Repositories;
|
using Gameboard.ShogiUI.Sockets.Extensions;
|
||||||
|
using Gameboard.ShogiUI.Sockets.Repositories;
|
||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Gameboard.ShogiUI.Sockets
|
namespace Gameboard.ShogiUI.Sockets
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Standardizes the claims from third party issuers. Also registers new msal users in the database.
|
/// Standardizes the claims from third party issuers. Also registers new msal users in the database.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ShogiUserClaimsTransformer : IClaimsTransformation
|
public class ShogiUserClaimsTransformer : IClaimsTransformation
|
||||||
{
|
{
|
||||||
private static readonly string MsalUsernameClaim = "preferred_username";
|
private readonly IGameboardRepository gameboardRepository;
|
||||||
private readonly IGameboardRepository gameboardRepository;
|
|
||||||
|
|
||||||
public ShogiUserClaimsTransformer(IGameboardRepository gameboardRepository)
|
public ShogiUserClaimsTransformer(IGameboardRepository gameboardRepository)
|
||||||
{
|
{
|
||||||
this.gameboardRepository = gameboardRepository;
|
this.gameboardRepository = gameboardRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
|
public async Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
|
||||||
{
|
{
|
||||||
var nameClaim = principal.Claims.FirstOrDefault(c => c.Type == MsalUsernameClaim);
|
var id = principal.UserId();
|
||||||
if (nameClaim != default)
|
if (!string.IsNullOrWhiteSpace(id))
|
||||||
{
|
{
|
||||||
var user = await gameboardRepository.ReadUser(nameClaim.Value);
|
var user = await gameboardRepository.ReadUser(id);
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
var newUser = Models.User.CreateMsalUser(nameClaim.Value);
|
var newUser = principal.IsMicrosoft()
|
||||||
await gameboardRepository.CreateUser(newUser);
|
? Models.User.CreateMsalUser(id)
|
||||||
user = newUser;
|
: Models.User.CreateGuestUser(id);
|
||||||
}
|
|
||||||
|
|
||||||
if (user != null)
|
await gameboardRepository.CreateUser(newUser);
|
||||||
{
|
user = newUser;
|
||||||
return new ClaimsPrincipal(user.CreateClaimsIdentity());
|
}
|
||||||
}
|
|
||||||
}
|
if (user != null)
|
||||||
return principal;
|
{
|
||||||
}
|
return new ClaimsPrincipal(user.CreateClaimsIdentity());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return principal;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,43 +1,44 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<UserSecretsId>96d6281d-a75b-4181-b535-ea34b26dc8a2</UserSecretsId>
|
<UserSecretsId>96d6281d-a75b-4181-b535-ea34b26dc8a2</UserSecretsId>
|
||||||
</PropertyGroup>
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Remove="appsettings.json" />
|
<None Remove="appsettings.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="appsettings.json">
|
<Content Include="appsettings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.7.0" />
|
<PackageReference Include="FluentAssertions" Version="6.7.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="6.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.44.0" />
|
<PackageReference Include="Microsoft.Identity.Client" Version="4.44.0" />
|
||||||
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||||
<PackageReference Include="xunit" Version="2.4.1" />
|
<PackageReference Include="xunit" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -44,9 +44,6 @@ namespace Shogi.AcceptanceTests.TestSetup
|
|||||||
authResult.AccessToken.Should().NotBeNullOrEmpty();
|
authResult.AccessToken.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
Service.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
|
Service.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
|
||||||
|
|
||||||
var response = await Service.GetAsync("Socket/Token");
|
|
||||||
response.IsSuccessStatusCode.Should().BeTrue(because: "AAT client should create an account for tests.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.2.0" />
|
<PackageReference Include="FluentAssertions" Version="6.2.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0-preview-20211130-02" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
|
||||||
<PackageReference Include="xunit" Version="2.4.2-pre.12" />
|
<PackageReference Include="xunit" Version="2.4.2-pre.12" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
|||||||
Reference in New Issue
Block a user