Use OpenIddict with real db instead of inmemory (#14465)

* Add OpenIddict tables to database (#14449)

* Added migrations to install EF Core OpenIddict tables

* Handle Install of ef core data (Needs to be outside of transaction

* Cleanup and renaming, as these things will be reused for more than openiddict in the future

* Cleanup

* Extract db context setup

* Minor cleanup

---------

Co-authored-by: Nikolaj <nikolajlauridsen@protonmail.ch>

* Use OpenIddict from DB instead of InMemoryDb

* Do not try to clean up, while not it run mode

* Fixed tests

* Clean up

---------

Co-authored-by: Nikolaj <nikolajlauridsen@protonmail.ch>
Co-authored-by: Elitsa <elm@umbraco.dk>
This commit is contained in:
Bjarke Berg
2023-06-28 08:40:28 +02:00
committed by GitHub
parent dfc7054720
commit 7265d5c3be
8 changed files with 74 additions and 80 deletions

View File

@@ -1,7 +1,6 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using OpenIddict.Validation.AspNetCore;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.DependencyInjection;
@@ -10,6 +9,7 @@ using Umbraco.Cms.Api.Management.Security;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Cms.Infrastructure.HostedServices;
using Umbraco.Cms.Infrastructure.Security;
using Umbraco.Cms.Web.Common.ApplicationBuilder;
namespace Umbraco.Cms.Api.Management.DependencyInjection;
@@ -18,43 +18,18 @@ public static class BackOfficeAuthBuilderExtensions
public static IUmbracoBuilder AddBackOfficeAuthentication(this IUmbracoBuilder builder)
{
builder
.AddDbContext()
.AddOpenIddict()
.AddBackOfficeLogin();
return builder;
}
private static IUmbracoBuilder AddDbContext(this IUmbracoBuilder builder)
{
builder.Services.AddDbContext<DbContext>(options =>
{
// Configure the DB context
// TODO: use actual Umbraco DbContext once EF is implemented - and remove dependency on Microsoft.EntityFrameworkCore.InMemory
options.UseInMemoryDatabase(nameof(DbContext));
// Register the entity sets needed by OpenIddict.
options.UseOpenIddict();
});
return builder;
}
private static IUmbracoBuilder AddOpenIddict(this IUmbracoBuilder builder)
{
builder.Services.AddAuthentication();
builder.Services.AddAuthorization(CreatePolicies);
builder.Services.AddOpenIddict()
// Register the OpenIddict core components.
.AddCore(options =>
{
options
.UseEntityFrameworkCore()
.UseDbContext<DbContext>();
})
// Register the OpenIddict server components.
.AddServer(options =>
{
@@ -118,9 +93,9 @@ public static class BackOfficeAuthBuilderExtensions
builder.Services.AddTransient<IBackOfficeApplicationManager, BackOfficeApplicationManager>();
builder.Services.AddSingleton<BackOfficeAuthorizationInitializationMiddleware>();
builder.Services.Configure<UmbracoPipelineOptions>(options => options.AddFilter(new BackofficePipelineFilter("Backoffice")));
builder.Services.AddHostedService<OpenIddictCleanup>();
builder.Services.AddHostedService<DatabaseManager>();
return builder;
}
@@ -138,28 +113,6 @@ public static class BackOfficeAuthBuilderExtensions
return builder;
}
// TODO: remove this once EF is implemented
public class DatabaseManager : IHostedService
{
private readonly IServiceProvider _serviceProvider;
public DatabaseManager(IServiceProvider serviceProvider) => _serviceProvider = serviceProvider;
public async Task StartAsync(CancellationToken cancellationToken)
{
using IServiceScope scope = _serviceProvider.CreateScope();
DbContext context = scope.ServiceProvider.GetRequiredService<DbContext>();
await context.Database.EnsureCreatedAsync(cancellationToken);
// TODO: add BackOfficeAuthorizationInitializationMiddleware before UseAuthorization (to make it run for unauthorized API requests) and remove this
IBackOfficeApplicationManager backOfficeApplicationManager = scope.ServiceProvider.GetRequiredService<IBackOfficeApplicationManager>();
await backOfficeApplicationManager.EnsureBackOfficeApplicationAsync(new Uri("https://" +
"localhost:44339/"), cancellationToken);
}
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
// TODO: move this to an appropriate location and implement the policy scheme that should be used for the new management APIs
private static void CreatePolicies(AuthorizationOptions options)
@@ -186,3 +139,10 @@ public static class BackOfficeAuthBuilderExtensions
AddPolicy(AuthorizationPolicies.SectionAccessContentOrMedia, Constants.Security.AllowedApplicationsClaimType, Constants.Applications.Content, Constants.Applications.Media);
}
}
internal class BackofficePipelineFilter : UmbracoPipelineFilter
{
public BackofficePipelineFilter(string name)
: base(name)
=> PrePipeline = builder => builder.UseMiddleware<BackOfficeAuthorizationInitializationMiddleware>();
}