Autho fix

This commit is contained in:
Vitaliy 2024-06-19 21:31:25 +03:00
parent 1dcb66b08d
commit f29c3d19dd
9 changed files with 109 additions and 42 deletions

View File

@ -4,16 +4,19 @@ using Microsoft.EntityFrameworkCore;
namespace HackathonPreparing.ApiService.AuthFeature.EfCore; namespace HackathonPreparing.ApiService.AuthFeature.EfCore;
public class UserContext : IdentityDbContext<AuthFeature.User, IdentityRole<int>, int> public class UserContext : IdentityDbContext<User, IdentityRole<int>, int>
{ {
public UserContext (DbContextOptions<UserContext> options) : base(options) {} public UserContext (DbContextOptions<UserContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(typeof(Program).Assembly);
builder.HasDefaultSchema("user"); builder.HasDefaultSchema("user");
builder.ApplyConfigurationsFromAssembly(typeof(Program).Assembly);
} }
} }

View File

@ -2,6 +2,8 @@ using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerGen;
using static HackathonPreparing.ApiService.Features.DevFeature.ReflectionHelpers;
namespace HackathonPreparing.ApiService.DevFeature; namespace HackathonPreparing.ApiService.DevFeature;
@ -9,21 +11,15 @@ public static class DbHelpersEndpointsExtensions
{ {
public static RouteGroupBuilder AddDbHelpersEndpoints(this WebApplication app) public static RouteGroupBuilder AddDbHelpersEndpoints(this WebApplication app)
{ {
var group = app.MapGroup("/db"); var group = app.MapGroup("db");
group.MapPost("/migrate/{contexClassName}", async (string contexClasstName, IServiceProvider services) => group.MapPost("/migrate/{contexClassName}", async (string contexClasstName, IServiceProvider services) =>
{ {
var contextType = typeof(Program).Assembly.GetType(contexClasstName); var contextType = GetEfCoreClassContexts().FirstOrDefault(c => c.Name == contexClasstName);
if(contextType is null) if(contextType is null)
return Results.NotFound(); return Results.NotFound();
var inheritanceChain = contextType.GetInheritanceChain();
if(!inheritanceChain.Any(t => typeof(DbContext) == t))
return Results.NotFound();
using var scope = services.CreateScope(); using var scope = services.CreateScope();
var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType); var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType);
@ -34,17 +30,11 @@ public static class DbHelpersEndpointsExtensions
group.MapPost("/initdb/{contexClassName}", async (string contexClasstName, IServiceProvider services) => group.MapPost("/initdb/{contexClassName}", async (string contexClasstName, IServiceProvider services) =>
{ {
var contextType = typeof(Program).Assembly.GetType(contexClasstName); var contextType = GetEfCoreClassContexts().FirstOrDefault(c => c.Name == contexClasstName);
if(contextType is null) if(contextType is null)
return Results.NotFound(); return Results.NotFound();
var inheritanceChain = contextType.GetInheritanceChain();
if(!inheritanceChain.Any(t => typeof(DbContext) == t))
return Results.NotFound();
using var scope = services.CreateScope(); using var scope = services.CreateScope();
var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType); var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType);
@ -53,6 +43,33 @@ public static class DbHelpersEndpointsExtensions
return Results.Ok(); return Results.Ok();
}); });
group.MapPost("/initdb", async (IServiceProvider services) =>
{
foreach(var contextType in GetEfCoreClassContexts())
{
using var scope = services.CreateScope();
var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType);
await dbContext.Database.EnsureCreatedAsync();
}
return Results.Ok();
});
group.MapPost("/migrate", async (IServiceProvider services) =>
{
foreach(var contextType in GetEfCoreClassContexts())
{
using var scope = services.CreateScope();
var dbContext = (DbContext)scope.ServiceProvider.GetRequiredService(contextType);
await dbContext.Database.MigrateAsync();
}
return Results.Ok();
});
group.MapPost("/add-moderator", async ([FromServices]UserManager<AuthFeature.User> userManager) => { group.MapPost("/add-moderator", async ([FromServices]UserManager<AuthFeature.User> userManager) => {
var user = new AuthFeature.User{ var user = new AuthFeature.User{
Email = "m@gmail.com", Email = "m@gmail.com",

View File

@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace HackathonPreparing.ApiService.Features.DevFeature;
public static class ReflectionHelpers
{
private static IEnumerable<Type>? EfCoreDbContexts;
// !!!!
// DONT USE FOR HIGH CONCURANCY TASKS
// IT NOT FOR MULTITHREADING CODE
// OF FOR MANY REQUESTS PER MINUTE
// !!!!
public static IEnumerable<Type> GetEfCoreClassContexts()
{
if(EfCoreDbContexts is null)
{
//Get all types with DbContext parent type
EfCoreDbContexts = typeof(Program).Assembly.GetTypes().Where(t =>
t.GetInheritanceChain().Any(inheritanType =>
inheritanType.Name is not null && inheritanType.Name == nameof(DbContext)));
}
return EfCoreDbContexts;
}
}

View File

@ -12,4 +12,13 @@ public static class ServicesExtensions
optionsBuilder => optionsBuilder.UseNpgsql(npgsqlBuilder => optionsBuilder => optionsBuilder.UseNpgsql(npgsqlBuilder =>
npgsqlBuilder.MigrationsAssembly(typeof(Program).Assembly.GetName().Name))); npgsqlBuilder.MigrationsAssembly(typeof(Program).Assembly.GetName().Name)));
} }
// public static void AddDbContextWithDefaultConfiguration<TDbContext>(this WebApplicationBuilder builder) where TDbContext : DbContext
// {
// var connection = builder.Configuration.GetConnectionString("prod") ?? throw new NullReferenceException("CONNECTION TO POSTGRES IS NULL");
// builder.Services.AddDbContext<TDbContext>(b => b.UseNpgsql(connection, npgsqlBuilder =>
// npgsqlBuilder.MigrationsAssembly(typeof(Program).Assembly.GetName().Name)));
// }
} }

View File

@ -10,12 +10,12 @@ public sealed class WeatherForecastContext : DbContext
} }
public DbSet<WeatherForecast> Forecasts => Set<ApiService.WeatherForecastFeature.WeatherForecast>(); public DbSet<WeatherForecast> Forecasts => Set<WeatherForecast>();
protected override void OnModelCreating(ModelBuilder builder) protected override void OnModelCreating(ModelBuilder builder)
{ {
base.OnModelCreating(builder); base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(typeof(Program).Assembly);
builder.HasDefaultSchema("weatherforecast"); builder.HasDefaultSchema("weatherforecast");
builder.ApplyConfigurationsFromAssembly(typeof(Program).Assembly);
} }
} }

