Skip to content

Instantly share code, notes, and snippets.

@MichalZalecki
Created July 30, 2018 08:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MichalZalecki/91c2b0bc9c5abe30eb0077747da2a1a5 to your computer and use it in GitHub Desktop.
Save MichalZalecki/91c2b0bc9c5abe30eb0077747da2a1a5 to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"errors"
"fmt"
"strconv"
"strings"
"github.com/hyperledger/fabric/core/chaincode/lib/cid"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
)
type Prescription struct {
Patient string `json:"patient"`
Doctor string `json:"doctor"`
Content string `json:"content"`
Expires string `json:"expires"`
FilledBy string `json:"filled_by"`
}
type SmartContract struct {
}
func (s *SmartContract) Init(stub shim.ChaincodeStubInterface) peer.Response {
return shim.Success(nil)
}
func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
fn, args := stub.GetFunctionAndParameters()
if fn == "initLedger" {
return s.initLedger(stub)
} else if fn == "addPrescription" {
return s.addPrescription(stub, args)
} else if fn == "getPrescription" {
return s.getPrescription(stub, args)
} else if fn == "transferPrescription" {
return s.transferPrescription(stub, args)
}
return shim.Error("Invalid function name.")
}
func (s *SmartContract) initLedger(stub shim.ChaincodeStubInterface) peer.Response {
prescriptions := []Prescription{
Prescription{Patient: "PAT0", Doctor: "DOC0", Expires: "2018-07-17 14:01:52"},
}
for i, prescription := range prescriptions {
prescriptionAsBytes, _ := json.Marshal(prescription)
stub.PutPrivateData("healthcarePrescriptions", "PRE"+strconv.Itoa(i), prescriptionAsBytes)
}
return shim.Success(nil)
}
func (s *SmartContract) addPrescription(stub shim.ChaincodeStubInterface, args []string) peer.Response {
// Check arguments
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 4")
}
// Check if doctor
role, err := s.getRole(stub)
if err != nil {
return shim.Error(err.Error())
}
if !strings.HasPrefix(role, "DOC") {
return shim.Error(fmt.Sprintf("Only doctors can add new prescriptions. Your role is %s", role))
}
// Check if given prescription already exists
key := "PRE" + args[0]
prescriptionBytes, err := stub.GetPrivateData("healthcarePrescriptions", key)
if err != nil {
return shim.Error(err.Error())
}
if prescriptionBytes != nil {
return shim.Error("Prescription with such key already exists")
}
// Add prescription
prescription := Prescription{Patient: args[1], Doctor: role, Content: args[2], Expires: args[3]}
prescriptionBytes, err = json.Marshal(prescription)
if err != nil {
return shim.Error(err.Error())
}
err = stub.PutPrivateData("healthcarePrescriptions", key, prescriptionBytes)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
func (s *SmartContract) getPrescription(stub shim.ChaincodeStubInterface, args []string) peer.Response {
// Check arguments
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
// Get prescription
role, err := s.getRole(stub)
if err != nil {
return shim.Error(err.Error())
}
key := "PRE" + args[0]
var prescriptionBytes []byte
if strings.HasPrefix(role, "PAT") || strings.HasPrefix(role, "DOC") {
// When patient or doctor
prescriptionBytes, err = stub.GetPrivateData("healthcarePrescriptions", key)
if prescriptionBytes != nil {
prescription := Prescription{}
json.Unmarshal(prescriptionBytes, &prescription)
if prescription.Patient == role || prescription.Doctor == role {
return shim.Success(prescriptionBytes)
}
}
} else if strings.HasPrefix(role, "PHR") {
// When pharmacy
prescriptionBytes, err = stub.GetPrivateData("pharmacyPrescriptions", key)
if prescriptionBytes != nil {
return shim.Success(prescriptionBytes)
}
} else {
// When other
return shim.Error("Only patients, doctors and pharmacies can access prescriptions")
}
return shim.Error("Prescription not found")
}
func (s *SmartContract) transferPrescription(stub shim.ChaincodeStubInterface, args []string) peer.Response {
// Check arguments
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
role, err := s.getRole(stub)
if err != nil {
return shim.Error(err.Error())
}
if strings.HasPrefix(role, "PAT") {
return shim.Error("Only patients can transfer prescriptions")
}
// Get prescription
key := "PRE" + args[0]
prescriptionBytes, err := stub.GetPrivateData("healthcarePrescriptions", key)
if err != nil {
return shim.Error(err.Error())
}
if prescriptionBytes == nil {
return shim.Error("Prescription not found")
}
prescription := Prescription{}
json.Unmarshal(prescriptionBytes, &prescription)
// Check permissions
if prescription.Patient != role {
return shim.Error("Prescription not found")
}
// Set FilledBy
prescription.FilledBy = args[1]
prescriptionBytes, _ = json.Marshal(prescription)
err = stub.PutPrivateData("healthcarePrescriptions", key, prescriptionBytes)
if err != nil {
return shim.Error(err.Error())
}
// Save pharmacy prescription
err = stub.PutPrivateData("pharmacyPrescriptions", key, prescriptionBytes)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
func (s *SmartContract) getRole(stub shim.ChaincodeStubInterface) (string, error) {
role, ok, err := cid.GetAttributeValue(stub, "role")
if err != nil {
return "", err
}
if !ok {
return "", errors.New("role attribute is missing")
}
return role, nil
}
func main() {
err := shim.Start(new(SmartContract))
if err != nil {
fmt.Printf("Error starting SmartContract chaincode: %s", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment