role.tsx 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import {useMemo} from 'react';
  2. import ConfigStore from 'sentry/stores/configStore';
  3. import {Organization, User} from 'sentry/types';
  4. import {isActiveSuperuser} from 'sentry/utils/isActiveSuperuser';
  5. import {isRenderFunc} from 'sentry/utils/isRenderFunc';
  6. import withOrganization from 'sentry/utils/withOrganization';
  7. type RoleRenderProps = {
  8. hasRole: boolean;
  9. };
  10. type ChildrenRenderFn = (props: RoleRenderProps) => React.ReactElement | null;
  11. function checkUserRole(user: User, organization: Organization, role: RoleProps['role']) {
  12. if (!user) {
  13. return false;
  14. }
  15. if (isActiveSuperuser()) {
  16. return true;
  17. }
  18. if (!Array.isArray(organization.orgRoleList)) {
  19. return false;
  20. }
  21. const roleIds = organization.orgRoleList.map(r => r.id);
  22. if (!roleIds.includes(role) || !roleIds.includes(organization.role ?? '')) {
  23. return false;
  24. }
  25. const requiredIndex = roleIds.indexOf(role);
  26. const currentIndex = roleIds.indexOf(organization.role ?? '');
  27. return currentIndex >= requiredIndex;
  28. }
  29. interface RoleProps {
  30. /**
  31. * If children is a function then will be treated as a render prop and
  32. * passed RoleRenderProps.
  33. *
  34. * The other interface is more simple, only show `children` if user has
  35. * the minimum required role.
  36. */
  37. children: React.ReactElement | ChildrenRenderFn;
  38. /**
  39. * Current Organization
  40. */
  41. organization: Organization;
  42. /**
  43. * Minimum required role
  44. */
  45. role: string;
  46. }
  47. function Role({role, organization, children}: RoleProps): React.ReactElement | null {
  48. const user = ConfigStore.get('user');
  49. const hasRole = useMemo(
  50. () => checkUserRole(user, organization, role),
  51. // It seems that this returns a stable reference, but
  52. [organization, role, user]
  53. );
  54. if (isRenderFunc<ChildrenRenderFn>(children)) {
  55. return children({hasRole});
  56. }
  57. return hasRole ? children : null;
  58. }
  59. const withOrganizationRole = withOrganization(Role);
  60. export {withOrganizationRole as Role};