View File

@ -1,5 +1,6 @@
using HackathonPreparing.ApiService.WeatherForecastFeature.EfCore; using HackathonPreparing.ApiService.WeatherForecastFeature.EfCore;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authorization;
namespace HackathonPreparing.ApiService.WeatherForecastFeature; namespace HackathonPreparing.ApiService.WeatherForecastFeature;
@ -7,9 +8,9 @@ public static class WeatherForecastEndpointsExtensions
{ {
public static void AddWeatherForecastEndpoints (this WebApplication app) public static void AddWeatherForecastEndpoints (this WebApplication app)
{ {
var group = app.MapGroup("/weatherforecast"); var group = app.MapGroup("weatherforecast");
group.MapGet("/", async (WeatherForecastContext db) => await db.Forecasts.ToListAsync()); group.MapGet(string.Empty, async (WeatherForecastContext db) => await db.Forecasts.ToListAsync());
group.MapDelete("/{id}", async (WeatherForecastContext db, int id) => group.MapDelete("{id}", [Authorize(Roles="moderator")]async (WeatherForecastContext db, int id) =>
{ {
var forecast = await db.Forecasts.FindAsync(id); var forecast = await db.Forecasts.FindAsync(id);
if (forecast == null) if (forecast == null)
@ -21,15 +22,15 @@ public static class WeatherForecastEndpointsExtensions
await db.SaveChangesAsync(); await db.SaveChangesAsync();
return Results.NoContent(); return Results.NoContent();
}).RequireAuthorization("moderator"); });
group.MapPost("/", async (WeatherForecastContext db, ApiService.WeatherForecastFeature.WeatherForecast forecast) => group.MapPost(string.Empty, [Authorize(Roles="moderator")] async (WeatherForecastContext db, WeatherForecast forecast) =>
{ {
db.Forecasts.Add(forecast); db.Forecasts.Add(forecast);
await db.SaveChangesAsync(); await db.SaveChangesAsync();
return Results.Created($"/weatherforecast/{forecast.Id}", forecast); return Results.Created($"/weatherforecast/{forecast.Id}", forecast);
}); });
group.MapPut("/{id}", async (WeatherForecastContext db, int id, ApiService.WeatherForecastFeature.WeatherForecast forecast) => group.MapPut("{id}", [Authorize(Roles="moderator")] async (WeatherForecastContext db, int id, WeatherForecast forecast) =>
{ {
if (id != forecast.Id) if (id != forecast.Id)
{ {
@ -53,7 +54,7 @@ public static class WeatherForecastEndpointsExtensions
} }
return Results.NoContent(); return Results.NoContent();
}).RequireAuthorization("moderator"); });
group.WithTags("weatherforecast"); group.WithTags("weatherforecast");
} }
} }

