Fix and cleanup for Events.WebApi
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Events.WebAPI.Contract.Command;
|
||||
using Events.Auth;
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Contract.Queries.Generic;
|
||||
using MediatR;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AutoMapper;
|
||||
using Events.Auth;
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.WebAPI.Contract.Queries.Generic;
|
||||
using Events.WebAPI.Models;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Events.WebAPI.Contract.DTOs;
|
||||
using Events.Auth;
|
||||
using Events.WebAPI.Contract.LookupQueries;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -8,10 +9,10 @@ namespace Events.WebAPI.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Route("[controller]/[action]")]
|
||||
public class LookupController : ControllerBase
|
||||
public class LookupController(IMediator mediator) : ControllerBase
|
||||
{
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<List<IdName<string>>>> Countries(string? text, [FromServices] IMediator mediator)
|
||||
public async Task<ActionResult<List<IdName<string>>>> Countries(string? text)
|
||||
{
|
||||
var countries = await mediator.Send(new LookupCountryQuery { Text = text });
|
||||
return countries;
|
||||
@@ -19,7 +20,7 @@ public class LookupController : ControllerBase
|
||||
|
||||
[Authorize(Policy = nameof(Policies.ReadData))]
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<List<IdName<int>>>> People(string? text, string? countryCode, [FromServices] IMediator mediator)
|
||||
public async Task<ActionResult<List<IdName<int>>>> People(string? text, string? countryCode)
|
||||
{
|
||||
var people = await mediator.Send(new LookupPeopleQuery
|
||||
{
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Events.Auth\Events.Auth.csproj" />
|
||||
<ProjectReference Include="..\Events.WebAPI.Contract\Events.WebAPI.Contract.csproj" />
|
||||
<ProjectReference Include="..\Events.WebAPI.Handlers.EF\Events.WebAPI.Handlers.EF.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Events.WebAPI;
|
||||
|
||||
public class Policies
|
||||
{
|
||||
public static IEnumerable<KeyValuePair<string, Action<AuthorizationPolicyBuilder>>> All
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return new KeyValuePair<string, Action<AuthorizationPolicyBuilder>>(nameof(ReadData), ReadData);
|
||||
yield return new KeyValuePair<string, Action<AuthorizationPolicyBuilder>>(nameof(EditData), EditData);
|
||||
}
|
||||
}
|
||||
|
||||
public static Action<AuthorizationPolicyBuilder> ReadData
|
||||
{
|
||||
get
|
||||
{
|
||||
return policy => policy.RequireClaim("scope", "events:read");
|
||||
}
|
||||
}
|
||||
|
||||
public static Action<AuthorizationPolicyBuilder> EditData
|
||||
{
|
||||
get
|
||||
{
|
||||
return policy => policy.RequireClaim("scope", "events:write");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Reflection;
|
||||
using AutoMapper;
|
||||
using Events.Auth;
|
||||
using Events.WebAPI;
|
||||
using Events.WebAPI.Contract.Validation.Sport;
|
||||
using Events.WebAPI.Contract.Validation;
|
||||
@@ -23,7 +24,7 @@ builder.Services
|
||||
.AddJsonOptions(configure => configure.JsonSerializerOptions.PropertyNamingPolicy = null);
|
||||
|
||||
builder.Services.AddDbContext<EventsContext>(options =>
|
||||
options.UseNpgsql(builder.Configuration.GetConnectionString("EventDB")));
|
||||
options.UseNpgsql(builder.Configuration.GetConnectionString("EventsPostgres")));
|
||||
|
||||
builder.Services.Configure<SieveOptions>(builder.Configuration.GetSection("Sieve"));
|
||||
builder.Services.AddScoped<ISieveProcessor, SieveProcessor>();
|
||||
@@ -31,12 +32,12 @@ builder.Services.AddScoped<IValidationMessageProvider, ValidationMessageProvider
|
||||
|
||||
builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>));
|
||||
builder.Services.AddValidatorsFromAssemblyContaining(typeof(AddSportValidator));
|
||||
builder.Services.AddMediatR(cfg => {
|
||||
cfg.RegisterServicesFromAssembly(typeof(SportsQueryHandler).Assembly);
|
||||
});
|
||||
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(CountriesLookupQueryHandler).Assembly));
|
||||
|
||||
builder.Services.SetupMassTransit(builder.Configuration);
|
||||
builder.Services.SetupAuthenticationAndAuthorization(builder.Configuration);
|
||||
builder.Services.SetupAuthenticationAndAuthorization(
|
||||
builder.Configuration["Auth:Authority"] ?? throw new InvalidOperationException("Missing configuration value Auth:Authority."),
|
||||
builder.Configuration["Auth:Audience"] ?? throw new InvalidOperationException("Missing configuration value Auth:Audience."));
|
||||
|
||||
#region AutoMapper settings
|
||||
Action<IServiceProvider, IMapperConfigurationExpression> mapperConfigAction = (serviceProvider, cfg) =>
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Events.WebAPI.Util.Startup;
|
||||
|
||||
public static class AuthSetupExtensions
|
||||
{
|
||||
public static void SetupAuthenticationAndAuthorization(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.DefaultInboundClaimTypeMap.Clear();
|
||||
|
||||
services.AddScoped<IClaimsTransformation, ScopeClaimsTransformation>();
|
||||
|
||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(opt =>
|
||||
{
|
||||
opt.Authority = configuration["Auth:Authority"];
|
||||
opt.Audience = configuration["Auth:Audience"];
|
||||
opt.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateAudience = true,
|
||||
ValidateIssuerSigningKey = true,
|
||||
NameClaimType = ClaimTypes.NameIdentifier
|
||||
};
|
||||
opt.Events = new JwtBearerEvents
|
||||
{
|
||||
OnAuthenticationFailed = context =>
|
||||
{
|
||||
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
|
||||
{
|
||||
context.Response.Headers.Append("Token-Expired", "true");
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
services.AddAuthorization(options =>
|
||||
{
|
||||
foreach (var policy in Policies.All)
|
||||
{
|
||||
options.AddPolicy(policy.Key, policy.Value);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
|
||||
namespace Events.WebAPI.Util.Startup;
|
||||
|
||||
public sealed class ScopeClaimsTransformation : IClaimsTransformation
|
||||
{
|
||||
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
|
||||
{
|
||||
if (principal.Identity is not ClaimsIdentity identity || !identity.IsAuthenticated)
|
||||
{
|
||||
return Task.FromResult(principal);
|
||||
}
|
||||
|
||||
Claim[] combinedScopeClaims = identity
|
||||
.FindAll("scope")
|
||||
.Where(claim => claim.Value.Contains(' '))
|
||||
.ToArray();
|
||||
|
||||
if (combinedScopeClaims.Length == 0)
|
||||
{
|
||||
return Task.FromResult(principal);
|
||||
}
|
||||
|
||||
var additionalIdentity = new ClaimsIdentity();
|
||||
|
||||
foreach (Claim combinedClaim in combinedScopeClaims)
|
||||
{
|
||||
foreach (string scope in combinedClaim.Value.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries))
|
||||
{
|
||||
if (identity.HasClaim("scope", scope) || additionalIdentity.HasClaim("scope", scope))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
additionalIdentity.AddClaim(new Claim("scope", scope, combinedClaim.ValueType, combinedClaim.Issuer));
|
||||
}
|
||||
}
|
||||
|
||||
if (additionalIdentity.Claims.Any())
|
||||
{
|
||||
principal.AddIdentity(additionalIdentity);
|
||||
}
|
||||
|
||||
return Task.FromResult(principal);
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
"Password": "guest"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"EventDB": "Host=localhost;Port=5432;Database=events;Username=sport;Password=go and look in the secrets file;Persist Security Info=True;"
|
||||
"EventsPostgres": "Host=localhost;Port=5432;Database=events;Username=sport;Password=go and look in the secrets file;Persist Security Info=True;"
|
||||
},
|
||||
"Auth": {
|
||||
"Authority": "https://fer-web2.eu.auth0.com/",
|
||||
|
||||
Reference in New Issue
Block a user