0

A custom ReactJS wrapper component should be used to wrap code and only render it, if the user has the required permission. Therefore, it needs to accept two parameters, the children that shall be rendered as well as the permission it needs to check for.

The idea is to use it like this:

const AdminTools = () => {
  return (
    <RequirePermission require_permission="ui:see_admin_menu">
      <>
        <h1>Sudo mode</h1>
        <Link href="/intern/users/">
          <a>
            <ActionCard link>User management</ActionCard>
          </a>
        </Link>
      </>
    </RequirePermission>
  );

};

What I came up with so far is the following code:

const RequirePermission = (children: React.FC<{}>, required_permission: string) => {
    const user = useContext(AuthContext);

    let hasPermission = false;
    if (user.state == AuthState.Authorized) {

        user.user?.realm_access?.roles.forEach(role => {
            if (permissions[role].includes(required_permission)) {
                hasPermission = true;
            }
        });
    }

    if (hasPermission) {
        return children;
    } else {
        return <div />;
    }

};

export default RequirePermission;

When using the code snippet as described above, the following error is thrown:

    Type '{ children: Element; require_permission: string; }' is not assignable to type 'IntrinsicAttributes & FC<{}>'.
  Property 'children' does not exist on type 'IntrinsicAttributes & FC<{}>'.ts(2322)
'RequirePermission' cannot be used as a JSX component.
  Its return type 'FC<{}> | Element' is not a valid JSX element.
    Type 'FunctionComponent<{}>' is missing the following properties from type 'Element': type, props, keyts(2786)

I don't really understand the error message to be frank. Any help would be much appreciated.

//Edit:

Error messages given by proposed code:

This JSX tag's 'children' prop expects a single child of type 'ReactChildren', but multiple children were provided.ts(2746)

and

'RequirePermission' cannot be used as a JSX component.
  Its return type 'Element | ReactChildren' is not a valid JSX element.
    Type 'ReactChildren' is missing the following properties from type 'Element': type, props, key
Daniel
  • 1,398
  • 4
  • 20
  • 47

1 Answers1

2

Try this, importing ReactChildren from react.

I wish i could explain this better, but i know typescript is expecting a JSX/TSX element, so we could use ReactElement for the return type.

For a better explanation on the children type

https://stackoverflow.com/a/58123882/7174241

import React, { ReactChildren, ReactElement, ReactNode } from "react";

interface RequireType {
  children: ReactChildren | ReactNode | ReactElement;
  required_permission: string;
}

const RequirePermission = ({ children, required_permission }: RequireType):ReactElement => {
  const user = useContext(AuthContext);

  let hasPermission = false;
  if (user.state == AuthState.Authorized) {
    user.user?.realm_access?.roles.forEach((role) => {
      if (permissions[role].includes(required_permission)) {
        hasPermission = true;
      }
    });
  }

 return <>{hasPermission ? children : null}</>

};

export default RequirePermission;
BARNOWL
  • 3,326
  • 10
  • 44
  • 80
  • Thank you for your answer! This changed code still yields two errors, I've edited them in the original question for better readability – Daniel May 16 '22 at 16:01
  • try the updated answer.. – BARNOWL May 16 '22 at 16:09
  • 1
    Thank you @BARNOWL, this works absolutely perfect! I'll try to understand the changes and their behaviour now to learn a bit more myself. Thanks for your help! – Daniel May 16 '22 at 16:14