Skip to content

Commit

Permalink
feat: change default MultiTenantIdentityDbContext default index and k…
Browse files Browse the repository at this point in the history
…ey behavior

BREAKING CHANGE: all unique indexes and the UserLogin primary key in the standard Identity models are adjusted to include the tenant id
  • Loading branch information
AndrewTriesToCode committed Apr 21, 2024
1 parent 6d6f77f commit 81f5612
Showing 1 changed file with 174 additions and 118 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,148 +4,204 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Finbuckle.MultiTenant.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace Finbuckle.MultiTenant
namespace Finbuckle.MultiTenant.EntityFrameworkCore;

/// <summary>
/// An Identity database context that enforces tenant integrity on multi-tenant entity types.
/// <remarks>
/// All Identity entity types are multi-tenant by default.
/// </remarks>
/// </summary>
public class MultiTenantIdentityDbContext : MultiTenantIdentityDbContext<IdentityUser>
{
/// <summary>
/// An Identity database context that enforces tenant integrity on entity types
/// marked with the MultiTenant annotation or attribute.
/// <remarks>
/// All Identity entity types are multitenant by default.
/// </remarks>
/// </summary>
public abstract class MultiTenantIdentityDbContext : MultiTenantIdentityDbContext<IdentityUser>
/// <inheritdoc />
public MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor) : base(multiTenantContextAccessor)
{
protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo) : base(tenantInfo)
{
}
}

protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(tenantInfo, options)
{
}
/// <inheritdoc />
public MultiTenantIdentityDbContext(ITenantInfo tenantInfo) : base(tenantInfo)
{
}

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/// <inheritdoc />
public MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor, DbContextOptions options) : base(multiTenantContextAccessor, options)
{
}

builder.Entity<IdentityUser>().IsMultiTenant();
}
/// <inheritdoc />
public MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(tenantInfo, options)
{
}

/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

/// <summary>
/// An Identity database context that enforces tenant integrity on entity types
/// marked with the MultiTenant annotation or attribute.
/// <remarks>
/// TUser is not multitenant by default.
/// All other Identity entity types are multitenant by default.
/// </remarks>
/// </summary>
public abstract class MultiTenantIdentityDbContext<TUser> : MultiTenantIdentityDbContext<TUser, IdentityRole, string>
where TUser : IdentityUser
builder.Entity<IdentityUser>().IsMultiTenant().AdjustUniqueIndexes();
}
}

/// <summary>
/// An Identity database context that enforces tenant integrity on multi-tenant entity types.
/// <remarks>
/// TUser is not multitenant by default.
/// All other Identity entity types are multitenant by default.
/// </remarks>
/// </summary>
public abstract class MultiTenantIdentityDbContext<TUser> : MultiTenantIdentityDbContext<TUser, IdentityRole, string>
where TUser : IdentityUser
{
/// <inheritdoc />
protected MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor) : base(multiTenantContextAccessor)
{
protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo) : base(tenantInfo)
{
}
}

protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(tenantInfo, options)
{
}
/// <inheritdoc />
protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo) : base(tenantInfo)
{
}

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/// <inheritdoc />
protected MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor, DbContextOptions options) : base(multiTenantContextAccessor, options)
{
}

/// <inheritdoc />
protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(tenantInfo, options)
{
}

/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

builder.Entity<IdentityRole>().IsMultiTenant();
}
builder.Entity<IdentityRole>().IsMultiTenant().AdjustUniqueIndexes();
}
}

/// <summary>
/// An Identity database context that enforces tenant integrity on multi-tenant entity types.
/// <remarks>
/// TUser and TRole are not multitenant by default.
/// All other Identity entity types are multitenant by default.
/// </remarks>
/// </summary>
public abstract class MultiTenantIdentityDbContext<TUser, TRole, TKey> : MultiTenantIdentityDbContext<TUser, TRole, TKey, IdentityUserClaim<TKey>, IdentityUserRole<TKey>, IdentityUserLogin<TKey>, IdentityRoleClaim<TKey>, IdentityUserToken<TKey>>
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TKey : IEquatable<TKey>
{
/// <inheritdoc />
protected MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor) : base(multiTenantContextAccessor)
{
}

/// <summary>
/// An Identity database context that enforces tenant integrity on entity types
/// marked with the MultiTenant annotation or attribute.
/// <remarks>
/// TUser and TRole are not multitenant by default.
/// All other Identity entity types are multitenant by default.
/// </remarks>
/// </summary>
public abstract class MultiTenantIdentityDbContext<TUser, TRole, TKey> : MultiTenantIdentityDbContext<TUser, TRole, TKey, IdentityUserClaim<TKey>, IdentityUserRole<TKey>, IdentityUserLogin<TKey>, IdentityRoleClaim<TKey>, IdentityUserToken<TKey>>
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TKey : IEquatable<TKey>
/// <inheritdoc />
protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo) : base(tenantInfo)
{
protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo) : base(tenantInfo)
{
}
}

protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(tenantInfo, options)
{
}
/// <inheritdoc />
protected MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor, DbContextOptions options) : base(multiTenantContextAccessor, options)
{
}

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
/// <inheritdoc />
protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(tenantInfo, options)
{
}

/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

builder.Entity<IdentityUserClaim<TKey>>().IsMultiTenant();
builder.Entity<IdentityUserRole<TKey>>().IsMultiTenant();
builder.Entity<IdentityUserLogin<TKey>>().IsMultiTenant();
builder.Entity<IdentityRoleClaim<TKey>>().IsMultiTenant();
builder.Entity<IdentityUserToken<TKey>>().IsMultiTenant();
}
builder.Entity<IdentityUserClaim<TKey>>().IsMultiTenant().AdjustUniqueIndexes();
builder.Entity<IdentityUserRole<TKey>>().IsMultiTenant().AdjustUniqueIndexes();
builder.Entity<IdentityUserLogin<TKey>>().IsMultiTenant().AdjustUniqueIndexes().AdjustKeys(builder);
builder.Entity<IdentityRoleClaim<TKey>>().IsMultiTenant().AdjustUniqueIndexes();
builder.Entity<IdentityUserToken<TKey>>().IsMultiTenant().AdjustUniqueIndexes();
}
}

/// <summary>
/// An Identity database context that enforces tenant integrity on entity types
/// marked with the MultiTenant annotation or attribute.
/// <remarks>
/// No Identity entity types are multitenant by default.
/// </remarks>
/// </summary>
public abstract class MultiTenantIdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken>, IMultiTenantDbContext
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TUserRole : IdentityUserRole<TKey>
where TUserLogin : IdentityUserLogin<TKey>
where TRoleClaim : IdentityRoleClaim<TKey>
where TUserToken : IdentityUserToken<TKey>
where TKey : IEquatable<TKey>
{
public ITenantInfo? TenantInfo { get; }

public TenantMismatchMode TenantMismatchMode { get; set; } = TenantMismatchMode.Throw;

public TenantNotSetMode TenantNotSetMode { get; set; } = TenantNotSetMode.Throw;

/// <summary>
/// Constructs the database context instance and binds to the current tenant.
/// </summary>
/// <param name="multiTenantContextAccessor">The MultiTenantContextAccessor instance used to bind the context instance to a tenant.</param>
protected MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor)
{
TenantInfo = multiTenantContextAccessor.MultiTenantContext.TenantInfo;
}

protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo)
{
TenantInfo = tenantInfo;
}

/// <summary>
/// An Identity database context that enforces tenant integrity on entity types
/// marked with the MultiTenant annotation or attribute.
/// <remarks>
/// No Identity entity types are multitenant by default.
/// </remarks>
/// Constructs the database context instance and binds to the current tenant.
/// </summary>
public abstract class MultiTenantIdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken>, IMultiTenantDbContext
where TUser : IdentityUser<TKey>
where TRole : IdentityRole<TKey>
where TUserClaim : IdentityUserClaim<TKey>
where TUserRole : IdentityUserRole<TKey>
where TUserLogin : IdentityUserLogin<TKey>
where TRoleClaim : IdentityRoleClaim<TKey>
where TUserToken : IdentityUserToken<TKey>
where TKey : IEquatable<TKey>
{
public ITenantInfo TenantInfo { get; }

public TenantMismatchMode TenantMismatchMode { get; set; } = TenantMismatchMode.Throw;

public TenantNotSetMode TenantNotSetMode { get; set; } = TenantNotSetMode.Throw;

protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo)
{
this.TenantInfo = tenantInfo;
}

protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(options)
{
this.TenantInfo = tenantInfo;
}

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureMultiTenant();
}

public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
this.EnforceMultiTenant();
return base.SaveChanges(acceptAllChangesOnSuccess);
}

public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
CancellationToken cancellationToken = default(CancellationToken))
{
this.EnforceMultiTenant();
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
/// <param name="multiTenantContextAccessor">The MultiTenantContextAccessor instance used to bind the context instance to a tenant.</param>
/// <param name="options">The database options instance.</param>
protected MultiTenantIdentityDbContext(IMultiTenantContextAccessor multiTenantContextAccessor, DbContextOptions options) : base(options)
{
TenantInfo = multiTenantContextAccessor.MultiTenantContext.TenantInfo;
}

protected MultiTenantIdentityDbContext(ITenantInfo tenantInfo, DbContextOptions options) : base(options)
{
TenantInfo = tenantInfo;
}

/// <inheritdoc />
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ConfigureMultiTenant();
}

/// <inheritdoc />
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
this.EnforceMultiTenant();
return base.SaveChanges(acceptAllChangesOnSuccess);
}

/// <inheritdoc />
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess,
CancellationToken cancellationToken = default(CancellationToken))
{
this.EnforceMultiTenant();
return await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
}

0 comments on commit 81f5612

Please sign in to comment.