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>
This commit is contained in:
Bjarke Berg
2023-06-26 13:50:57 +02:00
committed by GitHub
parent 62f692e617
commit 2973f9fe5a
33 changed files with 1847 additions and 2 deletions

View File

@@ -14,6 +14,9 @@
<PackageReference Include="OpenIddict.AspNetCore" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Cms.Persistence.EFCore.Sqlite\Umbraco.Cms.Persistence.EFCore.Sqlite.csproj" />
<ProjectReference Include="..\Umbraco.Cms.Persistence.EFCore.SqlServer\Umbraco.Cms.Persistence.EFCore.SqlServer.csproj" />
<ProjectReference Include="..\Umbraco.Cms.Persistence.EFCore\Umbraco.Cms.Persistence.EFCore.csproj" />
<ProjectReference Include="..\Umbraco.Core\Umbraco.Core.csproj" />
<ProjectReference Include="..\Umbraco.Web.Common\Umbraco.Web.Common.csproj" />
</ItemGroup>

View File

@@ -1,7 +1,6 @@
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Api.Common.Configuration;
using Umbraco.Cms.Api.Common.DependencyInjection;
using Umbraco.Cms.Api.Delivery.Accessors;
using Umbraco.Cms.Api.Delivery.Configuration;
@@ -33,6 +32,7 @@ public static class UmbracoBuilderExtensions
builder.Services.ConfigureOptions<ConfigureUmbracoDeliveryApiSwaggerGenOptions>();
builder.AddUmbracoApiOpenApiUI();
builder.AddUmbracoEFCoreDbContext();
builder
.Services
.AddControllers()
@@ -47,3 +47,4 @@ public static class UmbracoBuilderExtensions
return builder;
}
}

View File

@@ -0,0 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Persistence.EFCore.Migrations;
namespace Umbraco.Cms.Persistence.EFCore.SqlServer;
public class EFCoreSqlServerComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddSingleton<IMigrationProvider, SqlServerMigrationProvider>();
builder.Services.AddSingleton<IMigrationProviderSetup, SqlServerMigrationProviderSetup>();
}
}

View File

@@ -0,0 +1,266 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Umbraco.Cms.Persistence.EFCore.SqlServer.Migrations
{
[DbContext(typeof(UmbracoDbContext))]
[Migration("20230622184303_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ClientId")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ClientSecret")
.HasColumnType("nvarchar(max)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("ConsentType")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayNames")
.HasColumnType("nvarchar(max)");
b.Property<string>("Permissions")
.HasColumnType("nvarchar(max)");
b.Property<string>("PostLogoutRedirectUris")
.HasColumnType("nvarchar(max)");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<string>("RedirectUris")
.HasColumnType("nvarchar(max)");
b.Property<string>("Requirements")
.HasColumnType("nvarchar(max)");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("ClientId")
.IsUnique()
.HasFilter("[ClientId] IS NOT NULL");
b.ToTable("umbracoOpenIddictApplications", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ApplicationId")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime?>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<string>("Scopes")
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictAuthorizations", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Descriptions")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayNames")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<string>("Resources")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique()
.HasFilter("[Name] IS NOT NULL");
b.ToTable("umbracoOpenIddictScopes", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ApplicationId")
.HasColumnType("nvarchar(450)");
b.Property<string>("AuthorizationId")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime?>("CreationDate")
.HasColumnType("datetime2");
b.Property<DateTime?>("ExpirationDate")
.HasColumnType("datetime2");
b.Property<string>("Payload")
.HasColumnType("nvarchar(max)");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("RedemptionDate")
.HasColumnType("datetime2");
b.Property<string>("ReferenceId")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("AuthorizationId");
b.HasIndex("ReferenceId")
.IsUnique()
.HasFilter("[ReferenceId] IS NOT NULL");
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictTokens", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Authorizations")
.HasForeignKey("ApplicationId");
b.Navigation("Application");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Tokens")
.HasForeignKey("ApplicationId");
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization")
.WithMany("Tokens")
.HasForeignKey("AuthorizationId");
b.Navigation("Application");
b.Navigation("Authorization");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Navigation("Authorizations");
b.Navigation("Tokens");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Navigation("Tokens");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,166 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Umbraco.Cms.Persistence.EFCore.SqlServer.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "umbracoOpenIddictApplications",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
ClientId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
ClientSecret = table.Column<string>(type: "nvarchar(max)", nullable: true),
ConcurrencyToken = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
ConsentType = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
DisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
DisplayNames = table.Column<string>(type: "nvarchar(max)", nullable: true),
Permissions = table.Column<string>(type: "nvarchar(max)", nullable: true),
PostLogoutRedirectUris = table.Column<string>(type: "nvarchar(max)", nullable: true),
Properties = table.Column<string>(type: "nvarchar(max)", nullable: true),
RedirectUris = table.Column<string>(type: "nvarchar(max)", nullable: true),
Requirements = table.Column<string>(type: "nvarchar(max)", nullable: true),
Type = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictApplications", x => x.Id);
});
migrationBuilder.CreateTable(
name: "umbracoOpenIddictScopes",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
ConcurrencyToken = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
Descriptions = table.Column<string>(type: "nvarchar(max)", nullable: true),
DisplayName = table.Column<string>(type: "nvarchar(max)", nullable: true),
DisplayNames = table.Column<string>(type: "nvarchar(max)", nullable: true),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: true),
Properties = table.Column<string>(type: "nvarchar(max)", nullable: true),
Resources = table.Column<string>(type: "nvarchar(max)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictScopes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "umbracoOpenIddictAuthorizations",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
ApplicationId = table.Column<string>(type: "nvarchar(450)", nullable: true),
ConcurrencyToken = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
CreationDate = table.Column<DateTime>(type: "datetime2", nullable: true),
Properties = table.Column<string>(type: "nvarchar(max)", nullable: true),
Scopes = table.Column<string>(type: "nvarchar(max)", nullable: true),
Status = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column<string>(type: "nvarchar(400)", maxLength: 400, nullable: true),
Type = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictAuthorizations", x => x.Id);
table.ForeignKey(
name: "FK_umbracoOpenIddictAuthorizations_umbracoOpenIddictApplications_ApplicationId",
column: x => x.ApplicationId,
principalTable: "umbracoOpenIddictApplications",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "umbracoOpenIddictTokens",
columns: table => new
{
Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
ApplicationId = table.Column<string>(type: "nvarchar(450)", nullable: true),
AuthorizationId = table.Column<string>(type: "nvarchar(450)", nullable: true),
ConcurrencyToken = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
CreationDate = table.Column<DateTime>(type: "datetime2", nullable: true),
ExpirationDate = table.Column<DateTime>(type: "datetime2", nullable: true),
Payload = table.Column<string>(type: "nvarchar(max)", nullable: true),
Properties = table.Column<string>(type: "nvarchar(max)", nullable: true),
RedemptionDate = table.Column<DateTime>(type: "datetime2", nullable: true),
ReferenceId = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: true),
Status = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true),
Subject = table.Column<string>(type: "nvarchar(400)", maxLength: 400, nullable: true),
Type = table.Column<string>(type: "nvarchar(50)", maxLength: 50, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictTokens", x => x.Id);
table.ForeignKey(
name: "FK_umbracoOpenIddictTokens_umbracoOpenIddictApplications_ApplicationId",
column: x => x.ApplicationId,
principalTable: "umbracoOpenIddictApplications",
principalColumn: "Id");
table.ForeignKey(
name: "FK_umbracoOpenIddictTokens_umbracoOpenIddictAuthorizations_AuthorizationId",
column: x => x.AuthorizationId,
principalTable: "umbracoOpenIddictAuthorizations",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictApplications_ClientId",
table: "umbracoOpenIddictApplications",
column: "ClientId",
unique: true,
filter: "[ClientId] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictAuthorizations_ApplicationId_Status_Subject_Type",
table: "umbracoOpenIddictAuthorizations",
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictScopes_Name",
table: "umbracoOpenIddictScopes",
column: "Name",
unique: true,
filter: "[Name] IS NOT NULL");
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictTokens_ApplicationId_Status_Subject_Type",
table: "umbracoOpenIddictTokens",
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictTokens_AuthorizationId",
table: "umbracoOpenIddictTokens",
column: "AuthorizationId");
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictTokens_ReferenceId",
table: "umbracoOpenIddictTokens",
column: "ReferenceId",
unique: true,
filter: "[ReferenceId] IS NOT NULL");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "umbracoOpenIddictScopes");
migrationBuilder.DropTable(
name: "umbracoOpenIddictTokens");
migrationBuilder.DropTable(
name: "umbracoOpenIddictAuthorizations");
migrationBuilder.DropTable(
name: "umbracoOpenIddictApplications");
}
}
}

View File

