I am developing a blockchain application using Hyperledger Composer.
This is a part of my model i.e. .cto file:
concept Address{
o String addressId
o String PersonInChargeFullName
o String title
o String address1
o String address2 optional
o String city
o String country
o String zipcode regex=/^\d{5}$/
o String phone regex=/^\s*(?:\+?(\d{1,3}))?[-. (]*(\d{3})[-. )]*(\d{3})[-. ]*(\d{4})(?: *x(\d+))?\s*$/
o String email regex=/^([a-zA-Z0-9_\-\.]+)#([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/
o Boolean isActive default=true
}
abstract participant Company identified by companyId{
o String companyId
o String companyName
o Address defaultAddress
}
participant OEM extends Company {
o Address[] plants
}
From this page, I understand that if we use optional as a field validator, which means that that field is optional, and others are not. Am I right?
Although, I have not made PersonInChargeFullName as optional, when I submit the data (for eg: "PersonInChargeFullName": "",) from composer-rest-server API, the transaction gets processed, without any error.
Please advise.
Here option is little bit of different concept try running your code without PersonInChargeFullName field not as PersonInChargeFullName = "" but don't include it in json input i am pretty sure you will get error.
Related
I am trying to create a chain which holds a document.
I have created the asset in the model file as
asset document identified by documentid {
o String documentid
o String formImageBase64 //will use IPFS Later
o String nameOfSignator
o String addressOfSignator
o Integer ageOfSignator
o Boolean isSigned
o DateTime dateTimeOfSigning
}
And there are multiple documents containing information of different people.
If the document is updated(new asset is created), How to show a link between the old document and the updated document.
Update
Changing Title from "Creating Application Form using Hyperledger Composer"
To "Chaining/Connecting updated assets in Hyperledger Composer"
I don't know what type of relation you want to show between the past documents and the new documents but if you want to show the historical information of the transactions then you can use HistorianRecord
On the New Updating document, I added a new string which contains the unique "document of the previous string. Making it kind of a singly linked list.
asset document identified by documentid {
o String documentID
o String previousDocumentID // optional(later) original document "0" for now
o String formImageBase64 //will use IPFS Later
o String nameOfSignator
o String addressOfSignator
o Integer ageOfSignator
o Boolean isSigned
o DateTime dateTimeOfSigning
}
This way I can chain documents together.
I am grabbing the resource of particular asset from registry by something like this:-
var flight = factory.newResource(Namespace,'Aircraft',flightId);
To this resource, i am assigning a relationship by :-
flight.aircraft = factory.newRelationship('org.acme.airline.aircraft','Aircraft',aircraftId);
flight.aircraft.firstClassSeats = 10;
flight.aircraft.secondClassSeats = 10;
This relationship contains the following properties as defined in model file :
asset Aircraft identified by aircraftId {
o String aircraftId
// Number of seats per class
o Integer firstClassSeats default = 0
o Integer businessClassSeats default = 0
o Integer economyClassSeats default = 0
}
Flight Data :
asset Flight identified by flightId {
o String flightId regex=/[A-Z][A-Z][0-9][0-9][0-9]-[0-9][0-9]-[0-3][0-9]-[0-9][0-9]/
o String flightNumber
o Route route
o String[] aliasFlightNumber optional
--> Aircraft aircraft optional
}
Now, how to update these relationship values (for example firstClassSeats) of a particular flight resource and update it to the corresponding registry.
My model is as follows
abstract concept Address {
o String street
o String zip
o String city
o String country
}
participant Actor identified by userId {
o String userId
o String firstName
o String name
o Address address
}
When I POST a new Actor in composer rest server, I get the following error
"Cannot instantiate Abstract Type Address in namespace
io.mydomain.myapp",
What am I missing out on here ?
Abstract types are not meant to be instantiated so no wonder that it can't be created.
Read: https://hyperledger.github.io/composer/latest/reference/cto_language
Specifically this quote is of interest:
An optional 'abstract' declaration, to indicate that this type cannot
be created. Abstract resources can be used as a basis for other
classes to extend. Extensions of abstract classes do not inherit the
abstract status. For example, the asset Vehicle defined above should
never be created, as there should be more specific asset classes
defined to extend it.
Consider the Concepts subheading of the docs.
TL;DR: Read the documentation.
I have made a query in Hyperledger Composer where in the query tries to search for all invoices of a borrower. The borrower is a participant of the invoice asset:
asset Invoice identified by invoiceId {
o String invoiceId
o String invoiceRef optional
o DateTime dateCreated
o String type
o DateTime invoiceOrPurchaseDate optional
o Double amount
o DateTime invoiceDueDate optional
o String paymentStatus optional
o Boolean overdue
o Double outstandingBalance
--> Participant borrower
--> Participant lender
}
I need a query that will return all invoices of a borrower and I did this in Hyperledger composer by coding below:
query QInvoiceByBorrower {
description: "Select invoice by borrower"
statement:
SELECT org.n.blockchaindemo.Invoice
WHERE (_$borrower == borrower)
}
But when I try to call the query through REST API, I get [] empty result as below:
http://10.10.4.244:3000/api/queries/QInvoiceByBorrower?borrower=resource:org.n.blockchaindemo.User#1381991
May I know how to create a query that will search using a foreign relation in Hyperledger Composer?
In you Invoice definition you need to refer to your specific Participant type i.e. User rather that the system type Participant. So the last part of your Invoice will be:
o Double outstandingBalance
--> User borrower
--> User lender
}
With this change your Query should work. A useful diagnostic method is to create a duplicate query without the where clause and then examine the returned data to help understand the parameters to use for a query.
(By using Participant I think your asset will include the first participant type in your model at the time the asset type was first used - this sounds like it could generate some unexpected behaviours, so specifying the actual participant type makes sense.)
Instead of giving full update access to a participant I'd like to give him update access to a specific property within the asset.
From what I've read from the documentation it's possible to apply a rule to a property.
Rule:
rule PatientAddMentor {
description: "A patient is allowed to add mentors"
participant(p): "nl.epd.blockchain.Patient"
operation: UPDATE
resource(m): "nl.epd.blockchain.MedicalFile.mentors"
condition: (m.owner.getIdentifier() == p.getIdentifier())
action: ALLOW
}
The part where I am stuck at is how to target the asset in the condition. I'm assuming (m) equals the mentors in the condition because the error message says that the participant does not have UPDATE rights. (I'm not sure if it's even possible.)
Model:
namespace nl.epd.blockchain
asset MedicalFile identified by bsn {
o String bsn
--> Patient owner
--> Patient[] mentors optional
--> Organisation[] organisations optional
o Visit[] visits optional
o String[] allergies optional
o Treatment[] treatments optional
o Medicine[] medicine optional
}
participant Patient identified by bsn {
o String bsn
o String firstName
o String namePrefix optional
o String lastName
o String email
o String telephoneNumber
o String birthday
o String gender
o String city
o String zipCode
o String street
o String houseNumber
o String houseNumberExtra optional
}
The ACL engine does not yet enforce property level access control (only namespace and class level access control has been implemented).
You will have to use programmatic access control using the getCurrentParticipant() runtime API until declarative access control for properties is implemented.