Implementing Multitenancy with GoodData.UI

  • 30 July 2021
  • 0 replies
  • 265 views

Userlevel 3

Maybe you’ve built your perfect analytics application already, and perhaps you only just finished a minimum viable product or a proof of concept. One way or another, sooner or later, you will want to make sure it works well against multiple workspaces.

Prerequisites

When developing custom solutions with GoodData.UI, you typically work against a single “master” workspace. In production though, you'll most commonly have a separate workspace for each of your customers/tenants. That means that you'll need to implement a mechanism that will execute the GoodData.UI frontend against the correct workspace for each authenticated user. 

As long as you use standard GoodData multi-tenancy tooling (LCM, workspace hierarchy, etc.) to create the individual workspaces for your tenants, you already comply with the following:

  • All the workspaces share the same logical data model (LDM).
  • All the workspaces share the same metadata objects referenced in the custom application (measures, attributes, insights, dashboards, …).

During the implementation, make sure that you use identifiers to identify the metadata (MD) objects in the source code. The reason is that identifiers remain the same across the master and all the tenant workspaces. It is recommended to use the catalog export tool that comes with create-gooddata-react-app and exposes all the workspace’s MD objects through the global Md variable. Here’s an example:

<ColumnChart
measures={[newMeasure('aaWP28vUgl64'), Md.TotalSales]} // ✅ using MD catalog
viewBy={newAttribute('label.product.brand')} // ✅ using identifier
stackBy={newAttribute('/gdc/md/<workspace-id>/obj/123')} // ❌ using URI
/>

Things to look out for:

  • Do not make manual adjustments to objects (LDM, measures, insights, dashboards) inherited from the master workspace in the individual tenant workspaces. If you modify a shared object referenced from your code your application might not work correctly against the modified tenant workspaces anymore.
  • If you use URIs or other means of identifying MD objects apart from identifiers, your custom application will not work correctly against the tenant workspaces (only identifiers stay the same across all workspaces).

Dynamic Workspace Resolution

In GoodData, each user has to have a GoodData account and can be given access to an arbitrary number of workspaces. As long as LDM is shared across workspaces and identifiers are used to identify the MD objects, the only remaining consideration is to make the workspace identifier itself dynamic. At this point, the implementation depends on your specific use case.

One workspace per user

Let’s assume that based on your business rules, each of your users needs access to exactly one workspace. In that case, you can let the user authenticate, then use the backend.workspaces().forCurrentUser().query() call to get the list of workspaces the user has access to, and simply pick the first (and only) one. In a create-gooddata-react-app, this can be done by setWorkspace('<workspace-id>') method returned by useWorkspace() context.

Note: To instantiate the backend variable, see bearFactory import from @gooddata/sdk-backend-bear for hosted GoodData Platform, and tigerFactory import from @gooddata/sdk-backend-tiger for GoodData.CN.

Multiple workspaces per user

If your users can generally access more than one workspace, the responsibility of workspace switching falls on you as a developer. It could be some smart, invisible logic underneath to decide for each user what workspace to choose. Or it could be some UI element, like a dropdown, to allow for workspace switching.

If you started your project with create-gooddata-react-app, navigate to /src/components/Header/Header.js, look for a component called <WorkspacePicker />, and uncomment it. Doing so will display a workspace picker in your UI, where each user will have a list of available workspaces to choose from. There’s also a workspaceFilter variable in src/constants.js, allowing you to filter out workspaces that should not render to the application user.

You can see the implementation of the default workspace picker in src/components/controls/WorkspacePicker.js. You can always develop your own and use this code for inspiration.

Summary

As long as you use identifiers to identify metadata objects in your source code, your application should be multi-tenant by default and should work fine against multiple workspaces. All the workspaces must share the same logical data model (LDM) and any measures, insights, and dashboards you reference from your code.

Our create-gooddata-react-app comes with a pre-built <WorkspacePicker /> component that can be easily uncommented and used for switching between workspaces. If you haven’t started your project using the create-gooddata-react-app tooling, we’d still recommend trying it out and getting inspired by the <WorkspaceProvider /> and <WorkspacePicker /> components.


0 replies

Be the first to reply!

Reply