Skip to content

Commit

Permalink
Merge pull request #208 from energywebfoundation/feature/SWTCH-1112_s…
Browse files Browse the repository at this point in the history
…eparate_conn_to_cache_and_did

feature/SWTCH-1112 separate connection to cache server and did registry from iam ininitialization
  • Loading branch information
JGiter authored Jul 13, 2021
2 parents 613ccf8 + 64b4b31 commit aaadb57
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 176 deletions.
3 changes: 2 additions & 1 deletion src/errors/ErrorMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ export enum ERROR_MESSAGES {
ROLE_PRECONDITION_NOT_MET = "Precondition not met, user not eligible to enrol for a role",
ROLE_NOT_EXISTS = "Role you want to enroll to does not exists",
CLAIM_PUBLISHER_NOT_REQUESTER = "Claim subject is not controlled by publisher",
ONCHAIN_ROLE_VERSION_NOT_SPECIFIED = "On-chain role version not specified"
ONCHAIN_ROLE_VERSION_NOT_SPECIFIED = "On-chain role version not specified",
CACHE_SERVER_NOT_REGISTERED = "Cache server for this chain is not registered"
}
20 changes: 16 additions & 4 deletions src/iam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,16 @@ export class IAM extends IAMBase {
*/
async initializeConnection({
walletProvider = this._providerType,
reinitializeMetamask
}: { walletProvider?: WalletProvider; reinitializeMetamask?: boolean } = {}): Promise<
InitializeData
> {
reinitializeMetamask,
initCacheServer = true,
initDID = true
}: {
walletProvider?: WalletProvider;
reinitializeMetamask?: boolean;
initCacheServer?: boolean,
initDID?: boolean
} = {}
): Promise<InitializeData> {
const { privateKey } = this._connectionOptions;

if (!walletProvider && !privateKey) {
Expand All @@ -187,6 +193,12 @@ export class IAM extends IAMBase {
initializeMetamask: reinitializeMetamask,
walletProvider
});
if (initCacheServer) {
await this.connectToCacheServer();
}
if (initDID) {
await this.connectToDIDRegistry();
}
} catch (err) {
if (err.message === "User closed modal") {
return {
Expand Down
65 changes: 39 additions & 26 deletions src/iam/iam-base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,35 +157,15 @@ export class IAMBase {
walletProvider?: WalletProvider;
}) {
await this.initSigner({ walletProvider, initializeMetamask });
await this.setAddress();
this.setDid();
await this.initChain();
this.initEventHandlers();

if (this._runningInBrowser) {
await this.setupMessaging();
}
if (this._signer) {
const fromCacheLogin = await this.loginToCacheServer();
this._publicKey = fromCacheLogin?.publicKey ?? this._publicKey;
this._identityToken = fromCacheLogin?.identityToken;

// We need a pubKey to create DID document.
// So if didn't get one from cache server login and there wasn't one saved
// then need to request signature to compute one.
if (!this._publicKey) {
const { publicKey, identityToken } = await getPublicKeyAndIdentityToken(this._signer);
this._publicKey = publicKey;
this._identityToken = identityToken;
}
if (!this._publicKey) {
throw new Error(ERROR_MESSAGES.UNABLE_TO_OBTAIN_PUBLIC_KEY);
}
this._didSigner = new Owner(this._signer, this._provider, this._publicKey);

await this.setAddress();
this.setDid();
await this.setDocument();
this.setClaims();
}
this.setResolver();
this.setJWT();
this.storeSession();
Expand Down Expand Up @@ -269,6 +249,41 @@ export class IAMBase {
throw new Error(ERROR_MESSAGES.WALLET_TYPE_NOT_PROVIDED);
}

/**
* @description established connection to cache server and logins in signing authentication token
*/
async connectToCacheServer() {
const { chainId } = await this._provider.getNetwork();
const cacheOptions = cacheServerClientOptions[chainId];
if (!this._signer) {
throw new Error(ERROR_MESSAGES.SIGNER_NOT_INITIALIZED);
}
if (!cacheOptions.url) {
throw new Error(ERROR_MESSAGES.CACHE_SERVER_NOT_REGISTERED);
}
this._cacheClient = new CacheServerClient(cacheOptions, this._signer);
const fromCacheLogin = await this.loginToCacheServer();
this._publicKey = fromCacheLogin?.publicKey ?? this._publicKey;
this._identityToken = fromCacheLogin?.identityToken;
}

/**
* @description creates users DID document if it is not yet exist
*/
async connectToDIDRegistry() {
if (!this._signer) {
throw new Error(ERROR_MESSAGES.SIGNER_NOT_INITIALIZED);
}
if (!this._publicKey) {
const { publicKey, identityToken } = await getPublicKeyAndIdentityToken(this._signer);
this._publicKey = publicKey;
this._identityToken = identityToken;
}
this._didSigner = new Owner(this._signer, this._provider, this._publicKey);
await this.setDocument();
this.setClaims();
}

/**
* Check if session is active
*
Expand Down Expand Up @@ -413,8 +428,8 @@ export class IAMBase {
}

private setJWT() {
if (this._didSigner) {
this._jwt = new JWT(this._didSigner);
if (this._signer) {
this._jwt = new JWT(this._signer);
return;
}
throw new Error(ERROR_MESSAGES.SIGNER_NOT_INITIALIZED);
Expand Down Expand Up @@ -651,9 +666,7 @@ export class IAMBase {
});
this._claimManager = ClaimManager__factory.connect(claimManagerAddress, this._signer);

const cacheOptions = cacheServerClientOptions[chainId];

cacheOptions.url && (this._cacheClient = new CacheServerClient(cacheOptions, this._signer));

this._messagingOptions = messagingOptions[chainId];
}
Expand Down
39 changes: 16 additions & 23 deletions test/application.testSuite.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ENSNamespaceTypes, IAM } from "../src/iam";
import { iam, root, rootOwner } from "./iam.test";
import { ENSNamespaceTypes } from "../src/iam";
import { createIam, rootOwnerIam, root, rootOwner } from "./iam.test";
import { org1 } from "./organization.testSuite";
import { ensResolver, replenish } from "./setup_contracts";
import { utils } from "ethers";
Expand All @@ -13,61 +13,54 @@ export const appsTests = () => {

test("application can be created", async () => {
const appDefinition = { appName: "Application 1" };
await iam.createApplication({
await rootOwnerIam.createApplication({
appName: app,
data: appDefinition,
namespace: `${ENSNamespaceTypes.Application}.${org1}.${root}`
});

expect(await iam.checkExistenceOfDomain({ domain: appNode })).toBe(true);
expect(await rootOwnerIam.checkExistenceOfDomain({ domain: appNode })).toBe(true);
expect(
await iam.checkExistenceOfDomain({ domain: `${ENSNamespaceTypes.Roles}.${appNode}` })
await rootOwnerIam.checkExistenceOfDomain({ domain: `${ENSNamespaceTypes.Roles}.${appNode}` })
).toBe(true);
expect(await ensResolver.name(namehash(appNode))).toBe(appNode);
expect(
await iam.getSubdomains({ domain: `${ENSNamespaceTypes.Application}.${org1}.${root}` })
await rootOwnerIam.getSubdomains({ domain: `${ENSNamespaceTypes.Application}.${org1}.${root}` })
).toContain(`${app}.${ENSNamespaceTypes.Application}.${org1}.${root}`);

const readAppDefinition = await iam.getDefinition({ type: ENSNamespaceTypes.Application, namespace: appNode});
const readAppDefinition = await rootOwnerIam.getDefinition({ type: ENSNamespaceTypes.Application, namespace: appNode });
expect(readAppDefinition).toMatchObject(appDefinition);
});

test("application owner can be changed", async () => {
const newOwner = new Keys();
await replenish(newOwner.getAddress());
const newOwnerIam = new IAM({
rpcUrl: "http://localhost:8544/",
privateKey: newOwner.privateKey
});
await newOwnerIam.initializeConnection({
reinitializeMetamask: false,
walletProvider: undefined
});
const newOwnerIam = await createIam(newOwner.privateKey);

expect(await iam.isOwner({ domain: appNode, user: rootOwner.getAddress() }));
expect(await rootOwnerIam.isOwner({ domain: appNode, user: rootOwner.address }));

await iam.changeAppOwnership({
await rootOwnerIam.changeAppOwnership({
namespace: appNode,
newOwner: newOwner.getAddress()
});

expect(await iam.isOwner({ domain: appNode, user: newOwner.getAddress() }));
expect(await rootOwnerIam.isOwner({ domain: appNode, user: newOwner.getAddress() }));

await newOwnerIam.changeAppOwnership({
namespace: appNode,
newOwner: rootOwner.getAddress()
newOwner: rootOwner.address
});

expect(await iam.isOwner({ domain: appNode, user: rootOwner.getAddress() }));
expect(await rootOwnerIam.isOwner({ domain: appNode, user: rootOwner.address }));
});

test("application can be deleted", async () => {
expect(await iam.checkExistenceOfDomain({ domain: appNode })).toBe(true);
expect(await rootOwnerIam.checkExistenceOfDomain({ domain: appNode })).toBe(true);

await iam.deleteApplication({
await rootOwnerIam.deleteApplication({
namespace: appNode
});

expect(await iam.checkExistenceOfDomain({ domain: appNode })).toBe(false);
expect(await rootOwnerIam.checkExistenceOfDomain({ domain: appNode })).toBe(false);
});
};
58 changes: 32 additions & 26 deletions test/assets.testsuite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,29 @@ import { Keys } from "@ew-did-registry/keys";
import { OfferableIdentityFactory } from "../ethers/OfferableIdentityFactory";
import { IAM } from "../src/iam";
import { emptyAddress } from "../src/utils/constants";
import { iam, provider, rootOwner, rpcUrl } from "./iam.test";
import { replenish } from "./setup_contracts";
import { PubKeyType } from '@ew-did-registry/did-resolver-interface/src/models/operator';
import { Algorithms, DIDAttribute, Encoding } from '@ew-did-registry/did-resolver-interface';
import { Methods } from '@ew-did-registry/did';
import { createIam, rootOwner } from "./iam.test";
import { replenish, provider, rpcUrl } from "./setup_contracts";
import { PubKeyType } from "@ew-did-registry/did-resolver-interface/src/models/operator";
import { Algorithms, DIDAttribute, Encoding } from "@ew-did-registry/did-resolver-interface";
import { Methods } from "@ew-did-registry/did";

export const assetsTests = () => {
let rootOwnerIam: IAM;

beforeAll(async () => {
rootOwnerIam = await createIam(rootOwner.privateKey, { initDID: true });
});

test("asset should be created", async () => {
const assetAddress = await iam.registerAsset();
const assetAddress = await rootOwnerIam.registerAsset();
const assetContract = OfferableIdentityFactory.connect(assetAddress, provider);
const owner = await assetContract.owner();
expect(owner).toBe(rootOwner.getAddress());
expect(owner).toBe(rootOwner.address);
});
test("asset should be offered", async () => {
const assetAddress = await iam.registerAsset();
const assetAddress = await rootOwnerIam.registerAsset();
const newOwner = new Keys();
await iam.offerAsset({
await rootOwnerIam.offerAsset({
assetDID: `did:ethr:${assetAddress}`,
offerTo: `did:ethr:${newOwner.getAddress()}`
});
Expand All @@ -27,31 +33,31 @@ export const assetsTests = () => {
expect(offered).toBe(newOwner.getAddress());
});
test("asset should be able to cancel offer", async () => {
const assetAddress = await iam.registerAsset();
const assetAddress = await rootOwnerIam.registerAsset();
const newOwner = new Keys();
const assetDID = `did:ethr:${assetAddress}`;
await iam.offerAsset({
await rootOwnerIam.offerAsset({
assetDID,
offerTo: `did:ethr:${newOwner.getAddress()}`
});
const assetContract = OfferableIdentityFactory.connect(assetAddress, provider);
const offered = await assetContract.offeredTo();
expect(offered).toBe(newOwner.getAddress());
await iam.cancelAssetOffer({ assetDID });
await rootOwnerIam.cancelAssetOffer({ assetDID });
const notOffered = await assetContract.offeredTo();
expect(notOffered).toBe(emptyAddress);
});
test("asset should be able to accept offer", async () => {
const assetAddress = await iam.registerAsset();
const assetAddress = await rootOwnerIam.registerAsset();
const newOwner = new Keys();
await replenish(newOwner.getAddress());
const assetDID = `did:ethr:${assetAddress}`;
await iam.offerAsset({ assetDID, offerTo: `did:ethr:${newOwner.getAddress()}` });
await rootOwnerIam.offerAsset({ assetDID, offerTo: `did:ethr:${newOwner.getAddress()}` });
const newOwnerIAM = new IAM({
privateKey: newOwner.privateKey,
rpcUrl
rpcUrl,
});
await newOwnerIAM.initializeConnection();
await newOwnerIAM.initializeConnection({ initCacheServer: false, initDID: false });
await newOwnerIAM.acceptAssetOffer({
assetDID
});
Expand All @@ -63,49 +69,49 @@ export const assetsTests = () => {
});

test("asset should be able to reject offer", async () => {
const assetAddress = await iam.registerAsset();
const assetAddress = await rootOwnerIam.registerAsset();
const newOwner = new Keys();
await replenish(newOwner.getAddress());
const assetDID = `did:ethr:${assetAddress}`;
await iam.offerAsset({ assetDID, offerTo: `did:ethr:${newOwner.getAddress()}` });
await rootOwnerIam.offerAsset({ assetDID, offerTo: `did:ethr:${newOwner.getAddress()}` });
const newOwnerIAM = new IAM({
privateKey: newOwner.privateKey,
rpcUrl
});
await newOwnerIAM.initializeConnection();
await newOwnerIAM.initializeConnection({ initCacheServer: false, initDID: false });
await newOwnerIAM.rejectAssetOffer({
assetDID
});
const assetContract = OfferableIdentityFactory.connect(assetAddress, provider);
const owner = await assetContract.owner();
const offeredTo = await assetContract.offeredTo();
expect(owner).toBe(rootOwner.getAddress());
expect(owner).toBe(rootOwner.address);
expect(offeredTo).toBe(emptyAddress);
});

test("update did document for asset", async () => {
const assetAddress = await iam.registerAsset();
const assetAddress = await rootOwnerIam.registerAsset();

const asset1 = await iam.getDidDocument({ did: `did:${Methods.Erc1056}:${assetAddress}` });
const asset1 = await rootOwnerIam.getDidDocument({ did: `did:${Methods.Erc1056}:${assetAddress}` });
expect(asset1.publicKey.length).toBe(0);

const update = await iam.updateDidDocument({
const update = await rootOwnerIam.updateDidDocument({
didAttribute: DIDAttribute.PublicKey,
did: `did:ethr:${assetAddress}`,
data: {
algo: Algorithms.Secp256k1,
encoding: Encoding.HEX,
type: PubKeyType.SignatureAuthentication2018,
value: { tag: 'key-1', publicKey: `0x${new Keys().publicKey}` }
value: { tag: "key-1", publicKey: `0x${new Keys().publicKey}` }
}
});
expect(update).toBeTruthy();

const asset = await iam.getDidDocument({ did: `did:${Methods.Erc1056}:${assetAddress}` });
const asset = await rootOwnerIam.getDidDocument({ did: `did:${Methods.Erc1056}:${assetAddress}` });
expect(asset.publicKey.length).toBe(1);

const did = `did:${Methods.Erc1056}:${assetAddress}#key-1`;
const type = 'Secp256k1sigAuth';
const type = "Secp256k1sigAuth";
expect(asset.publicKey.find((asset) => asset.id === did && asset.type === type)).toBeTruthy();
});
};
Loading

0 comments on commit aaadb57

Please sign in to comment.