From c9155ff24e58d7228bb1635f019f06d88b2582f0 Mon Sep 17 00:00:00 2001 From: John Cardinal Date: Thu, 17 Oct 2019 17:50:21 +0000 Subject: [PATCH] Swagger working but with removed api versioning system and a lot of other shit removed during diagnosis. Revert to this commit to go that route. --- devdocs/todo.txt | 23 ++ server/AyaNova/AyaNova.csproj | 16 +- .../AyaNova/Controllers/ApiRootController.cs | 6 +- .../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 | 360 ++++++++++-------- server/AyaNova/SwaggerDefaultValues.cs | 104 +++-- 27 files changed, 385 insertions(+), 282 deletions(-) diff --git a/devdocs/todo.txt b/devdocs/todo.txt index 70110ab2..5da3d6b6 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -11,6 +11,29 @@ 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 42178ba8..62178b27 100644 --- a/server/AyaNova/AyaNova.csproj +++ b/server/AyaNova/AyaNova.csproj @@ -32,22 +32,18 @@ - - + - - 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 03dbe79c..d6dd29d2 100644 --- a/server/AyaNova/Controllers/ApiRootController.cs +++ b/server/AyaNova/Controllers/ApiRootController.cs @@ -4,14 +4,16 @@ using System; using AyaNova.Util; using AyaNova.Biz; using AyaNova.Api.ControllerHelpers; +using Microsoft.AspNetCore.Authorization; 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 60cc2998..4e9189da 100644 --- a/server/AyaNova/Controllers/AttachmentController.cs +++ b/server/AyaNova/Controllers/AttachmentController.cs @@ -32,8 +32,8 @@ namespace AyaNova.Api.Controllers /// /// Attachment controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 7572f3c6..db59dfb2 100644 --- a/server/AyaNova/Controllers/AuthController.cs +++ b/server/AyaNova/Controllers/AuthController.cs @@ -10,6 +10,7 @@ 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; @@ -19,9 +20,10 @@ namespace AyaNova.Api.Controllers /// /// Authentication controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 cd4a285b..c6364b85 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 /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 3c5fdb73..6bc1e616 100644 --- a/server/AyaNova/Controllers/AyaTypeController.cs +++ b/server/AyaNova/Controllers/AyaTypeController.cs @@ -15,8 +15,8 @@ namespace AyaNova.Api.Controllers /// /// AyaType list controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 90b4f20e..b0be0732 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 /// /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 f549bdc9..07990ae6 100644 --- a/server/AyaNova/Controllers/DataFilterController.cs +++ b/server/AyaNova/Controllers/DataFilterController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 f9ae1117..f23d8616 100644 --- a/server/AyaNova/Controllers/EventLogController.cs +++ b/server/AyaNova/Controllers/EventLogController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// Log files controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 1e621e3f..468d0c92 100644 --- a/server/AyaNova/Controllers/FormCustomController.cs +++ b/server/AyaNova/Controllers/FormCustomController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 be990765..24299593 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 /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 4dd8b621..dc1cb2dd 100644 --- a/server/AyaNova/Controllers/JobOperationsController.cs +++ b/server/AyaNova/Controllers/JobOperationsController.cs @@ -17,8 +17,8 @@ namespace AyaNova.Api.Controllers /// /// JobOperations controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 811ae95c..ebbff73f 100644 --- a/server/AyaNova/Controllers/LicenseController.cs +++ b/server/AyaNova/Controllers/LicenseController.cs @@ -16,8 +16,8 @@ namespace AyaNova.Api.Controllers /// /// License route /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 43f3306e..2825ee62 100644 --- a/server/AyaNova/Controllers/LocaleController.cs +++ b/server/AyaNova/Controllers/LocaleController.cs @@ -23,8 +23,8 @@ namespace AyaNova.Api.Controllers /// /// Localized text controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 71d19716..0c4d4d96 100644 --- a/server/AyaNova/Controllers/LogFilesController.cs +++ b/server/AyaNova/Controllers/LogFilesController.cs @@ -16,8 +16,8 @@ namespace AyaNova.Api.Controllers /// /// Log files controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 e1f87d2d..4024350f 100644 --- a/server/AyaNova/Controllers/MetricsController.cs +++ b/server/AyaNova/Controllers/MetricsController.cs @@ -18,8 +18,8 @@ namespace AyaNova.Api.Controllers /// /// Log files controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 f991e561..ffa5bf90 100644 --- a/server/AyaNova/Controllers/SearchController.cs +++ b/server/AyaNova/Controllers/SearchController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// Search /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 ced534cc..06b49c81 100644 --- a/server/AyaNova/Controllers/ServerStateController.cs +++ b/server/AyaNova/Controllers/ServerStateController.cs @@ -15,8 +15,8 @@ namespace AyaNova.Api.Controllers /// /// Server state controller /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 07255035..4659cb5f 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 /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 e8cc9906..f850dce5 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 /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 5f9ada8d..70dee427 100644 --- a/server/AyaNova/Controllers/UserController.cs +++ b/server/AyaNova/Controllers/UserController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// User /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 10285549..97158471 100644 --- a/server/AyaNova/Controllers/UserOptionsController.cs +++ b/server/AyaNova/Controllers/UserOptionsController.cs @@ -19,8 +19,8 @@ namespace AyaNova.Api.Controllers /// /// UserOptions /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 80619579..b17f3527 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 /// - [ApiVersion("8.0")] - [Route("api/v{version:apiVersion}/[controller]")] + //SWASHBUCKLETEST [ApiVersion("8.0")] + [Route("api/v8/[controller]")]//was [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 f1e22136..3d317698 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 7c2307e9..0d21506a 100644 --- a/server/AyaNova/Startup.cs +++ b/server/AyaNova/Startup.cs @@ -62,23 +62,31 @@ 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()); + + //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(); + // _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); @@ -135,44 +143,45 @@ namespace AyaNova #endregion _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; - }); + // services + // .AddApiVersioning(options => + // { + // options.AssumeDefaultVersionWhenUnspecified = true; + // options.DefaultApiVersion = Microsoft.AspNetCore.Mvc.ApiVersion.Parse("8.0"); + // options.ReportApiVersions = true; + // }); - // 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()); - }); + //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() + // ); + // }); _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)); + // 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; - }); + // }).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 @@ -181,73 +190,112 @@ namespace AyaNova //https://github.com/domaindrivendev/Swashbuckle.AspNetCore _log.LogDebug("BOOT: init API explorer service"); - 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 => + // { + // c.SwaggerDoc("v8", new OpenApiInfo { Title = "My API", Version = "v8" }); + // c.OperationFilter(); - // 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)); - } + // }); + // services.AddSwaggerGen( + // c => + // { - // 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); + // 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); + // }); - //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" + // // 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(); - // }); + // // 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 @@ -319,10 +367,19 @@ 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, IApiVersionDescriptionProvider provider, AyaNova.Api.ControllerHelpers.ApiServerState apiServerState, IServiceProvider serviceProvider) + AyContext dbContext, 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; @@ -337,26 +394,15 @@ 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 - _log.LogDebug("BOOT: pipeline - CORS"); - app.UseCors("CorsPolicy"); + //v3test + // _log.LogDebug("BOOT: pipeline - CORS"); + // app.UseCors("CorsPolicy"); #region AUTH / ROLES @@ -364,6 +410,9 @@ namespace AyaNova //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) => @@ -395,28 +444,46 @@ 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(); + // // 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(); 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.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1"); + c.DefaultModelsExpandDepth(-1); c.DocumentTitle = "AyaNova API explorer"; c.RoutePrefix = "api-docs"; }); @@ -427,21 +494,12 @@ 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 ***************************** // //Set this to true to wipe the db and reinstall a trial license and re-seed the data - var TESTING_REFRESH_DB = true;//####################################################################################### + var TESTING_REFRESH_DB = false;//####################################################################################### #if (DEBUG) //TESTING @@ -524,33 +582,33 @@ _log.LogDebug("BOOT: pipeline - ENDPOINTS"); #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 eff78291..56525ed1 100644 --- a/server/AyaNova/SwaggerDefaultValues.cs +++ b/server/AyaNova/SwaggerDefaultValues.cs @@ -1,47 +1,69 @@ -// namespace AyaNova -// { -// using Swashbuckle.AspNetCore.SwaggerGen; -// using System.Linq; +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; + } + } + } -// /// -// /// 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; -// } -// if ( routeInfo == null ) -// { -// continue; -// } +// 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 ( parameter.Default == null ) -// { -// parameter.Default = routeInfo.DefaultValue; -// } + if (authAttributes.Any()) + operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" }); + } +} + +} -// parameter.Required |= !routeInfo.IsOptional; -// } -// } -// } -// } \ No newline at end of file