class NetworkViewSet(viewsets.ViewSet): #authentication_classes = (JSONWebTokenAuthentication, TokenAuth) def _genesis2base64(self, network): """ convert genesis.block to Base64 HTTP_201_CREATED :param network: network id :return: genesis block :rtype: bytearray """ try: dir_node = "{}/{}/".format(CELLO_HOME, network) name = "genesis.block" zname = "block.zip" zip_file("{}{}".format(dir_node, name), "{}{}".format(dir_node, zname)) with open("{}{}".format(dir_node, zname), "rb") as f_block: block = base64.b64encode(f_block.read()) return block except Exception as e: raise e @swagger_auto_schema( query_serializer=NetworkQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse}) ), ) def list(self, request): """ List network :param request: query parameter :return: network list :rtype: list """ serializer = NetworkQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page", 1) per_page = serializer.validated_data.ger_page", 10) name = serializer.validated_data.get("name") parameters = {} if name: parameters.update({"name__icontains": name}) networks = Network.objects.filter(**parameters) p = Paginator(networks, per_page) networks = p.page(page) networks = [ { "id": network.id, "name": network.name, "created_at": network.created_at, } for network in networks ]
class NetworkViewSet(viewsets.ViewSet): @swagger_auto_schema( query_serializer=NetworkQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse})), ) def list(self, request, *args, **kwargs): """ List Networks Filter networks with query parameters. """ return Response(data=[], status=status.HTTP_200_OK)
class NodeViewSet(viewsets.ViewSet): @swagger_auto_schema( query_serializer=NodeQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse})), ) def list(self, request, *args, **kwargs): """ List Nodes Filter nodes with query parameters. """ return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=NodeCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NodeIDSerializer}), ) def create(self, request): """ Create Node Create new node """ pass @swagger_auto_schema( methods=["post"], query_serializer=NodeOperationSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="operations") def operate(self, request, pk=None): """ Operate Node Do some operation on node, start/stop/restart """ pass @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete Node Delete node """ pass
class NodeViewSet(viewsets.ViewSet): authentication_classes = (CustomAuthenticate, JSONWebTokenAuthentication) # Only operator can update node info def get_permissions(self): if self.action in ["update"]: permission_classes = (IsAuthenticated, IsOperatorAuthenticated) else: permission_classes = (IsAuthenticated, ) return [permission() for permission in permission_classes] @staticmethod def _validate_organization(request): if request.user.organization is None: raise CustomError(detail="Need join in organization.") @swagger_auto_schema( query_serializer=NodeQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NodeListSerializer})), ) def list(self, request, *args, **kwargs): """ List Nodes Filter nodes with query parameters. """ serializer = NodeQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") node_type = serializer.validated_data.get("type") name = serializer.validated_data.get("name") network_type = serializer.validated_data.get("network_type") network_version = serializer.validated_data.get("network_version") agent_id = serializer.validated_data.get("agent_id") if agent_id is not None and not request.user.is_operator: raise PermissionDenied query_filter = {} if node_type: query_filter.update({"type": node_type}) if name: query_filter.update({"name__icontains": name}) if network_type: query_filter.update({"network_type": network_type}) if network_version: query_filter.update({"network_version": network_version}) if request.user.is_administrator: query_filter.update( {"organization": request.user.organization}) elif request.user.is_common_user: query_filter.update({"user": request.user}) if agent_id: query_filter.update({"agent__id": agent_id}) nodes = Node.objects.filter(**query_filter) p = Paginator(nodes, per_page) nodes = p.page(page) nodes = [node.__dict__ for node in nodes] response = NodeListSerializer(data={ "total": p.count, "data": nodes }) if response.is_valid(raise_exception=True): return Response(data=response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=NodeCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NodeIDSerializer}), ) def create(self, request): """ Create Node Create node """ serializer = NodeCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): self._validate_organization(request) agent_type = serializer.validated_data.get("agent_type") network_type = serializer.validated_data.get("network_type") network_version = serializer.validated_data.get("network_version") agent = serializer.validated_data.get("agent") node_type = serializer.validated_data.get("type") ca = serializer.validated_data.get("ca", {}) if agent is None: available_agents = (Agent.objects.annotate( network_num=Count("node__network")).annotate( node_num=Count("node")).filter( schedulable=True, type=agent_type, network_num__lt=F("capacity"), node_num__lt=F("node_capacity"), organization=request.user.organization, ).order_by("node_num")) if len(available_agents) > 0: agent = available_agents[0] else: raise NoResource else: if not request.user.is_operator: raise PermissionDenied node_count = Node.objects.filter(agent=agent).count() if node_count >= agent.node_capacity or not agent.schedulable: raise NoResource fabric_ca = None if node_type == FabricNodeType.Ca.name.lower(): ca_body = {} admin_name = ca.get("admin_name") admin_password = ca.get("admin_password") # If found tls type ca server under this organization, # will cause resource exists error ca_server_type = ca.get("type", FabricCAServerType.Signature.value) if ca_server_type == FabricCAServerType.TLS.value: exist_ca_server = Node.objects.filter( organization=request.user.organization, ca__type=FabricCAServerType.TLS.value, ).count() if exist_ca_server > 0: raise ResourceExists hosts = ca.get("hosts", []) if admin_name: ca_body.update({"admin_name": admin_name}) if admin_password: ca_body.update({"admin_password": admin_password}) fabric_ca = FabricCA(**ca_body, hosts=hosts, type=ca_server_type) fabric_ca.save() node = Node( network_type=network_type, agent=agent, network_version=network_version, user=request.user, organization=request.user.organization, type=node_type, ca=fabric_ca, ) node.save() agent_config_file = request.build_absolute_uri( agent.config_file.url) node_detail_url = reverse("node-detail", args=[str(node.id)]) node_detail_url = request.build_absolute_uri(node_detail_url) node_file_upload_api = reverse("node-files", args=[str(node.id)]) node_file_upload_api = request.build_absolute_uri( node_file_upload_api) operate_node.delay( str(node.id), AgentOperation.Create.value, agent_config_file=agent_config_file, node_detail_url=node_detail_url, node_file_upload_api=node_file_upload_api, ) response = NodeIDSerializer({"id": str(node.id)}) return Response(response.data, status=status.HTTP_201_CREATED) @swagger_auto_schema( methods=["post"], query_serializer=NodeOperationSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="operations") def operate(self, request, pk=None): """ Operate Node Do some operation on node, start/stop/restart """ pass @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete Node Delete node """ try: if request.user.is_superuser: node = Node.objects.get(id=pk) else: node = Node.objects.get(id=pk, organization=request.user.organization) except ObjectDoesNotExist: raise ResourceNotFound else: if node.status != NodeStatus.Deleting.name.lower(): if node.status not in [ NodeStatus.Error.name.lower(), NodeStatus.Deleted.name.lower(), ]: node.status = NodeStatus.Deleting.name.lower() node.save() agent_config_file = request.build_absolute_uri( node.agent.config_file.url) node_detail_url = reverse("node-detail", args=[pk]) node_detail_url = request.build_absolute_uri( node_detail_url) operate_node.delay( str(node.id), AgentOperation.Delete.value, agent_config_file=agent_config_file, node_detail_url=node_detail_url, ) else: node.delete() return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema( operation_id="update node", request_body=NodeUpdateBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update Node Update special node with id. """ serializer = NodeUpdateBody(data=request.data) if serializer.is_valid(raise_exception=True): node_status = serializer.validated_data.get("status") ports = serializer.validated_data.get("ports", []) try: node = Node.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound node.status = node_status node.save() for port_item in ports: port = Port( external=port_item.get("external"), internal=port_item.get("internal"), node=node, ) port.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema( methods=["post"], manual_parameters=NodeFileCreateSerializer().to_form_paras(), responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="files", url_name="files") def upload_files(self, request, pk=None): """ Upload file to node Upload related files to node """ serializer = NodeFileCreateSerializer(data=request.data) if serializer.is_valid(raise_exception=True): file = serializer.validated_data.get("file") try: node = Node.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: # delete old file if node.file: node.file.delete() node.file = file node.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema(responses=with_common_response( with_common_response({status.HTTP_200_OK: NodeInfoSerializer}))) def retrieve(self, request, pk=None): """ Get Node information Get node detail information. """ self._validate_organization(request) try: node = Node.objects.get(id=pk, organization=request.user.organization) except ObjectDoesNotExist: raise ResourceNotFound else: # Set file url of node node.file = request.build_absolute_uri(node.file.url) response = NodeInfoSerializer(node) return Response(data=response.data, status=status.HTTP_200_OK) @swagger_auto_schema( methods=["post"], request_body=NodeUserCreateSerializer, responses=with_common_response( {status.HTTP_201_CREATED: NodeUserIDSerializer}), ) @action(methods=["post"], detail=True, url_path="users", url_name="users") def users(self, request, pk=None): """ Register user to node Register user to node """ serializer = NodeUserCreateSerializer(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") secret = serializer.validated_data.get("secret") user_type = serializer.validated_data.get("user_type") attrs = serializer.validated_data.get("attrs", "") try: node = Node.objects.get(id=pk, organization=request.user.organization) # Name is unique for each node user_count = NodeUser.objects.filter(node=node, name=name).count() if user_count > 0: raise ResourceExists except ObjectDoesNotExist: raise ResourceNotFound node_user = NodeUser( name=name, secret=secret, user_type=user_type, attrs=attrs, node=node, ) node_user.save() agent_config_file = request.build_absolute_uri( node.agent.config_file.url) node_file_url = request.build_absolute_uri(node.file.url) user_patch_url = self.reverse_action("patch-user", kwargs={ "pk": pk, "user_pk": node_user.id }) user_patch_url = request.build_absolute_uri(user_patch_url) operate_node.delay( str(node.id), AgentOperation.FabricCARegister.value, agent_config_file=agent_config_file, node_file_url=node_file_url, user_patch_url=user_patch_url, fabric_ca_user={ "name": name, "secret": secret, "type": user_type, "attrs": attrs, }, ) response = NodeUserIDSerializer(node_user) return Response(data=response.data, status=status.HTTP_201_CREATED) @swagger_auto_schema( methods=["patch"], request_body=NodeUserPatchSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action( methods=["patch"], detail=True, url_path="users/(?P<user_pk>[^/.]+)", url_name="patch-user", ) def patch_user(self, request, pk=None, user_pk=None): """ Patch user status for node Patch user status for node """ serializer = NodeUserPatchSerializer(data=request.data) if serializer.is_valid(raise_exception=True): try: node_user = NodeUser.objects.get(id=user_pk, node__id=pk) except ObjectDoesNotExist: raise ResourceNotFound node_user.status = serializer.validated_data.get("status") node_user.save() return Response(status=status.HTTP_202_ACCEPTED)
class NodeViewSet(viewsets.ViewSet): #authentication_classes = (CustomAuthenticate, JSONWebTokenAuthentication) # Only operator can update node info # def get_permissions(self): # if self.action in ["update"]: # permission_classes = (IsAuthenticated, IsOperatorAuthenticated) # else: # permission_classes = (IsAuthenticated,) # # return [permission() for permission in permission_classes] @staticmethod def _validate_organization(request): if request.user.organization is None: raise CustomError(detail="Need join in organization.") @swagger_auto_schema( query_serializer=NodeQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NodeListSerializer}) ), ) def list(self, request, *args, **kwargs): """ List node :param request: query parameter :return: node list :rtype: list """ serializer = NodeQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") node_type = serializer.validated_data.get("type") name = serializer.validated_data.get("name") agent_id = serializer.validated_data.get("agent_id") # if agent_id is not None and not request.user.is_operator: # raise PermissionDenied query_filter = {} if node_type: query_filter.update({"type": node_type}) if name: query_filter.update({"name__icontains": name}) # if request.user.is_administrator: # query_filter.update( # {"organization": request.user.organization} # ) # elif request.user.is_common_user: # query_filter.update({"user": request.user}) if agent_id: query_filter.update({"agent__id": agent_id}) nodes = Node.objects.filter(**query_filter) p = Paginator(nodes, per_page) nodes = p.page(page) response = NodeListSerializer({"total": p.count, "data": nodes}) return Response(data=response.data, status=status.HTTP_200_OK) def _save_fabric_ca(self, request, ca=None): if ca is None: return None ca_body = {} admin_name = ca.get("admin_name") admin_password = ca.get("admin_password") # If found tls type ca server under this organization, # will cause resource exists error ca_server_type = ca.get("type", FabricCAServerType.Signature.value) if ca_server_type == FabricCAServerType.TLS.value: exist_ca_server = Node.objects.filter( organization=request.user.organization, ca__type=FabricCAServerType.TLS.value, ).count() if exist_ca_server > 0: raise ResourceExists hosts = ca.get("hosts", []) if admin_name: ca_body.update({"admin_name": admin_name}) if admin_password: ca_body.update({"admin_password": admin_password}) fabric_ca = FabricCA(**ca_body, hosts=hosts, type=ca_server_type) fabric_ca.save() return fabric_ca def _save_fabric_peer(self, request, peer=None): if peer is None: return None name = peer.get("name") gossip_use_leader_reflection = peer.get("gossip_use_leader_reflection") gossip_org_leader = peer.get("gossip_org_leader") gossip_skip_handshake = peer.get("gossip_skip_handshake") local_msp_id = peer.get("local_msp_id") ca_nodes = peer.get("ca_nodes") body = {"name": name, "local_msp_id": local_msp_id} if gossip_use_leader_reflection is not None: body.update( {"gossip_use_leader_reflection": gossip_use_leader_reflection} ) if gossip_org_leader is not None: body.update({"gossip_org_leader": gossip_org_leader}) if gossip_skip_handshake is not None: body.update({"gossip_skip_handshake": gossip_skip_handshake}) fabric_peer = FabricPeer(**body) fabric_peer.save() ca_nodes_list = [] for ca_node in ca_nodes: node = ca_node.get("node") address = ca_node.get("address") certificate = ca_node.get("certificate") ca_type = ca_node.get("type") ca_body = {"peer": fabric_peer} ca_node_dict = {} if node is not None: ca_body.update({"node": node}) port = Port.objects.filter(node=node, internal=7054).first() if port: ca_node_dict.update( {"address": "%s:%s" % (node.agent.ip, port.external)} ) ca_node_dict.update( { "type": node.ca.type, "certificate": request.build_absolute_uri( node.file.url ), } ) else: update_body = { "address": address, "certificate": certificate, "type": ca_type, } ca_body.update(update_body) ca_node_dict.update(update_body) peer_ca = PeerCa(**ca_body) peer_ca.save() users = ca_node.get("users") user_list = [] for ca_user in users: ca_user_body = {"peer_ca": peer_ca} user_dict = {} user = ca_user.get("user") username = ca_user.get("username") password = ca_user.get("password") user_type = ca_user.get("type") if user is not None: ca_user_body.update({"user": user}) user_dict.update( { "username": user.name, "password": user.secret, "type": user.user_type, } ) else: update_body = { "username": username, "password": password, "type": user_type, } ca_user_body.update(update_body) user_dict.update(update_body) user_list.append(user_dict) ca_user_obj = PeerCaUser(**ca_user_body) ca_user_obj.save() ca_node_dict.update({"users": user_list}) ca_nodes_list.append(ca_node_dict) return fabric_peer, ca_nodes_list @swagger_auto_schema( request_body=NodeCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NodeIDSerializer} ), ) def create(self, request): """ Create Node :param request: create parameter :return: node ID :rtype: uuid """ serializer = NodeCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): #self._validate_organization(request) name = serializer.validated_data.get("name") type = serializer.validated_data.get("type") urls = serializer.validated_data.get("urls") organization = serializer.validated_data.get("organization") org = Organization.objects.get(id=organization) if org.organization.all(): pass else: raise NoResource nodes = { "type": type, "Specs": [name] } CryptoConfig(org.name).update(nodes) CryptoGen(org.name).extend() msp, tls = self._conversion_msp_tls(type, org.name, name) node = Node( name=name, org=org, urls=urls, type=type, msp=msp, tls=tls ) node.save() response = NodeIDSerializer(data=node.__dict__) if response.is_valid(raise_exception=True): return Response( response.validated_data, status=status.HTTP_201_CREATED ) def _conversion_msp_tls(self, type, org, node): """ msp and tls from zip file to byte :param org: organization name :param type: node type :param node: node name :return: msp, tls :rtype: bytes """ try: if type == "peer": dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/" \ .format(CELLO_HOME, org, org, node + "." + org) else: dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/" \ .format(CELLO_HOME, org, org.split(".", 1)[1], node + "." + org.split(".", 1)[1]) zip_dir("{}msp".format(dir_node), "{}msp.zip".format(dir_node)) with open("{}msp.zip".format(dir_node), "rb") as f_msp: msp = base64.b64encode(f_msp.read()) zip_dir("{}tls".format(dir_node), "{}tls.zip".format(dir_node)) with open("{}tls.zip".format(dir_node), "rb") as f_tls: tls = base64.b64encode(f_tls.read()) except Exception as e: raise e return msp, tls @swagger_auto_schema( methods=["post"], query_serializer=NodeOperationSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="operations") def operate(self, request, pk=None): """ Operate Node Do some operation on node, start/stop/restart """ pass @swagger_auto_schema( responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"} ) ) def destroy(self, request, pk=None): """ Delete Node :param request: destory parameter :param pk: primary key :return: none :rtype: rest_framework.status """ try: node = Node.objects.get(id=pk) node.delete() # todo delete node from agent except ObjectDoesNotExist: raise ResourceNotFound return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema( operation_id="update node", request_body=NodeUpdateBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update Node Update special node with id. """ serializer = NodeUpdateBody(data=request.data) if serializer.is_valid(raise_exception=True): node_status = serializer.validated_data.get("status") ports = serializer.validated_data.get("ports", []) try: node = Node.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound node.status = node_status node.save() for port_item in ports: port = Port( external=port_item.get("external"), internal=port_item.get("internal"), node=node, ) port.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema( methods=["post"], request_body=NodeFileCreateSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="files", url_name="files") def upload_files(self, request, pk=None): """ Upload file to node Upload related files to node """ serializer = NodeFileCreateSerializer(data=request.data) if serializer.is_valid(raise_exception=True): file = serializer.validated_data.get("file") try: node = Node.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: # delete old file if node.file: node.file.delete() node.file = file node.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema( responses=with_common_response( with_common_response({status.HTTP_200_OK: NodeInfoSerializer}) ) ) def retrieve(self, request, pk=None): """ Get Node information Get node detail information. """ self._validate_organization(request) try: node = Node.objects.get( id=pk, organization=request.user.organization ) except ObjectDoesNotExist: raise ResourceNotFound else: # Set file url of node if node.file: node.file = request.build_absolute_uri(node.file.url) ports = Port.objects.filter(node=node) node.links = [ { "internal_port": port.internal, "url": "%s:%s" % (node.agent.ip, port.external), } for port in ports ] response = NodeInfoSerializer(node) return Response(data=response.data, status=status.HTTP_200_OK) def _register_user(self, request, pk=None): serializer = NodeUserCreateSerializer(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") secret = serializer.validated_data.get("secret") user_type = serializer.validated_data.get("user_type") attrs = serializer.validated_data.get("attrs", "") try: node = Node.objects.get( id=pk, organization=request.user.organization ) # Name is unique for each node user_count = NodeUser.objects.filter( node=node, name=name ).count() if user_count > 0: raise ResourceExists except ObjectDoesNotExist: raise ResourceNotFound node_user = NodeUser( name=name, secret=secret, user_type=user_type, attrs=attrs, node=node, ) node_user.save() agent_config_file = request.build_absolute_uri( node.agent.config_file.url ) node_file_url = request.build_absolute_uri(node.file.url) user_patch_url = self.reverse_action( "patch-user", kwargs={"pk": pk, "user_pk": node_user.id} ) user_patch_url = request.build_absolute_uri(user_patch_url) operate_node.delay( str(node.id), AgentOperation.FabricCARegister.value, agent_config_file=agent_config_file, node_file_url=node_file_url, user_patch_url=user_patch_url, fabric_ca_user={ "name": name, "secret": secret, "type": user_type, "attrs": attrs, }, ) response = NodeUserIDSerializer(node_user) return Response(data=response.data, status=status.HTTP_201_CREATED) def _list_user(self, request, pk=None): serializer = NodeUserQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") name = serializer.validated_data.get("name") user_type = serializer.validated_data.get("user_type") user_status = serializer.validated_data.get("status") query_param = {"node__id": pk} if name is not None: query_param.update({"name__icontains": name}) if user_type is not None: query_param.update({"user_type": user_type}) if user_status is not None: query_param.update({"status": user_status}) users = NodeUser.objects.filter(**query_param) p = Paginator(users, per_page) users = p.page(page) response = NodeUserListSerializer( {"data": users, "total": p.count} ) return Response(response.data, status=status.HTTP_200_OK) @swagger_auto_schema( methods=["post"], operation_description="Register user to node", operation_summary="Register user to node", request_body=NodeUserCreateSerializer, responses=with_common_response( {status.HTTP_201_CREATED: NodeUserIDSerializer} ), ) @swagger_auto_schema( methods=["get"], operation_description="List user of node", operation_summary="List user of node", query_serializer=NodeUserQuerySerializer, responses=with_common_response( {status.HTTP_200_OK: NodeUserListSerializer} ), ) @action( methods=["post", "get"], detail=True, url_path="users", url_name="users", ) def users(self, request, pk=None): if request.method == "POST": return self._register_user(request, pk) elif request.method == "GET": return self._list_user(request, pk) @swagger_auto_schema( methods=["patch"], request_body=NodeUserPatchSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action( methods=["patch"], detail=True, url_path="users/(?P<user_pk>[^/.]+)", url_name="patch-user", ) def patch_user(self, request, pk=None, user_pk=None): """ Patch user status for node Patch user status for node """ serializer = NodeUserPatchSerializer(data=request.data) if serializer.is_valid(raise_exception=True): try: node_user = NodeUser.objects.get(id=user_pk, node__id=pk) except ObjectDoesNotExist: raise ResourceNotFound node_user.status = serializer.validated_data.get("status") node_user.save() return Response(status=status.HTTP_202_ACCEPTED)
class OrganizationViewSet(viewsets.ViewSet): """Class represents orgnization related operations.""" #authentication_classes = (JSONWebTokenAuthentication, TokenAuth) #permission_classes = (IsAuthenticated, IsOperatorAuthenticated) @swagger_auto_schema( query_serializer=OrganizationQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: OrganizationList})), ) def list(self, request): """ List Organizations :param request: query parameter :return: organization list :rtype: list """ serializer = OrganizationQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page", 1) per_page = serializer.validated_data.get("per_page", 10) name = serializer.validated_data.get("name") parameters = {} if name: parameters.update({"name__icontains": name}) organizations = Organization.objects.filter(**parameters) p = Paginator(organizations, per_page) organizations = p.page(page) organizations = [{ "id": str(organization.id), "name": organization.name, "network": str(organization.network.id) if organization.network else None, "agents": organization.agents if organization.agents else None, "channel": str(organization.channel.id) if organization.channel else None, "created_at": organization.created_at, } for organization in organizations] response = OrganizationList(data={ "total": p.count, "data": organizations }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=OrganizationCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: OrganizationIDSerializer}), ) def create(self, request): """ Create Organization :param request: create parameter :return: organization ID :rtype: uuid """ serializer = OrganizationCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") peernum = serializer.validated_data.get("org_peernum") orderernum = serializer.validated_data.get("org_orderernum") try: Organization.objects.get(name=name) except ObjectDoesNotExist: pass else: raise ResourceExists CryptoConfig(name).create(peernum, orderernum) CryptoGen(name).generate() msp, tls = self._conversion_msp_tls(name) organization = Organization(name=name, msp=msp, tls=tls) organization.save() # create node config if peernum > 0: self._create_node(organization, peernum, "peer") if orderernum > 0: self._create_node(organization, orderernum, "orderer") response = OrganizationIDSerializer(data=organization.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) def _create_node(self, org, num, nodeType): """ create node :param org: organization :param num: the number of node :param nodeType: the type of node :return: null """ for i in range(num): nodeName = "peer" + str( i) if nodeType == "peer" else "orderer" + str(i) self._generate_config(nodeType, org.name, nodeName) msp, tls, cfg = self._conversion_msp_tls_cfg( nodeType, org.name, nodeName) urls = "{}.{}".format(nodeName, org.name) node = Node(name=nodeName, org=org, urls=urls, type=nodeType, msp=msp, tls=tls, agent=None, config_file=cfg) node.save() def _conversion_msp_tls_cfg(self, type, org, node): """ msp and tls , cfg from zip file to byte :param org: organization name :param type: node type :param node: node name :return: msp, tls, cfg :rtype: bytes """ try: if type == "peer": dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/" \ .format(CELLO_HOME, org, org, node + "." + org) name = "core.yaml" cname = "peer_config.zip" else: dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/" \ .format(CELLO_HOME, org, org.split(".", 1)[1], node + "." + org.split(".", 1)[1]) name = "orderer.yaml" cname = "orderer_config.zip" zip_dir("{}msp".format(dir_node), "{}msp.zip".format(dir_node)) with open("{}msp.zip".format(dir_node), "rb") as f_msp: msp = base64.b64encode(f_msp.read()) zip_dir("{}tls".format(dir_node), "{}tls.zip".format(dir_node)) with open("{}tls.zip".format(dir_node), "rb") as f_tls: tls = base64.b64encode(f_tls.read()) zip_file("{}{}".format(dir_node, name), "{}{}".format(dir_node, cname)) with open("{}{}".format(dir_node, cname), "rb") as f_cfg: cfg = base64.b64encode(f_cfg.read()) except Exception as e: raise e return msp, tls, cfg def _generate_config(self, type, org, node): """ generate config for node :param org: organization name :param type: node type :param node: node name :param port: node port(todo: automatic distribution port) :return: none :rtype: none """ args = {} if type == "peer": args.update({"peer_id": "{}.{}".format(node, org)}) args.update({"peer_address": "{}.{}:{}".format(node, org, 7051)}) args.update({ "peer_gossip_externalEndpoint": "{}.{}:{}".format(node, org, 7051) }) args.update( {"peer_chaincodeAddress": "{}.{}:{}".format(node, org, 7052)}) args.update({"peer_tls_enabled": True}) args.update({"peer_localMspId": "{}MSP".format(org.capitalize())}) a = NodeConfig(org) a.peer(node, **args) else: args.update({"General_ListenPort": 7050}) args.update({ "General_LocalMSPID": "{}OrdererMSP".format(org.capitalize()) }) args.update({"General_TLS_Enabled": True}) args.update({"General_BootstrapFile": "genesis.block"}) a = NodeConfig(org) a.orderer(node, **args) def _conversion_msp_tls(self, name): """ msp and tls from zip file to byte :param name: organization name :return: msp, tls :rtype: bytes """ try: dir_org = "{}/{}/crypto-config/peerOrganizations/{}/" \ .format(CELLO_HOME, name, name) zip_dir("{}msp".format(dir_org), "{}msp.zip".format(dir_org)) with open("{}msp.zip".format(dir_org), "rb") as f_msp: msp = base64.b64encode(f_msp.read()) zip_dir("{}tlsca".format(dir_org), "{}tls.zip".format(dir_org)) with open("{}tls.zip".format(dir_org), "rb") as f_tls: tls = base64.b64encode(f_tls.read()) except Exception as e: raise e return msp, tls @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete Organization :param request: destory parameter :param pk: primary key :return: none :rtype: rest_framework.status """ try: organization = Organization.objects.get(id=pk) if organization.network: raise ResourceInUse # user_count = UserProfile.objects.filter( # organization=organization # ).count() # if user_count > 0: # raise ResourceInUse path = "{}/{}".format(CELLO_HOME, organization.name) if os.path.exists(path): shutil.rmtree(path, True) organization.delete() except ObjectDoesNotExist: raise ResourceNotFound return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema(responses=with_common_response( {status.HTTP_200_OK: OrganizationResponse})) def retrieve(self, request, pk=None): """ Retrieve Organization :param request: retrieve parameter :param pk: primary key :return: organization info :rtype: OrganizationResponse """ try: organization = Organization.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: response = OrganizationResponse(data=organization.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=OrganizationUpdateBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update Agent Update special agent with id. """ serializer = OrganizationUpdateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") agents = serializer.validated_data.get("agents") network = serializer.validated_data.get("network") channel = serializer.validated_data.get("channel") try: Organization.objects.get(name=name) except ObjectDoesNotExist: pass organization = Organization.objects.filter(name=name).update( agents=agents, network=network.id, channel=channel.id) return Response(status=status.HTTP_204_NO_CONTENT) @staticmethod def _list_users(request, pk=None): serializer = UserQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): try: organization = Organization.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") name = serializer.validated_data.get("name") parameter = {"organization": organization} if name: parameter.update({"username__icontains": name}) users = UserProfile.objects.filter(**parameter) p = Paginator(users, per_page) users = p.page(page) users = [{ "id": str(user.id), "username": user.username, "role": user.role, } for user in users] response = UserListSerializer(data={ "total": p.count, "data": users }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @staticmethod def _add_user(request, pk=None): serializer = UserIDSerializer(data=request.data) if serializer.is_valid(raise_exception=True): user_id = serializer.validated_data.get("id") try: organization = Organization.objects.get(id=pk) user = UserProfile.objects.get(id=user_id) if user.organization: raise ResourceInUse except ObjectDoesNotExist: raise ResourceNotFound else: user.organization = organization user.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema( method="get", query_serializer=UserQuerySerializer, responses=with_common_response( {status.HTTP_200_OK: UserListSerializer}), ) @swagger_auto_schema( method="post", request_body=UserIDSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["get", "post"], detail=True, url_path="users") def manage_users(self, request, pk=None): """ get: List users List users in Organization post: Add User Add user into Organization """ if request.method == "GET": return self._list_users(request, pk) elif request.method == "POST": return self._add_user(request, pk) @swagger_auto_schema( method="delete", responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"}), ) @action(methods=["delete"], detail=True, url_path="users/(?P<user_id>[^/.]+)") def remove_user_from_govern(self, request, pk=None, user_id=None): """ Remove user from Organization Remove user from Organization """ try: user = UserProfile.objects.get(id=user_id, organization__id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: user.organization = None user.save() return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="certificates") def request_certificate(self, request, pk=None): """ post: Request Certificate Request certificate """ pass
class UserViewSet(viewsets.ViewSet): authentication_classes = (JSONWebTokenAuthentication, ) def get_permissions(self): permission_classes = [] if self.action not in ["auth"]: permission_classes = ( IsAuthenticated, any_of(IsAdminAuthenticated, IsOperatorAuthenticated), ) return [permission() for permission in permission_classes] @swagger_auto_schema( query_serializer=UserQuerySerializer, responses=with_common_response( {status.HTTP_200_OK: UserListSerializer}), ) def list(self, request, *args, **kwargs): """ List Users List user through query parameter """ serializer = UserQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): username = serializer.validated_data.get("username") page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") query_params = {} if username: query_params.update({"username__icontains": username}) users = UserProfile.objects.filter(**query_params).exclude( username=ADMIN_USERNAME) p = Paginator(users, per_page) users = p.page(page) users = [user.__dict__ for user in users] response = UserListSerializer(data={ "total": p.count, "data": users }) if response.is_valid(raise_exception=True): return Response(data=response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=UserCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: UserIDSerializer}), ) def create(self, request): """ Create User Create new user """ serializer = UserCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): username = serializer.validated_data.get("username") role = serializer.validated_data.get("role") organization = serializer.validated_data.get("organization") password = serializer.validated_data.get("password") email = serializer.validated_data.get("email") user_count = UserProfile.objects.filter( Q(username=username) | Q(email=email)).count() if user_count > 0: raise ResourceExists( detail="User name or email already exists") user = UserProfile( username=username, role=role, email=email, organization=organization, ) user.set_password(password) user.save() response = UserIDSerializer(data={"id": user.id}) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete User Delete user """ try: UserProfile.objects.get(id=pk).delete() except Exception as e: raise CustomError(detail=str(e)) else: return Response(status=status.HTTP_204_NO_CONTENT) @action( methods=["get", "post", "put", "delete"], detail=True, url_path="attributes", ) def attributes(self, request, pk=None): """ get: Get User Attributes Get attributes of user post: Create Attributes Create attribute for user put: Update Attribute Update attribute of user delete: Delete Attribute Delete attribute of user """ pass @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="password") def password(self, request, pk=None): """ post: Update/Reset Password Update/Reset password for user """ pass
class UserViewSet(viewsets.ViewSet): authentication_classes = (CustomAuthenticate, ) permission_classes = (IsAuthenticated, IsAdminAuthenticated) @swagger_auto_schema(responses=with_common_response(with_common_response()) ) def list(self, request, *args, **kwargs): """ List Users List user through query parameter """ return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=UserCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: UserIDSerializer}), ) def create(self, request): """ Create User Create new user """ serializer = UserCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") role = serializer.validated_data.get("role") govern = serializer.validated_data.get("govern") password = serializer.validated_data.get("password") keycloak_client = KeyCloakClient() user_exists = keycloak_client.get_user(username=name) if user_exists: raise ResourceExists create_user_body = { "username": name, "requiredActions": [], "enabled": True, } keycloak_client.create_user(create_user_body) user_id = keycloak_client.get_user_id(username=name) keycloak_client.reset_user_password(user_id, password) user_attr = {"role": role} if govern: user_attr.update({"govern": str(govern.id)}) keycloak_client.update_user(user_id, body={"attributes": user_attr}) user, _ = UserModel.objects.get_or_create(id=user_id, name=name, role=role, govern=govern) response = UserIDSerializer(data={"id": user_id}) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete User Delete user """ pass @action( methods=["get", "post", "put", "delete"], detail=True, url_path="attributes", ) def attributes(self, request, pk=None): """ get: Get User Attributes Get attributes of user post: Create Attributes Create attribute for user put: Update Attribute Update attribute of user delete: Delete Attribute Delete attribute of user """ pass @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="password") def password(self, request, pk=None): """ post: Update/Reset Password Update/Reset password for user """ pass
class NetworkViewSet(viewsets.ViewSet): authentication_classes = (JSONWebTokenAuthentication, TokenAuth) def _genesis2base64(self, network): """ convert genesis.block to Base64 :param network: network id :return: genesis block :rtype: bytearray """ try: dir_node = "{}/{}/".format(CELLO_HOME, network) name = "genesis.block" zname = "block.zip" zip_file("{}{}".format(dir_node, name), "{}{}".format(dir_node, zname)) with open("{}{}".format(dir_node, zname), "rb") as f_block: block = base64.b64encode(f_block.read()) return block except Exception as e: raise e @swagger_auto_schema( query_serializer=NetworkQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse}) ), ) def list(self, request): """ List network :param request: query parameter :return: network list :rtype: list """ serializer = NetworkQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page", 1) per_page = serializer.validated_data.get("per_page", 10) name = serializer.validated_data.get("name") parameters = {} if name: parameters.update({"name__icontains": name}) networks = Network.objects.filter(**parameters) p = Paginator(networks, per_page) networks = p.page(page) networks = [ { "id": network.id, "name": network.name, "created_at": network.created_at, } for network in networks ] response = NetworkListResponse( data={"total": p.count, "data": networks} ) if response.is_valid(raise_exception=True): return Response( response.validated_data, status=status.HTTP_200_OK ) return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=NetworkCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NetworkIDSerializer} ), ) def create(self, request): """ Create Network :param request: create parameter :return: organization ID :rtype: uuid """ serializer = NetworkCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") consensus = serializer.validated_data.get("consensus") organizations = serializer.validated_data.get("organizations") try: Network.objects.get(name=name) except ObjectDoesNotExist: pass orderers = [] peers = [] i = 0 for organization in organizations: org = Organization.objects.get(pk=organization) orderers.append({"name": org.name, "hosts": []}) peers.append({"name": org.name, "hosts": []}) nodes = Node.objects.filter(org=org) for node in nodes: if node.type == "peer": peers[i]["hosts"].append({"name": node.name, "port": node.urls.split(":")[2]}) elif node.type == "orderer": orderers[i]["hosts"].append({"name": node.name, "port": node.urls.split(":")[2]}) i = i + 1 ConfigTX(name).create(consensus=consensus, orderers=orderers, peers=peers) ConfigTxGen(name).genesis() block = self._genesis2base64(name) network = Network(name=name, consensus=consensus, organizations=organizations, genesisblock=block) network.save() for organization in organizations: Organization.objects.filter(pk=organization).update(network=network) response = NetworkIDSerializer(data=network.__dict__) if response.is_valid(raise_exception=True): return Response( response.validated_data, status=status.HTTP_201_CREATED ) @swagger_auto_schema(responses=with_common_response()) def retrieve(self, request, pk=None): """ Get Network Get network information """ pass @swagger_auto_schema( responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"} ) ) def destroy(self, request, pk=None): try: network = Network.objects.get(pk=pk) network.delete() except ObjectDoesNotExist: raise BaseException return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema( methods=["get"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse} ), ) @swagger_auto_schema( methods=["post"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse} ), ) @action(methods=["get", "post"], detail=True, url_path="peers") def peers(self, request, pk=None): """ get: Get Peers Get peers of network. post: Add New Peer Add peer into network """ pass @swagger_auto_schema( methods=["delete"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse} ), ) @action(methods=["delete"], detail=True, url_path="peers/<str:peer_id>") def delete_peer(self, request, pk=None, peer_id=None): """ delete: Delete Peer Delete peer in network """ pass
class AgentViewSet(viewsets.ViewSet): """Class represents agent related operations.""" authentication_classes = (JSONWebTokenAuthentication, ) def get_permissions(self): if self.action in ["apply", "list", "release", "retrieve"]: permission_classes = ( IsAuthenticated, any_of(IsAdminAuthenticated, IsOperatorAuthenticated), ) else: permission_classes = (IsAuthenticated, IsOperatorAuthenticated) return [permission() for permission in permission_classes] @swagger_auto_schema( query_serializer=AgentQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: AgentListResponse})), ) def list(self, request): """ List Agents :param request: query parameter :return: agent list :rtype: list """ serializer = AgentQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") agent_status = serializer.validated_data.get("status") name = serializer.validated_data.get("name") agent_type = serializer.validated_data.get("type") organization = serializer.validated_data.get("organization") query_filters = {} # if organization: # if not request.user.is_operator: # raise PermissionDenied() # query_filters.update({"organization": organization}) # else: # org_name = ( # request.user.organization.name # if request.user.organization # else "" # ) # if request.user.is_administrator: # query_filters.update({"organization__name": org_name}) if name: query_filters.update({"name__icontains": name}) if agent_status: query_filters.update({"status": agent_status}) if agent_type: query_filters.update({"type": agent_type}) agents = Agent.objects.filter(**query_filters) p = Paginator(agents, per_page) agents = p.page(page) # agents = [agent.__dict__ for agent in agents] agent_list = [] for agent in agents: agent_dict = agent.__dict__ agent_list.append(agent_dict) response = AgentListResponse(data={ "data": agent_list, "total": p.count }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=AgentCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: AgentIDSerializer}), ) def create(self, request): """ Create Agent :param request: create parameter :return: agent ID :rtype: uuid """ serializer = AgentCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") agent_type = serializer.validated_data.get("type") urls = serializer.validated_data.get("urls") config_file = serializer.validated_data.get("config_file") organization = serializer.validated_data.get("organization") body = { "type": agent_type, "urls": urls, "name": name, } if name: agent_count = Agent.objects.filter(name=name).count() if agent_count > 0: raise ResourceExists(detail="Name %s already exists" % name) body.update({"name": name}) if config_file is not None: body.update({"config_file": config_file}) if organization is not None: org = Organization.objects.get(id=organization) if org.organization.all(): raise ResourceExists else: body.update({"organization": org}) agent = Agent(**body) agent.save() response = AgentIDSerializer(data=agent.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) @swagger_auto_schema(responses=with_common_response( {status.HTTP_200_OK: AgentInfoSerializer})) def retrieve(self, request, pk=None): """ Retrieve agent :param request: destory parameter :param pk: primary key :return: none :rtype: rest_framework.status """ try: if request.user.is_operator: agent = Agent.objects.get(id=pk) else: agent = Agent.objects.get( id=pk, organization=request.user.organization) k8s_config = None if agent.type == HostType.Kubernetes.name.lower(): k8s_config = KubernetesConfig.objects.get(agent=agent) except ObjectDoesNotExist: raise ResourceNotFound else: data = agent.__dict__ if k8s_config: data.update({"k8s_config": k8s_config.__dict__}) response = AgentInfoSerializer(data=data) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=AgentUpdateBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update Agent Update special agent with id. """ pass @swagger_auto_schema( request_body=AgentPatchBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def partial_update(self, request, pk=None): """ Partial Update Agent Partial update special agent with id. """ serializer = AgentPatchBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") capacity = serializer.validated_data.get("capacity") log_level = serializer.validated_data.get("log_level") try: agent = Agent.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: if name: agent.name = name if capacity: agent.capacity = capacity if log_level: agent.log_level = log_level agent.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema(responses=with_common_response({ status.HTTP_204_NO_CONTENT: "No Content", status.HTTP_404_NOT_FOUND: "Not Found", })) def destroy(self, request, pk=None): """ Delete Agent Delete agent """ try: agent = Agent.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: if agent.organization is not None: raise ResourceInUse agent.delete() return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema( method="post", request_body=AgentApplySerializer, responses=with_common_response({status.HTTP_200_OK: AgentIDSerializer}), ) @action(methods=["post"], detail=False, url_path="organization") def apply(self, request): """ Apply Agent Apply Agent """ serializer = AgentApplySerializer(data=request.data) if serializer.is_valid(raise_exception=True): agent_type = serializer.validated_data.get("type") capacity = serializer.validated_data.get("capacity") if request.user.organization is None: raise CustomError(detail="Need join in organization") agent_count = Agent.objects.filter( organization=request.user.organization).count() if agent_count > 0: raise CustomError(detail="Already applied agent.") agents = Agent.objects.filter( organization__isnull=True, type=agent_type, capacity__gte=capacity, schedulable=True, ).order_by("capacity") if len(agents) == 0: raise NoResource agent = agents[0] agent.organization = request.user.organization agent.save() response = AgentIDSerializer(data=agent.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( method="delete", responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"}), ) @action(methods=["delete"], detail=True, url_path="organization") def release(self, request, pk=None): """ Release Agent Release Agent """ try: if request.user.is_operator: agent = Agent.objects.get(id=pk) else: if request.user.organization is None: raise CustomError("Need join in organization") agent = Agent.objects.get( id=pk, organization=request.user.organization) except ObjectDoesNotExist: raise ResourceNotFound else: agent.organization = None agent.save() return Response(status=status.HTTP_204_NO_CONTENT)
class NetworkViewSet(viewsets.ViewSet): authentication_classes = (JSONWebTokenAuthentication, TokenAuth) def _genesis2base64(self, network): """ convert genesis.block to Base64 :param network: network id :return: genesis block :rtype: bytearray """ try: dir_node = "{}/{}/".format(CELLO_HOME, network) name = "genesis.block" zname = "block.zip" zip_file("{}{}".format(dir_node, name), "{}{}".format(dir_node, zname)) with open("{}{}".format(dir_node, zname), "rb") as f_block: block = base64.b64encode(f_block.read()) return block except Exception as e: raise e @swagger_auto_schema( query_serializer=NetworkQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse})), ) def list(self, request): """ List network :param request: query parameter :return: network list :rtype: list """ try: serializer = NetworkQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page", 1) per_page = serializer.validated_data.get("page", 10) org = request.user.organization networks = org.network if not networks: return Response(ok(data={ "total": 0, "data": None }), status=status.HTTP_200_OK) p = Paginator([networks], per_page) networks = p.page(page) networks = [{ "id": network.id, "name": network.name, "created_at": network.created_at, } for network in networks] response = NetworkListResponse(data={ "total": p.count, "data": networks }) if response.is_valid(raise_exception=True): return Response(ok(response.validated_data), status=status.HTTP_200_OK) return Response(ok(data={ "total": 0, "data": None }), status=status.HTTP_200_OK) except Exception as e: return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) def _agent_params(self, pk): """ get node's params from db :param node: node id :return: info """ try: node = Node.objects.get(id=pk) org = node.organization if org is None: raise ResourceNotFound network = org.network if network is None: raise ResourceNotFound agent = org.agent.get() if agent is None: raise ResourceNotFound ports = Port.objects.filter(node=node) if ports is None: raise ResourceNotFound info = {} org_name = org.name if node.type == "peer" else org.name.split( ".", 1)[1] # get info of node, e.g, tls, msp, config. info["status"] = node.status info["msp"] = node.msp info["tls"] = node.tls info["config_file"] = node.config_file info["type"] = node.type info["name"] = "{}.{}".format(node.name, org_name) info["bootstrap_block"] = network.genesisblock info["urls"] = agent.urls info["network_type"] = network.type info["agent_type"] = agent.type info["ports"] = ports return info except Exception as e: raise e def _start_node(self, pk): """ start node from agent :param node: node id :return: null """ try: infos = self._agent_params(pk) agent = AgentHandler(infos) cid = agent.create(infos) if cid: Node.objects.filter(id=pk).update(cid=cid) else: raise ResourceNotFound except Exception as e: raise e @swagger_auto_schema( request_body=NetworkCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NetworkIDSerializer}), ) def create(self, request): """ Create Network :param request: create parameter :return: organization ID :rtype: uuid """ try: serializer = NetworkCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") consensus = serializer.validated_data.get("consensus") database = serializer.validated_data.get("database") try: if Network.objects.get(name=name): raise ResourceExists except ObjectDoesNotExist: pass org = request.user.organization if org.network: raise ResourceExists orderers = [] peers = [] orderers.append({"name": org.name, "hosts": []}) peers.append({"name": org.name, "hosts": []}) nodes = Node.objects.filter(organization=org) for node in nodes: if node.type == "peer": peers[0]["hosts"].append({"name": node.name}) elif node.type == "orderer": orderers[0]["hosts"].append({"name": node.name}) ConfigTX(name).create(consensus=consensus, orderers=orderers, peers=peers) ConfigTxGen(name).genesis() block = self._genesis2base64(name) network = Network(name=name, consensus=consensus, genesisblock=block) network.save() org.network = network org.save() nodes = Node.objects.filter(organization=org) for node in nodes: try: threading.Thread(target=self._start_node, args=(node.id, )).start() except Exception as e: raise e response = NetworkIDSerializer(data=network.__dict__) if response.is_valid(raise_exception=True): return Response(ok(response.validated_data), status=status.HTTP_201_CREATED) except ResourceExists as e: raise e except Exception as e: return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema(responses=with_common_response()) def retrieve(self, request, pk=None): """ Get Network Get network information """ pass @swagger_auto_schema(responses=with_common_response( {status.HTTP_202_ACCEPTED: "No Content"})) def destroy(self, request, pk=None): """ Delete Network :param request: destory parameter :param pk: primary key :return: none :rtype: rest_framework.status """ try: network = Network.objects.get(pk=pk) path = "{}/{}".format(CELLO_HOME, network.name) if os.path.exists(path): shutil.rmtree(path, True) network.delete() return Response(ok(None), status=status.HTTP_202_ACCEPTED) except Exception as e: return Response(err(e.args), status=status.HTTP_400_BAD_REQUEST) @swagger_auto_schema( methods=["get"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse}), ) @swagger_auto_schema( methods=["post"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse}), ) @action(methods=["get", "post"], detail=True, url_path="peers") def peers(self, request, pk=None): """ get: Get Peers Get peers of network. post: Add New Peer Add peer into network """ pass @swagger_auto_schema( methods=["delete"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse}), ) @action(methods=["delete"], detail=True, url_path="peers/<str:peer_id>") def delete_peer(self, request, pk=None, peer_id=None): """ delete: Delete Peer Delete peer in network """ pass
class FileViewSet(viewsets.ViewSet): authentication_classes = (JSONWebTokenAuthentication,) permission_classes = ( IsAuthenticated, any_of(IsAdminAuthenticated, IsOperatorAuthenticated), ) @staticmethod def _validate_organization(request): if not request.user.is_operator and request.user.organization is None: raise CustomError(detail="Need join in organization.") @swagger_auto_schema( query_serializer=FileQuerySerializer, responses=with_common_response( {status.HTTP_200_OK: FileListSerializer} ), ) def list(self, request): """ List Files Filter files with query parameters, """ serializer = FileQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") file_type = serializer.validated_data.get("type") organization = serializer.validated_data.get("organization") page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") if organization is not None and not request.user.is_operator: raise PermissionDenied query_filter = {} if name: query_filter.update({"name__icontains": name}) if file_type: query_filter.update({"type": file_type}) if organization: query_filter.update({"organization": organization}) files = File.objects.filter(**query_filter) p = Paginator(files, per_page) files = p.page(page) files = [ { "id": str(file.id), "name": file.name, "type": file.type, "url": request.build_absolute_uri(file.file.url), "organization": file.organization.id, } for file in files ] response = FileListSerializer( data={"data": files, "total": p.count} ) if response.is_valid(raise_exception=True): return Response( response.validated_data, status=status.HTTP_200_OK ) @swagger_auto_schema( request_body=FileCreateSerializer, responses=with_common_response( {status.HTTP_201_CREATED: FileIDSerializer} ), ) def create(self, request): """ Create new file Create new file """ serializer = FileCreateSerializer(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") file_type = serializer.validated_data.get("type") file = serializer.validated_data.get("file") self._validate_organization(request) file = File( name=name, type=file_type, file=file, organization=request.user.organization, ) file.save() response = FileIDSerializer(data=file.__dict__) if response.is_valid(raise_exception=True): return Response( response.validated_data, status=status.HTTP_201_CREATED )
class OrganizationViewSet(viewsets.ViewSet): authentication_classes = (JSONWebTokenAuthentication, ) permission_classes = (IsAuthenticated, IsOperatorAuthenticated) @swagger_auto_schema( query_serializer=OrganizationQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: OrganizationList})), ) def list(self, request): """ List Organizations List organizations through query parameter """ serializer = OrganizationQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page", 1) per_page = serializer.validated_data.get("per_page", 10) name = serializer.validated_data.get("name") parameters = {} if name: parameters.update({"name__icontains": name}) organizations = Organization.objects.filter(**parameters) p = Paginator(organizations, per_page) organizations = p.page(page) organizations = [{ "id": str(organization.id), "name": organization.name, "created_at": organization.created_at, } for organization in organizations] response = OrganizationList(data={ "total": p.count, "data": organizations }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=OrganizationCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: OrganizationIDSerializer}), ) def create(self, request): """ Create Organization Create Organization """ serializer = OrganizationCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") try: Organization.objects.get(name=name) except ObjectDoesNotExist: pass else: raise ResourceExists organization = Organization(name=name) organization.save() response = OrganizationIDSerializer(data=organization.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete Organization Delete Organization """ try: organization = Organization.objects.get(id=pk) user_count = UserProfile.objects.filter( organization=organization).count() if user_count > 0: raise ResourceInUse organization.delete() except ObjectDoesNotExist: raise ResourceNotFound return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema(responses=with_common_response( {status.HTTP_200_OK: OrganizationResponse})) def retrieve(self, request, pk=None): """ Retrieve Organization Retrieve Organization """ try: organization = Organization.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: response = OrganizationResponse(data=organization.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @staticmethod def _list_users(request, pk=None): serializer = UserQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): try: organization = Organization.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") name = serializer.validated_data.get("name") parameter = {"organization": organization} if name: parameter.update({"name__icontains": name}) users = UserProfile.objects.filter(**parameter) p = Paginator(users, per_page) users = p.page(page) users = [{ "id": str(user.id), "name": user.name, "role": user.role } for user in users] response = UserListSerializer(data={ "total": p.count, "data": users }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @staticmethod def _add_user(request, pk=None): serializer = UserIDSerializer(data=request.data) if serializer.is_valid(raise_exception=True): user_id = serializer.validated_data.get("id") try: organization = Organization.objects.get(id=pk) user = UserProfile.objects.get(id=user_id) if user.govern: raise ResourceInUse except ObjectDoesNotExist: raise ResourceNotFound else: keycloak_client = KeyCloakClient() user_info = keycloak_client.get_user(user.name) user_attr = user_info.get("attributes", {}) user_attr.update({"organization": pk}) keycloak_client.update_user(user_id, body={"attributes": user_attr}) user.organization = organization user.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema( method="get", query_serializer=UserQuerySerializer, responses=with_common_response( {status.HTTP_200_OK: UserListSerializer}), ) @swagger_auto_schema( method="post", request_body=UserIDSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["get", "post"], detail=True, url_path="users") def manage_users(self, request, pk=None): """ get: List users List users in Organization post: Add User Add user into Organization """ if request.method == "GET": return self._list_users(request, pk) elif request.method == "POST": return self._add_user(request, pk) @swagger_auto_schema( method="delete", responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"}), ) @action(methods=["delete"], detail=True, url_path="users/(?P<user_id>[^/.]+)") def remove_user_from_govern(self, request, pk=None, user_id=None): """ Remove user from Organization Remove user from Organization """ try: user = UserProfile.objects.get(id=user_id, organization__id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: keycloak_client = KeyCloakClient() user_info = keycloak_client.get_user(user.name) user_attr = user_info.get("attributes", {}) if "organization" in user_attr: del user_attr["organization"] keycloak_client.update_user(user_id, body={"attributes": user_attr}) user.govern = None user.save() return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="certificates") def request_certificate(self, request, pk=None): """ post: Request Certificate Request certificate """ pass
class AgentViewSet(viewsets.ViewSet): @swagger_auto_schema( query_serializer=AgentQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: AgentListResponse})), ) def list(self, request, *args, **kwargs): """ List Agents Filter agents with query parameters. """ return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=AgentCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: AgentIDSerializer}), ) def create(self, request): """ Create Agent Create new agent """ pass @swagger_auto_schema( request_body=AgentUpdateBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update Agent Update special agent with id. """ pass @swagger_auto_schema( request_body=AgentPatchBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def partial_update(self, request, pk=None): """ Partial Update Agent Partial update special agent with id. """ pass @swagger_auto_schema(responses=with_common_response({ status.HTTP_204_NO_CONTENT: "No Content", status.HTTP_404_NOT_FOUND: "Not Found", })) def destroy(self, request, pk=None): """ Delete Agent Delete agent """ pass
class NodeViewSet(viewsets.ViewSet): #authentication_classes = (TokenAuth, JSONWebTokenAuthentication) # Only operator can update node info # def get_permissions(self): # if self.action in ["update"]: # permission_classes = (IsAuthenticated, IsOperatorAuthenticated) # else: # permission_classes = (IsAuthenticated,) # # return [permission() for permission in permission_classes] @staticmethod def _validate_organization(request): if request.user.organization is None: raise CustomError(detail="Need join in organization.") @swagger_auto_schema( query_serializer=NodeQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NodeListSerializer})), ) def list(self, request, *args, **kwargs): """ List node :param request: query parameter :return: node list :rtype: list """ serializer = NodeQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") node_type = serializer.validated_data.get("type") name = serializer.validated_data.get("name") agent_id = serializer.validated_data.get("agent_id") # if agent_id is not None and not request.user.is_operator: # raise PermissionDenied query_filter = {} if node_type: query_filter.update({"type": node_type}) if name: query_filter.update({"name__icontains": name}) # if request.user.is_administrator: # query_filter.update( # {"organization": request.user.organization} # ) # elif request.user.is_common_user: # query_filter.update({"user": request.user}) if agent_id: query_filter.update({"agent__id": agent_id}) nodes = Node.objects.filter(**query_filter) p = Paginator(nodes, per_page) nodes = p.page(page) nodes = [{ "id": str(node.id), "name": node.name, "type": node.type, "org": node.org, "urls": node.urls, "network": str(node.org.network.id) if node.org.network else None, "agents": node.agent if node.agent else None, "channel": str(node.org.channel.id) if node.org.channel else None, "ports": node.port, "created_at": node.created_at, } for node in nodes] response = NodeListSerializer({"total": p.count, "data": nodes}) return Response(data=response.data, status=status.HTTP_200_OK) def _save_fabric_ca(self, request, ca=None): if ca is None: return None ca_body = {} admin_name = ca.get("admin_name") admin_password = ca.get("admin_password") # If found tls type ca server under this organization, # will cause resource exists error ca_server_type = ca.get("type", FabricCAServerType.Signature.value) if ca_server_type == FabricCAServerType.TLS.value: exist_ca_server = Node.objects.filter( organization=request.user.organization, ca__type=FabricCAServerType.TLS.value, ).count() if exist_ca_server > 0: raise ResourceExists hosts = ca.get("hosts", []) if admin_name: ca_body.update({"admin_name": admin_name}) if admin_password: ca_body.update({"admin_password": admin_password}) fabric_ca = FabricCA(**ca_body, hosts=hosts, type=ca_server_type) fabric_ca.save() return fabric_ca def _save_fabric_peer(self, request, peer=None): if peer is None: return None name = peer.get("name") gossip_use_leader_reflection = peer.get("gossip_use_leader_reflection") gossip_org_leader = peer.get("gossip_org_leader") gossip_skip_handshake = peer.get("gossip_skip_handshake") local_msp_id = peer.get("local_msp_id") ca_nodes = peer.get("ca_nodes") body = {"name": name, "local_msp_id": local_msp_id} if gossip_use_leader_reflection is not None: body.update( {"gossip_use_leader_reflection": gossip_use_leader_reflection}) if gossip_org_leader is not None: body.update({"gossip_org_leader": gossip_org_leader}) if gossip_skip_handshake is not None: body.update({"gossip_skip_handshake": gossip_skip_handshake}) fabric_peer = FabricPeer(**body) fabric_peer.save() ca_nodes_list = [] for ca_node in ca_nodes: node = ca_node.get("node") address = ca_node.get("address") certificate = ca_node.get("certificate") ca_type = ca_node.get("type") ca_body = {"peer": fabric_peer} ca_node_dict = {} if node is not None: ca_body.update({"node": node}) port = Port.objects.filter(node=node, internal=7054).first() if port: ca_node_dict.update( {"address": "%s:%s" % (node.agent.ip, port.external)}) ca_node_dict.update({ "type": node.ca.type, "certificate": request.build_absolute_uri(node.file.url), }) else: update_body = { "address": address, "certificate": certificate, "type": ca_type, } ca_body.update(update_body) ca_node_dict.update(update_body) peer_ca = PeerCa(**ca_body) peer_ca.save() users = ca_node.get("users") user_list = [] for ca_user in users: ca_user_body = {"peer_ca": peer_ca} user_dict = {} user = ca_user.get("user") username = ca_user.get("username") password = ca_user.get("password") user_type = ca_user.get("type") if user is not None: ca_user_body.update({"user": user}) user_dict.update({ "username": user.name, "password": user.secret, "type": user.user_type, }) else: update_body = { "username": username, "password": password, "type": user_type, } ca_user_body.update(update_body) user_dict.update(update_body) user_list.append(user_dict) ca_user_obj = PeerCaUser(**ca_user_body) ca_user_obj.save() ca_node_dict.update({"users": user_list}) ca_nodes_list.append(ca_node_dict) return fabric_peer, ca_nodes_list @swagger_auto_schema( request_body=NodeCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NodeIDSerializer}), ) def create(self, request): """ Create Node :param request: create parameter :return: node ID :rtype: uuid """ serializer = NodeCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): #self._validate_organization(request) name = serializer.validated_data.get("name") type = serializer.validated_data.get("type") urls = serializer.validated_data.get("urls") organization = serializer.validated_data.get("organization") org = Organization.objects.get(id=organization) agent = org.agent.get() if org and agent: pass else: raise NoResource nodes = {"type": type, "Specs": [name]} CryptoConfig(org.name).update(nodes) CryptoGen(org.name).extend() self._generate_config(type, org.name, name) msp, tls, cfg = self._conversion_msp_tls_cfg(type, org.name, name) node = Node(name=name, org=org, urls=urls, type=type, msp=msp, tls=tls, agent=agent, config_file=cfg) node.save() self._set_port(type, node, agent) response = NodeIDSerializer(data=node.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) def _set_port(self, type, node, agent): """ get free port from agent, :param type: node type :param node: node obj :param agent: agent obj :return: none :rtype: none """ ip = agent.urls.split(":")[1].strip("//") if type == "peer": ports = find_available_ports(ip, node.id, agent.id, 2) set_ports_mapping(node.id, [{ "internal": 7051, "external": ports[0] }, { "internal": 7053, "external": ports[1] }], True) else: ports = find_available_ports(ip, node.id, agent.id, 1) set_ports_mapping(node.id, [{ "internal": 7050, "external": ports[0] }], True) def _conversion_msp_tls_cfg(self, type, org, node): """ msp and tls , cfg from zip file to byte :param org: organization name :param type: node type :param node: node name :return: msp, tls, cfg :rtype: bytes """ try: if type == "peer": dir_node = "{}/{}/crypto-config/peerOrganizations/{}/peers/{}/" \ .format(CELLO_HOME, org, org, node + "." + org) name = "core.yaml" cname = "peer_config.zip" else: dir_node = "{}/{}/crypto-config/ordererOrganizations/{}/orderers/{}/" \ .format(CELLO_HOME, org, org.split(".", 1)[1], node + "." + org.split(".", 1)[1]) name = "orderer.yaml" cname = "orderer_config.zip" zip_dir("{}msp".format(dir_node), "{}msp.zip".format(dir_node)) with open("{}msp.zip".format(dir_node), "rb") as f_msp: msp = base64.b64encode(f_msp.read()) zip_dir("{}tls".format(dir_node), "{}tls.zip".format(dir_node)) with open("{}tls.zip".format(dir_node), "rb") as f_tls: tls = base64.b64encode(f_tls.read()) zip_file("{}{}".format(dir_node, name), "{}{}".format(dir_node, cname)) with open("{}{}".format(dir_node, cname), "rb") as f_cfg: cfg = base64.b64encode(f_cfg.read()) except Exception as e: raise e return msp, tls, cfg def _generate_config(self, type, org, node): """ generate config for node :param org: organization name :param type: node type :param node: node name :param port: node port(todo: automatic distribution port) :return: none :rtype: none """ args = {} if type == "peer": args.update({"peer_id": "{}.{}".format(node, org)}) args.update({"peer_address": "{}.{}:{}".format(node, org, 7051)}) args.update({ "peer_gossip_externalEndpoint": "{}.{}:{}".format(node, org, 7051) }) args.update( {"peer_chaincodeAddress": "{}.{}:{}".format(node, org, 7052)}) args.update({"peer_tls_enabled": True}) args.update({"peer_localMspId": "{}MSP".format(org.capitalize())}) a = NodeConfig(org) a.peer(node, **args) else: args.update({"General_ListenPort": 7050}) args.update({ "General_LocalMSPID": "{}OrdererMSP".format(org.capitalize()) }) args.update({"General_TLS_Enabled": True}) args.update({"General_BootstrapFile": "genesis.block"}) a = NodeConfig(org) a.orderer(node, **args) pass def _agent_params(self, pk): """ get node's params from db :param node: node id :return: info """ try: node = Node.objects.get(id=pk) org = node.org if org is None: raise ResourceNotFound network = org.network if network is None: raise ResourceNotFound agent = org.agent.get() if agent is None: raise ResourceNotFound info = {} # get info of node, e.g, tls, msp, config. info["status"] = node.status info["msp"] = node.msp info["tls"] = node.tls info["config_file"] = node.config_file info["type"] = node.type info["name"] = node.name info["bootstrap_block"] = network.genesisblock info["urls"] = agent.urls info["network_type"] = network.type info["agent_type"] = agent.type return info except Exception as e: raise e @swagger_auto_schema( methods=["post"], request_body=NodeOperationSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="operations") def operate(self, request, pk=None): """ Operate Node Do some operation on node, start/stop/restart """ serializer = NodeOperationSerializer(data=request.data) if serializer.is_valid(raise_exception=True): action = serializer.validated_data.get("action") if action == "start": try: infos = self._agent_params(pk) agent = AgentHandler(infos) cid = agent.create(infos) if cid: Node.objects.filter(id=pk).update(cid=cid) response = NodeCIDSerializer(data={"id": cid}) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) else: raise ResourceNotFound except Exception as e: raise e if infos.get("status") == "running" or infos.get( "status") == "deleting" or infos.get( "status") == "deploying": raise ResourceInUse elif infos.get("status") == "": pass elif infos.get("status") == "stopped" or infos.get( "status") == "deleted": pass elif infos.get("status") == "error": pass else: pass elif action == "stop": #todo pass elif action == "restart": # todo pass else: # todo pass @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete Node :param request: destory parameter :param pk: primary key :return: none :rtype: rest_framework.status """ try: node = Node.objects.get(id=pk) node.delete() # todo delete node from agent except ObjectDoesNotExist: raise ResourceNotFound return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema( operation_id="update node", request_body=NodeUpdateBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update Node Update special node with id. """ serializer = NodeUpdateBody(data=request.data) if serializer.is_valid(raise_exception=True): node_status = serializer.validated_data.get("status") ports = serializer.validated_data.get("ports", []) try: node = Node.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound node.status = node_status node.save() for port_item in ports: port = Port( external=port_item.get("external"), internal=port_item.get("internal"), node=node, ) port.save() return Response(status=status.HTTP_202_ACCEPTED) # @swagger_auto_schema( # methods=["post"], # request_body=NodeFileCreateSerializer, # responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), # ) # @action(methods=["post"], detail=True, url_path="files", url_name="files") # def upload_files(self, request, pk=None): # """ # Upload file to node # Upload related files to node # """ # serializer = NodeFileCreateSerializer(data=request.data) # if serializer.is_valid(raise_exception=True): # file = serializer.validated_data.get("file") # try: # node = Node.objects.get(id=pk) # except ObjectDoesNotExist: # raise ResourceNotFound # else: # # delete old file # if node.file: # node.file.delete() # node.file = file # node.save() # return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema(responses=with_common_response( with_common_response({status.HTTP_200_OK: NodeInfoSerializer}))) def retrieve(self, request, pk=None): """ Get Node information Get node detail information. """ self._validate_organization(request) try: node = Node.objects.get(id=pk, organization=request.user.organization) except ObjectDoesNotExist: raise ResourceNotFound else: # Set file url of node if node.file: node.file = request.build_absolute_uri(node.file.url) ports = Port.objects.filter(node=node) node.links = [{ "internal_port": port.internal, "url": "%s:%s" % (node.agent.ip, port.external), } for port in ports] response = NodeInfoSerializer(node) return Response(data=response.data, status=status.HTTP_200_OK) def _register_user(self, request, pk=None): serializer = NodeUserCreateSerializer(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") secret = serializer.validated_data.get("secret") user_type = serializer.validated_data.get("user_type") attrs = serializer.validated_data.get("attrs", "") try: node = Node.objects.get(id=pk, organization=request.user.organization) # Name is unique for each node user_count = NodeUser.objects.filter(node=node, name=name).count() if user_count > 0: raise ResourceExists except ObjectDoesNotExist: raise ResourceNotFound node_user = NodeUser( name=name, secret=secret, user_type=user_type, attrs=attrs, node=node, ) node_user.save() agent_config_file = request.build_absolute_uri( node.agent.config_file.url) node_file_url = request.build_absolute_uri(node.file.url) user_patch_url = self.reverse_action("patch-user", kwargs={ "pk": pk, "user_pk": node_user.id }) user_patch_url = request.build_absolute_uri(user_patch_url) operate_node.delay( str(node.id), AgentOperation.FabricCARegister.value, agent_config_file=agent_config_file, node_file_url=node_file_url, user_patch_url=user_patch_url, fabric_ca_user={ "name": name, "secret": secret, "type": user_type, "attrs": attrs, }, ) response = NodeUserIDSerializer(node_user) return Response(data=response.data, status=status.HTTP_201_CREATED) def _list_user(self, request, pk=None): serializer = NodeUserQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") name = serializer.validated_data.get("name") user_type = serializer.validated_data.get("user_type") user_status = serializer.validated_data.get("status") query_param = {"node__id": pk} if name is not None: query_param.update({"name__icontains": name}) if user_type is not None: query_param.update({"user_type": user_type}) if user_status is not None: query_param.update({"status": user_status}) users = NodeUser.objects.filter(**query_param) p = Paginator(users, per_page) users = p.page(page) response = NodeUserListSerializer({ "data": users, "total": p.count }) return Response(response.data, status=status.HTTP_200_OK) @swagger_auto_schema( methods=["post"], operation_description="Register user to node", operation_summary="Register user to node", request_body=NodeUserCreateSerializer, responses=with_common_response( {status.HTTP_201_CREATED: NodeUserIDSerializer}), ) @swagger_auto_schema( methods=["get"], operation_description="List user of node", operation_summary="List user of node", query_serializer=NodeUserQuerySerializer, responses=with_common_response( {status.HTTP_200_OK: NodeUserListSerializer}), ) @action( methods=["post", "get"], detail=True, url_path="users", url_name="users", ) def users(self, request, pk=None): if request.method == "POST": return self._register_user(request, pk) elif request.method == "GET": return self._list_user(request, pk) @swagger_auto_schema( methods=["patch"], request_body=NodeUserPatchSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action( methods=["patch"], detail=True, url_path="users/(?P<user_pk>[^/.]+)", url_name="patch-user", ) def patch_user(self, request, pk=None, user_pk=None): """ Patch user status for node Patch user status for node """ serializer = NodeUserPatchSerializer(data=request.data) if serializer.is_valid(raise_exception=True): try: node_user = NodeUser.objects.get(id=user_pk, node__id=pk) except ObjectDoesNotExist: raise ResourceNotFound node_user.status = serializer.validated_data.get("status") node_user.save() return Response(status=status.HTTP_202_ACCEPTED)
class UserViewSet(viewsets.ViewSet): authentication_classes = (CustomAuthenticate,) permission_classes = (IsAuthenticated,) @swagger_auto_schema( query_serializer=CompanyQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse}) ), ) def list(self, request, *args, **kwargs): """ List Users List user through query parameter """ LOG.info("user %s", request.user.role) return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=CompanyCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: CompanyIDSerializer} ), ) def create(self, request): """ Create User Create new user """ pass @swagger_auto_schema( responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"} ) ) def destroy(self, request, pk=None): """ Delete User Delete user """ pass @action( methods=["get", "post", "put", "delete"], detail=True, url_path="attributes", ) def attributes(self, request, pk=None): """ get: Get User Attributes Get attributes of user post: Create Attributes Create attribute for user put: Update Attribute Update attribute of user delete: Delete Attribute Delete attribute of user """ pass @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="password") def password(self, request, pk=None): """ post: Update/Reset Password Update/Reset password for user """ pass
class UserViewSet(viewsets.ViewSet): authentication_classes = (JSONWebTokenAuthentication, ) def get_permissions(self): permission_classes = [] if self.action not in ["auth"]: permission_classes = ( IsAuthenticated, any_of(IsAdminAuthenticated, IsOperatorAuthenticated), ) return [permission() for permission in permission_classes] @swagger_auto_schema(responses=with_common_response(with_common_response()) ) def list(self, request, *args, **kwargs): """ List Users List user through query parameter """ return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=UserCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: UserIDSerializer}), ) def create(self, request): """ Create User Create new user """ serializer = UserCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): username = serializer.validated_data.get("username") role = serializer.validated_data.get("role") organization = serializer.validated_data.get("organization") password = serializer.validated_data.get("password") email = serializer.validated_data.get("email") user_count = UserProfile.objects.filter( Q(username=username) | Q(email=email)).count() if user_count > 0: raise ResourceExists( detail="User name or email already exists") user = UserProfile( username=username, role=role, email=email, organization=organization, ) user.set_password(password) user.save() response = UserIDSerializer(data={"id": user.id}) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete User Delete user """ try: UserProfile.objects.get(id=pk).delete() except Exception as e: raise CustomError(detail=str(e)) else: return Response(status=status.HTTP_204_NO_CONTENT) @action( methods=["get", "post", "put", "delete"], detail=True, url_path="attributes", ) def attributes(self, request, pk=None): """ get: Get User Attributes Get attributes of user post: Create Attributes Create attribute for user put: Update Attribute Update attribute of user delete: Delete Attribute Delete attribute of user """ pass @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="password") def password(self, request, pk=None): """ post: Update/Reset Password Update/Reset password for user """ pass @swagger_auto_schema( method="post", request_body=UserAuthSerializer, responses=with_common_response( {status.HTTP_200_OK: UserAuthResponseSerializer}), ) @action(methods=["post"], detail=False, url_path="auth") def auth(self, request): """ Authenticate user with username & password Authenticate user with username & password """ serializer = UserAuthSerializer(data=request.data) if serializer.is_valid(raise_exception=True): username = serializer.validated_data.get("username") password = serializer.validated_data.get("password") try: token = keycloak_openid.token(username, password) except KeycloakAuthenticationError as e: error_msg = json.loads(e.error_message) raise CustomError( detail=error_msg.get("error_description", "")) response = UserAuthResponseSerializer(data=token) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK)
class ChannelViewSet(viewsets.ViewSet): """Class represents Channel related operations.""" authentication_classes = (JSONWebTokenAuthentication, TokenAuth) @swagger_auto_schema( query_serializer=PageQuerySerializer, responses=with_common_response( {status.HTTP_201_CREATED: ChannelListResponse}), ) def list(self, request): """ List Channels :param request: org_id :return: channel list :rtype: list """ serializer = PageQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") try: org = request.user.organization channels = Channel.objects.filter( organizations=org).order_by("create_ts") p = Paginator(channels, per_page) channels_pages = p.page(page) channels_list = [{ "id": channel.id, "name": channel.name, "network": channel.network.__dict__, "organizations": [{ "id": org.id, "name": org.name } for org in channel.organizations.all()], "create_ts": channel.create_ts, } for channel in channels_pages] response = ChannelListResponse(data={ "data": channels_list, "total": channels.count() }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) except ObjectDoesNotExist: pass @swagger_auto_schema( request_body=ChannelCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: ChannelIDSerializer}), ) def create(self, request): """ Create Channel :param request: create parameter :return: Channel ID :rtype: uuid """ serializer = ChannelCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") peers = serializer.validated_data.get("peers") orderers = serializer.validated_data.get("orderers") try: org = request.user.organization ConfigTX(org.network.name).createChannel(name, [org.name]) ConfigTxGen(org.network.name).channeltx( profile=name, channelid=name, outputCreateChannelTx="{}.tx".format(name)) tx_path = "{}/{}/channel-artifacts/{}.tx".format( CELLO_HOME, org.network.name, name) block_path = "{}/{}/channel-artifacts/{}.block".format( CELLO_HOME, org.network.name, name) ordering_node = Node.objects.get(id=orderers[0]) peer_node = Node.objects.get(id=peers[0]) envs = init_env_vars(peer_node, org) peer_channel_cli = PeerChannel("v2.2.0", **envs) peer_channel_cli.create(channel=name, orderer_url="{}.{}:{}".format( ordering_node.name, org.name.split(".", 1)[1], str(7050)), channel_tx=tx_path, output_block=block_path) for i in range(len(peers)): peer_node = Node.objects.get(id=peers[i]) envs = init_env_vars(peer_node, org) #envs["CORE_PEER_LOCALMSPID"] = '{}MSP'.format(peer_node.name.split(".")[0].capitalize()) #Org1MSP join_peers(envs, block_path) channel = Channel(name=name, network=org.network) channel.save() channel.organizations.add(org) channel.orderers.add(ordering_node) response = ChannelIDSerializer(data=channel.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) except ObjectDoesNotExist: pass @swagger_auto_schema( responses=with_common_response( {status.HTTP_200_OK: ChannelResponseSerializer}), ) def retrieve(self, request, pk=None): """ Retrieve channel :param request: retrieve parameter :param pk: primary key :return: none :rtype: rest_framework.status """ try: channel = Channel.objects.get(id=pk) response = ChannelResponseSerializer(instance=channel) return Response(response.data, status=status.HTTP_200_OK) except ObjectDoesNotExist: raise ResourceNotFound @swagger_auto_schema( request_body=ChannelUpdateSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update channel :param request: update parameters :param pk: primary key :return: none :rtype: rest_framework.status """ serializer = ChannelUpdateSerializer(data=request.data) if serializer.is_valid(raise_exception=True): peers = serializer.validated_data.get("peers") channel = Channel.objects.get(id=pk) try: org = request.user.organization org_name = org.name msp_id = org_name.split(".")[0].capitalize() dir_node = "{}/{}/crypto-config/peerOrganizations".format( CELLO_HOME, org_name) peer_cli_envs = { "CORE_PEER_LOCALMSPID": msp_id, "CORE_PEER_MSPCONFIGPATH": "{}/{}/users/Admin@{}/msp".format(dir_node, org_name, org_name), } join_peers(peers, peer_cli_envs, dir_node, org, channel.name) return Response(status=status.HTTP_202_ACCEPTED) except ObjectDoesNotExist: raise ResourceNotFound
class OrganizationViewSet(viewsets.ViewSet): """Class represents orgnization related operations.""" #authentication_classes = (JSONWebTokenAuthentication,) #permission_classes = (IsAuthenticated, IsOperatorAuthenticated) @swagger_auto_schema( query_serializer=OrganizationQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: OrganizationList})), ) def list(self, request): """ List Organizations :param request: query parameter :return: organization list :rtype: list """ serializer = OrganizationQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page", 1) per_page = serializer.validated_data.get("per_page", 10) name = serializer.validated_data.get("name") parameters = {} if name: parameters.update({"name__icontains": name}) organizations = Organization.objects.filter(**parameters) p = Paginator(organizations, per_page) organizations = p.page(page) organizations = [{ "id": str(organization.id), "name": organization.name, "created_at": organization.created_at, } for organization in organizations] response = OrganizationList(data={ "total": p.count, "data": organizations }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=OrganizationCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: OrganizationIDSerializer}), ) def create(self, request): """ Create Organization :param request: create parameter :return: organization ID :rtype: uuid """ serializer = OrganizationCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") try: Organization.objects.get(name=name) except ObjectDoesNotExist: pass else: raise ResourceExists CryptoConfig(name).create() CryptoGen(name).generate() msp, tls = self._conversion_msp_tls(name) organization = Organization(name=name, msp=msp, tls=tls) organization.save() response = OrganizationIDSerializer(data=organization.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) def _conversion_msp_tls(self, name): """ msp and tls from zip file to byte :param name: organization name :return: msp, tls :rtype: bytes """ try: dir_org = "{}/{}/crypto-config/peerOrganizations/{}/" \ .format(CELLO_HOME, name, name) zip_dir("{}msp".format(dir_org), "{}msp.zip".format(dir_org)) with open("{}msp.zip".format(dir_org), "rb") as f_msp: msp = base64.b64encode(f_msp.read()) zip_dir("{}tlsca".format(dir_org), "{}tls.zip".format(dir_org)) with open("{}tls.zip".format(dir_org), "rb") as f_tls: tls = base64.b64encode(f_tls.read()) except Exception as e: raise e return msp, tls @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete Organization :param request: destory parameter :param pk: primary key :return: none :rtype: rest_framework.status """ try: organization = Organization.objects.get(id=pk) if organization.network: raise ResourceInUse # user_count = UserProfile.objects.filter( # organization=organization # ).count() # if user_count > 0: # raise ResourceInUse organization.delete() except ObjectDoesNotExist: raise ResourceNotFound return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema(responses=with_common_response( {status.HTTP_200_OK: OrganizationResponse})) def retrieve(self, request, pk=None): """ Retrieve Organization :param request: retrieve parameter :param pk: primary key :return: organization info :rtype: OrganizationResponse """ try: organization = Organization.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: response = OrganizationResponse(data=organization.__dict__) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @staticmethod def _list_users(request, pk=None): serializer = UserQuerySerializer(data=request.GET) if serializer.is_valid(raise_exception=True): try: organization = Organization.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") name = serializer.validated_data.get("name") parameter = {"organization": organization} if name: parameter.update({"username__icontains": name}) users = UserProfile.objects.filter(**parameter) p = Paginator(users, per_page) users = p.page(page) users = [{ "id": str(user.id), "username": user.username, "role": user.role, } for user in users] response = UserListSerializer(data={ "total": p.count, "data": users }) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_200_OK) @staticmethod def _add_user(request, pk=None): serializer = UserIDSerializer(data=request.data) if serializer.is_valid(raise_exception=True): user_id = serializer.validated_data.get("id") try: organization = Organization.objects.get(id=pk) user = UserProfile.objects.get(id=user_id) if user.organization: raise ResourceInUse except ObjectDoesNotExist: raise ResourceNotFound else: user.organization = organization user.save() return Response(status=status.HTTP_202_ACCEPTED) @swagger_auto_schema( method="get", query_serializer=UserQuerySerializer, responses=with_common_response( {status.HTTP_200_OK: UserListSerializer}), ) @swagger_auto_schema( method="post", request_body=UserIDSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["get", "post"], detail=True, url_path="users") def manage_users(self, request, pk=None): """ get: List users List users in Organization post: Add User Add user into Organization """ if request.method == "GET": return self._list_users(request, pk) elif request.method == "POST": return self._add_user(request, pk) @swagger_auto_schema( method="delete", responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"}), ) @action(methods=["delete"], detail=True, url_path="users/(?P<user_id>[^/.]+)") def remove_user_from_govern(self, request, pk=None, user_id=None): """ Remove user from Organization Remove user from Organization """ try: user = UserProfile.objects.get(id=user_id, organization__id=pk) except ObjectDoesNotExist: raise ResourceNotFound else: user.organization = None user.save() return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="certificates") def request_certificate(self, request, pk=None): """ post: Request Certificate Request certificate """ pass
class NodeViewSet(viewsets.ViewSet): authentication_classes = (CustomAuthenticate, JSONWebTokenAuthentication) # Only operator can update node info def get_permissions(self): if self.action in ["update"]: permission_classes = (IsAuthenticated, IsOperatorAuthenticated) else: permission_classes = (IsAuthenticated, ) return [permission() for permission in permission_classes] @staticmethod def _validate_organization(request): if request.user.organization is None: raise CustomError(detail="Need join in organization.") @swagger_auto_schema( query_serializer=NodeQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NodeListSerializer})), ) def list(self, request, *args, **kwargs): """ List Nodes Filter nodes with query parameters. """ serializer = NodeQuery(data=request.GET) if serializer.is_valid(raise_exception=True): page = serializer.validated_data.get("page") per_page = serializer.validated_data.get("per_page") node_type = serializer.validated_data.get("type") name = serializer.validated_data.get("name") network_type = serializer.validated_data.get("network_type") network_version = serializer.validated_data.get("network_version") agent_id = serializer.validated_data.get("agent_id") if agent_id is not None and not request.user.is_operator: raise PermissionDenied query_filter = {} if node_type: query_filter.update({"type": node_type}) if name: query_filter.update({"name__icontains": name}) if network_type: query_filter.update({"network_type": network_type}) if network_version: query_filter.update({"network_version": network_version}) if request.user.is_administrator: query_filter.update( {"organization": request.user.organization}) elif request.user.is_common_user: query_filter.update({"user": request.user}) if agent_id: query_filter.update({"agent__id": agent_id}) nodes = Node.objects.filter(**query_filter) p = Paginator(nodes, per_page) nodes = p.page(page) nodes = [node.__dict__ for node in nodes] response = NodeListSerializer(data={ "total": p.count, "data": nodes }) if response.is_valid(raise_exception=True): return Response(data=response.validated_data, status=status.HTTP_200_OK) @swagger_auto_schema( request_body=NodeCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NodeIDSerializer}), ) def create(self, request): """ Create Node Create node """ serializer = NodeCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): self._validate_organization(request) agent_type = serializer.validated_data.get("agent_type") network_type = serializer.validated_data.get("network_type") network_version = serializer.validated_data.get("network_version") agent = serializer.validated_data.get("agent") node_type = serializer.validated_data.get("type") if agent is None: available_agents = (Agent.objects.annotate( network_num=Count("node__network")).annotate( node_num=Count("node")).filter( schedulable=True, type=agent_type, network_num__lt=F("capacity"), node_num__lt=F("node_capacity"), organization=request.user.organization, ).order_by("node_num")) if len(available_agents) > 0: agent = available_agents[0] else: raise NoResource else: if not request.user.is_operator: raise PermissionDenied node_count = Node.objects.filter(agent=agent).count() if node_count >= agent.node_capacity or not agent.schedulable: raise NoResource node = Node( network_type=network_type, agent=agent, network_version=network_version, user=request.user, organization=request.user.organization, type=node_type, ) node.save() agent_config_file = (request.build_absolute_uri( agent.config_file.url), ) node_update_api = reverse("node-detail", args=[str(node.id)]) node_update_api = request.build_absolute_uri(node_update_api) if isinstance(agent_config_file, tuple): agent_config_file = list(agent_config_file)[0] create_node.delay( str(node.id), agent.image, agent_config_file=agent_config_file, node_update_api=node_update_api, ) response = NodeIDSerializer(data={"id": str(node.id)}) if response.is_valid(raise_exception=True): return Response(response.validated_data, status=status.HTTP_201_CREATED) @swagger_auto_schema( methods=["post"], query_serializer=NodeOperationSerializer, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="operations") def operate(self, request, pk=None): """ Operate Node Do some operation on node, start/stop/restart """ pass @swagger_auto_schema(responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"})) def destroy(self, request, pk=None): """ Delete Node Delete node """ try: if request.user.is_superuser: node = Node.objects.get(id=pk) else: node = Node.objects.get(id=pk, organization=request.user.organization) except ObjectDoesNotExist: raise ResourceNotFound else: if node.status != NodeStatus.Deleting.name.lower(): if node.status != NodeStatus.Error.name.lower(): node.status = NodeStatus.Deleting.name.lower() node.save() delete_node.delay(str(node.id)) else: node.delete() return Response(status=status.HTTP_204_NO_CONTENT) @swagger_auto_schema( operation_id="update node", request_body=NodeUpdateBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) def update(self, request, pk=None): """ Update Node Update special node with id. """ serializer = NodeUpdateBody(data=request.data) if serializer.is_valid(raise_exception=True): node_status = serializer.validated_data.get("status") ports = serializer.validated_data.get("ports") try: node = Node.objects.get(id=pk) except ObjectDoesNotExist: raise ResourceNotFound node.status = node_status node.save() for port_item in ports: port = Port( external=port_item.get("external"), internal=port_item.get("internal"), node=node, ) port.save() return Response(status=status.HTTP_202_ACCEPTED)
class CompanyViewSet(viewsets.ViewSet): @swagger_auto_schema( query_serializer=CompanyQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse}) ), ) def list(self, request, *args, **kwargs): """ List Companies List company through query parameter """ return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=CompanyCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: CompanyIDSerializer} ), ) def create(self, request): """ Create Company Create new company """ pass @swagger_auto_schema( responses=with_common_response( {status.HTTP_204_NO_CONTENT: "No Content"} ) ) def destroy(self, request, pk=None): """ Delete Company Delete company """ pass @swagger_auto_schema(method="get", responses=with_common_response()) @swagger_auto_schema(method="post", responses=with_common_response()) @swagger_auto_schema(method="delete", responses=with_common_response()) @action(methods=["get", "post", "delete"], detail=True, url_path="users") def users(self, request, pk=None): """ get: List users List users in company post: Add User Add user into company delete: Delete User Delete user from company """ pass @swagger_auto_schema(method="post", responses=with_common_response()) @action(methods=["post"], detail=True, url_path="certificates") def request_certificate(self, request, pk=None): """ post: Request Certificate Request certificate """ pass
class NetworkViewSet(viewsets.ViewSet): @swagger_auto_schema( query_serializer=NetworkQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse})), ) def list(self, request): """ List Networks Filter networks with query parameters. """ return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema( request_body=NetworkCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NetworkIDSerializer}), ) def create(self, request): """ New Network Create new network through internal nodes, or import exists network outside """ pass @swagger_auto_schema(responses=with_common_response()) def retrieve(self, request, pk=None): """ Get Network Get network information """ pass @swagger_auto_schema( methods=["get"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse}), ) @swagger_auto_schema( methods=["post"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse}), ) @action(methods=["get", "post"], detail=True, url_path="peers") def peers(self, request, pk=None): """ get: Get Peers Get peers of network. post: Add New Peer Add peer into network """ pass @swagger_auto_schema( methods=["delete"], responses=with_common_response( {status.HTTP_200_OK: NetworkMemberResponse}), ) @action(methods=["delete"], detail=True, url_path="peers/<str:peer_id>") def delete_peer(self, request, pk=None, peer_id=None): """ delete: Delete Peer Delete peer in network """ pass
class NetworkViewSet(viewsets.ViewSet): @swagger_auto_schema( query_serializer=NetworkQuery, responses=with_common_response( with_common_response({status.HTTP_200_OK: NetworkListResponse})), ) def list(self, request): """ List Networks Filter networks with query parameters. """ return Response(data=[], status=status.HTTP_200_OK) @swagger_auto_schema(responses=with_common_response( {status.HTTP_201_CREATED: "Created"})) def create(self, request): """ New Network Create new network through internal nodes, or import exists network outside """ pass @swagger_auto_schema( methods=["post"], request_body=NetworkOperationBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action(methods=["post"], detail=True, url_path="operations") def operate(self, request, pk=None): """ Operate Network Operate on network """ pass @swagger_auto_schema( methods=["post"], request_body=ChannelCreateBody, responses=with_common_response({status.HTTP_201_CREATED: ChannelID}), ) @action( methods=["post"], detail=True, url_path="channels", url_name="create_channel", ) def create_channel(self, request, pk=None): """ Create Channel Create new channel in network """ pass @swagger_auto_schema( methods=["put"], request_body=ChannelBody, responses=with_common_response({status.HTTP_202_ACCEPTED: "Accepted"}), ) @action( methods=["put"], detail=True, url_path="channels/<str:channel_id>", url_name="update_channel", ) def update_channel(self, request, pk=None, channel_id=None): """ Update Channel Update channel in network """ pass @swagger_auto_schema(methods=["get"], responses=with_common_response()) @action(methods=["get"], detail=True, url_path="members") def members(self, request, pk=None): """ Get Consortium Members Get consortium members of network. """ pass @swagger_auto_schema( method="get", operation_id="Get Channel Members", operation_description="Get members of channel", responses=with_common_response(), ) @swagger_auto_schema( method="post", operation_id="Join Node Into Channel", operation_description="Join peer node into channel", responses=with_common_response(), ) @swagger_auto_schema( method="delete", operation_id="Remove Node From Channel", operation_description="Remove peer from channel", responses=with_common_response(), ) @action( methods=["get", "post", "delete"], detail=True, url_path="channels/<str:channel_id>/members", ) def channel_members(self, request, pk=None, channel_id=None): pass
infos = self._agent_params(pk) agent = AgentHandler(infos) cid = agent.create(infos) if cid: Node.objects.filter(id=pk).update(cid=cid) else: raise ResourceNotFound except Exception as e: raise e @swagger_auto_schema( request_body=NetworkCreateBody, responses=with_common_response( {status.HTTP_201_CREATED: NetworkIDSerializer} ), ) def create(self, request): """ Create Network :param request: create parameter :return: organization ID :rtype: uuid """ serializer = NetworkCreateBody(data=request.data) if serializer.is_valid(raise_exception=True): name = serializer.validated_data.get("name") consensus = serializer.validated_data.get("consensus") organizations = serializer.validated_data.get("organizations")