diff --git a/.circleci/config.yml b/.circleci/config.yml index 206e99bd..8b43a4cb 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -3,7 +3,7 @@ version: 2.1 jobs: all-tests: docker: - - image: mcr.microsoft.com/playwright:next + - image: mcr.microsoft.com/playwright:latest # Steps to the job steps: - checkout @@ -14,12 +14,11 @@ jobs: git submodule update --init --recursive --jobs 8 - run: name: Install framework - # should be 20.04 but...whatever command: | - curl -O https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb - dpkg -i packages-microsoft-prod.deb && rm packages-microsoft-prod.deb - apt update && apt install -y dotnet-sdk-8.0 - corepack enable + apt update; apt install software-properties-common -y + add-apt-repository ppa:dotnet/backports -y + apt update && apt install -y dotnet-sdk-9.0 + corepack enable; corepack install -g pnpm - run: name: Show versions command: | @@ -32,7 +31,7 @@ jobs: dotnet restore cd DotnetPlayground.Web pnpm i - npx playwright install + npx playwright install --only-shell chromium cd .. - run: name: Run Unit and Integration Tests @@ -62,7 +61,7 @@ jobs: Pomelo-tests: docker: - - image: mcr.microsoft.com/dotnet/sdk:8.0 + - image: mcr.microsoft.com/dotnet/sdk:9.0 # Steps to the job steps: - checkout @@ -102,7 +101,7 @@ jobs: InkBall-tests: docker: - - image: mcr.microsoft.com/dotnet/sdk:8.0 + - image: mcr.microsoft.com/dotnet/sdk:9.0 # Steps to the job steps: - checkout @@ -142,7 +141,7 @@ jobs: DotnetPlayground-tests: docker: - - image: mcr.microsoft.com/dotnet/sdk:8.0 + - image: mcr.microsoft.com/dotnet/sdk:9.0 # Steps to the job steps: - checkout @@ -182,7 +181,7 @@ jobs: Playwright-tests: docker: - - image: mcr.microsoft.com/playwright:next + - image: mcr.microsoft.com/playwright:latest # Steps to the job steps: - checkout @@ -193,12 +192,11 @@ jobs: git submodule update --init --recursive --jobs 8 - run: name: Install framework - # should be 20.04 but...whatever command: | - curl -O https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb - dpkg -i packages-microsoft-prod.deb && rm packages-microsoft-prod.deb - apt update && apt install -y dotnet-sdk-8.0 - corepack enable + apt update; apt install software-properties-common -y + add-apt-repository ppa:dotnet/backports -y + apt update && apt install -y dotnet-sdk-9.0 + corepack enable; corepack install -g pnpm - run: name: Show versions command: | @@ -211,7 +209,7 @@ jobs: dotnet restore cd DotnetPlayground.Web pnpm i - npx playwright install chromium + npx playwright install --only-shell chromium cd .. - run: name: End-2-End Playwright browser tests @@ -225,7 +223,7 @@ jobs: build: docker: - - image: mcr.microsoft.com/dotnet/sdk:8.0 + - image: mcr.microsoft.com/dotnet/sdk:9.0 # Steps to the job steps: - checkout @@ -240,9 +238,9 @@ jobs: command: | curl -SLO https://deb.nodesource.com/nsolid_setup_deb.sh chmod 500 nsolid_setup_deb.sh - ./nsolid_setup_deb.sh 20 + ./nsolid_setup_deb.sh 21 apt-get install -y nodejs - corepack enable + corepack enable; corepack install -g pnpm - run: name: "Build Application according to some given configuration" command: dotnet publish -c Release --self-contained -r linux-x64 DotnetPlayground.Web diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 73bfb266..1ab637ab 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -52,7 +52,7 @@ jobs: - name: Set up .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: '8.x' + dotnet-version: '9.x' # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index c91ba4a1..17089a8e 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -18,7 +18,7 @@ jobs: - name: Setup .NET Core uses: actions/setup-dotnet@v4 with: - dotnet-version: 8.0.x + dotnet-version: 9.0.x - name: Build with dotnet env: DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 @@ -26,6 +26,6 @@ jobs: - name: Test with dotnet env: DBKind: "sqlite" - ConnectionStrings__Sqlite: "Filename=./bin/Debug/net8.0/Blogging.db" + ConnectionStrings__Sqlite: "Filename=./bin/Debug/net9.0/Blogging.db" DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 run: dotnet test -v m --configuration Debug diff --git a/.github/workflows/trivy-analysis.yml b/.github/workflows/trivy-analysis.yml index c14c1921..1ea4a88d 100644 --- a/.github/workflows/trivy-analysis.yml +++ b/.github/workflows/trivy-analysis.yml @@ -21,8 +21,7 @@ jobs: uses: aquasecurity/trivy-action@master with: image-ref: 'docker.io/chaosengine/dotnetplayground:${{ github.sha }}' - format: 'template' - template: '@/contrib/sarif.tpl' + format: 'sarif' output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' diff --git a/.vscode/launch.json b/.vscode/launch.json index 10967e4b..47ab206a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,7 @@ "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "${workspaceFolder}/DotnetPlayground.Web/bin/Debug/net8.0/DotnetPlayground.Web.dll", + "program": "${workspaceFolder}/DotnetPlayground.Web/bin/Debug/net9.0/DotnetPlayground.Web.dll", "args": [], "cwd": "${workspaceFolder}/DotnetPlayground.Web", "stopAtEntry": false, diff --git a/Caching-MySQL b/Caching-MySQL index b57e038c..d4ca0f9a 160000 --- a/Caching-MySQL +++ b/Caching-MySQL @@ -1 +1 @@ -Subproject commit b57e038ca5409e7f41dd4b63f579765d3738fcbc +Subproject commit d4ca0f9aa85b4124bb24c880b0a9fd309d97f2bb diff --git a/Dockerfile b/Dockerfile index 43b54a80..b4fbb50d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,13 +1,13 @@ # syntax = docker/dockerfile:experimental -FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0-bookworm-slim AS build RUN --mount=type=cache,target=/root/.nuget --mount=type=cache,target=/root/.local/ --mount=type=cache,target=/root/.cache/ --mount=type=cache,target=./DotnetPlayground.Web/node_modules RUN curl -SLO https://deb.nodesource.com/nsolid_setup_deb.sh && \ chmod 500 nsolid_setup_deb.sh && \ - ./nsolid_setup_deb.sh 20 && \ + ./nsolid_setup_deb.sh 21 && \ apt-get install -y nodejs && npm install -g pnpm WORKDIR /build -ENV DBKind="sqlite" ConnectionStrings__Sqlite="Filename=./bin/Debug/net8.0/Blogging.db" +ENV DBKind="sqlite" ConnectionStrings__Sqlite="Filename=./bin/Debug/net9.0/Blogging.db" ARG SOURCE_COMMIT ARG SOURCE_BRANCH ARG BUILD_CONFIG=${BUILD_CONFIG:-Release} @@ -35,11 +35,11 @@ RUN dotnet publish -c $BUILD_CONFIG --self-contained -r linux-x64 \ -FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-bookworm-slim +FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-bookworm-slim WORKDIR /app ENV USER=nobody ARG BUILD_CONFIG=${BUILD_CONFIG:-Release} -COPY --from=build --chown="$USER":"$USER" /build/DotnetPlayground.Web/bin/$BUILD_CONFIG/net8.0/linux-x64/publish/ /build/startApp.sh ./ +COPY --from=build --chown="$USER":"$USER" /build/DotnetPlayground.Web/bin/$BUILD_CONFIG/net9.0/linux-x64/publish/ /build/startApp.sh ./ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/Dockerfile.alpine b/Dockerfile.alpine index ea300011..717545a5 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -1,10 +1,10 @@ # syntax = docker/dockerfile:experimental -FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build +FROM mcr.microsoft.com/dotnet/sdk:9.0-alpine AS build RUN --mount=type=cache,target=/root/.nuget --mount=type=cache,target=/root/.local/ --mount=type=cache,target=/root/.cache/ --mount=type=cache,target=./DotnetPlayground.Web/node_modules RUN apk add --update nodejs npm && npm install -g pnpm WORKDIR /build -ENV DBKind="sqlite" ConnectionStrings__Sqlite="Filename=./bin/Debug/net8.0/Blogging.db" +ENV DBKind="sqlite" ConnectionStrings__Sqlite="Filename=./bin/Debug/net9.0/Blogging.db" ARG SOURCE_COMMIT ARG SOURCE_BRANCH ARG BUILD_CONFIG=${BUILD_CONFIG:-Release} @@ -32,12 +32,12 @@ RUN dotnet publish -c $BUILD_CONFIG --self-contained -r linux-musl-x64 \ -FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine +FROM mcr.microsoft.com/dotnet/runtime-deps:9.0-alpine RUN apk add tzdata WORKDIR /app ENV USER=nobody ARG BUILD_CONFIG=${BUILD_CONFIG:-Release} -COPY --from=build --chown="$USER":"$USER" /build/DotnetPlayground.Web/bin/$BUILD_CONFIG/net8.0/linux-musl-x64/publish/ /build/startApp.sh ./ +COPY --from=build --chown="$USER":"$USER" /build/DotnetPlayground.Web/bin/$BUILD_CONFIG/net9.0/linux-musl-x64/publish/ /build/startApp.sh ./ RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone diff --git a/DotnetPlayground.Tests/BaseTests.cs b/DotnetPlayground.Tests/BaseTests.cs index 95f131dd..289813e5 100644 --- a/DotnetPlayground.Tests/BaseTests.cs +++ b/DotnetPlayground.Tests/BaseTests.cs @@ -1,4 +1,5 @@ using DotnetPlayground.Models; +using InkBall.Module; using Lib.ServerTiming; using Microsoft.AspNetCore.DataProtection; using Microsoft.Data.Sqlite; @@ -51,6 +52,7 @@ public CancellationToken CancellationToken { "ConnectionStrings:Sqlite", "DataSource=:memory:" }, { "DBKind", "sqlite" } }); + ContextSnapshotHelper.DBKind = "sqlite"; var config = builder.Build(); var connection = new SqliteConnection(config.GetConnectionString("Sqlite")); @@ -60,6 +62,9 @@ public CancellationToken CancellationToken var options = new DbContextOptionsBuilder() .UseSqlite(connection) + // .ConfigureWarnings(b => + // b.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning) + // ) .Options; // Create the schema in the database diff --git a/DotnetPlayground.Tests/DotnetPlayground.Tests.csproj b/DotnetPlayground.Tests/DotnetPlayground.Tests.csproj index 54e44221..bcc988cf 100644 --- a/DotnetPlayground.Tests/DotnetPlayground.Tests.csproj +++ b/DotnetPlayground.Tests/DotnetPlayground.Tests.csproj @@ -1,7 +1,7 @@  - net8.0 + net9.0 latest false @@ -10,21 +10,21 @@ - - + + - + all runtime; build; native; contentfiles; analyzers - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/DotnetPlayground.Web/DotnetPlayground.Web.csproj b/DotnetPlayground.Web/DotnetPlayground.Web.csproj index 9a6d903e..58a62199 100644 --- a/DotnetPlayground.Web/DotnetPlayground.Web.csproj +++ b/DotnetPlayground.Web/DotnetPlayground.Web.csproj @@ -1,8 +1,8 @@  - 1.0.27-dotnet8 - net8.0 + 1.0.29-dotnet9 + net9.0 latest DotnetPlayground.Web Exe @@ -10,9 +10,9 @@ aspnet-DotnetPlayground-20161230022416 2.8 true - true + Debug;Release;Oracle @@ -37,27 +37,27 @@ - - + + buildTransitive - - - - - - - + + + + + + + - + - - - - - + + + + + @@ -79,9 +79,9 @@ - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/DotnetPlayground.Web/Helpers/ContextFactory.cs b/DotnetPlayground.Web/Helpers/ContextFactory.cs index d848a121..4b8e43d4 100644 --- a/DotnetPlayground.Web/Helpers/ContextFactory.cs +++ b/DotnetPlayground.Web/Helpers/ContextFactory.cs @@ -13,6 +13,7 @@ using System.Data.Common; using System.IO; using System.Linq; +using System.Net.Security; using System.Security.Cryptography.X509Certificates; using System.Text.RegularExpressions; using System.Threading; @@ -80,7 +81,12 @@ internal static string ConfigureDBKind(DbContextOptionsBuilder dbContextOpts, IC case "sqlite": conn_str = configuration.GetConnectionString("Sqlite"); if (dbContextOpts != null) + { dbContextOpts.UseSqlite(conn_str); + // dbContextOpts.ConfigureWarnings(b => + // b.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning) + // ); + } break; #if INCLUDE_POSTGRES @@ -93,7 +99,16 @@ internal static string ConfigureDBKind(DbContextOptionsBuilder dbContextOpts, IC { dbContextOpts.UseNpgsql(conn_str, (connBuilder) => { - connBuilder.ProvideClientCertificatesCallback(MyProvideClientCertificatesCallback); + // connBuilder.ProvideClientCertificatesCallback(MyProvideClientCertificatesCallback); + // connBuilder.RemoteCertificateValidationCallback(MyRemoteCertificateValidationCallback); + connBuilder.ConfigureDataSource(dsBuilder => + { + dsBuilder.UseSslClientAuthenticationOptionsCallback(authenticationOptions => + { + authenticationOptions.LocalCertificateSelectionCallback = MyLocalCertificateSelectionCallback; + //authenticationOptions.RemoteCertificateValidationCallback = MyRemoteCertificateValidationCallback; + }); + }); }); } break; @@ -113,7 +128,7 @@ internal static string ConfigureDBKind(DbContextOptionsBuilder dbContextOpts, IC if (start != -1) { start = start + "DIRECTORY=".Length; - int end = tab.Slice(start).IndexOf(")"); + int end = tab.Slice(start).IndexOf(")"); if (end != -1) { var directory = tab.Slice(start, end); @@ -128,7 +143,7 @@ internal static string ConfigureDBKind(DbContextOptionsBuilder dbContextOpts, IC dbContextOpts.UseOracle(conn_str, builder => //enable compatibility with old bool and json handling: https://docs.oracle.com/en/database/oracle/oracle-database/21/odpnt/EFCoreAPI.html#GUID-41786CF0-11E3-4AD2-8ED1-3D31D5FE2082 - builder .UseOracleSQLCompatibility(OracleSQLCompatibility.DatabaseVersion19) + builder.UseOracleSQLCompatibility(OracleSQLCompatibility.DatabaseVersion19) ); } break; @@ -158,6 +173,33 @@ internal static void MyProvideClientCertificatesCallback(X509CertificateCollecti } } + internal static X509Certificate MyLocalCertificateSelectionCallback(object sender, string targetHost, + X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers) + { + using (X509Store store = new X509Store(StoreLocation.CurrentUser)) + { + store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); + + var currentCerts = store.Certificates; + currentCerts = currentCerts.Find(X509FindType.FindByTimeValid, DateTime.Now, false); + currentCerts = currentCerts.Find(X509FindType.FindByIssuerName, "theBrain.ca", false); + currentCerts = currentCerts.Find(X509FindType.FindBySubjectName, Environment.MachineName, false); + if (currentCerts != null && currentCerts.Count > 0) + { + X509Certificate2 cert = currentCerts[0]; + return cert; + } + } + + return null; + } + + internal static bool MyRemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, + SslPolicyErrors sslPolicyErrors) + { + return true; + } + public IConfiguration GetConfiguration(string[] args) { var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); @@ -196,7 +238,7 @@ private static async Task SeedUsers(IServiceProvider scopedServices) }, pass: $"Playwright{i}!" //example pass: Playwright1!, Playwright2!... ); - + var existing_usr = await userManager.FindByEmailAsync(pair.user.Email); if (existing_usr == null) { @@ -224,19 +266,28 @@ public static async Task CreateDBApplyMigrationsAndSeedDebugUsers(IHost host, Ca { //main app context - blogging using var blogging_ctx = scope.ServiceProvider.GetRequiredService(); - //check if any migrations applied, if not - do that - var migrations_applied = await blogging_ctx.Database.GetAppliedMigrationsAsync(token); - if (!migrations_applied.Any()) + + //check if any migrations pending, if not - do that + var migrations_pending = await blogging_ctx.Database.GetPendingMigrationsAsync(token); + if (migrations_pending.Any()) + { + InkBall.Module.ContextSnapshotHelper.DBKind = blogging_ctx.Database.ProviderName; + await blogging_ctx.Database.MigrateAsync(token); + } //blogging db created now apply migration to games context using var games_ctx = scope.ServiceProvider.GetRequiredService(); - migrations_applied = await games_ctx.Database.GetAppliedMigrationsAsync(token); - //check if games related context migrations applied, if not - do that - if (!migrations_applied.Any(m => m.Contains(nameof(InkBall.Module.Migrations.InitialInkBall)))) - await games_ctx.Database.MigrateAsync(token); + migrations_pending = await games_ctx.Database.GetPendingMigrationsAsync(token); + //check if games related context migrations pending, if not - do that + if (migrations_pending.Any(m => m.Contains(nameof(InkBall.Module.Migrations.InitialInkBall)))) + { + InkBall.Module.ContextSnapshotHelper.DBKind = blogging_ctx.Database.ProviderName; + + await games_ctx.Database.MigrateAsync(token); + } //seed debug/test users if not present already await SeedUsers(scope.ServiceProvider); diff --git a/DotnetPlayground.Web/Migrations/20241214192549_PostColumnsNotNull.Designer.cs b/DotnetPlayground.Web/Migrations/20241214192549_PostColumnsNotNull.Designer.cs new file mode 100644 index 00000000..98852d4d --- /dev/null +++ b/DotnetPlayground.Web/Migrations/20241214192549_PostColumnsNotNull.Designer.cs @@ -0,0 +1,467 @@ +// +using System; +using DotnetPlayground.Models; +using InkBall.Module.Model; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +#if INCLUDE_POSTGRES +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +#endif +#if INCLUDE_ORACLE +using Oracle.EntityFrameworkCore.Metadata; +#endif + +#nullable disable + +namespace DotnetPlayground.Migrations +{ + [DbContext(typeof(BloggingContext))] + [Migration("20241214192549_PostColumnsNotNull")] + partial class PostColumnsNotNull + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.0"); + + modelBuilder.Entity("DotnetPlayground.SessionCache", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasMaxLength(449); + + b.Property("AbsoluteExpiration"); + + b.Property("ExpiresAtTime"); + + b.Property("SlidingExpirationInSeconds"); + + b.Property("Value") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("ExpiresAtTime") + .HasDatabaseName("Index_ExpiresAtTime"); + + b.ToTable("SessionCache"); + }); + + modelBuilder.Entity("DotnetPlayground.Models.Blog", b => + { + b.Property("BlogId") + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + + b.Property("Url") + .IsRequired(); + + b.HasKey("BlogId"); + + b.ToTable("Blog"); + }); + + modelBuilder.Entity("DotnetPlayground.Models.DataProtectionKey", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + + b.Property("FriendlyName").HasMaxLength(100); + + b.Property("Xml").HasMaxLength(4000); + + b.HasKey("Id"); + + b.ToTable("DataProtectionKeys"); + }); + + modelBuilder.Entity("DotnetPlayground.Models.GoogleProtectionKey", b => + { + b.Property("Id"); + + b.Property("Environment").HasMaxLength(100); + + b.Property("Json") + .HasColumnType(BloggingContext.JsonColumnTypeFromProvider(ActiveProvider)); + + b.HasKey("Id", "Environment"); + + b.ToTable("GoogleProtectionKeys"); + }); + + modelBuilder.Entity("DotnetPlayground.Models.HashesInfo", b => + { + b.Property("ID"); + + b.Property("Alphabet") + .HasColumnType("varchar(100)"); + + b.Property("Count"); + + b.Property("IsCalculating"); + + b.Property("KeyLength"); + + b.HasKey("ID"); + + b.ToTable("HashesInfo"); + }); + + modelBuilder.Entity("DotnetPlayground.Models.Post", b => + { + b.Property("PostId") + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + + b.Property("BlogId"); + + b.Property("Content") + .IsRequired(); + + b.Property("Title") + .IsRequired(); + + b.HasKey("PostId"); + + b.HasIndex("BlogId"); + + b.ToTable("Post"); + }); + + modelBuilder.Entity("DotnetPlayground.Models.ThinHashes", b => + { + b.Property("Key") + .ValueGeneratedOnAdd() + .HasColumnType("varchar(20)"); + + b.Property("HashMD5") + .IsRequired() + .HasColumnName("hashMD5") + .HasColumnType("char(32)"); + + b.Property("HashSHA256") + .IsRequired() + .HasColumnName("hashSHA256") + .HasColumnType("char(64)"); + + b.HasKey("Key"); + + b.ToTable("Hashes"); + }); + + modelBuilder.Entity("IdentitySample.DefaultUI.Data.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") + .HasMaxLength(256); + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("Name"); + + b.Property("NormalizedEmail") + .HasMaxLength(256); + + b.Property("NormalizedUserName") + .HasMaxLength(256); + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserName") + .HasMaxLength(256); + + b.Property("UserSettingsJSON") + .HasColumnName("UserSettings") + .HasColumnType(BloggingContext.JsonColumnTypeFromProvider(ActiveProvider)); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter(GamesContext.HasIndexFilterFromProvider(ActiveProvider, + null, null, null,null, "[NormalizedUserName] IS NOT NULL") + ); + + b.ToTable("AspNetUsers"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter(GamesContext.HasIndexFilterFromProvider(ActiveProvider, + null, null, null,null, "[NormalizedName] IS NOT NULL") + ); + + b.ToTable("AspNetRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(128); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId"); + + b.Property("RoleId"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("Name") + .HasMaxLength(128); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("DotnetPlayground.Models.Post", b => + { + b.HasOne("DotnetPlayground.Models.Blog", "Blog") + .WithMany("Post") + .HasForeignKey("BlogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Blog"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("IdentitySample.DefaultUI.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("IdentitySample.DefaultUI.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("IdentitySample.DefaultUI.Data.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("IdentitySample.DefaultUI.Data.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("DotnetPlayground.Models.Blog", b => + { + b.Navigation("Post"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DotnetPlayground.Web/Migrations/20241214192549_PostColumnsNotNull.cs b/DotnetPlayground.Web/Migrations/20241214192549_PostColumnsNotNull.cs new file mode 100644 index 00000000..d225befb --- /dev/null +++ b/DotnetPlayground.Web/Migrations/20241214192549_PostColumnsNotNull.cs @@ -0,0 +1,56 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DotnetPlayground.Migrations +{ + /// + public partial class PostColumnsNotNull : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Title", + table: "Post", + // type: "TEXT", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + // oldType: "TEXT", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "Content", + table: "Post", + // type: "TEXT", + nullable: false, + defaultValue: "", + oldClrType: typeof(string), + // oldType: "TEXT", + oldNullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "Title", + table: "Post", + // type: "TEXT", + nullable: true, + // oldType: "TEXT", + oldClrType: typeof(string) + ); + + migrationBuilder.AlterColumn( + name: "Content", + table: "Post", + // type: "TEXT", + nullable: true, + // oldType: "TEXT", + oldClrType: typeof(string) + ); + } + } +} diff --git a/DotnetPlayground.Web/Migrations/BloggingContextModelSnapshot.cs b/DotnetPlayground.Web/Migrations/BloggingContextModelSnapshot.cs index 81434912..08db6865 100644 --- a/DotnetPlayground.Web/Migrations/BloggingContextModelSnapshot.cs +++ b/DotnetPlayground.Web/Migrations/BloggingContextModelSnapshot.cs @@ -1,6 +1,9 @@ // using System; +using System.Linq; using DotnetPlayground.Models; +using InkBall.Module; +using InkBall.Module.Model; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; @@ -12,6 +15,8 @@ using Oracle.EntityFrameworkCore.Metadata; #endif +#nullable disable + namespace DotnetPlayground.Migrations { [DbContext(typeof(BloggingContext))] @@ -21,7 +26,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "5.0.1"); + .HasAnnotation("ProductVersion", "9.0.0"); modelBuilder.Entity("DotnetPlayground.SessionCache", b => { @@ -49,7 +54,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("DotnetPlayground.Models.Blog", b => { b.Property("BlogId") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; b.Property("Url") .IsRequired(); @@ -93,7 +112,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Environment").HasMaxLength(100); - b.Property("Json"); + b.Property("Json") + .HasColumnType(BloggingContext.JsonColumnTypeFromProvider(ContextSnapshotHelper.DBKind)); b.HasKey("Id", "Environment"); @@ -121,13 +141,29 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("DotnetPlayground.Models.Post", b => { b.Property("PostId") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; b.Property("BlogId"); - b.Property("Content"); + b.Property("Content") + .IsRequired(); - b.Property("Title"); + b.Property("Title") + .IsRequired(); b.HasKey("PostId"); @@ -139,19 +175,23 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("DotnetPlayground.Models.ThinHashes", b => { b.Property("Key") - .ValueGeneratedOnAdd() + .IsRequired() .HasColumnType("varchar(20)"); b.Property("HashMD5") .IsRequired() .HasColumnName("hashMD5") - .HasColumnType("char(32)"); + .HasColumnType(GamesContext.CharColumnTypeFromProvider(ContextSnapshotHelper.DBKind, + "char(32)", "char(32)", "character(32)", "char(32)", "char(32)" + )); b.Property("HashSHA256") .IsRequired() .HasColumnName("hashSHA256") - .HasColumnType("char(64)"); - + .HasColumnType(GamesContext.CharColumnTypeFromProvider(ContextSnapshotHelper.DBKind, + "char(64)", "char(64)", "character(64)", "char(64)", "char(64)" + )); + b.HasKey("Key"); b.ToTable("Hashes"); @@ -198,7 +238,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasMaxLength(256); b.Property("UserSettingsJSON") - .HasColumnName("UserSettings"); + .HasColumnName("UserSettings") + .HasColumnType(BloggingContext.JsonColumnTypeFromProvider(ContextSnapshotHelper.DBKind)); b.HasKey("Id"); @@ -207,7 +248,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("NormalizedUserName") .IsUnique() - .HasDatabaseName("UserNameIndex"); + .HasDatabaseName("UserNameIndex") + .HasFilter(GamesContext.HasIndexFilterFromProvider(ContextSnapshotHelper.DBKind, + null, null, null,null, "[NormalizedUserName] IS NOT NULL") + ); b.ToTable("AspNetUsers"); }); @@ -230,7 +274,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("NormalizedName") .IsUnique() - .HasDatabaseName("RoleNameIndex"); + .HasDatabaseName("RoleNameIndex") + .HasFilter(GamesContext.HasIndexFilterFromProvider(ContextSnapshotHelper.DBKind, + null, null, null,null, "[NormalizedName] IS NOT NULL") + ); b.ToTable("AspNetRoles"); }); @@ -238,7 +285,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; b.Property("ClaimType"); @@ -257,7 +318,21 @@ protected override void BuildModel(ModelBuilder modelBuilder) modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.Property("Id") - .ValueGeneratedOnAdd(); + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; b.Property("ClaimType"); diff --git a/DotnetPlayground.Web/Models/BloggingContext.cs b/DotnetPlayground.Web/Models/BloggingContext.cs index 23df51c6..4b6195df 100644 --- a/DotnetPlayground.Web/Models/BloggingContext.cs +++ b/DotnetPlayground.Web/Models/BloggingContext.cs @@ -4,8 +4,16 @@ using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.Extensions.Configuration; using System; +#if INCLUDE_POSTGRES +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +#endif +#if INCLUDE_ORACLE +using Oracle.EntityFrameworkCore.Metadata; +#endif namespace DotnetPlayground.Models { @@ -26,6 +34,9 @@ public BloggingContext CreateDbContext(string[] args) { var configuration = GetConfiguration(args); + InkBall.Module.ContextSnapshotHelper.DBKind = configuration.GetValue("DBKind"); + //Console.WriteLine($"DBKind = {configuration.GetValue("DBKind")}"); + var optionsBuilder = new DbContextOptionsBuilder(); ConfigureDBKind(optionsBuilder, configuration, null); @@ -66,7 +77,9 @@ public string ConnectionTypeName } internal static string JsonColumnTypeFromProvider(string activeProvider) => - GamesContext.JsonColumnTypeFromProvider(activeProvider); + GamesContext.JsonColumnTypeFromProvider(activeProvider, + "TEXT", "json", "jsonb", "VARCHAR2(4000)", "NVARCHAR(1000)" + ); public BloggingContext(DbContextOptions options) : base(options) @@ -82,7 +95,23 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity(entity => { - entity.Property(e => e.BlogId).ValueGeneratedOnAdd(); + entity.Property(e => e.BlogId) + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + entity.Property(e => e.Url).IsRequired(); entity.ToTable("Blog"); }); @@ -93,7 +122,24 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .WithMany(p => p.Post) .OnDelete(DeleteBehavior.Cascade) .HasForeignKey(d => d.BlogId); - entity.Property(e => e.PostId).ValueGeneratedOnAdd(); + + entity.Property(e => e.PostId) + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + entity.ToTable("Post"); }); @@ -112,9 +158,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.Property(e => e.HashSHA256).IsRequired().HasColumnType("char(64)").HasColumnName("hashSHA256"); } - //modelBuilder.Entity().HasIndex(e => e.HashMD5); - //modelBuilder.Entity().HasIndex(e => e.HashSHA256); - modelBuilder.Entity().ToTable("Hashes"); }); @@ -156,11 +199,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.HasKey(e => new { e.Id, e.Environment }); entity.Property(e => e.Environment) - //.HasConversion(new EnumToNumberConverter()) .HasMaxLength(100); entity.Property(e => e.Json) - .HasColumnType(JsonColumnTypeFromProvider(Database.ProviderName)); + .HasColumnType(BloggingContext.JsonColumnTypeFromProvider(Database.ProviderName)); entity.ToTable("GoogleProtectionKeys"); }); @@ -174,8 +216,144 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) // v => JsonConvert.DeserializeObject(v, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }) // ) .HasColumnName("UserSettings") - .HasColumnType(JsonColumnTypeFromProvider(Database.ProviderName)); + .HasColumnType(BloggingContext.JsonColumnTypeFromProvider(Database.ProviderName)); + + entity.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex") + .HasFilter(GamesContext.HasIndexFilterFromProvider(Database.ProviderName, + null, null, null,null, "[NormalizedUserName] IS NOT NULL") + ); }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId"); + + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("Name") + .HasMaxLength(128); + + b.Property("Value"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasMaxLength(128); + + b.Property("ProviderKey") + .HasMaxLength(128); + + b.Property("ProviderDisplayName"); + + b.Property("UserId") + .IsRequired(); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasAnnotation("Sqlite:Autoincrement", true) +#if INCLUDE_MYSQL + .HasAnnotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_SQLSERVER + .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_ORACLE + .HasAnnotation("Oracle:ValueGenerationStrategy", OracleValueGenerationStrategy.IdentityColumn) +#endif +#if INCLUDE_POSTGRES + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn) +#endif + ; + + b.Property("ClaimType"); + + b.Property("ClaimValue"); + + b.Property("RoleId") + .IsRequired(); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Name") + .HasMaxLength(256); + + b.Property("NormalizedName") + .HasMaxLength(256); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex") + .HasFilter(GamesContext.HasIndexFilterFromProvider(Database.ProviderName, + null, null, null,null, "[NormalizedName] IS NOT NULL") + ); + + b.ToTable("AspNetRoles"); + }); } } } diff --git a/DotnetPlayground.Web/Models/GamesContext.cs b/DotnetPlayground.Web/Models/GamesContext.cs index c2c10b3a..296c070a 100644 --- a/DotnetPlayground.Web/Models/GamesContext.cs +++ b/DotnetPlayground.Web/Models/GamesContext.cs @@ -1,7 +1,9 @@ using System; using System.Diagnostics.CodeAnalysis; +using InkBall.Module; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; namespace DotnetPlayground.Models { @@ -26,7 +28,10 @@ public InkBall.Module.Model.GamesContext CreateDbContext(string[] args) { var configuration = GetConfiguration(args); - var optionsBuilder = new DbContextOptionsBuilder(); + ContextSnapshotHelper.DBKind = configuration.GetValue("DBKind"); + //Console.WriteLine($"DBKind = {configuration.GetValue("DBKind")}"); + + var optionsBuilder = new DbContextOptionsBuilder(); ConfigureDBKind(optionsBuilder, configuration, null); diff --git a/DotnetPlayground.Web/Pages/WebCamGallery.cshtml b/DotnetPlayground.Web/Pages/WebCamGallery.cshtml index 959982df..204da167 100644 --- a/DotnetPlayground.Web/Pages/WebCamGallery.cshtml +++ b/DotnetPlayground.Web/Pages/WebCamGallery.cshtml @@ -17,7 +17,7 @@ - @@ -137,7 +137,7 @@ - diff --git a/DotnetPlayground.Web/Repositories/HashesRepository.cs b/DotnetPlayground.Web/Repositories/HashesRepository.cs index 1bf66187..3ab7840b 100644 --- a/DotnetPlayground.Web/Repositories/HashesRepository.cs +++ b/DotnetPlayground.Web/Repositories/HashesRepository.cs @@ -650,15 +650,15 @@ FROM RowAndWhere B LIMIT @limit OFFSET @offset "); - using (var conn = new NpgsqlConnection(_configuration.GetConnectionString("PostgreSql"))) + var conn = _entities.Database.GetDbConnection(); { - conn.ProvideClientCertificatesCallback = ContextFactory.MyProvideClientCertificatesCallback; + // conn.ProvideClientCertificatesCallback = ContextFactory.MyProvideClientCertificatesCallback; var found = new List(limit); int count = 0; await conn.OpenAsync(token); - using (var cmd = new NpgsqlCommand(sql, conn)) + using (var cmd = new NpgsqlCommand(sql, (NpgsqlConnection)conn)) { cmd.CommandText = sql; _logger.LogInformation("sql => {sql}", sql); diff --git a/DotnetPlayground.Web/Startup.cs b/DotnetPlayground.Web/Startup.cs index 153f17b1..a206ce97 100644 --- a/DotnetPlayground.Web/Startup.cs +++ b/DotnetPlayground.Web/Startup.cs @@ -451,7 +451,7 @@ public void ConfigureServices(IServiceCollection services) //.SetDefaultKeyLifetime(TimeSpan.FromDays(14)) //the default id 90 days - enough .PersistKeysToDbContext(); if (!string.IsNullOrEmpty(Configuration["DataProtection:CertFile"])) - protection_builder.ProtectKeysWithCertificate(new X509Certificate2(Configuration["DataProtection:CertFile"], Configuration["DataProtection:CertPassword"])); + protection_builder.ProtectKeysWithCertificate(X509CertificateLoader.LoadPkcs12FromFile(Configuration["DataProtection:CertFile"], Configuration["DataProtection:CertPassword"])); services.AddSignalR(options => diff --git a/DotnetPlayground.Web/Views/Hashes/VirtualScroll.cshtml b/DotnetPlayground.Web/Views/Hashes/VirtualScroll.cshtml index 42095a81..5f42e203 100644 --- a/DotnetPlayground.Web/Views/Hashes/VirtualScroll.cshtml +++ b/DotnetPlayground.Web/Views/Hashes/VirtualScroll.cshtml @@ -44,7 +44,7 @@ - @@ -56,7 +56,7 @@ - diff --git a/DotnetPlayground.Web/Views/ViewCodeGenerator/Index.cshtml b/DotnetPlayground.Web/Views/ViewCodeGenerator/Index.cshtml index 9f88edd5..759b1f3d 100644 --- a/DotnetPlayground.Web/Views/ViewCodeGenerator/Index.cshtml +++ b/DotnetPlayground.Web/Views/ViewCodeGenerator/Index.cshtml @@ -17,13 +17,13 @@ - - - +