diff --git a/packages/letters-of-credit-network/README.md b/packages/letters-of-credit-network/README.md index 0a78346..60ff135 100644 --- a/packages/letters-of-credit-network/README.md +++ b/packages/letters-of-credit-network/README.md @@ -44,17 +44,17 @@ Navigate to the **Test** tab and then submit a `CreateDemoParticipants` transact ``` { - "$class": "org.acme.loc.CreateDemoParticipants" + "$class": "org.example.loc.CreateDemoParticipants" } ``` Navigate to the ID registry and generate IDs for: ``` -org.acme.loc.Customer#alice -org.acme.loc.Customer#bob -org.acme.loc.BankEmployee#matias -org.acme.loc.BankEmployee#ella +org.example.loc.Customer#alice +org.example.loc.Customer#bob +org.example.loc.BankEmployee#matias +org.example.loc.BankEmployee#ella ``` Select to Alice to be your identity. @@ -67,10 +67,10 @@ Navigate to the **Test** tab and then submit an `InitialApplication` transaction ``` { - "$class": "org.acme.loc.InitialApplication", + "$class": "org.example.loc.InitialApplication", "letterId": "LETTER-REF-123", - "applicant": "resource:org.acme.loc.Customer#alice", - "beneficiary": "resource:org.acme.loc.Customer#bob", + "applicant": "resource:org.example.loc.Customer#alice", + "beneficiary": "resource:org.example.loc.Customer#bob", "rules": [ { "ruleId": "LETTER-REF-123-RULE-1", @@ -82,7 +82,7 @@ Navigate to the **Test** tab and then submit an `InitialApplication` transaction } ], "productDetails": { - "$class": "org.acme.loc.ProductDetails", + "$class": "org.example.loc.ProductDetails", "productType": "Computers", "quantity": 100, "pricePerUnit": 450 @@ -102,8 +102,8 @@ Submit a `SuggestChanges` transaction to change the rules: ``` { - "$class": "org.acme.loc.SuggestChanges", - "loc": "resource:org.acme.loc.LetterOfCredit#4572", + "$class": "org.example.loc.SuggestChanges", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123", "rules": [ { "ruleId": "LETTER-REF-123-RULE-1", @@ -114,7 +114,7 @@ Submit a `SuggestChanges` transaction to change the rules: "ruleText": "The computers will be received within 15 days" } ], - "suggestingParty": "resource:org.acme.loc.BankEmployee#matias" + "suggestingParty": "resource:org.example.loc.BankEmployee#matias" } ``` @@ -126,13 +126,13 @@ Use the ID registry to select Alice to be your identity. Review the changes made to the letter of credit by selecting the `LetterOfCredit` asset. Alice agrees with the changes and decides she will approve. -Approve the letter by submitting an `ApproveTransaction`: +Approve the letter by submitting an `Approve` transaction: ``` { - "$class": "org.acme.loc.Approve", - "loc": "resource:org.acme.loc.LetterOfCredit#LETTER-REF-123", - "approvingParty": "resource:org.acme.loc.Customer#alice" + "$class": "org.example.loc.Approve", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123", + "approvingParty": "resource:org.example.loc.Customer#alice" } ``` @@ -140,17 +140,19 @@ This transaction adds Alice to the array of parties in the `approval` field of t --- -Use the ID registry to select Ella to be your identity. +Use the ID registry to select Ella to be your identity. + +**NOTE:** Alice doesn't have permission to see Ella and therefore you must switch via admin first. Ella works at Bob's bank. Review the letter of credit by selecting the `LetterOfCredit` asset. Ella decides that the letter of credit is acceptable to her bank and that she will approve the request. -Approve the letter by submitting an `ApproveTransaction`: +Approve the letter by submitting an `Approve` transaction: ``` { - "$class": "org.acme.loc.Approve", - "loc": "resource:org.acme.loc.LetterOfCredit#LETTER-REF-123", - "approvingParty": "resource:org.acme.loc.BankEmployee#ella" + "$class": "org.example.loc.Approve", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123", + "approvingParty": "resource:org.example.loc.BankEmployee#ella" } ``` @@ -162,26 +164,26 @@ Use the ID registry to select Bob to be your identity. Bob reviews the letter of credit to ensure that it matches with his and Alice's agreement. He notices that the rules don't quite match the agreement however he still decides to accept the letter of credit and go through with the deal. -Approve the letter by submitting an `ApproveTransaction`: +Approve the letter by submitting an `Approve` transaction: ``` { - "$class": "org.acme.loc.Approve", - "loc": "resource:org.acme.loc.LetterOfCredit#LETTER-REF-123", - "approvingParty": "resource:org.acme.loc.Customer#bob" + "$class": "org.example.loc.Approve", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123", + "approvingParty": "resource:org.example.loc.Customer#bob" } ``` This transaction adds Bob to the array of parties in the `approval` field of the `LetterOfCredit` asset. As now all the parties have submitted their approval the `status` field is also updated to be `APPROVED`. At this point no participant may reject or suggest changes to the letter. Further participants (e.g. other bank employees) are also blocked from adding their approval. -Bob manufactures the computers and gives ships them. He updates the `LetterOfCredit` asset to add proof that he has shipped the goods. +Bob manufactures the computers and ships them. He updates the `LetterOfCredit` asset to add proof that he has shipped the goods. Submit a `ShipProduct` transaction: ``` { - "$class": "org.acme.loc.ShipProduct", - "loc": "resource:org.acme.loc.LetterOfCredit#LETTER-REF-123", + "$class": "org.example.loc.ShipProduct", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123", "evidence": "337478411cab754ce47fcaa72ec1d0f6" } ``` @@ -198,8 +200,8 @@ Submit a `ReceiveProduct` transaction: ``` { - "$class": "org.acme.loc.ReceiveProduct", - "loc": "resource:org.acme.loc.LetterOfCredit#LETTER-REF-123" + "$class": "org.example.loc.ReceiveProduct", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123" } ``` @@ -215,8 +217,8 @@ Submit a `ReadyForPayment` transaction: ``` { - "$class": "org.acme.loc.ReadyForPayment", - "loc": "resource:org.acme.loc.LetterOfCredit#LETTER-REF-123" + "$class": "org.example.loc.ReadyForPayment", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123" } ``` @@ -226,18 +228,23 @@ This transaction updates the `status` of the letter of credit to be `READY_FOR_P Use the ID registry to select Ella to be your identity. +**NOTE:** Matias doesn't have permission to see Ella and therefore you must switch via admin first. + Ella having received the funds from Alice's bank can close the letter of credit and deposit the funds in Bob's bank account. Submit a `Close` transaction: ``` { - "$class": "org.acme.loc.Close", - "loc": "resource:org.acme.loc.LetterOfCredit#LETTER-REF-123", + "$class": "org.example.loc.Close", + "loc": "resource:org.example.loc.LetterOfCredit#LETTER-REF-123", "closeReason": "Payment made" } ``` This transaction updates the `status` of the letter to be `CLOSED`. The letter is now complete and no further transactions can take place. -This business network has been used to create demo application that simulate the scenario above. You can find more detail on these at https://github.com/hyperledger/composer-sample-applications/tree/master/packages/letters-of-credit \ No newline at end of file +This business network has been used to create demo application that simulate the scenario above. You can find more detail on these at https://github.com/hyperledger/composer-sample-applications/tree/master/packages/letters-of-credit + +## License +Hyperledger Project source code files are made available under the Apache License, Version 2.0 (Apache-2.0), located in the LICENSE file. Hyperledger Project documentation files are made available under the Creative Commons Attribution 4.0 International License (CC-BY-4.0), available at http://creativecommons.org/licenses/by/4.0/. \ No newline at end of file diff --git a/packages/letters-of-credit-network/lib/logic.js b/packages/letters-of-credit-network/lib/logic.js index 929d985..cf013c6 100644 --- a/packages/letters-of-credit-network/lib/logic.js +++ b/packages/letters-of-credit-network/lib/logic.js @@ -1,11 +1,27 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + 'use strict'; +/* global getFactory getAssetRegistry getParticipantRegistry emit */ + /** * Create the LOC asset * @param {org.example.loc.InitialApplication} initalAppliation - the InitialApplication transaction * @transaction */ -async function initialApplication(application) { +async function initialApplication(application) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -35,7 +51,7 @@ async function initialApplication(application) { * @param {org.example.loc.Approve} approve - the Approve transaction * @transaction */ -async function approve(approveRequest) { +async function approve(approveRequest) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -49,7 +65,13 @@ async function approve(approveRequest) { throw new Error ('This person has already approved this letter of credit'); } else if (approveRequest.approvingParty.getType() === 'BankEmployee') { letter.approval.forEach((approvingParty) => { - if (approvingParty.getType() === 'BankEmployee' && approvingParty.bank.getIdentifier() === approveRequest.approvingParty.bank.getIdentifier()) { + let bankApproved = false; + try { + bankApproved = approvingParty.getType() === 'BankEmployee' && approvingParty.bank.getIdentifier() === approveRequest.approvingParty.bank.getIdentifier(); + } catch (err) { + // ignore error as they don't have rights to access that participant + } + if (bankApproved) { throw new Error('Your bank has already approved of this request'); } }); @@ -77,7 +99,7 @@ async function approve(approveRequest) { * @param {org.example.loc.Reject} reject - the Reject transaction * @transaction */ -async function reject(rejectRequest) { +async function reject(rejectRequest) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -86,7 +108,7 @@ async function reject(rejectRequest) { if (letter.status === 'CLOSED' || letter.status === 'REJECTED') { throw new Error('This letter of credit has already been closed'); } else if (letter.status === 'APPROVED') { - throw new Error('This letter of credit has already been approved'); + throw new Error('This letter of credit has already been approved'); } else { letter.status = 'REJECTED'; letter.closeReason = rejectRequest.closeReason; @@ -108,7 +130,7 @@ async function reject(rejectRequest) { * @param {org.example.loc.SuggestChanges} suggestChanges - the SuggestChanges transaction * @transaction */ -async function suggestChanges(changeRequest) { +async function suggestChanges(changeRequest) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -117,7 +139,7 @@ async function suggestChanges(changeRequest) { if (letter.status === 'CLOSED' || letter.status === 'REJECTED') { throw new Error ('This letter of credit has already been closed'); } else if (letter.status === 'APPROVED') { - throw new Error('This letter of credit has already been approved'); + throw new Error('This letter of credit has already been approved'); } else if (letter.status === 'SHIPPED' || letter.status === 'RECEIVED' || letter.status === 'READY_FOR_PAYMENT') { throw new Error ('The product has already been shipped'); } else { @@ -144,7 +166,7 @@ async function suggestChanges(changeRequest) { * @param {org.example.loc.ShipProduct} shipProduct - the ShipProduct transaction * @transaction */ -async function shipProduct(shipRequest) { +async function shipProduct(shipRequest) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -176,7 +198,7 @@ async function shipProduct(shipRequest) { * @param {org.example.loc.ReceiveProduct} receiveProduct - the ReceiveProduct transaction * @transaction */ -async function receiveProduct(receiveRequest) { +async function receiveProduct(receiveRequest) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -208,7 +230,7 @@ async function receiveProduct(receiveRequest) { * @param {org.example.loc.ReadyForPayment} readyForPayment - the ReadyForPayment transaction * @transaction */ -async function readyForPayment(paymentRequest) { +async function readyForPayment(paymentRequest) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -239,7 +261,7 @@ async function readyForPayment(paymentRequest) { * @param {org.example.loc.Close} close - the Close transaction * @transaction */ -async function close(closeRequest) { +async function close(closeRequest) { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; @@ -270,7 +292,7 @@ async function close(closeRequest) { * @param {org.example.loc.CreateDemoParticipants} createDemoParticipants - the CreateDemoParticipants transaction * @transaction */ -async function createDemoParticipants() { +async function createDemoParticipants() { // eslint-disable-line no-unused-vars const factory = getFactory(); const namespace = 'org.example.loc'; diff --git a/packages/letters-of-credit-network/models/org.acme.loc.cto b/packages/letters-of-credit-network/models/org.example.loc.cto similarity index 80% rename from packages/letters-of-credit-network/models/org.acme.loc.cto rename to packages/letters-of-credit-network/models/org.example.loc.cto index 804c2c1..2b4b0aa 100644 --- a/packages/letters-of-credit-network/models/org.acme.loc.cto +++ b/packages/letters-of-credit-network/models/org.example.loc.cto @@ -1,7 +1,17 @@ -/** - * New model file +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - + namespace org.example.loc // ENUMS diff --git a/packages/letters-of-credit-network/package.json b/packages/letters-of-credit-network/package.json index ded23cd..da530f2 100644 --- a/packages/letters-of-credit-network/package.json +++ b/packages/letters-of-credit-network/package.json @@ -10,9 +10,18 @@ "scripts": { "prepublish": "mkdirp ./dist && composer archive create --sourceType dir --sourceName . -a ./dist/letters-of-credit-network.bna", "lint": "eslint .", + "postlint": "npm run licchk", + "licchk": "license-check-and-add", + "pretest": "npm run lint", "test": "mocha -t 0 --recursive", "test-cover": "nyc npm run test" }, + "keywords": [ + "letter", + "credit", + "composer", + "composer-network" + ], "repository": { "type": "git", "url": "https://github.com/hyperledger/composer-sample-networks.git" @@ -31,10 +40,39 @@ "eslint": "^3.6.1", "istanbul": "^0.4.5", "jsdoc": "^3.5.5", - "license-check-and-add": "~2.3.1", + "license-check-and-add": "~2.3.0", "mkdirp": "^0.5.1", "mocha": "^3.2.0", "moment": "^2.17.1", "nyc": "^11.0.2" + }, + "license-check-and-add-config": { + "folder": ".", + "license": "LICENSE.txt", + "exact_paths_method": "EXCLUDE", + "exact_paths": [ + "composer-logs", + "dist", + "node_modules", + "out", + ".git" + ], + "file_type_method": "EXCLUDE", + "file_types": [ + ".yml" + ], + "insert_license": false, + "license_formats": { + "js|cto|acl|qry": { + "prepend": "/*", + "append": " */", + "eachLine": { + "prepend": " * " + } + }, + "md": { + "file": "../../markdown-license.txt" + } + } } } diff --git a/packages/letters-of-credit-network/permissions.acl b/packages/letters-of-credit-network/permissions.acl index 81ee2d1..f035358 100644 --- a/packages/letters-of-credit-network/permissions.acl +++ b/packages/letters-of-credit-network/permissions.acl @@ -1,3 +1,17 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + rule ParticipantsSeeSelves { description: "Let participants see themselves" participant(p): "org.hyperledger.composer.system.Participant" @@ -7,6 +21,14 @@ rule ParticipantsSeeSelves { action: ALLOW } +rule ParticipantsSeeBanks { + description: "Let participants see themselves" + participant: "org.hyperledger.composer.system.Participant" + operation: READ + resource: "org.example.loc.Bank" + action: ALLOW +} + rule SeeOtherCustomers { description: "Let Customers see other Customers" participant: "org.example.loc.Customer" @@ -33,6 +55,15 @@ rule BankEmployeeSeeCustomer { action: ALLOW } +rule BankEmployeeSeeBankEmployee { + description: "Let BankEmployees see their colleagues" + participant(p): "org.example.loc.BankEmployee" + operation: READ + resource(r): "org.example.loc.BankEmployee" + condition: (r.bank.getIdentifier() == p.bank.getIdentifier()) + action: ALLOW +} + rule CustomerMakeApplication { description: "All customers can submit an InitialApplication transaction" participant: "org.example.loc.Customer" @@ -107,7 +138,7 @@ rule BankEmployeeAddApproval { action: ALLOW } -rule CustomerSuggestChanges { +rule CustomerSubmitSuggestChanges { description: "All customers can submit a SuggestChanges transaction to a Letter of Credit they are involved with" participant(p): "org.example.loc.Customer" operation: CREATE @@ -116,15 +147,35 @@ rule CustomerSuggestChanges { action: ALLOW } -rule BankEmployeeSuggestChanges { +rule BankEmployeeSubmitSuggestChanges { description: "All bank employees can submit a SuggestChanges transaction to a Letter of Credit their bank is involved with" - participant(p): "org.example.loc.Customer" + participant(p): "org.example.loc.BankEmployee" operation: CREATE resource(r): "org.example.loc.SuggestChanges" condition: (p.bank.getIdentifier() === r.loc.issuingBank.getIdentifier() || p.bank.getIdentifier() === r.loc.exportingBank.getIdentifier()) action: ALLOW } +rule CustomerSuggestChanges { + description: "All customers can submit a SuggestChanges transaction to a Letter of Credit they are involved with" + participant(p): "org.example.loc.Customer" + operation: UPDATE + resource(r): "org.example.loc.LetterOfCredit" + transaction(t): "org.example.loc.SuggestChanges" + condition: (p.getIdentifier() === r.applicant.getIdentifier() || p.getIdentifier() === r.beneficiary.getIdentifier()) + action: ALLOW +} + +rule BankEmployeeSuggestChanges { + description: "All bank employee can add their approval to a Letter of Credit their bank is involved with" + participant(p): "org.example.loc.BankEmployee" + operation: UPDATE + resource(r): "org.example.loc.LetterOfCredit" + transaction(t): "org.example.loc.SuggestChanges" + condition: (p.bank.getIdentifier() === r.issuingBank.getIdentifier() || p.bank.getIdentifier() === r.exportingBank.getIdentifier()) + action: ALLOW +} + rule CustomerAddChanges { description: "All customers can update a LetterOfCredit with their suggested rules if they are involved in it" participant(p): "org.example.loc.Customer" diff --git a/packages/letters-of-credit-network/test/script.js b/packages/letters-of-credit-network/test/script.js index 70454f1..21d1375 100644 --- a/packages/letters-of-credit-network/test/script.js +++ b/packages/letters-of-credit-network/test/script.js @@ -1,3 +1,17 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + 'use strict'; const AdminConnection = require('composer-admin').AdminConnection;