Scaffold some AAT stuff
This commit is contained in:
@@ -5,12 +5,8 @@ using Gameboard.ShogiUI.Sockets.ServiceModels.Api;
|
|||||||
using Microsoft.AspNetCore.Authentication;
|
using Microsoft.AspNetCore.Authentication;
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using System;
|
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Gameboard.ShogiUI.Sockets.Controllers
|
namespace Gameboard.ShogiUI.Sockets.Controllers
|
||||||
{
|
{
|
||||||
@@ -19,7 +15,6 @@ namespace Gameboard.ShogiUI.Sockets.Controllers
|
|||||||
[Authorize]
|
[Authorize]
|
||||||
public class SocketController : ControllerBase
|
public class SocketController : ControllerBase
|
||||||
{
|
{
|
||||||
private readonly ILogger<SocketController> logger;
|
|
||||||
private readonly ISocketTokenCache tokenCache;
|
private readonly ISocketTokenCache tokenCache;
|
||||||
private readonly IGameboardManager gameboardManager;
|
private readonly IGameboardManager gameboardManager;
|
||||||
private readonly IGameboardRepository gameboardRepository;
|
private readonly IGameboardRepository gameboardRepository;
|
||||||
@@ -33,7 +28,6 @@ namespace Gameboard.ShogiUI.Sockets.Controllers
|
|||||||
IGameboardRepository gameboardRepository,
|
IGameboardRepository gameboardRepository,
|
||||||
ISocketConnectionManager connectionManager)
|
ISocketConnectionManager connectionManager)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
|
||||||
this.tokenCache = tokenCache;
|
this.tokenCache = tokenCache;
|
||||||
this.gameboardManager = gameboardManager;
|
this.gameboardManager = gameboardManager;
|
||||||
this.gameboardRepository = gameboardRepository;
|
this.gameboardRepository = gameboardRepository;
|
||||||
|
|||||||
@@ -8,9 +8,12 @@
|
|||||||
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
||||||
<SignAssembly>False</SignAssembly>
|
<SignAssembly>False</SignAssembly>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UserSecretsId>973a1f5f-ef25-4f1c-a24d-b0fc7d016ab8</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.0.0" />
|
||||||
|
<PackageReference Include="Azure.Identity" Version="1.6.0" />
|
||||||
<PackageReference Include="FluentValidation" Version="10.3.6" />
|
<PackageReference Include="FluentValidation" Version="10.3.6" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.5" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.5" />
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Gameboard.ShogiUI.Sockets.Managers
|
|||||||
{
|
{
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||||
Tokens.Remove(userName, out _);
|
Tokens.Remove(userName, out _);
|
||||||
});
|
}).ConfigureAwait(false);
|
||||||
|
|
||||||
return guid;
|
return guid;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,16 +60,22 @@ namespace Gameboard.ShogiUI.Sockets
|
|||||||
{
|
{
|
||||||
// TODO: Figure out how to make a middleware for sockets?
|
// TODO: Figure out how to make a middleware for sockets?
|
||||||
var socketService = app.Services.GetRequiredService<ISocketService>();
|
var socketService = app.Services.GetRequiredService<ISocketService>();
|
||||||
|
var allowedOrigins = app.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>();
|
||||||
|
|
||||||
var origins = new[] {
|
|
||||||
"http://localhost:3000", "https://localhost:3000",
|
|
||||||
"http://127.0.0.1:3000", "https://127.0.0.1:3000",
|
|
||||||
"https://api.lucaserver.space", "https://lucaserver.space"
|
|
||||||
};
|
|
||||||
var socketOptions = new WebSocketOptions();
|
var socketOptions = new WebSocketOptions();
|
||||||
foreach (var o in origins)
|
foreach (var origin in allowedOrigins)
|
||||||
socketOptions.AllowedOrigins.Add(o);
|
socketOptions.AllowedOrigins.Add(origin);
|
||||||
app.UseCors(opt => opt.WithOrigins(origins).AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("Set-Cookie").AllowCredentials());
|
|
||||||
|
app.UseCors(options =>
|
||||||
|
{
|
||||||
|
options
|
||||||
|
.WithOrigins(allowedOrigins)
|
||||||
|
.SetIsOriginAllowedToAllowWildcardSubdomains()
|
||||||
|
.AllowAnyMethod()
|
||||||
|
.AllowAnyHeader()
|
||||||
|
.WithExposedHeaders("Set-Cookie")
|
||||||
|
.AllowCredentials();
|
||||||
|
});
|
||||||
app.UseWebSockets(socketOptions);
|
app.UseWebSockets(socketOptions);
|
||||||
app.Use(async (context, next) =>
|
app.Use(async (context, next) =>
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"resourceGroupName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "DefaultResourceGroup-CUS",
|
||||||
|
"metadata": {
|
||||||
|
"_parameterType": "resourceGroup",
|
||||||
|
"description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resourceGroupLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "centralus",
|
||||||
|
"metadata": {
|
||||||
|
"_parameterType": "location",
|
||||||
|
"description": "Location of the resource group. Resource groups could have different location than resources."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resourceLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[parameters('resourceGroupLocation')]",
|
||||||
|
"metadata": {
|
||||||
|
"_parameterType": "location",
|
||||||
|
"description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Resources/resourceGroups",
|
||||||
|
"name": "[parameters('resourceGroupName')]",
|
||||||
|
"location": "[parameters('resourceGroupLocation')]",
|
||||||
|
"apiVersion": "2019-10-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat('GameboardShogiUISocketsv', subscription().subscriptionId)))]",
|
||||||
|
"resourceGroup": "[parameters('resourceGroupName')]",
|
||||||
|
"apiVersion": "2019-10-01",
|
||||||
|
"dependsOn": [
|
||||||
|
"[parameters('resourceGroupName')]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"template": {
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"name": "GameboardShogiUISocketsv",
|
||||||
|
"type": "Microsoft.KeyVault/vaults",
|
||||||
|
"location": "[parameters('resourceLocation')]",
|
||||||
|
"properties": {
|
||||||
|
"sku": {
|
||||||
|
"family": "A",
|
||||||
|
"name": "Standard"
|
||||||
|
},
|
||||||
|
"tenantId": "d6019544-c403-415c-8e96-50009635b6aa",
|
||||||
|
"accessPolicies": [],
|
||||||
|
"enabledForDeployment": true,
|
||||||
|
"enabledForDiskEncryption": true,
|
||||||
|
"enabledForTemplateDeployment": true
|
||||||
|
},
|
||||||
|
"apiVersion": "2016-10-01"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"_dependencyType": "secrets.keyVault"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,9 @@
|
|||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"launchUrl": "swagger",
|
"launchUrl": "swagger",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||||
|
"VaultUri": "https://gameboardshogiuisocketsv.vault.azure.net/",
|
||||||
|
"AZURE_USERNAME": "Hauth@live.com"
|
||||||
},
|
},
|
||||||
"applicationUrl": "https://localhost:5001;http://localhost:5000"
|
"applicationUrl": "https://localhost:5001;http://localhost:5000"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,11 @@
|
|||||||
"identityapp1": {
|
"identityapp1": {
|
||||||
"type": "identityapp",
|
"type": "identityapp",
|
||||||
"dynamicId": null
|
"dynamicId": null
|
||||||
|
},
|
||||||
|
"secrets1": {
|
||||||
|
"type": "secrets",
|
||||||
|
"connectionId": "VaultUri",
|
||||||
|
"dynamicId": null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,13 @@
|
|||||||
"identityapp1": {
|
"identityapp1": {
|
||||||
"type": "identityapp.default",
|
"type": "identityapp.default",
|
||||||
"dynamicId": null
|
"dynamicId": null
|
||||||
|
},
|
||||||
|
"secrets1": {
|
||||||
|
"secretStore": null,
|
||||||
|
"resourceId": "/subscriptions/[parameters('subscriptionId')]/resourceGroups/[parameters('resourceGroupName')]/providers/Microsoft.KeyVault/vaults/GameboardShogiUISocketsv",
|
||||||
|
"type": "secrets.keyVault",
|
||||||
|
"connectionId": "VaultUri",
|
||||||
|
"dynamicId": null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
4
Gameboard.ShogiUI.Sockets/Readme.md
Normal file
4
Gameboard.ShogiUI.Sockets/Readme.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Gameboard.ShogiUI.Sockets
|
||||||
|
|
||||||
|
# Forgetmenots
|
||||||
|
Don't forget to run `dotnet user-secrets init` within the AAT project.
|
||||||
@@ -67,12 +67,14 @@ namespace Gameboard.ShogiUI.Sockets.Repositories
|
|||||||
* 3) User document of Player2.
|
* 3) User document of Player2.
|
||||||
*/
|
*/
|
||||||
var session = group.FirstOrDefault()?.doc.ToObject<SessionDocument>();
|
var session = group.FirstOrDefault()?.doc.ToObject<SessionDocument>();
|
||||||
var player1Doc = group.Skip(1).FirstOrDefault()?.doc.ToObject<UserDocument>();
|
var player1 = group.Skip(1).FirstOrDefault()?.doc.ToObject<UserDocument>();
|
||||||
var player2Doc = group.Skip(2).FirstOrDefault()?.doc.ToObject<UserDocument>();
|
var player2Doc = group.Skip(2).FirstOrDefault()?.doc;
|
||||||
if (session != null && player1Doc != null)
|
if (session != null && player1 != null && player2Doc != null)
|
||||||
{
|
{
|
||||||
var player2 = player2Doc == null ? null : new Models.User(player2Doc);
|
var player2 = IsUserDocument(player2Doc)
|
||||||
sessions.Add(new SessionMetadata(session.Name, session.IsPrivate, player1Doc.Id, player2?.Id));
|
? new Models.User(player2Doc.ToObject<UserDocument>()!)
|
||||||
|
: null;
|
||||||
|
sessions.Add(new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new Collection<SessionMetadata>(sessions);
|
return new Collection<SessionMetadata>(sessions);
|
||||||
@@ -80,6 +82,11 @@ namespace Gameboard.ShogiUI.Sockets.Repositories
|
|||||||
return new Collection<SessionMetadata>(Array.Empty<SessionMetadata>());
|
return new Collection<SessionMetadata>(Array.Empty<SessionMetadata>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsUserDocument(JObject player2Doc)
|
||||||
|
{
|
||||||
|
return player2Doc?.SelectToken(nameof(CouchDocument.DocumentType))?.Value<WhichDocumentType>() == WhichDocumentType.User;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<Session?> ReadSession(string name)
|
public async Task<Session?> ReadSession(string name)
|
||||||
{
|
{
|
||||||
static Shogi.Domain.Pieces.Piece? MapPiece(Piece? piece)
|
static Shogi.Domain.Pieces.Piece? MapPiece(Piece? piece)
|
||||||
@@ -112,17 +119,16 @@ namespace Gameboard.ShogiUI.Sockets.Repositories
|
|||||||
* Everything Else) Snapshots of the boardstate after every player move.
|
* Everything Else) Snapshots of the boardstate after every player move.
|
||||||
*/
|
*/
|
||||||
var session = group[0].doc.ToObject<SessionDocument>();
|
var session = group[0].doc.ToObject<SessionDocument>();
|
||||||
var player1Doc = group[1].doc.ToObject<UserDocument>();
|
var player1 = group[1].doc.ToObject<UserDocument>();
|
||||||
var group2DocumentType = group[2].doc.Property(nameof(UserDocument.DocumentType).ToCamelCase())?.Value.Value<string>();
|
var player2Doc = group[2].doc;
|
||||||
var player2Doc = group2DocumentType == WhichDocumentType.User.ToString()
|
|
||||||
? group[2].doc.ToObject<UserDocument>()
|
|
||||||
: null;
|
|
||||||
var boardState = group.Last().doc.ToObject<BoardStateDocument>();
|
var boardState = group.Last().doc.ToObject<BoardStateDocument>();
|
||||||
|
|
||||||
if (session != null && player1Doc != null && boardState != null)
|
if (session != null && player1 != null && boardState != null)
|
||||||
{
|
{
|
||||||
var player2 = player2Doc == null ? null : new Models.User(player2Doc);
|
var player2 = IsUserDocument(player2Doc)
|
||||||
var metaData = new SessionMetadata(session.Name, session.IsPrivate, player1Doc.DisplayName, player2Doc?.DisplayName);
|
? new Models.User(player2Doc.ToObject<UserDocument>()!)
|
||||||
|
: null;
|
||||||
|
var metaData = new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id);
|
||||||
var shogiBoardState = new BoardState(boardState.Board.ToDictionary(kvp => kvp.Key, kvp => MapPiece(kvp.Value)));
|
var shogiBoardState = new BoardState(boardState.Board.ToDictionary(kvp => kvp.Key, kvp => MapPiece(kvp.Value)));
|
||||||
return new Session(shogiBoardState, metaData);
|
return new Session(shogiBoardState, metaData);
|
||||||
}
|
}
|
||||||
@@ -151,15 +157,14 @@ namespace Gameboard.ShogiUI.Sockets.Repositories
|
|||||||
* 3) User document of Player2.
|
* 3) User document of Player2.
|
||||||
*/
|
*/
|
||||||
var session = group[0].doc.ToObject<SessionDocument>();
|
var session = group[0].doc.ToObject<SessionDocument>();
|
||||||
var player1Doc = group[1].doc.ToObject<UserDocument>();
|
var player1 = group[1].doc.ToObject<UserDocument>();
|
||||||
var group2DocumentType = group[2].doc.Property(nameof(UserDocument.DocumentType).ToCamelCase())?.Value.Value<string>();
|
var player2Doc = group[2].doc;
|
||||||
var player2Doc = group2DocumentType == WhichDocumentType.User.ToString()
|
if (session != null && player1 != null)
|
||||||
? group[2].doc.ToObject<UserDocument>()
|
|
||||||
: null;
|
|
||||||
if (session != null && player1Doc != null)
|
|
||||||
{
|
{
|
||||||
var player2 = player2Doc == null ? null : new Models.User(player2Doc);
|
var player2 = IsUserDocument(player2Doc)
|
||||||
return new SessionMetadata(session.Name, session.IsPrivate, player1Doc.Id, player2?.Id);
|
? new Models.User(player2Doc.ToObject<UserDocument>()!)
|
||||||
|
: null;
|
||||||
|
return new SessionMetadata(session.Name, session.IsPrivate, player1.Id, player2?.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -18,5 +18,13 @@
|
|||||||
"ClientId": "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
"ClientId": "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
||||||
"SwaggerUIClientId": "26bf69a4-2af8-4711-bf5b-79f75e20b082"
|
"SwaggerUIClientId": "26bf69a4-2af8-4711-bf5b-79f75e20b082"
|
||||||
},
|
},
|
||||||
|
"Cors": {
|
||||||
|
"AllowedOrigins": [
|
||||||
|
"http://localhost:3000",
|
||||||
|
"https://localhost:3000",
|
||||||
|
"https://api.lucaserver.space",
|
||||||
|
"https://lucaserver.space"
|
||||||
|
]
|
||||||
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,26 @@
|
|||||||
|
using Shogi.AcceptanceTests.TestSetup;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
namespace Shogi.AcceptanceTests
|
namespace Shogi.AcceptanceTests
|
||||||
{
|
{
|
||||||
public class AcceptanceTests
|
public class AcceptanceTests : IClassFixture<AATFixture>
|
||||||
{
|
{
|
||||||
public AcceptanceTests()
|
private readonly AATFixture fixture;
|
||||||
{
|
private readonly ITestOutputHelper console;
|
||||||
|
|
||||||
|
public AcceptanceTests(AATFixture fixture, ITestOutputHelper console)
|
||||||
|
{
|
||||||
|
this.fixture = fixture;
|
||||||
|
this.console = console;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void CreateAndReadSession()
|
public async Task CreateAndReadSession()
|
||||||
{
|
{
|
||||||
|
var response = await fixture.Service.GetAsync(new Uri("Game", UriKind.Relative));
|
||||||
|
console.WriteLine(await response.Content.ReadAsStringAsync());
|
||||||
|
console.WriteLine(response.Headers.WwwAuthenticate.ToString());
|
||||||
|
response.IsSuccessStatusCode.Should().BeTrue(because: "AAT Client should be authorized.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
@@ -6,12 +6,31 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
|
<UserSecretsId>96d6281d-a75b-4181-b535-ea34b26dc8a2</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
<None Remove="appsettings.json" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="appsettings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentAssertions" Version="6.7.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
|
||||||
|
<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.Json" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Identity.Client" Version="4.44.0" />
|
||||||
|
<PackageReference Include="Microsoft.Net.Http.Headers" Version="2.2.8" />
|
||||||
|
<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.3">
|
<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>
|
||||||
|
|||||||
77
Shogi.AcceptanceTests/TestSetup/AATFixture.cs
Normal file
77
Shogi.AcceptanceTests/TestSetup/AATFixture.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Identity.Client;
|
||||||
|
using System.Net.Http.Headers;
|
||||||
|
|
||||||
|
namespace Shogi.AcceptanceTests.TestSetup
|
||||||
|
{
|
||||||
|
public class AATFixture : IAsyncLifetime, IDisposable
|
||||||
|
{
|
||||||
|
private bool disposedValue;
|
||||||
|
private readonly IConfidentialClientApplication app;
|
||||||
|
|
||||||
|
public AATFixture()
|
||||||
|
{
|
||||||
|
Configuration = new ConfigurationBuilder()
|
||||||
|
.AddJsonFile("appsettings.json")
|
||||||
|
.AddEnvironmentVariables()
|
||||||
|
.AddUserSecrets<AATFixture>()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
var azure = Configuration.GetSection("Auth");
|
||||||
|
app = ConfidentialClientApplicationBuilder.Create(azure["ClientId"])
|
||||||
|
.WithTenantId(azure["TenantId"])
|
||||||
|
.WithClientSecret(azure["SecretValue"])
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
Service = new HttpClient
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri(Configuration["ServiceUrl"], UriKind.Absolute)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
public HttpClient Service { get; }
|
||||||
|
|
||||||
|
public async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
var authResult = await app
|
||||||
|
.AcquireTokenForClient(Configuration.GetSection("Auth:Scopes").Get<string[]>())
|
||||||
|
.ExecuteAsync();
|
||||||
|
|
||||||
|
authResult.Should().NotBeNull();
|
||||||
|
authResult.AccessToken.Should().NotBeNullOrEmpty();
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (!disposedValue)
|
||||||
|
{
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Service.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
disposedValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task DisposeAsync()
|
||||||
|
{
|
||||||
|
Dispose(true);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Dispose(disposing: true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1,2 @@
|
|||||||
global using Xunit;
|
global using Xunit;
|
||||||
|
global using FluentAssertions;
|
||||||
11
Shogi.AcceptanceTests/appsettings.json
Normal file
11
Shogi.AcceptanceTests/appsettings.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"ServiceUrl": "https://localhost:5001",
|
||||||
|
"Auth": {
|
||||||
|
"TenantId": "d6019544-c403-415c-8e96-50009635b6aa",
|
||||||
|
"ClientId": "78b12a47-440c-4cc7-9402-f573a2802951",
|
||||||
|
"SecretValue": "REDACTED",
|
||||||
|
"Scopes": [
|
||||||
|
"api://c1e94676-cab0-42ba-8b6c-9532b8486fff/.default"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user