View File

@ -12,6 +12,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Aspire.Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.1" /> <PackageReference Include="Aspire.Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.6" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.6" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.6"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.6">

View File

@ -4,7 +4,6 @@ using HackathonPreparing.ApiService.DevFeature;
using HackathonPreparing.ApiService.WeatherForecastFeature; using HackathonPreparing.ApiService.WeatherForecastFeature;
using HackathonPreparing.ApiService.WeatherForecastFeature.EfCore; using HackathonPreparing.ApiService.WeatherForecastFeature.EfCore;
using HackathonPreparing.ServiceDefaults; using HackathonPreparing.ServiceDefaults;
using Microsoft.AspNetCore.Identity;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -43,16 +42,12 @@ builder.Services.AddSwaggerGen(c =>
builder.Services.AddAuthorization(); builder.Services.AddAuthorization();
builder.Services.AddAuthorizationBuilder()
.AddPolicy("moderator", policy =>
policy.RequireRole("MODERATOR"));
//TODO BEARER builder.Services.AddAuthentication().AddBearerToken();
builder.Services.AddAuthentication().AddBearerToken(IdentityConstants.BearerScheme);
builder.Services.AddIdentity<User, IdentityRole<int>>() builder.Services
.AddEntityFrameworkStores<UserContext>() .AddIdentityApiEndpoints<User>()
.AddApiEndpoints(); .AddEntityFrameworkStores<UserContext>();
// Add services to the container. // Add services to the container.
builder.Services.AddProblemDetails(); builder.Services.AddProblemDetails();
@ -62,7 +57,12 @@ builder.AddDbContextWithDefaultConfiguration<UserContext>();
var app = builder.Build(); var app = builder.Build();
app.UsePathBase(new PathString("/api"));
app.UsePathBase("/api");
app.UseRouting();
app.MapGet("/test", () => {});
if (app.Environment.IsDevelopment()) if (app.Environment.IsDevelopment())
{ {
@ -73,16 +73,21 @@ if (app.Environment.IsDevelopment())
app.AddDbHelpersEndpoints(); app.AddDbHelpersEndpoints();
} }
//Configure the HTTP request pipeline. //Configure the HTTP request pipeline.
app.UseExceptionHandler(); app.UseExceptionHandler();
app.UseAuthorization();
app.UseAuthentication(); app.UseAuthentication();
app.UseAuthorization();
app.AddWeatherForecastEndpoints(); app.AddWeatherForecastEndpoints();
app.MapDefaultEndpoints(); app.MapDefaultEndpoints();
app.MapGroup("/user")
app.MapGroup("user")
.MapIdentityApi<User>() .MapIdentityApi<User>()
.WithTags("user"); .WithTags("user");

View File

@ -5,5 +5,8 @@
"Microsoft.AspNetCore": "Warning" "Microsoft.AspNetCore": "Warning"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"ConnectionStrings": {
"prod": "User ID=postgres;Password=postgres;Host=localhost;Port=5432;Database=prod;"
}
} }