Просмотр исходного кода

ref(advanced-data-scrubbing): Open rule edition modal via url - (#38734)

Priscila Oliveira 2 лет назад
Родитель
Сommit
742df0a46d

+ 2 - 2
static/app/components/events/interfaces/crashContent/exception/content.spec.tsx

@@ -148,12 +148,12 @@ describe('Exception Content', function () {
       })
       })
     ).toHaveAttribute(
     ).toHaveAttribute(
       'href',
       'href',
-      '/settings/org-slug/projects/project-slug/security-and-privacy/#advanced-data-scrubbing'
+      '/settings/org-slug/projects/project-slug/security-and-privacy/advanced-data-scrubbing/0/'
     );
     );
 
 
     expect(screen.getByRole('link', {name: 'project-slug'})).toHaveAttribute(
     expect(screen.getByRole('link', {name: 'project-slug'})).toHaveAttribute(
       'href',
       'href',
-      '/settings/org-slug/projects/project-slug/security-and-privacy/#advanced-data-scrubbing'
+      '/settings/org-slug/projects/project-slug/'
     );
     );
   });
   });
 });
 });

+ 2 - 2
static/app/components/events/interfaces/frame/frameVariables.spec.tsx

@@ -98,12 +98,12 @@ describe('Frame Variables', function () {
       })
       })
     ).toHaveAttribute(
     ).toHaveAttribute(
       'href',
       'href',
-      '/settings/org-slug/projects/project-slug/security-and-privacy/#advanced-data-scrubbing'
+      '/settings/org-slug/projects/project-slug/security-and-privacy/advanced-data-scrubbing/0/'
     );
     );
 
 
     expect(screen.getByRole('link', {name: 'project-slug'})).toHaveAttribute(
     expect(screen.getByRole('link', {name: 'project-slug'})).toHaveAttribute(
       'href',
       'href',
-      '/settings/org-slug/projects/project-slug/security-and-privacy/#advanced-data-scrubbing'
+      '/settings/org-slug/projects/project-slug/'
     );
     );
   });
   });
 });
 });

+ 2 - 2
static/app/components/events/interfaces/message.spec.tsx

@@ -69,12 +69,12 @@ describe('Message entry', function () {
       })
       })
     ).toHaveAttribute(
     ).toHaveAttribute(
       'href',
       'href',
-      '/settings/org-slug/security-and-privacy/#advanced-data-scrubbing'
+      '/settings/org-slug/security-and-privacy/advanced-data-scrubbing/0/'
     );
     );
 
 
     expect(screen.getByRole('link', {name: 'org-slug'})).toHaveAttribute(
     expect(screen.getByRole('link', {name: 'org-slug'})).toHaveAttribute(
       'href',
       'href',
-      '/settings/org-slug/security-and-privacy/#advanced-data-scrubbing'
+      '/settings/org-slug/'
     );
     );
   });
   });
 });
 });

+ 49 - 66
static/app/components/events/meta/annotatedText/utils.tsx

@@ -2,7 +2,6 @@ import styled from '@emotion/styled';
 
 
 import Link from 'sentry/components/links/link';
 import Link from 'sentry/components/links/link';
 import {tct} from 'sentry/locale';
 import {tct} from 'sentry/locale';
-import space from 'sentry/styles/space';
 import {ChunkType, Organization, Project} from 'sentry/types';
 import {ChunkType, Organization, Project} from 'sentry/types';
 import {convertRelayPiiConfig} from 'sentry/views/settings/components/dataScrubbing/convertRelayPiiConfig';
 import {convertRelayPiiConfig} from 'sentry/views/settings/components/dataScrubbing/convertRelayPiiConfig';
 import {getRuleDescription} from 'sentry/views/settings/components/dataScrubbing/utils';
 import {getRuleDescription} from 'sentry/views/settings/components/dataScrubbing/utils';
