Add authorized URL removal (#1029)
* Add authorized URL removal Adds a trashcan icon to the website entries Introduces removeAuth and removeAuthorization functions * Resolves Linting issues
This commit is contained in:
parent
6ff6073d6a
commit
415184ac0d
@ -504,6 +504,10 @@ export default class Extension {
|
|||||||
return { list: this.#state.toggleAuthorization(url) };
|
return { list: this.#state.toggleAuthorization(url) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private removeAuthorization (url: string): ResponseAuthorizeList {
|
||||||
|
return { list: this.#state.removeAuthorization(url) };
|
||||||
|
}
|
||||||
|
|
||||||
// Weird thought, the eslint override is not needed in Tabs
|
// Weird thought, the eslint override is not needed in Tabs
|
||||||
// eslint-disable-next-line @typescript-eslint/require-await
|
// eslint-disable-next-line @typescript-eslint/require-await
|
||||||
public async handle<TMessageType extends MessageTypes> (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseType<TMessageType>> {
|
public async handle<TMessageType extends MessageTypes> (id: string, type: TMessageType, request: RequestTypes[TMessageType], port: chrome.runtime.Port): Promise<ResponseType<TMessageType>> {
|
||||||
@ -520,6 +524,9 @@ export default class Extension {
|
|||||||
case 'pri(authorize.toggle)':
|
case 'pri(authorize.toggle)':
|
||||||
return this.toggleAuthorization(request as string);
|
return this.toggleAuthorization(request as string);
|
||||||
|
|
||||||
|
case 'pri(authorize.remove)':
|
||||||
|
return this.removeAuthorization(request as string);
|
||||||
|
|
||||||
case 'pri(authorize.requests)':
|
case 'pri(authorize.requests)':
|
||||||
return this.authorizeSubscribe(id, port);
|
return this.authorizeSubscribe(id, port);
|
||||||
|
|
||||||
|
|||||||
@ -327,6 +327,17 @@ export default class State {
|
|||||||
return this.#authUrls;
|
return this.#authUrls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public removeAuthorization (url: string): AuthUrls {
|
||||||
|
const entry = this.#authUrls[url];
|
||||||
|
|
||||||
|
assert(entry, `The source ${url} is not known`);
|
||||||
|
|
||||||
|
delete this.#authUrls[url];
|
||||||
|
this.saveCurrentAuthList();
|
||||||
|
|
||||||
|
return this.#authUrls;
|
||||||
|
}
|
||||||
|
|
||||||
private updateIconAuth (shouldClose?: boolean): void {
|
private updateIconAuth (shouldClose?: boolean): void {
|
||||||
this.authSubject.next(this.allAuthRequests);
|
this.authSubject.next(this.allAuthRequests);
|
||||||
this.updateIcon(shouldClose);
|
this.updateIcon(shouldClose);
|
||||||
|
|||||||
@ -92,6 +92,7 @@ export interface RequestSignatures {
|
|||||||
'pri(authorize.reject)': [RequestAuthorizeReject, boolean];
|
'pri(authorize.reject)': [RequestAuthorizeReject, boolean];
|
||||||
'pri(authorize.requests)': [RequestAuthorizeSubscribe, boolean, AuthorizeRequest[]];
|
'pri(authorize.requests)': [RequestAuthorizeSubscribe, boolean, AuthorizeRequest[]];
|
||||||
'pri(authorize.toggle)': [string, ResponseAuthorizeList];
|
'pri(authorize.toggle)': [string, ResponseAuthorizeList];
|
||||||
|
'pri(authorize.remove)': [string, ResponseAuthorizeList];
|
||||||
'pri(derivation.create)': [RequestDeriveCreate, boolean];
|
'pri(derivation.create)': [RequestDeriveCreate, boolean];
|
||||||
'pri(derivation.validate)': [RequestDeriveValidate, ResponseDeriveValidate];
|
'pri(derivation.validate)': [RequestDeriveValidate, ResponseDeriveValidate];
|
||||||
'pri(json.restore)': [RequestJsonRestore, void];
|
'pri(json.restore)': [RequestJsonRestore, void];
|
||||||
|
|||||||
@ -7,24 +7,29 @@ import React, { useCallback } from 'react';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { AuthUrlInfo } from '@polkadot/extension-base/background/handlers/State';
|
import { AuthUrlInfo } from '@polkadot/extension-base/background/handlers/State';
|
||||||
import { Switch } from '@polkadot/extension-ui/components';
|
import { RemoveAuth, Switch } from '@polkadot/extension-ui/components';
|
||||||
|
|
||||||
import useTranslation from '../../hooks/useTranslation';
|
import useTranslation from '../../hooks/useTranslation';
|
||||||
|
|
||||||
interface Props extends ThemeProps {
|
interface Props extends ThemeProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
info: AuthUrlInfo;
|
info: AuthUrlInfo;
|
||||||
toggleAuth: (url: string) => void
|
toggleAuth: (url: string) => void;
|
||||||
|
removeAuth: (url: string) => void;
|
||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function WebsiteEntry ({ className = '', info, toggleAuth, url }: Props): React.ReactElement<Props> {
|
function WebsiteEntry ({ className = '', info, removeAuth, toggleAuth, url }: Props): React.ReactElement<Props> {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const switchAccess = useCallback(() => {
|
const switchAccess = useCallback(() => {
|
||||||
toggleAuth(url);
|
toggleAuth(url);
|
||||||
}, [toggleAuth, url]);
|
}, [toggleAuth, url]);
|
||||||
|
|
||||||
|
const _removeAuth = useCallback(() => {
|
||||||
|
removeAuth(url);
|
||||||
|
}, [removeAuth, url]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`${className} ${info.isAllowed ? 'allowed' : 'denied'}`}>
|
<div className={`${className} ${info.isAllowed ? 'allowed' : 'denied'}`}>
|
||||||
<div className='url'>
|
<div className='url'>
|
||||||
@ -37,6 +42,13 @@ function WebsiteEntry ({ className = '', info, toggleAuth, url }: Props): React.
|
|||||||
onChange={switchAccess}
|
onChange={switchAccess}
|
||||||
uncheckedLabel={t<string>('denied')}
|
uncheckedLabel={t<string>('denied')}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className='removeAuth'
|
||||||
|
onClick={_removeAuth}
|
||||||
|
>
|
||||||
|
<RemoveAuth />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { AuthUrlInfo, AuthUrls } from '@polkadot/extension-base/background/handl
|
|||||||
import { InputFilter } from '@polkadot/extension-ui/components';
|
import { InputFilter } from '@polkadot/extension-ui/components';
|
||||||
|
|
||||||
import useTranslation from '../../hooks/useTranslation';
|
import useTranslation from '../../hooks/useTranslation';
|
||||||
import { getAuthList, toggleAuthorization } from '../../messaging';
|
import { getAuthList, removeAuthorization, toggleAuthorization } from '../../messaging';
|
||||||
import { Header } from '../../partials';
|
import { Header } from '../../partials';
|
||||||
import WebsiteEntry from './WebsiteEntry';
|
import WebsiteEntry from './WebsiteEntry';
|
||||||
|
|
||||||
@ -39,6 +39,12 @@ function AuthManagement ({ className }: Props): React.ReactElement<Props> {
|
|||||||
.catch(console.error);
|
.catch(console.error);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
const removeAuth = useCallback((url: string) => {
|
||||||
|
removeAuthorization(url)
|
||||||
|
.then(({ list }) => setAuthList(list))
|
||||||
|
.catch(console.error);
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header
|
<Header
|
||||||
@ -66,6 +72,7 @@ function AuthManagement ({ className }: Props): React.ReactElement<Props> {
|
|||||||
<WebsiteEntry
|
<WebsiteEntry
|
||||||
info={info}
|
info={info}
|
||||||
key={url}
|
key={url}
|
||||||
|
removeAuth={removeAuth}
|
||||||
toggleAuth={toggleAuth}
|
toggleAuth={toggleAuth}
|
||||||
url={url}
|
url={url}
|
||||||
/>
|
/>
|
||||||
|
|||||||
39
packages/extension-ui/src/components/RemoveAuth.tsx
Normal file
39
packages/extension-ui/src/components/RemoveAuth.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// Copyright 2019-2022 @polkadot/extension-ui authors & contributors
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
import type { ThemeProps } from '../types';
|
||||||
|
|
||||||
|
import { faTrash } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
function RemoveAuth (): React.ReactElement {
|
||||||
|
return (
|
||||||
|
<FontAwesomeIcon
|
||||||
|
className='trashIcon'
|
||||||
|
icon={faTrash}
|
||||||
|
size='lg'
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default styled(RemoveAuth)(({ theme }: ThemeProps) => `
|
||||||
|
label {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 48px;
|
||||||
|
height: 24px;
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.trashIcon {
|
||||||
|
color: ${theme.iconNeutralColor};
|
||||||
|
margin-left: 8px;
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
color: ${theme.primaryColor};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
`);
|
||||||
@ -28,6 +28,7 @@ export { default as MenuDivider } from './MenuDivider';
|
|||||||
export { default as MenuItem } from './MenuItem';
|
export { default as MenuItem } from './MenuItem';
|
||||||
export { default as MnemonicSeed } from './MnemonicSeed';
|
export { default as MnemonicSeed } from './MnemonicSeed';
|
||||||
export { default as NextStepButton } from './NextStepButton';
|
export { default as NextStepButton } from './NextStepButton';
|
||||||
|
export { default as RemoveAuth } from './RemoveAuth';
|
||||||
export { default as Spinner } from './Spinner';
|
export { default as Spinner } from './Spinner';
|
||||||
export { default as Svg } from './Svg';
|
export { default as Svg } from './Svg';
|
||||||
export { default as Switch } from './Switch';
|
export { default as Switch } from './Switch';
|
||||||
|
|||||||
@ -196,6 +196,10 @@ export async function toggleAuthorization (url: string): Promise<ResponseAuthori
|
|||||||
return sendMessage('pri(authorize.toggle)', url);
|
return sendMessage('pri(authorize.toggle)', url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function removeAuthorization (url: string): Promise<ResponseAuthorizeList> {
|
||||||
|
return sendMessage('pri(authorize.remove)', url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function subscribeMetadataRequests (cb: (accounts: MetadataRequest[]) => void): Promise<boolean> {
|
export async function subscribeMetadataRequests (cb: (accounts: MetadataRequest[]) => void): Promise<boolean> {
|
||||||
return sendMessage('pri(metadata.requests)', null, cb);
|
return sendMessage('pri(metadata.requests)', null, cb);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user