Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to retrieve the user's roles in a ReactJS plugin application integrated with the Mashroom portal? #118

Open
atans96 opened this issue Jun 6, 2024 · 1 comment
Labels
question Further information is requested

Comments

@atans96
Copy link

atans96 commented Jun 6, 2024

import {
  MashroomPortalAppService,
  MashroomPortalAppSetup,
  MashroomPortalAppUser,
  MashroomPortalClientServices,
  MashroomPortalMessageBus,
  MashroomPortalProxyPaths,
} from '@mashroom/mashroom-portal/type-definitions'
import React, { ReactNode, createContext, useCallback, useContext } from 'react'

type MashroomContextProps = {
  messageBus: MashroomPortalMessageBus
  portalAppService: MashroomPortalAppService
  appConfig: any
  bffBasePath: string
  user: MashroomPortalAppUser
  appId: string
  proxyPaths: MashroomPortalProxyPaths
  portalAppSetup: MashroomPortalAppSetup
  portalClientServices: MashroomPortalClientServices
  getRemoteUserPrivateTopic: () => string
}
type MashroomProviderProps = {
  children: ReactNode
  portalClientServices: MashroomPortalClientServices
  portalAppSetup: MashroomPortalAppSetup
}

const MashroomContext = createContext({} as MashroomContextProps)

export const useMashroom = () => useContext(MashroomContext)

export const MashroomProvider = ({ children, portalAppSetup, portalClientServices }: MashroomProviderProps) => {
  const { appConfig, proxyPaths, user, appId } = portalAppSetup
  const { messageBus, portalAppService } = portalClientServices || {}

  const bffBasePath = proxyPaths.bff

  console.log('MashroomProvider MashroomContext.', MashroomContext)

  /**
   * This is a custom function to get the user's private topic. The reason of using this is
   * the default getRemoteUserPrivateTopic provided by Mashroom is using the username as the
   * topic, but instead of using username, our application uses user_uid
   *
   * @returns string - user's private topic
   *
   * @throws {Error} if user_uid is not defined in keycloak
   * */
  const getRemoteUserPrivateTopic = useCallback(() => {
    if (!user.extraData.user_uid) throw new Error('user_uid is not defined in keycloak')

    return `userID/${user.extraData.user_uid}`
  }, [user.extraData.user_uid])

  return (
    <MashroomContext.Provider
      value={{
        messageBus,
        portalAppService,
        appConfig,
        bffBasePath,
        user,
        appId,
        proxyPaths,
        portalAppSetup,
        portalClientServices,
        getRemoteUserPrivateTopic,
      }}
    >
      {children}
    </MashroomContext.Provider>
  )
}
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

import type { MashroomPortalAppPluginBootstrapFunction } from "@mashroom/mashroom-portal/type-definitions";
import { MashroomProvider } from "@predictintel/cybersmart-react-library";

export const bootstrap: MashroomPortalAppPluginBootstrapFunction = (
  portalAppHostElement,
  portalAppSetup,
  clientServices
) => {
  const root = ReactDOM.createRoot(portalAppHostElement);
  root.render(
    <React.StrictMode>
      <MashroomProvider
        portalAppSetup={portalAppSetup}
        portalClientServices={clientServices}
      >
        <App />
      </MashroomProvider>
    </React.StrictMode>
  );

  return Promise.resolve({
    willBeRemoved: () => {
      root.unmount();
    },
  });
};
import type { MashroomPortalAppPluginBootstrapFunction } from "@mashroom/mashroom-portal/type-definitions";

// This allows lazy load of actual bootstrap.
// It is required to support microfrontend using Mashroom and Webpack Module Federation
const bootstrap: MashroomPortalAppPluginBootstrapFunction = async (
  portalAppHostElement,
  portalAppSetup,
  clientServices,
) => {
  try {
    const bootstrapModule = await import("./bootstrap");
    const mashroomBootstrap = bootstrapModule.bootstrap;
    mashroomBootstrap(portalAppHostElement, portalAppSetup, clientServices);
  } catch (error) {
    console.error("Error importing the module:", error);
  }
};

(global as any).reactUserMgtBootstrap = bootstrap;

I am developing a ReactJS plugin application (let's call it "plugin-app2") that will be integrated with the Mashroom portal web application. In this plugin application, I need to check the user's role to conditionally show or hide certain functionalities based on their permissions.

Is there a way to retrieve the roles assigned to the currently logged-in user within the Mashroom portal? This information would allow me to control the visibility of features in my ReactJS plugin application based on the user's role and permissions.

If there is a method or API provided by the Mashroom portal to access the user's role information, could someone please guide me on how to implement it in my ReactJS application?

Maybe this?

portalClientServices.portalAdminService.getExistingRoles()

Any help or suggestions would be greatly appreciated.

@atans96 atans96 changed the title Get the roles from mashroom for OIDC plugin How to retrieve the user's roles in a ReactJS plugin application integrated with the Mashroom portal? Jun 6, 2024
@nonblocking
Copy link
Owner

One of the design goals of Mashroom was to make the Apps portable and maximally reusable, therefore it is not possible to directly check some roles (which may be different from server to server). Instead, you can define permissions which are mapped to roles in the metadata. The App itself only receives a map of "permission name" -> boolean.

It works like this:

{
    "mashroom": {
        "plugins": [
            {
              // ...
                "defaultConfig": {
                   // ...
                    "rolePermissions": {
                        "allowedTodoSomethingSpecial": ["Role2", "Role3"]
                    }
                }
            }
        ]
    }
}

And in the App you can check if the user has the permission "allowedTodoSomethingSpecial" like this:

const bootstrap: MashroomPortalAppPluginBootstrapFunction = (portalAppHostElement, portalAppSetup, clientServices) => {
    const {appConfig: {markdownMessage, pingButtonLabel}, user} = portalAppSetup;
  
    if (user.permissions.allowedTodoSomethingSpecial) {
        // ...
    }

}

You could then change the mapping for every server instance in the "plugins" section of the server config.

@nonblocking nonblocking added the question Further information is requested label Jul 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants