diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index 4c1ac045..a53accd7 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -84,6 +84,9 @@ namespace AyaNova options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc; }); + + + //2019-10-17 METRICS will not work just yet with .netcore 3.1 see here https://github.com/AppMetrics/AppMetrics/issues/480 //awaiting a new release from them //_log.LogDebug("BOOT: init Metrics service"); @@ -149,7 +152,7 @@ namespace AyaNova - // Add service and create Policy with options + // Add service and create Policy with options _log.LogDebug("BOOT: init CORS service"); services.AddCors(options => { @@ -172,40 +175,28 @@ namespace AyaNova options.AssumeDefaultVersionWhenUnspecified = true; options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0"); options.ReportApiVersions = true; - }); + }); services.AddVersionedApiExplorer(options => options.GroupNameFormat = "'v'VVV"); - // services.AddSwaggerGen( - // c => - // { - // c.SwaggerDoc("v8", new OpenApiInfo { Title = "XXX API - V8", Version = "v8" }); - // c.DocInclusionPredicate((docName, apiDesc) => - // { - // if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false; - - // var versions = methodInfo.DeclaringType - // .GetCustomAttributes(true) - // .OfType() - // .SelectMany(attr => attr.Versions); - - // return versions.Any(v => $"v{v.ToString()}" == docName); - // }); - // }); services.AddTransient, ConfigureSwaggerOptions>(); services.AddSwaggerGen( - c=>{ + c => + { - //https://stackoverflow.com/questions/56234504/migrating-to-swashbuckle-aspnetcore-version-5 - //First we define the security scheme - c.AddSecurityDefinition("Bearer", //Name the security scheme - new OpenApiSecurityScheme - { - Description = "JWT Authorization header using the Bearer scheme.", - Type = SecuritySchemeType.Http, //We set the scheme type to http since we're using bearer authentication + // integrate xml comments + c.IncludeXmlComments(XmlCommentsFilePath); + + //https://stackoverflow.com/questions/56234504/migrating-to-swashbuckle-aspnetcore-version-5 + //First we define the security scheme + c.AddSecurityDefinition("Bearer", //Name the security scheme + new OpenApiSecurityScheme + { + Description = "JWT Authorization header using the Bearer scheme.", + Type = SecuritySchemeType.Http, //We set the scheme type to http since we're using bearer authentication Scheme = "bearer" //The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer". }); - c.AddSecurityRequirement(new OpenApiSecurityRequirement{ + c.AddSecurityRequirement(new OpenApiSecurityRequirement{ { new OpenApiSecurityScheme{ Reference = new OpenApiReference{ @@ -362,9 +353,6 @@ namespace AyaNova context.Request.HttpContext.Items["AY_USERNAME"] = u.name; context.Request.HttpContext.Items["AY_USER_ID"] = u.id; context.Request.HttpContext.Items["AY_LOCALE_ID"] = u.localeId; - - - } await next.Invoke(); }); @@ -400,20 +388,6 @@ namespace AyaNova #endregion swagger - - - - - //According to https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-2.2&tabs=visual-studio#migrate-startupconfigure - //replace use mvc with use endpoints - // //USE MVC - // _log.LogDebug("BOOT: pipeline - MVC"); - // app.UseMvc(); - // _log.LogDebug("BOOT: pipeline - ENDPOINTS"); - // app.UseEndpoints(endpoints => { - // endpoints.MapControllers(); - // }); - // ****************************************************************** // ******************** TESTING WIPE DB ***************************** // @@ -513,700 +487,8 @@ namespace AyaNova } } - // static Microsoft.OpenApi.Models.OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) - // { - // var info = new Microsoft.OpenApi.Models.OpenApiInfo() - // { - // Title = $"AyaNova API {description.ApiVersion}", - // Version = description.ApiVersion.ToString() - // }; - - // if (description.IsDeprecated) - // { - // info.Description += " This API version has been deprecated."; - // } - - // return info; - // } - - - - //update for v3 from here https://github.com/microsoft/aspnet-api-versioning/wiki/API-Documentation#aspnet-core - //and example here: https://github.com/microsoft/aspnet-api-versioning/blob/master/samples/aspnetcore/SwaggerSample/ConfigureSwaggerOptions.cs - // public class ConfigureSwaggerOptions : IConfigureOptions - // { - // readonly IApiVersionDescriptionProvider provider; - - // public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) => - // this.provider = provider; - - // public void Configure(SwaggerGenOptions options) - // { - // foreach (var description in provider.ApiVersionDescriptions) - // { - // options.SwaggerDoc( - // description.GroupName, - // new OpenApiInfo() - // { - // Title = $"AyaNova API {description.ApiVersion}", - // Version = description.ApiVersion.ToString(), - // }); - // } - // } - // } #endregion } } - -/* - - -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.AspNetCore.Mvc.ApiExplorer; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; - -using Microsoft.Extensions.Logging; -using Microsoft.EntityFrameworkCore; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.IdentityModel.Tokens; -using Microsoft.Extensions.Hosting; -using Microsoft.AspNetCore.Http; - -using Microsoft.OpenApi.Models; - -using Microsoft.Extensions.Options; -using Swashbuckle.AspNetCore.Swagger; -using Swashbuckle.AspNetCore.SwaggerGen; - - -using AyaNova.Models; -using AyaNova.Util; -using AyaNova.Generator; -using AyaNova.Biz; - - -using Swashbuckle.AspNetCore.SwaggerUI; - -using System.IO; -using System.Reflection; -using System.Linq; -using System; -using System.Collections.Generic; -using Newtonsoft.Json.Serialization; - - -namespace AyaNova -{ - - public class Startup - { - - - ///////////////////////////////////////////////////////////// - // - public Startup(ILogger logger, ILoggerFactory logFactory, Microsoft.AspNetCore.Hosting.IWebHostEnvironment hostingEnvironment) - { - _log = logger; - _hostingEnvironment = hostingEnvironment; - AyaNova.Util.ApplicationLogging.LoggerFactory = logFactory; - //this must be set here - ServerBootConfig.AYANOVA_CONTENT_ROOT_PATH = hostingEnvironment.ContentRootPath; - - } - - private readonly ILogger _log; - private string _connectionString = ""; - private readonly Microsoft.AspNetCore.Hosting.IWebHostEnvironment _hostingEnvironment; - - //////////////////////////////////////////////////////////// - // This method gets called by the runtime. Use this method to add services to the container. - // - public void ConfigureServices(IServiceCollection services) - { - _log.LogDebug("BOOT: initializing services..."); - - - - //Server state service for shutting people out of api - _log.LogDebug("BOOT: init ApiServerState service"); - services.AddSingleton(new AyaNova.Api.ControllerHelpers.ApiServerState()); - - //Init controllers - _log.LogDebug("BOOT: init controllers"); - var MvcBuilder = services.AddControllers(config => - { - config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(AyaNova.Util.ApplicationLogging.LoggerFactory)); - }); - - _log.LogDebug("BOOT: init JSON"); - MvcBuilder.AddNewtonsoftJson(options => - { - options.SerializerSettings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc; - }); - - //2019-10-17 METRICS will not work just yet with .netcore 3.1 see here https://github.com/AppMetrics/AppMetrics/issues/480 - //awaiting a new release from them - //_log.LogDebug("BOOT: init Metrics service"); - //MvcBuilder.AddMetrics(); - - - - - - _log.LogDebug("BOOT: ensuring user and backup folders exist and are separate locations..."); - FileUtil.EnsureUserAndUtilityFoldersExistAndAreNotIdentical(_hostingEnvironment.ContentRootPath); - - #region DATABASE - _connectionString = ServerBootConfig.AYANOVA_DB_CONNECTION; - - //Check DB server exists and can be connected to - _log.LogDebug("BOOT: Testing database server connection..."); - - //parse the connection string properly - DbUtil.ParseConnectionString(_log, _connectionString); - - //Probe for database server - //Will retry every 10 seconds for up to 5 minutes before bailing - if (!DbUtil.DatabaseServerExists(_log, "BOOT: waiting for db server ")) - { - var err = $"BOOT: E1000 - AyaNova can't connect to the database server after trying for 5 minutes (connection string is:\"{DbUtil.DisplayableConnectionString}\")"; - _log.LogCritical(err); - throw new System.ApplicationException(err); - } - - - - _log.LogInformation("BOOT: Connected to database server - {0}", DbUtil.DisplayableConnectionString); - - - //ensure database is ready and present - DbUtil.EnsureDatabaseExists(_log); - - bool LOG_SENSITIVE_DATA = false; - -#if (DEBUG) - // LOG_SENSITIVE_DATA = true; - -#endif - - _log.LogDebug("BOOT: init EF service"); - - services.AddEntityFrameworkNpgsql().AddDbContext( - options => options.UseNpgsql(_connectionString - //,opt => opt.EnableRetryOnFailure()//REMOVED THIS BECAUSE IT WAS INTEFERING WITH TRANSACTIONS BUT THEN DIDN'T USE THE TRANSACTION BUT IT SEEMS FASTER WITHOUT IT AS WELL SO...?? - )//http://www.npgsql.org/efcore/misc.html?q=execution%20strategy#execution-strategy - .ConfigureWarnings(warnings => //https://livebook.manning.com/#!/book/entity-framework-core-in-action/chapter-12/v-10/85 - warnings.Throw( //Throw an exception on client eval, not necessarily an error but a smell - // Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.QueryClientEvaluationWarning - )) - .EnableSensitiveDataLogging(LOG_SENSITIVE_DATA) - ); - - - - - #endregion - - - - - // Add service and create Policy with options - _log.LogDebug("BOOT: init CORS service"); - services.AddCors(options => - { - options.AddPolicy("CorsPolicy", - builder => builder.AllowAnyOrigin() - .AllowAnyMethod() - .AllowAnyHeader() - //.AllowCredentials() - ); - }); - - - - - - #region Swagger - _log.LogDebug("BOOT: init ApiVersioning service"); - // services.AddApiVersioning(o => o.ReportApiVersions = true); - services - .AddApiVersioning(options => - { - options.AssumeDefaultVersionWhenUnspecified = true; - options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0"); - options.ReportApiVersions = true; - }); - - // add the versioned api explorer, which also adds IApiVersionDescriptionProvider service - // note: the specified format code will format the version as "'v'major[.minor][-status]" - _log.LogDebug("BOOT: init ApiExplorer service"); - services.AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV"); - - services.AddTransient, ConfigureSwaggerOptions>(); - - //https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?tabs=visual-studio-code - //https://swagger.io/ - //https://github.com/domaindrivendev/Swashbuckle.AspNetCore - - _log.LogDebug("BOOT: init API explorer service"); - services.AddSwaggerGen( - c => - { - - -// c.DocInclusionPredicate((docName, apiDesc) => -// { -// if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false; - -// var versions = methodInfo.DeclaringType -// .GetCustomAttributes(true) -// .OfType() -// .SelectMany(attr => attr.Versions); - -// return versions.Any(v => $"v{v.ToString()}" == docName); -// }); - - -// c.DocInclusionPredicate((docName, apiDesc) => -// { -// if (!apiDesc.TryGetMethodInfo(out MethodInfo methodInfo)) return false; - -// // Get the MapToApiVersion attributes of the action -// var mapApiVersions = methodInfo -// .GetCustomAttributes(true) -// .OfType() -// .SelectMany(attr => attr.Versions); - -// //if it contains MapToApiVersion attributes, then we should check those as the ApiVersion ones are ignored -// if (mapApiVersions.Any() && mapApiVersions.Any(v => $"v{v.ToString()}" == docName)) -// return true; - -// // Get the ApiVersion attributes of the controller -// var versions = methodInfo.DeclaringType -// .GetCustomAttributes(true) -// .OfType() -// .SelectMany(attr => attr.Versions); - -// return versions.Any(v => $"v{v.ToString()}" == docName); -// }); - - - // resolve the IApiVersionDescriptionProvider service - - //v3 commented this out - // // note: that we have to build a temporary service provider here because one has not been created yet - // var provider = services.BuildServiceProvider().GetRequiredService(); - - // // add a swagger document for each discovered API version - // // note: you might choose to skip or document deprecated API versions differently - // foreach (var description in provider.ApiVersionDescriptions) - // { - // c.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description)); - // } - - // add a custom operation filter which sets default values - //Removed because will no longer compile the SwaggerDefaultValues but may be needed, not sure it's all a bit muddled - c.OperationFilter(); - - // integrate xml comments - c.IncludeXmlComments(XmlCommentsFilePath); - - - - //2019-10-15 - Removed this because apikeyscheme is no longer recognized and it appears it *may* not be necessary... TWT - //If I have any issues with bearer tokens in swagger then this is probably necessary but in a new way - //this is required to allow authentication when testing secure routes via swagger UI - // c.AddSecurityDefinition("Bearer", new ApiKeyScheme - // { - // Description = "JWT Authorization header using the Bearer scheme. Get your token by logging in via the Auth route then enter it here with the \"Bearer \" prefix. Example: \"Bearer {token}\"", - // Name = "Authorization", - // In = "header", - // Type = "apiKey" - - // }); - - - - - - //https://stackoverflow.com/questions/56234504/migrating-to-swashbuckle-aspnetcore-version-5 - //First we define the security scheme - c.AddSecurityDefinition("Bearer", //Name the security scheme - new OpenApiSecurityScheme - { - Description = "JWT Authorization header using the Bearer scheme.", - Type = SecuritySchemeType.Http, //We set the scheme type to http since we're using bearer authentication - Scheme = "bearer" //The name of the HTTP Authorization scheme to be used in the Authorization header. In this case "bearer". - }); - - c.AddSecurityRequirement(new OpenApiSecurityRequirement{ - { - new OpenApiSecurityScheme{ - Reference = new OpenApiReference{ - Id = "Bearer", //The name of the previously defined security scheme. - Type = ReferenceType.SecurityScheme - } - },new List() - } - }); - - - }); - - - #endregion - - - #region JWT AUTHENTICATION - //get the key if specified - var secretKey = ServerBootConfig.AYANOVA_JWT_SECRET; - - //If no key specified make a unique one - //This means the jwt creds won't survive a server reboot - //so in that case users need to specify an AyaNova_JWT_SECRET environment variable - if (string.IsNullOrWhiteSpace(secretKey)) - { - secretKey = Util.Hasher.GenerateSalt(); - } - //WAS "UNLICENSED5G*QQJ8#bQ7$Xr_@sXfHq4" - - - //If secretKey is less than 32 characters, pad it - if (secretKey.Length < 32) - { - secretKey = secretKey.PadRight(32, '-'); - } - - ServerBootConfig.AYANOVA_JWT_SECRET = secretKey; - var signingKey = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes(ServerBootConfig.AYANOVA_JWT_SECRET)); - - _log.LogDebug("BOOT: init Authorization service"); - services.AddAuthentication(options => - { - options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; - options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; - }).AddJwtBearer(options => - { - // options.AutomaticAuthenticate = true; - // options.AutomaticChallenge = true; - options.TokenValidationParameters = new TokenValidationParameters - { - // Token signature will be verified using a private key. - ValidateIssuerSigningKey = true, - RequireSignedTokens = true, - IssuerSigningKey = signingKey, - ValidateIssuer = true, - ValidIssuer = "ayanova.com", - ValidateAudience = false, - //ValidAudience = "http://localhost:7575/" - - // Token will only be valid if not expired yet, with 5 minutes clock skew. - ValidateLifetime = true, - RequireExpirationTime = true, - ClockSkew = new TimeSpan(0, 5, 0), - }; - }); - - - - #endregion - - _log.LogDebug("BOOT: init Generator service"); - services.AddSingleton(); - - - } - - - - //////////////////////////////////////////////////////////// - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - // - public void Configure(IApplicationBuilder app, Microsoft.AspNetCore.Hosting.IWebHostEnvironment env, - AyContext dbContext, IApiVersionDescriptionProvider provider, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider) - { - _log.LogDebug("BOOT: configuring request pipeline..."); - - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - //Store a reference to the dependency injection service for static classes - ServiceProviderProvider.Provider = app.ApplicationServices; - - //Enable ability to handle reverse proxy - app.UseForwardedHeaders(new ForwardedHeadersOptions - { - ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedFor | Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto - }); - - #region STATIC FILES - _log.LogDebug("BOOT: pipeline - static files"); - app.UseDefaultFiles(); - app.UseStaticFiles(); - //Might need the following if the page doesn't update in the client properly - //however the vue build process will automatically uniquify each build file names so maybe not required - // app.UseStaticFiles(new StaticFileOptions - // { - // OnPrepareResponse = context => - // { - // if (context.File.Name == "index.html") - // { - // context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store"); - // context.Context.Response.Headers.Add("Expires", "-1"); - // } - // } - // }); - #endregion - - _log.LogDebug("BOOT: pipeline - ROUTING"); - app.UseRouting();//this wasn't here for 2.2 but added for 3.0, needs to come before the stuff after - - _log.LogDebug("BOOT: pipeline - CORS"); - app.UseCors("CorsPolicy"); - - - #region AUTH / ROLES - _log.LogDebug("BOOT: pipeline - authentication"); - //Use authentication middleware - app.UseAuthentication(); - - _log.LogDebug("BOOT: pipeline - authorization"); - app.UseAuthorization(); - - - //Custom middleware to get user roles and put them into the request so - //they can be authorized in routes. - app.Use(async (context, next) => - { - if (!context.User.Identity.IsAuthenticated) - { - context.Request.HttpContext.Items["AY_ROLES"] = 0; - } - else - { - //Get user ID from claims - long userId = Convert.ToInt64(context.User.FindFirst(c => c.Type == "id").Value); - - //Get the database context - var ct = context.RequestServices.GetService(); - - //get the user record - var u = ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { roles = m.Roles, name = m.Name, id = m.Id, localeId = m.LocaleId }).First(); - context.Request.HttpContext.Items["AY_ROLES"] = u.roles; - context.Request.HttpContext.Items["AY_USERNAME"] = u.name; - context.Request.HttpContext.Items["AY_USER_ID"] = u.id; - context.Request.HttpContext.Items["AY_LOCALE_ID"] = u.localeId; - - - - } - await next.Invoke(); - }); - - #endregion - - _log.LogDebug("BOOT: pipeline - ENDPOINTS"); - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - - #region SWAGGER - - _log.LogDebug("BOOT: pipeline - api explorer"); - // Enable middleware to serve generated Swagger as a JSON endpoint. - app.UseSwagger(); - - app.UseSwaggerUI(c => - { - // build a swagger endpoint for each discovered API version - foreach (var description in provider.ApiVersionDescriptions) - { - c.SwaggerEndpoint($"/swagger/{description.GroupName}/swagger.json", description.GroupName.ToUpperInvariant()); - } - - //clean up the swagger explorer UI page and remove the branding - //via our own css - //NOTE: this broke when updated to v2.x of swagger and it can be fixed according to docs: - //https://github.com/domaindrivendev/Swashbuckle.AspNetCore#inject-custom-css - // c.InjectStylesheet("/api/sw.css"); - - c.DefaultModelsExpandDepth(-1); - c.DocumentTitle = "AyaNova API explorer"; - c.RoutePrefix = "api-docs"; - }); - - - - #endregion swagger - - - - - - - //According to https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-2.2&tabs=visual-studio#migrate-startupconfigure - //replace use mvc with use endpoints - // //USE MVC - // _log.LogDebug("BOOT: pipeline - MVC"); - // app.UseMvc(); - // _log.LogDebug("BOOT: pipeline - ENDPOINTS"); - // app.UseEndpoints(endpoints => { - // endpoints.MapControllers(); - // }); - - // ****************************************************************** - // ******************** TESTING WIPE DB ***************************** - // - //Set this to true to wipe the db and reinstall a trial license and re-seed the data - var TESTING_REFRESH_DB = false;//####################################################################################### - -#if (DEBUG) - //TESTING - if (TESTING_REFRESH_DB) - ServerBootConfig.AYANOVA_PERMANENTLY_ERASE_DATABASE = TESTING_REFRESH_DB; - //TESTING -#endif - - - if (ServerBootConfig.AYANOVA_PERMANENTLY_ERASE_DATABASE) - { - _log.LogWarning("BOOT: AYANOVA_PERMANENTLY_ERASE_DATABASE is true, dropping and recreating database"); - Util.DbUtil.DropAndRecreateDb(_log); - AySchema.CheckAndUpdate(dbContext, _log); - } - - //Check schema - _log.LogDebug("BOOT: db schema check"); - AySchema.CheckAndUpdate(dbContext, _log); - - //Check database integrity - _log.LogDebug("BOOT: db integrity check"); - DbUtil.CheckFingerPrint(AySchema.EXPECTED_COLUMN_COUNT, AySchema.EXPECTED_INDEX_COUNT, _log); - - //Initialize license - AyaNova.Core.License.Initialize(apiServerState, dbContext, _log); - - //Ensure locales are present, not missing any keys and that there is a server default locale that exists - LocaleBiz lb = new LocaleBiz(dbContext, 1, ServerBootConfig.AYANOVA_DEFAULT_LANGUAGE_ID, AuthorizationRoles.OpsAdminFull); - lb.ValidateLocales(); - - - -#if (DEBUG) - //TESTING - if (TESTING_REFRESH_DB) - { - AyaNova.Core.License.Fetch(apiServerState, dbContext, _log); - Util.Seeder.SeedDatabase(Util.Seeder.SeedLevel.SmallOneManShopTrialDataSet, -7);//############################################################################################# - } - //TESTING -#endif - - - //AUTOID VALUES INITIALIZATION - ServerBootConfig.SetMostRecentAutoIdValuesFromDatabase(dbContext); - - //SPA FALLBACK ROUTE - app.Use(async (context, next) => - { - //to support html5 pushstate routing in spa - //this ensures that a refresh at the client will not 404 but rather force back to the index.html app page and then handled internally by the client - await next(); - if (!context.Response.HasStarted && context.Request.Path.Value != "/docs" && context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value)) - { - context.Request.Path = "/index.html"; - context.Response.StatusCode = 200; - context.Response.ContentType = "text/html"; - await context.Response.SendFileAsync(Path.Combine(env.WebRootPath, "index.html")); - } - }); - - - //Log the active user count so it's in the log record - _log.LogInformation($"BOOT: Active techs - {UserBiz.ActiveCount}"); - - //Log the license info so it's on the record - _log.LogInformation($"BOOT: License -\r\n=-=-=-=-=-=-=-=-=-=-\r\n{AyaNova.Core.License.LicenseInfo}=-=-=-=-=-=-=-=-=-=-"); - - - - //Open up the server for visitors - apiServerState.SetOpen(); - - //final startup log - _log.LogInformation("BOOT: COMPLETED - SERVER IS NOW OPEN"); - - } - - - #region Swagger and API Versioning utilities - - static string XmlCommentsFilePath - { - get - { - //Obsolete, used new method: https://developers.de/blogs/holger_vetter/archive/2017/06/30/swagger-includexmlcomments-platformservices-obsolete-replacement.aspx - //var basePath = PlatformServices.Default.Application.ApplicationBasePath; - var basePath = AppContext.BaseDirectory; - var fileName = typeof(Startup).GetTypeInfo().Assembly.GetName().Name + ".xml"; - return Path.Combine(basePath, fileName); - } - } - - // static Microsoft.OpenApi.Models.OpenApiInfo CreateInfoForApiVersion(ApiVersionDescription description) - // { - // var info = new Microsoft.OpenApi.Models.OpenApiInfo() - // { - // Title = $"AyaNova API {description.ApiVersion}", - // Version = description.ApiVersion.ToString() - // }; - - // if (description.IsDeprecated) - // { - // info.Description += " This API version has been deprecated."; - // } - - // return info; - // } - - - - //update for v3 from here https://github.com/microsoft/aspnet-api-versioning/wiki/API-Documentation#aspnet-core - //and example here: https://github.com/microsoft/aspnet-api-versioning/blob/master/samples/aspnetcore/SwaggerSample/ConfigureSwaggerOptions.cs - // public class ConfigureSwaggerOptions : IConfigureOptions - // { - // readonly IApiVersionDescriptionProvider provider; - - // public ConfigureSwaggerOptions(IApiVersionDescriptionProvider provider) => - // this.provider = provider; - - // public void Configure(SwaggerGenOptions options) - // { - // foreach (var description in provider.ApiVersionDescriptions) - // { - // options.SwaggerDoc( - // description.GroupName, - // new OpenApiInfo() - // { - // Title = $"AyaNova API {description.ApiVersion}", - // Version = description.ApiVersion.ToString(), - // }); - // } - // } - // } - - #endregion - } -} - - - - - */ diff --git a/server/AyaNova/SwaggerDefaultValues.cs b/server/AyaNova/SwaggerDefaultValues.cs deleted file mode 100644 index fc01dc14..00000000 --- a/server/AyaNova/SwaggerDefaultValues.cs +++ /dev/null @@ -1,136 +0,0 @@ -// namespace AyaNova -// { -// using Microsoft.OpenApi.Models; -// using Swashbuckle.AspNetCore.SwaggerGen; -// using System.Linq; -// using Microsoft.AspNetCore.Authorization; - -// //https://github.com/domaindrivendev/Swashbuckle.AspNetCore/releases/tag/v5.0.0-rc3 - -// /// -// /// Represents the Swagger/Swashbuckle operation filter used to document the implicit API version parameter. -// /// -// /// This is only required due to bugs in the . -// /// Once they are fixed and published, this class can be removed. -// public class SwaggerDefaultValues : IOperationFilter -// { -// /// -// /// Applies the filter to the specified operation using the given context. -// /// -// /// The operation to apply the filter to. -// /// The current operation filter context. -// public void Apply(OpenApiOperation operation, OperationFilterContext context) -// { -// // REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/412 -// // REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/413 -// foreach (var parameter in operation.Parameters) -// { -// var description = context.ApiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name); -// var routeInfo = description.RouteInfo; - -// if (parameter.Description == null) -// { -// parameter.Description = description.ModelMetadata?.Description; -// } - -// if (routeInfo == null) -// { -// continue; -// } - -// // if (parameter.Default == null) -// // { -// // parameter.Default = routeInfo.DefaultValue; -// // } - -// if (parameter.Schema.Default == null) { parameter.Schema.Default = new OpenApiString(description.DefaultValue.ToString()); } - -// parameter.Required |= !routeInfo.IsOptional; -// } -// } -// } - -namespace AyaNova -{ - using Microsoft.AspNetCore.Mvc.ApiExplorer; - using Microsoft.OpenApi.Any; - using Microsoft.OpenApi.Models; - using Swashbuckle.AspNetCore.SwaggerGen; - using System.Linq; - - /// - /// Represents the Swagger/Swashbuckle operation filter used to document the implicit API version parameter. - /// - /// This is only required due to bugs in the . - /// Once they are fixed and published, this class can be removed. - public class SwaggerDefaultValues : IOperationFilter - { - /// - /// Applies the filter to the specified operation using the given context. - /// - /// The operation to apply the filter to. - /// The current operation filter context. - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - var apiDescription = context.ApiDescription; - - operation.Deprecated |= apiDescription.IsDeprecated(); - - if (operation.Parameters == null) - { - return; - } - - // REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/412 - // REF: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/413 - foreach (var parameter in operation.Parameters) - { - var description = apiDescription.ParameterDescriptions.First(p => p.Name == parameter.Name); - - if (parameter.Description == null) - { - parameter.Description = description.ModelMetadata?.Description; - } - - if (parameter.Schema.Default == null && description.DefaultValue != null) - { - parameter.Schema.Default = new OpenApiString(description.DefaultValue.ToString()); - } - - parameter.Required |= description.IsRequired; - } - } - } -} - - - -// public void ConfigureServices(IServiceCollection services) -// { - - -// #region Swagger - -// services -// .AddApiVersioning(options => -// { -// options.AssumeDefaultVersionWhenUnspecified = true; -// options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0"); -// options.ReportApiVersions = true; -// }); - -// services.AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV"); - -// services.AddTransient, ConfigureSwaggerOptions>(); - - -// services.AddSwaggerGen( -// c => -// { -// c.OperationFilter(); -// }); - - -// #endregion - -