diff --git a/packages/composer-common/api.txt b/packages/composer-common/api.txt
index 56e1268541..ebf10a9182 100644
--- a/packages/composer-common/api.txt
+++ b/packages/composer-common/api.txt
@@ -54,6 +54,7 @@ class IdCard {
+ Object getConnectionProfile()
+ Object getCredentials()
+ Object getEnrollmentCredentials()
+ + String[] getRoles()
+ Promise fromArchive(Buffer)
}
class IllegalModelException extends BaseFileException {
diff --git a/packages/composer-common/changelog.txt b/packages/composer-common/changelog.txt
index 67bffc8e6a..5f60954df5 100644
--- a/packages/composer-common/changelog.txt
+++ b/packages/composer-common/changelog.txt
@@ -11,6 +11,9 @@
#
# Note that the latest public API is documented using JSDocs and is available in api.txt.
#
+Version 0.10.2 {e07efe48c4f431525388c10979b4289b} 2017-07-27
+- Added IdCard.getRoles function
+
Version 0.10.1 {d1fd512551ff5bb30b31f05f6817966e} 2017-07-24
- Added InvalidQueryException, BaseFileException
- Added IdCard to composer-common package
diff --git a/packages/composer-common/lib/idcard.js b/packages/composer-common/lib/idcard.js
index 43e8fac27c..78eb96bc18 100644
--- a/packages/composer-common/lib/idcard.js
+++ b/packages/composer-common/lib/idcard.js
@@ -96,7 +96,10 @@ class IdCard {
/**
* Credentials associated with this card, and which are used to connect to the associated business network.
- * @return {Object} credentials in the form { public: publicKey, private: privateKey }, if they exist.
+ *
+ * For PKI-based authentication, the credentials are expected to be of the form:
+ * { public: String, private: String }.
+ * @return {Object} credentials.
*/
getCredentials() {
return this.credentials;
@@ -105,8 +108,10 @@ class IdCard {
/**
* Enrollment credentials. If there are no credentials associated with this card, these credentials are used to
* enroll with a business network and obtain certificates.
- * @return {Object} enrollment credentials in the form { id: enrollmentId, secret: enrollmentSecret }, if
- * they exist.
+ *
+ * For an ID/secret enrollment scheme, the credentials are expected to be of the form:
+ * { id: String, secret: String }.
+ * @return {Object} enrollment credentials, if they exist.
*/
getEnrollmentCredentials() {
let result = null;
@@ -120,6 +125,19 @@ class IdCard {
return result;
}
+ /**
+ * Special roles for which this ID can be used, which can include:
+ *
+ * - peerAdmin
+ * - channelAdmin
+ * - issuer
+ *
+ * @return {String[]} roles.
+ */
+ getRoles() {
+ return this.metadata.roles || [ ];
+ }
+
/**
* Create an IdCard from a card archive.
* @param {Buffer} buffer - the Buffer to a zip archive
diff --git a/packages/composer-common/test/data/id-cards/valid-with-roles/connection.json b/packages/composer-common/test/data/id-cards/valid-with-roles/connection.json
new file mode 100644
index 0000000000..c77d5ec141
--- /dev/null
+++ b/packages/composer-common/test/data/id-cards/valid-with-roles/connection.json
@@ -0,0 +1,39 @@
+{
+ "name": "hlfv1",
+ "type": "hlfv1",
+ "orderers": [
+ {
+ "url": "grpcs://",
+ "cert": "orderer1.crt"
+ },
+ {
+ "url": "grpcs://",
+ "cert": "orderer2.crt"
+ }
+ ],
+ "ca": {
+ "url": "https://",
+ "name": "",
+ "trustedRoots": "",
+ "verify": true
+ },
+ "peers": [
+ {
+ "requestURL": "grpcs://",
+ "eventURL": "grpcs://",
+ "cert": "peer1.crt"
+ },
+ {
+ "requestURL": "grpcs://",
+ "eventURL": "grpcs://",
+ "cert": "peer2.crt"
+ }
+ ],
+ "keyValStore": "/YOUR_HOME_DIR/.composer-credentials",
+ "channel": "composerchannel",
+ "mspID": "Org1MSP",
+ "timeout": 300,
+ "globalcert": "",
+ "maxSendSize": 10,
+ "maxRecvSize": 15
+}
\ No newline at end of file
diff --git a/packages/composer-common/test/data/id-cards/valid-with-roles/credentials/private b/packages/composer-common/test/data/id-cards/valid-with-roles/credentials/private
new file mode 100644
index 0000000000..b35cc04c13
--- /dev/null
+++ b/packages/composer-common/test/data/id-cards/valid-with-roles/credentials/private
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg00IwLLBKoi/9ikb6
+ZOAV0S1XeNGWllvlFDeczRKQn2uhRANCAARrvCsQUNRpMUkzFaC7+zV4mClo+beg
+4VkUyQR5y5Fle5UVH2GigChWnUoouTO2e2acA/DUuyLDHT0emeBMhoMC
+-----END PRIVATE KEY-----
diff --git a/packages/composer-common/test/data/id-cards/valid-with-roles/credentials/public b/packages/composer-common/test/data/id-cards/valid-with-roles/credentials/public
new file mode 100644
index 0000000000..0038541cc4
--- /dev/null
+++ b/packages/composer-common/test/data/id-cards/valid-with-roles/credentials/public
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEa7wrEFDUaTFJMxWgu/s1eJgpaPm3
+oOFZFMkEecuRZXuVFR9hooAoVp1KKLkztntmnAPw1Lsiwx09HpngTIaDAg==
+-----END PUBLIC KEY-----
diff --git a/packages/composer-common/test/data/id-cards/valid-with-roles/metadata.json b/packages/composer-common/test/data/id-cards/valid-with-roles/metadata.json
new file mode 100644
index 0000000000..7d2b405457
--- /dev/null
+++ b/packages/composer-common/test/data/id-cards/valid-with-roles/metadata.json
@@ -0,0 +1,11 @@
+{
+ "name": "Conga",
+ "description": "A valid ID card",
+ "businessNetwork": "org-acme-biznet",
+ "image": "images/conga.png",
+ "roles": [
+ "peerAdmin",
+ "channelAdmin",
+ "issuer"
+ ]
+}
diff --git a/packages/composer-common/test/idcard.js b/packages/composer-common/test/idcard.js
index 7c65b61cf2..cb3805c734 100644
--- a/packages/composer-common/test/idcard.js
+++ b/packages/composer-common/test/idcard.js
@@ -121,14 +121,27 @@ describe('IdCard', function() {
});
});
- it('should load all metadata', function() {
+ it('should load name', function() {
return readIdCardAsync('valid').then((readBuffer) => {
return IdCard.fromArchive(readBuffer);
}).then((card) => {
card.getName().should.equal('Conga');
+ });
+ });
+
+ it('should load description', function() {
+ return readIdCardAsync('valid').then((readBuffer) => {
+ return IdCard.fromArchive(readBuffer);
+ }).then((card) => {
card.getDescription().should.equal('A valid ID card');
+ });
+ });
+
+ it('should load business network name', function() {
+ return readIdCardAsync('valid').then((readBuffer) => {
+ return IdCard.fromArchive(readBuffer);
+ }).then((card) => {
card.getBusinessNetworkName().should.equal('org-acme-biznet');
- should.not.exist(card.getEnrollmentCredentials());
});
});
@@ -136,7 +149,7 @@ describe('IdCard', function() {
return readIdCardAsync('minimal').then((readBuffer) => {
return IdCard.fromArchive(readBuffer);
}).then((card) => {
- card.getBusinessNetworkName().should.be.empty;
+ card.getBusinessNetworkName().should.be.a('String').that.is.empty;
});
});
@@ -144,7 +157,7 @@ describe('IdCard', function() {
return readIdCardAsync('minimal').then((readBuffer) => {
return IdCard.fromArchive(readBuffer);
}).then((card) => {
- card.getDescription().should.be.empty;
+ card.getDescription().should.be.a('String').that.is.empty;
});
});
@@ -152,7 +165,7 @@ describe('IdCard', function() {
return readIdCardAsync('valid').then((readBuffer) => {
return IdCard.fromArchive(readBuffer);
}).then((card) => {
- card.getConnectionProfile().should.be.an('Object');
+ card.getConnectionProfile().should.be.an('Object').that.includes({ name: 'hlfv1' });
});
});
@@ -166,6 +179,15 @@ describe('IdCard', function() {
});
});
+ it('should return empty credentials if none defined', function() {
+ return readIdCardAsync('minimal').then((readBuffer) => {
+ return IdCard.fromArchive(readBuffer);
+ }).then((card) => {
+ const credentials = card.getCredentials();
+ Object.keys(credentials).should.be.empty;
+ });
+ });
+
it('should load enrollment credentials', function() {
return readIdCardAsync('valid-with-enrollment').then((readBuffer) => {
return IdCard.fromArchive(readBuffer);
@@ -176,5 +198,31 @@ describe('IdCard', function() {
});
});
+ it('should return no enrollment credentials if none defined', function() {
+ return readIdCardAsync('valid').then((readBuffer) => {
+ return IdCard.fromArchive(readBuffer);
+ }).then((card) => {
+ should.not.exist(card.getEnrollmentCredentials());
+ });
+ });
+
+ it('should load roles', function() {
+ return readIdCardAsync('valid-with-roles').then((readBuffer) => {
+ return IdCard.fromArchive(readBuffer);
+ }).then((card) => {
+ const roles = card.getRoles();
+ roles.should.have.members(['peerAdmin', 'channelAdmin', 'issuer']);
+ });
+ });
+
+ it('should return empty roles if none defined', function() {
+ return readIdCardAsync('valid').then((readBuffer) => {
+ return IdCard.fromArchive(readBuffer);
+ }).then((card) => {
+ const roles = card.getRoles();
+ roles.should.be.empty;
+ });
+ });
+
});
});
\ No newline at end of file