Skip to content

Commit

Permalink
Cloudwallet Intergation (hyperledger-archives#3495)
Browse files Browse the repository at this point in the history
* prototype

Signed-off-by: Matthew B White <[email protected]>

* This is a preview implementation of the support for 'Cloud Wallets'.

Signed-off-by: Matthew B White <[email protected]>

* correct playground to return dummy wallet implementation

Signed-off-by: Matthew B White <[email protected]>

* review comments addressed

Signed-off-by: Matthew B White <[email protected]>
  • Loading branch information
mbwhite authored and Simon Stone committed Feb 28, 2018
1 parent b4331f7 commit db86ed1
Show file tree
Hide file tree
Showing 107 changed files with 2,815 additions and 901 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ packages/composer-runtime-hlfv1/vendor/gopkg.in/sourcemap.v1/
packages/composer-playground/e2e/downloads/

package-lock.json
packages/composer-tests-functional/storage
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,6 @@
"solutions"
],
"author": "Hyperledger Composer",
"license": "Apache-2.0"
}
"license": "Apache-2.0",
"dependencies": {}
}
11 changes: 7 additions & 4 deletions packages/composer-admin/lib/adminconnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
'use strict';

const ConnectionProfileManager = require('composer-common').ConnectionProfileManager;
const fs = require('fs');
const FileSystemCardStore = require('composer-common').FileSystemCardStore;
const NetworkCardStoreManager = require('composer-common').NetworkCardStoreManager;
const Logger = require('composer-common').Logger;
const Util = require('composer-common').Util;
const uuid = require('uuid');
Expand Down Expand Up @@ -60,7 +59,7 @@ class AdminConnection {
LOG.entry(method, options);
options = options || {};

this.cardStore = options.cardStore || new FileSystemCardStore({fs : options.fs || fs});
this.cardStore = options.cardStore || NetworkCardStoreManager.getCardStore(options.wallet);
this.connectionProfileManager = new ConnectionProfileManager();
this.connection = null;
this.securityContext = null;
Expand Down Expand Up @@ -94,6 +93,7 @@ class AdminConnection {
// if we have a certificate and optionally a privateKey we should ask the connection manager to import
let certificate = card.getCredentials().certificate;
let privateKey = card.getCredentials().privateKey;
connectionProfileData.wallet=this.cardStore.getWallet(name);
if (certificate){
return connectionManager.importIdentity(connectionProfileData.name, connectionProfileData, card.getUserName(), certificate, privateKey);
}
Expand Down Expand Up @@ -128,6 +128,7 @@ class AdminConnection {
connectionProfileData.cardName = cardName;
return this.connectionProfileManager.getConnectionManagerByType(connectionProfileData['x-type'])
.then((connectionManager) => {
connectionProfileData.wallet=this.cardStore.getWallet(cardName);
return connectionManager.exportIdentity(connectionProfileData.name, connectionProfileData, card.getUserName());
})
.then((result) => {
Expand Down Expand Up @@ -166,6 +167,7 @@ class AdminConnection {
connectionProfileData = card.getConnectionProfile();
cardUserName = card.getUserName();
connectionProfileData.cardName = name;
connectionProfileData.wallet=this.cardStore.getWallet(name);
return this.connectionProfileManager.getConnectionManagerByType(connectionProfileData['x-type']);
})
.then((connectionManager_) => {
Expand Down Expand Up @@ -235,7 +237,8 @@ class AdminConnection {
return this.connectionProfileManager.connectWithData(
card.getConnectionProfile(),
card.getBusinessNetworkName(),
{cardName : cardName});
{cardName : cardName,
wallet: this.cardStore.getWallet(cardName)});
})
.then((connection) => {
this.connection = connection;
Expand Down
4 changes: 3 additions & 1 deletion packages/composer-admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
},
"dependencies": {
"composer-common": "0.18.0",
"composer-connector-hlfv1": "0.18.0"
"composer-connector-hlfv1": "0.18.0",
"composer-wallet-filesystem": "0.18.0",
"composer-wallet-inmemory": "0.18.0"
},
"license-check-config": {
"src": [
Expand Down
112 changes: 62 additions & 50 deletions packages/composer-admin/test/adminconnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ const BusinessNetworkDefinition = require('composer-common').BusinessNetworkDefi
const Connection = require('composer-common').Connection;
const ConnectionManager = require('composer-common').ConnectionManager;
const Factory = require('composer-common').Factory;
const FileSystemCardStore = require('composer-common').FileSystemCardStore;
const IdCard = require('composer-common').IdCard;
const MemoryCardStore = require('composer-common').MemoryCardStore;
const NetworkCardStoreManager = require('composer-common').NetworkCardStoreManager;

const ModelManager = require('composer-common').ModelManager;
const SecurityContext = require('composer-common').SecurityContext;
const Util = require('composer-common').Util;
Expand All @@ -37,7 +37,7 @@ chai.use(require('chai-things'));
const sinon = require('sinon');

describe('AdminConnection', () => {
const testProfileName = 'TEST_PROFILE';
const testProfileName = 'profile';
let mockConnectionManager;
let mockConnection;
let mockSecurityContext;
Expand All @@ -46,9 +46,13 @@ describe('AdminConnection', () => {
let clock;
let cardStore;
let mockAdminIdCard;
let secretCard;
let credentialsCard;
let faultyCard;

const config =
{
name:testProfileName,
'x-type' : 'hlfv1'
};

Expand All @@ -75,11 +79,11 @@ describe('AdminConnection', () => {
mockConnection.list.resolves(['biznet1', 'biznet2']);

mockConnectionManager.connect.resolves(mockConnection);
cardStore = new MemoryCardStore();
const adminConnectionOptions = {
cardStore : cardStore
};

cardStore = NetworkCardStoreManager.getCardStore( { type : 'composer-wallet-inmemory' });
const adminConnectionOptions = { cardStore };
adminConnection = new AdminConnection(adminConnectionOptions);

adminConnection.securityContext = mockSecurityContext;
mockAdminIdCard = sinon.createStubInstance(IdCard);
mockAdminIdCard.getConnectionProfile.returns({name : 'profile', 'x-type' : 'test'});
Expand All @@ -90,6 +94,28 @@ describe('AdminConnection', () => {
delete process.env.COMPOSER_CONFIG;
sandbox = sinon.sandbox.create();
clock = sinon.useFakeTimers();
let faultyMetaData = { userName: 'fred',

description:'test'};

let minimalMetadata = { userName: 'fred',
businessNetwork:'network',
description:'test'};
let secretMetadata = { userName: 'fred',
businessNetwork:'network',
description:'test',
enrollmentSecret : 'password' };
let minimalConnectionProfile = config;
let validCredentials = {
certificate: 'cert',
privateKey: 'key'
};

secretCard = new IdCard(secretMetadata, minimalConnectionProfile);
faultyCard = new IdCard(faultyMetaData, minimalConnectionProfile);
credentialsCard = new IdCard(minimalMetadata, minimalConnectionProfile);
credentialsCard.setCredentials(validCredentials);

});

afterEach(() => {
Expand All @@ -110,44 +136,37 @@ describe('AdminConnection', () => {
adminConnection.cardStore.should.equal(cardStore);
});

it('should use FileSystemCardStore as default card store', function () {
const adminConnection = new AdminConnection();
adminConnection.cardStore.should.be.an.instanceOf(FileSystemCardStore);
});
});

describe('#connect', () => {
let cardStub;


beforeEach(() => {

sinon.spy(cardStore, 'get');
cardStub = sinon.createStubInstance(IdCard);
cardStub.getConnectionProfile.returns({});
cardStub.getUserName.returns('fred');
cardStub.getBusinessNetworkName.returns('network');
cardStub.getCredentials.returns({});
cardStub.getEnrollmentCredentials.returns({secret : 'password'});
cardStore.put('testCardname', cardStub);

sinon.stub(adminConnection.connectionProfileManager, 'connectWithData').resolves(mockConnection);
return cardStore.put('secretCardname', secretCard).then(()=>{
sinon.stub(adminConnection.connectionProfileManager, 'connectWithData').resolves(mockConnection);
return cardStore.put('testCardname', credentialsCard);
}).then(()=>{
return cardStore.put('faultyCardname', faultyCard);
});

});

it('should connect and login when card has secret', () => {
return adminConnection.connect('testCardname').then(() => {
return adminConnection.connect('secretCardname').then(() => {
sinon.assert.calledOnce(adminConnection.connectionProfileManager.connectWithData);
sinon.assert.calledWith(adminConnection.connectionProfileManager.connectWithData, {}, 'network');
sinon.assert.calledWith(adminConnection.connectionProfileManager.connectWithData, config, 'network',sinon.match({cardName : 'secretCardname'}));
sinon.assert.calledOnce(mockConnection.login);
sinon.assert.calledWith(mockConnection.login, 'fred', 'password');
});
});

it('should connect and login when card has certificates', () => {
cardStub.getCredentials.returns({certificate : 'cert', privateKey : 'key'});
cardStub.getEnrollmentCredentials.returns(null);

return adminConnection.connect('testCardname').then(() => {
sinon.assert.calledOnce(adminConnection.connectionProfileManager.connectWithData);
sinon.assert.calledWith(adminConnection.connectionProfileManager.connectWithData, {}, 'network');
sinon.assert.calledWith(adminConnection.connectionProfileManager.connectWithData, config, 'network',sinon.match({cardName : 'testCardname'}));
sinon.assert.calledOnce(mockConnection.login);
sinon.assert.calledWith(mockConnection.login, 'fred', 'na');
});
Expand All @@ -161,28 +180,24 @@ describe('AdminConnection', () => {
});

it('should not ping if card does not contain business network name', () => {
cardStub.getBusinessNetworkName.returns('');

return adminConnection.connect('testCardname').then(() => {
return adminConnection.connect('faultyCardname').then(() => {
sinon.assert.notCalled(mockConnection.ping);
});
});
});

describe('#disconnect', () => {
let cardStub;


beforeEach(() => {
sinon.spy(cardStore, 'get');
cardStub = sinon.createStubInstance(IdCard);
cardStub.getConnectionProfile.returns({});
cardStub.getUserName.returns('fred');
cardStub.getBusinessNetworkName.returns('network');
cardStub.getCredentials.returns({});
cardStub.getEnrollmentCredentials.returns({secret : 'password'});
cardStore.put('testCardname', cardStub);

sinon.stub(adminConnection.connectionProfileManager, 'connectWithData').resolves(mockConnection);
return cardStore.put('secretCardname', secretCard).then(()=>{
sinon.stub(adminConnection.connectionProfileManager, 'connectWithData').resolves(mockConnection);
return cardStore.put('testCardname', credentialsCard);
}).then(()=>{
return cardStore.put('faultyCardname', faultyCard);
});

});

it('should set connection and security context to null if connection is set', () => {
Expand Down Expand Up @@ -571,15 +586,12 @@ describe('AdminConnection', () => {
beforeEach(() => {
adminConnection.connection = mockConnection;
adminConnection.securityContext = mockSecurityContext;
let cardStub = sinon.createStubInstance(IdCard);
let cp = config;
cp.name = testProfileName;
cardStub.getConnectionProfile.returns(cp);
cardStub.getUserName.returns('fred');
cardStub.getBusinessNetworkName.returns('network');
cardStub.getCredentials.returns({});
cardStub.getEnrollmentCredentials.returns({secret : 'password'});
cardStore.put('testCardname', cardStub);
return cardStore.put('secretCardname', secretCard).then(()=>{
sinon.stub(adminConnection.connectionProfileManager, 'connectWithData').resolves(mockConnection);
return cardStore.put('testCardname', credentialsCard);
}).then(()=>{
return cardStore.put('faultyCardname', faultyCard);
});
});

it('should be able to request an identity', () => {
Expand Down Expand Up @@ -608,7 +620,7 @@ describe('AdminConnection', () => {
enrollId : 'fred'
});

return adminConnection.requestIdentity('testCardname')
return adminConnection.requestIdentity('secretCardname')
.then(() => {
sinon.assert.calledOnce(mockConnectionManager.requestIdentity);
sinon.assert.calledWith(mockConnectionManager.requestIdentity, testProfileName, config, 'fred', 'password');
Expand Down Expand Up @@ -1052,7 +1064,7 @@ describe('AdminConnection', () => {
return adminConnection.importCard(cardName, userCard)
.then((updated) => {
sinon.assert.calledOnce(mockConnectionManager.removeIdentity);
sinon.assert.calledWith(mockConnectionManager.removeIdentity, 'connectionName', expectedConnection, 'user');
sinon.assert.calledWith(mockConnectionManager.removeIdentity, 'connectionName', sinon.match(expectedConnection), 'user');
updated.should.be.true;
return cardStore.get(cardName).should.eventually.deep.equal(userCard);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/composer-cli/lib/cmds/utils/cmdutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ class CmdUtil {
*/
static log(){
Array.from(arguments).forEach((s)=>{
// eslint-disable-next-line no-console
console.log(s);
});

}

/**
Expand Down Expand Up @@ -177,7 +177,7 @@ class CmdUtil {

// Not enough certificate files or enrollment secrets!
else {
console.log(JSON.stringify(argv, null, 4));
CmdUtil.log(JSON.stringify(argv, null, 4));
throw new Error('You must specify certificate files or enrollment secrets for all network administrators');
}

Expand Down
2 changes: 2 additions & 0 deletions packages/composer-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
"composer-client": "0.18.0",
"composer-common": "0.18.0",
"composer-report": "0.18.0",
"composer-wallet-filesystem": "0.18.0",
"composer-wallet-inmemory": "0.18.0",
"homedir": "0.6.0",
"js-yaml": "3.10.0",
"mkdirp": "0.5.1",
Expand Down
7 changes: 6 additions & 1 deletion packages/composer-cli/test/utils/cmdutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,18 @@ describe('composer transaction cmdutils unit tests', () => {
const pem3 = '-----BEGIN CERTIFICATE-----\nsuch admin3\n-----END CERTIFICATE-----\n';

let sandbox;
let fsStub;

beforeEach(() => {
sandbox = sinon.sandbox.create();
sandbox.stub(fs, 'readFileSync');
fsStub = sandbox.stub(fs, 'readFileSync');
fs.readFileSync.withArgs('admin1.pem').returns(pem1);
fs.readFileSync.withArgs('admin2.pem').returns(pem2);
fs.readFileSync.withArgs('admin3.pem').returns(pem3);
});



afterEach(() => {
sandbox.restore();
});
Expand Down Expand Up @@ -343,6 +346,7 @@ describe('composer transaction cmdutils unit tests', () => {
describe('#createAdminConnection', () => {

it('should create a new admin connection', () => {
fsStub.restore();
CmdUtil.createAdminConnection().should.be.an.instanceOf(AdminConnection);
});

Expand All @@ -351,6 +355,7 @@ describe('composer transaction cmdutils unit tests', () => {
describe('#createBusinessNetworkConnection', () => {

it('should create a new business network connection', () => {
fsStub.restore();
CmdUtil.createBusinessNetworkConnection().should.be.an.instanceOf(BusinessNetworkConnection);
});

Expand Down
9 changes: 5 additions & 4 deletions packages/composer-client/lib/businessnetworkconnection.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ const AssetRegistry = require('./assetregistry');
const BusinessNetworkDefinition = require('composer-common').BusinessNetworkDefinition;
const ConnectionProfileManager = require('composer-common').ConnectionProfileManager;
const EventEmitter = require('events');
const fs = require('fs');
const Historian = require('./historian');
const IdentityRegistry = require('./identityregistry');
const Logger = require('composer-common').Logger;
Expand All @@ -31,7 +30,7 @@ const TransactionRegistry = require('./transactionregistry');
const Util = require('composer-common').Util;
const uuid = require('uuid');
const Registry = require('./registry');
const FileSystemCardStore = require('composer-common').FileSystemCardStore;
const NetworkCardStoreManager = require('composer-common').NetworkCardStoreManager;
const LOG = Logger.getLog('BusinessNetworkConnection');

/**
Expand All @@ -55,8 +54,7 @@ class BusinessNetworkConnection extends EventEmitter {
LOG.entry(method, options);
options = options || {};

this.cardStore = options.cardStore || new FileSystemCardStore({fs : options.fs || fs});

this.cardStore = options.cardStore || NetworkCardStoreManager.getCardStore();
this.connectionProfileManager = new ConnectionProfileManager();
this.connection = null;
this.securityContext = null;
Expand Down Expand Up @@ -399,6 +397,9 @@ class BusinessNetworkConnection extends EventEmitter {
if (!additionalConnectOptions) {
additionalConnectOptions = {};
}

// need to get from the cardstore, a wallet that uses the same backing store
additionalConnectOptions.wallet = this.cardStore.getWallet(cardName);
additionalConnectOptions.cardName = cardName;
return this.connectionProfileManager.connectWithData(this.card.getConnectionProfile(), this.card.getBusinessNetworkName(), additionalConnectOptions);
})
Expand Down
Loading

0 comments on commit db86ed1

Please sign in to comment.