Open Closed

Custom data filters - looking for correct approach for "sub-tenants" #11072

ips-ad created


Please answer the following questions before submitting an issue. YOU MAY DELETE THE PREREQUISITES SECTION.

  • What is your product version? -> 8.1
  • What is your product type (Angular or MVC)? -> Angular
  • What is product framework type (.net framework or .net core)? -> .net Core


We have an app running for offices with entities like dockets, correspondence, activity recordings, invoices, addresses and so on. We're hosting as cloud provider and use multi tenancy to separate different offices. So far, so good. Now we need to add client access for those offices, let's call it sub-tenants: An office wants to share the dockets related to the address of a certain client with this client. And (maybe) all related rows like correspondence etc. belonging to this client's dockets.

The idea is to provide those clients an account in Zero with a special role for customers. Then there will be a new "sharing" entity with rows containing e.g. docket ids. So we'd need a filter that checks:

  1. Is entity affected by sub-tenant/client filtering? (not everything has to be filtered)
  2. If true, is logged in user sub-tenant/client? (e.g. by looking up if he has a certain role associated)
  3. If true, apply additional filter by looking up in the sharing entity if he is allowed to access a certain docket id
    1. If the entity is not a docket, but an entity which is related to dockets, it also has to be checked if access to this docket id is allowed

I hope I cloud make clear what we need to realize - an optional filter for certain users only, and the filter has to lookup in a new "sharing" entity for allowed dockets. And all entities referring to dockets (i.e. they have a docketId property) have to be filtered with the same rule.

We started with this approach\How-To\add-custom-data-filter-ef-core, but still fail to implement the filter condition. We can't simply add a property to filter like in IMayHaveOrganizationUnit, we need a filter that looks up another entity and sort of joins them. If we're wrong with this approach and there's a better solution, we'd also be happy to learn about it.

Thanks very much!

6 Answer(s)
  • 0
    ismcagdas created
    Support Team

    Hi @ips-ad

    For item 2, you can store a field in AbpSession, for example IsThisASubTenant. In this way, you can use it in your custom filter. For item 1, could you explain what do you mean by "Is entity affected by sub-tenant/client" ? Obviously, for itme 3, you need acess the database.

    I'm not totally sure but, it seems like creating a new entity named Client and creating your own structure for clients to access Dockets might be a better choice.

  • 0
    ips-ad created

    Thank you for your quick answer and pointing to the possibility of storing a field in AbpSession! I will give a quick example of our current data structure and the goal.

    Users properties (existing entity)

    • Regular user: All tenant's data should be accessible
    • Special user for client access: Only filtered dockets and rows of other entities related to those dockets should be accessible

    Docket properties (existing entity)

    • Id
    • Client address number
    • Title, byte arrays and more...

    Other entities (e. g. correspondence, existing entity)

    • Docket Id (not a foreign key in all cases)
    • Subject, byte arrays and more...

    <br> A new "sharing" entity to manage client access would mainly consist of rows containing:

    • User Id (or maybe role Id or OU Id)
    • List of allowed docket Ids for this user/role/OU
    • and/or list of allowed client address numbers (for above docket property) -> also resulting in a list of allowed docket Ids

    So the filter would always (if user has client flag) have to check through a docket Id if access is allowed. The filter may have to read the corresponding docket row to get the client address number and look for an allowing rule in mentioned new sharing entity.

    This approach would save us from having to add fields in all entities and having to update all of them when changes in the client access happen (WAL archive might get really big in that case). The price will certainly be less performance for filtered users due to the filter, but hopefully acceptable.

    Another idea is to create a new claim with a list of allowed docket Ids first and do something like this  Expression<Func<TEntity, bool>> mayHaveClientFilter = e => ClientAccessAllowedDocketIds().Contains(EF.Property<string>(e, "ID_AKTE"))  in protected override Expression<Func<TEntity, bool>> CreateFilterExpression<TEntity>(). The docket Ids list should be refreshed at user login at least.

  • 0
    ismcagdas created
    Support Team


    Another idea is to create a new claim with a list of allowed docket Ids

    This is a good idea and which will allow you to use a custom filter. I didn't suggest this since I don't know how big this list can get. If it is not a big list, this will be really a good choice.

  • 0
    ips-ad created

    Well, it might be a list length somewhere between 10 and max. 10000 docket Ids, so not always that small. Is it possible to create a claim or field in AbpSession of type List<string>? Can you maybe give an example?

    We'd do some performance testing with this approach then.

  • 0
    ismcagdas created
    Support Team


    Yes, you can follow\How-To\add-custom-session-field-aspnet-core. Instead of public string UserEmail, you can define a List field.

    But, you will still need to sync this List when a docket is granted/revoked from a tenant.

  • 0
    ips-ad created

    Thanks, we'll give that a try and see how performant it is. At least it should only affect the performance of filtered users.