Skip to content

Commit

Permalink
Add Blockaid / PPOM Failed Request Security Alert (#20362)
Browse files Browse the repository at this point in the history
* WIP blockaid: add request failed UI
- proposed to update reason value. planning to update upon update

* alphabetize

* BlockaidBannerAlert: update tkeys based on reason

* SecurityProviderBannerAlert: fix footer alignment

* BlockaidBannerAlert: rm footer w failed resultType

---------

Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>
Co-authored-by: Jyoti Puri <jyotipuri@gmail.com>
  • Loading branch information
3 people authored Aug 14, 2023
1 parent e9fbf85 commit 136ede5
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 57 deletions.
6 changes: 6 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion shared/constants/security-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export enum BlockaidReason {
other = 'other',

// Locally defined
notApplicable = 'NotApplicable',
failed = 'Failed',
notApplicable = 'NotApplicable',
}

export enum BlockaidResultType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ exports[`Security Provider Banner Alert should match snapshot 1`] = `
</details>
</div>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ exports[`Blockaid Banner Alert should render 'danger' UI when securityAlertRespo
If you approve this request, a third party known for scams might take all your assets.
</p>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"
Expand All @@ -46,6 +46,30 @@ exports[`Blockaid Banner Alert should render 'danger' UI when securityAlertRespo
</div>
`;

exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResponse.result_type is 'Failed 1`] = `
<div
class="box mm-banner-base mm-banner-alert mm-banner-alert--severity-warning box--margin-4 box--padding-3 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--background-color-warning-muted box--rounded-sm"
>
<span
class="mm-box mm-icon mm-icon--size-lg mm-box--display-inline-block mm-box--color-warning-default"
style="mask-image: url('./images/icons/warning.svg');"
/>
<div>
<h5
class="mm-box mm-text mm-banner-base__title mm-text--body-lg-medium mm-box--color-text-default"
data-testid="mm-banner-base-title"
>
This is a deceptive request
</h5>
<p
class="mm-box mm-text mm-text--body-md mm-box--margin-top-2 mm-box--color-text-default"
>
If you approve this request, a third party known for scams might take all your assets.
</p>
</div>
</div>
`;

exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResponse.result_type is 'Warning 1`] = `
<div
class="box mm-banner-base mm-banner-alert mm-banner-alert--severity-warning box--margin-4 box--padding-3 box--padding-left-2 box--display-flex box--gap-2 box--flex-direction-row box--background-color-warning-muted box--rounded-sm"
Expand All @@ -67,7 +91,7 @@ exports[`Blockaid Banner Alert should render 'warning' UI when securityAlertResp
If you approve this request, a third party known for scams might take all your assets.
</p>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"
Expand Down Expand Up @@ -152,7 +176,7 @@ exports[`Blockaid Banner Alert should render details when provided 1`] = `
</details>
</div>
<p
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-2 mm-box--align-items-center mm-box--color-text-alternative"
class="mm-box mm-text mm-text--body-sm mm-box--margin-top-3 mm-box--display-flex mm-box--align-items-center mm-box--color-text-alternative"
>
<span
class="mm-box disclosure__summary--icon mm-icon mm-icon--size-sm mm-box--margin-inline-end-1 mm-box--display-inline-block mm-box--color-primary-default"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const REASON_TO_DESCRIPTION_TKEY = Object.freeze({

[BlockaidReason.blurFarming]: 'blockaidDescriptionBlurFarming',

[BlockaidReason.failed]: 'blockaidDescriptionFailed',

[BlockaidReason.seaportFarming]: 'blockaidDescriptionSeaportFarming',

[BlockaidReason.maliciousDomain]: 'blockaidDescriptionMaliciousDomain',
Expand All @@ -36,8 +38,11 @@ const REASON_TO_DESCRIPTION_TKEY = Object.freeze({
[BlockaidReason.other]: 'blockaidDescriptionMightLoseAssets',
});

/** List of suspicious reason(s). Other reasons will be deemed as deceptive. */
const SUSPCIOUS_REASON = [BlockaidReason.rawSignatureFarming];
/** Reason to title translation key mapping. */
const REASON_TO_TITLE_TKEY = Object.freeze({
[BlockaidReason.failed]: 'blockaidTitleMayNotBeSafe',
[BlockaidReason.rawSignatureFarming]: 'blockaidTitleSuspicious',
});

function BlockaidBannerAlert({ securityAlertResponse }) {
const t = useContext(I18nContext);
Expand All @@ -48,10 +53,7 @@ function BlockaidBannerAlert({ securityAlertResponse }) {

const { reason, result_type: resultType, features } = securityAlertResponse;

if (
resultType === BlockaidResultType.Benign ||
resultType === BlockaidResultType.Failed
) {
if (resultType === BlockaidResultType.Benign) {
return null;
}

Expand All @@ -69,21 +71,20 @@ function BlockaidBannerAlert({ securityAlertResponse }) {
</Text>
);

const isFailedResultType = resultType === BlockaidResultType.Failed;

const severity =
resultType === BlockaidResultType.Malicious
? Severity.Danger
: Severity.Warning;

const title =
SUSPCIOUS_REASON.indexOf(reason) > -1
? t('blockaidTitleSuspicious')
: t('blockaidTitleDeceptive');
const title = t(REASON_TO_TITLE_TKEY[reason] || 'blockaidTitleDeceptive');

return (
<SecurityProviderBannerAlert
description={description}
details={details}
provider={SecurityProvider.Blockaid}
provider={isFailedResultType ? null : SecurityProvider.Blockaid}
severity={severity}
title={title}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ describe('Blockaid Banner Alert', () => {
expect(container.querySelector('.mm-banner-alert')).toBeNull();
});

it(`should not render when securityAlertResponse.result_type is '${BlockaidResultType.Failed}'`, () => {
it(`should render '${Severity.Warning}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Failed}`, () => {
const { container } = renderWithLocalization(
<BlockaidBannerAlert
securityAlertResponse={{
Expand All @@ -49,8 +49,24 @@ describe('Blockaid Banner Alert', () => {
}}
/>,
);
const warningBannerAlert = container.querySelector(
'.mm-banner-alert--severity-warning',
);

expect(container.querySelector('.mm-banner-alert')).toBeNull();
expect(warningBannerAlert).toBeInTheDocument();
expect(warningBannerAlert).toMatchSnapshot();
});

it(`should render '${Severity.Warning}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Warning}`, () => {
const { container } = renderWithLocalization(
<BlockaidBannerAlert securityAlertResponse={mockSecurityAlertResponse} />,
);
const warningBannerAlert = container.querySelector(
'.mm-banner-alert--severity-warning',
);

expect(warningBannerAlert).toBeInTheDocument();
expect(warningBannerAlert).toMatchSnapshot();
});

it(`should render '${Severity.Danger}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Malicious}`, () => {
Expand All @@ -70,27 +86,28 @@ describe('Blockaid Banner Alert', () => {
expect(dangerBannerAlert).toMatchSnapshot();
});

it(`should render '${Severity.Warning}' UI when securityAlertResponse.result_type is '${BlockaidResultType.Warning}`, () => {
const { container } = renderWithLocalization(
it('should render title, "This is a deceptive request"', () => {
const { getByText } = renderWithLocalization(
<BlockaidBannerAlert securityAlertResponse={mockSecurityAlertResponse} />,
);
const warningBannerAlert = container.querySelector(
'.mm-banner-alert--severity-warning',
);

expect(warningBannerAlert).toBeInTheDocument();
expect(warningBannerAlert).toMatchSnapshot();
expect(getByText('This is a deceptive request')).toBeInTheDocument();
});

it('should render title, "This is a deceptive request"', () => {
it(`should render title, "This is a suspicious request", when the reason is "${BlockaidReason.failed}"`, () => {
const { getByText } = renderWithLocalization(
<BlockaidBannerAlert securityAlertResponse={mockSecurityAlertResponse} />,
<BlockaidBannerAlert
securityAlertResponse={{
...mockSecurityAlertResponse,
reason: BlockaidReason.failed,
}}
/>,
);

expect(getByText('This is a deceptive request')).toBeInTheDocument();
expect(getByText('Request may not be safe')).toBeInTheDocument();
});

it('should render title, "This is a suspicious request", when the reason is "raw_signature_farming"', () => {
it(`should render title, "This is a suspicious request", when the reason is "${BlockaidReason.rawSignatureFarming}"`, () => {
const { getByText } = renderWithLocalization(
<BlockaidBannerAlert
securityAlertResponse={{
Expand Down Expand Up @@ -131,6 +148,8 @@ describe('Blockaid Banner Alert', () => {
'If you approve this request, a third party known for scams might take all your assets.',
[BlockaidReason.blurFarming]:
'If you approve this request, someone can steal your assets listed on Blur.',
[BlockaidReason.failed]:
'Because of an error, this request was not verified by the security provider. Proceed with caution.',
[BlockaidReason.maliciousDomain]:
"You're interacting with a malicious domain. If you approve this request, you might lose your assets.",
[BlockaidReason.other]:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { I18nContext } from '../../../contexts/i18n';
import {
AlignItems,
Color,
Display,
IconColor,
Severity,
Size,
Expand Down Expand Up @@ -45,30 +46,33 @@ function SecurityProviderBannerAlert({
</Disclosure>
)}

<Text
marginTop={2}
alignItems={AlignItems.center}
color={Color.textAlternative}
variant={TextVariant.bodySm}
>
<Icon
className="disclosure__summary--icon"
color={IconColor.primaryDefault}
name={IconName.SecurityTick}
size={IconSize.Sm}
marginInlineEnd={1}
/>
{t('securityProviderAdviceBy', [
<ButtonLink
key={`security-provider-button-link-${provider}`}
size={Size.inherit}
href={SECURITY_PROVIDER_CONFIG[provider].url}
externalLink
>
{t(SECURITY_PROVIDER_CONFIG[provider].tKeyName)}
</ButtonLink>,
])}
</Text>
{provider && (
<Text
marginTop={3}
display={Display.Flex}
alignItems={AlignItems.center}
color={Color.textAlternative}
variant={TextVariant.bodySm}
>
<Icon
className="disclosure__summary--icon"
color={IconColor.primaryDefault}
name={IconName.SecurityTick}
size={IconSize.Sm}
marginInlineEnd={1}
/>
{t('securityProviderAdviceBy', [
<ButtonLink
key={`security-provider-button-link-${provider}`}
size={Size.inherit}
href={SECURITY_PROVIDER_CONFIG[provider].url}
externalLink
>
{t(SECURITY_PROVIDER_CONFIG[provider].tKeyName)}
</ButtonLink>,
])}
</Text>
)}
</BannerAlert>
);
}
Expand All @@ -78,9 +82,6 @@ SecurityProviderBannerAlert.propTypes = {
description: PropTypes.oneOfType([PropTypes.string, PropTypes.element])
.isRequired,

/** Name of the security provider */
provider: PropTypes.oneOfType(Object.values(SecurityProvider)).isRequired,

/** Severity level */
severity: PropTypes.oneOfType([Severity.Danger, Severity.Warning]).isRequired,

Expand All @@ -93,6 +94,9 @@ SecurityProviderBannerAlert.propTypes = {

/** Additional details to be displayed under the description */
details: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),

/** Name of the security provider */
provider: PropTypes.oneOfType(Object.values(SecurityProvider)),
};

export default SecurityProviderBannerAlert;
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ export default {
control: {
type: 'select',
},
options: [Object.values(SecurityProvider)],
options: ['none', ...Object.values(SecurityProvider)],
mapping: {
none: null,
},
},
severity: {
control: {
Expand Down

0 comments on commit 136ede5

Please sign in to comment.