Hide a module in UI via app model?

Hi,
How can I hide/show a module (a tab) via app model depend on different user role? For example as admin I want to see all tabs in the UI but as a broker employee I should be able to see and work with only 1 tab.
Regards,

Hi,
Please have a look at the “permission” setting in the menu of your module definition, to see if it satifies your use case.

module-permissions

Kind regards

Hi,
I found helpful middlewares in the full-stack project template that could add & remove modules based on loggin & logout action. You could get the user roles and apply your “authority rule” here.

/**
 * On login, registers all modules that current user has access to.
 */
export const registerModulesOnLoginMiddleware = StoreFactories.createMiddleware((api, next, action) => {
    if (UaaActions.loggedIn.match(action)) {
        getAllModules().forEach(m => moduleRegistry.addModule(m));
    }
    return next(action);
});

/**
 * On logout, unregisters all modules.
 */
export const unregisterModulesOnLogoutMiddleware = StoreFactories.createMiddleware((api, next, action) => {
    if (UaaActions.loggedOut.match(action)) {
        // The logout action has to be processed first so that any existing activities are removed first
        const result = next(action);

        const moduleIds = moduleRegistry.getAllModules().map(({ id }) => id);
        moduleIds.forEach(id => moduleRegistry.removeModuleById(id));

        return result;
    }
    return next(action);
});

Best

Moin moin,

in the PI-project we did this by extending the registerModulesOnLoginMiddleware:

/**
 * On login, registers all modules that current user has access to.
 */
export const registerModulesOnLoginMiddleware = StoreFactories.createMiddleware((api, next, action) => {
	if (UaaActions.loggedIn.match(action)) {
		const user = action.payload.user as UaaExtendedUser;
		getUserAccessibleModules(user, getAllModules()).forEach(m => {
			moduleRegistry.addModule(m);
		});
	}
	return next(action);
});
/**
 * Filters a given array of modules based on the access rights of the user and the `roles` annotation in the appmodel.
 * @param user The logged in user
 * @param modules All modules in the application for role based checks
 * @returns An array of modules the user has the rights to access
 */
export function getUserAccessibleModules(user: UaaExtendedUser, modules: Module[]): Module[] {
	return modules
		.map(module => {
			const moduleAnnotations = module.model && module.model({}).header.annotations;
			const requiredRoles = moduleAnnotations?.find(a => a.name === "roles")?.value?.split(",");
			// Some modules might have no roles, so ensure they are added
			const userHasRole = !requiredRoles || userHasAtLeastOneRole(user, requiredRoles);
			return userHasRole ? module : undefined;
		})
		.filter(Boolean) as Module[];
}

export function userHasAtLeastOneRole(user: UaaExtendedUser, requiredRoles: string[]): boolean {
	const userRoles = user.roles.map(role => role.name);
	return requiredRoles.some(roleName => userRoles.indexOf(roleName) >= 0);
}

Hi, thanks for the hint.
I’ve tried the permission with specific role, but it does not seem to work. I tried on appmodel version 1.0.0 and 3.1.0

Hi,
please note that the user permissions should be passed as a prop to the ApplicationFrameLayout component for the menu item filtering to work, e.g.:

function ApplicationFrameLayoutWithPermissions(props: FrameViews.ApplicationFrameLayoutProps): JSX.Element {
    const user = useSelector(UaaSelectors.user) as UaaExtendedUser | undefined;
    const permissions = user?.roles.flatMap(role => role.accessRights.map(right => right.name));

    return (
        <FrameViews.ApplicationFrameLayout
            {...props}
            permissions={permissions}
        />
    );
}

In this example (taken from the A12 fullstack template), the user will only see the menu items that have a matching permission set up (or none at all).

So if all menu items were to have “admin” as permission and the current user does not have this permission, he/she would see no menu entries at all :slight_smile: