using System.Globalization; using System.Reflection; using System.Text; using System.Text.Json.Serialization; using Amazon.DynamoDBv2.DocumentModel; using Asp.Versioning; using JwtRoleAuthentication.Services; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Localization; using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.Filters; using Swashbuckle.AspNetCore.SwaggerGen; using Microsoft.Extensions.Configuration; using Microsoft.AspNetCore.HttpLogging; using StackExchange.Redis; using ServerCore; using ServerBase; using ServerCommon; using UGQApiServer.Auth; using UGQApiServer.Settings; using UGQApiServer.Storage; using UGQApiServer.UGQData; using UGQDataAccess.Settings; using UGQDataAccess.Extensions; using UGQApiServer.Controllers.Common; using UGQDataAccess.Service; namespace UGQApiServer.Extensions; public class AcceptLanguageHeaderFilter : IOperationFilter { public void Apply(OpenApiOperation operation, OperationFilterContext context) { if (operation == null) { throw new Exception("Invalid operation"); } operation.Parameters.Add(new OpenApiParameter { In = ParameterLocation.Header, Name = "accept-language", Description = "pass the locale here: examples like => en-US,en,ko-KR,ko,ja-JP,ja", Schema = new OpenApiSchema { Type = "String" }, }); } } public static class UGQApiExtentions { public static async Task AddUGQApiExtention(this IServiceCollection services, IConfiguration configuration) { // Add services to the container. services.AddControllers().AddJsonOptions(x => { // serialize enums as strings in api responses (e.g. Role) x.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); x.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }); Log.getLogger().info("AddJsonOptions"); services.ConfigureHttpJsonOptions(options => { // options.SerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.SerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; }); Log.getLogger().info("ConfigureHttpJsonOptions"); services.Configure(options => { var supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("en"), new CultureInfo("ko-KR"), new CultureInfo("ko"), new CultureInfo("ja-JP"), new CultureInfo("ja"), }; options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US"); options.RequestCultureProviders.Insert(0, new AcceptLanguageHeaderRequestCultureProvider()); }); Log.getLogger().info("RequestLocalizationOptions"); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle services.AddEndpointsApiExplorer(); services.AddSwaggerGen(options => { options.OperationFilter(); options.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme { Name = "Authorization", Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http, Scheme = "Bearer", BearerFormat = "JWT", In = Microsoft.OpenApi.Models.ParameterLocation.Header, Description = "JWT Authorization header using the Bearer scheme." }); options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement { { new Microsoft.OpenApi.Models.OpenApiSecurityScheme { Reference = new Microsoft.OpenApi.Models.OpenApiReference { Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme, Id = "Bearer" } }, new string [] {} } }); // using System.Reflection; // var xmlFilename = $"{Assembly.GetEntryAssembly()?.GetName().Name ?? string.Empty}.xml"; // ÀÌ ÇÁ·ÎÁ§Æ® À̸§À¸·Î ÇØ¾ß Comment°¡ ·Îµå µÈ´Ù. var xmlFilename = "UGQApiServer.xml"; options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); options.OperationFilter(); options.SwaggerDoc("v1", new OpenApiInfo { Title = "UGQApiServer", Version = "v1" }); options.SwaggerDoc("ingame", new OpenApiInfo { Title = "InGame Api", Version = "ingame" }); options.SwaggerDoc("admin", new OpenApiInfo { Title = "Admin Api", Version = "admin" }); options.SwaggerDoc("development", new OpenApiInfo { Title = "Development Api", Version = "development" }); }); Log.getLogger().info("AddSwaggerGen"); services.AddApiVersioning(x => { x.DefaultApiVersion = new ApiVersion(1, 0); x.AssumeDefaultVersionWhenUnspecified = true; x.ReportApiVersions = true; }) .AddApiExplorer(x => { x.GroupNameFormat = "'v'VVV"; x.SubstituteApiVersionInUrl = true; }); Log.getLogger().info("AddApiVersioning"); services.Configure(configuration.GetSection("JWT")); var jwtSettings = new JWTSettings(); configuration.Bind("JWT", jwtSettings); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.IncludeErrorDetails = true; options.TokenValidationParameters = new TokenValidationParameters() { ClockSkew = TimeSpan.Zero, ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = jwtSettings.ValidIssuer, ValidAudience = jwtSettings.ValidAudience, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Secret) ), }; }); Log.getLogger().info("JWT"); MetaData.Instance.LoadTableAll(); Log.getLogger().info("LoadTableAll"); await services.AddUGQDataAccess(configuration); Log.getLogger().info("AddUGQDataAccess"); services.AddSingleton(provider => { var inGameService = provider.GetRequiredService(); var ugqMetaData = new UGQMetaData(inGameService); ugqMetaData.init(); return ugqMetaData; }); Log.getLogger().info("UGQMetaData"); services.Configure(configuration.GetSection("S3")); services.AddSingleton(); services.AddSingleton(); Log.getLogger().info("S3StorageService"); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(ConnectionMultiplexer.Connect(configuration["Redis"]!)); Log.getLogger().info("Redis"); services.AddSingleton(_ => { var dynamoDbClient = new DynamoDbClient(); var settings = configuration.GetSection("DynamoDb").Get(); (var error_code, var table_names) = ServerConfigHelper.getDynamoDbTableNamesWithServiceType(settings?.TablePostfix ?? string.Empty); ConditionValidCheckHelper.throwIfFalseWithCondition(() => ServerErrorCode.Success == error_code, () => $"Failed to ServerConfigHelper.getDynamoDbTableNamesWithServiceType() !!! : errorCode:{error_code}"); if (settings != null) { var local = !string.IsNullOrEmpty(settings.Url); dynamoDbClient.connectToDb( table_names, local, settings.Url ?? string.Empty , settings.AccessKey, settings.SecretKey, settings.Region ); } dynamoDbClient.createDBIfNotExists(false).GetAwaiter().GetResult(); CurrencyControlHelper.setDbConnector(dynamoDbClient); return dynamoDbClient; }); Log.getLogger().info("DynamoDbClient"); services.AddSingleton(); services.AddSingleton(); services.AddCors(options => options.AddPolicy("Everything", policy => { policy .AllowAnyOrigin() .AllowAnyHeader() .AllowAnyMethod(); })); Log.getLogger().info("AddCors"); services.AddHealthChecks(); Log.getLogger().info("AddHealthChecks"); /* services.AddHttpLogging(o => { o.LoggingFields = HttpLoggingFields.RequestBody | HttpLoggingFields.ResponseBody; o.RequestBodyLogLimit = 4096; o.ResponseBodyLogLimit = 4096; }); Log.getLogger().info("AddHttpLogging"); */ } }