Prevent eth accounts to be selected for derivation (#595)

* prevent eth accounts to be selected

* stray log

* use type && [ed25519, sr25519, ecdsa].includes(type)

* use utils

* fix test

* proper testing for eth

* fix derive test (will change these soon anyway)
This commit is contained in:
Thibaut Sardan 2020-12-18 15:18:06 +01:00 committed by GitHub
parent 3d0b4985e5
commit 57635016a6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 13 deletions

View File

@ -9,6 +9,7 @@ import type { SubjectInfo } from '@polkadot/ui-keyring/observable/types';
import type { MessageTypes, RequestAccountList, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestTypes, ResponseRpcListProviders, ResponseSigning, ResponseTypes, SubscriptionMessageTypes } from '../types';
import { PHISHING_PAGE_REDIRECT } from '@polkadot/extension-base/defaults';
import { canDerive } from '@polkadot/extension-base/utils';
import { checkIfDenied } from '@polkadot/phishing';
import keyring from '@polkadot/ui-keyring';
import { accounts as accountsObservable } from '@polkadot/ui-keyring/observable/accounts';
@ -23,7 +24,7 @@ function transformAccounts (accounts: SubjectInfo, anyType = false): InjectedAcc
return Object
.values(accounts)
.filter(({ json: { meta: { isHidden } } }) => !isHidden)
.filter(({ type }) => anyType ? true : type && ['ed25519', 'sr25519', 'ecdsa'].includes(type))
.filter(({ type }) => anyType ? true : canDerive(type))
.sort((a, b) => (a.json.meta.whenCreated || 0) - (b.json.meta.whenCreated || 0))
.map(({ json: { address, meta: { genesisHash, name } }, type }): InjectedAccount => ({
address,

View File

@ -0,0 +1,8 @@
// Copyright 2019-2020 @polkadot/extension authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { KeypairType } from '@polkadot/util-crypto/types';
export default function canDerive (type?: KeypairType): boolean {
return !!type && ['ed25519', 'sr25519', 'ecdsa'].includes(type);
}

View File

@ -0,0 +1,4 @@
// Copyright 2019-2020 @polkadot/extension authors & contributors
// SPDX-License-Identifier: Apache-2.0
export { default as canDerive } from './canDerive';

View File

@ -30,7 +30,7 @@ describe('Account component', () => {
</MemoryRouter>);
it('shows Export option if account is not external', () => {
wrapper = mountAccountComponent({ isExternal: false });
wrapper = mountAccountComponent({ isExternal: false, type: 'ed25519' });
wrapper.find('.settings').first().simulate('click');
expect(wrapper.find('a.menuItem').length).toBe(4);
@ -41,11 +41,21 @@ describe('Account component', () => {
});
it('does not show Export option if account is external', () => {
wrapper = mountAccountComponent({ isExternal: true });
wrapper = mountAccountComponent({ isExternal: true, type: 'ed25519' });
wrapper.find('.settings').first().simulate('click');
expect(wrapper.find('a.menuItem').length).toBe(2);
expect(wrapper.find('a.menuItem').at(0).text()).toBe('Rename');
expect(wrapper.find('a.menuItem').at(1).text()).toBe('Forget Account');
});
it('does not show Derive option if account is of ethereum type', () => {
wrapper = mountAccountComponent({ isExternal: false, type: 'ethereum' });
wrapper.find('.settings').first().simulate('click');
expect(wrapper.find('a.menuItem').length).toBe(3);
expect(wrapper.find('a.menuItem').at(0).text()).toBe('Rename');
expect(wrapper.find('a.menuItem').at(1).text()).toBe('Export Account');
expect(wrapper.find('a.menuItem').at(2).text()).toBe('Forget Account');
});
});

View File

@ -6,6 +6,7 @@ import type { AccountJson } from '@polkadot/extension-base/background/types';
import React, { useCallback, useContext, useMemo, useState } from 'react';
import styled from 'styled-components';
import { canDerive } from '@polkadot/extension-base/utils';
import genesisOptions from '@polkadot/extension-chains/genesisHashes';
import { ActionContext, Address, Dropdown, Link, MenuDivider } from '../../components';
@ -62,7 +63,7 @@ function Account ({ address, className, genesisHash, isExternal, isHidden, paren
>
{t<string>('Rename')}
</Link>
{!isExternal && type !== 'ethereum' && (
{!isExternal && canDerive(type) && (
<Link
className='menuItem'
to={`/account/derive/${address}/locked`}

View File

@ -3,7 +3,7 @@
import '../../../../../__mocks__/chrome';
import type { ResponseDeriveValidate } from '@polkadot/extension-base/background/types';
import type { AccountJson, ResponseDeriveValidate } from '@polkadot/extension-base/background/types';
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
import { configure, mount, ReactWrapper } from 'enzyme';
@ -23,13 +23,13 @@ import Derive from '.';
configure({ adapter: new Adapter() });
const accounts = [
{ address: '5FjgD3Ns2UpnHJPVeRViMhCttuemaRXEqaD8V5z4vxcsUByA', name: 'A' },
{ address: '5GYmFzQCuC5u3tQNiMZNbFGakrz3Jq31NmMg4D2QAkSoQ2g5', name: 'B' },
{ address: '5D2TPhGEy2FhznvzaNYW9AkuMBbg3cyRemnPsBvBY4ZhkZXA', name: 'BB', parentAddress: '5GYmFzQCuC5u3tQNiMZNbFGakrz3Jq31NmMg4D2QAkSoQ2g5' },
{ address: '5GhGENSJBWQZ8d8mARKgqEkiAxiW3hHeznQDW2iG4XzNieb6', isExternal: true, name: 'C' },
{ address: '5EeaoDj4VDk8V6yQngKBaCD5MpJUCHrhYjVhBjgMHXoYon1s', isExternal: false, name: 'D' },
{ address: '5HRKYp5anSNGtqC7cq9ftiaq4y8Mk7uHk7keaXUrQwZqDWLJ', name: 'DD', parentAddress: '5EeaoDj4VDk8V6yQngKBaCD5MpJUCHrhYjVhBjgMHXoYon1s' }
];
{ address: '5FjgD3Ns2UpnHJPVeRViMhCttuemaRXEqaD8V5z4vxcsUByA', name: 'A', type: 'sr25519' },
{ address: '5GYmFzQCuC5u3tQNiMZNbFGakrz3Jq31NmMg4D2QAkSoQ2g5', name: 'B', type: 'sr25519' },
{ address: '5D2TPhGEy2FhznvzaNYW9AkuMBbg3cyRemnPsBvBY4ZhkZXA', name: 'BB', parentAddress: '5GYmFzQCuC5u3tQNiMZNbFGakrz3Jq31NmMg4D2QAkSoQ2g5', type: 'sr25519' },
{ address: '5GhGENSJBWQZ8d8mARKgqEkiAxiW3hHeznQDW2iG4XzNieb6', isExternal: true, name: 'C', type: 'sr25519' },
{ address: '5EeaoDj4VDk8V6yQngKBaCD5MpJUCHrhYjVhBjgMHXoYon1s', isExternal: false, name: 'D', type: 'sr25519' },
{ address: '5HRKYp5anSNGtqC7cq9ftiaq4y8Mk7uHk7keaXUrQwZqDWLJ', name: 'DD', parentAddress: '5EeaoDj4VDk8V6yQngKBaCD5MpJUCHrhYjVhBjgMHXoYon1s', type: 'sr25519' }
] as AccountJson[];
describe('Derive', () => {
const mountComponent = async (locked = false): Promise<{

View File

@ -6,6 +6,7 @@ import type { ThemeProps } from '../../types';
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import styled from 'styled-components';
import { canDerive } from '@polkadot/extension-base/utils';
import { assert } from '@polkadot/util';
import { AccountContext, ActionContext, Address, ButtonArea, Checkbox, InputWithLabel, Label, NextStepButton, VerticalSpace, Warning } from '../../components';
@ -38,6 +39,7 @@ function SelectParent ({ className, isLocked, onDerivationConfirmed, parentAddre
const allAddresses = useMemo(
() => hierarchy
.filter(({ isExternal }) => !isExternal)
.filter(({ type }) => canDerive(type))
.map(({ address, genesisHash }): [string, string | null] => [address, genesisHash || null]),
[hierarchy]
);

View File

@ -8,6 +8,7 @@ import React, { useEffect, useState } from 'react';
import { Route, Switch } from 'react-router';
import { PHISHING_PAGE_REDIRECT } from '@polkadot/extension-base/defaults';
import { canDerive } from '@polkadot/extension-base/utils';
import uiSettings from '@polkadot/ui-settings';
import { ErrorBoundary, Loading } from '../components';
@ -51,7 +52,7 @@ async function requestMediaAccess (cameraOn: boolean): Promise<boolean> {
function initAccountContext (accounts: AccountJson[]): AccountsContext {
const hierarchy = buildHierarchy(accounts);
const master = hierarchy.find((account) => !account.isExternal);
const master = hierarchy.find(({ isExternal, type }) => !isExternal && canDerive(type));
return {
accounts,