diff --git a/asset-transfer-basic/chaincode-go/chaincode/jsonValidation.go.txt b/asset-transfer-basic/chaincode-go/chaincode/jsonValidation.go.txt new file mode 100644 index 00000000..2a0b9655 --- /dev/null +++ b/asset-transfer-basic/chaincode-go/chaincode/jsonValidation.go.txt @@ -0,0 +1,31 @@ +package main + +import ( + "fmt" + + "github.com/xeipuuv/gojsonschema" +) + +func main() { + //data := Data{ + //"DocType": "TestType", "Id": "00000", "Title": "TestSample", "Description": "description", "Type": "TestType", "DOI": "https://doi.org/10.57873/T34W2R", "Url": "sdsc.edu", "Manifest": "TestManifest", "Footprint": "", "Keywords": '["SmartContrac", "ChainCode", "Peer"]'ß, "OtherDataIdName": "None", "OtherDataIdValue": "None", "FundingAgencies": ["DOS", "NASA"], "Acknowledgment": "SDSC", "NoteForChange": "NONE", "Contributor": "AveryhardworkingUser@email.com", "Contributor_id": "ABC123" + //} + + schemaLoader := gojsonschema.NewReferenceLoader("file:///Users/fernando/Projects/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/Schema.json") + documentLoader := gojsonschema.NewReferenceLoader("file:////Users/fernando/Projects/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/testFile.json") + + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + //fmt.Printf(result.Valid()) + if err != nil { + panic(err.Error()) + } + + if result.Valid() { + fmt.Printf("The document is valid\n") + } else { + fmt.Printf("The document is not valid. see errors :\n") + for _, desc := range result.Errors() { + fmt.Printf("- %s\n", desc) + } + } +} diff --git a/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go index 28c89271..9d96be07 100644 --- a/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go +++ b/asset-transfer-basic/chaincode-go/chaincode/smartcontract.go @@ -3,6 +3,7 @@ package chaincode import ( "encoding/json" "fmt" + "github.com/hyperledger/fabric-contract-api-go/contractapi" "github.com/xeipuuv/gojsonschema" ) @@ -16,7 +17,6 @@ type SmartContract struct { // Insert struct field in alphabetic order => to achieve determinism across languages // golang keeps the order when marshal to json but doesn't order automatically - /*type Data struct { docType string `json:"docType"` id string `json:"id"` @@ -37,16 +37,15 @@ type SmartContract struct { contributor_id string `json:"contributor_id"` }*/ - // Asset describes basic details of what makes up a simple asset // Insert struct field in alphabetic order => to achieve determinism across languages // golang keeps the order when marshal to json but doesn't order automatically type Data struct { - Contributor string `json:"Contributor"` - ContributorId string `json:"ContributorId"` - ContentHash string `json:"ContentHash"` - Id string `json:"Id"` + Contributor string `json:"Contributor"` + ContributorId string `json:"ContributorId"` + ContentHash string `json:"ContentHash"` + Id string `json:"Id"` Owners []string `json:"Owners"` } @@ -111,10 +110,13 @@ func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, // JSON Validation -func (s *SmartContract) validJson() (bool, error) { - - schemaLoader := gojsonschema.NewReferenceLoader("file:///home/ofgarzon2662/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/Schema.json") - documentLoader := gojsonschema.NewReferenceLoader("file:////home/ofgarzon2662/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/testFile.json") +func (s *SmartContract) ValidJson(ctx contractapi.TransactionContextInterface) (bool, error) { + + //schemaLoader := gojsonschema.NewReferenceLoader("file:///Users/fernando/Projects/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/Schema.json") + //documentLoader := gojsonschema.NewReferenceLoader("file:////Users/fernando/Projects/OSC-IS/fabric-samples/test-network/JsonSchemaValidationTests/testFile.json") + + schemaLoader := gojsonschema.NewReferenceLoader("file:///home/chaincode/Schema.json") + documentLoader := gojsonschema.NewReferenceLoader("file:////home/chaincode/testFile.json") result, err := gojsonschema.Validate(schemaLoader, documentLoader) @@ -145,26 +147,26 @@ func (s *SmartContract) CreateDataSample(ctx contractapi.TransactionContextInter return fmt.Errorf("the asset %s already exists", Id) } - //valid, err := s.validJson() - //if err != nil { - // return err - //} - //if !valid { - // return fmt.Errorf("The Json file provided is not valid") - //} else { - data := Data{ - Contributor :Contributor, - ContributorId :ContributorId, - ContentHash :ContentHash, - Id :Id, - Owners :[]string{"DOE", "DOS", "DOJ"}} - - assetJSON, err := json.Marshal(data) + valid, err := s.ValidJson(ctx) if err != nil { return err } - return ctx.GetStub().PutState(Id, assetJSON) - //} + if !valid { + return fmt.Errorf("the json file provided is not valid") + } else { + data := Data{ + Contributor: Contributor, + ContributorId: ContributorId, + ContentHash: ContentHash, + Id: Id, + Owners: []string{"DOE", "DOS", "DOJ"}} + + assetJSON, err := json.Marshal(data) + if err != nil { + return err + } + return ctx.GetStub().PutState(Id, assetJSON) + } } // UpdateAsset updates an existing asset in the world state with provided parameters. @@ -181,11 +183,11 @@ func (s *SmartContract) UpdateAsset(ctx contractapi.TransactionContextInterface, // overwriting original asset with new asset data := Data{ - Contributor :Contributor, - ContributorId :ContributorId, - ContentHash :ContentHash, - Id :Id, - Owners :[]string{"DOE", "DOS", "DOJ"}, + Contributor: Contributor, + ContributorId: ContributorId, + ContentHash: ContentHash, + Id: Id, + Owners: []string{"DOE", "DOS", "DOJ"}, } assetJSON, err := json.Marshal(data) diff --git a/asset-transfer-basic/chaincode-go/go.mod b/asset-transfer-basic/chaincode-go/go.mod index a39adb01..9392ead8 100644 --- a/asset-transfer-basic/chaincode-go/go.mod +++ b/asset-transfer-basic/chaincode-go/go.mod @@ -8,4 +8,5 @@ require ( github.com/hyperledger/fabric-contract-api-go v1.1.0 github.com/hyperledger/fabric-protos-go v0.0.0-20200424173316-dd554ba3746e github.com/stretchr/testify v1.5.1 + github.com/xeipuuv/gojsonschema v1.2.0 // indirect ) diff --git a/asset-transfer-basic/chaincode-go/vendor/modules.txt b/asset-transfer-basic/chaincode-go/vendor/modules.txt index f209fc3c..efec300d 100644 --- a/asset-transfer-basic/chaincode-go/vendor/modules.txt +++ b/asset-transfer-basic/chaincode-go/vendor/modules.txt @@ -69,6 +69,7 @@ github.com/xeipuuv/gojsonpointer # github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 github.com/xeipuuv/gojsonreference # github.com/xeipuuv/gojsonschema v1.2.0 +## explicit github.com/xeipuuv/gojsonschema # golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 golang.org/x/net/http/httpguts diff --git a/test-network/JsonSchemaValidationTests/testFile.json b/test-network/JsonSchemaValidationTests/testFile.json index 92827a1b..4ed79eb2 100755 --- a/test-network/JsonSchemaValidationTests/testFile.json +++ b/test-network/JsonSchemaValidationTests/testFile.json @@ -1 +1 @@ -{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Carrera" } \ No newline at end of file +{ "number": 1600, "street_name": "Pennsylvania", "street_type": "Avenue" } \ No newline at end of file diff --git a/test-network/QuickCCTest.sh b/test-network/QuickCCTest.sh index 47313082..580cce39 100644 --- a/test-network/QuickCCTest.sh +++ b/test-network/QuickCCTest.sh @@ -138,3 +138,7 @@ peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.exa echo "========= Transfer Sample 00000 to new contributor ===========" peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"TransferAsset","Args":["00000", "NSF", "NSF_ID"]}' + +echo "========= CC Query: Get all DataSamples ===========" + +peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}' diff --git a/test-network/test_validation.go b/test-network/test_validation.go new file mode 100644 index 00000000..54e9e723 --- /dev/null +++ b/test-network/test_validation.go @@ -0,0 +1,86 @@ +package main + +import ( + "github.com/go-playground/validator/v10" + "github.com/gofiber/fiber/v2" +) + +/* +type Dog struct { + Name string `json:"name" validate:"required,min=3,max=12"` + Age int `json:"age" validate:"required,numeric"` + IsGoodBoy bool `json:"isGoodBoy" validate:"required"` +} +*/ + +type Dog struct { + DocType string `json:"docType" validate:"required,min=3,max=26"` + Id string `json:"id" validate:"required,alphanum"` + Title string `json:"title" validate:"required,min=3"` + Description string `json:"description" validate:"required,min=3"` + Type string `json:"Type" validate:"required,min=1"` + DOI string `json:"DOI" validate:"required,url"` + Url string `json:"url" validate:"required,url"` + Manifest *[]Manifest `json:"manifest" validate:"required,dive"` + Footprint string `json:"footprint"` + Keywords []string `json:"keywords"` + OtherDataIdName string `json:"otherDataIdName"` + OtherDataIdValue string `json:"otherDataIdValue"` + FundingAgencies []string `json:"fundingAgencies"` + Acknowledgment string `json:"acknowledgment"` + NoteForChange string `json:"noteForChange"` + Contributor string `json:"contributor"` + Contributor_id string `json:"contributor_id"` +} + +// Do we need to creat a struct for Manifest, or any other field for that matter? + +type Manifest struct { + Algorithm string `json:"algorithm" validate:"required,min=3,max=26"` + Filename string `json:"fileName" validate:"required,alphanum"` + Hash string `json:"hash" validate:"required,min=3"` +} + +type IError struct { + Field string + Tag string + Value string +} + +var Validator = validator.New() + +func ValidateAddDog(c *fiber.Ctx) error { + var errors []*IError + body := new(Dog) + c.BodyParser(&body) + + err := Validator.Struct(body) + if err != nil { + for _, err := range err.(validator.ValidationErrors) { + var el IError + el.Field = err.Field() + el.Tag = err.Tag() + el.Value = err.Param() + errors = append(errors, &el) + } + return c.Status(fiber.StatusBadRequest).JSON(errors) + } + return c.Next() +} + +func main() { + app := fiber.New() + + app.Get("/", func(c *fiber.Ctx) error { + return c.SendString("Thank God it works 🙏") + }) + + app.Post("/", ValidateAddDog, func(c *fiber.Ctx) error { + body := new(Dog) + c.BodyParser(&body) + return c.Status(fiber.StatusOK).JSON(body) + }) + + app.Listen(":3030") + +}