diff --git a/paket.dependencies b/paket.dependencies index c5ef189c0..88899c4dd 100644 --- a/paket.dependencies +++ b/paket.dependencies @@ -49,7 +49,7 @@ nuget Be.Vlaanderen.Basisregisters.IntegrationDb.SuspiciousCases.Api.Abstraction nuget Be.Vlaanderen.Basisregisters.Build.Pipeline 7.2.4 nuget Be.Vlaanderen.Basisregisters.Auth.AcmIdm 2.0.0 -nuget Be.Vlaanderen.Basisregisters.Api 21.1.0 +nuget Be.Vlaanderen.Basisregisters.Api 22.0.0 // DataDog To Remove after testing nuget Be.Vlaanderen.Basisregisters.DataDog.Tracing 6.0.0 diff --git a/paket.lock b/paket.lock index a441b79e2..1bac294c5 100644 --- a/paket.lock +++ b/paket.lock @@ -63,7 +63,7 @@ NUGET Be.Vlaanderen.Basisregisters.AggregateSource (9.0.1) Be.Vlaanderen.Basisregisters.EventHandling (>= 5.0) SqlStreamStore (>= 1.2) - Be.Vlaanderen.Basisregisters.Api (21.1) + Be.Vlaanderen.Basisregisters.Api (22.0) Asp.Versioning.Mvc.ApiExplorer (>= 8.0) Autofac (>= 8.0) Autofac.Extensions.DependencyInjection (>= 9.0) diff --git a/src/Public.Api/ErrorDetail/ErrorDetailController.cs b/src/Public.Api/ErrorDetail/ErrorDetailController.cs index 275d7bf6d..8a1262777 100644 --- a/src/Public.Api/ErrorDetail/ErrorDetailController.cs +++ b/src/Public.Api/ErrorDetail/ErrorDetailController.cs @@ -13,7 +13,7 @@ namespace Public.Api.ErrorDetail using Microsoft.Extensions.Configuration; using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [ApiVersion(Version.V2)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] diff --git a/src/Public.Api/Infrastructure/Startup.cs b/src/Public.Api/Infrastructure/Startup.cs index 6f88d1519..7cf83dfe7 100644 --- a/src/Public.Api/Infrastructure/Startup.cs +++ b/src/Public.Api/Infrastructure/Startup.cs @@ -203,7 +203,6 @@ public IServiceProvider ConfigureServices(IServiceCollection services) builder .AddMvcOptions(options => { - options.Conventions.Add(new FeatureToggleConvention(_configuration)); //GRAR-1877 options.ModelBindingMessageProvider.SetAttemptedValueIsInvalidAccessor((value,fieldName) => $"De waarde '{value}' is ongeldig voor {fieldName}."); @@ -272,9 +271,13 @@ public IServiceProvider ConfigureServices(IServiceCollection services) .RewriteAcceptTypeForProblemDetail(); } }, - ActionModelConventions = { new ApiDocumentationHiddenConvention() } + ActionModelConventions = + { + new ApiVisibleActionModelConvention(), + new FeatureToggleConvention(_configuration) + } } - .EnableJsonErrorActionFilterOption()) + .EnableJsonErrorActionFilterOption()) .AddHttpClient() @@ -408,8 +411,7 @@ public IServiceProvider ConfigureServices(IServiceCollection services) .AddSingleton(c => new DetailSuspiciousCasesToggle(c.GetRequiredService>().Value.GetSuspiciousCases)); services - .RemoveAll() - .TryAddEnumerable(ServiceDescriptor.Transient()); + .RemoveAll(); var containerBuilder = new ContainerBuilder(); diff --git a/src/Public.Api/Infrastructure/Swagger/ApiDocumentationHiddenConvention.cs b/src/Public.Api/Infrastructure/Swagger/ApiDocumentationHiddenConvention.cs deleted file mode 100644 index 2b85ffd0a..000000000 --- a/src/Public.Api/Infrastructure/Swagger/ApiDocumentationHiddenConvention.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Public.Api.Infrastructure.Swagger -{ - using System.Collections.Generic; - using Microsoft.AspNetCore.Mvc.ApplicationModels; - - public class ApiDocumentationHiddenConvention : IActionModelConvention - { - public void Apply(ActionModel action) - { - var hiddenMethods = new List - { - "CompleteTicket", - "CreateTicket", - "DeleteTicket", - "GetTickets", - "PendingTicket" - }; - - if (hiddenMethods.Contains(action.ActionMethod.Name)) - { - action.ApiExplorer.IsVisible = false; - } - } - } -} diff --git a/src/Public.Api/Infrastructure/Swagger/ApiVisibleActionModelConvention.cs b/src/Public.Api/Infrastructure/Swagger/ApiVisibleActionModelConvention.cs new file mode 100644 index 000000000..86d43180b --- /dev/null +++ b/src/Public.Api/Infrastructure/Swagger/ApiVisibleActionModelConvention.cs @@ -0,0 +1,25 @@ +namespace Public.Api.Infrastructure.Swagger; + +using System.Linq; +using System.Reflection; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.ApplicationModels; + +public class ApiVisibleActionModelConvention : IActionModelConvention +{ + public void Apply(ActionModel action) + { + var actionIgnored = action.ActionMethod.GetCustomAttribute()?.IgnoreApi == true; + if (actionIgnored) + { + return; + } + + var isVisible = action.Controller.ControllerType + .GetCustomAttributes(true) + .Select(x => x.Visible) + .FirstOrDefault(); + + action.ApiExplorer.IsVisible = isVisible; + } +} diff --git a/src/Public.Api/Infrastructure/Swagger/ApiVisibleAttribute.cs b/src/Public.Api/Infrastructure/Swagger/ApiVisibleAttribute.cs new file mode 100644 index 000000000..2615a6af2 --- /dev/null +++ b/src/Public.Api/Infrastructure/Swagger/ApiVisibleAttribute.cs @@ -0,0 +1,13 @@ +namespace Public.Api.Infrastructure.Swagger +{ + using System; + + [AttributeUsage(AttributeTargets.Class)] + public class ApiVisibleAttribute : Attribute + { + public bool Visible { get; } + + public ApiVisibleAttribute() : this(true) { } + public ApiVisibleAttribute(bool visible) => Visible = visible; + } +} diff --git a/src/Public.Api/Infrastructure/Swagger/ToggledApiControllerSpec.cs b/src/Public.Api/Infrastructure/Swagger/ToggledApiControllerSpec.cs deleted file mode 100755 index 59bd5f1b3..000000000 --- a/src/Public.Api/Infrastructure/Swagger/ToggledApiControllerSpec.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace Public.Api.Infrastructure.Swagger -{ - using System; - using System.Linq; - using System.Reflection; - using Asp.Versioning.ApplicationModels; - using Common.Infrastructure; - using Feeds.V2; - using Microsoft.AspNetCore.Mvc.ApplicationModels; - - [AttributeUsage(AttributeTargets.Class)] - public class ApiVisibleAttribute : Attribute - { - public bool Visible { get; } - - public ApiVisibleAttribute() : this(true) { } - public ApiVisibleAttribute(bool visible) => Visible = visible; - } - - public class ToggledApiControllerSpec : IApiControllerSpecification - { - private readonly FeedsVisibleToggle _feedsVisibleToggle; - - public ToggledApiControllerSpec(FeedsVisibleToggle feedsVisibleToggle) - { - _feedsVisibleToggle = feedsVisibleToggle; - } - - public bool IsSatisfiedBy(ControllerModel controller) - { - var apiVisibility = controller - .ControllerType - .GetCustomAttributes(true) - .Select(x => x.Visible) - .ToList(); - - if (controller.ApiExplorer.GroupName == FeedV2Controller.FeedsGroupName) - return _feedsVisibleToggle.FeatureEnabled; - - return apiVisibility.Count != 0 && apiVisibility.First(); - } - } -} diff --git a/src/Public.Api/Infrastructure/Version/Version.cs b/src/Public.Api/Infrastructure/Version/Version.cs index 95b6969a5..63e1bfb0a 100644 --- a/src/Public.Api/Infrastructure/Version/Version.cs +++ b/src/Public.Api/Infrastructure/Version/Version.cs @@ -3,7 +3,7 @@ namespace Public.Api.Infrastructure.Version public static class Version { // TODO: remove current when road is v2 - public const string Current = "1.0"; + public const string V1 = "1.0"; public const string CurrentAdvertised = "2.0"; public const string V2 = "2.0"; } diff --git a/src/Public.Api/Road/Changes/ChangeFeedController.cs b/src/Public.Api/Road/Changes/ChangeFeedController.cs index 2dcaabc49..8ccef4833 100755 --- a/src/Public.Api/Road/Changes/ChangeFeedController.cs +++ b/src/Public.Api/Road/Changes/ChangeFeedController.cs @@ -13,7 +13,7 @@ namespace Public.Api.Road.Changes using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.Logging; - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Activiteit")] diff --git a/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetContent.cs b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetContent.cs new file mode 100644 index 000000000..84dbb3988 --- /dev/null +++ b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetContent.cs @@ -0,0 +1,32 @@ +namespace Public.Api.Road.Changes.V2 +{ + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + using System.Threading; + using System.Threading.Tasks; + + public partial class ChangeFeedControllerV2 + { + [HttpGet("wegen/activiteit/gebeurtenis/{id}/inhoud", Name = nameof(GetContentV2))] + public async Task GetContentV2( + [FromRoute] long? id, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "changefeed/entry/{id}/content") + .AddParameter(nameof(id), id, ParameterType.UrlSegment); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetHead.cs b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetHead.cs new file mode 100644 index 000000000..cf4b93561 --- /dev/null +++ b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetHead.cs @@ -0,0 +1,34 @@ +namespace Public.Api.Road.Changes.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class ChangeFeedControllerV2 + { + [HttpGet("wegen/activiteit/begin", Name = nameof(GetHeadV2))] + public async Task GetHeadV2( + [FromQuery] int? maxEntryCount, + [FromQuery] string? filter, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "changefeed/head") + .AddParameter(nameof(maxEntryCount), maxEntryCount, ParameterType.QueryString) + .AddParameter(nameof(filter), filter, ParameterType.QueryString); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetNext.cs b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetNext.cs new file mode 100644 index 000000000..419cad125 --- /dev/null +++ b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetNext.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Changes.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class ChangeFeedControllerV2 + { + [HttpGet("wegen/activiteit/volgende", Name = nameof(GetNextV2))] + public async Task GetNextV2( + [FromQuery] long? afterEntry, + [FromQuery] int? maxEntryCount, + [FromQuery] string? filter, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "changefeed/next") + .AddParameter(nameof(maxEntryCount), maxEntryCount, ParameterType.QueryString) + .AddParameter(nameof(afterEntry), afterEntry, ParameterType.QueryString) + .AddParameter(nameof(filter), filter, ParameterType.QueryString); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetPrevious.cs b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetPrevious.cs new file mode 100644 index 000000000..5bedfd324 --- /dev/null +++ b/src/Public.Api/Road/Changes/V2/ChangeFeedController-GetPrevious.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Changes.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class ChangeFeedControllerV2 + { + [HttpGet("wegen/activiteit/vorige", Name = nameof(GetPreviousV2))] + public async Task GetPreviousV2( + [FromQuery] long? beforeEntry, + [FromQuery] int? maxEntryCount, + [FromQuery] string? filter, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "changefeed/previous") + .AddParameter(nameof(maxEntryCount), maxEntryCount, ParameterType.QueryString) + .AddParameter(nameof(beforeEntry), beforeEntry, ParameterType.QueryString) + .AddParameter(nameof(filter), filter, ParameterType.QueryString); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Changes/V2/ChangeFeedControllerV2.cs b/src/Public.Api/Road/Changes/V2/ChangeFeedControllerV2.cs new file mode 100644 index 000000000..5641a7100 --- /dev/null +++ b/src/Public.Api/Road/Changes/V2/ChangeFeedControllerV2.cs @@ -0,0 +1,35 @@ +namespace Public.Api.Road.Changes.V2 +{ + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Activiteit")] + [ApiOrder(ApiOrder.Road.ChangeFeed)] + public partial class ChangeFeedControllerV2 : RoadRegistryApiController + { + protected override string NotFoundExceptionMessage => "Onbestaande activiteit."; + protected override string GoneExceptionMessage => "Verwijderde activiteit."; + + public ChangeFeedControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) { } + } +} diff --git a/src/Public.Api/Road/Downloads/DownloadController.cs b/src/Public.Api/Road/Downloads/DownloadController.cs index 3d3b65dfb..29a82f9c7 100755 --- a/src/Public.Api/Road/Downloads/DownloadController.cs +++ b/src/Public.Api/Road/Downloads/DownloadController.cs @@ -15,7 +15,7 @@ namespace Public.Api.Road.Downloads using System.Net.Http; using Asp.Versioning; - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Download")] diff --git a/src/Public.Api/Road/Downloads/V2/DownloadController-GetForEditor.cs b/src/Public.Api/Road/Downloads/V2/DownloadController-GetForEditor.cs new file mode 100644 index 000000000..a9de33172 --- /dev/null +++ b/src/Public.Api/Road/Downloads/V2/DownloadController-GetForEditor.cs @@ -0,0 +1,31 @@ +namespace Public.Api.Road.Downloads.V2 +{ + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + + public partial class DownloadControllerV2 + { + [HttpGet("wegen/download/voor-editor")] + public async Task GetForEditorV2( + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + HttpRequestMessage BackendRequest() => + CreateBackendHttpRequestMessage(HttpMethod.Get, "download/for-editor"); + + var response = await GetFromBackendWithBadRequestAsync( + _httpClient, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken + ); + + return response.ToActionResult(); + } + } +} diff --git a/src/Public.Api/Road/Downloads/V2/DownloadController-GetForProduct.cs b/src/Public.Api/Road/Downloads/V2/DownloadController-GetForProduct.cs new file mode 100644 index 000000000..cb8fd66cd --- /dev/null +++ b/src/Public.Api/Road/Downloads/V2/DownloadController-GetForProduct.cs @@ -0,0 +1,32 @@ +namespace Public.Api.Road.Downloads.V2 +{ + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + + public partial class DownloadControllerV2 + { + [HttpGet("wegen/download/voor-product/{datum}")] + public async Task GetForProductV2( + [FromRoute] string datum, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + HttpRequestMessage BackendRequest() => + CreateBackendHttpRequestMessage(HttpMethod.Get, $"download/for-product/{datum}"); + + var response = await GetFromBackendWithBadRequestAsync( + _httpClient, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken + ); + + return response.ToActionResult(); + } + } +} diff --git a/src/Public.Api/Road/Downloads/V2/DownloadController.cs b/src/Public.Api/Road/Downloads/V2/DownloadController.cs new file mode 100644 index 000000000..8ff836228 --- /dev/null +++ b/src/Public.Api/Road/Downloads/V2/DownloadController.cs @@ -0,0 +1,43 @@ +namespace Public.Api.Road.Downloads.V2 +{ + using System.Net.Http; + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using Common.Infrastructure.Controllers.Attributes; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Download")] + [ApiOrder(ApiOrder.Road.Download)] + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + public partial class DownloadControllerV2 : RoadRegistryApiController + { + private readonly HttpClient _httpClient; + protected override string NotFoundExceptionMessage => "Onbestaande download."; + protected override string GoneExceptionMessage => "Verwijderde download."; + + public DownloadControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] HttpClient httpClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) + { + _httpClient = httpClient; + } + } +} diff --git a/src/Public.Api/Road/Extracts/ExtractController.cs b/src/Public.Api/Road/Extracts/ExtractController.cs index 5d5509b9c..824169522 100755 --- a/src/Public.Api/Road/Extracts/ExtractController.cs +++ b/src/Public.Api/Road/Extracts/ExtractController.cs @@ -14,7 +14,7 @@ namespace Public.Api.Road.Extracts using System.Net.Http; using Asp.Versioning; - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Extract")] diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-CreateJob.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-CreateJob.cs new file mode 100644 index 000000000..070986dc9 --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-CreateJob.cs @@ -0,0 +1,51 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Common.Infrastructure.Extensions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Public.Api.Infrastructure; + using RestSharp; + using RoadRegistry.BackOffice.Abstractions.Jobs; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class ExtractControllerV2 + { + [ProducesResponseType(typeof(GetPresignedUploadUrlResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [HttpPost("wegen/extract/download/{downloadId}/jobs", Name = nameof(RoadExtractCreateJobV2))] + public async Task RoadExtractCreateJobV2( + [FromRoute] string downloadId, + [FromServices] IActionContextAccessor actionContextAccessor, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] RoadJobsToggle featureToggle, + CancellationToken cancellationToken = default) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(actionContextAccessor.ActionContext); + + RestRequest BackendRequest() => new RestRequest($"extracts/download/{downloadId}/jobs", Method.Post) + .AddHeaderAuthorization(actionContextAccessor); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequests.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequests.cs new file mode 100644 index 000000000..6e35be971 --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequests.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + using RoadRegistry.BackOffice.Api.Extracts; + + public partial class ExtractControllerV2 + { + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + [HttpPost("wegen/extract/downloadaanvragen")] + public async Task PostDownloadRequestV2( + [FromBody]DownloadExtractRequestBody body, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "extracts/downloadrequests") + .AddParameter(nameof(body), body, ParameterType.RequestBody); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByContour.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByContour.cs new file mode 100644 index 000000000..13c69640e --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByContour.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + using RoadRegistry.BackOffice.Api.Extracts; + + public partial class ExtractControllerV2 + { + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + [HttpPost("wegen/extract/downloadaanvragen/percontour")] + public async Task PostDownloadRequestByContourV2( + [FromBody] DownloadExtractByContourRequestBody body, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, "extracts/downloadrequests/bycontour") + .AddJsonBodyOrEmpty(body); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByFile.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByFile.cs new file mode 100644 index 000000000..967c573cd --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByFile.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + using RoadRegistry.BackOffice.Api.Extracts; + + public partial class ExtractControllerV2 + { + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + [HttpPost("wegen/extract/downloadaanvragen/perbestand")] + public async Task PostDownloadRequestByFileV2( + [FromBody] DownloadExtractByFileRequestBody body, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, "extracts/downloadrequests/byfile") + .AddJsonBodyOrEmpty(body); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByNisCode.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByNisCode.cs new file mode 100644 index 000000000..10cbe98bd --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-DownloadRequestsByNisCode.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + using RoadRegistry.BackOffice.Api.Extracts; + + public partial class ExtractControllerV2 + { + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + [HttpPost("wegen/extract/downloadaanvragen/perniscode")] + public async Task PostDownloadRequestByNisCodeV2( + [FromBody] DownloadExtractByNisCodeRequestBody body, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, "extracts/downloadrequests/byniscode") + .AddJsonBodyOrEmpty(body); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-GetDownload.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-GetDownload.cs new file mode 100644 index 000000000..075ab58f1 --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-GetDownload.cs @@ -0,0 +1,34 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + + public partial class ExtractControllerV2 + { + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + [HttpPost("wegen/extract/download/{downloadId}")] + public async Task PostDownloadRequestV2( + [FromRoute]string downloadId, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + HttpRequestMessage BackendRequest() => + CreateBackendHttpRequestMessage(HttpMethod.Get, $"extracts/download/{downloadId}"); + + var response = await GetFromBackendWithBadRequestAsync( + _httpClient, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken + ); + + return response.ToActionResult(); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-GetOverlappingTransactionZonesGeoJson.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-GetOverlappingTransactionZonesGeoJson.cs new file mode 100644 index 000000000..1f2698aa8 --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-GetOverlappingTransactionZonesGeoJson.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class ExtractControllerV2 + { + [HttpGet("wegen/extract/overlappingtransactionzones.geojson")] + public async Task GetOverlappingTransactionZonesGeoJsonV2( + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "extracts/overlappingtransactionzones.geojson"); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + var options = new BackendResponseResultOptions + { + ForwardHeaders = new[] {"Retry-After"} + }; + + return response.ToActionResult(options); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-GetStatus.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-GetStatus.cs new file mode 100644 index 000000000..c1c827900 --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-GetStatus.cs @@ -0,0 +1,40 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class ExtractControllerV2 + { + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + [HttpGet("wegen/extract/upload/{uploadId}/status")] + public async Task GetStatusV2( + [FromRoute]string uploadId, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "extracts/upload/{uploadId}/status") + .AddParameter(nameof(uploadId), uploadId, ParameterType.UrlSegment); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + var options = new BackendResponseResultOptions + { + ForwardHeaders = new[] {"Retry-After"} + }; + + return response.ToActionResult(options); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController-GetTransactionZonesGeoJson.cs b/src/Public.Api/Road/Extracts/V2/ExtractController-GetTransactionZonesGeoJson.cs new file mode 100644 index 000000000..35bdf773a --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController-GetTransactionZonesGeoJson.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class ExtractControllerV2 + { + [HttpGet("wegen/extract/transactionzones.geojson")] + public async Task GetTransactionZonesGeoJsonV2( + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "extracts/transactionzones.geojson"); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + var options = new BackendResponseResultOptions + { + ForwardHeaders = new[] {"Retry-After"} + }; + + return response.ToActionResult(options); + } + } +} diff --git a/src/Public.Api/Road/Extracts/V2/ExtractController.cs b/src/Public.Api/Road/Extracts/V2/ExtractController.cs new file mode 100644 index 000000000..51c528084 --- /dev/null +++ b/src/Public.Api/Road/Extracts/V2/ExtractController.cs @@ -0,0 +1,44 @@ +namespace Public.Api.Road.Extracts.V2 +{ + using System.Net.Http; + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Extract")] + [ApiOrder(ApiOrder.Road.RoadExtract)] + public partial class ExtractControllerV2 : RoadRegistryApiController + { + private readonly HttpClient _httpClient; + protected override string NotFoundExceptionMessage => "Onbestaand extract."; + protected override string GoneExceptionMessage => "Verwijderd extract."; + + public ExtractControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] HttpClient httpClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) + { + _httpClient = httpClient; + } + + private static ContentFormat DetermineFormat(ActionContext context) + => ContentFormat.For(EndpointType.BackOffice, context); + } +} diff --git a/src/Public.Api/Road/Information/InformationController.cs b/src/Public.Api/Road/Information/InformationController.cs index 392a0dd4d..4f3b7a624 100755 --- a/src/Public.Api/Road/Information/InformationController.cs +++ b/src/Public.Api/Road/Information/InformationController.cs @@ -13,7 +13,7 @@ namespace Public.Api.Road.Information using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.Logging; - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Informatie")] diff --git a/src/Public.Api/Road/Information/V2/InformationController-GetInformation.cs b/src/Public.Api/Road/Information/V2/InformationController-GetInformation.cs new file mode 100644 index 000000000..5b0f71f88 --- /dev/null +++ b/src/Public.Api/Road/Information/V2/InformationController-GetInformation.cs @@ -0,0 +1,26 @@ +namespace Public.Api.Road.Information.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class InformationControllerV2 + { + [HttpGet("wegen/informatie", Name = nameof(GetInformationV2))] + public async Task GetInformationV2(CancellationToken cancellationToken) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "information"); + + var response = await GetFromBackendAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + cancellationToken); + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Information/V2/InformationController-ValidateWKT.cs b/src/Public.Api/Road/Information/V2/InformationController-ValidateWKT.cs new file mode 100644 index 000000000..e979b0d76 --- /dev/null +++ b/src/Public.Api/Road/Information/V2/InformationController-ValidateWKT.cs @@ -0,0 +1,36 @@ +namespace Public.Api.Road.Information.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + using RoadRegistry.BackOffice.Api.Information; + + public partial class InformationControllerV2 + { + [HttpPost("wegen/informatie/valideer-wkt")] + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + public async Task PostValidateWktContourRequestV2( + [FromBody] ValidateWktContourRequestBody body, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken = default) + { + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, "information/validate-wkt") + .AddJsonBodyOrEmpty(body); + + var response = await GetFromBackendWithBadRequestAsync( + AcceptType.Json, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(response); + } + } +} diff --git a/src/Public.Api/Road/Information/V2/InformationController.cs b/src/Public.Api/Road/Information/V2/InformationController.cs new file mode 100644 index 000000000..2bcae4d76 --- /dev/null +++ b/src/Public.Api/Road/Information/V2/InformationController.cs @@ -0,0 +1,37 @@ +namespace Public.Api.Road.Information.V2 +{ + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Informatie")] + [ApiOrder(ApiOrder.Road.Information)] + public partial class InformationControllerV2 : RoadRegistryApiController + { + protected override string NotFoundExceptionMessage => "Onbestaande informatie."; + protected override string GoneExceptionMessage => "Verwijderde informatie."; + + public InformationControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) + { + } + } +} diff --git a/src/Public.Api/Road/Organizations/OrganizationsController-Get.cs b/src/Public.Api/Road/Organizations/OrganizationsController-Get.cs index 00d1a8c2b..72d36429f 100644 --- a/src/Public.Api/Road/Organizations/OrganizationsController-Get.cs +++ b/src/Public.Api/Road/Organizations/OrganizationsController-Get.cs @@ -19,7 +19,7 @@ public partial class OrganizationsController private const string GetOrganizationsRoute = "wegen/organisaties"; /// - /// Vraag een lijst met organisaties op. + /// Vraag een lijst met organisaties op (v1). /// /// /// diff --git a/src/Public.Api/Road/Organizations/OrganizationsController.cs b/src/Public.Api/Road/Organizations/OrganizationsController.cs index 28d3afc73..20a48ccd9 100644 --- a/src/Public.Api/Road/Organizations/OrganizationsController.cs +++ b/src/Public.Api/Road/Organizations/OrganizationsController.cs @@ -15,7 +15,7 @@ namespace Public.Api.Road.Organizations using Microsoft.Extensions.Logging; [ApiVisible] - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Wegen")] diff --git a/src/Public.Api/Road/Organizations/V2/OrganizationsController-Get.cs b/src/Public.Api/Road/Organizations/V2/OrganizationsController-Get.cs new file mode 100644 index 000000000..aa268cd8f --- /dev/null +++ b/src/Public.Api/Road/Organizations/V2/OrganizationsController-Get.cs @@ -0,0 +1,65 @@ +namespace Public.Api.Road.Organizations.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.Organizations; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class OrganizationsControllerV2 + { + private const string GetOrganizationsRoute = "wegen/organisaties"; + + /// + /// Vraag een lijst met organisaties op (v2). + /// + /// + /// + /// + /// Als de opvraging van een lijst met organisaties gelukt is. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpGet(GetOrganizationsRoute, Name = nameof(GetV2))] + [ApiOrder(ApiOrder.Road.Organization + 1)] + [ProducesResponseType(typeof(GetOrganizationsResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseExample(StatusCodes.Status200OK, typeof(GetOrganizationsResponseResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerOperation(OperationId = nameof(GetV2))] + public async Task GetV2( + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] GetRoadOrganizationsToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "organizations"); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForRead()); + } + } +} diff --git a/src/Public.Api/Road/Organizations/V2/OrganizationsController.cs b/src/Public.Api/Road/Organizations/V2/OrganizationsController.cs new file mode 100644 index 000000000..a341d423c --- /dev/null +++ b/src/Public.Api/Road/Organizations/V2/OrganizationsController.cs @@ -0,0 +1,46 @@ +namespace Public.Api.Road.Organizations.V2 +{ + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using Common.Infrastructure.Controllers.Attributes; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + + [ApiVisible] + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Wegen")] + [ApiConsumes(EndpointType.BackOffice)] + [ApiProduces(EndpointType.BackOffice)] + [ApiOrder(ApiOrder.Road.RoadSegment)] + public partial class OrganizationsControllerV2 : RoadRegistryApiController + { + protected override string NotFoundExceptionMessage => "Onbestaande organisatie."; + protected override string GoneExceptionMessage => "Verwijderde organisatie."; + + public OrganizationsControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) + { + } + + private ContentFormat DetermineFormat() + { + return ContentFormat.For(EndpointType.BackOffice, ActionContextAccessor.ActionContext); + } + } +} diff --git a/src/Public.Api/Road/Security/SecurityController.cs b/src/Public.Api/Road/Security/SecurityController.cs index 73274eccc..024257edd 100644 --- a/src/Public.Api/Road/Security/SecurityController.cs +++ b/src/Public.Api/Road/Security/SecurityController.cs @@ -13,7 +13,7 @@ namespace Public.Api.Road.Security using Microsoft.AspNetCore.Mvc.Infrastructure; using Microsoft.Extensions.Logging; - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Security")] diff --git a/src/Public.Api/Road/Security/V2/SecurityController-ExchangeCode.cs b/src/Public.Api/Road/Security/V2/SecurityController-ExchangeCode.cs new file mode 100644 index 000000000..55ad3429d --- /dev/null +++ b/src/Public.Api/Road/Security/V2/SecurityController-ExchangeCode.cs @@ -0,0 +1,39 @@ +namespace Public.Api.Road.Security.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class SecurityControllerV2 + { + [HttpGet("wegen/security/exchange", Name = nameof(ExchangeCodeV2))] + public async Task ExchangeCodeV2( + string code, + string verifier, + string? redirectUri, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken) + { + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "security/exchange") + .AddParameter("code", code) + .AddParameter("verifier", verifier) + .AddParameter("redirectUri", redirectUri); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForRead()); + } + } +} diff --git a/src/Public.Api/Road/Security/V2/SecurityController-GetUser.cs b/src/Public.Api/Road/Security/V2/SecurityController-GetUser.cs new file mode 100644 index 000000000..53b7baab4 --- /dev/null +++ b/src/Public.Api/Road/Security/V2/SecurityController-GetUser.cs @@ -0,0 +1,35 @@ +namespace Public.Api.Road.Security.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure.Controllers.Attributes; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class SecurityControllerV2 + { + [HttpGet("wegen/security/user", Name = nameof(GetUserV2))] + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + public async Task GetUserV2( + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken) + { + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "security/user"); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForRead()); + } + } +} diff --git a/src/Public.Api/Road/Security/V2/SecurityController-Info.cs b/src/Public.Api/Road/Security/V2/SecurityController-Info.cs new file mode 100644 index 000000000..4950d7085 --- /dev/null +++ b/src/Public.Api/Road/Security/V2/SecurityController-Info.cs @@ -0,0 +1,33 @@ +namespace Public.Api.Road.Security.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using RestSharp; + + public partial class SecurityControllerV2 + { + [HttpGet("wegen/security/info", Name = nameof(InfoV2))] + public async Task InfoV2( + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken) + { + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, "security/info"); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForRead()); + } + } +} diff --git a/src/Public.Api/Road/Security/V2/SecurityController.cs b/src/Public.Api/Road/Security/V2/SecurityController.cs new file mode 100644 index 000000000..8a8128584 --- /dev/null +++ b/src/Public.Api/Road/Security/V2/SecurityController.cs @@ -0,0 +1,42 @@ +namespace Public.Api.Road.Security.V2 +{ + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Security")] + [ApiOrder(ApiOrder.Road.RoadUpload)] + public partial class SecurityControllerV2 : RoadRegistryApiController + { + protected override string NotFoundExceptionMessage => "Onbestaande security."; + protected override string GoneExceptionMessage => "Verwijderde security."; + + public SecurityControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) + { + } + + private ContentFormat DetermineFormat() + { + return ContentFormat.For(EndpointType.BackOffice, ActionContextAccessor.ActionContext); + } + } +} diff --git a/src/Public.Api/Road/Uploads/UploadController.cs b/src/Public.Api/Road/Uploads/UploadController.cs index 08da7acb4..f6ac6fafd 100644 --- a/src/Public.Api/Road/Uploads/UploadController.cs +++ b/src/Public.Api/Road/Uploads/UploadController.cs @@ -15,7 +15,7 @@ namespace Public.Api.Road.Uploads using System.Net.Http; using Asp.Versioning; - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Upload")] diff --git a/src/Public.Api/Road/Uploads/V2/UploadController-CancelJob.cs b/src/Public.Api/Road/Uploads/V2/UploadController-CancelJob.cs new file mode 100644 index 000000000..b76302a70 --- /dev/null +++ b/src/Public.Api/Road/Uploads/V2/UploadController-CancelJob.cs @@ -0,0 +1,53 @@ +namespace Public.Api.Road.Uploads.V2 +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Common.Infrastructure.Extensions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Public.Api.Infrastructure; + using RestSharp; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class UploadControllerV2 + { + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [HttpDelete("wegen/upload/jobs/{objectId}", Name = nameof(RoadUploadCancelJobV2))] + public async Task RoadUploadCancelJobV2( + [FromServices] IActionContextAccessor actionContextAccessor, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] RoadJobsToggle featureToggle, + [FromRoute] Guid objectId, + CancellationToken cancellationToken = default) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(actionContextAccessor.ActionContext); + + RestRequest BackendRequest() => new RestRequest("upload/jobs/{objectId}", Method.Delete) + .AddParameter("objectId", objectId, ParameterType.UrlSegment) + .AddHeaderAuthorization(actionContextAccessor); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + + } +} diff --git a/src/Public.Api/Road/Uploads/V2/UploadController-CreateJob.cs b/src/Public.Api/Road/Uploads/V2/UploadController-CreateJob.cs new file mode 100644 index 000000000..e411ce9d2 --- /dev/null +++ b/src/Public.Api/Road/Uploads/V2/UploadController-CreateJob.cs @@ -0,0 +1,50 @@ +namespace Public.Api.Road.Uploads.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Common.Infrastructure.Extensions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Public.Api.Infrastructure; + using RestSharp; + using RoadRegistry.BackOffice.Abstractions.Jobs; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class UploadControllerV2 + { + [ProducesResponseType(typeof(GetPresignedUploadUrlResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [HttpPost("wegen/upload/jobs", Name = nameof(RoadUploadCreateJobV2))] + public async Task RoadUploadCreateJobV2( + [FromServices] IActionContextAccessor actionContextAccessor, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] RoadJobsToggle featureToggle, + CancellationToken cancellationToken = default) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(actionContextAccessor.ActionContext); + + RestRequest BackendRequest() => new RestRequest("upload/jobs", Method.Post) + .AddHeaderAuthorization(actionContextAccessor); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/Road/Uploads/V2/UploadController-Get.cs b/src/Public.Api/Road/Uploads/V2/UploadController-Get.cs new file mode 100644 index 000000000..7efc3dfab --- /dev/null +++ b/src/Public.Api/Road/Uploads/V2/UploadController-Get.cs @@ -0,0 +1,32 @@ +namespace Public.Api.Road.Uploads.V2 +{ + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + + public partial class UploadControllerV2 + { + [HttpGet("wegen/upload/{identifier}", Name = nameof(RoadGetUploadV2))] + public async Task RoadGetUploadV2( + [FromRoute] string identifier, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + CancellationToken cancellationToken) + { + HttpRequestMessage BackendRequest() => + CreateBackendHttpRequestMessage(HttpMethod.Get, $"upload/{identifier}"); + + var response = await GetFromBackendWithBadRequestAsync( + _httpClient, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken + ); + + return response.ToActionResult(); + } + } +} diff --git a/src/Public.Api/Road/Uploads/V2/UploadController-GetActiveJobs.cs b/src/Public.Api/Road/Uploads/V2/UploadController-GetActiveJobs.cs new file mode 100644 index 000000000..7010a74d7 --- /dev/null +++ b/src/Public.Api/Road/Uploads/V2/UploadController-GetActiveJobs.cs @@ -0,0 +1,49 @@ +namespace Public.Api.Road.Uploads.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Common.Infrastructure.Extensions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Public.Api.Infrastructure; + using RestSharp; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class UploadControllerV2 + { + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [HttpGet("wegen/upload/jobs/active", Name = nameof(RoadUploadGetActiveJobsV2))] + public async Task RoadUploadGetActiveJobsV2( + [FromServices] IActionContextAccessor actionContextAccessor, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] RoadJobsToggle featureToggle, + CancellationToken cancellationToken = default) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(actionContextAccessor.ActionContext); + + RestRequest BackendRequest() => new RestRequest("upload/jobs/active", Method.Get) + .AddHeaderAuthorization(actionContextAccessor); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/Road/Uploads/V2/UploadController-GetJob.cs b/src/Public.Api/Road/Uploads/V2/UploadController-GetJob.cs new file mode 100644 index 000000000..d9a5c1925 --- /dev/null +++ b/src/Public.Api/Road/Uploads/V2/UploadController-GetJob.cs @@ -0,0 +1,52 @@ +namespace Public.Api.Road.Uploads.V2 +{ + using System; + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Common.Infrastructure.Extensions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Public.Api.Infrastructure; + using RestSharp; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class UploadControllerV2 + { + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [HttpGet("wegen/upload/jobs/{jobId}", Name = nameof(RoadUploadGetJobV2))] + public async Task RoadUploadGetJobV2( + [FromServices] IActionContextAccessor actionContextAccessor, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] RoadJobsToggle featureToggle, + [FromRoute] Guid jobId, + CancellationToken cancellationToken = default) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(actionContextAccessor.ActionContext); + + RestRequest BackendRequest() => new RestRequest("upload/jobs/{jobId}", Method.Get) + .AddParameter("jobId", jobId, ParameterType.UrlSegment) + .AddHeaderAuthorization(actionContextAccessor); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/Road/Uploads/V2/UploadController-GetJobs.cs b/src/Public.Api/Road/Uploads/V2/UploadController-GetJobs.cs new file mode 100644 index 000000000..b80e83fde --- /dev/null +++ b/src/Public.Api/Road/Uploads/V2/UploadController-GetJobs.cs @@ -0,0 +1,49 @@ +namespace Public.Api.Road.Uploads.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Common.Infrastructure.Extensions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Public.Api.Infrastructure; + using RestSharp; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class UploadControllerV2 + { + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status401Unauthorized)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [HttpGet("wegen/upload/jobs", Name = nameof(RoadUploadGetJobsV2))] + public async Task RoadUploadGetJobsV2( + [FromServices] IActionContextAccessor actionContextAccessor, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] RoadJobsToggle featureToggle, + CancellationToken cancellationToken = default) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(actionContextAccessor.ActionContext); + + RestRequest BackendRequest() => new RestRequest("upload/jobs", Method.Get) + .AddHeaderAuthorization(actionContextAccessor); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/Road/Uploads/V2/UploadController.cs b/src/Public.Api/Road/Uploads/V2/UploadController.cs new file mode 100644 index 000000000..799acf8bd --- /dev/null +++ b/src/Public.Api/Road/Uploads/V2/UploadController.cs @@ -0,0 +1,46 @@ +namespace Public.Api.Road.Uploads.V2 +{ + using System.Net.Http; + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using Common.Infrastructure.Controllers.Attributes; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Upload")] + [ApiOrder(ApiOrder.Road.RoadUpload)] + [ApiKeyAuth("Road", AllowAuthorizationHeader = true)] + public partial class UploadControllerV2 : RoadRegistryApiController + { + private readonly HttpClient _httpClient; + protected override string NotFoundExceptionMessage => "Onbestaande upload."; + protected override string GoneExceptionMessage => "Verwijderde upload."; + + public UploadControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] HttpClient httpClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) + { + _httpClient = httpClient; + } + + private static ContentFormat DetermineFormat(ActionContext context) + => ContentFormat.For(EndpointType.BackOffice, context); + } +} diff --git a/src/Public.Api/RoadSegment/RoadSegmentController.cs b/src/Public.Api/RoadSegment/RoadSegmentController.cs index dcdbd9ffd..7aafff0bc 100644 --- a/src/Public.Api/RoadSegment/RoadSegmentController.cs +++ b/src/Public.Api/RoadSegment/RoadSegmentController.cs @@ -16,7 +16,7 @@ namespace Public.Api.RoadSegment using Road; [ApiVisible] - [ApiVersion(Version.Current)] + [ApiVersion(Version.V1)] [AdvertiseApiVersions(Version.CurrentAdvertised)] [ApiRoute("")] [ApiExplorerSettings(GroupName = "Wegen")] diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeAttributes.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeAttributes.cs new file mode 100644 index 000000000..22346e29d --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeAttributes.cs @@ -0,0 +1,85 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using RoadRegistry.BackOffice.Api.RoadSegments.ChangeAttributes; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string ChangeRoadSegmentAttributesRoute = "wegsegmenten/acties/wijzigen/attributen"; + + /// + /// Wijzig een attribuutwaarde voor één of meerdere wegsegmenten (v2). + /// + /// + /// + /// + /// + /// Als het wegsegment gevonden is. + /// Als uw verzoek foutieve data bevat. + /// Als het wegsegment niet gevonden kan worden. + /// Als de If-Match header niet overeenkomt met de laatste ETag. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpPost(ChangeRoadSegmentAttributesRoute, Name = nameof(ChangeRoadSegmentAttributesV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 2)] + [ProducesResponseType(StatusCodes.Status202Accepted)] + [ProducesResponseType(typeof(Be.Vlaanderen.Basisregisters.BasicApiProblem.ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "ETag", "string", "De ETag van de response.")] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "x-correlation-id", "string", "Correlatie identificator van de response.")] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status404NotFound, typeof(RoadSegmentNotFoundResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status412PreconditionFailed, typeof(PreconditionFailedResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerRequestExample(typeof(ChangeRoadSegmentAttributesParameters), typeof(ChangeRoadSegmentAttributesParametersExamples))] + [SwaggerAuthorizeOperation( + OperationId = nameof(ChangeRoadSegmentAttributesV2), + Description = "Attributen wijzigen van een wegsegment: status, toegangsbeperking, wegklasse, wegbeheerder en wegcategorie.", + Authorize = Scopes.DvWrAttribuutWaardenBeheer + )] + public async Task ChangeRoadSegmentAttributesV2( + [FromBody] ChangeRoadSegmentAttributesParameters request, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] ChangeRoadSegmentAttributesToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, ChangeRoadSegmentAttributesRoute) + .AddJsonBody(request); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeDynamicAttributes.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeDynamicAttributes.cs new file mode 100644 index 000000000..6f78f43a2 --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeDynamicAttributes.cs @@ -0,0 +1,85 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using RoadRegistry.BackOffice.Api.RoadSegments.ChangeDynamicAttributes; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string ChangeRoadSegmentDynamicAttributesRoute = "wegsegmenten/acties/wijzigen/dynamischeattributen"; + + /// + /// Wijzig een dynamisch attribuut voor één of meerdere wegsegmenten (v2). + /// + /// + /// + /// + /// + /// Als het wegsegment gevonden is. + /// Als uw verzoek foutieve data bevat. + /// Als het wegsegment niet gevonden kan worden. + /// Als de If-Match header niet overeenkomt met de laatste ETag. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpPost(ChangeRoadSegmentDynamicAttributesRoute, Name = nameof(ChangeRoadSegmentDynamicAttributesV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 3)] + [ProducesResponseType(StatusCodes.Status202Accepted)] + [ProducesResponseType(typeof(Be.Vlaanderen.Basisregisters.BasicApiProblem.ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "ETag", "string", "De ETag van de response.")] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "x-correlation-id", "string", "Correlatie identificator van de response.")] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status404NotFound, typeof(RoadSegmentNotFoundResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status412PreconditionFailed, typeof(PreconditionFailedResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerRequestExample(typeof(ChangeRoadSegmentsDynamicAttributesParameters), typeof(ChangeRoadSegmentsDynamicAttributesParametersExamples))] + [SwaggerAuthorizeOperation( + OperationId = nameof(ChangeRoadSegmentDynamicAttributesV2), + Description = "Dynamische attributen wijzigen van een wegsegment: wegverharding, wegbreedte en aantal rijstroken.", + Authorize = Scopes.DvWrAttribuutWaardenBeheer + )] + public async Task ChangeRoadSegmentDynamicAttributesV2( + [FromBody] ChangeRoadSegmentsDynamicAttributesParameters request, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] ChangeRoadSegmentDynamicAttributesToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, ChangeRoadSegmentDynamicAttributesRoute) + .AddJsonBody(request); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeOutlineGeometry.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeOutlineGeometry.cs new file mode 100644 index 000000000..037d7d1c0 --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-ChangeOutlineGeometry.cs @@ -0,0 +1,90 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string ChangeRoadSegmentOutlineGeometryRoute = "wegsegmenten/{id}/acties/wijzigen/schetsgeometrie"; + + /// + /// Wijzig de geometrie van een ingeschetst wegsegment (v2). + /// + /// Identificator van het wegsegment. + /// + /// + /// + /// + /// + /// Als het wegsegment gevonden is. + /// Als uw verzoek foutieve data bevat. + /// Als het wegsegment niet gevonden kan worden. + /// Als de If-Match header niet overeenkomt met de laatste ETag. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpPost(ChangeRoadSegmentOutlineGeometryRoute, Name = nameof(ChangeRoadSegmentOutlineGeometryV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 5)] + [ProducesResponseType(StatusCodes.Status202Accepted)] + [ProducesResponseType(typeof(Be.Vlaanderen.Basisregisters.BasicApiProblem.ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "ETag", "string", "De ETag van de response.")] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "x-correlation-id", "string", "Correlatie identificator van de response.")] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status404NotFound, typeof(RoadSegmentNotFoundResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status412PreconditionFailed, typeof(PreconditionFailedResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerRequestExample(typeof(PostChangeOutlineGeometryParameters), typeof(PostChangeOutlineGeometryParametersExamples))] + [SwaggerAuthorizeOperation( + OperationId = nameof(ChangeRoadSegmentOutlineGeometryV2), + Description = "Wijzig de geometrie van een wegsegment met geometriemethode 'ingeschetst'.", + Authorize = Scopes.DvWrGeschetsteWegBeheer + )] + public async Task ChangeRoadSegmentOutlineGeometryV2( + [FromRoute] string id, + [FromBody] PostChangeOutlineGeometryParameters request, + [FromServices] IActionContextAccessor actionContextAccessor, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] ChangeRoadSegmentOutlineGeometryToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, ChangeRoadSegmentOutlineGeometryRoute) + .AddJsonBody(request) + .AddParameter(nameof(id), id, ParameterType.UrlSegment); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-CreateOutline.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-CreateOutline.cs new file mode 100644 index 000000000..59195f397 --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-CreateOutline.cs @@ -0,0 +1,81 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string CreateRoadSegmentOutlineRoute = "wegsegmenten/acties/schetsen"; + + /// + /// Schets een wegsegment (v2). + /// + /// + /// + /// + /// + /// Als het wegsegment gevonden is. + /// Als uw verzoek foutieve data bevat. + /// Als de If-Match header niet overeenkomt met de laatste ETag. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpPost(CreateRoadSegmentOutlineRoute, Name = nameof(CreateRoadSegmentOutlineV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 4)] + [ProducesResponseType(StatusCodes.Status202Accepted)] + [ProducesResponseType(typeof(Be.Vlaanderen.Basisregisters.BasicApiProblem.ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "ETag", "string", "De ETag van de response.")] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "x-correlation-id", "string", "Correlatie identificator van de response.")] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status412PreconditionFailed, typeof(PreconditionFailedResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerRequestExample(typeof(PostRoadSegmentOutlineParameters), typeof(PostRoadSegmentOutlineParametersExamples))] + [SwaggerAuthorizeOperation( + OperationId = nameof(CreateRoadSegmentOutlineV2), + Description = "Voeg een nieuw wegsegment toe aan het Wegenregister met geometriemethode 'ingeschetst'.", + Authorize = Scopes.DvWrGeschetsteWegBeheer + )] + public async Task CreateRoadSegmentOutlineV2( + [FromBody] PostRoadSegmentOutlineParameters request, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] CreateRoadSegmentOutlineToggle featureToggle, + CancellationToken cancellationToken = default) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, CreateRoadSegmentOutlineRoute) + .AddJsonBody(request); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-DeleteOutline.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-DeleteOutline.cs new file mode 100644 index 000000000..6fe18b05d --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-DeleteOutline.cs @@ -0,0 +1,83 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string DeleteRoadSegmentOutlineRoute = "wegsegmenten/{id}/acties/verwijderen/schets"; + + /// + /// Verwijder een ingeschetst wegsegment (v2). + /// + /// Identificator van het wegsegment. + /// + /// + /// + /// Als het ingeschetst wegsegment gevonden is. + /// Als uw verzoek foutieve data bevat. + /// Als het ingeschetst wegsegment niet gevonden kan worden. + /// Als de If-Match header niet overeenkomt met de laatste ETag. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpPost(DeleteRoadSegmentOutlineRoute, Name = nameof(DeleteRoadSegmentOutlineV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 6)] + [ProducesResponseType(StatusCodes.Status202Accepted)] + [ProducesResponseType(typeof(Be.Vlaanderen.Basisregisters.BasicApiProblem.ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "ETag", "string", "De ETag van de response.")] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "x-correlation-id", "string", "Correlatie identificator van de response.")] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status404NotFound, typeof(RoadSegmentNotFoundResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status412PreconditionFailed, typeof(PreconditionFailedResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerAuthorizeOperation( + OperationId = nameof(DeleteRoadSegmentOutlineV2), + Description = "Verwijder een wegsegment met geometriemethode 'ingeschetst'.", + Authorize = Scopes.DvWrGeschetsteWegBeheer + )] + public async Task DeleteRoadSegmentOutlineV2( + [FromRoute] string id, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] DeleteRoadSegmentOutlineToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, DeleteRoadSegmentOutlineRoute) + .AddParameter(nameof(id), id, ParameterType.UrlSegment); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-Get.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-Get.cs new file mode 100644 index 000000000..1f5d8bd02 --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-Get.cs @@ -0,0 +1,71 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string GetRoadSegmentRoute = "wegsegmenten/{id}"; + + /// + /// Vraag een wegsegment op (v2). + /// + /// De identificator van het wegsegment. + /// + /// + /// + /// Als het wegsegment gevonden is. + /// Als het wegsegment niet gevonden kan worden. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpGet(GetRoadSegmentRoute, Name = nameof(GetRoadSegmentV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 1)] + [ProducesResponseType(typeof(GetRoadSegmentResponse), StatusCodes.Status200OK)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseExample(StatusCodes.Status200OK, typeof(GetRoadSegmentResponseResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status404NotFound, typeof(RoadSegmentNotFoundResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerOperation(OperationId = nameof(GetRoadSegmentV2))] + public async Task GetRoadSegmentV2( + [FromRoute] int id, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] GetRoadSegmentToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Get, GetRoadSegmentRoute) + .AddParameter(nameof(id), id, ParameterType.UrlSegment); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForRead()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-LinkStreetName.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-LinkStreetName.cs new file mode 100644 index 000000000..e494ef73a --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-LinkStreetName.cs @@ -0,0 +1,87 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string LinkRoadSegmentStreetNameRoute = "wegsegmenten/{id}/acties/straatnaamkoppelen"; + + /// + /// Koppel een straatnaam aan een wegsegment (v2). + /// + /// Identificator van het wegsegment. + /// + /// + /// + /// + /// Als het ticket succesvol is aangemaakt. + /// Als uw verzoek foutieve data bevat. + /// Als het wegsegment niet gevonden kan worden. + /// Als de If-Match header niet overeenkomt met de laatste ETag. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpPost(LinkRoadSegmentStreetNameRoute, Name = nameof(LinkRoadSegmentStreetNameV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 8)] + [ProducesResponseType(StatusCodes.Status202Accepted)] + [ProducesResponseType(typeof(Be.Vlaanderen.Basisregisters.BasicApiProblem.ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "ETag", "string", "De ETag van de response.")] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "x-correlation-id", "string", "Correlatie identificator van de response.")] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status404NotFound, typeof(RoadSegmentNotFoundResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status412PreconditionFailed, typeof(PreconditionFailedResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerRequestExample(typeof(PostLinkStreetNameParameters), typeof(PostLinkStreetNameParametersExamples))] + [SwaggerAuthorizeOperation( + OperationId = nameof(LinkRoadSegmentStreetNameV2), + Description = "Koppel een linker- en/of rechterstraatnaam met status `voorgesteld` of `inGebruik` aan een wegsegment waaraan momenteel geen linker- en/of rechterstraatnaam gekoppeld werd.", + Authorize = Scopes.DvWrAttribuutWaardenBeheer + )] + public async Task LinkRoadSegmentStreetNameV2( + [FromRoute] string id, + [FromBody] PostLinkStreetNameParameters request, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] LinkRoadSegmentStreetNameToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, LinkRoadSegmentStreetNameRoute) + .AddJsonBody(request) + .AddParameter(nameof(id), id, ParameterType.UrlSegment); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentController-UnlinkStreetName.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentController-UnlinkStreetName.cs new file mode 100644 index 000000000..cb847591c --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentController-UnlinkStreetName.cs @@ -0,0 +1,87 @@ +namespace Public.Api.RoadSegment.V2 +{ + using System.Threading; + using System.Threading.Tasks; + using Be.Vlaanderen.Basisregisters.Api.Exceptions; + using Be.Vlaanderen.Basisregisters.Auth.AcmIdm; + using Common.Infrastructure; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Public.Api.Infrastructure; + using Public.Api.Infrastructure.Swagger; + using RestSharp; + using RoadRegistry.BackOffice.Api.RoadSegments; + using Swashbuckle.AspNetCore.Annotations; + using Swashbuckle.AspNetCore.Filters; + using ProblemDetails = Be.Vlaanderen.Basisregisters.BasicApiProblem.ProblemDetails; + + public partial class RoadSegmentControllerV2 + { + private const string UnlinkRoadSegmentStreetNameRoute = "wegsegmenten/{id}/acties/straatnaamontkoppelen"; + + /// + /// Ontkoppel een straatnaam van een wegsegment (v2). + /// + /// Identificator van het wegsegment. + /// + /// + /// + /// + /// Als het ticket succesvol is aangemaakt. + /// Als uw verzoek foutieve data bevat. + /// Als het wegsegment niet gevonden kan worden. + /// Als de If-Match header niet overeenkomt met de laatste ETag. + /// Als het aantal requests per seconde de limiet overschreven heeft. + /// Als er een interne fout is opgetreden. + [HttpPost(UnlinkRoadSegmentStreetNameRoute, Name = nameof(UnlinkRoadSegmentStreetNameV2))] + [ApiOrder(ApiOrder.Road.RoadSegment + 9)] + [ProducesResponseType(StatusCodes.Status202Accepted)] + [ProducesResponseType(typeof(Be.Vlaanderen.Basisregisters.BasicApiProblem.ValidationProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status412PreconditionFailed)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status429TooManyRequests)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "ETag", "string", "De ETag van de response.")] + [SwaggerResponseHeader(StatusCodes.Status202Accepted, "x-correlation-id", "string", "Correlatie identificator van de response.")] + [SwaggerResponseExample(StatusCodes.Status400BadRequest, typeof(BadRequestResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status404NotFound, typeof(RoadSegmentNotFoundResponseExamples))] + [SwaggerResponseExample(StatusCodes.Status412PreconditionFailed, typeof(PreconditionFailedResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status429TooManyRequests, typeof(TooManyRequestsResponseExamplesV2))] + [SwaggerResponseExample(StatusCodes.Status500InternalServerError, typeof(InternalServerErrorResponseExamplesV2))] + [SwaggerRequestExample(typeof(PostUnlinkStreetNameParameters), typeof(PostUnlinkStreetNameParametersExamples))] + [SwaggerAuthorizeOperation( + OperationId = nameof(UnlinkRoadSegmentStreetNameV2), + Description = "Ontkoppel een linker- en/of rechterstraatnaam van een wegsegment waaraan momenteel een linker- en/of rechterstraatnaam gekoppeld is.", + Authorize = Scopes.DvWrAttribuutWaardenBeheer + )] + public async Task UnlinkRoadSegmentStreetNameV2( + [FromRoute] string id, + [FromBody] PostUnlinkStreetNameParameters request, + [FromServices] ProblemDetailsHelper problemDetailsHelper, + [FromServices] UnlinkRoadSegmentStreetNameToggle featureToggle, + CancellationToken cancellationToken) + { + if (!featureToggle.FeatureEnabled) + { + return NotFound(); + } + + var contentFormat = DetermineFormat(); + + RestRequest BackendRequest() => + CreateBackendRestRequest(Method.Post, UnlinkRoadSegmentStreetNameRoute) + .AddJsonBody(request) + .AddParameter(nameof(id), id, ParameterType.UrlSegment); + + var value = await GetFromBackendWithBadRequestAsync( + contentFormat.ContentType, + BackendRequest, + CreateDefaultHandleBadRequest(), + problemDetailsHelper, + cancellationToken: cancellationToken + ); + + return new BackendResponseResult(value, BackendResponseResultOptions.ForBackOffice()); + } + } +} diff --git a/src/Public.Api/RoadSegment/V2/RoadSegmentControllerV2.cs b/src/Public.Api/RoadSegment/V2/RoadSegmentControllerV2.cs new file mode 100644 index 000000000..d3ee436db --- /dev/null +++ b/src/Public.Api/RoadSegment/V2/RoadSegmentControllerV2.cs @@ -0,0 +1,47 @@ +namespace Public.Api.RoadSegment.V2 +{ + using Asp.Versioning; + using Autofac.Features.AttributeFilters; + using Be.Vlaanderen.Basisregisters.Api; + using Common.Infrastructure; + using Common.Infrastructure.Controllers.Attributes; + using FeatureToggle; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.Infrastructure; + using Microsoft.Extensions.Logging; + using Public.Api.Infrastructure.Configuration; + using Public.Api.Infrastructure.Swagger; + using Public.Api.Infrastructure.Version; + using Public.Api.Road; + + [ApiVisible] + [ApiVersion(Version.V2)] + [AdvertiseApiVersions(Version.CurrentAdvertised)] + [ApiRoute("")] + [ApiExplorerSettings(GroupName = "Wegen")] + [ApiConsumes(EndpointType.BackOffice)] + [ApiProduces(EndpointType.BackOffice)] + [ApiOrder(ApiOrder.Road.RoadSegment)] + public partial class RoadSegmentControllerV2 : RoadRegistryApiController + { + public RoadSegmentControllerV2( + IHttpContextAccessor httpContextAccessor, + IActionContextAccessor actionContextAccessor, + [KeyFilter(RegistryKeys.Road)] IRestClient restClient, + [KeyFilter(RegistryKeys.Road)] IFeatureToggle cacheToggle, + ConnectionMultiplexerProvider redis, + ILogger logger) + : base(httpContextAccessor, redis, logger, restClient, cacheToggle, actionContextAccessor) + { + } + + protected override string NotFoundExceptionMessage => "Onbestaand wegsegment."; + protected override string GoneExceptionMessage => "Verwijderd wegsegment."; + + private ContentFormat DetermineFormat() + { + return ContentFormat.For(EndpointType.BackOffice, ActionContextAccessor.ActionContext); + } + } +}