Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP - feat/1078: Extension: Permission improvements #1142

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 17 additions & 5 deletions apps/extension/src/Approvals/ApproveConnection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ import { ConnectInterfaceResponseMsg } from "background/approvals";
import { useQuery } from "hooks";
import { useRequester } from "hooks/useRequester";
import { Ports } from "router";
import { AllowedPermissions } from "storage";
import { closeCurrentTab } from "utils";

export const ApproveConnection: React.FC = () => {
const requester = useRequester();
const params = useQuery();
const interfaceOrigin = params.get("interfaceOrigin");
const chainId = params.get("chainId")!;

const handleResponse = async (allowConnection: boolean): Promise<void> => {
const handleResponse = async (
permissions: AllowedPermissions
): Promise<void> => {
if (interfaceOrigin) {
await requester.sendMessage(
Ports.Background,
new ConnectInterfaceResponseMsg(interfaceOrigin, allowConnection)
new ConnectInterfaceResponseMsg(interfaceOrigin, chainId, permissions)
);
await closeCurrentTab();
}
Expand All @@ -26,15 +30,23 @@ export const ApproveConnection: React.FC = () => {
<PageHeader title="Approve Request" />
<Stack full className="justify-between" gap={12}>
<Alert type="warning">
Approve connection for <strong>{interfaceOrigin}</strong>?
Approve connection for <strong>{interfaceOrigin}</strong> and enable
signing for <strong>{chainId}</strong>?
</Alert>
<Stack gap={2}>
<ActionButton onClick={() => handleResponse(true)}>
<ActionButton
onClick={() =>
// NOTE: In the future we may want the user to have
// granular control over what access the extension may
// have for any particular domain
handleResponse(["accounts", "proofGenKeys", "signing"])
}
>
Approve
</ActionButton>
<ActionButton
outlineColor="yellow"
onClick={() => handleResponse(false)}
onClick={() => handleResponse([])}
>
Reject
</ActionButton>
Expand Down
7 changes: 6 additions & 1 deletion apps/extension/src/Approvals/ApproveDisconnection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ export const ApproveDisconnection: React.FC = () => {
const requester = useRequester();
const params = useQuery();
const interfaceOrigin = params.get("interfaceOrigin");
const chainId = params.get("chainId")!;

const handleResponse = async (revokeConnection: boolean): Promise<void> => {
if (interfaceOrigin) {
await requester.sendMessage(
Ports.Background,
new DisconnectInterfaceResponseMsg(interfaceOrigin, revokeConnection)
new DisconnectInterfaceResponseMsg(
interfaceOrigin,
chainId,
revokeConnection
)
);
await closeCurrentTab();
}
Expand Down
9 changes: 6 additions & 3 deletions apps/extension/src/background/approvals/handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ describe("approvals handler", () => {
});

test("handlers switch", () => {
const chainId = "";
const service: jest.Mocked<ApprovalsService> = createMockInstance(
ApprovalsService as any
);
Expand Down Expand Up @@ -72,23 +73,25 @@ describe("approvals handler", () => {
handler(env, rejectTxMsg);
expect(service.rejectSignTx).toBeCalled();

const isConnectionApprovedMsg = new IsConnectionApprovedMsg();
const isConnectionApprovedMsg = new IsConnectionApprovedMsg(chainId);
handler(env, isConnectionApprovedMsg);
expect(service.isConnectionApproved).toBeCalled();

const approveConnectInterfaceMsg = new ApproveConnectInterfaceMsg();
const approveConnectInterfaceMsg = new ApproveConnectInterfaceMsg(chainId);
handler(env, approveConnectInterfaceMsg);
expect(service.approveConnection).toBeCalled();

const connectInterfaceResponseMsg = new ConnectInterfaceResponseMsg(
"",
true
chainId,
["accounts", "signing"]
);
handler(env, connectInterfaceResponseMsg);
expect(service.approveConnectionResponse).toBeCalled();

const disconnectInterfaceResponseMsg = new DisconnectInterfaceResponseMsg(
"",
"chainId",
true
);
handler(env, disconnectInterfaceResponseMsg);
Expand Down
20 changes: 11 additions & 9 deletions apps/extension/src/background/approvals/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,16 +117,16 @@ export const getHandler: (service: ApprovalsService) => Handler = (service) => {
const handleIsConnectionApprovedMsg: (
service: ApprovalsService
) => InternalHandler<IsConnectionApprovedMsg> = (service) => {
return async (_, { origin }) => {
return await service.isConnectionApproved(origin);
return async (_, { origin, chainId }) => {
return await service.isConnectionApproved(origin, chainId);
};
};

const handleApproveConnectInterfaceMsg: (
service: ApprovalsService
) => InternalHandler<ApproveConnectInterfaceMsg> = (service) => {
return async (_, { origin }) => {
return await service.approveConnection(origin);
return async (_, { origin, chainId }) => {
return await service.approveConnection(origin, chainId);
};
};

Expand All @@ -135,21 +135,22 @@ const handleConnectInterfaceResponseMsg: (
) => InternalHandler<ConnectInterfaceResponseMsg> = (service) => {
return async (
{ senderTabId: popupTabId },
{ interfaceOrigin, allowConnection }
{ interfaceOrigin, chainId, permissions }
) => {
return await service.approveConnectionResponse(
popupTabId,
interfaceOrigin,
allowConnection
chainId,
permissions
);
};
};

const handleApproveDisconnectInterfaceMsg: (
service: ApprovalsService
) => InternalHandler<ApproveDisconnectInterfaceMsg> = (service) => {
return async (_, { origin }) => {
return await service.approveDisconnection(origin);
return async (_, { origin, chainId }) => {
return await service.approveDisconnection(origin, chainId);
};
};

Expand All @@ -158,11 +159,12 @@ const handleDisconnectInterfaceResponseMsg: (
) => InternalHandler<DisconnectInterfaceResponseMsg> = (service) => {
return async (
{ senderTabId: popupTabId },
{ interfaceOrigin, revokeConnection }
{ interfaceOrigin, chainId, revokeConnection }
) => {
return await service.approveDisconnectionResponse(
popupTabId,
interfaceOrigin,
chainId,
revokeConnection
);
};
Expand Down
15 changes: 12 additions & 3 deletions apps/extension/src/background/approvals/messages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,20 +63,29 @@ describe("approvals messages", () => {
});

test("valid ConnectInterfaceResponseMsg", () => {
const msg = new ConnectInterfaceResponseMsg("interface", true);
const msg = new ConnectInterfaceResponseMsg("interface", "chainId", [
"accounts",
"signing",
]);

expect(msg.type()).toBe(MessageType.ConnectInterfaceResponse);
expect(msg.route()).toBe(ROUTE);
expect(msg.validate()).toBeUndefined();
});

test("invalid ConnectInterfaceResponseMsg", () => {
const msg = new ConnectInterfaceResponseMsg("interface", true);
const msg = new ConnectInterfaceResponseMsg("interface", "chainId", [
"accounts",
"signing",
]);
(msg as any).interfaceOrigin = undefined;

expect(() => msg.validate()).toThrow();

const msg2 = new ConnectInterfaceResponseMsg("interface", true);
const msg2 = new ConnectInterfaceResponseMsg("interface", "chainId", [
"accounts",
"signing",
]);
(msg2 as any).allowConnection = undefined;

expect(() => msg2.validate()).toThrow();
Expand Down
9 changes: 6 additions & 3 deletions apps/extension/src/background/approvals/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ROUTE } from "./constants";

import { TxDetails } from "@namada/types";
import { ResponseSign } from "@zondax/ledger-namada";
import { AllowedPermissions } from "storage";
import { validateProps } from "utils";

export enum MessageType {
Expand Down Expand Up @@ -147,13 +148,14 @@ export class ConnectInterfaceResponseMsg extends Message<void> {

constructor(
public readonly interfaceOrigin: string,
public readonly allowConnection: boolean
public readonly chainId: string,
public readonly permissions: AllowedPermissions
) {
super();
}

validate(): void {
validateProps(this, ["interfaceOrigin", "allowConnection"]);
validateProps(this, ["interfaceOrigin", "chainId", "permissions"]);
}

route(): string {
Expand All @@ -172,13 +174,14 @@ export class DisconnectInterfaceResponseMsg extends Message<void> {

constructor(
public readonly interfaceOrigin: string,
public readonly chainId: string,
public readonly revokeConnection: boolean
) {
super();
}

validate(): void {
validateProps(this, ["interfaceOrigin", "revokeConnection"]);
validateProps(this, ["interfaceOrigin", "chainId", "revokeConnection"]);
}

route(): string {
Expand Down
Loading
Loading