forked from chainHero/resource-manager
/
query.go
258 lines (211 loc) · 8.35 KB
/
query.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
// Copyright 2018 Antoine CHABERT, toHero.
//
// 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.
package main
import (
"fmt"
"github.com/chainHero/resource-manager/chaincode/model"
"github.com/hyperledger/fabric/core/chaincode/lib/cid"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"time"
)
// query function that handle every readonly in the ledger
func (t *ResourceManagerChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
fmt.Println("## query")
// Check whether the number of arguments is sufficient
if len(args) < 1 {
return shim.Error("The number of arguments is insufficient.")
}
if args[0] == "admin" {
return t.admin(stub, args[1:])
}
if args[0] == "consumer" {
return t.consumer(stub, args[1:])
}
if args[0] == "resources" {
return t.resources(stub, args[1:])
}
if args[0] == "resources-deleted" {
return t.resourcesDeleted(stub, args[1:])
}
if args[0] == "resource" {
return t.resource(stub, args[1:])
}
// If the arguments given don’t match any function, we return an error
return shim.Error("Unknown query action, check the second argument.")
}
func (t *ResourceManagerChaincode) admin(stub shim.ChaincodeStubInterface, args []string) pb.Response {
fmt.Println("# admin information")
err := cid.AssertAttributeValue(stub, model.ActorAttribute, model.ActorAdmin)
if err != nil {
return shim.Error(fmt.Sprintf("Only admin is allowed for the kind of request: %v", err))
}
adminID, err := cid.GetID(stub)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to identify the ID of the request owner: %v", err))
}
var admin model.Admin
err = getFromLedger(stub, model.ObjectTypeAdmin, adminID, &admin)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to retrieve admin in the ledger: %v", err))
}
adminAsByte, err := objectToByte(admin)
if err != nil {
return shim.Error(fmt.Sprintf("Unable convert the admin to byte: %v", err))
}
return shim.Success(adminAsByte)
}
func (t *ResourceManagerChaincode) consumer(stub shim.ChaincodeStubInterface, args []string) pb.Response {
fmt.Println("# consumer information")
err := cid.AssertAttributeValue(stub, model.ActorAttribute, model.ActorConsumer)
if err != nil {
return shim.Error(fmt.Sprintf("Only consumer is allowed for the kind of request: %v", err))
}
consumerID, err := cid.GetID(stub)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to identify the ID of the request owner: %v", err))
}
var consumer model.Consumer
err = getFromLedger(stub, model.ObjectTypeConsumer, consumerID, &consumer)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to retrieve consumer in the ledger: %v", err))
}
clientAsByte, err := objectToByte(consumer)
if err != nil {
return shim.Error(fmt.Sprintf("Unable convert the consumer to byte: %v", err))
}
return shim.Success(clientAsByte)
}
func (t *ResourceManagerChaincode) resources(stub shim.ChaincodeStubInterface, args []string) pb.Response {
fmt.Println("# resources list")
if len(args) < 1 {
return shim.Error("The number of arguments is insufficient.")
}
iterator, err := stub.GetStateByPartialCompositeKey(model.ObjectTypeResource, []string{})
if err != nil {
return shim.Error(fmt.Sprintf("Unable to retrieve the list of resource in the ledger: %v", err))
}
actorType, found, err := cid.GetAttributeValue(stub, model.ActorAttribute)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to identify the type of the request owner: %v", err))
}
if !found {
return shim.Error("The type of the request owner is not present")
}
actorID, err := cid.GetID(stub)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to identify the ID of the request owner: %v", err))
}
filter := args[0]
resources := make([]model.Resource, 0)
for iterator.HasNext() {
keyValueState, errIt := iterator.Next()
if errIt != nil {
return shim.Error(fmt.Sprintf("Unable to retrieve a resource in the ledger: %v", errIt))
}
var resource model.Resource
err = byteToObject(keyValueState.Value, &resource)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to convert a resource: %v", err))
}
if isResourceCanBeReturned(actorID, actorType, filter, &resource) {
resources = append(resources, resource)
}
}
resourcesAsByte, err := objectToByte(resources)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to convert the resource list to byte: %v", err))
}
return shim.Success(resourcesAsByte)
}
// isResourceCanBeReturned check if the resource can be return to the given actor and filter given.
func isResourceCanBeReturned(actorID string, actorType string, filter string, resource *model.Resource) bool {
// If the request owner is a consumer, we give only available resources or its previously acquired
if model.ActorConsumer == actorType && !resource.Available && resource.Consumer != actorID {
return false
}
if filter == model.ResourcesFilterOnlyAvailable && !resource.Available {
return false
}
if filter == model.ResourcesFilterOnlyUnavailable && resource.Available {
return false
}
return true
}
func (t *ResourceManagerChaincode) resourcesDeleted(stub shim.ChaincodeStubInterface, args []string) pb.Response {
fmt.Println("# resources deleted list")
err := cid.AssertAttributeValue(stub, model.ActorAttribute, model.ActorAdmin)
if err != nil {
return shim.Error(fmt.Sprintf("Only admin is allowed for the kind of request: %v", err))
}
var resourcesDeleted model.ResourcesDeleted
err = getFromLedger(stub, model.ObjectTypeResourcesDeleted, "", &resourcesDeleted)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to retrieve consumer in the ledger: %v", err))
}
resourcesDeletedAsByte, err := objectToByte(resourcesDeleted)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to convert the list of resource deleted to byte: %v", err))
}
return shim.Success(resourcesDeletedAsByte)
}
func (t *ResourceManagerChaincode) resource(stub shim.ChaincodeStubInterface, args []string) pb.Response {
fmt.Println("# resource detail")
err := cid.AssertAttributeValue(stub, model.ActorAttribute, model.ActorAdmin)
if err != nil {
return shim.Error(fmt.Sprintf("Only admin is allowed for the kind of request: %v", err))
}
if len(args) < 1 {
return shim.Error("The number of arguments is insufficient.")
}
resourceID := args[0]
if resourceID == "" {
return shim.Error("The resource ID is empty.")
}
key, err := stub.CreateCompositeKey(model.ObjectTypeResource, []string{resourceID})
if err != nil {
return shim.Error(fmt.Sprintf("unable to create the object key for the ledger: %v", err))
}
iterator, err := stub.GetHistoryForKey(key)
if err != nil {
return shim.Error(fmt.Sprintf("unable to retrieve an history resource in the ledger: %v", err))
}
var resourceHistories model.ResourceHistories
for iterator.HasNext() {
historyState, errIt := iterator.Next()
if errIt != nil {
return shim.Error(fmt.Sprintf("unable to retrieve a resource history in the ledger: %v", errIt))
}
var resourceHistory model.ResourceHistory
resourceHistory.Deleted = historyState.GetIsDelete()
if !resourceHistory.Deleted {
err = byteToObject(historyState.GetValue(), &resourceHistory.Resource)
if err != nil {
return shim.Error(fmt.Sprintf("unable to convert the resource history value to a valid resource: %v", err))
}
}
resourceHistory.Transaction = historyState.GetTxId()
timestamp := historyState.GetTimestamp()
resourceHistory.Time = time.Unix(timestamp.Seconds, int64(timestamp.Nanos))
resourceHistories = append(resourceHistories, resourceHistory)
}
if len(resourceHistories) <= 0 {
return shim.Error(fmt.Sprintf("Unable to found an history for the resource ID given: %v", err))
}
resourcesHistoryAsByte, err := objectToByte(resourceHistories)
if err != nil {
return shim.Error(fmt.Sprintf("Unable to convert the resource histories to byte: %v", err))
}
return shim.Success(resourcesHistoryAsByte)
}