Skip to content

Commit

Permalink
Merge pull request #2002 from getAlby/task-account-perms
Browse files Browse the repository at this point in the history
feat: include account ID in permissions
  • Loading branch information
bumi authored Mar 6, 2023
2 parents dd16e3b + 0412db8 commit cc64a57
Show file tree
Hide file tree
Showing 18 changed files with 106 additions and 15 deletions.
15 changes: 9 additions & 6 deletions src/app/components/AllowanceMenu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { CrossIcon } from "@bitcoin-design/bitcoin-icons-react/outline";
import Setting from "@components/Setting";
import Toggle from "@components/form/Toggle";
import type { FormEvent } from "react";
import { useEffect, useState } from "react";
import { Fragment, useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import Modal from "react-modal";
import { toast } from "react-toastify";
import { useAccount } from "~/app/context/AccountContext";
import { useSettings } from "~/app/context/SettingsContext";
import msg from "~/common/lib/msg";
import type { Allowance, Permission } from "~/types";
Expand All @@ -28,7 +29,7 @@ function AllowanceMenu({ allowance, onEdit, onDelete }: Props) {
getFormattedFiat,
} = useSettings();
const showFiat = !isLoadingSettings && settings.showFiat;

const { account } = useAccount();
const [modalIsOpen, setIsOpen] = useState(false);
const [budget, setBudget] = useState("");
const [lnurlAuth, setLnurlAuth] = useState(false);
Expand Down Expand Up @@ -58,6 +59,7 @@ function AllowanceMenu({ allowance, onEdit, onDelete }: Props) {
permissions: Permission[];
}>("listPermissions", {
id: allowance.id,
accountId: account?.id,
});

const permissions: Permission[] = permissionResponse?.permissions;
Expand All @@ -72,8 +74,8 @@ function AllowanceMenu({ allowance, onEdit, onDelete }: Props) {
}
};

!permissions && fetchPermissions();
}, [allowance.id, permissions]);
fetchPermissions();
}, [account?.id, allowance.id]);

