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

feat(app,iam): using did session to sign challenges #1936

Merged
merged 2 commits into from
Nov 27, 2023
Merged
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
1 change: 1 addition & 0 deletions app/__test-fixtures__/contextTestHelpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,7 @@ const datastoreConnectionContext = {
disconnect: jest.fn(),
dbAccessToken: "token",
dbAccessTokenStatus: "idle" as DbAuthTokenStatus,
did: jest.fn() as any,
};

export const renderWithContext = (
Expand Down
5 changes: 3 additions & 2 deletions app/__tests__/components/GenericPlatform.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const { Ens } = platforms;
import { CeramicContextState } from "../../context/ceramicContext";
import { mockAddress } from "../../__test-fixtures__/onboardHookValues";
import { UN_SUCCESSFUL_ENS_RESULT, SUCCESFUL_ENS_RESULTS } from "../../__test-fixtures__/verifiableCredentialResults";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";
import { makeTestCeramicContext, renderWithContext } from "../../__test-fixtures__/contextTestHelpers";
import { JsonRpcSigner } from "@ethersproject/providers";
import { mock } from "jest-mock-extended";
Expand All @@ -24,11 +24,12 @@ jest.mock("@didtools/cacao", () => ({
},
}));

jest.mock("@gitcoin/passport-identity/dist/commonjs/src/credentials", () => ({
jest.mock("@gitcoin/passport-identity", () => ({
fetchVerifiableCredential: jest.fn(),
}));

jest.mock("../../utils/helpers.tsx", () => ({
createSignedPayload: jest.fn(),
generateUID: jest.fn(),
getProviderSpec: jest.fn(),
difference: (setA: any, setB: any) => ({
Expand Down
4 changes: 2 additions & 2 deletions app/__tests__/components/ProviderCards/BrightidCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { mockAddress, mockWallet } from "../../../__test-fixtures__/onboardHookV
import { STAMP_PROVIDERS } from "../../../config/providers";
import { brightidStampFixture } from "../../../__test-fixtures__/databaseStorageFixtures";
import { SUCCESFUL_BRIGHTID_RESULT } from "../../../__test-fixtures__/verifiableCredentialResults";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";
import { mock } from "jest-mock-extended";
import { JsonRpcSigner } from "@ethersproject/providers";
import { makeTestCeramicContext, renderWithContext } from "../../../__test-fixtures__/contextTestHelpers";
import { CeramicContextState } from "../../../context/ceramicContext";

jest.mock("@gitcoin/passport-identity/dist/commonjs/src/credentials", () => ({
jest.mock("@gitcoin/passport-identity", () => ({
fetchVerifiableCredential: jest.fn(),
}));

Expand Down
4 changes: 2 additions & 2 deletions app/__tests__/components/ProviderCards/EnsCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import { mockAddress } from "../../../__test-fixtures__/onboardHookValues";
import { STAMP_PROVIDERS } from "../../../config/providers";
import { ensStampFixture } from "../../../__test-fixtures__/databaseStorageFixtures";
import { SUCCESFUL_ENS_RESULT } from "../../../__test-fixtures__/verifiableCredentialResults";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";
import { makeTestCeramicContext, renderWithContext } from "../../../__test-fixtures__/contextTestHelpers";
import { JsonRpcSigner } from "@ethersproject/providers";
import { mock } from "jest-mock-extended";

jest.mock("@gitcoin/passport-identity/dist/commonjs/src/credentials", () => ({
jest.mock("@gitcoin/passport-identity", () => ({
fetchVerifiableCredential: jest.fn(),
}));

Expand Down
4 changes: 2 additions & 2 deletions app/__tests__/components/ProviderCards/PohCard.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import { mockAddress, mockWallet } from "../../../__test-fixtures__/onboardHookV
import { STAMP_PROVIDERS } from "../../../config/providers";
import { pohStampFixture } from "../../../__test-fixtures__/databaseStorageFixtures";
import { SUCCESFUL_POH_RESULT } from "../../../__test-fixtures__/verifiableCredentialResults";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";
import { mock } from "jest-mock-extended";
import { JsonRpcSigner } from "@ethersproject/providers";
import { makeTestCeramicContext, renderWithContext } from "../../../__test-fixtures__/contextTestHelpers";
import { CeramicContextState } from "../../../context/ceramicContext";

jest.mock("@gitcoin/passport-identity/dist/commonjs/src/credentials", () => ({
jest.mock("@gitcoin/passport-identity", () => ({
fetchVerifiableCredential: jest.fn(),
}));

Expand Down
9 changes: 3 additions & 6 deletions app/__tests__/components/RefreshMyStampsModalContent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { makeTestCeramicContext, renderWithContext } from "../../__test-fixtures
import { useNavigate } from "react-router-dom";
import { ValidatedPlatform } from "../../signer/utils";

import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";
import { reduceStampResponse } from "../../utils/helpers";
import { CredentialResponseBody } from "@gitcoin/passport-types";
import { IAM_SIGNATURE_TYPE } from "../../config/stamp_config";
Expand All @@ -15,7 +15,7 @@ jest.mock("react-router-dom", () => ({
useNavigate: jest.fn(),
}));

jest.mock("@gitcoin/passport-identity/dist/commonjs/src/credentials", () => ({
jest.mock("@gitcoin/passport-identity", () => ({
fetchVerifiableCredential: jest.fn().mockResolvedValue({ credentials: [] } as unknown as CredentialResponseBody),
}));

Expand Down Expand Up @@ -43,11 +43,8 @@ const mockWalletState = {
address: "0xmyAddress",
};

const mockSigner = jest.fn();

jest.mock("../../context/walletStore", () => ({
useWalletStore: (callback: (state: any) => any) => callback(mockWalletState),
useSigner: () => mockSigner,
}));

const validPlatforms: ValidatedPlatform[] = [
Expand Down Expand Up @@ -117,7 +114,7 @@ describe("RefreshMyStampsModalContent", () => {
proofs: {},
signatureType: IAM_SIGNATURE_TYPE,
},
mockSigner
expect.any(Function)
)
);
});
Expand Down
26 changes: 0 additions & 26 deletions app/__tests__/context/datastoreConnectionContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,32 +107,6 @@ describe("<UserContext>", () => {
localStorage.setItem("connectedWallets", "[]");
});

it("should delete localStorage item if session has expired", async () => {
const ceramicConnect = jest.fn().mockResolvedValueOnce({
client: {
session: {
isExpired: true,
expireInSecs: 3400,
},
},
});
(framework.useViewerConnection as jest.Mock).mockReturnValue([
{ status: "connecting", selfID: { did: "did:test" } },
ceramicConnect,
jest.fn(),
]);

localStorage.setItem("didsession-0xmyAddress", "eyJzZXNzaW9uS2V5U2VlZCI6IlF5cTN4aW9ubGxD...");

renderTestComponent();

expect(screen.getByTestId("session-id")).toHaveTextContent("eyJzZXNzaW9uS2V5U2VlZCI6IlF5cTN4aW9ubGxD...");

screen.getByRole("button").click();

await waitFor(() => expect(screen.getByTestId("session-id").textContent).toBe(""));
});

describe("when using multichain", () => {
beforeEach(async () => {
const ceramicConnect = jest.fn().mockResolvedValueOnce({
Expand Down
45 changes: 33 additions & 12 deletions app/__tests__/context/stampClaimingContext.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ import { makeTestCeramicContext } from "../../__test-fixtures__/contextTestHelpe

import { CeramicContext } from "../../context/ceramicContext";
import { StampClaimingContext, StampClaimingContextProvider } from "../../context/stampClaimingContext";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";

import { PLATFORM_ID } from "@gitcoin/passport-types";
import { PlatformProps } from "../../components/GenericPlatform";
import { AppContext, PlatformClass } from "@gitcoin/passport-platforms";
import { DatastoreConnectionContext, DbAuthTokenStatus } from "../../context/datastoreConnectionContext";

jest.mock("../../utils/helpers", () => ({
generateUID: jest.fn((length: number) => "some random string"),
}));

jest.mock("@gitcoin/passport-identity/dist/commonjs/src/credentials", () => ({
jest.mock("@gitcoin/passport-identity", () => ({
fetchVerifiableCredential: jest.fn(),
}));

Expand Down Expand Up @@ -118,20 +119,40 @@ const mockCeramicContext = makeTestCeramicContext({
describe("<StampClaimingContext>", () => {
const renderTestComponent = () =>
render(
<CeramicContext.Provider value={mockCeramicContext}>
<StampClaimingContextProvider>
<TestingComponent />
</StampClaimingContextProvider>
</CeramicContext.Provider>
<DatastoreConnectionContext.Provider
value={{
connect: jest.fn(),
disconnect: jest.fn(),
dbAccessToken: "token",
dbAccessTokenStatus: "idle" as DbAuthTokenStatus,
did: jest.fn() as any,
}}
>
<CeramicContext.Provider value={mockCeramicContext}>
<StampClaimingContextProvider>
<TestingComponent />
</StampClaimingContextProvider>
</CeramicContext.Provider>
</DatastoreConnectionContext.Provider>
);

const renderTestComponentWithEvmStamp = () =>
render(
<CeramicContext.Provider value={mockCeramicContext}>
<StampClaimingContextProvider>
<TestingComponentWithEvmStamp />
</StampClaimingContextProvider>
</CeramicContext.Provider>
<DatastoreConnectionContext.Provider
value={{
connect: jest.fn(),
disconnect: jest.fn(),
dbAccessToken: "token",
dbAccessTokenStatus: "idle" as DbAuthTokenStatus,
did: jest.fn() as any,
}}
>
<CeramicContext.Provider value={mockCeramicContext}>
<StampClaimingContextProvider>
<TestingComponentWithEvmStamp />
</StampClaimingContextProvider>
</CeramicContext.Provider>
</DatastoreConnectionContext.Provider>
);

beforeEach(() => {
Expand Down
45 changes: 45 additions & 0 deletions app/__tests__/utils/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { createSignedPayload } from "../../utils/helpers";
import { Cacao } from "@didtools/cacao";

jest.mock("@didtools/cacao", () => ({
Cacao: {
fromBlockBytes: jest.fn().mockImplementation((_) => {
return {
p: {
iss: "did:ethr:0x123",
},
};
}),
},
}));

describe("createSignedPayload", () => {
it("should sign", async () => {
const mockDid = {
createDagJWS: () => ({
jws: {
link: {
bytes: [7, 8, 9],
},
payload: {
hello: "world",
},
signatures: ["0x123"],
},
cacaoBlock: [0, 1, 2],
}),
};

const signedPayload = await createSignedPayload(mockDid as any, { hello: "world" });

expect(Cacao.fromBlockBytes).toHaveBeenCalledWith([0, 1, 2]);

expect(signedPayload).toEqual({
signatures: ["0x123"],
payload: { hello: "world" },
cid: [7, 8, 9],
cacao: [0, 1, 2],
issuer: "did:ethr:0x123",
});
});
});
15 changes: 9 additions & 6 deletions app/components/GenericPlatform.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// --- Methods
import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
import React, { useContext, useEffect, useMemo, useState } from "react";

// --- Datadog
import { datadogLogs } from "@datadog/browser-logs";
Expand All @@ -12,7 +12,7 @@ import {
PLATFORM_ID,
StampPatch,
} from "@gitcoin/passport-types";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity/dist/commonjs/src/credentials";
import { fetchVerifiableCredential } from "@gitcoin/passport-identity";

// --- Style Components
import { SideBarContent } from "./SideBarContent";
Expand All @@ -23,7 +23,7 @@ import { JsonOutputModal } from "./JsonOutputModal";

// --- Context
import { CeramicContext } from "../context/ceramicContext";
import { useSigner, useWalletStore } from "../context/walletStore";
import { useWalletStore } from "../context/walletStore";
import { waitForRedirect } from "../context/stampClaimingContext";

// --- Types
Expand All @@ -32,10 +32,11 @@ import { PlatformClass } from "@gitcoin/passport-platforms";
import { IAM_SIGNATURE_TYPE, iamUrl } from "../config/stamp_config";

// --- Helpers
import { difference, generateUID } from "../utils/helpers";
import { createSignedPayload, difference, generateUID } from "../utils/helpers";

import { datadogRum } from "@datadog/browser-rum";
import { PlatformScoreSpec } from "../context/scorerContext";
import { useDatastoreConnectionContext } from "../context/datastoreConnectionContext";

export type PlatformProps = {
platFormGroupSpec: PlatformGroupSpec[];
Expand Down Expand Up @@ -68,13 +69,13 @@ export const GenericPlatform = ({
onClose,
}: GenericPlatformProps): JSX.Element => {
const address = useWalletStore((state) => state.address);
const signer = useSigner();
const { handlePatchStamps, verifiedProviderIds, userDid } = useContext(CeramicContext);
const [isLoading, setLoading] = useState(false);
const [canSubmit, setCanSubmit] = useState(false);
const [submitted, setSubmitted] = useState(false);
const [verificationResponse, setVerificationResponse] = useState<CredentialResponseBody[]>([]);
const [payloadModalIsOpen, setPayloadModalIsOpen] = useState(false);
const { did } = useDatastoreConnectionContext();
// const { handleFetchCredential } = useContext(StampClaimingContext);

// --- Chakra functions
Expand Down Expand Up @@ -153,6 +154,7 @@ export const GenericPlatform = ({
datadogLogs.logger.info("Saving Stamp", { platform: platform.platformId });
setLoading(true);
try {
if (!did) throw new Error("No DID found");
const state = `${platform.path}-` + generateUID(10);
const providerPayload = (await platform.getProviderPayload({
state,
Expand Down Expand Up @@ -181,7 +183,7 @@ export const GenericPlatform = ({
proofs: providerPayload,
signatureType: IAM_SIGNATURE_TYPE,
},
signer as { signMessage: (message: string) => Promise<string> }
(data: any) => createSignedPayload(did, data)
);

const verifiedCredentials =
Expand Down Expand Up @@ -246,6 +248,7 @@ export const GenericPlatform = ({

setLoading(false);
} catch (e) {
console.error(e);
datadogLogs.logger.error("Verification Error", { error: e, platform: platform.platformId });
doneToast(
"Verification Failed",
Expand Down
Loading
Loading