@@ -0,0 +1,264 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Umbraco.Cms.Persistence.EFCore;
#nullable disable
namespace Umbraco.Cms.Persistence.EFCore.SqlServer.Migrations
{
[DbContext(typeof(UmbracoDbContext))]
partial class UmbracoOpenIddictDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.7")
.HasAnnotation("Relational:MaxIdentifierLength", 128);
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ClientId")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("ClientSecret")
.HasColumnType("nvarchar(max)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("ConsentType")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayNames")
.HasColumnType("nvarchar(max)");
b.Property<string>("Permissions")
.HasColumnType("nvarchar(max)");
b.Property<string>("PostLogoutRedirectUris")
.HasColumnType("nvarchar(max)");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<string>("RedirectUris")
.HasColumnType("nvarchar(max)");
b.Property<string>("Requirements")
.HasColumnType("nvarchar(max)");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("ClientId")
.IsUnique()
.HasFilter("[ClientId] IS NOT NULL");
b.ToTable("umbracoOpenIddictApplications", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ApplicationId")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime?>("CreationDate")
.HasColumnType("datetime2");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<string>("Scopes")
.HasColumnType("nvarchar(max)");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictAuthorizations", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Description")
.HasColumnType("nvarchar(max)");
b.Property<string>("Descriptions")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayName")
.HasColumnType("nvarchar(max)");
b.Property<string>("DisplayNames")
.HasColumnType("nvarchar(max)");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("nvarchar(200)");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<string>("Resources")
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique()
.HasFilter("[Name] IS NOT NULL");
b.ToTable("umbracoOpenIddictScopes", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("nvarchar(450)");
b.Property<string>("ApplicationId")
.HasColumnType("nvarchar(450)");
b.Property<string>("AuthorizationId")
.HasColumnType("nvarchar(450)");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<DateTime?>("CreationDate")
.HasColumnType("datetime2");
b.Property<DateTime?>("ExpirationDate")
.HasColumnType("datetime2");
b.Property<string>("Payload")
.HasColumnType("nvarchar(max)");
b.Property<string>("Properties")
.HasColumnType("nvarchar(max)");
b.Property<DateTime?>("RedemptionDate")
.HasColumnType("datetime2");
b.Property<string>("ReferenceId")
.HasMaxLength(100)
.HasColumnType("nvarchar(100)");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("nvarchar(400)");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("nvarchar(50)");
b.HasKey("Id");
b.HasIndex("AuthorizationId");
b.HasIndex("ReferenceId")
.IsUnique()
.HasFilter("[ReferenceId] IS NOT NULL");
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictTokens", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Authorizations")
.HasForeignKey("ApplicationId");
b.Navigation("Application");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Tokens")
.HasForeignKey("ApplicationId");
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization")
.WithMany("Tokens")
.HasForeignKey("AuthorizationId");
b.Navigation("Application");
b.Navigation("Authorization");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Navigation("Authorizations");
b.Navigation("Tokens");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Navigation("Tokens");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore;
using Umbraco.Cms.Persistence.EFCore.Migrations;
using Umbraco.Extensions;
namespace Umbraco.Cms.Persistence.EFCore.SqlServer;
public class SqlServerMigrationProvider : IMigrationProvider
{
private readonly IDbContextFactory<UmbracoDbContext> _dbContextFactory;
public SqlServerMigrationProvider(IDbContextFactory<UmbracoDbContext> dbContextFactory) => _dbContextFactory = dbContextFactory;
public string ProviderName => "Microsoft.Data.SqlClient";
public async Task MigrateAsync(EFCoreMigration migration)
{
UmbracoDbContext context = await _dbContextFactory.CreateDbContextAsync();
await context.MigrateDatabaseAsync(GetMigrationType(migration));
}
public async Task MigrateAllAsync()
{
UmbracoDbContext context = await _dbContextFactory.CreateDbContextAsync();
await context.Database.MigrateAsync();
}
private static Type GetMigrationType(EFCoreMigration migration) =>
migration switch
{
EFCoreMigration.InitialCreate => typeof(Migrations.InitialCreate),
_ => throw new ArgumentOutOfRangeException(nameof(migration), $@"Not expected migration value: {migration}")
};
}

View File

@@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore;
using Umbraco.Cms.Persistence.EFCore.Migrations;
namespace Umbraco.Cms.Persistence.EFCore.SqlServer;
public class SqlServerMigrationProviderSetup : IMigrationProviderSetup
{
public string ProviderName => "Microsoft.Data.SqlClient";
public void Setup(DbContextOptionsBuilder builder, string? connectionString)
{
builder.UseSqlServer(connectionString, x => x.MigrationsAssembly(GetType().Assembly.FullName));
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Title>Umbraco CMS - EF Core - SqlServer migrations</Title>
<!-- TODO: Enable when final version is shipped (because there's currently no previous version) -->
<EnablePackageValidation>false</EnablePackageValidation>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Cms.Persistence.EFCore\Umbraco.Cms.Persistence.EFCore.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,15 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Persistence.EFCore.Migrations;
namespace Umbraco.Cms.Persistence.EFCore.Sqlite;
public class EFCoreSqliteComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddSingleton<IMigrationProvider, SqliteMigrationProvider>();
builder.Services.AddSingleton<IMigrationProviderSetup, SqliteMigrationProviderSetup>();
}
}

View File

@@ -0,0 +1,258 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Umbraco.Cms.Persistence.EFCore.Sqlite.Migrations
{
[DbContext(typeof(UmbracoDbContext))]
[Migration("20230622183638_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.7");
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ClientId")
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<string>("ClientSecret")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("ConsentType")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("DisplayName")
.HasColumnType("TEXT");
b.Property<string>("DisplayNames")
.HasColumnType("TEXT");
b.Property<string>("Permissions")
.HasColumnType("TEXT");
b.Property<string>("PostLogoutRedirectUris")
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<string>("RedirectUris")
.HasColumnType("TEXT");
b.Property<string>("Requirements")
.HasColumnType("TEXT");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ClientId")
.IsUnique();
b.ToTable("umbracoOpenIddictApplications", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ApplicationId")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreationDate")
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<string>("Scopes")
.HasColumnType("TEXT");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("TEXT");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictAuthorizations", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<string>("Descriptions")
.HasColumnType("TEXT");
b.Property<string>("DisplayName")
.HasColumnType("TEXT");
b.Property<string>("DisplayNames")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<string>("Resources")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("umbracoOpenIddictScopes", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ApplicationId")
.HasColumnType("TEXT");
b.Property<string>("AuthorizationId")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreationDate")
.HasColumnType("TEXT");
b.Property<DateTime?>("ExpirationDate")
.HasColumnType("TEXT");
b.Property<string>("Payload")
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<DateTime?>("RedemptionDate")
.HasColumnType("TEXT");
b.Property<string>("ReferenceId")
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("TEXT");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorizationId");
b.HasIndex("ReferenceId")
.IsUnique();
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictTokens", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Authorizations")
.HasForeignKey("ApplicationId");
b.Navigation("Application");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Tokens")
.HasForeignKey("ApplicationId");
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization")
.WithMany("Tokens")
.HasForeignKey("AuthorizationId");
b.Navigation("Application");
b.Navigation("Authorization");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Navigation("Authorizations");
b.Navigation("Tokens");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Navigation("Tokens");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,163 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Umbraco.Cms.Persistence.EFCore.Sqlite.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "umbracoOpenIddictApplications",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
ClientId = table.Column<string>(type: "TEXT", maxLength: 100, nullable: true),
ClientSecret = table.Column<string>(type: "TEXT", nullable: true),
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
ConsentType = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
DisplayName = table.Column<string>(type: "TEXT", nullable: true),
DisplayNames = table.Column<string>(type: "TEXT", nullable: true),
Permissions = table.Column<string>(type: "TEXT", nullable: true),
PostLogoutRedirectUris = table.Column<string>(type: "TEXT", nullable: true),
Properties = table.Column<string>(type: "TEXT", nullable: true),
RedirectUris = table.Column<string>(type: "TEXT", nullable: true),
Requirements = table.Column<string>(type: "TEXT", nullable: true),
Type = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictApplications", x => x.Id);
});
migrationBuilder.CreateTable(
name: "umbracoOpenIddictScopes",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
Description = table.Column<string>(type: "TEXT", nullable: true),
Descriptions = table.Column<string>(type: "TEXT", nullable: true),
DisplayName = table.Column<string>(type: "TEXT", nullable: true),
DisplayNames = table.Column<string>(type: "TEXT", nullable: true),
Name = table.Column<string>(type: "TEXT", maxLength: 200, nullable: true),
Properties = table.Column<string>(type: "TEXT", nullable: true),
Resources = table.Column<string>(type: "TEXT", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictScopes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "umbracoOpenIddictAuthorizations",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
ApplicationId = table.Column<string>(type: "TEXT", nullable: true),
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
CreationDate = table.Column<DateTime>(type: "TEXT", nullable: true),
Properties = table.Column<string>(type: "TEXT", nullable: true),
Scopes = table.Column<string>(type: "TEXT", nullable: true),
Status = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
Subject = table.Column<string>(type: "TEXT", maxLength: 400, nullable: true),
Type = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictAuthorizations", x => x.Id);
table.ForeignKey(
name: "FK_umbracoOpenIddictAuthorizations_umbracoOpenIddictApplications_ApplicationId",
column: x => x.ApplicationId,
principalTable: "umbracoOpenIddictApplications",
principalColumn: "Id");
});
migrationBuilder.CreateTable(
name: "umbracoOpenIddictTokens",
columns: table => new
{
Id = table.Column<string>(type: "TEXT", nullable: false),
ApplicationId = table.Column<string>(type: "TEXT", nullable: true),
AuthorizationId = table.Column<string>(type: "TEXT", nullable: true),
ConcurrencyToken = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
CreationDate = table.Column<DateTime>(type: "TEXT", nullable: true),
ExpirationDate = table.Column<DateTime>(type: "TEXT", nullable: true),
Payload = table.Column<string>(type: "TEXT", nullable: true),
Properties = table.Column<string>(type: "TEXT", nullable: true),
RedemptionDate = table.Column<DateTime>(type: "TEXT", nullable: true),
ReferenceId = table.Column<string>(type: "TEXT", maxLength: 100, nullable: true),
Status = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true),
Subject = table.Column<string>(type: "TEXT", maxLength: 400, nullable: true),
Type = table.Column<string>(type: "TEXT", maxLength: 50, nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_umbracoOpenIddictTokens", x => x.Id);
table.ForeignKey(
name: "FK_umbracoOpenIddictTokens_umbracoOpenIddictApplications_ApplicationId",
column: x => x.ApplicationId,
principalTable: "umbracoOpenIddictApplications",
principalColumn: "Id");
table.ForeignKey(
name: "FK_umbracoOpenIddictTokens_umbracoOpenIddictAuthorizations_AuthorizationId",
column: x => x.AuthorizationId,
principalTable: "umbracoOpenIddictAuthorizations",
principalColumn: "Id");
});
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictApplications_ClientId",
table: "umbracoOpenIddictApplications",
column: "ClientId",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictAuthorizations_ApplicationId_Status_Subject_Type",
table: "umbracoOpenIddictAuthorizations",
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictScopes_Name",
table: "umbracoOpenIddictScopes",
column: "Name",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictTokens_ApplicationId_Status_Subject_Type",
table: "umbracoOpenIddictTokens",
columns: new[] { "ApplicationId", "Status", "Subject", "Type" });
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictTokens_AuthorizationId",
table: "umbracoOpenIddictTokens",
column: "AuthorizationId");
migrationBuilder.CreateIndex(
name: "IX_umbracoOpenIddictTokens_ReferenceId",
table: "umbracoOpenIddictTokens",
column: "ReferenceId",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "umbracoOpenIddictScopes");
migrationBuilder.DropTable(
name: "umbracoOpenIddictTokens");
migrationBuilder.DropTable(
name: "umbracoOpenIddictAuthorizations");
migrationBuilder.DropTable(
name: "umbracoOpenIddictApplications");
}
}
}

