Skip to content

Commit

Permalink
feat: join group ui (#859)
Browse files Browse the repository at this point in the history
- [x] Add join group page
- [x] Add bandada site url
- [x] Support history events and notifications for group join
- [x] Emit event when joining the group
- [x] Check group membership before joining
- [x] Support user reject event
- [x] Set max failures to zero for e2e

---------

Co-authored-by: 0xmad <[email protected]>
  • Loading branch information
0xmad and 0xmad authored Sep 13, 2023
1 parent 9b72e84 commit db06152
Show file tree
Hide file tree
Showing 65 changed files with 1,256 additions and 244 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ ALCHEMY_API_KEY=
FREIGHT_TRUST_NETWORK=
PULSECHAIN_API_KEY=
BANDADA_API_URL=https://api.bandada.pse.dev
BANDADA_URL=https://bandada.pse.dev
TARGET=chrome
DEMO_URL=https://ckdemo.appliedzkp.org
MANIFEST_VERSION=3
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "chrome"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "chrome"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/deployDocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
branches: [main]
paths:
- "docs/**"

workflow_dispatch:
inputs:
build:
Expand All @@ -13,8 +13,8 @@ on:
default: "enable"
type: choice
options:
- enable
- disable
- enable
- disable

permissions:
contents: read
Expand All @@ -26,20 +26,20 @@ concurrency:
cancel-in-progress: true

defaults:
run:
working-directory: ./docs
run:
working-directory: ./docs

jobs:
build:
runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v4

- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: 'latest'
mdbook-version: "latest"

- name: Setup Pages
id: pages
Expand All @@ -57,7 +57,7 @@ jobs:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-22.04
needs: build
steps:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "chrome"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/healthCheck.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "chrome"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/publishChrome.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "chrome"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/publishFirefox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "firefox"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/publishPackages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "chrome"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "chrome"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/webExtLint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ env:
FREIGHT_TRUST_NETWORK: ${{ secrets.FREIGHT_TRUST_NETWORK }}
PULSECHAIN_API_KEY: ${{ secrets.PULSECHAIN_API_KEY }}
BANDADA_API_URL: ${{ vars.BANDADA_API_URL }}
BANDADA_URL: ${{ vars.BANDADA_URL }}
TARGET: "firefox"
DEMO_URL: ${{ vars.DEMO_URL }}
MERKLE_MOCK_SERVER: ${{ vars.MERKLE_MOCK_SERVER }}
Expand Down
30 changes: 23 additions & 7 deletions packages/app/src/background/contentScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import browser from "webextension-polyfill";
import { setStatus } from "@src/ui/ducks/app";
import { setConnectedIdentity } from "@src/ui/ducks/identities";

import type { IInjectedMessageData, IReduxAction, ConnectedIdentityMetadata } from "@cryptkeeperzk/types";
import type {
IInjectedMessageData,
IReduxAction,
ConnectedIdentityMetadata,
IRejectedRequest,
} from "@cryptkeeperzk/types";

function injectScript() {
const url = browser.runtime.getURL("js/injected.js");
Expand Down Expand Up @@ -69,23 +74,34 @@ function injectScript() {
);
break;
}
case EventName.REJECT_VERIFIABLE_CREDENTIAL: {
case EventName.REVEAL_COMMITMENT: {
window.postMessage(
{
target: "injected-injectedscript",
payload: [null],
nonce: EventName.REJECT_VERIFIABLE_CREDENTIAL,
payload: [null, action.payload as { commitment: string }],
nonce: EventName.REVEAL_COMMITMENT,
},
"*",
);
break;
}
case EventName.REVEAL_COMMITMENT: {
case EventName.JOIN_GROUP: {
window.postMessage(
{
target: "injected-injectedscript",
payload: [null, action.payload as { commitment: string }],
nonce: EventName.REVEAL_COMMITMENT,
payload: [null, action.payload as { groupId: string }],
nonce: EventName.JOIN_GROUP,
},
"*",
);
break;
}
case EventName.USER_REJECT: {
window.postMessage(
{
target: "injected-injectedscript",
payload: [null, action.payload as IRejectedRequest],
nonce: EventName.USER_REJECT,
},
"*",
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
/* eslint-disable @typescript-eslint/unbound-method */
import browser from "webextension-polyfill";

import BrowserUtils from "../browserUtils";

describe("background/controllers/browserUtils", () => {
const defaultTabs = [
{ id: 1, active: true, highlighted: true },
{ id: 2, active: true, highlighted: false },
{ id: 1, active: true, highlighted: true, url: "http://localhost:3000" },
{ id: 2, active: true, highlighted: false, url: "http://localhost:3000" },
{ id: 3, active: true, highlighted: false },
];

const defaultPopupTab = { id: 3, active: true, highlighted: true };
Expand Down Expand Up @@ -50,9 +52,7 @@ describe("background/controllers/browserUtils", () => {
browserUtils.addRemoveWindowListener(callback);
browserUtils.removeRemoveWindowListener(callback);

// eslint-disable-next-line @typescript-eslint/unbound-method
expect(browser.windows.onRemoved.addListener).toBeCalledTimes(2);
// eslint-disable-next-line @typescript-eslint/unbound-method
expect(browser.windows.onRemoved.removeListener).toBeCalledTimes(1);
});

Expand All @@ -61,7 +61,14 @@ describe("background/controllers/browserUtils", () => {

await browserUtils.clearStorage();

// eslint-disable-next-line @typescript-eslint/unbound-method
expect(browser.storage.sync.clear).toBeCalledTimes(1);
});

test("should push event properly", async () => {
const browserUtils = BrowserUtils.getInstance();

await browserUtils.pushEvent({ type: "type" }, { urlOrigin: "http://localhost:3000" });

expect(browser.tabs.sendMessage).toBeCalledTimes(2);
});
});
12 changes: 12 additions & 0 deletions packages/app/src/background/controllers/browserUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import browser, { Windows } from "webextension-polyfill";

import type { IReduxAction, IZkMetadata } from "@cryptkeeperzk/types";

interface CreateWindowArgs {
type: "popup";
focused: boolean;
Expand Down Expand Up @@ -86,6 +88,16 @@ export default class BrowserUtils {
browser.windows.onRemoved.removeListener(callback);
};

pushEvent = async (action: IReduxAction, meta?: IZkMetadata): Promise<void> => {
const tabs = await browser.tabs
.query({})
.then((browserTabs) =>
browserTabs.filter(({ url }) => (url && meta?.urlOrigin ? new URL(url).origin === meta.urlOrigin : false)),
);

await Promise.all(tabs.map((tab) => browser.tabs.sendMessage(tab.id!, action).catch(() => undefined)));
};

private createTab = async (options: CreateTabArgs) => browser.tabs.create(options);

private createWindow = async (options: CreateWindowArgs) => browser.windows.create(options);
Expand Down
8 changes: 5 additions & 3 deletions packages/app/src/background/cryptKeeper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const RPC_METHOD_ACCESS: Record<RPCAction, boolean> = {
[RPCAction.ADD_VERIFIABLE_CREDENTIAL_REQUEST]: true,
[RPCAction.REVEAL_CONNECTED_IDENTITY_COMMITMENT_REQUEST]: true,
[RPCAction.JOIN_GROUP_REQUEST]: true,
[RPCAction.GENERATE_GROUP_MEMBERSHIP_PROOF_REQUEST]: true,
[RPCAction.GENERATE_GROUP_MERKLE_PROOF]: true,
};

Object.freeze(RPC_METHOD_ACCESS);
Expand Down Expand Up @@ -173,10 +173,11 @@ export default class CryptKeeperController {
// Groups
this.handler.add(RPCAction.JOIN_GROUP, this.lockService.ensure, this.groupService.joinGroup);
this.handler.add(
RPCAction.GENERATE_GROUP_MEMBERSHIP_PROOF,
RPCAction.GENERATE_GROUP_MERKLE_PROOF,
this.lockService.ensure,
this.groupService.generateGroupMembershipProof,
this.groupService.generateGroupMerkleProof,
);
this.handler.add(RPCAction.CHECK_GROUP_MEMBERSHIP, this.lockService.ensure, this.groupService.checkGroupMembership);

// History
this.handler.add(RPCAction.GET_IDENTITY_HISTORY, this.lockService.ensure, this.historyService.getOperations);
Expand Down Expand Up @@ -281,6 +282,7 @@ export default class CryptKeeperController {
// Browser
this.handler.add(RPCAction.CLOSE_POPUP, this.browserService.closePopup);
this.handler.add(RPCAction.CLEAR_STORAGE, this.lockService.ensure, this.browserService.clearStorage);
this.handler.add(RPCAction.PUSH_EVENT, this.lockService.ensure, this.browserService.pushEvent);

return this;
};
Expand Down
26 changes: 21 additions & 5 deletions packages/app/src/background/services/bandada/BandadaService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { hexToBigint } from "bigint-conversion";

import { getBandadaApiUrl } from "@src/config/env";

import type { IMerkleProof, IGenerateBandadaMerkleProofArgs, IAddBandadaGroupMemberArgs } from "@cryptkeeperzk/types";
import type {
IMerkleProof,
IGenerateBandadaMerkleProofArgs,
IAddBandadaGroupMemberArgs,
ICheckBandadaGroupMembershipArgs,
} from "@cryptkeeperzk/types";

const API_URL = getBandadaApiUrl();

Expand All @@ -23,7 +30,7 @@ export class BandadaService {
return BandadaService.INSTANCE;
};

async addMember({ groupId, commitment, apiKey, inviteCode }: IAddBandadaGroupMemberArgs): Promise<boolean> {
async addMember({ groupId, identity, apiKey, inviteCode }: IAddBandadaGroupMemberArgs): Promise<boolean> {
if (!apiKey && !inviteCode) {
throw new Error("Provide api key or invide code");
}
Expand All @@ -32,7 +39,7 @@ export class BandadaService {
throw new Error("Don't provide both api key and invide code");
}

const response = await fetch(`${API_URL}/groups/${groupId}/members/${commitment}`, {
const response = await fetch(`${API_URL}/groups/${groupId}/members/${hexToBigint(identity.commitment)}`, {
method: "POST",
headers: apiKey ? { ...DEFAULT_HEADERS, "x-api-key": apiKey } : DEFAULT_HEADERS,
body: inviteCode ? JSON.stringify({ inviteCode }) : undefined,
Expand All @@ -47,8 +54,17 @@ export class BandadaService {
throw new Error(result.message.toString());
}

async generateMerkleProof({ groupId, commitment }: IGenerateBandadaMerkleProofArgs): Promise<IMerkleProof> {
const response = await fetch(`${API_URL}/groups/${groupId}/members/${commitment}/proof`, {
async checkGroupMembership({ identity, groupId }: ICheckBandadaGroupMembershipArgs): Promise<boolean> {
const response = await fetch(`${API_URL}/groups/${groupId}/members/${hexToBigint(identity.commitment)}`, {
method: "GET",
headers: DEFAULT_HEADERS,
}).then((res) => res.json() as Promise<string>);

return JSON.parse(response) as boolean;
}

async generateMerkleProof({ groupId, identity }: IGenerateBandadaMerkleProofArgs): Promise<IMerkleProof> {
const response = await fetch(`${API_URL}/groups/${groupId}/members/${hexToBigint(identity.commitment)}/proof`, {
method: "GET",
headers: DEFAULT_HEADERS,
});
Expand Down
Loading

0 comments on commit db06152

Please sign in to comment.