Reactive Web and Multi Tenant

Can anyone confirm that the new 'Reactive Web' works with the Multi Tenant features?

As an FYI we have built a test multi tenant site using the traditional web app. In this app we have a number of tenants. We can create tenant specific records and the aggregates correctly display tenant specific content for various users. .... this is looking good.

BUT ....

When we apply a similar logic and design to a 'Reactive Web' app the aggregates don't naturally display content that is tenant specific. Is there something more we need to do?

Wouldn't expect any changes to be necessary here for this behaviour to work OOTB.


  1. Have you tried exposing the Tenant Id of your tables in your Reactive Web consumer module, and then filtering your aggregates using the built-in Site Property?

    TenantId = Site.TenantId


  2. You can also try to force the Tenant ID upon User Login using the TenantSwitch System action, to see if this affects your aggregates.

Hi Goncalo, thanks for the note. I have tried this option in the display from list aggregate, it just returns no values .

So, on further review of the records created with say 'UserTenant1' or 'UserTenant2' ... the records have no specific Tenant Name in 'Tenant ID'. See attached. 

Looks like we need to add some more logic on the creation of a record to push the correct Tenant Name into the record. Not sure.

Hmm... what's strange to me as well is that your previous, non-Reactive solution was already working with multi-tenancy enabled.


Can you confirm whether your Reactive Web module(s) are configured to use the same User Provider as your remaining modules?

If so, can you try switching the "Is Multi-tenant" option on/off in your Reactive Web module, to see if that has any effect?



The only other possible (though strange) explanations for a zero'ed Tenant ID that I can think of are:

  • You're creating Records before a User login, and this is somehow attributing the TenantId 'zero', or;
  • You're creating Records via a Timer or BPT process, and this is somehow attributing the TenantId 'zero'.



Looks like we need to add some more logic on the creation of a record to push the correct Tenant Name into the record. Not sure.

Absolutely. 

Whether the above cases are true for you or not, this would be my next course of action.
To do this:

  1. Create a Public Action or Function in one of your "working" multi-tenant modules to return the correct default Tenant ID, and pass this value to the "TenantSwitch" System Action in your Reactive Module before calling any CreateRecord actions.

    ... and if this fails ...

  2. Use the same Public Action, but explicitly pass the returned Tenant Id to each CreateRecord action, to force this value in the database.


Hopefully, one of the above methods will do the trick!

Hi Gonzalo, again many thanks for your note.

As a FYI .... we are only using logged in users, and the records are not being created with BPT or Timer ... so I don't feel these factors are causing the problem.

I am working on your option 2 as a possible answer i.e. Use the same Public Action, but explicitly pass the returned Tenant Id to each CreateRecord action, to force this value in the database.

Not sure how to call the logged in users 'Tenant ID' .... should we use the built in function GetEntryEspaceName()?

On the record creation side, how do we pass this value to the 'Tenant_ID' in the created record .... from within the Detail form? Not sure. 


Hi, John

Upon creation of the records, you should be providing its TenantId to be added like anyother attribute. The difference is that you must be on a module that exposes MultiTenancy and using entities exposed aswell.

Sam

John Ackery wrote:

Not sure how to call the logged in users 'Tenant ID' .... should we use the built in function GetEntryEspaceName()?

Use the built-in Site.TenantId site property to get the current Tenant Identifier.


It should always be non-zero; if it's zero in your Reactive Web module, use the one from the Public Action from your consumed, working module.


On the record creation side, how do we pass this value to the 'Tenant_ID' in the created record .... from within the Detail form? Not sure. 

If by Detail Form you mean the Form Widget in your WebScreen, then that's not quite right.


In your Reactive Web "consumer" Module, make sure the consumed Entity has it's Tenant ID exposed, by going to Data > [Dependencies] > [Your Entity] > Right-click > Advanced, and selecting the "Expose Tenant Identifier" from my first picture.


When you do this, the dependency will turn from Blue to Red, and the hidden Tenant_Id column will be exposed.

At this point, you can assign a value to this Tenant_Id column and ensure it gets written to the database upon Create, using the Site.TenantId value mentioned above, with a regular Assign.

Hi Goncalo, thanks again for your note. We have made progress but we still don't have a working multi tenant solution running on the Reactive Web.

Here is the Save Action with the Assign added

From within the Assign we cannot see the Site.TenantID


So we created a new Aggregate on Users with a filter User.Tenant_ID = Site.TenantID


We used this in the Assign. With this logic we can create new records with the correct Tenant ID. See below.

When we change from a user in Tenant 1 to say Tenant 4 the display shows only the correct tenant data. So far so goo.


The problem we have now is ..... our Tenant 1 has 3 users .... every time we select safe we get 3 records created.  Tenant 4 has 2 users ATM .... every time we select safe we get 2 records created.

Any ideas ... this seems weird ... like Reactive is not properly supporting 'Multi Tenant' features.


Ah! Now I see your problem clearly...


Site properties are only available Server-side, which explains why, when you are calling CreateOrUpdateUser from inside your Client Action in your Reactive Module, the Tenant ID is zero.


Instead, create a Server Action in the same module, and place the CreateOrUpdateUser inside that Server Action.
Here, the Site Property will be available for you to use in your Assign.


Replace the CreateOrUpdateUser with this new Server Action, and you should be good to go :-)

Hi Goncalo, 

Thanks for persevering on this ticket. We can create records with the specific Tenant ID. We have tried the 'Server Action' as suggested above ... this also works.

The issue now is on the display side, filtering the records by the logged in users Tenant ID. We need to be able to filter the aggregate ... this doesn't work.

SyntaxEditor Code Snippet

InjuryNotification.Tenant_Id = Site.TenantId

 We/you [thank you again!] have spent the last few days trying to make the 'Reactive Web' work as multi tenant option.  I am fast reaching a view we should switch development back to the core web solution. 

Solution

Hi John,


I’m a little confused. In your previous post, your server-side Aggregate was already filtering by Site.TenantID correctly.


If you’re trying to filter a Local Entity with the TenantId, then the Site.TenantID won’t be available for your client-side Aggregate. You’ll need to store it client-side and pass it to the Local Aggregate.


But I think we may be overcomplicating here. The User table should already be filtering correctly when you perform your server-side Aggregate.

Your original problem was the creation of User records. This is best solved by keeping the CreateRecord server-side as described in my previous reply.


Keep this, and remove the “Expose Tenant Identifer” from the Advanced Options so your User Entity returns to blue. Also remove the query of the Tenant table, and all logic you had to set/unset/manipulate the Tenant Identifier.


Hopefully, this will let the platform do its job and fix any remaining issues.

Solution

Hi Goncalo,

Thank you! Thank you!

I followed your instruction above. It took sometime to remove all the references to the 'User' Entity ... this was the problem. Once this was done .... it all worked.

I now have 4 test tenants, each with a number of users. I can now switch across user/tenants to properly create and view the correct data. Fantastic!

Regards John Ackery

I'll buy you a beer the next time you are in Australia ... Cheers.