superuserWarning.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. import {Fragment, useEffect} from 'react';
  2. import type {Client} from 'sentry/api';
  3. import {Badge} from 'sentry/components/core/badge';
  4. import {Button} from 'sentry/components/core/button';
  5. import {Tooltip} from 'sentry/components/tooltip';
  6. import AlertStore from 'sentry/stores/alertStore';
  7. import {space} from 'sentry/styles/space';
  8. import type {Organization} from 'sentry/types/organization';
  9. import useApi from 'sentry/utils/useApi';
  10. const POLICY_URL =
  11. 'https://www.notion.so/sentry/Sentry-Rules-for-Handling-Customer-Data-9612532c37e14eeb943a6a584abbac99';
  12. const SUPERUSER_MESSAGE = 'You are in superuser mode.';
  13. const WARNING_MESSAGE = (
  14. <Fragment>
  15. Please be familiar with the{' '}
  16. <a href={POLICY_URL} target="_none">
  17. rules for handling customer data
  18. </a>
  19. . Misuse of superuser will result in an unpleasant coffee chat with Legal, Security,
  20. and HR.
  21. </Fragment>
  22. );
  23. export function shouldExcludeOrg(organization?: Organization | null) {
  24. return organization?.slug === 'demo';
  25. }
  26. function handleExitSuperuser(api: Client) {
  27. api
  28. .requestPromise('/staff-auth/', {
  29. method: 'DELETE',
  30. })
  31. .then(() => window.location.reload());
  32. }
  33. function ExitSuperuserButton() {
  34. const api = useApi({persistInFlight: true});
  35. return (
  36. <Button
  37. style={{
  38. top: space(0.5),
  39. bottom: space(0.75),
  40. }}
  41. size="xs"
  42. priority="primary"
  43. onClick={() => {
  44. handleExitSuperuser(api);
  45. }}
  46. >
  47. Exit Superuser Mode
  48. </Button>
  49. );
  50. }
  51. type Props = {
  52. className?: string;
  53. organization?: Organization;
  54. };
  55. function SuperuserWarning({organization, className}: Props) {
  56. const isExcludedOrg = shouldExcludeOrg(organization);
  57. useEffect(() => {
  58. if (!isExcludedOrg) {
  59. AlertStore.addAlert({
  60. id: 'superuser-warning',
  61. message: (
  62. <Fragment>
  63. {SUPERUSER_MESSAGE} {WARNING_MESSAGE}
  64. </Fragment>
  65. ),
  66. type: 'error',
  67. opaque: true,
  68. neverExpire: true,
  69. noDuplicates: true,
  70. });
  71. }
  72. }, [isExcludedOrg]);
  73. if (isExcludedOrg) {
  74. return null;
  75. }
  76. return (
  77. <Badge type="warning" className={className}>
  78. <Tooltip
  79. isHoverable
  80. title={
  81. <Fragment>
  82. <ExitSuperuserButton />
  83. <br />
  84. <br />
  85. {WARNING_MESSAGE}
  86. </Fragment>
  87. }
  88. >
  89. Superuser
  90. </Tooltip>
  91. </Badge>
  92. );
  93. }
  94. export default SuperuserWarning;