using UserManagement.Api.Helpers; using UserManagement.API.Helpers.Mapping; using UserManagement.Data; using UserManagement.Data.Dto; using UserManagement.Domain; using UserManagement.Helper; using UserManagement.MediatR.PipeLineBehavior; using FluentValidation; using MediatR; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.ResponseCompression; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.OpenApi.Models; using Newtonsoft.Json; using System; using System.IO; using System.Linq; using System.Reflection; using UserManagement.Repository; using Hangfire; using Hangfire.Dashboard; namespace UserManagement.API { 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) { var assembly = AppDomain.CurrentDomain.Load("UserManagement.MediatR"); services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(assembly)); services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); services.AddValidatorsFromAssemblies(Enumerable.Repeat(assembly, 1)); services.AddSingleton(); JwtSettings settings; settings = GetJwtSettings(); services.AddSingleton(settings); services.AddSingleton(new PathHelper(Configuration)); services.AddSingleton(); services.AddScoped(c => new UserInfoToken() { Id = "" }); services.AddDbContextPool(options => { options.UseSqlServer(Configuration.GetConnectionString("UserDbConnectionString")); options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); }); services.AddIdentity() .AddEntityFrameworkStores() .AddDefaultTokenProviders(); services.Configure(options => { options.Password.RequireDigit = false; options.Password.RequiredLength = 5; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = false; options.Password.RequireLowercase = false; }); services.AddSingleton(MapperConfig.GetMapperConfigs()); services.AddDependencyInjection(); services.AddJwtAutheticationConfiguration(settings); services.AddCors(options => { options.AddPolicy("ExposeResponseHeaders", builder => { builder.WithOrigins("http://localhost:4000", "http://localhost:4200", "http://localhost:4201") .WithExposedHeaders("X-Pagination") .AllowAnyHeader() .AllowCredentials() .WithMethods("POST", "PUT", "PATCH", "GET", "DELETE") .SetIsOriginAllowed(host => true); }); }); services.AddSignalR(); services.Configure(options => { options.AutomaticAuthentication = false; }); services.AddResponseCompression(options => { options.Providers.Add(); }); services.AddControllers() .AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local; }); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Version = "v1", Title = "User Management API" }); c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"", Name = "Authorization", In = ParameterLocation.Header, Type = SecuritySchemeType.ApiKey, Scheme = "Bearer" }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new string[] { } } }); //Set the comments path for the Swagger JSON and UI. var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); }); SpaStartup.ConfigureServices(services); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler(appBuilder => { appBuilder.Run(async context => { var exceptionHandlerFeature = context.Features.Get(); if (exceptionHandlerFeature != null) { var logger = loggerFactory.CreateLogger("Global exception logger"); logger.LogError(500, exceptionHandlerFeature.Error, exceptionHandlerFeature.Error.Message); } context.Response.StatusCode = 500; await context.Response.WriteAsync("An unexpected fault happened. Try again later."); }); }); } app.UseSwagger(c => { c.SerializeAsV2 = true; }); app.UseSwaggerUI(c => { c.DefaultModelsExpandDepth(-1); c.SwaggerEndpoint($"v1/swagger.json", "User Management"); c.RoutePrefix = "swagger"; }); app.UseStaticFiles(); app.UseCors("ExposeResponseHeaders"); app.UseHttpsRedirection(); app.UseAuthentication(); app.UseRouting(); app.UseAuthorization(); app.UseResponseCompression(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapHub("/userHub"); }); app.UseHangfireDashboard("/hangfire", new DashboardOptions { Authorization = new[] { new AllowAllUsers() } // Allow custom authorization }); SpaStartup.Configure(app); } public JwtSettings GetJwtSettings() { JwtSettings settings = new JwtSettings(); settings.Key = Configuration["JwtSettings:key"]; settings.Audience = Configuration["JwtSettings:audience"]; settings.Issuer = Configuration["JwtSettings:issuer"]; settings.MinutesToExpiration = Convert.ToInt32( Configuration["JwtSettings:minutesToExpiration"]); return settings; } public class AllowAllUsers : IDashboardAuthorizationFilter { public bool Authorize(DashboardContext context) { return true; // Allow everyone to see the Hangfire Dashboard } } } }