View File

@@ -0,0 +1,256 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Umbraco.Cms.Persistence.EFCore;
#nullable disable
namespace Umbraco.Cms.Persistence.EFCore.Sqlite.Migrations
{
[DbContext(typeof(UmbracoDbContext))]
partial class UmbracoOpenIddictDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.7");
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ClientId")
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<string>("ClientSecret")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("ConsentType")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("DisplayName")
.HasColumnType("TEXT");
b.Property<string>("DisplayNames")
.HasColumnType("TEXT");
b.Property<string>("Permissions")
.HasColumnType("TEXT");
b.Property<string>("PostLogoutRedirectUris")
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<string>("RedirectUris")
.HasColumnType("TEXT");
b.Property<string>("Requirements")
.HasColumnType("TEXT");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ClientId")
.IsUnique();
b.ToTable("umbracoOpenIddictApplications", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ApplicationId")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreationDate")
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<string>("Scopes")
.HasColumnType("TEXT");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("TEXT");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictAuthorizations", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreScope", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Description")
.HasColumnType("TEXT");
b.Property<string>("Descriptions")
.HasColumnType("TEXT");
b.Property<string>("DisplayName")
.HasColumnType("TEXT");
b.Property<string>("DisplayNames")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasMaxLength(200)
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<string>("Resources")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("Name")
.IsUnique();
b.ToTable("umbracoOpenIddictScopes", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<string>("ApplicationId")
.HasColumnType("TEXT");
b.Property<string>("AuthorizationId")
.HasColumnType("TEXT");
b.Property<string>("ConcurrencyToken")
.IsConcurrencyToken()
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<DateTime?>("CreationDate")
.HasColumnType("TEXT");
b.Property<DateTime?>("ExpirationDate")
.HasColumnType("TEXT");
b.Property<string>("Payload")
.HasColumnType("TEXT");
b.Property<string>("Properties")
.HasColumnType("TEXT");
b.Property<DateTime?>("RedemptionDate")
.HasColumnType("TEXT");
b.Property<string>("ReferenceId")
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<string>("Status")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.Property<string>("Subject")
.HasMaxLength(400)
.HasColumnType("TEXT");
b.Property<string>("Type")
.HasMaxLength(50)
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("AuthorizationId");
b.HasIndex("ReferenceId")
.IsUnique();
b.HasIndex("ApplicationId", "Status", "Subject", "Type");
b.ToTable("umbracoOpenIddictTokens", (string)null);
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Authorizations")
.HasForeignKey("ApplicationId");
b.Navigation("Application");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreToken", b =>
{
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", "Application")
.WithMany("Tokens")
.HasForeignKey("ApplicationId");
b.HasOne("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", "Authorization")
.WithMany("Tokens")
.HasForeignKey("AuthorizationId");
b.Navigation("Application");
b.Navigation("Authorization");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreApplication", b =>
{
b.Navigation("Authorizations");
b.Navigation("Tokens");
});
modelBuilder.Entity("OpenIddict.EntityFrameworkCore.Models.OpenIddictEntityFrameworkCoreAuthorization", b =>
{
b.Navigation("Tokens");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore;
using Umbraco.Cms.Persistence.EFCore.Migrations;
using Umbraco.Extensions;
namespace Umbraco.Cms.Persistence.EFCore.Sqlite;
public class SqliteMigrationProvider : IMigrationProvider
{
private readonly IDbContextFactory<UmbracoDbContext> _dbContextFactory;
public SqliteMigrationProvider(IDbContextFactory<UmbracoDbContext> dbContextFactory)
=> _dbContextFactory = dbContextFactory;
public string ProviderName => "Microsoft.Data.Sqlite";
public async Task MigrateAsync(EFCoreMigration migration)
{
UmbracoDbContext context = await _dbContextFactory.CreateDbContextAsync();
await context.MigrateDatabaseAsync(GetMigrationType(migration));
}
public async Task MigrateAllAsync()
{
UmbracoDbContext context = await _dbContextFactory.CreateDbContextAsync();
if (context.Database.CurrentTransaction is not null)
{
throw new InvalidOperationException("Cannot migrate all when a transaction is active.");
}
await context.Database.MigrateAsync();
}
private static Type GetMigrationType(EFCoreMigration migration) =>
migration switch
{
EFCoreMigration.InitialCreate => typeof(Migrations.InitialCreate),
_ => throw new ArgumentOutOfRangeException(nameof(migration), $@"Not expected migration value: {migration}")
};
}

View File

@@ -0,0 +1,14 @@
using Microsoft.EntityFrameworkCore;
using Umbraco.Cms.Persistence.EFCore.Migrations;
namespace Umbraco.Cms.Persistence.EFCore.Sqlite;
public class SqliteMigrationProviderSetup : IMigrationProviderSetup
{
public string ProviderName => "Microsoft.Data.Sqlite";
public void Setup(DbContextOptionsBuilder builder, string? connectionString)
{
builder.UseSqlite(connectionString, x => x.MigrationsAssembly(GetType().Assembly.FullName));
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Title>Umbraco CMS - EF Core - Sqlite migrations</Title>
<!-- TODO: Enable when final version is shipped (because there's currently no previous version) -->
<EnablePackageValidation>false</EnablePackageValidation>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.7" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Umbraco.Cms.Persistence.EFCore\Umbraco.Cms.Persistence.EFCore.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,56 @@
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Notifications;
using Umbraco.Cms.Infrastructure.Migrations;
using Umbraco.Cms.Infrastructure.Migrations.Notifications;
using Umbraco.Cms.Persistence.EFCore;
namespace Umbraco.Cms.Persistence.EFCore.Composition;
public class UmbracoEFCoreComposer : IComposer
{
public void Compose(IUmbracoBuilder builder)
{
builder.Services.AddSingleton<IEFCoreMigrationExecutor, EfCoreMigrationExecutor>();
builder.AddNotificationAsyncHandler<DatabaseSchemaAndDataCreatedNotification, EFCoreCreateTablesNotificationHandler>();
builder.AddNotificationAsyncHandler<UnattendedInstallNotification, EFCoreCreateTablesNotificationHandler>();
builder.Services.AddOpenIddict()
// Register the OpenIddict core components.
.AddCore(options =>
{
options
.UseEntityFrameworkCore()
.UseDbContext<UmbracoDbContext>();
});
}
}
public class EFCoreCreateTablesNotificationHandler : INotificationAsyncHandler<DatabaseSchemaAndDataCreatedNotification>, INotificationAsyncHandler<UnattendedInstallNotification>
{
private readonly IEFCoreMigrationExecutor _iefCoreMigrationExecutor;
public EFCoreCreateTablesNotificationHandler(IEFCoreMigrationExecutor iefCoreMigrationExecutor)
{
_iefCoreMigrationExecutor = iefCoreMigrationExecutor;
}
public async Task HandleAsync(UnattendedInstallNotification notification, CancellationToken cancellationToken)
{
await HandleAsync();
}
public async Task HandleAsync(DatabaseSchemaAndDataCreatedNotification notification, CancellationToken cancellationToken)
{
await HandleAsync();
}
private async Task HandleAsync()
{
await _iefCoreMigrationExecutor.ExecuteAllMigrationsAsync();
}
}

View File

@@ -0,0 +1,42 @@
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Infrastructure.Migrations;
using Umbraco.Cms.Persistence.EFCore.Migrations;
namespace Umbraco.Cms.Persistence.EFCore;
public class EfCoreMigrationExecutor : IEFCoreMigrationExecutor
{
private readonly IEnumerable<IMigrationProvider> _migrationProviders;
private readonly IOptions<ConnectionStrings> _options;
// We need to do migrations out side of a scope due to sqlite
public EfCoreMigrationExecutor(
IEnumerable<IMigrationProvider> migrationProviders,
IOptions<ConnectionStrings> options)
{
_migrationProviders = migrationProviders;
_options = options;
}
public async Task ExecuteSingleMigrationAsync(EFCoreMigration migration)
{
IMigrationProvider? provider = _migrationProviders.FirstOrDefault(x => x.ProviderName == _options.Value.ProviderName);
if (provider is not null)
{
await provider.MigrateAsync(migration);
}
}
public async Task ExecuteAllMigrationsAsync()
{
IMigrationProvider? provider = _migrationProviders.FirstOrDefault(x => x.ProviderName == _options.Value.ProviderName);
if (provider is not null)
{
await provider.MigrateAllAsync();
}
}
}

View File

@@ -0,0 +1,19 @@
using Microsoft.EntityFrameworkCore;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Persistence.EFCore;
namespace Umbraco.Extensions;
public static class BackOfficeAuthBuilderOpenIddictExtensions
{
public static IUmbracoBuilder AddUmbracoEFCoreDbContext(this IUmbracoBuilder builder)
{
builder.Services.AddUmbracoEFCoreContext<UmbracoDbContext>((options, connectionString, providerName) =>
{
// Register the entity sets needed by OpenIddict.
options.UseOpenIddict();
});
return builder;
}
}

View File

@@ -2,6 +2,7 @@ using System.Data;
using System.Data.Common;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage;
namespace Umbraco.Extensions;
@@ -50,4 +51,21 @@ public static class DbContextExtensions
var result = await dbCommand.ExecuteScalarAsync();
return (T?)result;
}
public static async Task MigrateDatabaseAsync(this DbContext context, Type targetMigration)
{
MigrationAttribute? migrationAttribute = targetMigration.GetCustomAttribute<MigrationAttribute>(false);
if (migrationAttribute is null)
{
throw new ArgumentException("The type does not have a MigrationAttribute", nameof(targetMigration));
}
await context.MigrateDatabaseAsync(migrationAttribute.Id);
}
public static async Task MigrateDatabaseAsync(this DbContext context, string targetMigrationId)
{
await context.GetService<IMigrator>().MigrateAsync(targetMigrationId);
}
}

View File

@@ -1,8 +1,11 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DistributedLocking;
using Umbraco.Cms.Persistence.EFCore.Locking;
using Umbraco.Cms.Persistence.EFCore.Migrations;
using Umbraco.Cms.Persistence.EFCore.Scoping;
namespace Umbraco.Extensions;
@@ -11,6 +14,55 @@ public static class UmbracoEFCoreServiceCollectionExtensions
{
public delegate void DefaultEFCoreOptionsAction(DbContextOptionsBuilder options, string? providerName, string? connectionString);
public static IServiceCollection AddUmbracoEFCoreContext<T>(this IServiceCollection services, DefaultEFCoreOptionsAction? defaultEFCoreOptionsAction = null)
where T : DbContext
{
defaultEFCoreOptionsAction ??= DefaultOptionsAction;
services.AddDbContext<T>(
(provider, builder) => SetupDbContext(defaultEFCoreOptionsAction, provider, builder),
optionsLifetime: ServiceLifetime.Transient);
services.AddDbContextFactory<T>((provider, builder) => SetupDbContext(defaultEFCoreOptionsAction, provider, builder));
services.AddUnique<IAmbientEFCoreScopeStack<T>, AmbientEFCoreScopeStack<T>>();
services.AddUnique<IEFCoreScopeAccessor<T>, EFCoreScopeAccessor<T>>();
services.AddUnique<IEFCoreScopeProvider<T>, EFCoreScopeProvider<T>>();
services.AddSingleton<IDistributedLockingMechanism, SqliteEFCoreDistributedLockingMechanism<T>>();
services.AddSingleton<IDistributedLockingMechanism, SqlServerEFCoreDistributedLockingMechanism<T>>();
return services;
}
private static void SetupDbContext(DefaultEFCoreOptionsAction defaultEFCoreOptionsAction, IServiceProvider provider, DbContextOptionsBuilder builder)
{
ConnectionStrings connectionStrings = GetConnectionStringAndProviderName(provider);
IEnumerable<IMigrationProviderSetup> migrationProviders = provider.GetServices<IMigrationProviderSetup>();
IMigrationProviderSetup? migrationProvider =
migrationProviders.FirstOrDefault(x => x.ProviderName == connectionStrings.ProviderName);
migrationProvider?.Setup(builder, connectionStrings.ConnectionString);
defaultEFCoreOptionsAction(builder, connectionStrings.ConnectionString, connectionStrings.ProviderName);
}
private static ConnectionStrings GetConnectionStringAndProviderName(IServiceProvider serviceProvider)
{
string? connectionString = null;
string? providerName = null;
ConnectionStrings connectionStrings = serviceProvider.GetRequiredService<IOptionsMonitor<ConnectionStrings>>().CurrentValue;
// Replace data directory
string? dataDirectory = AppDomain.CurrentDomain.GetData(Constants.System.DataDirectoryName)?.ToString();
if (string.IsNullOrEmpty(dataDirectory) is false)
{
connectionStrings.ConnectionString = connectionStrings.ConnectionString?.Replace(Constants.System.DataDirectoryPlaceholder, dataDirectory);
}
return connectionStrings;
}
public static IServiceCollection AddUmbracoEFCoreContext<T>(this IServiceCollection services, string connectionString, string providerName, DefaultEFCoreOptionsAction? defaultEFCoreOptionsAction = null)
where T : DbContext
{

View File

@@ -0,0 +1,10 @@
namespace Umbraco.Cms.Persistence.EFCore.Migrations;
public interface IMigrationProvider
{
string ProviderName { get; }
Task MigrateAsync(EFCoreMigration migration);
Task MigrateAllAsync();
}

View File

@@ -0,0 +1,10 @@
using Microsoft.EntityFrameworkCore;
namespace Umbraco.Cms.Persistence.EFCore.Migrations;
public interface IMigrationProviderSetup
{
string ProviderName { get; }
void Setup(DbContextOptionsBuilder builder, string? connectionString);
}

View File

@@ -8,7 +8,6 @@
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="7.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.7" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.5.0" />
</ItemGroup>

View File

@@ -0,0 +1,33 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
using Umbraco.Cms.Core;
namespace Umbraco.Cms.Persistence.EFCore;
/// <remarks>
/// To autogenerate migrations use the following commands
/// and insure the 'src/Umbraco.Web.UI/appsettings.json' have a connection string set with the right provider.
///
/// dotnet ef migrations add %Name% -s src/Umbraco.Web.UI -p src/Umbraco.Cms.Persistence.EFCore.SqlServer -- --provider SqlServer
/// dotnet ef migrations add %Name% -s src/Umbraco.Web.UI -p src/Umbraco.Cms.Persistence.EFCore.Sqlite -- --provider Sqlite
///
/// To find documentation about this way of working with the context see
/// https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/providers?tabs=dotnet-core-cli#using-one-context-type
/// </remarks>
public class UmbracoDbContext : DbContext
{
public UmbracoDbContext(DbContextOptions<UmbracoDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
foreach (IMutableEntityType entity in modelBuilder.Model.GetEntityTypes())
{
entity.SetTableName(Constants.DatabaseSchema.TableNamePrefix + entity.GetTableName());
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Umbraco.Cms.Persistence.EFCore.Migrations;
public enum EFCoreMigration
{
InitialCreate = 0
}

View File

@@ -0,0 +1,10 @@
using Umbraco.Cms.Persistence.EFCore.Migrations;
namespace Umbraco.Cms.Infrastructure.Migrations;
public interface IEFCoreMigrationExecutor
{
Task ExecuteSingleMigrationAsync(EFCoreMigration efCoreMigration);
Task ExecuteAllMigrationsAsync();
}

View File

@@ -291,6 +291,7 @@ namespace Umbraco.Cms.Infrastructure.Migrations.Install
using (var scope = _scopeProvider.CreateCoreScope())
{
var result = CreateSchemaAndData(scope);
scope.Notifications.Publish(new DatabaseSchemaAndDataCreatedNotification());
scope.Complete();
return result;
}

View File

@@ -0,0 +1,8 @@
using Umbraco.Cms.Core.Notifications;
namespace Umbraco.Cms.Infrastructure.Migrations.Notifications;
public class DatabaseSchemaAndDataCreatedNotification : INotification
{
}

View File

@@ -80,5 +80,6 @@ public class UmbracoPlan : MigrationPlan
// To 12.1.0
To<V_12_1_0.TablesIndexesImprovement>("{1187192D-EDB5-4619-955D-91D48D738871}");
To<V_12_1_0.AddOpenIddict>("{47DE85CE-1E16-42A0-8AF6-3EC3BCEF5471}");
}
}

View File

@@ -0,0 +1,20 @@
using Umbraco.Cms.Persistence.EFCore.Migrations;
namespace Umbraco.Cms.Infrastructure.Migrations.Upgrade.V_12_1_0;
public class AddOpenIddict : UnscopedMigrationBase
{
private readonly IEFCoreMigrationExecutor _iefCoreMigrationExecutor;
public AddOpenIddict(IMigrationContext context, IEFCoreMigrationExecutor iefCoreMigrationExecutor)
: base(context)
{
_iefCoreMigrationExecutor = iefCoreMigrationExecutor;
}
protected override void Migrate()
{
_iefCoreMigrationExecutor.ExecuteSingleMigrationAsync(EFCoreMigration.InitialCreate).GetAwaiter().GetResult();
}
}

View File

@@ -16,6 +16,12 @@
<RuntimeHostConfigurationOption Include="System.Globalization.AppLocalIcu" Value="68.2.0.9" Condition="$(RuntimeIdentifier.StartsWith('linux')) or $(RuntimeIdentifier.StartsWith('win')) or ('$(RuntimeIdentifier)' == '' and !$([MSBuild]::IsOSPlatform('osx')))" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.7">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<PropertyGroup>
<!-- Razor files are needed for the backoffice to work correctly -->
<CopyRazorGenerateFilesToPublishDirectory>true</CopyRazorGenerateFilesToPublishDirectory>

View File

@@ -153,6 +153,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Umbraco.Cms.Imaging.ImageSh
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Cms.Persistence.EFCore", "src\Umbraco.Cms.Persistence.EFCore\Umbraco.Cms.Persistence.EFCore.csproj", "{9046F56E-4AC3-4603-A6A3-3ACCF632997E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Cms.Persistence.EFCore.Sqlite", "src\Umbraco.Cms.Persistence.EFCore.Sqlite\Umbraco.Cms.Persistence.EFCore.Sqlite.csproj", "{8B4771F0-8EC2-4761-BBCE-DDE073DB3B7A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Umbraco.Cms.Persistence.EFCore.SqlServer", "src\Umbraco.Cms.Persistence.EFCore.SqlServer\Umbraco.Cms.Persistence.EFCore.SqlServer.csproj", "{9276C3F0-0DC9-46C9-BF32-9EE79D92AE02}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -311,6 +315,18 @@ Global
{35E3DA10-5549-41DE-B7ED-CC29355BA9FD}.Release|Any CPU.Build.0 = Release|Any CPU
{35E3DA10-5549-41DE-B7ED-CC29355BA9FD}.SkipTests|Any CPU.ActiveCfg = Debug|Any CPU
{35E3DA10-5549-41DE-B7ED-CC29355BA9FD}.SkipTests|Any CPU.Build.0 = Debug|Any CPU
{8B4771F0-8EC2-4761-BBCE-DDE073DB3B7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B4771F0-8EC2-4761-BBCE-DDE073DB3B7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B4771F0-8EC2-4761-BBCE-DDE073DB3B7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B4771F0-8EC2-4761-BBCE-DDE073DB3B7A}.Release|Any CPU.Build.0 = Release|Any CPU
{8B4771F0-8EC2-4761-BBCE-DDE073DB3B7A}.SkipTests|Any CPU.ActiveCfg = Debug|Any CPU
{8B4771F0-8EC2-4761-BBCE-DDE073DB3B7A}.SkipTests|Any CPU.Build.0 = Debug|Any CPU
{9276C3F0-0DC9-46C9-BF32-9EE79D92AE02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9276C3F0-0DC9-46C9-BF32-9EE79D92AE02}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9276C3F0-0DC9-46C9-BF32-9EE79D92AE02}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9276C3F0-0DC9-46C9-BF32-9EE79D92AE02}.Release|Any CPU.Build.0 = Release|Any CPU
{9276C3F0-0DC9-46C9-BF32-9EE79D92AE02}.SkipTests|Any CPU.ActiveCfg = Debug|Any CPU
{9276C3F0-0DC9-46C9-BF32-9EE79D92AE02}.SkipTests|Any CPU.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE