Merge pull request #5741 from sbwalker/dev

refactor TenantDBContext to accomodate AspNetUserPasskeys
This commit is contained in:
Shaun Walker
2025-10-22 14:06:30 -04:00
committed by GitHub
5 changed files with 102 additions and 12 deletions

View File

@ -84,7 +84,11 @@ namespace Microsoft.Extensions.DependencyInjection
options.Cookie.HttpOnly = true;
});
services.AddIdentityCore<IdentityUser>(options => { })
services.AddIdentityCore<IdentityUser>(options =>
{
// must be set prior to AddEntityFrameworkStores
options.Stores.SchemaVersion = IdentitySchemaVersions.Version3;
})
.AddEntityFrameworkStores<TenantDBContext>()
.AddSignInManager()
.AddDefaultTokenProviders()
@ -167,7 +171,7 @@ namespace Microsoft.Extensions.DependencyInjection
public static IServiceCollection AddOqtaneDbContext(this IServiceCollection services)
{
services.AddDbContext<MasterDBContext>(options => { }, ServiceLifetime.Transient);
services.AddDbContext<TenantDBContext>(options => { }, ServiceLifetime.Transient);
services.AddDbContext<TenantDBContext>(options => { }, ServiceLifetime.Scoped);
services.AddDbContextFactory<TenantDBContext>(opt => { }, ServiceLifetime.Transient);
return services;
}
@ -366,9 +370,6 @@ namespace Microsoft.Extensions.DependencyInjection
// User settings
options.User.RequireUniqueEmail = false;
options.User.AllowedUserNameCharacters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
// Stores settings
options.Stores.SchemaVersion = IdentitySchemaVersions.Version3;
});
// overrides defined in appsettings

View File

@ -395,7 +395,7 @@ namespace Oqtane.Infrastructure
var connectionString = _configManager.GetSetting($"{SettingKeys.ConnectionStringsSection}:{tenant.DBConnectionString}", "");
if (!string.IsNullOrEmpty(connectionString))
{
using (var tenantDbContext = new TenantDBContext(DBContextDependencies))
using (var tenantDbContext = new TenantDBContext(new DbContextOptions<TenantDBContext>(), DBContextDependencies))
{
AddEFMigrationsHistory(sql, connectionString, tenant.DBType, tenant.Version, false);
// push latest model into database

View File

@ -369,6 +369,15 @@ namespace Oqtane.Managers
IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
if (identityuser != null)
{
try
{
var passKeysFunctional = await _identityUserManager.GetPasskeysAsync(identityuser);
}
catch (Exception ex)
{
var error = ex.ToString();
}
var result = await _identitySignInManager.CheckPasswordSignInAsync(identityuser, user.Password, true);
if (result.Succeeded)
{

View File

@ -4,7 +4,6 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.Configuration;
@ -19,7 +18,7 @@ using Oqtane.Shared;
namespace Oqtane.Repository
{
public class DBContextBase : IdentityUserContext<IdentityUser>
public class DBContextBase : DbContext
{
private readonly ITenantManager _tenantManager;
private readonly IHttpContextAccessor _accessor;
@ -75,8 +74,6 @@ namespace Oqtane.Repository
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
ActiveDatabase.UpdateIdentityStoreTableNames(builder);
}
public override int SaveChanges()

View File

@ -1,6 +1,19 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.Extensions.Configuration;
using Oqtane.Databases.Interfaces;
using Oqtane.Extensions;
using Oqtane.Infrastructure;
using Oqtane.Migrations.Framework;
using Oqtane.Models;
using Oqtane.Repository.Databases.Interfaces;
using Oqtane.Shared;
// ReSharper disable CheckNamespace
// ReSharper disable MemberCanBePrivate.Global
@ -8,9 +21,79 @@ using Oqtane.Repository.Databases.Interfaces;
namespace Oqtane.Repository
{
public class TenantDBContext : DBContextBase, IMultiDatabase
public class TenantDBContext : IdentityUserContext<IdentityUser>, IMultiDatabase
{
public TenantDBContext(IDBContextDependencies DBContextDependencies) : base(DBContextDependencies) { }
private readonly ITenantManager _tenantManager;
private readonly IHttpContextAccessor _accessor;
private readonly IConfigurationRoot _config;
private string _connectionString = "";
private string _databaseType = "";
public TenantDBContext(DbContextOptions<TenantDBContext> options, IDBContextDependencies DBContextDependencies) : base(options)
{
_tenantManager = DBContextDependencies.TenantManager;
_accessor = DBContextDependencies.Accessor;
_config = DBContextDependencies.Config;
}
public IDatabase ActiveDatabase { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ReplaceService<IMigrationsAssembly, MultiDatabaseMigrationsAssembly>();
if (string.IsNullOrEmpty(_connectionString))
{
Tenant tenant = _tenantManager.GetTenant();
if (tenant != null)
{
_connectionString = _config.GetConnectionString(tenant.DBConnectionString);
if (_connectionString != null)
{
_connectionString = _connectionString.Replace($"|{Constants.DataDirectory}|", AppDomain.CurrentDomain.GetData(Constants.DataDirectory)?.ToString());
_databaseType = tenant.DBType;
}
else
{
// tenant connection string does not exist in appsettings.json
}
}
}
if (!string.IsNullOrEmpty(_databaseType))
{
var type = Type.GetType(_databaseType);
ActiveDatabase = Activator.CreateInstance(type) as IDatabase;
}
if (!string.IsNullOrEmpty(_connectionString) && ActiveDatabase != null)
{
optionsBuilder.UseOqtaneDatabase(ActiveDatabase, _connectionString);
}
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
ActiveDatabase.UpdateIdentityStoreTableNames(builder);
}
public override int SaveChanges()
{
DbContextUtils.SaveChanges(this, _accessor);
return base.SaveChanges();
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
DbContextUtils.SaveChanges(this, _accessor);
return base.SaveChangesAsync(cancellationToken);
}
public virtual DbSet<Site> Site { get; set; }
public virtual DbSet<Page> Page { get; set; }