From 854711a73584b3ae7edadd113c376f1d34f9a5ec Mon Sep 17 00:00:00 2001 From: Denis Prokhorchik Date: Thu, 13 Jan 2022 06:59:23 +0300 Subject: [PATCH 1/2] feat(issue-149): implement api gateway for e-sender api --- .../Config/UrlsConfig.cs | 8 +++ .../Features/C-Gen/CertificatesController.cs | 8 +-- .../Features/C-Gen/VersionController.cs | 8 +-- .../Features/E-Sender/ESenderController.cs | 69 +++++++++++++++++++ .../E-Sender/Models/MailRequestViewModel.cs | 12 ++++ .../E-Sender/Services/ESenderService.cs | 37 ++++++++++ .../E-Sender/Services/IESenderService.cs | 12 ++++ .../Features/E-Sender/VersionController.cs | 8 +-- ...ttpClientAuthorizationDelegatingHandler.cs | 50 ++++++++++++++ .../O2NextGen.Web.BFF.Core.csproj | 3 +- .../O2NextGen.Web.BFF.Core/Startup.cs | 69 +++++++++++++++++-- .../O2NextGen.Web.BFF.Core/appsettings.json | 5 +- 12 files changed, 261 insertions(+), 28 deletions(-) create mode 100644 src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Config/UrlsConfig.cs create mode 100644 src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs create mode 100644 src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Models/MailRequestViewModel.cs create mode 100644 src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs create mode 100644 src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/IESenderService.cs create mode 100644 src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Config/UrlsConfig.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Config/UrlsConfig.cs new file mode 100644 index 00000000..61a7ffd9 --- /dev/null +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Config/UrlsConfig.cs @@ -0,0 +1,8 @@ +namespace O2NextGen.Web.BFF.Core.Config +{ + public class UrlsConfig + { + public string ESenderUrl { get; set; } + public string CGenUrl { get; set; } + } +} \ No newline at end of file diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/CertificatesController.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/CertificatesController.cs index 8b9b4550..d55d676b 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/CertificatesController.cs +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/CertificatesController.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; -namespace O2NextGen.Mobile.BFF.Core.Features.CGen +namespace O2NextGen.Web.BFF.Core.Features.C_Gen { [Route("api/features/c-gen/[controller]")] public class CertificatesController : Controller diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/VersionController.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/VersionController.cs index 7305f73b..08dff44d 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/VersionController.cs +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/C-Gen/VersionController.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; -namespace O2NextGen.Mobile.BFF.Core.Features.CGen +namespace O2NextGen.Web.BFF.Core.Features.C_Gen { [Route("api/features/c-gen/[controller]")] public class VersionController : Controller diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs new file mode 100644 index 00000000..92ffb657 --- /dev/null +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs @@ -0,0 +1,69 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using O2NextGen.Web.BFF.Core.Features.E_Sender.Models; +using O2NextGen.Web.BFF.Core.Features.E_Sender.Services; + +namespace O2NextGen.Web.BFF.Core.Features.E_Sender +{ + [Route("api/features/e-sender")] + public class ESenderController : Controller + { + private readonly IESenderService _senderService; + + public ESenderController(IESenderService senderService) + { + _senderService = senderService; + } + + #region Methods + + [HttpGet] + [Route("")] + public async Task GetAllAsync() + { + // var models = await _emailSenderService.GetAllAsync(CancellationToken.None); + // return Ok(models.ToViewModel()); + throw new NotImplementedException(); + } + + [HttpGet] + [Route("{id}")] + public async Task GetByIdAsync(long id, CancellationToken ct) + { + var result = _senderService.GetAsync(id,ct); + return Ok(result); + } + + [HttpPut] + [Route("id")] + public async Task UpdateAsync(long id, [FromBody]MailRequestViewModel model, CancellationToken ct) + { + // var certificate = await _emailSenderService.UpdateAsync(model.ToModel(), ct); + // return Ok(certificate.ToViewModel()); + throw new NotImplementedException(); + } + + [HttpPost] + [HttpPut] + [Route("")] + public async Task AddAsync([FromBody]MailRequestViewModel model, CancellationToken ct) + { + var result = await _senderService.AddAsync(model,ct); + return CreatedAtAction(nameof(GetByIdAsync), new {id=result.Id}, result); + } + + #endregion + + [HttpDelete] + [Route("id")] + public async Task RemoveAsync(long id,CancellationToken ct) + { + // await _emailSenderService.RemoveAsync(id, ct); + // return NoContent(); + throw new NotImplementedException(); + } + } +} + diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Models/MailRequestViewModel.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Models/MailRequestViewModel.cs new file mode 100644 index 00000000..6d3ae639 --- /dev/null +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Models/MailRequestViewModel.cs @@ -0,0 +1,12 @@ +namespace O2NextGen.Web.BFF.Core.Features.E_Sender.Models +{ + public class MailRequestViewModel + { + public long Id { get; set; } + public string From { get; set; } + public string To { get; set; } + public string Body { get; set; } + public string Subject { get; set; } + } +} + diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs new file mode 100644 index 00000000..4b7ded45 --- /dev/null +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs @@ -0,0 +1,37 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using O2NextGen.Web.BFF.Core.Config; +using O2NextGen.Web.BFF.Core.Features.E_Sender.Models; + +namespace O2NextGen.Web.BFF.Core.Features.E_Sender.Services +{ + public class ESenderService: IESenderService + { + private readonly HttpClient _httpClient; + private readonly IOptions _config; + private string ApiVersion { get; } = "1.0"; + + public ESenderService(HttpClient httpClient, IOptions config) + { + _httpClient = httpClient ?? throw new ArgumentNullException(nameof(httpClient)); + _config = config ?? throw new ArgumentNullException(nameof(config)); + } + public async Task AddAsync(MailRequestViewModel model, CancellationToken ct) + { + var response = await _httpClient.PostAsJsonAsync(_config.Value.ESenderUrl+"/api/emailsender",model,ct); + return await response.Content.ReadAsAsync(ct); + } + + public async Task GetAsync(long id, CancellationToken ct) + { + var response = await _httpClient.GetAsync(_config.Value.ESenderUrl+"/api/mailsender",ct); + // if (response.StatusCode == HttpStatusCode.NotFound) + // return NotFound(); + return await response.Content.ReadAsAsync(ct); + + } + } +} \ No newline at end of file diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/IESenderService.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/IESenderService.cs new file mode 100644 index 00000000..0f4e7646 --- /dev/null +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/IESenderService.cs @@ -0,0 +1,12 @@ +using System.Threading; +using System.Threading.Tasks; +using O2NextGen.Web.BFF.Core.Features.E_Sender.Models; + +namespace O2NextGen.Web.BFF.Core.Features.E_Sender.Services +{ + public interface IESenderService + { + Task AddAsync(MailRequestViewModel model, CancellationToken ct); + Task GetAsync(long id, CancellationToken ct); + } +} \ No newline at end of file diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/VersionController.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/VersionController.cs index 7c85915f..e73e1ff7 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/VersionController.cs +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/VersionController.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc; -namespace O2NextGen.Web.BFF.Core.Features.ESender +namespace O2NextGen.Web.BFF.Core.Features.E_Sender { [Route("api/features/e-sender/[controller]")] public class VersionController : Controller diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs new file mode 100644 index 00000000..43a4b483 --- /dev/null +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Infrastructure/HttpClientAuthorizationDelegatingHandler.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; + +namespace O2NextGen.Web.BFF.Core.Infrastructure +{ + public class HttpClientAuthorizationDelegatingHandler + : DelegatingHandler + { + private readonly IHttpContextAccessor _httpContextAccesor; + + public HttpClientAuthorizationDelegatingHandler(IHttpContextAccessor httpContextAccesor) + { + _httpContextAccesor = httpContextAccesor; + } + + protected override async Task SendAsync(HttpRequestMessage request, + CancellationToken cancellationToken) + { + var authorizationHeader = _httpContextAccesor.HttpContext + .Request.Headers["Authorization"]; + + if (!string.IsNullOrEmpty(authorizationHeader)) + { + request.Headers.Add("Authorization", new List() {authorizationHeader}); + } + + var token = await GetToken(); + + if (token != null) + { + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); + } + + return await base.SendAsync(request, cancellationToken); + } + + async Task GetToken() + { + const string ACCESS_TOKEN = "access_token"; + + return await _httpContextAccesor.HttpContext + .GetTokenAsync(ACCESS_TOKEN); + } + } +} \ No newline at end of file diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core.csproj b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core.csproj index 747837c1..70010504 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core.csproj +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core.csproj @@ -1,7 +1,7 @@ - netcoreapp2.1 + netcoreapp2.2 @@ -13,7 +13,6 @@ - diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Startup.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Startup.cs index e512a750..ee0cb2e1 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Startup.cs +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Startup.cs @@ -1,15 +1,20 @@ using System; using System.Collections.Generic; +using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; +using Microsoft.AspNetCore.Internal; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using O2NextGen.Web.BFF.Core.Config; +using O2NextGen.Web.BFF.Core.Features.E_Sender.Services; namespace O2NextGen.Web.BFF.Core { @@ -24,7 +29,8 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { - services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); + services.AddCustomMvc(Configuration); + services.AddApplicationServices(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) @@ -33,14 +39,63 @@ public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseDeveloperExceptionPage(); } - else - { - app.UseHsts(); - } - - app.UseHttpsRedirection(); + + // app.UseHttpsRedirection(); + // app.UseRouting(); + // + // app.UseAuthorization(); + app.UseMvc(); } } + + //Todo: will move to file + public static class ServiceCollectionExtensions + { + public static IServiceCollection AddCustomMvc(this IServiceCollection services, IConfiguration configuration) + { + services.AddOptions(); + services.Configure(configuration.GetSection("urls")); + + var mvcBuilder = services.AddMvcCore(); + mvcBuilder.SetCompatibilityVersion(CompatibilityVersion.Version_2_2); + mvcBuilder.AddJsonFormatters(); + return services; + } + + public static IServiceCollection AddCustomAuthentication(this IServiceCollection services, IConfiguration configuration) + { + JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub"); + + // var identityUrl = configuration.GetValue("urls:e-sender"); + // services.AddAuthentication(options => + // { + // options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; + // options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; + // + // }) + // .AddJwtBearer(options => + // { + // options.Authority = identityUrl; + // options.RequireHttpsMetadata = false; + // options.Audience = "webshoppingagg"; + // }); + + return services; + } + public static IServiceCollection AddApplicationServices(this IServiceCollection services) + { + //register delegating handlers + // services.AddTransient(); + services.AddSingleton(); + + //register http services + + services + .AddHttpClient(); + + return services; + } + } } diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/appsettings.json b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/appsettings.json index 013120d6..b5773938 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/appsettings.json +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/appsettings.json @@ -4,6 +4,9 @@ "Default": "Warning" } }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "urls": { + "ESenderUrl": "https://e-sender" + } } From aeaf196cb56fe6ef401767cf0d1d5751de33aac4 Mon Sep 17 00:00:00 2001 From: Denis Prokhorchik Date: Thu, 13 Jan 2022 07:02:39 +0300 Subject: [PATCH 2/2] style(issue-149): code cleanup --- .../Features/E-Sender/ESenderController.cs | 91 +++++++++---------- .../E-Sender/Services/ESenderService.cs | 4 +- 2 files changed, 44 insertions(+), 51 deletions(-) diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs index 92ffb657..4dc7ed06 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/ESenderController.cs @@ -16,54 +16,49 @@ public ESenderController(IESenderService senderService) { _senderService = senderService; } - - #region Methods - - [HttpGet] - [Route("")] - public async Task GetAllAsync() - { - // var models = await _emailSenderService.GetAllAsync(CancellationToken.None); - // return Ok(models.ToViewModel()); - throw new NotImplementedException(); - } - - [HttpGet] - [Route("{id}")] - public async Task GetByIdAsync(long id, CancellationToken ct) - { - var result = _senderService.GetAsync(id,ct); - return Ok(result); - } - - [HttpPut] - [Route("id")] - public async Task UpdateAsync(long id, [FromBody]MailRequestViewModel model, CancellationToken ct) - { - // var certificate = await _emailSenderService.UpdateAsync(model.ToModel(), ct); - // return Ok(certificate.ToViewModel()); - throw new NotImplementedException(); - } - - [HttpPost] - [HttpPut] - [Route("")] - public async Task AddAsync([FromBody]MailRequestViewModel model, CancellationToken ct) - { - var result = await _senderService.AddAsync(model,ct); - return CreatedAtAction(nameof(GetByIdAsync), new {id=result.Id}, result); - } - - #endregion - - [HttpDelete] - [Route("id")] - public async Task RemoveAsync(long id,CancellationToken ct) - { - // await _emailSenderService.RemoveAsync(id, ct); - // return NoContent(); - throw new NotImplementedException(); - } + + #region Methods + + [HttpGet] + [Route("")] + public async Task GetAllAsync() + { + throw new NotImplementedException(); + } + + [HttpGet] + [Route("{id}")] + public async Task GetByIdAsync(long id, CancellationToken ct) + { + var result = _senderService.GetAsync(id, ct); + return Ok(result); + } + + [HttpPut] + [Route("id")] + public async Task UpdateAsync(long id, [FromBody] MailRequestViewModel model, + CancellationToken ct) + { + throw new NotImplementedException(); + } + + [HttpPost] + [HttpPut] + [Route("")] + public async Task AddAsync([FromBody] MailRequestViewModel model, CancellationToken ct) + { + var result = await _senderService.AddAsync(model, ct); + return CreatedAtAction(nameof(GetByIdAsync), new {id = result.Id}, result); + } + + #endregion + + [HttpDelete] + [Route("id")] + public async Task RemoveAsync(long id, CancellationToken ct) + { + throw new NotImplementedException(); + } } } diff --git a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs index 4b7ded45..43367142 100644 --- a/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs +++ b/src/ApiGateways/O2NextGen.Web.BFF.Core/O2NextGen.Web.BFF.Core/Features/E-Sender/Services/ESenderService.cs @@ -27,9 +27,7 @@ public async Task AddAsync(MailRequestViewModel model, Can public async Task GetAsync(long id, CancellationToken ct) { - var response = await _httpClient.GetAsync(_config.Value.ESenderUrl+"/api/mailsender",ct); - // if (response.StatusCode == HttpStatusCode.NotFound) - // return NotFound(); + var response = await _httpClient.GetAsync(_config.Value.ESenderUrl+"/api/emailsender",ct); return await response.Content.ReadAsAsync(ct); }