useRole.tsx 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import {useMemo} from 'react';
  2. import type {Organization} from 'sentry/types/organization';
  3. import {isActiveSuperuser} from 'sentry/utils/isActiveSuperuser';
  4. import useOrganization from 'sentry/utils/useOrganization';
  5. function hasOrganizationRole(organization: Organization, roleRequired: string): boolean {
  6. if (!Array.isArray(organization.orgRoleList)) {
  7. return false;
  8. }
  9. const roleIds = organization.orgRoleList.map(r => r.id);
  10. const requiredIndex = roleIds.indexOf(roleRequired);
  11. const currentIndex = roleIds.indexOf(organization.orgRole ?? '');
  12. if (requiredIndex === -1 || currentIndex === -1) {
  13. return false;
  14. }
  15. // If the user is a lower role than the required role, they do not have access
  16. return currentIndex >= requiredIndex;
  17. }
  18. interface UseRoleOptions {
  19. /**
  20. * Minimum required role.
  21. * The required role ('member', 'admin') are stored in the organization object.
  22. * eg: Organization.debugFilesRole = 'member'
  23. */
  24. role: // Extract keys to enforce that they are available on the Organization type
  25. Extract<keyof Organization, 'debugFilesRole' | 'attachmentsRole'>;
  26. }
  27. interface UseRoleResult {
  28. hasRole: boolean;
  29. /**
  30. * The required role ('member', 'admin') from the organization object.
  31. */
  32. roleRequired: string;
  33. }
  34. export function useRole(options: UseRoleOptions): UseRoleResult {
  35. const organization = useOrganization();
  36. return useMemo((): UseRoleResult => {
  37. const roleRequired = organization[options.role];
  38. if (isActiveSuperuser()) {
  39. return {hasRole: true, roleRequired};
  40. }
  41. const hasRole = hasOrganizationRole(organization, roleRequired);
  42. return {hasRole, roleRequired};
  43. }, [organization, options.role]);
  44. }