@@ -35,10 +34,9 @@ export function getTooltipText({
 
 
   // default data scrubbing
   // default data scrubbing
   if (KNOWN_RULES[rule_id]) {
   if (KNOWN_RULES[rule_id]) {
-    return tct('[method] because of the PII rule [break][rule-description]', {
+    return tct('[method] because of the PII rule [ruleDescription]', {
       method,
       method,
-      break: <br />,
-      'rule-description': KNOWN_RULES[rule_id],
+      ruleDescription: KNOWN_RULES[rule_id],
     });
     });
   }
   }
 
 
@@ -48,11 +46,14 @@ export function getTooltipText({
   if (level === 'organization') {
   if (level === 'organization') {
     // if organization is not available, fall back to the default message
     // if organization is not available, fall back to the default message
     if (!organization) {
     if (!organization) {
-      return tct('[method] because of the PII rule [break][rule-description]', {
-        method,
-        break: <br />,
-        'rule-description': rule_id,
-      });
+      return (
+        <Wrapper>
+          {tct('[method] because of the PII rule [ruleDescription]', {
+            method,
+            ruleDescription: rule_id,
+          })}
+        </Wrapper>
+      );
     }
     }
 
 
     const rules = convertRelayPiiConfig(organization?.relayPiiConfig);
     const rules = convertRelayPiiConfig(organization?.relayPiiConfig);
@@ -61,27 +62,18 @@ export function getTooltipText({
     return (
     return (
       <Wrapper>
       <Wrapper>
         {tct(
         {tct(
-          '[method] because of the PII rule [break][rule-description] in the settings of the organization [break][slug]',
+          '[method] because of the PII rule [ruleDescription] in the settings of the organization [organizationSlug]',
           {
           {
             method,
             method,
-            break: <br />,
-            'rule-description': (
-              <RuleDescription>
-                <Link
-                  to={`/settings/${organization.slug}/security-and-privacy/#advanced-data-scrubbing`}
-                >
-                  {rule ? getRuleDescription(rule) : ruleId}
-                </Link>
-              </RuleDescription>
+            ruleDescription: (
+              <Link
+                to={`/settings/${organization.slug}/security-and-privacy/advanced-data-scrubbing/${ruleId}/`}
+              >
+                {rule ? getRuleDescription(rule) : ruleId}
+              </Link>
             ),
             ),
-            slug: (
-              <Slug>
-                <Link
-                  to={`/settings/${organization.slug}/security-and-privacy/#advanced-data-scrubbing`}
-                >
-                  {organization.slug}
-                </Link>
-              </Slug>
+            organizationSlug: (
+              <Link to={`/settings/${organization.slug}/`}>{organization.slug}</Link>
             ),
             ),
           }
           }
         )}
         )}
@@ -91,52 +83,43 @@ export function getTooltipText({
 
 
   // if project and organization are not available, fall back to the default message
   // if project and organization are not available, fall back to the default message
   if (!project || !organization) {
   if (!project || !organization) {
-    return tct('[method] because of the PII rule [break][rule-description]', {
-      method,
-      break: <br />,
-      'rule-description': rule_id,
-    });
+    return (
+      <Wrapper>
+        {tct('[method] because of the PII rule [ruleDescription]', {
+          method,
+          ruleDescription: rule_id,
+        })}
+      </Wrapper>
+    );
   }
   }
 
 
   const rules = convertRelayPiiConfig(project?.relayPiiConfig);
   const rules = convertRelayPiiConfig(project?.relayPiiConfig);
   const rule = rules.find(({id}) => String(id) === ruleId);
   const rule = rules.find(({id}) => String(id) === ruleId);
 
 
-  return tct(
-    '[method] because of the PII rule [break][rule-description] in the settings of the project [break][slug]',
-    {
-      method,
-      break: <br />,
-      'rule-description': (
-        <RuleDescription>
-          <Link
-            to={`/settings/${organization.slug}/projects/${project.slug}/security-and-privacy/#advanced-data-scrubbing`}
-          >
-            {rule ? getRuleDescription(rule) : ruleId}
-          </Link>
-        </RuleDescription>
-      ),
-      slug: (
-        <Slug>
-          <Link
-            to={`/settings/${organization.slug}/projects/${project?.slug}/security-and-privacy/#advanced-data-scrubbing`}
-          >
-            {project.slug}
-          </Link>
-        </Slug>
-      ),
-    }
+  return (
+    <Wrapper>
+      {tct(
+        '[method] because of the PII rule [ruleDescription] in the settings of the project [projectSlug]',
+        {
+          method,
+          ruleDescription: (
+            <Link
+              to={`/settings/${organization.slug}/projects/${project.slug}/security-and-privacy/advanced-data-scrubbing/${ruleId}/`}
+            >
+              {rule ? getRuleDescription(rule) : ruleId}
+            </Link>
+          ),
+          projectSlug: (
+            <Link to={`/settings/${organization.slug}/projects/${project?.slug}/`}>
+              {project.slug}
+            </Link>
+          ),
+        }
+      )}
+    </Wrapper>
   );
   );
 }
 }
 
 
 const Wrapper = styled('div')`
 const Wrapper = styled('div')`
-  display: grid;
-  gap: ${space(0.5)};
-`;
-
-const RuleDescription = styled('div')`
-  margin: ${space(0.5)} 0;
-`;
-
-const Slug = styled('div')`
-  margin-top: ${space(0.5)};
+  line-height: ${p => p.theme.text.lineHeightBody};
 `;
 `;

+ 17 - 0
static/app/data/forms/organizationSecurityAndPrivacyGroups.tsx

@@ -18,6 +18,9 @@ export default [
         type: 'boolean',
         type: 'boolean',
         label: t('Require Two-Factor Authentication'),
         label: t('Require Two-Factor Authentication'),
         help: t('Require and enforce two-factor authentication for all members'),
         help: t('Require and enforce two-factor authentication for all members'),
+        'aria-label': t(
+          'Enable to require and enforce two-factor authentication for all members'
+        ),
         confirm: {
         confirm: {
           true: t(
           true: t(
             'This will remove all members without two-factor authentication' +
             'This will remove all members without two-factor authentication' +
@@ -104,6 +107,7 @@ export default [
 
 
         label: t('Allow Join Requests'),
         label: t('Allow Join Requests'),
         help: t('Allow users to request to join your organization'),
         help: t('Allow users to request to join your organization'),
+        'aria-label': t('Enable to allow users to request to join your organization'),
         confirm: {
         confirm: {
           true: t(
           true: t(
             'Are you sure you want to allow users to request to join your organization?'
             'Are you sure you want to allow users to request to join your organization?'
@@ -121,6 +125,7 @@ export default [
         type: 'boolean',
         type: 'boolean',
         label: t('Require Data Scrubber'),
         label: t('Require Data Scrubber'),
         help: t('Require server-side data scrubbing be enabled for all projects'),
         help: t('Require server-side data scrubbing be enabled for all projects'),
+        'aria-label': t('Enable server-side data scrubbing'),
         confirm: {
         confirm: {
           false: t(
           false: t(
             'Disabling this can have privacy implications for ALL projects, are you sure you want to continue?'
             'Disabling this can have privacy implications for ALL projects, are you sure you want to continue?'
@@ -134,6 +139,9 @@ export default [
         help: t(
         help: t(
           'Require the default scrubbers be applied to prevent things like passwords and credit cards from being stored for all projects'
           'Require the default scrubbers be applied to prevent things like passwords and credit cards from being stored for all projects'
         ),
         ),
+        'aria-label': t(
+          'Enable to apply default scrubbers to prevent things like passwords and credit cards from being stored'
+        ),
         confirm: {
         confirm: {
           false: t(
           false: t(
             'Disabling this can have privacy implications for ALL projects, are you sure you want to continue?'
             'Disabling this can have privacy implications for ALL projects, are you sure you want to continue?'
@@ -152,6 +160,9 @@ export default [
         help: t(
         help: t(
           'Additional field names to match against when scrubbing data for all projects. Separate multiple entries with a newline.'
           'Additional field names to match against when scrubbing data for all projects. Separate multiple entries with a newline.'
         ),
         ),
+        'aria-label': t(
+          'Enter additional field names to match against when scrubbing data for all projects. Separate multiple entries with a newline.'
+        ),
         extraHelp: t(
         extraHelp: t(
           'Note: These fields will be used in addition to project specific fields.'
           'Note: These fields will be used in addition to project specific fields.'
         ),
         ),
@@ -170,6 +181,9 @@ export default [
         help: t(
         help: t(
           'Field names which data scrubbers should ignore. Separate multiple entries with a newline.'
           'Field names which data scrubbers should ignore. Separate multiple entries with a newline.'
         ),
         ),
+        'aria-label': t(
+          'Enter field names which data scrubbers should ignore. Separate multiple entries with a newline.'
+        ),
         extraHelp: t(
         extraHelp: t(
           'Note: These fields will be used in addition to project specific fields'
           'Note: These fields will be used in addition to project specific fields'
         ),
         ),
@@ -183,6 +197,9 @@ export default [
         help: t(
         help: t(
           'Preventing IP addresses from being stored for new events on all projects'
           'Preventing IP addresses from being stored for new events on all projects'
         ),
         ),
+        'aria-label': t(
+          'Enable to prevent IP addresses from being stored for new events'
+        ),
         confirm: {
         confirm: {
           false: t(
           false: t(
             'Disabling this can have privacy implications for ALL projects, are you sure you want to continue?'
             'Disabling this can have privacy implications for ALL projects, are you sure you want to continue?'

+ 13 - 0
static/app/data/forms/projectSecurityAndPrivacyGroups.tsx

@@ -66,6 +66,7 @@ export default [
         disabled: hasOrgOverride,
         disabled: hasOrgOverride,
         disabledReason: ORG_DISABLED_REASON,
         disabledReason: ORG_DISABLED_REASON,
         help: t('Enable server-side data scrubbing'),
         help: t('Enable server-side data scrubbing'),
+        'aria-label': t('Enable server-side data scrubbing'),
         // `props` are the props given to FormField
         // `props` are the props given to FormField
         setValue: (val, props) =>
         setValue: (val, props) =>
           (props.organization && props.organization[props.name]) || val,
           (props.organization && props.organization[props.name]) || val,
@@ -82,6 +83,9 @@ export default [
         help: t(
         help: t(
           'Apply default scrubbers to prevent things like passwords and credit cards from being stored'
           'Apply default scrubbers to prevent things like passwords and credit cards from being stored'
         ),
         ),
+        'aria-label': t(
+          'Enable to apply default scrubbers to prevent things like passwords and credit cards from being stored'
+        ),
         // `props` are the props given to FormField
         // `props` are the props given to FormField
         setValue: (val, props) =>
         setValue: (val, props) =>
           (props.organization && props.organization[props.name]) || val,
           (props.organization && props.organization[props.name]) || val,
@@ -99,6 +103,9 @@ export default [
           (props.organization && props.organization[props.name]) || val,
           (props.organization && props.organization[props.name]) || val,
         label: t('Prevent Storing of IP Addresses'),
         label: t('Prevent Storing of IP Addresses'),
         help: t('Preventing IP addresses from being stored for new events'),
         help: t('Preventing IP addresses from being stored for new events'),
+        'aria-label': t(
+          'Enable to prevent IP addresses from being stored for new events'
+        ),
         confirm: {
         confirm: {
           false: t('Are you sure you want to disable scrubbing IP addresses?'),
           false: t('Are you sure you want to disable scrubbing IP addresses?'),
         },
         },
@@ -115,6 +122,9 @@ export default [
         help: t(
         help: t(
           'Additional field names to match against when scrubbing data. Separate multiple entries with a newline'
           'Additional field names to match against when scrubbing data. Separate multiple entries with a newline'
         ),
         ),
+        'aria-label': t(
+          'Enter additional field names to match against when scrubbing data. Separate multiple entries with a newline'
+        ),
         getValue: val => extractMultilineFields(val),
         getValue: val => extractMultilineFields(val),
         setValue: val => convertMultilineFieldValue(val),
         setValue: val => convertMultilineFieldValue(val),
       },
       },
@@ -130,6 +140,9 @@ export default [
         help: t(
         help: t(
           'Field names which data scrubbers should ignore. Separate multiple entries with a newline'
           'Field names which data scrubbers should ignore. Separate multiple entries with a newline'
         ),
         ),
+        'aria-label': t(
+          'Enter field names which data scrubbers should ignore. Separate multiple entries with a newline'
+        ),
         getValue: val => extractMultilineFields(val),
         getValue: val => extractMultilineFields(val),
         setValue: val => convertMultilineFieldValue(val),
         setValue: val => convertMultilineFieldValue(val),
       },
       },

+ 27 - 12
static/app/routes.tsx

@@ -413,11 +413,19 @@ function buildRoutes() {
         name={t('Data Forwarding')}
         name={t('Data Forwarding')}
         component={make(() => import('sentry/views/settings/projectDataForwarding'))}
         component={make(() => import('sentry/views/settings/projectDataForwarding'))}
       />
       />
-      <Route
-        path="security-and-privacy/"
-        name={t('Security & Privacy')}
-        component={make(() => import('sentry/views/settings/projectSecurityAndPrivacy'))}
-      />
+      <Route path="security-and-privacy/" name={t('Security & Privacy')}>
+        <IndexRoute
+          component={make(
+            () => import('sentry/views/settings/projectSecurityAndPrivacy')
+          )}
+        />
+        <Route
+          path="advanced-data-scrubbing/:scrubbingId/"
+          component={make(
+            () => import('sentry/views/settings/projectSecurityAndPrivacy')
+          )}
+        />
+      </Route>
       <Route
       <Route
         path="debug-symbols/"
         path="debug-symbols/"
         name={t('Debug Information Files')}
         name={t('Debug Information Files')}
@@ -658,13 +666,20 @@ function buildRoutes() {
           () => import('sentry/views/settings/organizationGeneralSettings')
           () => import('sentry/views/settings/organizationGeneralSettings')
         )}
         )}
       />
       />
-      <Route
-        path="security-and-privacy/"
-        name={t('Security & Privacy')}
-        component={make(
-          () => import('sentry/views/settings/organizationSecurityAndPrivacy')
-        )}
-      />
+      <Route path="security-and-privacy/" name={t('Security & Privacy')}>
+        <IndexRoute
+          component={make(
+            () => import('sentry/views/settings/organizationSecurityAndPrivacy')
+          )}
+        />
+        <Route
+          path="advanced-data-scrubbing/:scrubbingId/"
+          component={make(
+            () => import('sentry/views/settings/organizationSecurityAndPrivacy')
+          )}
+        />
+      </Route>
+
       <Route name={t('Teams')} path="teams/">
       <Route name={t('Teams')} path="teams/">
         <IndexRoute
         <IndexRoute
           component={make(() => import('sentry/views/settings/organizationTeams'))}
           component={make(() => import('sentry/views/settings/organizationTeams'))}

+ 2 - 2
static/app/utils.tsx

@@ -231,7 +231,7 @@ export function parseRepo<T>(repo: T): T {
  * Converts a multi-line textarea input value into an array,
  * Converts a multi-line textarea input value into an array,
  * eliminating empty lines
  * eliminating empty lines
  */
  */
-export function extractMultilineFields(value: string): Array<string> {
+export function extractMultilineFields(value: string): string[] {
   return value
   return value
     .split('\n')
     .split('\n')
     .map(f => trim(f))
     .map(f => trim(f))
@@ -241,7 +241,7 @@ export function extractMultilineFields(value: string): Array<string> {
 /**
 /**
  * If the value is of type Array, converts it to type string, keeping the line breaks, if there is any
  * If the value is of type Array, converts it to type string, keeping the line breaks, if there is any
  */
  */
-export function convertMultilineFieldValue<T extends string | Array<string>>(
+export function convertMultilineFieldValue<T extends string | string[]>(
   value: T
   value: T
 ): string {
 ): string {
   if (Array.isArray(value)) {
   if (Array.isArray(value)) {

+ 0 - 26
static/app/views/settings/components/dataScrubbing/content.spec.tsx

@@ -1,26 +0,0 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
-
-import Content from 'sentry/views/settings/components/dataScrubbing/content';
-import {convertRelayPiiConfig} from 'sentry/views/settings/components/dataScrubbing/convertRelayPiiConfig';
-
-describe('Content', function () {
-  it('default empty', function () {
-    render(<Content rules={[]} onEditRule={jest.fn()} onDeleteRule={jest.fn()} />);
-
-    expect(screen.getByText('You have no data scrubbing rules')).toBeInTheDocument();
-  });
-
-  it('render rules', function () {
-    render(
-      <Content
-        rules={convertRelayPiiConfig(
-          JSON.stringify(TestStubs.DataScrubbingRelayPiiConfig())
-        )}
-        onEditRule={jest.fn()}
-        onDeleteRule={jest.fn()}
-      />
-    );
-
-    expect(screen.getAllByRole('button', {name: 'Edit Rule'})).toHaveLength(3);
-  });
-});

+ 0 - 35
static/app/views/settings/components/dataScrubbing/content.tsx

@@ -1,35 +0,0 @@
-import EmptyMessage from 'sentry/components/emptyMessage';
-import {IconWarning} from 'sentry/icons';
-import {t} from 'sentry/locale';
-
-import Rules from './rules';
-import {Rule} from './types';
-
-type Props = {
-  onDeleteRule: (rule: Rule['id']) => () => void;
-  onEditRule: (rule: Rule['id']) => () => void;
-  rules: Array<Rule>;
-  disabled?: boolean;
-};
-
-const Content = ({rules, disabled, onDeleteRule, onEditRule}: Props) => {
-  if (rules.length === 0) {
-    return (
-      <EmptyMessage
-        icon={<IconWarning size="xl" />}
-        description={t('You have no data scrubbing rules')}
-      />
-    );
-  }
-
-  return (
-    <Rules
-      rules={rules}
-      onDeleteRule={onDeleteRule}
-      onEditRule={onEditRule}
-      disabled={disabled}
-    />
-  );
-};
-
-export default Content;

Некоторые файлы не были показаны из-за большого количества измененных файлов