Skip to content

Commit

Permalink
FABN-859 Add support for File System Wallet
Browse files Browse the repository at this point in the history
The extends the network package to add a File System Based
Wallet where identities are persisted to the file system

Change-Id: I1cffeb0bb2e9b4c043ac86a234a424ea49e17055
Signed-off-by: Dave Kelsey <d_kelsey@uk.ibm.com>
  • Loading branch information
Dave Kelsey committed Aug 22, 2018
1 parent b2416b3 commit cb591c5
Show file tree
Hide file tree
Showing 12 changed files with 626 additions and 39 deletions.
1 change: 1 addition & 0 deletions fabric-network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
module.exports.Network = require('./lib/network');
module.exports.InMemoryWallet = require('./lib/impl/wallet/inmemorywallet');
module.exports.X509WalletMixin = require('./lib/impl/wallet/x509walletmixin');
module.exports.FileSystemWallet = require('./lib/impl/wallet/filesystemwallet');
4 changes: 2 additions & 2 deletions fabric-network/lib/channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
'use strict';
const FabricConstants = require('fabric-client/lib/Constants');
const Contract = require('./contract');
const logger = require('./logger').getLogger('channel.js');
const logger = require('./logger').getLogger('FabricNetwork.Channel');
const util = require('util');

class Channel {
Expand Down Expand Up @@ -166,4 +166,4 @@ class Channel {

}

module.exports = Channel;
module.exports = Channel;
4 changes: 2 additions & 2 deletions fabric-network/lib/contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

'use strict';

const logger = require('./logger').getLogger('contract.js');
const logger = require('./logger').getLogger('Contract');
const util = require('util');

class Contract {
Expand Down Expand Up @@ -148,4 +148,4 @@ class Contract {
}
}

module.exports = Contract;
module.exports = Contract;
14 changes: 7 additions & 7 deletions fabric-network/lib/impl/wallet/basewallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
const Client = require('fabric-client');
const X509WalletMixin = require('./x509walletmixin');
const Wallet = require('../../api/wallet');
const logger = require('../../logger').getLogger('network.js');
const logger = require('../../logger').getLogger('BaseWallet');
const util = require('util');

class BaseWallet extends Wallet {

constructor(walletMixin = new X509WalletMixin()) {
super();
logger.debug(util.format('in BaseWallet constructor, mixin = %O', walletMixin));
logger.debug('in BaseWallet constructor, mixin = %O', walletMixin);
this.storesInitialized = false;
this.walletMixin = walletMixin;
}
Expand All @@ -35,7 +35,7 @@ class BaseWallet extends Wallet {
* @memberof Wallet
*/
async setUserContext(client, label) {
logger.debug(util.format('in setUserContext, label = %s', label));
logger.debug('in setUserContext, label = %s', label);

label = this.normalizeLabel(label);

Expand All @@ -53,7 +53,7 @@ class BaseWallet extends Wallet {
}

async configureClientStores(client, label) {
logger.debug(util.format('in configureClientStores, label = %s', label));
logger.debug('in configureClientStores, label = %s', label);

label = this.normalizeLabel(label);
if (!client) {
Expand Down Expand Up @@ -104,7 +104,7 @@ class BaseWallet extends Wallet {
//=========================================================

async import(label, identity) {
logger.debug(util.format('in import, label = %s', label));
logger.debug('in import, label = %s', label);

label = this.normalizeLabel(label);
const client = await this.configureClientStores(null, label);
Expand All @@ -117,7 +117,7 @@ class BaseWallet extends Wallet {
}

async export(label) {
logger.debug(util.format('in export, label = %s', label));
logger.debug('in export, label = %s', label);

label = this.normalizeLabel(label);
const client = await this.configureClientStores(null, label);
Expand Down Expand Up @@ -155,7 +155,7 @@ class BaseWallet extends Wallet {
}
}

logger.debug(util.format('list returns %j', idInfoList));
logger.debug('list returns %j', idInfoList);
return idInfoList;
}

Expand Down
167 changes: 167 additions & 0 deletions fabric-network/lib/impl/wallet/filesystemwallet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
/**
* Copyright 2018 IBM All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';

const Client = require('fabric-client');
const rimraf = require('rimraf');
const fs = require('fs-extra');
const Path = require('path');
const BaseWallet = require('./basewallet');
const FileKVS = require('fabric-client/lib/impl/FileKeyValueStore');
const logger = require('../../logger').getLogger('FileSystemWallet');

/**
* This class defines an implementation of an Identity wallet that persists
* to the file system.
*
* @class FileSystemWallet
* @see See {@link BaseWallet}
* @extends {BaseWallet}
*/
class FileSystemWallet extends BaseWallet {

/*
* create a new File Key Value Store
*
* @static
* @param {string} path the root path of the key value store
* @returns {Promise} a promise that is resolved when a new File KVS instance is recreated.
* @memberof FileSystemWallet
* @private
*/
static async _createFileKVS(path) {
return await new FileKVS({path});
}

/*
* check to see if the label defines a directory in the wallet
*
* @static
* @param {string} label
* @returns {Promise} a promise that returns true if this is a valid directory, false otherwise
* @memberof FileSystemWallet
* @private
*/
async _isDirectory(label) {
const method = '_isDirectory';
let isDir;
try {
const stat = await fs.lstat(Path.join(this.path, label));
isDir = stat.isDirectory();
} catch(err) {
isDir = false;
}
logger.debug('%s - return value: %s', method, isDir);
return isDir;
}

/**
* Creates an instance of FileSystemWallet.
* @param {string} path The root path for this wallet on the file system
* @param {WalletMixin} [mixin] optionally provide an alternative WalletMixin. Defaults to X509WalletMixin
* @memberof FileSystemWallet
*/
constructor(path, mixin) {
if (!path) {
throw new Error('No path for wallet has been provided');
}
super(mixin);
this.path = path;
}

/*
* Get the partitioned path for the provided label
*
* @param {string} label
* @returns {string} the partitioned path
* @memberof FileSystemWallet
* @private
*/
_getPartitionedPath(label) {
label = this.normalizeLabel(label);
const partitionedPath = Path.join(this.path, label);
return partitionedPath;
}

/**
* @inheritdoc
*/
async getStateStore(label) {
const partitionedPath = this._getPartitionedPath(label);
return FileSystemWallet._createFileKVS(partitionedPath);
}

/**
* @inheritdoc
*/
async getCryptoSuite(label) {
const partitionedPath = this._getPartitionedPath(label);
const cryptoSuite = Client.newCryptoSuite();
cryptoSuite.setCryptoKeyStore(Client.newCryptoKeyStore({path: partitionedPath}));
return cryptoSuite;
}

/**
* @inheritdoc
*/
async getAllLabels() {
let dirList;
const labelList = [];
try {
dirList = await fs.readdir(this.path);
} catch(err) {
return [];
}

if (dirList && dirList.length > 0) {
for (const label of dirList) {
const reallyExists = await this.exists(label);
if (reallyExists) {
labelList.push(label);
}
}
}
return labelList;
}

/**
* @inheritdoc
*/
async delete(label) {
const method = 'delete';
const reallyExists = await this.exists(label);
if (!reallyExists) {
return false;
}
const partitionedPath = this._getPartitionedPath(label);
const rmPromise = new Promise((resolve, reject) => {
rimraf(partitionedPath, (err) => {
if (err) {
logger.debug('%s - error returned trying to rm rf \'%s\': %s', method, partitionedPath, err);
reject(err);
}
resolve(true);
});
});
return await rmPromise;
}

/**
* @inheritdoc
*/
async exists(label) {
const method = 'exists';
let exists = false;
const isDir = await this._isDirectory(label);
if (isDir) {
exists = await fs.exists(Path.join(this._getPartitionedPath(label), label));
}
logger.debug('%s - label: %s, isDir: %s, exists: %s', method, label, isDir, exists);
return exists;
}
}

module.exports = FileSystemWallet;
20 changes: 12 additions & 8 deletions fabric-network/lib/impl/wallet/inmemorywallet.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
const Client = require('fabric-client');
const BaseWallet = require('./basewallet');
const api = require('fabric-client/lib/api.js');
const logger = require('../../logger').getLogger('network.js');
const logger = require('../../logger').getLogger('InMemoryWallet');
const util = require('util');

// this will be shared across all instance of a memory wallet, so really an app should
Expand All @@ -24,35 +24,39 @@ class InMemoryWallet extends BaseWallet {
}

async getStateStore(label) {
logger.debug(util.format('in getStateStore, label = %s', label));
logger.debug('in getStateStore, label = %s', label);
label = this.normalizeLabel(label);
const store = await new InMemoryKVS(label);
return store;
}

async getCryptoSuite(label) {
logger.debug(util.format('in getCryptoSuite, label = %s', label));
logger.debug('in getCryptoSuite, label = %s', label);
label = this.normalizeLabel(label);
const cryptoSuite = Client.newCryptoSuite();
cryptoSuite.setCryptoKeyStore(Client.newCryptoKeyStore(InMemoryKVS, label));
return cryptoSuite;
}

async delete(label) {
logger.debug(util.format('in delete, label = %s', label));
logger.debug('in delete, label = %s', label);
label = this.normalizeLabel(label);
memoryStore.delete(label);
if (memoryStore.has(label)) {
memoryStore.delete(label);
return true;
}
return false;
}

async exists(label) {
logger.debug(util.format('in exists, label = %s', label));
logger.debug('in exists, label = %s', label);
label = this.normalizeLabel(label);
return memoryStore.has(label);
}

async getAllLabels() {
const labels = Array.from(memoryStore.keys());
logger.debug(util.format('getAllLabels returns: %j', labels));
logger.debug('getAllLabels returns: %j', labels);
return labels;
}
}
Expand Down Expand Up @@ -93,4 +97,4 @@ class InMemoryKVS extends api.KeyValueStore {
}
}

module.exports = InMemoryWallet;
module.exports = InMemoryWallet;
10 changes: 5 additions & 5 deletions fabric-network/lib/impl/wallet/x509walletmixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

'use strict';

const logger = require('../../logger').getLogger('network.js');
const logger = require('../../logger').getLogger('X509WalletMixin');
const util = require('util');

class X509WalletMixin {
Expand All @@ -22,7 +22,7 @@ class X509WalletMixin {
}

async importIdentity(client, label, identity) {
logger.debug(util.format('in importIdentity, label = %s', label));
logger.debug('in importIdentity, label = %s', label);
// check identity type
const cryptoContent = {
signedCertPEM: identity.certificate,
Expand All @@ -38,7 +38,7 @@ class X509WalletMixin {
}

async exportIdentity(client, label) {
logger.debug(util.format('in exportIdentity, label = %s', label));
logger.debug('in exportIdentity, label = %s', label);
const user = await client.getUserContext(label, true);
let result = null;
if (user) {
Expand All @@ -52,7 +52,7 @@ class X509WalletMixin {
}

async getIdentityInfo(client, label) {
logger.debug(util.format('in getIdentityInfo, label = %s', label));
logger.debug('in getIdentityInfo, label = %s', label);
const user = await client.getUserContext(label, true);
let result = null;
if (user) {
Expand All @@ -66,4 +66,4 @@ class X509WalletMixin {
}
}

module.exports = X509WalletMixin;
module.exports = X509WalletMixin;
4 changes: 2 additions & 2 deletions fabric-network/lib/network.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

const Client = require('fabric-client');
const Channel = require('./channel');
const logger = require('./logger').getLogger('network.js');
const logger = require('./logger').getLogger('Network');

class Network {

Expand Down Expand Up @@ -142,4 +142,4 @@ class Network {
}


module.exports = Network;
module.exports = Network;
Loading

0 comments on commit cb591c5

Please sign in to comment.