using System; using System.Globalization; using System.IO; using System.Reflection; using System.Text; using System.Threading.Tasks; using Hangfire; using Hangfire.PostgreSql; using MEU.API.Config; using MEU.API.MiddleWare; //using MEU.API.Models; //using MEU.API.Services.CronJobs; //using MEU.API.Services.NotificationHub; using MEU.API.Utils; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Server.Kestrel.Core; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using Microsoft.IdentityModel.Logging; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Newtonsoft.Json; using NLog; using Sieve.Models; using Sieve.Services; namespace MEU.API { public class Startup { private IWebHostEnvironment CurrentEnvironment { get; set; } public Startup(Microsoft.AspNetCore.Hosting.IWebHostEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true); Configuration = builder.Build(); CurrentEnvironment = env; } 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) { if (CurrentEnvironment.IsDevelopment()) { ConfigEnvironment.load("development"); } else if (CurrentEnvironment.IsStaging()) { ConfigEnvironment.load("staging"); } else { ConfigEnvironment.load("production"); } services.AddHangfire(x => x.UsePostgreSqlStorage(ConfigEnvironment.CONECTION_STRING)); services.AddHangfireServer(); //services.AddCronJob<CronJobSyncInOutLog>(c => //{ // c.TimeZoneInfo = TimeZoneInfo.Local; // c.CronExpression = @"1/1 * * * *"; //}); services.AddCors(o => o.AddPolicy("MyPolicy", builder => { builder .SetIsOriginAllowedToAllowWildcardSubdomains() .WithOrigins("http://localhost:4200", "https://localhost:4200", "http://localhost:4000", "https://localhost:4000", "http://*.meu-solutions.com", "https://*.meu-solutions.com", "http://localhost:8000", "https://localhost:8000", "http://localhost:8080", "https://localhost:8080", "http://27.74.255.96:90", "http://27.74.255.96:8090", "https://27.74.255.96:8090", "http://192.168.0.188:8090", "https://192.168.0.188:8090") .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); })); services.Configure<IISServerOptions>(options => { options.AllowSynchronousIO = true; }); // If using Kestrel: services.Configure<KestrelServerOptions>(options => { options.AllowSynchronousIO = true; options.Limits.MaxRequestBodySize = null; }); services.Configure<FormOptions>(options => { options.ValueLengthLimit = int.MaxValue; options.MultipartBodyLengthLimit = int.MaxValue; // if don't set default value is: 128 MB options.MultipartHeadersLengthLimit = int.MaxValue; }); services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(x => { x.Events = new JwtBearerEvents { OnMessageReceived = context => { var accessToken = context.Request.Query["access_token"]; // If the request is for our hub... var path = context.HttpContext.Request.Path; if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/api/notificationhub"))) { // Read the token out of the query string context.Token = accessToken; } return Task.CompletedTask; } }; #region verify user is existed //x.Events = new JwtBearerEvents() //{ // OnAuthenticationFailed = context => // { // if (context.Exception is SecurityTokenExpiredException) // { // context.Response.StatusCode = StatusCodes.Status401Unauthorized; // context.Response.ContentType = "application/json; charset=utf-8"; // var result = JsonConvert.SerializeObject(new { status = "Unauthorized", message = "Token expired." }); // context.Response.WriteAsync(result).Wait(); // return Task.CompletedTask; // } // else // { // context.Response.StatusCode = StatusCodes.Status401Unauthorized; // context.Response.ContentType = "application/json; charset=utf-8"; // var result = JsonConvert.SerializeObject(new { status = "Unauthorized", message = "An error occurred processing your authentication." }); // context.Response.WriteAsync(result).Wait(); // return Task.CompletedTask; // } // } //}; //x.Events = new JwtBearerEvents //{ // OnTokenValidated = context => // { // var userService = context.HttpContext.RequestServices.GetRequiredService<IUserService>(); // var userId = int.Parse(context.Principal.Identity.Name); // var user = userService.GetById(userId); // if (user == null) // { // // return unauthorized if user no longer exists // context.Fail("Unauthorized"); // } // return Task.CompletedTask; // } //}; #endregion x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(ConfigEnvironment.TOKEN_ENCRYPTED_KEY)), ValidateIssuer = false, ValidateAudience = false }; }); services.AddSignalR(o => { o.EnableDetailedErrors = true; o.MaximumReceiveMessageSize = 102400000; }); //services.AddSingleton<NotificationHub>(); services.AddControllers() .AddMvcOptions(options => { options.ModelBinderProviders.Insert(0, new DateTimeModelBinderProvider()); }); services.Configure<FormOptions>(x => { x.ValueLengthLimit = int.MaxValue; x.MultipartBodyLengthLimit = int.MaxValue; // In case of multipart }); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddScoped<SieveProcessor>(); services.Configure<SieveOptions>(Configuration.GetSection("Sieve")); services.AddControllers().AddNewtonsoftJson(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); //services.AddDbContext<meuerpContext>(opt => opt.UseNpgsql(Configuration.GetConnectionString("DefaultConnection"))); // Disable swagger on Production env if (!CurrentEnvironment.IsProduction()) { // Register the Swagger generator, defining 1 or more Swagger documents services.AddSwaggerGen(c => { c.SchemaFilter<ApplyCustomSchemaFilters>(); c.SwaggerDoc("v1", new OpenApiInfo { Title = "MEU ERP API", Version = "v1" }); // Set the comments path for the Swagger JSON and UI. try { var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); c.IncludeXmlComments(xmlPath); } catch (Exception) { } //c.DocumentFilter<SwaggerDocumentFilter>(); c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme { In = ParameterLocation.Header, Description = "Usage: Bearer $token", Name = "Authorization", Type = SecuritySchemeType.ApiKey }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" } }, new string[] { } } }); }); //services.AddSwaggerGenNewtonsoftSupport(); } } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { AppHttpContext.Services = app.ApplicationServices; IdentityModelEventSource.ShowPII = true; app.UseHangfireDashboard(); //Delare static physical File provider app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")), RequestPath = "/StaticFiles", OnPrepareResponse = context => { context.Context.Response.Headers["Access-Control-Allow-Origin"] = "*"; } }); //Create public folder if not exist //if (!Directory.Exists(MEU.FILE.Config.rootPath + ConfigEnvironment.STORAGE_PUBLIC)) //{ // Directory.CreateDirectory(MEU.FILE.Config.rootPath + ConfigEnvironment.STORAGE_PUBLIC); //} //Declare statis file path app.UseStaticFiles(new StaticFileOptions { //FileProvider = new PhysicalFileProvider(MEU.FILE.Config.rootPath + ConfigEnvironment.STORAGE_PUBLIC), RequestPath = "/public", ServeUnknownFileTypes = true, OnPrepareResponse = context => { context.Context.Response.Headers["Access-Control-Allow-Origin"] = "*"; } }); // Disable swagger on Production env if (!env.IsProduction()) { // Enable middleware to serve generated Swagger as a JSON endpoint. app.UseSwagger(); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // specifying the Swagger JSON endpoint. app.UseSwaggerUI(c => { c.InjectJavascript("/StaticFiles/js/jquery-3.4.1.min.js"); c.InjectJavascript("/StaticFiles/js/swagger-auth-custom.js"); c.DocExpansion(Swashbuckle.AspNetCore.SwaggerUI.DocExpansion.None); c.SwaggerEndpoint("/swagger/v1/swagger.json", "MEU ERP API V1"); }); } if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //Localization var supportedCultures = new[] { new CultureInfo("vi-VN") }; app.UseRequestLocalization(new RequestLocalizationOptions { DefaultRequestCulture = new RequestCulture("vi-VN"), SupportedCultures = supportedCultures, SupportedUICultures = supportedCultures }); //app.UseHttpsRedirection(); app.UseRouting(); app.UseCors("MyPolicy"); app.UseAuthentication(); app.Use(async (context, next) => { context.Response.Headers.Add("X-Xss-Protection", "1"); await next(); }); app.Use(async (context, next) => { // Check if the request endpoint is an upload API? If yes, increase the bufferLimit to 500Mb to avoid exception if (context.Request.Path.Value.ToString().ToLower().Contains("upload")) { context.Request.EnableBuffering(bufferThreshold: 1024 * 45, bufferLimit: 1024 * 500000); } else { context.Request.EnableBuffering(bufferThreshold: 1024 * 45, bufferLimit: 1024 * 100); } await next(); }); app.UseAuthorization(); app.UseMiddleware(typeof(SignatureMiddleware)); app.UseMiddleware(typeof(AddErrorLogToHeaderMiddelware)); //Return exception content when 500 //app.UseMiddleware(typeof(ErrorHandlingMiddleware)); app.UseEndpoints(endpoints => { endpoints.MapControllers(); //endpoints.MapHub<NotificationHub>("/api/notificationhub"); }); } } }