index.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import {useState} from 'react';
  2. import Button from 'sentry/components/button';
  3. import ButtonBar from 'sentry/components/buttonBar';
  4. import EventDataSection from 'sentry/components/events/eventDataSection';
  5. import KeyValueList from 'sentry/components/events/interfaces/keyValueList';
  6. import {t} from 'sentry/locale';
  7. import {EntryType, Event} from 'sentry/types/event';
  8. import Help, {HelpProps} from './help';
  9. type View = 'report' | 'raw' | 'help';
  10. function getView(view: View, data: Record<any, any>, meta: Record<any, any>) {
  11. switch (view) {
  12. case 'report':
  13. return (
  14. <KeyValueList
  15. data={Object.entries(data).map(([key, value]) => {
  16. return {
  17. key,
  18. subject: key,
  19. value,
  20. meta: meta?.[key]?.[''],
  21. };
  22. })}
  23. isContextData
  24. />
  25. );
  26. case 'raw':
  27. return <pre>{JSON.stringify({'csp-report': data}, null, 2)}</pre>;
  28. case 'help':
  29. return <Help data={data as HelpProps['data']} />;
  30. default:
  31. throw new TypeError(`Invalid view: ${view}`);
  32. }
  33. }
  34. type Props = {
  35. data: Record<string, any>;
  36. event: Event;
  37. };
  38. export function Csp({data, event}: Props) {
  39. const [view, setView] = useState<View>('report');
  40. const entryIndex = event.entries.findIndex(entry => entry.type === EntryType.CSP);
  41. const meta = event._meta?.entries?.[entryIndex]?.data;
  42. const cleanData =
  43. data.original_policy !== 'string'
  44. ? data
  45. : {
  46. ...data,
  47. // Hide the report-uri since this is redundant and silly
  48. original_policy: data.original_policy.replace(/(;\s+)?report-uri [^;]+/, ''),
  49. };
  50. const actions = (
  51. <ButtonBar merged active={view}>
  52. <Button barId="report" size="xs" onClick={() => setView('report')}>
  53. {t('Report')}
  54. </Button>
  55. <Button barId="raw" size="xs" onClick={() => setView('raw')}>
  56. {t('Raw')}
  57. </Button>
  58. <Button barId="help" size="xs" onClick={() => setView('help')}>
  59. {t('Help')}
  60. </Button>
  61. </ButtonBar>
  62. );
  63. return (
  64. <EventDataSection
  65. type="csp"
  66. title={<h3>{t('CSP Report')}</h3>}
  67. actions={actions}
  68. wrapTitle={false}
  69. >
  70. {getView(view, cleanData, meta)}
  71. </EventDataSection>
  72. );
  73. }