reworking Program.cs
This commit is contained in:
@@ -1,13 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
|
||||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
using BenchmarkDotNet.Attributes;
|
|
||||||
using BenchmarkDotNet.Engines;
|
|
||||||
using BenchmarkDotNet.Running;
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Numerics;
|
|
||||||
|
|
||||||
namespace Benchmarking
|
|
||||||
{
|
|
||||||
public class Benchmarks
|
|
||||||
{
|
|
||||||
private readonly Vector2[] directions;
|
|
||||||
// Consumer is for IEnumerables.
|
|
||||||
private readonly Consumer consumer = new();
|
|
||||||
|
|
||||||
public Benchmarks()
|
|
||||||
{
|
|
||||||
//moves = new[]
|
|
||||||
//{
|
|
||||||
// // P1 Rook
|
|
||||||
// new Move { From = new Vector2(7, 1), To = new Vector2(4, 1) },
|
|
||||||
// // P2 Gold
|
|
||||||
// new Move { From = new Vector2(3, 8), To = new Vector2(2, 7) },
|
|
||||||
// // P1 Pawn
|
|
||||||
// new Move { From = new Vector2(4, 2), To = new Vector2(4, 3) },
|
|
||||||
// // P2 other Gold
|
|
||||||
// new Move { From = new Vector2(5, 8), To = new Vector2(6, 7) },
|
|
||||||
// // P1 same Pawn
|
|
||||||
// new Move { From = new Vector2(4, 3), To = new Vector2(4, 4) },
|
|
||||||
// // P2 Pawn
|
|
||||||
// new Move { From = new Vector2(4, 6), To = new Vector2(4, 5) },
|
|
||||||
// // P1 Pawn takes P2 Pawn
|
|
||||||
// new Move { From = new Vector2(4, 4), To = new Vector2(4, 5) },
|
|
||||||
// // P2 King
|
|
||||||
// new Move { From = new Vector2(4, 8), To = new Vector2(4, 7) },
|
|
||||||
// // P1 Pawn promotes
|
|
||||||
// new Move { From = new Vector2(4, 5), To = new Vector2(4, 6), IsPromotion = true },
|
|
||||||
// // P2 King retreat
|
|
||||||
// new Move { From = new Vector2(4, 7), To = new Vector2(4, 8) },
|
|
||||||
//};
|
|
||||||
//var rand = new Random();
|
|
||||||
|
|
||||||
//directions = new Vector2[10];
|
|
||||||
//for (var n = 0; n < 10; n++) directions[n] = new Vector2(rand.Next(-2, 2), rand.Next(-2, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public void One()
|
|
||||||
{
|
|
||||||
for(var i=0; i<10000; i++)
|
|
||||||
{
|
|
||||||
Guid.NewGuid();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//[Benchmark]
|
|
||||||
public void Two()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public Vector2 FindDirection(Vector2[] directions, Vector2 destination)
|
|
||||||
{
|
|
||||||
var smallerDistance = float.MaxValue;
|
|
||||||
Vector2 found = Vector2.Zero;
|
|
||||||
foreach (var d in directions)
|
|
||||||
{
|
|
||||||
var distance = Vector2.Distance(d, destination);
|
|
||||||
if (distance < smallerDistance)
|
|
||||||
{
|
|
||||||
smallerDistance = distance;
|
|
||||||
found = d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Vector2 FindDirectionLinq(Vector2[] directions, Vector2 destination) =>
|
|
||||||
directions.Aggregate((a, b) => Vector2.Distance(destination, a) < Vector2.Distance(destination, b) ? a : b);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public void Directions_A()
|
|
||||||
{
|
|
||||||
FindDirection(directions, new Vector2(8, 7));
|
|
||||||
}
|
|
||||||
[Benchmark]
|
|
||||||
public void Directions_B()
|
|
||||||
{
|
|
||||||
FindDirectionLinq(directions, new Vector2(8, 7));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
BenchmarkRunner.Run<Benchmarks>();
|
|
||||||
Console.WriteLine("Done");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,13 +9,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Gameboard.ShogiUI.Sockets.S
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{F35A56FB-B8D8-4CB7-ABF6-D40049C9B42E}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{F35A56FB-B8D8-4CB7-ABF6-D40049C9B42E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Benchmarking", "Benchmarking\Benchmarking.csproj", "{DADFF5D6-581F-4D69-845D-53ABD6ABF62F}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shogi.Domain", "Shogi.Domain\Shogi.Domain.csproj", "{0211B1E4-20F0-4058-AAC4-3845D19910AF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shogi.Domain", "Shogi.Domain\Shogi.Domain.csproj", "{0211B1E4-20F0-4058-AAC4-3845D19910AF}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shogi.Domain.UnitTests", "Shogi.Domain.UnitTests\Shogi.Domain.UnitTests.csproj", "{F256989E-B6AF-4731-9DB4-88991C40B2CE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shogi.Domain.UnitTests", "Shogi.Domain.UnitTests\Shogi.Domain.UnitTests.csproj", "{F256989E-B6AF-4731-9DB4-88991C40B2CE}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shogi.AcceptanceTests", "Shogi.AcceptanceTests\Shogi.AcceptanceTests.csproj", "{F4AB1C7C-CDE5-465D-81A1-DAF1D97225BA}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shogi.AcceptanceTests", "Shogi.AcceptanceTests\Shogi.AcceptanceTests.csproj", "{F4AB1C7C-CDE5-465D-81A1-DAF1D97225BA}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
@@ -31,10 +29,6 @@ Global
|
|||||||
{FE775DE4-50F0-4C5D-AD2B-01320B1E7086}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{FE775DE4-50F0-4C5D-AD2B-01320B1E7086}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{FE775DE4-50F0-4C5D-AD2B-01320B1E7086}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{FE775DE4-50F0-4C5D-AD2B-01320B1E7086}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{FE775DE4-50F0-4C5D-AD2B-01320B1E7086}.Release|Any CPU.Build.0 = Release|Any CPU
|
{FE775DE4-50F0-4C5D-AD2B-01320B1E7086}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{DADFF5D6-581F-4D69-845D-53ABD6ABF62F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{DADFF5D6-581F-4D69-845D-53ABD6ABF62F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{DADFF5D6-581F-4D69-845D-53ABD6ABF62F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{DADFF5D6-581F-4D69-845D-53ABD6ABF62F}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{0211B1E4-20F0-4058-AAC4-3845D19910AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{0211B1E4-20F0-4058-AAC4-3845D19910AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{0211B1E4-20F0-4058-AAC4-3845D19910AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{0211B1E4-20F0-4058-AAC4-3845D19910AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{0211B1E4-20F0-4058-AAC4-3845D19910AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{0211B1E4-20F0-4058-AAC4-3845D19910AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
18
Gameboard.ShogiUI.Sockets/.config/dotnet-tools.json
Normal file
18
Gameboard.ShogiUI.Sockets/.config/dotnet-tools.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"dotnet-ef": {
|
||||||
|
"version": "6.0.5",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-ef"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"microsoft.dotnet-msidentity": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-msidentity"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,17 +5,20 @@
|
|||||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||||
<AnalysisLevel>5</AnalysisLevel>
|
<AnalysisLevel>5</AnalysisLevel>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<GenerateDocumentationFile>False</GenerateDocumentationFile>
|
||||||
|
<SignAssembly>False</SignAssembly>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentValidation" Version="10.3.6" />
|
<PackageReference Include="FluentValidation" Version="10.3.6" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.AzureAD.UI" Version="6.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.Identity.Web" Version="1.21.1" />
|
<PackageReference Include="Microsoft.Identity.Web" Version="1.21.1" />
|
||||||
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="1.21.1" />
|
<PackageReference Include="Microsoft.Identity.Web.UI" Version="1.16.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="NSwag.AspNetCore" Version="13.15.5" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,5 +1,23 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using Gameboard.ShogiUI.Sockets.Managers;
|
||||||
|
using Gameboard.ShogiUI.Sockets.Managers.ClientActionHandlers;
|
||||||
|
using Gameboard.ShogiUI.Sockets.Repositories;
|
||||||
|
using Gameboard.ShogiUI.Sockets.ServiceModels.Socket;
|
||||||
|
using Gameboard.ShogiUI.Sockets.Services;
|
||||||
|
using Gameboard.ShogiUI.Sockets.Services.RequestValidators;
|
||||||
|
using Microsoft.AspNetCore.Authentication;
|
||||||
|
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.AspNetCore.HttpLogging;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Identity.Web;
|
||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Converters;
|
||||||
|
using Newtonsoft.Json.Serialization;
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Gameboard.ShogiUI.Sockets
|
namespace Gameboard.ShogiUI.Sockets
|
||||||
{
|
{
|
||||||
@@ -7,14 +25,190 @@ namespace Gameboard.ShogiUI.Sockets
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
CreateHostBuilder(args).Build().Run();
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
|
ConfigureAuthentication(builder);
|
||||||
|
ConfigureControllersWithNewtonsoft(builder);
|
||||||
|
ConfigureSwagger(builder);
|
||||||
|
ConfigureDependencyInjection(builder);
|
||||||
|
ConfigureLogging(builder);
|
||||||
|
|
||||||
|
var app = builder.Build();
|
||||||
|
|
||||||
|
app.UseHttpLogging();
|
||||||
|
|
||||||
|
// Configure the HTTP request pipeline.
|
||||||
|
if (app.Environment.IsDevelopment())
|
||||||
|
{
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI(options =>
|
||||||
|
{
|
||||||
|
options.OAuthConfigObject.ClientId = builder.Configuration["AzureAd:ClientId"];
|
||||||
|
options.OAuthConfigObject.UsePkceWithAuthorizationCodeGrant = true;
|
||||||
|
});
|
||||||
|
app.UseHttpsRedirection(); // Apache handles HTTPS in production.
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IHostBuilder CreateHostBuilder(string[] args) =>
|
app.UseAuthentication();
|
||||||
Host.CreateDefaultBuilder(args)
|
app.UseAuthorization();
|
||||||
.ConfigureWebHostDefaults(webBuilder =>
|
|
||||||
|
app.MapControllers();
|
||||||
|
UseCorsAndWebSockets(app);
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void UseCorsAndWebSockets(WebApplication app)
|
||||||
{
|
{
|
||||||
webBuilder.UseStartup<Startup>();
|
// TODO: Figure out how to make a middleware for sockets?
|
||||||
|
var socketService = app.Services.GetRequiredService<ISocketService>();
|
||||||
|
|
||||||
|
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();
|
||||||
|
foreach (var o in origins)
|
||||||
|
socketOptions.AllowedOrigins.Add(o);
|
||||||
|
app.UseCors(opt => opt.WithOrigins(origins).AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("Set-Cookie").AllowCredentials());
|
||||||
|
app.UseWebSockets(socketOptions);
|
||||||
|
app.Use(async (context, next) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("Use websocket");
|
||||||
|
if (context.WebSockets.IsWebSocketRequest)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Is websocket request");
|
||||||
|
await socketService.HandleSocketRequest(context);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await next();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ConfigureLogging(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Services.AddHttpLogging(options =>
|
||||||
|
{
|
||||||
|
options.LoggingFields = HttpLoggingFields.Request;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureAuthentication(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
// Add services to the container.
|
||||||
|
builder.Services
|
||||||
|
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));
|
||||||
|
|
||||||
|
builder.Services
|
||||||
|
.AddAuthentication("CookieOrJwt")
|
||||||
|
.AddPolicyScheme("CookieOrJwt", "Either cookie or jwt", options =>
|
||||||
|
{
|
||||||
|
options.ForwardDefaultSelector = context =>
|
||||||
|
{
|
||||||
|
var bearerAuth = context.Request.Headers["Authorization"].FirstOrDefault()?.StartsWith("Bearer ") ?? false;
|
||||||
|
return bearerAuth
|
||||||
|
? JwtBearerDefaults.AuthenticationScheme
|
||||||
|
: CookieAuthenticationDefaults.AuthenticationScheme;
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.AddCookie(options =>
|
||||||
|
{
|
||||||
|
options.Cookie.Name = "session-id";
|
||||||
|
options.Cookie.SameSite = SameSiteMode.None;
|
||||||
|
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
|
||||||
|
options.SlidingExpiration = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureControllersWithNewtonsoft(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Services
|
||||||
|
.AddControllers()
|
||||||
|
.AddNewtonsoftJson(options =>
|
||||||
|
{
|
||||||
|
options.SerializerSettings.Formatting = Formatting.Indented;
|
||||||
|
options.SerializerSettings.ContractResolver = new DefaultContractResolver
|
||||||
|
{
|
||||||
|
NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true }
|
||||||
|
};
|
||||||
|
options.SerializerSettings.Converters = new[] { new StringEnumConverter() };
|
||||||
|
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
||||||
|
});
|
||||||
|
|
||||||
|
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
|
||||||
|
{
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
ContractResolver = new DefaultContractResolver
|
||||||
|
{
|
||||||
|
NamingStrategy = new CamelCaseNamingStrategy
|
||||||
|
{
|
||||||
|
ProcessDictionaryKeys = true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Converters = new[] { new StringEnumConverter() },
|
||||||
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureDependencyInjection(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
var services = builder.Services;
|
||||||
|
services.AddSingleton<IJoinByCodeHandler, JoinByCodeHandler>();
|
||||||
|
services.AddSingleton<ISocketConnectionManager, SocketConnectionManager>();
|
||||||
|
services.AddSingleton<ISocketTokenCache, SocketTokenCache>();
|
||||||
|
services.AddSingleton<IGameboardManager, GameboardManager>();
|
||||||
|
services.AddSingleton<IValidator<JoinByCodeRequest>, JoinByCodeRequestValidator>();
|
||||||
|
services.AddSingleton<IValidator<JoinGameRequest>, JoinGameRequestValidator>();
|
||||||
|
services.AddSingleton<ISocketService, SocketService>();
|
||||||
|
services.AddTransient<IGameboardRepository, GameboardRepository>();
|
||||||
|
services.AddSingleton<IClaimsTransformation, ShogiUserClaimsTransformer>();
|
||||||
|
services.AddHttpClient("couchdb", c =>
|
||||||
|
{
|
||||||
|
var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes("admin:admin"));
|
||||||
|
c.DefaultRequestHeaders.Add("Accept", "application/json");
|
||||||
|
c.DefaultRequestHeaders.Add("Authorization", $"Basic {base64}");
|
||||||
|
|
||||||
|
var baseUrl = $"{builder.Configuration["AppSettings:CouchDB:Url"]}/{builder.Configuration["AppSettings:CouchDB:Database"]}/";
|
||||||
|
c.BaseAddress = new Uri(baseUrl);
|
||||||
|
});
|
||||||
|
services.AddTransient<IModelMapper, ModelMapper>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ConfigureSwagger(WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
builder.Services.AddSwaggerGen(options =>
|
||||||
|
{
|
||||||
|
var bearerKey = "Bearer";
|
||||||
|
options.AddSecurityDefinition(bearerKey, new OpenApiSecurityScheme
|
||||||
|
{
|
||||||
|
Type = SecuritySchemeType.OAuth2,
|
||||||
|
Flows = new OpenApiOAuthFlows
|
||||||
|
{
|
||||||
|
Implicit = new OpenApiOAuthFlow
|
||||||
|
{
|
||||||
|
AuthorizationUrl = new Uri("https://login.microsoftonline.com/common/oauth2/v2.0/authorize"),
|
||||||
|
TokenUrl = new Uri("https://login.microsoftonline.com/common/oauth2/v2.0/token"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Scheme = "Bearer",
|
||||||
|
BearerFormat = "JWT",
|
||||||
|
In = ParameterLocation.Header,
|
||||||
|
});
|
||||||
|
// This adds the lock symbol next to every route in SwaggerUI.
|
||||||
|
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
|
{
|
||||||
|
{
|
||||||
|
new OpenApiSecurityScheme{ Reference = new OpenApiReference{ Type = ReferenceType.SecurityScheme, Id = bearerKey } },
|
||||||
|
Array.Empty<string>()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||||
|
-->
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<DeleteExistingFiles>true</DeleteExistingFiles>
|
||||||
|
<ExcludeApp_Data>false</ExcludeApp_Data>
|
||||||
|
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
|
||||||
|
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
|
||||||
|
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||||
|
<PublishProvider>FileSystem</PublishProvider>
|
||||||
|
<PublishUrl>bin\Release\net6.0\publish\</PublishUrl>
|
||||||
|
<WebPublishMethod>FileSystem</WebPublishMethod>
|
||||||
|
<SiteUrlToLaunchAfterPublish />
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ProjectGuid>4ff35f9d-e525-46cf-a8a6-a147fe50ad68</ProjectGuid>
|
||||||
|
<SelfContained>false</SelfContained>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"Kestrel": {
|
"Kestrel": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"launchUrl": "/swagger",
|
"launchUrl": "swagger",
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"identityapp1": {
|
||||||
|
"type": "identityapp",
|
||||||
|
"dynamicId": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"identityapp1": {
|
||||||
|
"type": "identityapp.default",
|
||||||
|
"dynamicId": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,210 +0,0 @@
|
|||||||
using FluentValidation;
|
|
||||||
using Gameboard.ShogiUI.Sockets.Managers;
|
|
||||||
using Gameboard.ShogiUI.Sockets.Managers.ClientActionHandlers;
|
|
||||||
using Gameboard.ShogiUI.Sockets.Repositories;
|
|
||||||
using Gameboard.ShogiUI.Sockets.ServiceModels.Socket;
|
|
||||||
using Gameboard.ShogiUI.Sockets.Services;
|
|
||||||
using Gameboard.ShogiUI.Sockets.Services.RequestValidators;
|
|
||||||
using Microsoft.AspNetCore.Authentication;
|
|
||||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Identity.Web;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Converters;
|
|
||||||
using Newtonsoft.Json.Serialization;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Gameboard.ShogiUI.Sockets
|
|
||||||
{
|
|
||||||
public class Startup
|
|
||||||
{
|
|
||||||
public Startup(IConfiguration configuration)
|
|
||||||
{
|
|
||||||
Configuration = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IConfiguration Configuration { get; }
|
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to add services to the container.
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
|
||||||
{
|
|
||||||
services.AddSingleton<IJoinByCodeHandler, JoinByCodeHandler>();
|
|
||||||
services.AddSingleton<ISocketConnectionManager, SocketConnectionManager>();
|
|
||||||
services.AddSingleton<ISocketTokenCache, SocketTokenCache>();
|
|
||||||
services.AddSingleton<IGameboardManager, GameboardManager>();
|
|
||||||
services.AddSingleton<IValidator<JoinByCodeRequest>, JoinByCodeRequestValidator>();
|
|
||||||
services.AddSingleton<IValidator<JoinGameRequest>, JoinGameRequestValidator>();
|
|
||||||
services.AddSingleton<ISocketService, SocketService>();
|
|
||||||
services.AddTransient<IGameboardRepository, GameboardRepository>();
|
|
||||||
services.AddSingleton<IClaimsTransformation, ShogiUserClaimsTransformer>();
|
|
||||||
services.AddHttpClient("couchdb", c =>
|
|
||||||
{
|
|
||||||
var base64 = Convert.ToBase64String(Encoding.UTF8.GetBytes("admin:admin"));
|
|
||||||
c.DefaultRequestHeaders.Add("Accept", "application/json");
|
|
||||||
c.DefaultRequestHeaders.Add("Authorization", $"Basic {base64}");
|
|
||||||
|
|
||||||
var baseUrl = $"{Configuration["AppSettings:CouchDB:Url"]}/{Configuration["AppSettings:CouchDB:Database"]}/";
|
|
||||||
c.BaseAddress = new Uri(baseUrl);
|
|
||||||
});
|
|
||||||
services.AddTransient<IModelMapper, ModelMapper>();
|
|
||||||
|
|
||||||
services
|
|
||||||
.AddControllers()
|
|
||||||
.AddNewtonsoftJson(options =>
|
|
||||||
{
|
|
||||||
options.SerializerSettings.Formatting = Formatting.Indented;
|
|
||||||
options.SerializerSettings.ContractResolver = new DefaultContractResolver
|
|
||||||
{
|
|
||||||
NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true }
|
|
||||||
};
|
|
||||||
options.SerializerSettings.Converters = new[] { new StringEnumConverter() };
|
|
||||||
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddAuthentication("CookieOrJwt")
|
|
||||||
.AddPolicyScheme("CookieOrJwt", "Either cookie or jwt", options =>
|
|
||||||
{
|
|
||||||
options.ForwardDefaultSelector = context =>
|
|
||||||
{
|
|
||||||
var bearerAuth = context.Request.Headers["Authorization"].FirstOrDefault()?.StartsWith("Bearer ") ?? false;
|
|
||||||
return bearerAuth
|
|
||||||
? JwtBearerDefaults.AuthenticationScheme
|
|
||||||
: CookieAuthenticationDefaults.AuthenticationScheme;
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.AddCookie(options =>
|
|
||||||
{
|
|
||||||
options.Cookie.Name = "session-id";
|
|
||||||
options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
|
|
||||||
options.Cookie.SecurePolicy = Microsoft.AspNetCore.Http.CookieSecurePolicy.Always;
|
|
||||||
options.SlidingExpiration = true;
|
|
||||||
})
|
|
||||||
.AddMicrosoftIdentityWebApi(Configuration);
|
|
||||||
|
|
||||||
services.AddSwaggerDocument(config =>
|
|
||||||
{
|
|
||||||
// This just ensures anyone with a microsoft account can make API calls.
|
|
||||||
config.AddSecurity("bearer", new NSwag.OpenApiSecurityScheme
|
|
||||||
{
|
|
||||||
Type = NSwag.OpenApiSecuritySchemeType.OAuth2,
|
|
||||||
Flow = NSwag.OpenApiOAuth2Flow.Implicit,
|
|
||||||
AuthorizationUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
||||||
TokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
||||||
Scopes = new Dictionary<string, string> {
|
|
||||||
{ "api://c1e94676-cab0-42ba-8b6c-9532b8486fff/access_as_user", "The scope" },
|
|
||||||
{ "api://c1e94676-cab0-42ba-8b6c-9532b8486fff/ShogiAdmin", "Admin scope" }
|
|
||||||
},
|
|
||||||
Scheme = "bearer",
|
|
||||||
BearerFormat = "JWT",
|
|
||||||
In = NSwag.OpenApiSecurityApiKeyLocation.Header,
|
|
||||||
});
|
|
||||||
config.PostProcess = document =>
|
|
||||||
{
|
|
||||||
document.Info.Title = "Gameboard.ShogiUI.Sockets";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
services.AddHttpLogging(options =>
|
|
||||||
{
|
|
||||||
options.LoggingFields = Microsoft.AspNetCore.HttpLogging.HttpLoggingFields.Request;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
|
||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISocketService socketConnectionManager)
|
|
||||||
{
|
|
||||||
app.UseHttpLogging();
|
|
||||||
|
|
||||||
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();
|
|
||||||
foreach (var o in origins)
|
|
||||||
socketOptions.AllowedOrigins.Add(o);
|
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
|
||||||
{
|
|
||||||
app.UseDeveloperExceptionPage();
|
|
||||||
//var client = PublicClientApplicationBuilder
|
|
||||||
// .Create(Configuration["AzureAd:ClientId"])
|
|
||||||
// .WithLogging(
|
|
||||||
// (level, message, pii) =>
|
|
||||||
// {
|
|
||||||
// Console.WriteLine(message);
|
|
||||||
// },
|
|
||||||
// LogLevel.Verbose,
|
|
||||||
// true,
|
|
||||||
// true
|
|
||||||
// )
|
|
||||||
// .Build();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Disable this because Apache handles HTTPS in production.
|
|
||||||
//app.UseHsts();
|
|
||||||
}
|
|
||||||
app
|
|
||||||
//.UseRequestResponseLogging()
|
|
||||||
.UseCors(opt => opt.WithOrigins(origins).AllowAnyMethod().AllowAnyHeader().WithExposedHeaders("Set-Cookie").AllowCredentials())
|
|
||||||
.UseRouting()
|
|
||||||
.UseAuthentication()
|
|
||||||
.UseAuthorization()
|
|
||||||
.UseOpenApi()
|
|
||||||
.UseSwaggerUi3(config =>
|
|
||||||
{
|
|
||||||
config.OAuth2Client = new NSwag.AspNetCore.OAuth2ClientSettings()
|
|
||||||
{
|
|
||||||
ClientId = "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
|
||||||
UsePkceWithAuthorizationCodeGrant = true
|
|
||||||
};
|
|
||||||
config.TransformToExternalPath = (route, request) =>
|
|
||||||
{
|
|
||||||
return request.Host.HasValue && request.Host.Value.Contains("localhost")
|
|
||||||
? route
|
|
||||||
: $"/Gameboard.ShogiUI.Sockets{route}";
|
|
||||||
};
|
|
||||||
//config.WithCredentials = true;
|
|
||||||
})
|
|
||||||
.UseWebSockets(socketOptions)
|
|
||||||
.UseEndpoints(endpoints =>
|
|
||||||
{
|
|
||||||
endpoints.MapControllers();
|
|
||||||
})
|
|
||||||
.Use(async (context, next) =>
|
|
||||||
{
|
|
||||||
if (context.WebSockets.IsWebSocketRequest)
|
|
||||||
{
|
|
||||||
await socketConnectionManager.HandleSocketRequest(context);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await next();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
|
|
||||||
{
|
|
||||||
Formatting = Formatting.Indented,
|
|
||||||
ContractResolver = new DefaultContractResolver
|
|
||||||
{
|
|
||||||
NamingStrategy = new CamelCaseNamingStrategy
|
|
||||||
{
|
|
||||||
ProcessDictionaryKeys = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Converters = new[] { new StringEnumConverter() },
|
|
||||||
NullValueHandling = NullValueHandling.Ignore,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -14,10 +14,20 @@
|
|||||||
},
|
},
|
||||||
"AzureAd": {
|
"AzureAd": {
|
||||||
"Instance": "https://login.microsoftonline.com/",
|
"Instance": "https://login.microsoftonline.com/",
|
||||||
|
"Domain": "Hauthlive.onmicrosoft.com",
|
||||||
|
"TenantId": "d6019544-c403-415c-8e96-50009635b6aa",
|
||||||
"ClientId": "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
"ClientId": "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
||||||
"TenantId": "common",
|
"Scopes": "",
|
||||||
|
"CallbackPath": "/signin-oidc"
|
||||||
|
},
|
||||||
|
"AzureAd2": {
|
||||||
|
"Instance": "https://login.microsoftonline.com/",
|
||||||
|
"ClientId": "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
||||||
|
"TenantId": "d6019544-c403-415c-8e96-50009635b6aa",
|
||||||
"Audience": "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
"Audience": "c1e94676-cab0-42ba-8b6c-9532b8486fff",
|
||||||
"ClientSecret": ""
|
"ClientSecret": "",
|
||||||
|
"Domain": "Hauthlive.onmicrosoft.com",
|
||||||
|
"CallbackPath": "/signin-oidc"
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*"
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user