diff --git a/Persistence.API/Controllers/DataSaubController.cs b/Persistence.API/Controllers/DataSaubController.cs index 60b4e48..63069a9 100644 --- a/Persistence.API/Controllers/DataSaubController.cs +++ b/Persistence.API/Controllers/DataSaubController.cs @@ -1,9 +1,11 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Persistence.Repositories; using Persistence.Repository.Data; namespace Persistence.API.Controllers; [ApiController] +[Authorize] [Route("api/[controller]")] public class DataSaubController : TimeSeriesController { diff --git a/Persistence.API/Controllers/TimeSeriesController.cs b/Persistence.API/Controllers/TimeSeriesController.cs index 154b96f..e6c74ef 100644 --- a/Persistence.API/Controllers/TimeSeriesController.cs +++ b/Persistence.API/Controllers/TimeSeriesController.cs @@ -1,9 +1,11 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Persistence.Models; using Persistence.Repositories; namespace Persistence.API.Controllers; [ApiController] +[Authorize] [Route("api/[controller]")] public class TimeSeriesController : ControllerBase, ITimeSeriesDataApi where TDto : class, ITimeSeriesAbstractDto, new() @@ -27,10 +29,8 @@ public class TimeSeriesController : ControllerBase, ITimeSeriesDataApi GetDatesRangeAsync(CancellationToken token) { - //var result = await this.timeSeriesDataCashedRepository.GetDatesRangeAsync(token); - //return Ok(result); - - return null; + var result = await this.timeSeriesDataRepository.GetDatesRangeAsync(token); + return Ok(result); } [HttpPost] diff --git a/Persistence.API/DependencyInjection.cs b/Persistence.API/DependencyInjection.cs new file mode 100644 index 0000000..e91e3a0 --- /dev/null +++ b/Persistence.API/DependencyInjection.cs @@ -0,0 +1,88 @@ +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.IdentityModel.Tokens; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using System.Text.Json.Nodes; + +namespace Persistence.API; + +public static class DependencyInjection +{ + public static void AddSwagger(this IServiceCollection services, IConfiguration configuration) + { + services.AddSwaggerGen(c => + { + c.MapType(() => new OpenApiSchema { Type = "string", Example = new OpenApiString("0.00:00:00") }); + c.MapType(() => new OpenApiSchema { Type = "string", Format = "date" }); + c.MapType(() => new OpenApiSchema + { + AnyOf = new OpenApiSchema[] + { + new OpenApiSchema {Type = "string", Format = "string" }, + new OpenApiSchema {Type = "number", Format = "int32" }, + new OpenApiSchema {Type = "number", Format = "float" }, + } + }); + + c.CustomOperationIds(e => + { + return $"{e.ActionDescriptor.RouteValues["action"]}"; + }); + + c.SwaggerDoc("v1", new OpenApiInfo { Title = "Persistence web api", Version = "v1" }); + c.AddSecurityDefinition("Keycloack", new OpenApiSecurityScheme + { + Description = @"JWT Authorization header using the Bearer scheme. Enter 'Bearer' [space] and then your token in the text input below. Example: 'Bearer 12345abcdef'", + Name = "Authorization", + In = ParameterLocation.Header, + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows + { + Implicit = new OpenApiOAuthFlow + { + AuthorizationUrl = new Uri(configuration["Authentication:AuthorizationUrl"]), + } + } + }); + + c.AddSecurityRequirement(new OpenApiSecurityRequirement() + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "Keycloack" + }, + Scheme = "Bearer", + Name = "Bearer", + In = ParameterLocation.Header, + }, + new List() + } + }); + + //var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + //var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + //var includeControllerXmlComment = true; + //c.IncludeXmlComments(xmlPath, includeControllerXmlComment); + //c.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "AsbCloudApp.xml"), includeControllerXmlComment); + }); + } + + public static void AddJWTAuthentication(this IServiceCollection services, IConfiguration configuration) + { + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddJwtBearer(o => + { + o.RequireHttpsMetadata = false; + o.Audience = configuration["Authentication:Audience"]; + o.MetadataAddress = configuration["Authentication:MetadataAddress"]!; + o.TokenValidationParameters = new TokenValidationParameters + { + ValidIssuer = configuration["Authentication:ValidIssuer"], + }; + }); + } +} diff --git a/Persistence.API/Extensions.cs b/Persistence.API/Extensions.cs new file mode 100644 index 0000000..601a2f4 --- /dev/null +++ b/Persistence.API/Extensions.cs @@ -0,0 +1,26 @@ +using System.ComponentModel; +using System.Security.Claims; + +namespace Persistence.API; + +public static class Extensions +{ + public static T GetUserId(this ClaimsPrincipal principal) + { + if (principal == null) + throw new ArgumentNullException(nameof(principal)); + + var loggedInUserId = principal.FindFirstValue(ClaimTypes.NameIdentifier); + + if (String.IsNullOrEmpty(loggedInUserId)) + throw new ArgumentNullException(nameof(loggedInUserId)); + + var result = TypeDescriptor.GetConverter(typeof(T)).ConvertFromInvariantString(loggedInUserId); + + if (result is null) + throw new ArgumentNullException(nameof(result)); + + return (T)result; + + } +} diff --git a/Persistence.API/Persistence.API.csproj b/Persistence.API/Persistence.API.csproj index 40bed8a..2b8cb73 100644 --- a/Persistence.API/Persistence.API.csproj +++ b/Persistence.API/Persistence.API.csproj @@ -8,6 +8,7 @@ + diff --git a/Persistence.API/Startup.cs b/Persistence.API/Startup.cs index 1afaa18..32466c8 100644 --- a/Persistence.API/Startup.cs +++ b/Persistence.API/Startup.cs @@ -19,9 +19,10 @@ public class Startup services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle services.AddEndpointsApiExplorer(); - services.AddSwaggerGen(); - services.AddPersistenceDbContext(Configuration); + services.AddSwagger(Configuration); services.AddInfrastructure(); + services.AddPersistenceDbContext(Configuration); + services.AddJWTAuthentication(Configuration); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) @@ -32,7 +33,8 @@ public class Startup app.UseRouting(); - //app.UseAuthorization(); + app.UseAuthentication(); + app.UseAuthorization(); app.UseEndpoints(endpoints => { diff --git a/Persistence.API/appsettings.json b/Persistence.API/appsettings.json index 14eabf9..2e0033b 100644 --- a/Persistence.API/appsettings.json +++ b/Persistence.API/appsettings.json @@ -6,7 +6,13 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Database=persistence;Username=postgres;Password=q;Persist Security Info=True", + "DefaultConnection": "Host=localhost;Database=persistence;Username=postgres;Password=q;Persist Security Info=True" }, - "AllowedHosts": "*" + "AllowedHosts": "*", + "Authentication": { + "MetadataAddress": "http://localhost:8080/realms/TestRealm/.well-known/openid-configuration", + "Audience": "account", + "ValidIssuer": "http://localhost:8080/realms/TestRealm", + "AuthorizationUrl": "http://localhost:8080/realms/TestRealm/protocol/openid-connect/auth" + } }