using System; using FluentValidation; using FluentValidation.AspNetCore; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.ApplicationParts; using Microsoft.AspNetCore.Mvc.Razor; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using SharedLibraryCore; using SharedLibraryCore.Configuration; using SharedLibraryCore.Dtos; using SharedLibraryCore.Dtos.Meta.Responses; using SharedLibraryCore.Interfaces; using SharedLibraryCore.Services; using Stats.Dtos; using Stats.Helpers; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Reflection; using System.Threading.Tasks; using Data.Abstractions; using Data.Helpers; using IW4MAdmin.Plugins.Stats.Config; using Stats.Client.Abstractions; using Stats.Config; using WebfrontCore.Controllers.API.Validation; using WebfrontCore.Middleware; namespace WebfrontCore { public class Startup { // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // allow CORS services.AddCors(_options => { _options.AddPolicy("AllowAll", _builder => { _builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); }); }); IEnumerable pluginAssemblies() { string pluginDir = $"{Utilities.OperatingDirectory}Plugins{Path.DirectorySeparatorChar}"; if (Directory.Exists(pluginDir)) { var dllFileNames = Directory.GetFiles($"{Utilities.OperatingDirectory}Plugins{Path.DirectorySeparatorChar}", "*.dll"); return dllFileNames.Select(_file => Assembly.LoadFrom(_file)); } return Enumerable.Empty(); } // Add framework services. var mvcBuilder = services.AddMvc(_options => _options.SuppressAsyncSuffixInActionNames = false) .AddFluentValidation() .ConfigureApplicationPartManager(_partManager => { foreach (var assembly in pluginAssemblies()) { if (assembly.FullName.Contains("Views")) { _partManager.ApplicationParts.Add(new CompiledRazorAssemblyPart(assembly)); } else if (assembly.FullName.Contains("Web")) { _partManager.ApplicationParts.Add(new AssemblyPart(assembly)); } } }); #if DEBUG { mvcBuilder = mvcBuilder.AddRazorRuntimeCompilation(); services.Configure(_options => { _options.ViewLocationFormats.Add(@"/Views/Plugins/{1}/{0}" + RazorViewEngine.ViewExtension); _options.ViewLocationFormats.Add("/Views/Plugins/Stats/Advanced.cshtml"); }); } #endif foreach (var asm in pluginAssemblies()) { mvcBuilder.AddApplicationPart(asm); } services.AddHttpContextAccessor(); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options => { options.AccessDeniedPath = "/"; options.LoginPath = "/"; }); services.AddSingleton(Program.Manager); services.AddSingleton, ChatResourceQueryHelper>(); services.AddTransient, FindClientRequestValidator>(); services.AddSingleton, ClientService>(); services.AddSingleton, StatsResourceQueryHelper>(); services.AddSingleton, AdvancedClientStatsResourceQueryHelper>(); services.AddSingleton(typeof(IDataValueCache<,>), typeof(DataValueCache<,>)); // todo: this needs to be handled more gracefully services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService>()); #pragma warning disable CS0618 services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); #pragma warning restore CS0618 services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton( Program.ApplicationServiceProvider.GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider .GetRequiredService>()); services.AddSingleton(Program.ApplicationServiceProvider .GetRequiredService()); services.AddSingleton(Program.ApplicationServiceProvider.GetRequiredService()); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider) { app.UseStatusCodePages(_context => { if (_context.HttpContext.Response.StatusCode == (int)HttpStatusCode.NotFound) { _context.HttpContext.Response.Redirect($"/Home/ResponseStatusCode?statusCode={_context.HttpContext.Response.StatusCode}"); } return Task.CompletedTask; }); if (env.EnvironmentName == "Development") { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } if (Program.Manager.GetApplicationSettings().Configuration().EnableWebfrontConnectionWhitelist) { app.UseMiddleware(serviceProvider.GetService>(), serviceProvider.GetRequiredService().WebfrontConnectionWhitelist); } app.UseStaticFiles(); app.UseAuthentication(); app.UseCors("AllowAll"); // prevents banned/demoted users from keeping their claims app.UseMiddleware(Program.Manager); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); }); } } }