mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 01:39:44 +01:00
Replace ActionableMessage components with BannerAlerts in SIWE Sign-in with Ethereum page (#18207)
* siwe: re-enable warning UI for mismatched domains - unblocks mismatched domain support - we may re-add error handling here #18184 - reverts logic from #16616 * siwe: fix mismatch domain warning msg UI * lint: rm whitespace EOL * siwe: rm unit test * lint: fix whitespace * Icon: support .mm-icon - apply to SIWE actionable-message - .mm-icon is a <span> * lint: fix newline * Revert "siwe: rm unit test" This reverts commit c80a4a2e661609c46c76d1e43e05909b6db3f0f5. * ActionableMessage: add deprecation * siwe: replace actionable-msg w/ banner-alert * ActionableMessage: add param for lint * revert .mm_icon ActionableMessage support * siwe: create tests * siwe: fix typo in tests * siwe: fix - do not allow nested <p> elements * Update ui/components/app/signature-request-siwe/signature-request-siwe.js Co-authored-by: George Marshall <george.marshall@consensys.net> * Update ui/components/app/signature-request-siwe/signature-request-siwe.js Co-authored-by: George Marshall <george.marshall@consensys.net> * eslint fix --------- Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com> Co-authored-by: George Marshall <george.marshall@consensys.net>
This commit is contained in:
parent
a04fa20f96
commit
5e3770eb13
@ -0,0 +1,245 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`SignatureRequestSIWE (Sign in with Ethereum) should match snapshot 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="signature-request-siwe"
|
||||
>
|
||||
<div
|
||||
class="signature-request-siwe-header"
|
||||
>
|
||||
<div
|
||||
class="box permissions-connect-header box--flex-direction-column box--justify-content-center box--display-flex"
|
||||
>
|
||||
<div
|
||||
class="permissions-connect-header__icon"
|
||||
>
|
||||
<div
|
||||
class="site-origin"
|
||||
>
|
||||
<div
|
||||
class="chip chip--with-left-icon chip--border-color-border-muted chip--background-color-undefined"
|
||||
>
|
||||
<div
|
||||
class="chip__left-icon"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<img
|
||||
alt="icon"
|
||||
src="https://example-dapp.website/favicon-32x32.png"
|
||||
style="height: 24px; width: 24px;"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
class="box box--margin-top-1 box--margin-bottom-1 box--flex-direction-row typography chip__label typography--h6 typography--weight-normal typography--style-normal typography--color-text-alternative"
|
||||
>
|
||||
https://example-dapp.website
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="permissions-connect-header__title"
|
||||
>
|
||||
Sign-in request
|
||||
</div>
|
||||
<div
|
||||
class="permissions-connect-header__subtitle"
|
||||
>
|
||||
This site is requesting to sign in with
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="account-list-item signature-request-siwe-header__account-list-item"
|
||||
data-testid="account-list-item"
|
||||
>
|
||||
<div
|
||||
class="account-list-item__top-row"
|
||||
>
|
||||
<div
|
||||
class=""
|
||||
>
|
||||
<div
|
||||
class="identicon account-list-item__identicon"
|
||||
style="height: 18px; width: 18px; border-radius: 9px;"
|
||||
>
|
||||
<div
|
||||
style="border-radius: 50px; overflow: hidden; padding: 0px; margin: 0px; width: 18px; height: 18px; display: inline-block; background: rgb(250, 58, 0);"
|
||||
>
|
||||
<svg
|
||||
height="18"
|
||||
width="18"
|
||||
x="0"
|
||||
y="0"
|
||||
>
|
||||
<rect
|
||||
fill="#18CDF2"
|
||||
height="18"
|
||||
transform="translate(-0.5897213458840913 -1.8586597890715306) rotate(328.9 9 9)"
|
||||
width="18"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#035E56"
|
||||
height="18"
|
||||
transform="translate(-10.292884711218024 5.9582598028585885) rotate(176.2 9 9)"
|
||||
width="18"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
<rect
|
||||
fill="#F26602"
|
||||
height="18"
|
||||
transform="translate(9.375661135250958 -7.990391094185859) rotate(468.9 9 9)"
|
||||
width="18"
|
||||
x="0"
|
||||
y="0"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="account-list-item__account-name"
|
||||
>
|
||||
Test Account
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box signature-request-siwe-message box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="box box--flex-direction-column"
|
||||
>
|
||||
<div
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Message:
|
||||
</h4>
|
||||
<h6
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography signature-request-siwe-message__sub-text typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Click to sign in and accept the Terms of Service: https://community.metamask.io/tos
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
URI:
|
||||
</h4>
|
||||
<h6
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography signature-request-siwe-message__sub-text typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
http://localhost:8080
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Version:
|
||||
</h4>
|
||||
<h6
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography signature-request-siwe-message__sub-text typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
1
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Chain ID:
|
||||
</h4>
|
||||
<h6
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography signature-request-siwe-message__sub-text typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
1
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Nonce:
|
||||
</h4>
|
||||
<h6
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography signature-request-siwe-message__sub-text typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
STMt6KQMwwdOXE306
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Issued At:
|
||||
</h4>
|
||||
<h6
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography signature-request-siwe-message__sub-text typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
2023-03-18T21:40:40.823Z
|
||||
</h6>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row"
|
||||
>
|
||||
<h4
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography typography--h4 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
Resources: 2
|
||||
</h4>
|
||||
<h6
|
||||
class="box box--margin-top-2 box--margin-bottom-2 box--flex-direction-row typography signature-request-siwe-message__sub-text typography--h6 typography--weight-normal typography--style-normal typography--color-text-default"
|
||||
>
|
||||
ipfs://Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu
|
||||
https://example.com/my-web2-claim.json
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="page-container__footer signature-request-siwe__page-container-footer"
|
||||
>
|
||||
<footer>
|
||||
<button
|
||||
class="button btn--rounded btn-secondary page-container__footer-button page-container__footer-button__cancel"
|
||||
data-testid="page-container-footer-cancel"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary page-container__footer-button"
|
||||
data-testid="page-container-footer-next"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
Sign-In
|
||||
</button>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -20,27 +20,6 @@
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
/** @todo replace ActionableMessage or remove overwritten code. */
|
||||
.signature-request-siwe__actionable-message {
|
||||
margin: 0 16px;
|
||||
flex-direction: row;
|
||||
align-items: initial;
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 17px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.actionable-message__message {
|
||||
padding-left: 16px;
|
||||
}
|
||||
|
||||
&.actionable-message--with-icon {
|
||||
padding-left: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.signature-request-siwe__warning-popover {
|
||||
|
@ -2,7 +2,7 @@ import React, { useCallback, useContext, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import log from 'loglevel';
|
||||
import ActionableMessage from '../../ui/actionable-message';
|
||||
import { BannerAlert, Text } from '../../component-library';
|
||||
import Popover from '../../ui/popover';
|
||||
import Checkbox from '../../ui/check-box';
|
||||
import { I18nContext } from '../../../contexts/i18n';
|
||||
@ -13,8 +13,10 @@ import {
|
||||
} from '../../../selectors';
|
||||
import { getAccountByAddress } from '../../../helpers/utils/util';
|
||||
import { formatMessageParams } from '../../../../shared/modules/siwe';
|
||||
import { Icon } from '../../component-library/icon/icon';
|
||||
import { IconColor } from '../../../helpers/constants/design-system';
|
||||
import {
|
||||
SEVERITIES,
|
||||
TextVariant,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
|
||||
import SecurityProviderBannerMessage from '../security-provider-banner-message/security-provider-banner-message';
|
||||
import { SECURITY_PROVIDER_MESSAGE_SEVERITIES } from '../security-provider-banner-message/security-provider-banner-message.constants';
|
||||
@ -101,38 +103,30 @@ export default function SignatureRequestSIWE({
|
||||
) : null}
|
||||
<Message data={formatMessageParams(parsedMessage, t)} />
|
||||
{!isMatchingAddress && (
|
||||
<ActionableMessage
|
||||
className="signature-request-siwe__actionable-message"
|
||||
type="warning"
|
||||
message={t('SIWEAddressInvalid', [
|
||||
<BannerAlert
|
||||
severity={SEVERITIES.WARNING}
|
||||
marginLeft={4}
|
||||
marginRight={4}
|
||||
marginBottom={4}
|
||||
>
|
||||
{t('SIWEAddressInvalid', [
|
||||
parsedMessage.address,
|
||||
fromAccount.address,
|
||||
])}
|
||||
iconFillColor="var(--color-warning-default)"
|
||||
useIcon
|
||||
withRightButton
|
||||
icon={<Icon name="danger" color={IconColor.warningDefault} />}
|
||||
/>
|
||||
</BannerAlert>
|
||||
)}
|
||||
{!isSIWEDomainValid && (
|
||||
<ActionableMessage
|
||||
className="signature-request-siwe__actionable-message"
|
||||
type="danger"
|
||||
message={
|
||||
<>
|
||||
<p
|
||||
className="typography--weight-bold"
|
||||
style={{ display: 'inline' }}
|
||||
>
|
||||
{t('SIWEDomainInvalidTitle')}
|
||||
</p>{' '}
|
||||
{t('SIWEDomainInvalidText')}
|
||||
</>
|
||||
}
|
||||
iconFillColor="var(--color-error-default)"
|
||||
useIcon
|
||||
icon={<Icon name="danger" color={IconColor.errorDefault} />}
|
||||
/>
|
||||
<BannerAlert
|
||||
severity={SEVERITIES.DANGER}
|
||||
marginLeft={4}
|
||||
marginRight={4}
|
||||
marginBottom={4}
|
||||
>
|
||||
<Text variant={TextVariant.bodyMdBold}>
|
||||
{t('SIWEDomainInvalidTitle')}
|
||||
</Text>{' '}
|
||||
<Text>{t('SIWEDomainInvalidText')}</Text>
|
||||
</BannerAlert>
|
||||
)}
|
||||
<PageContainerFooter
|
||||
footerClassName="signature-request-siwe__page-container-footer"
|
||||
|
@ -0,0 +1,113 @@
|
||||
import React from 'react';
|
||||
import { cloneDeep } from 'lodash';
|
||||
import { MESSAGE_TYPE } from '../../../../shared/constants/app';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import configureStore from '../../../store/store';
|
||||
import SignatureRequestSIWE from '.';
|
||||
|
||||
const MOCK_ORIGIN = 'https://example-dapp.website';
|
||||
const MOCK_ADDRESS = '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc';
|
||||
|
||||
const mockStoreInitialState = {
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
subjectMetadata: {
|
||||
[MOCK_ORIGIN]: {
|
||||
iconUrl: 'https://example-dapp.website/favicon-32x32.png',
|
||||
name: 'Example Test Dapp',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockProps = {
|
||||
cancelPersonalMessage: jest.fn(),
|
||||
signPersonalMessage: jest.fn(),
|
||||
txData: {
|
||||
msgParams: {
|
||||
from: MOCK_ADDRESS,
|
||||
data: '0x6c6f63616c686f73743a383038302077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078466232433135303034333433393034653566343038323537386334653865313131303563463765330a0a436c69636b20746f207369676e20696e20616e642061636365707420746865205465726d73206f6620536572766963653a2068747470733a2f2f636f6d6d756e6974792e6d6574616d61736b2e696f2f746f730a0a5552493a20687474703a2f2f6c6f63616c686f73743a383038300a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a2053544d74364b514d7777644f58453330360a4973737565642041743a20323032322d30332d31385432313a34303a34302e3832335a0a5265736f75726365733a0a2d20697066733a2f2f516d653773733341525667787636725871565069696b4d4a3875324e4c676d67737a673133705972444b456f69750a2d2068747470733a2f2f6578616d706c652e636f6d2f6d792d776562322d636c61696d2e6a736f6e',
|
||||
origin: MOCK_ORIGIN,
|
||||
siwe: {
|
||||
isSIWEMessage: true,
|
||||
parsedMessage: {
|
||||
domain: 'example-dapp.website',
|
||||
address: MOCK_ADDRESS,
|
||||
statement:
|
||||
'Click to sign in and accept the Terms of Service: https://community.metamask.io/tos',
|
||||
uri: 'http://localhost:8080',
|
||||
version: '1',
|
||||
nonce: 'STMt6KQMwwdOXE306',
|
||||
chainId: 1,
|
||||
issuedAt: '2023-03-18T21:40:40.823Z',
|
||||
resources: [
|
||||
'ipfs://Qme7ss3ARVgxv6rXqVPiikMJ8u2NLgmgszg13pYrDKEoiu',
|
||||
'https://example.com/my-web2-claim.json',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
type: MESSAGE_TYPE.PERSONAL_SIGN,
|
||||
},
|
||||
};
|
||||
|
||||
const render = (txData = mockProps.txData) => {
|
||||
const store = configureStore(mockStoreInitialState);
|
||||
|
||||
return renderWithProvider(
|
||||
<SignatureRequestSIWE {...mockProps} txData={txData} />,
|
||||
store,
|
||||
);
|
||||
};
|
||||
|
||||
describe('SignatureRequestSIWE (Sign in with Ethereum)', () => {
|
||||
it('should match snapshot', () => {
|
||||
const { container } = render();
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('should render', async () => {
|
||||
const { container, findByText } = render();
|
||||
const bannerAlert = container.querySelector('.mm-banner-alert');
|
||||
|
||||
expect(bannerAlert).not.toBeTruthy();
|
||||
expect(await findByText('Sign-in request')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render SiteOrigin', () => {
|
||||
const { container } = render();
|
||||
const siteOriginElem = container.querySelector('.site-origin');
|
||||
expect(siteOriginElem).toHaveTextContent(MOCK_ORIGIN);
|
||||
});
|
||||
|
||||
it('should render BannerAlert when addresses do not match', () => {
|
||||
const store = configureStore(mockStoreInitialState);
|
||||
const txData = cloneDeep(mockProps.txData);
|
||||
txData.msgParams.siwe.parsedMessage.address = '0x12345';
|
||||
|
||||
const { container } = renderWithProvider(
|
||||
<SignatureRequestSIWE {...mockProps} txData={txData} />,
|
||||
store,
|
||||
);
|
||||
const bannerAlert = container.querySelector('.mm-banner-alert');
|
||||
|
||||
expect(bannerAlert).toBeTruthy();
|
||||
expect(bannerAlert).toHaveTextContent('does not match the address');
|
||||
});
|
||||
|
||||
it('should render BannerAlert when domains do not match', () => {
|
||||
const store = configureStore(mockStoreInitialState);
|
||||
const txData = cloneDeep(mockProps.txData);
|
||||
txData.msgParams.siwe.parsedMessage.domain = 'potentially-malicious.com';
|
||||
|
||||
const { container } = renderWithProvider(
|
||||
<SignatureRequestSIWE {...mockProps} txData={txData} />,
|
||||
store,
|
||||
);
|
||||
const bannerAlert = container.querySelector('.mm-banner-alert');
|
||||
|
||||
expect(bannerAlert).toBeTruthy();
|
||||
expect(bannerAlert).toHaveTextContent('Deceptive site request.');
|
||||
});
|
||||
});
|
@ -16,6 +16,30 @@ export const typeHash = {
|
||||
default: '',
|
||||
};
|
||||
|
||||
/**
|
||||
* @deprecated `<ActionableMessage />` has been deprecated in favour of the `<BannerAlert />`
|
||||
* component in ./ui/components/component-library/banner-alert/banner-alert.js.
|
||||
* See storybook documentation for Text here:
|
||||
* {@see {@link https://metamask.github.io/metamask-storybook/?path=/docs/components-componentlibrary-banneralert--default-story#banneralert}}
|
||||
*
|
||||
* Help to replace `ActionableMessage` with `BannerAlert` by submitting a PR
|
||||
* @param options
|
||||
* @param options.message
|
||||
* @param options.primaryAction
|
||||
* @param options.primaryActionV2
|
||||
* @param options.secondaryAction
|
||||
* @param options.className
|
||||
* @param options.infoTooltipText
|
||||
* @param options.withRightButton
|
||||
* @param options.type
|
||||
* @param options.useIcon
|
||||
* @param options.icon
|
||||
* @param options.iconFillColor
|
||||
* @param options.roundedButtons
|
||||
* @param options.dataTestId
|
||||
* @param options.autoHideTime
|
||||
* @param options.onAutoHide
|
||||
*/
|
||||
export default function ActionableMessage({
|
||||
message = '',
|
||||
primaryAction = null,
|
||||
|
Loading…
Reference in New Issue
Block a user