From 0d42f163fc18b66f6e3f4ae73a79c1d1f41c6735 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 17 Oct 2019 18:42:28 +0000 Subject: [PATCH] Ok, everything seems to be working except for the api explorer so now can turn back to that. (api explorer issues are caused by the api versioning system as removing it fixes the missing api explorer routes --- devdocs/todo.txt | 23 -- server/AyaNova/AyaNova.csproj | 16 +- .../AyaNova/Controllers/ApiRootController.cs | 4 +- .../Controllers/AttachmentController.cs | 4 +- server/AyaNova/Controllers/AuthController.cs | 6 +- .../Controllers/AyaEnumPickListController.cs | 4 +- .../AyaNova/Controllers/AyaTypeController.cs | 4 +- .../AyaNova/Controllers/BackupController.cs | 4 +- .../Controllers/DataFilterController.cs | 4 +- .../AyaNova/Controllers/EventLogController.cs | 4 +- .../Controllers/FormCustomController.cs | 4 +- .../Controllers/ImportAyaNova7Controller.cs | 4 +- .../Controllers/JobOperationsController.cs | 4 +- .../AyaNova/Controllers/LicenseController.cs | 4 +- .../AyaNova/Controllers/LocaleController.cs | 4 +- .../AyaNova/Controllers/LogFilesController.cs | 4 +- .../AyaNova/Controllers/MetricsController.cs | 4 +- .../AyaNova/Controllers/SearchController.cs | 4 +- .../Controllers/ServerStateController.cs | 4 +- .../AyaNova/Controllers/TagListController.cs | 4 +- server/AyaNova/Controllers/TrialController.cs | 4 +- server/AyaNova/Controllers/UserController.cs | 4 +- .../Controllers/UserOptionsController.cs | 4 +- .../AyaNova/Controllers/WidgetController.cs | 4 +- server/AyaNova/Program.cs | 72 ++-- server/AyaNova/Startup.cs | 355 ++++++++---------- server/AyaNova/SwaggerDefaultValues.cs | 104 ++--- 27 files changed, 285 insertions(+), 375 deletions(-) diff --git a/devdocs/todo.txt b/devdocs/todo.txt index 5da3d6b6..70110ab2 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -11,29 +11,6 @@ UPDATE all the things before commencing work - https://github.com/domaindrivendev/Swashbuckle.AspNetCore#swashbuckleaspnetcoreannotations - - -2019-10-16 12:47:22.3600|ERROR|Microsoft.AspNetCore.Server.Kestrel|Connection id "0HLQIE5LC01UO", Request id "0HLQIE5LC01UO:00000003": -An unhandled exception was thrown by the application.=>System.InvalidOperationException: Endpoint AyaNova.Api.Controllers.WidgetController.ListWidgets (AyaNova) -contains authorization metadata, but a middleware was not found that supports authorization. -Configure your application startup by adding app.UseAuthorization() inside the call to Configure(..) in the application startup code. The call to app.UseAuthorization() must appear between app.UseRouting() and app.UseEndpoints(...). - at Microsoft.AspNetCore.Routing.EndpointMiddleware.ThrowMissingAuthMiddlewareException(Endpoint endpoint) - - - - 2019-10-16 12:45:37.5732|ERROR|Microsoft.AspNetCore.Server.Kestrel|Connection id "0HLQIE5LC01UI", Request id "0HLQIE5LC01UI:00000001": - An unhandled exception was thrown by the application.=>System.TypeLoadException: - Could not load type 'Microsoft.AspNetCore.Mvc.Internal.MvcAttributeRouteHandler' from assembly 'Microsoft.AspNetCore.Mvc.Core, Version=3.1.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'. - at Microsoft.AspNetCore.Mvc.Internal.MvcRouteTemplateResolver.ResolveMatchingTemplateRouteAsync(RouteData routeData) - - - - - - - - - - Need a sprint to get to a fully testable client with entry form, list and as much as possible all features from COMMON-* specs list Do the stuff in the Client todo first then back to the server as required. diff --git a/server/AyaNova/AyaNova.csproj b/server/AyaNova/AyaNova.csproj index 62178b27..42178ba8 100644 --- a/server/AyaNova/AyaNova.csproj +++ b/server/AyaNova/AyaNova.csproj @@ -32,18 +32,22 @@ - + + - - runtime; build; native; contentfiles; analyzers; buildtransitive - all + + runtime; build; native; contentfiles; analyzers; buildtransitive + all - + + + + + diff --git a/server/AyaNova/Controllers/ApiRootController.cs b/server/AyaNova/Controllers/ApiRootController.cs index d6dd29d2..dc74c239 100644 --- a/server/AyaNova/Controllers/ApiRootController.cs +++ b/server/AyaNova/Controllers/ApiRootController.cs @@ -11,9 +11,9 @@ namespace AyaNova.Api.Controllers /// /// Meta controller class /// + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/")] [AllowAnonymous] - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/")]//was [Route("api/v{version:apiVersion}/")] public class ApiMetaController : Controller { private readonly ApiServerState serverState; diff --git a/server/AyaNova/Controllers/AttachmentController.cs b/server/AyaNova/Controllers/AttachmentController.cs index 4e9189da..60cc2998 100644 --- a/server/AyaNova/Controllers/AttachmentController.cs +++ b/server/AyaNova/Controllers/AttachmentController.cs @@ -32,8 +32,8 @@ namespace AyaNova.Api.Controllers /// /// Attachment controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class AttachmentController : Controller diff --git a/server/AyaNova/Controllers/AuthController.cs b/server/AyaNova/Controllers/AuthController.cs index db59dfb2..7572f3c6 100644 --- a/server/AyaNova/Controllers/AuthController.cs +++ b/server/AyaNova/Controllers/AuthController.cs @@ -10,7 +10,6 @@ using System; using System.Threading.Tasks; using App.Metrics; using AyaNova.Biz; -using Microsoft.AspNetCore.Authorization; //required to inject configuration in constructor using Microsoft.Extensions.Configuration; @@ -20,10 +19,9 @@ namespace AyaNova.Api.Controllers /// /// Authentication controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] - [AllowAnonymous] public class AuthController : Controller { private readonly AyContext ct; diff --git a/server/AyaNova/Controllers/AyaEnumPickListController.cs b/server/AyaNova/Controllers/AyaEnumPickListController.cs index c6364b85..cd4a285b 100644 --- a/server/AyaNova/Controllers/AyaEnumPickListController.cs +++ b/server/AyaNova/Controllers/AyaEnumPickListController.cs @@ -15,8 +15,8 @@ namespace AyaNova.Api.Controllers /// /// Enum pick list controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class AyaEnumPickListController : Controller diff --git a/server/AyaNova/Controllers/AyaTypeController.cs b/server/AyaNova/Controllers/AyaTypeController.cs index 6bc1e616..3c5fdb73 100644 --- a/server/AyaNova/Controllers/AyaTypeController.cs +++ b/server/AyaNova/Controllers/AyaTypeController.cs @@ -15,8 +15,8 @@ namespace AyaNova.Api.Controllers /// /// AyaType list controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class AyaTypeController : Controller diff --git a/server/AyaNova/Controllers/BackupController.cs b/server/AyaNova/Controllers/BackupController.cs index b0be0732..90b4f20e 100644 --- a/server/AyaNova/Controllers/BackupController.cs +++ b/server/AyaNova/Controllers/BackupController.cs @@ -46,8 +46,8 @@ namespace AyaNova.Api.Controllers /// and triggering a restore from backup /// /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class BackupController : Controller diff --git a/server/AyaNova/Controllers/DataFilterController.cs b/server/AyaNova/Controllers/DataFilterController.cs index 07990ae6..f549bdc9 100644 --- a/server/AyaNova/Controllers/DataFilterController.cs +++ b/server/AyaNova/Controllers/DataFilterController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class DataFilterController : Controller diff --git a/server/AyaNova/Controllers/EventLogController.cs b/server/AyaNova/Controllers/EventLogController.cs index f23d8616..f9ae1117 100644 --- a/server/AyaNova/Controllers/EventLogController.cs +++ b/server/AyaNova/Controllers/EventLogController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// Log files controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Authorize] public class EventLogController : Controller { diff --git a/server/AyaNova/Controllers/FormCustomController.cs b/server/AyaNova/Controllers/FormCustomController.cs index 468d0c92..1e621e3f 100644 --- a/server/AyaNova/Controllers/FormCustomController.cs +++ b/server/AyaNova/Controllers/FormCustomController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class FormCustomController : Controller diff --git a/server/AyaNova/Controllers/ImportAyaNova7Controller.cs b/server/AyaNova/Controllers/ImportAyaNova7Controller.cs index 24299593..be990765 100644 --- a/server/AyaNova/Controllers/ImportAyaNova7Controller.cs +++ b/server/AyaNova/Controllers/ImportAyaNova7Controller.cs @@ -29,8 +29,8 @@ namespace AyaNova.Api.Controllers /// /// Import AyaNova 7 data controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class ImportAyaNova7Controller : Controller diff --git a/server/AyaNova/Controllers/JobOperationsController.cs b/server/AyaNova/Controllers/JobOperationsController.cs index dc1cb2dd..4dd8b621 100644 --- a/server/AyaNova/Controllers/JobOperationsController.cs +++ b/server/AyaNova/Controllers/JobOperationsController.cs @@ -17,8 +17,8 @@ namespace AyaNova.Api.Controllers /// /// JobOperations controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class JobOperationsController : Controller diff --git a/server/AyaNova/Controllers/LicenseController.cs b/server/AyaNova/Controllers/LicenseController.cs index ebbff73f..811ae95c 100644 --- a/server/AyaNova/Controllers/LicenseController.cs +++ b/server/AyaNova/Controllers/LicenseController.cs @@ -16,8 +16,8 @@ namespace AyaNova.Api.Controllers /// /// License route /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class LicenseController : Controller diff --git a/server/AyaNova/Controllers/LocaleController.cs b/server/AyaNova/Controllers/LocaleController.cs index 2825ee62..43f3306e 100644 --- a/server/AyaNova/Controllers/LocaleController.cs +++ b/server/AyaNova/Controllers/LocaleController.cs @@ -23,8 +23,8 @@ namespace AyaNova.Api.Controllers /// /// Localized text controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class LocaleController : Controller diff --git a/server/AyaNova/Controllers/LogFilesController.cs b/server/AyaNova/Controllers/LogFilesController.cs index 0c4d4d96..71d19716 100644 --- a/server/AyaNova/Controllers/LogFilesController.cs +++ b/server/AyaNova/Controllers/LogFilesController.cs @@ -16,8 +16,8 @@ namespace AyaNova.Api.Controllers /// /// Log files controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] //[Produces("application/json")] [Authorize] public class LogFilesController : Controller diff --git a/server/AyaNova/Controllers/MetricsController.cs b/server/AyaNova/Controllers/MetricsController.cs index 4024350f..e1f87d2d 100644 --- a/server/AyaNova/Controllers/MetricsController.cs +++ b/server/AyaNova/Controllers/MetricsController.cs @@ -18,8 +18,8 @@ namespace AyaNova.Api.Controllers /// /// Log files controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Authorize] public class MetricsController : Controller { diff --git a/server/AyaNova/Controllers/SearchController.cs b/server/AyaNova/Controllers/SearchController.cs index ffa5bf90..f991e561 100644 --- a/server/AyaNova/Controllers/SearchController.cs +++ b/server/AyaNova/Controllers/SearchController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// Search /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class SearchController : Controller diff --git a/server/AyaNova/Controllers/ServerStateController.cs b/server/AyaNova/Controllers/ServerStateController.cs index 06b49c81..ced534cc 100644 --- a/server/AyaNova/Controllers/ServerStateController.cs +++ b/server/AyaNova/Controllers/ServerStateController.cs @@ -15,8 +15,8 @@ namespace AyaNova.Api.Controllers /// /// Server state controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] public class ServerStateController : Controller { diff --git a/server/AyaNova/Controllers/TagListController.cs b/server/AyaNova/Controllers/TagListController.cs index 4659cb5f..07255035 100644 --- a/server/AyaNova/Controllers/TagListController.cs +++ b/server/AyaNova/Controllers/TagListController.cs @@ -15,8 +15,8 @@ namespace AyaNova.Api.Controllers /// /// Enum pick list controller /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class TagListController : Controller diff --git a/server/AyaNova/Controllers/TrialController.cs b/server/AyaNova/Controllers/TrialController.cs index f850dce5..e8cc9906 100644 --- a/server/AyaNova/Controllers/TrialController.cs +++ b/server/AyaNova/Controllers/TrialController.cs @@ -13,8 +13,8 @@ namespace AyaNova.Api.Controllers /// ///Test controller class used during development /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class TrialController : Controller diff --git a/server/AyaNova/Controllers/UserController.cs b/server/AyaNova/Controllers/UserController.cs index 70dee427..5f9ada8d 100644 --- a/server/AyaNova/Controllers/UserController.cs +++ b/server/AyaNova/Controllers/UserController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// User /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class UserController : Controller diff --git a/server/AyaNova/Controllers/UserOptionsController.cs b/server/AyaNova/Controllers/UserOptionsController.cs index 97158471..10285549 100644 --- a/server/AyaNova/Controllers/UserOptionsController.cs +++ b/server/AyaNova/Controllers/UserOptionsController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// UserOptions /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class UserOptionsController : Controller diff --git a/server/AyaNova/Controllers/WidgetController.cs b/server/AyaNova/Controllers/WidgetController.cs index b17f3527..80619579 100644 --- a/server/AyaNova/Controllers/WidgetController.cs +++ b/server/AyaNova/Controllers/WidgetController.cs @@ -22,8 +22,8 @@ namespace AyaNova.Api.Controllers /// /// Sample controller class used during development for testing purposes /// - //SWASHBUCKLETEST [ApiVersion("8.0")] - [Route("api/v8/[controller]")]//was [Route("api/v{version:apiVersion}/[controller]")] + [ApiVersion("8.0")] + [Route("api/v{version:apiVersion}/[controller]")] [Produces("application/json")] [Authorize] public class WidgetController : Controller diff --git a/server/AyaNova/Program.cs b/server/AyaNova/Program.cs index 3d317698..f1e22136 100644 --- a/server/AyaNova/Program.cs +++ b/server/AyaNova/Program.cs @@ -207,45 +207,45 @@ namespace AyaNova .UseUrls(ServerBootConfig.AYANOVA_USE_URLS)//default port and urls, set first can be overridden by any later setting here .UseConfiguration(configuration)//support command line override of port (dotnet run urls=http://*:8081) .UseIISIntegration()//support IIS integration just in case, it appears here to override prior settings if necessary (port) - // .ConfigureMetricsWithDefaults(builder => - // { - // if (ServerBootConfig.AYANOVA_METRICS_USE_INFLUXDB) - // { - // builder.Report.ToInfluxDb( - // options => - // { + .ConfigureMetricsWithDefaults(builder => + { + if (ServerBootConfig.AYANOVA_METRICS_USE_INFLUXDB) + { + builder.Report.ToInfluxDb( + options => + { - // options.InfluxDb.BaseUri = new Uri(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_BASEURL); - // options.InfluxDb.Database = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_DBNAME; - // if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY)) - // { - // options.InfluxDb.Consistenency = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY; - // } - // options.InfluxDb.UserName = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_USERNAME; - // options.InfluxDb.Password = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_PASSWORD; - // if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY)) - // { - // options.InfluxDb.RetentionPolicy = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY; - // } + options.InfluxDb.BaseUri = new Uri(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_BASEURL); + options.InfluxDb.Database = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_DBNAME; + if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY)) + { + options.InfluxDb.Consistenency = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_CONSISTENCY; + } + options.InfluxDb.UserName = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_USERNAME; + options.InfluxDb.Password = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_PASSWORD; + if (!string.IsNullOrWhiteSpace(ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY)) + { + options.InfluxDb.RetentionPolicy = ServerBootConfig.AYANOVA_METRICS_INFLUXDB_RETENTION_POLICY; + } - // options.InfluxDb.CreateDataBaseIfNotExists = true; - // options.HttpPolicy.BackoffPeriod = TimeSpan.FromSeconds(30); - // options.HttpPolicy.FailuresBeforeBackoff = 5; - // options.HttpPolicy.Timeout = TimeSpan.FromSeconds(10); - // //options.MetricsOutputFormatter = new App.Metrics.Formatters.Json.MetricsJsonOutputFormatter(); - // //options.Filter = filter; - // options.FlushInterval = TimeSpan.FromSeconds(20); - // }); - // } + options.InfluxDb.CreateDataBaseIfNotExists = true; + options.HttpPolicy.BackoffPeriod = TimeSpan.FromSeconds(30); + options.HttpPolicy.FailuresBeforeBackoff = 5; + options.HttpPolicy.Timeout = TimeSpan.FromSeconds(10); + //options.MetricsOutputFormatter = new App.Metrics.Formatters.Json.MetricsJsonOutputFormatter(); + //options.Filter = filter; + options.FlushInterval = TimeSpan.FromSeconds(20); + }); + } - // }) - // .UseMetricsEndpoints(opt => - // { - // opt.EnvironmentInfoEndpointEnabled = false; - // opt.MetricsEndpointEnabled = false; - // opt.MetricsTextEndpointEnabled = false; - // }) - // .UseMetrics() + }) + .UseMetricsEndpoints(opt => + { + opt.EnvironmentInfoEndpointEnabled = false; + opt.MetricsEndpointEnabled = false; + opt.MetricsTextEndpointEnabled = false; + }) + .UseMetrics() .UseStartup() .ConfigureLogging((context, logging) => { diff --git a/server/AyaNova/Startup.cs b/server/AyaNova/Startup.cs index 0d21506a..2dad823f 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -62,31 +62,36 @@ namespace AyaNova { _log.LogDebug("BOOT: initializing services..."); - //dotnet 3.x added this wasn't here before - services.AddControllers(); - services.AddSwaggerGen(c => - { - c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); - }); //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(); - //dotnet 3 commented this out, new project doesn't have it - //Init mvc - // _log.LogDebug("BOOT: init MVC Core service"); - // var mvc = services.AddMvcCore(); - // _log.LogDebug("BOOT: add json service"); - // mvc.AddNewtonsoftJson(); // 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.AddVersionedApiExplorer(o => o.GroupNameFormat = "'v'VVV"); _log.LogDebug("BOOT: ensuring user and backup folders exist and are separate locations..."); FileUtil.EnsureUserAndUtilityFoldersExistAndAreNotIdentical(_hostingEnvironment.ContentRootPath); @@ -143,46 +148,31 @@ namespace AyaNova #endregion _log.LogDebug("BOOT: init ApiVersioning service"); - // services - // .AddApiVersioning(options => - // { - // options.AssumeDefaultVersionWhenUnspecified = true; - // options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0"); - // options.ReportApiVersions = true; - // }); + // services.AddApiVersioning(o => o.ReportApiVersions = true); + services + .AddApiVersioning(options => + { + options.AssumeDefaultVersionWhenUnspecified = true; + options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0"); + options.ReportApiVersions = true; + }); - //v3 commented out to try to figure out why the swagger docs aren't generating and may be superfluous - // // 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() - // ); - // }); + // 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() + ); + }); - _log.LogDebug("BOOT: init MVC service"); - _log.LogDebug("BOOT: init Metrics service"); - // services.AddMvc(config => - // { - // //was this but needed logging, not certain about the new way of adding so keeping this in case it all goes sideways in testing - // //config.Filters.Add(typeof(AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter)); - // config.Filters.Add(new AyaNova.Api.ControllerHelpers.ApiCustomExceptionFilter(AyaNova.Util.ApplicationLogging.LoggerFactory)); - - // }).AddMetrics().AddJsonOptions(options => - // { - // //2019-10-15 - removed this due to fuckery after update, is it required??? Not sure at this point - // //if metrics have wrong dates then it's important I guess - // //options.JsonSerializerOptions.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc; - // }); - #region Swagger //https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?tabs=visual-studio-code @@ -190,112 +180,73 @@ namespace AyaNova //https://github.com/domaindrivendev/Swashbuckle.AspNetCore _log.LogDebug("BOOT: init API explorer service"); - // services.AddSwaggerGen(c => - // { - // c.SwaggerDoc("v8", new OpenApiInfo { Title = "My API", Version = "v8" }); - // c.OperationFilter(); + services.AddSwaggerGen( + c => + { + // resolve the IApiVersionDescriptionProvider service + // note: that we have to build a temporary service provider here because one has not been created yet + var provider = services.BuildServiceProvider().GetRequiredService(); - // }); - // services.AddSwaggerGen( - // c => - // { + // 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(); - // 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); - // }); + // integrate xml comments + c.IncludeXmlComments(XmlCommentsFilePath); - // // resolve the IApiVersionDescriptionProvider service - // // note: that we have to build a temporary service provider here because one has not been created yet - // var provider = services.BuildServiceProvider().GetRequiredService(); + //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" - // // 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 - // // c.OperationFilter(); - - // //test filter WTF? - // //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" - - // // }); + // }); - // //Obsolete way - // // c.AddSecurityRequirement(new System.Collections.Generic.Dictionary> - // // { - // // { "Bearer", new string[] { } } - // // }); + //Obsolete way + // c.AddSecurityRequirement(new System.Collections.Generic.Dictionary> + // { + // { "Bearer", new string[] { } } + // }); - // //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". - // }); + //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() - // } - // }); + c.AddSecurityRequirement(new OpenApiSecurityRequirement{ + { + new OpenApiSecurityScheme{ + Reference = new OpenApiReference{ + Id = "Bearer", //The name of the previously defined security scheme. + Type = ReferenceType.SecurityScheme + } + },new List() + } + }); - // //https://github.com/domaindrivendev/Swashbuckle.AspNetCore - // //ARGGHHHHHHHH!!!!! - - - // }); + }); #endregion @@ -367,20 +318,14 @@ namespace AyaNova // 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, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider) + AyContext dbContext, IApiVersionDescriptionProvider provider, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider) { - //This was in constructor right after dbcontext: IApiVersionDescriptionProvider provider, _log.LogDebug("BOOT: configuring request pipeline..."); - //dotnet3 test added if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } - - //This is in new templates generated for webapi but it errors out for me so removing it for now - // app.UseHttpsRedirection(); - //Store a reference to the dependency injection service for static classes ServiceProviderProvider.Provider = app.ApplicationServices; @@ -394,15 +339,26 @@ namespace AyaNova _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 - //v3test - // _log.LogDebug("BOOT: pipeline - CORS"); - // app.UseCors("CorsPolicy"); + _log.LogDebug("BOOT: pipeline - CORS"); + app.UseCors("CorsPolicy"); #region AUTH / ROLES @@ -413,6 +369,7 @@ namespace AyaNova _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) => @@ -444,46 +401,33 @@ namespace AyaNova #endregion - //According to https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-2.2&tabs=visual-studio#migrate-startupconfigure _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"; - - // }); - - app.UseSwagger(); + // Enable middleware to serve generated Swagger as a JSON endpoint. + app.UseSwagger(); app.UseSwaggerUI(c => { - c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); - c.DefaultModelsExpandDepth(-1); + // 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"; }); @@ -494,6 +438,15 @@ namespace AyaNova + //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 ***************************** @@ -582,33 +535,33 @@ namespace AyaNova #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 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() - // }; + 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."; - // } + if (description.IsDeprecated) + { + info.Description += " This API version has been deprecated."; + } - // return info; - // } + return info; + } #endregion diff --git a/server/AyaNova/SwaggerDefaultValues.cs b/server/AyaNova/SwaggerDefaultValues.cs index 56525ed1..eff78291 100644 --- a/server/AyaNova/SwaggerDefaultValues.cs +++ b/server/AyaNova/SwaggerDefaultValues.cs @@ -1,69 +1,47 @@ -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; - // } - - parameter.Required |= !routeInfo.IsOptional; - } - } - } +// namespace AyaNova +// { +// 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( Operation 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.OfType() ) +// { +// var description = context.ApiDescription.ParameterDescriptions.First( p => p.Name == parameter.Name ); +// var routeInfo = description.RouteInfo; +// if ( parameter.Description == null ) +// { +// parameter.Description = description.ModelMetadata?.Description; +// } -// AuthResponsesOperationFilter.cs -public class AuthResponsesOperationFilter : IOperationFilter -{ - public void Apply(OpenApiOperation operation, OperationFilterContext context) - { - var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true) - .Union(context.MethodInfo.GetCustomAttributes(true)) - .OfType(); +// if ( routeInfo == null ) +// { +// continue; +// } - if (authAttributes.Any()) - operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" }); - } -} - -} +// if ( parameter.Default == null ) +// { +// parameter.Default = routeInfo.DefaultValue; +// } +// parameter.Required |= !routeInfo.IsOptional; +// } +// } +// } +// } \ No newline at end of file