-
Notifications
You must be signed in to change notification settings - Fork 463
Expand file tree
/
Copy pathserializers.py
More file actions
186 lines (155 loc) · 6.11 KB
/
Copy pathserializers.py
File metadata and controls
186 lines (155 loc) · 6.11 KB
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
import tarfile
from typing import Dict, Any
from django.core.validators import MinValueValidator
from rest_framework import serializers
from chaincode.models import Chaincode
from chaincode.service import ChaincodeAction, create_chaincode, get_chaincode, install_chaincode, \
approve_chaincode, commit_chaincode, send_chaincode_request, metadata_exists, get_chaincode_status, \
get_chaincode_commit_readiness, ChaincodeTransactionError
from channel.models import Channel
from channel.serializers import ChannelID
from common.serializers import ListResponseSerializer
from user.serializers import UserID
class ChaincodeID(serializers.ModelSerializer):
class Meta:
model = Chaincode
fields = ("id",)
extra_kwargs = {
# Temporarily make "id" writable only for validation purposes
"id": {"read_only": False}
}
def validate(self, attrs: Dict[str, Any]) -> Dict[str, Any]:
chaincode = get_chaincode(attrs["id"])
if chaincode is None:
raise serializers.ValidationError("Chaincode with id {} does not exist.".format(attrs["id"]))
self.instance = chaincode
return attrs
def update(self, instance: Chaincode, validated_data: Dict[str, Any]) -> Chaincode:
return instance
class ChaincodeResponse(ChaincodeID):
channel = ChannelID()
creator = UserID()
status = serializers.SerializerMethodField()
approvals = serializers.SerializerMethodField()
class Meta:
model = Chaincode
fields = (
"id",
"name",
"version",
"sequence",
"init_required",
"signature_policy",
"package_id",
"label",
"creator",
"channel",
"language",
"created_at",
"description",
"status",
"approvals"
)
def get_status(self, chaincode) -> str:
organization = self.context.get("organization")
return get_chaincode_status(organization, chaincode) if organization else chaincode.get("status")
def get_approvals(self, chaincode) -> str:
organization = self.context.get("organization")
return get_chaincode_commit_readiness(organization, chaincode) if organization else chaincode.get("approvals")
class ChaincodeList(ListResponseSerializer):
data = ChaincodeResponse(many=True, help_text="Chaincode data")
class ChaincodeCreateBody(serializers.ModelSerializer):
class Meta:
model = Chaincode
fields = (
"name",
"version",
"sequence",
"init_required",
"signature_policy",
"package",
"channel",
"description",
)
extra_kwargs = {
"sequence": {
"validators": [MinValueValidator(1)]
},
"init_required": {"required": False},
"signature_policy": {"required": False},
"description": {"required": False},
}
@staticmethod
def validate_package(value):
if not value.name.endswith(".tar.gz"):
raise serializers.ValidationError("Chaincode Package must be a '.tar.gz' file.")
if value.content_type != "application/gzip":
raise serializers.ValidationError(
"Chaincode Package is not a 'application/gzip' file but {} instead."
.format(value.content_type)
)
try:
if not metadata_exists(value):
raise serializers.ValidationError("Metadata not found.")
except tarfile.TarError:
raise serializers.ValidationError("Failed to open the chaincode tar package.")
return value
def validate_channel(self, value: Channel) -> Channel:
if not value.organizations.contains(self.context["organization"]):
raise serializers.ValidationError("You can only install chaincodes on your organization.")
return value
def create(self, validated_data: Dict[str, Any]) -> ChaincodeID:
validated_data["user"] = self.context["user"]
validated_data["organization"] = self.context["organization"]
return ChaincodeID({"id": create_chaincode(**validated_data).id})
class ChaincodeInstallBody(ChaincodeID):
def update(self, instance: Chaincode, validated_data: Dict[str, Any]) -> Chaincode:
install_chaincode(
self.context["organization"],
instance
)
return instance
class ChaincodeApproveBody(ChaincodeID):
def update(self, instance: Chaincode, validated_data: Dict[str, Any]) -> Chaincode:
approve_chaincode(
self.context["organization"],
instance
)
return instance
class ChaincodeCommitBody(ChaincodeID):
def update(self, instance: Chaincode, validated_data: Dict[str, Any]) -> Chaincode:
commit_chaincode(
self.context["organization"],
instance
)
return instance
class ChaincodeRequestBody(ChaincodeID):
action = serializers.ChoiceField(choices=[(tag.name, tag.name) for tag in ChaincodeAction])
function = serializers.CharField()
arguments = serializers.ListField(
child=serializers.CharField(),
allow_empty=True,
required=False,
default=[],
)
class Meta:
model = Chaincode
fields = ("id", "action", "function", "arguments")
extra_kwargs = {
# Temporarily make "id" writable only for validation purposes
"id": {"read_only": False},
"arguments": {"required": False},
}
def update(self, instance: Chaincode, validated_data: Dict[str, Any]) -> Chaincode:
try:
result = send_chaincode_request(
self.context["organization"],
instance,
ChaincodeAction[validated_data["action"]],
validated_data["function"],
*validated_data["arguments"]
)
instance.result = result
return instance
except ChaincodeTransactionError as e:
raise serializers.ValidationError(str(e))