useEffect(() => {
if (budget !== "" && showFiat) {
Expand Down Expand Up @@ -125,6 +127,7 @@ function AllowanceMenu({ allowance, onEdit, onDelete }: Props) {
if (changedIds.length) {
await msg.request("deletePermissionsById", {
ids: changedIds,
accountId: account?.id,
});
}

Expand Down Expand Up @@ -237,7 +240,7 @@ function AllowanceMenu({ allowance, onEdit, onDelete }: Props) {
</h2>
<div>
{permissions.map((permission) => (
<>
<Fragment key={permission.id}>
<Setting
title={permission.method}
subtitle={tPermissions(
Expand Down Expand Up @@ -265,7 +268,7 @@ function AllowanceMenu({ allowance, onEdit, onDelete }: Props) {
}}
/>
</Setting>
</>
</Fragment>
))}
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const mockAllowances: DbAllowance[] = allowanceFixture;
const mockPermissions = [
{
id: 1,
accountId: "123456",
allowanceId: 1,
createdAt: "1667291216372",
host: "pro.kollider.xyz",
Expand All @@ -18,6 +19,7 @@ const mockPermissions = [
},
{
id: 2,
accountId: "123456",
allowanceId: 2,
createdAt: "1667291216372",
host: "lnmarkets.com",
Expand All @@ -27,6 +29,7 @@ const mockPermissions = [
},
{
id: 3,
accountId: "123456",
allowanceId: 2,
createdAt: "1667291216372",
host: "lnmarkets.com",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const ConnectorClass = jest.fn().mockImplementation(() => {
jest.mock("~/extension/background-script/state", () => ({
getState: () => ({
getConnector: jest.fn(() => Promise.resolve(new ConnectorClass())),
currentAccountId: "123456",
}),
}));

Expand All @@ -40,6 +41,7 @@ const allowanceInDB = {

const permissionInDB = {
id: 1,
accountId: "123456",
allowanceId: allowanceInDB.id,
createdAt: "1487076708000",
host: allowanceInDB.host,
Expand Down
9 changes: 8 additions & 1 deletion src/extension/background-script/actions/ln/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const request = async (
message: MessageGenericRequest
): Promise<{ data: unknown } | { error: string }> => {
const connector = await state.getState().getConnector();
const accountId = state.getState().currentAccountId;

const { origin, args } = message;

Expand Down Expand Up @@ -43,14 +44,19 @@ const request = async (
throw new Error("Could not find an allowance for this host");
}

if (!accountId) {
// type guard
throw new Error("Could not find a selected account");
}

const connectorName = connector.constructor.name.toLowerCase();
// prefix method with webln to prevent potential naming conflicts (e.g. with nostr calls that also use the permissions)
const weblnMethod = `${WEBLN_PREFIX}${connectorName}/${methodInLowerCase}`;

const permission = await db.permissions
.where("host")
.equalsIgnoreCase(origin.host)
.and((p) => p.method === weblnMethod)
.and((p) => p.accountId === accountId && p.method === weblnMethod)
.first();

// request method is allowed to be called
Expand Down Expand Up @@ -89,6 +95,7 @@ const request = async (
if (promptResponse.data.enabled) {
const permissionIsAdded = await db.permissions.add({
createdAt: Date.now().toString(),
accountId: accountId,
allowanceId: allowance.id,
host: origin.host,
method: weblnMethod, // ensure to store the prefixed method string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const NostrClass = jest.fn().mockImplementation(() => {
jest.mock("~/extension/background-script/state", () => ({
getState: () => ({
getNostr: jest.fn(() => new NostrClass()),
currentAccountId: "123456",
}),
}));

Expand Down
12 changes: 11 additions & 1 deletion src/extension/background-script/actions/nostr/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as secp256k1 from "@noble/secp256k1";
import Hex from "crypto-js/enc-hex";
import sha256 from "crypto-js/sha256";
import db from "~/extension/background-script/db";
import state from "~/extension/background-script/state";
import { Event } from "~/extension/ln/nostr/types";

export async function hasPermissionFor(method: string, host: string) {
Expand All @@ -20,24 +21,33 @@ export async function hasPermissionFor(method: string, host: string) {
);
}

const accountId = state.getState().currentAccountId;

if (!accountId) {
return Promise.reject(new Error("Account doesn't exist"));
}

const findPermission = await db.permissions.get({
host,
method,
accountId,
});

return !!findPermission?.enabled;
}

export async function addPermissionFor(method: string, host: string) {
const accountId = state.getState().currentAccountId;
const allowance = await db.allowances.get({
host,
});

if (!allowance?.id) {
if (!allowance?.id || !accountId) {
return false;
}
const permissionIsAdded = await db.permissions.add({
createdAt: Date.now().toString(),
accountId: accountId,
allowanceId: allowance.id,
host: host,
method: method,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
import db from "~/extension/background-script/db";
import state from "~/extension/background-script/state";
import { allowanceFixture } from "~/fixtures/allowances";
import { permissionsFixture } from "~/fixtures/permissions";
import type { DbAllowance, MessagePermissionAdd } from "~/types";

import addPermission from "../add";

jest.mock("~/extension/background-script/state");

const defaultMockState = {
currentAccountId: "123456",
};

const mockState = defaultMockState;
state.getState = jest.fn().mockReturnValue(mockState);

Date.now = jest.fn(() => 1487076708000);

const mockAllowances: DbAllowance[] = [allowanceFixture[0]];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe("delete permission", () => {
args: {
host: mockPermissions[1].host,
method: "the-request-method-2",
accountId: "123456",
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ describe("delete permissions by id", () => {
},
args: {
ids: [2, 3],
accountId: "123456",
},
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import db from "~/extension/background-script/db";
import { permissionsFixture } from "~/fixtures/permissions";
import type { DbPermission, Permission, MessagePermissionsList } from "~/types";
import type { DbPermission, MessagePermissionsList, Permission } from "~/types";

import listByAllowance from "../list";

Expand Down Expand Up @@ -40,6 +40,7 @@ describe("delete permissions by id", () => {
},
args: {
id: 1,
accountId: "123456",
},
};

Expand Down
7 changes: 7 additions & 0 deletions src/extension/background-script/actions/permissions/add.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { MessagePermissionAdd } from "~/types";

import db from "../../db";
import state from "../../state";

const addPermission = async (message: MessagePermissionAdd) => {
const { host, method, enabled, blocked } = message.args;

const accountId = state.getState().currentAccountId;
const matchingAllowance = await db.allowances
.where("host")
.equalsIgnoreCase(host)
Expand All @@ -14,9 +16,14 @@ const addPermission = async (message: MessagePermissionAdd) => {
return { error: "No Allowance set for this host" };
}

if (!accountId) {
return { error: "No Account selected" };
}

const added = await db.permissions.add({
createdAt: Date.now().toString(),
allowanceId: matchingAllowance.id,
accountId,
host,
method,
enabled,
Expand Down
4 changes: 2 additions & 2 deletions src/extension/background-script/actions/permissions/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import type { MessagePermissionDelete } from "~/types";
import db from "../../db";

const deletePermission = async (message: MessagePermissionDelete) => {
const { host, method } = message.args;
const { host, method, accountId } = message.args;

const deleteCount = await db.permissions
.where("host")
.equalsIgnoreCase(host)
.and((p) => p.method === method)
.and((p) => p.accountId === accountId && p.method === method)
.delete();

await db.saveToStorage();
Expand Down
14 changes: 12 additions & 2 deletions src/extension/background-script/actions/permissions/deleteByIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@ import db from "~/extension/background-script/db";
import type { MessagePermissionsDelete } from "~/types";

const deleteByIds = async (message: MessagePermissionsDelete) => {
const { ids } = message.args;
const { ids, accountId } = message.args;

await db.permissions.bulkDelete(ids);
if (!accountId) {
return {
error: "Missing account id to delete permission(s).",
};
}

await db.permissions
.where("id")
.anyOf(ids)
.and((p) => p.accountId === accountId)
.delete();
await db.saveToStorage();

return { data: true };
Expand Down
11 changes: 9 additions & 2 deletions src/extension/background-script/actions/permissions/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@ import db from "~/extension/background-script/db";
import type { MessagePermissionsList, Permission } from "~/types";

const listByAllowance = async (message: MessagePermissionsList) => {
const { id } = message.args;
const { id, accountId } = message.args;

if (!accountId) {
return {
error: "Missing account id to fetch permissions.",
};
}

const dbPermissions = await db.permissions
.where({ allowanceId: id })
.where({ allowanceId: id, accountId })
.toArray();

const permissions: Permission[] = [];
Expand Down
4 changes: 4 additions & 0 deletions src/extension/background-script/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export class DB extends Dexie {
this.version(3).stores({
permissions: "++id,allowanceId,host,method,enabled,blocked,createdAt",
});
this.version(4).stores({
permissions:
"++id,accountId,allowanceId,host,method,enabled,blocked,createdAt",
});
this.on("ready", this.loadFromStorage.bind(this));
this.allowances = this.table("allowances");
this.payments = this.table("payments");
Expand Down
17 changes: 17 additions & 0 deletions src/extension/background-script/migrations/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import db from "../db";
import state from "../state";

export type Migration = keyof typeof migrations;
Expand Down Expand Up @@ -53,6 +54,17 @@ const migrations = {
});
// will be persisted by setMigrated
},

migratePermissionsWithoutAccountId: async () => {
const { accounts } = state.getState();
const accountId = Object.keys(accounts)[0];
const permissions = await db.permissions.toArray();

permissions.forEach(async (permission) => {
permission.id &&
(await db.permissions.update(permission.id, { accountId }));
});
},
};

const migrate = async () => {
Expand All @@ -68,6 +80,11 @@ const migrate = async () => {
await migrations["ensureAccountId"]();
await setMigrated("ensureAccountId");
}
if (shouldMigrate("migratePermissionsWithoutAccountId")) {
console.info("Running migration for: migratePermissionsWithoutAccountId");
await migrations["migratePermissionsWithoutAccountId"]();
await setMigrated("migratePermissionsWithoutAccountId");
}
};

export default migrate;
Loading

0 comments on commit cc64a57

Please sign in to comment.