using Gameboard.ShogiUI.Sockets.Repositories.RepositoryManagers; using Gameboard.ShogiUI.Sockets.Extensions; 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 Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; using System.Linq; using Gameboard.ShogiUI.Sockets.Managers; using Gameboard.ShogiUI.Sockets.Managers.ClientActionHandlers; using Gameboard.ShogiUI.Sockets.Repositories; using Gameboard.ShogiUI.Sockets.Repositories.Utility; using Gameboard.ShogiUI.Sockets.ServiceModels.Socket.Types; 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) { // Socket ActionHandlers services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); // Managers services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddScoped(); services.AddSingleton(); services.AddSingleton(sp => action => { return action switch { ClientAction.ListGames => sp.GetService(), ClientAction.CreateGame => sp.GetService(), ClientAction.JoinGame => sp.GetService(), ClientAction.JoinByCode => sp.GetService(), ClientAction.LoadGame => sp.GetService(), ClientAction.Move => sp.GetService(), _ => throw new KeyNotFoundException($"Unable to resolve {nameof(IActionHandler)} for {nameof(ClientAction)} {action}"), }; }); // Repositories services.AddTransient(); services.AddSingleton(); services.AddControllers(); services .AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.Authority = "https://login.microsoftonline.com/9188040d-6c67-4c5b-b112-36a304b66dad/v2.0"; options.Audience = "935df672-efa6-45fa-b2e8-b76dfd65a122"; options.TokenValidationParameters.ValidateIssuer = true; options.TokenValidationParameters.ValidateAudience = true; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISocketConnectionManager socketConnectionManager) { var origins = new[] { "http://localhost:3000", "https://localhost:3000", "http://127.0.0.1:3000", "https://127.0.0.1:3000", "https://dev.lucaserver.space", "https://lucaserver.space" }; var socketOptions = new WebSocketOptions(); foreach (var o in origins) socketOptions.AllowedOrigins.Add(o); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app .UseRequestResponseLogging() .UseCors( opt => opt .WithOrigins(origins) .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials() ) .UseRouting() .UseAuthentication() .UseAuthorization() .UseWebSockets(socketOptions) .UseEndpoints(endpoints => { endpoints.MapControllers(); }) .Use(async (context, next) => { var isUpgradeHeader = context .Request .Headers .Any(h => h.Key.Contains("upgrade", StringComparison.InvariantCultureIgnoreCase) && h.Value.ToString().Contains("websocket", StringComparison.InvariantCultureIgnoreCase)); if (isUpgradeHeader) { await socketConnectionManager.HandleSocketRequest(context); } else { await next(); } }); JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Formatting = Formatting.Indented, ContractResolver = new DefaultContractResolver { NamingStrategy = new CamelCaseNamingStrategy(), }, Converters = new[] { new StringEnumConverter() }, NullValueHandling = NullValueHandling.Ignore }; } } }