Skip to content

Multi tenant configuration

Jon P Smith edited this page Sep 16, 2021 · 12 revisions

The multi-tenant feature requires three configuration setting to make it work:

  1. Setting the AuthP's options TenantType property.
  2. Setting the AuthP's options AppConnectionString property to the connection string used by your application's DbContext.
  3. Providing a implementation of the ITenantChangeService.

The code below is an example (taken from Example3' Startup class) of what you would put in your ASP.NET Core Startup class

services.RegisterAuthPermissions<Example3Permissions>(options =>
    {
        options.TenantType = TenantTypes.SingleLevel;
        options.AppConnectionString = Configuration
             .GetConnectionString("DefaultConnection");
    })
    .RegisterTenantChangeService<InvoiceTenantChangeService>()
    // ... other AuthP setup methods left out.

These three stages are covered below

1. Setting the TenantType property

By default AuthP's multi-tenant feature is not activated and you turn it on you need to set the TenantType to either:

  • TenantTypes.SingleLevel where each tenant is completely separate from other tenants
  • TenantTypes.HierarchicalTenant where each tenant can create sub-tenants

Setting TenantType property will cause AuthP to registers the https://github.com/JonPSmith/AuthPermissions.AspNetCore/blob/main/AuthPermissions.AspNetCore/Services/GetDataKeyFromUser.cs against the IGetDataKeyFilterFromUser interface - see Creating a multi-tenant app for how you can use this service.

2. Setting the AppConnectionString property

Changes to a AuthP Tenant also effects the your application data, so a create, update, delete or hierarchical tenant move requires changes in your application data. To do this the AuthP has to work with your implementation of the ITenantChangeService to update both the AuthP DbContext and your application DbContext within a SQL transaction. This means if an error occurs in either DbContext, then any changes already applied can be rolled back.

To make this work you need to:

  1. Your application DbContext and the AuthP DbContext must reside in the same database. This is possible because the AuthP DbContext sets a non-standard migration history table name which means AuthP migration and your application DbContext migrations can be applied separately.
  2. It needs the connection string to this database. I have chosen that you provide the connection string of your application DbContext, which means that AuthP can check that the AuthP connection string matches the application DbContext connection string.
  3. You need to create a class that implements the ITenantChangeService interface (see next section).

The digram below shows how this works.

How Tenant Change Service Works

3. Implement the ITenantChangeService interface an register it with AuthP

NOTE: There are two useful examples of Implementations of the ITenantChangeService. The Example3's InvoiceTenantChangeService and Example4' RetailTenantChangeService which provide a good starting point.

The ITenantChangeService interface contains five methods. they are:

  • DbContext GetNewInstanceOfAppContext(SqlConnection sqlConnection): this must create a valid instance of your application's DbContext from a SqlConnection. Note that you should provide null for the IGetDataKeyFromUser parameter in your application's DbContext constructor (see Creating a multi tenant app for more on this).
  • Task<string> CreateNewTenantAsync(DbContext appTransactionContext, string dataKey, int tenantId, string fullTenantName), which is called when a new AuthP tenant is created.
  • Task HandleUpdateNameAsync(DbContext appTransactionContext, string dataKey, int tenantId, string fullTenantName)`, which is called if the AuthP tenant's FullName has been updated.
  • Task<string> HandleTenantDeleteAsync(DbContext appTransactionContext, string dataKey, int tenantId, string fullTenantName), which is called when an AuthP tenant is deleted.
  • Task<string> MoveHierarchicalTenantDataAsync(DbContext appTransactionContext, string oldDataKey, string newDataKey, int tenantId, string newFullTenantName), which is called when a hierarchical Tenant is moved inside the hierarchy.

The last four method (create, update, delete and move) return a string - null means OK, a actual string says there is an error and the method will be aborted and both DbContexts are rolled back. Then the provided sting is returned as an error message to show to the user. NOTE: Alternatively you can throw a exception, which will also rolled back any changes applied within the transaction.

The transaction isolation level is Serializable because with hierarchical Tenants there can be lots of updates applied to the database.

As shown at the start you must register your implementation of the ITenantChangeService interface via the RegisterTenantChangeService<ITenantChangeService>() AuthP extension method.

Articles / Videos

Concepts

Setup

Usage

Admin

SupportCode

Clone this wiki locally