Coverage for django_napse/api/spaces/views/space_view.py: 28%

95 statements  

« prev     ^ index     » next       coverage.py v7.4.3, created at 2024-03-12 13:49 +0000

1from rest_framework import status 

2from rest_framework.decorators import action 

3from rest_framework.response import Response 

4from rest_framework_api_key.permissions import HasAPIKey 

5 

6from django_napse.api.custom_permissions import HasFullAccessPermission, HasMasterKey, HasReadPermission 

7from django_napse.api.custom_viewset import CustomViewSet 

8from django_napse.api.spaces.serializers import SpaceDetailSerializer, SpaceMoneyFlowSerializer, SpaceSerializer 

9from django_napse.core.models import NapseSpace 

10from django_napse.utils.constants import EXCHANGE_TICKERS 

11from django_napse.utils.errors import SpaceError 

12 

13 

14class SpaceView(CustomViewSet): 

15 permission_classes = [HasFullAccessPermission] 

16 serializer_class = SpaceSerializer 

17 

18 def get_object(self): 

19 return self.get_queryset().get(uuid=self.kwargs["pk"]) 

20 

21 def get_queryset(self): 

22 return NapseSpace.objects.all() 

23 

24 def get_serializer_class(self, *args, **kwargs): 

25 actions: dict = { 

26 "list": SpaceSerializer, 

27 "retrieve": SpaceDetailSerializer, 

28 "create": SpaceSerializer, 

29 "update": SpaceSerializer, 

30 "partial_update": SpaceSerializer, 

31 "invest": SpaceMoneyFlowSerializer, 

32 "withdraw": SpaceMoneyFlowSerializer, 

33 } 

34 result = actions.get(self.action, None) 

35 return result if result else super().get_serializer_class() 

36 

37 def get_permissions(self): 

38 match self.action: 

39 case "retrieve": 

40 return [HasReadPermission()] 

41 case "list": 

42 return [HasAPIKey()] 

43 case "create": 

44 return [HasMasterKey()] 

45 

46 case _: 

47 return super().get_permissions() 

48 

49 def list(self, request): 

50 api_key = self.get_api_key(request) 

51 spaces = NapseSpace.objects.all() if api_key.is_master_key else NapseSpace.objects.filter(permissions__in=api_key.permissions.all()) 

52 serializer = self.get_serializer(spaces, many=True) 

53 return Response(serializer.data, status=status.HTTP_200_OK) 

54 

55 def retrieve(self, request, pk=None): 

56 instance = self.get_object() 

57 serializer = self.get_serializer(instance) 

58 return Response(serializer.data, status=status.HTTP_200_OK) 

59 

60 def create(self, request, *args, **kwargs): 

61 serializer = self.serializer_class(data=request.data) 

62 serializer.is_valid(raise_exception=True) 

63 space = serializer.save() 

64 serialized_space = self.get_serializer(space) 

65 return Response(serialized_space.data, status=status.HTTP_201_CREATED) 

66 

67 def update(self, request, *args, **kwargs): 

68 partial = kwargs.pop("partial", False) 

69 instance = self.get_object() 

70 

71 serializer = self.get_serializer(instance=instance, data=request.data, partial=partial) 

72 serializer.is_valid(raise_exception=True) 

73 serializer.save() 

74 return Response(status=status.HTTP_200_OK) 

75 

76 def partial_update(self, request, **kwargs): 

77 """Partial update the connected user.""" 

78 return self.update(request, partial=True, **kwargs) 

79 

80 def delete(self, request, *args, **kwargs): 

81 instance = self.get_object() 

82 try: 

83 instance.delete() 

84 except SpaceError.DeleteError: 

85 return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) 

86 return Response(status=status.HTTP_204_NO_CONTENT) 

87 

88 @action(detail=True, methods=["GET", "POST"]) 

89 def invest(self, request, pk=None): 

90 """Endpoint to invest on space. 

91 

92 GET: Return all {ticker: amount} which can be invested in the space. 

93 POST: Invest in the space. 

94 """ 

95 space: NapseSpace = self.get_object() 

96 if not space.testing: 

97 return Response(status=status.HTTP_501_NOT_IMPLEMENTED) 

98 

99 exchange_name: str = space.exchange_account.exchange.name 

100 

101 match request.method: 

102 case "GET": 

103 possible_investments = [{"ticker": ticker, "amount": 1_000_000} for ticker in EXCHANGE_TICKERS.get(exchange_name)] 

104 return Response(possible_investments, status=status.HTTP_200_OK) 

105 

106 case "POST": 

107 space = self.get_object() 

108 if not space.testing: 

109 error_msg: str = "Investing in real is not allowed yet." 

110 return Response(error_msg, status=status.HTTP_403_FORBIDDEN) 

111 serializer = self.get_serializer(data=request.data, instance=space, side="INVEST") 

112 serializer.is_valid(raise_exception=True) 

113 serializer.save() 

114 

115 case _: 

116 return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) 

117 

118 return Response(status=status.HTTP_200_OK) 

119 

120 @action(detail=True, methods=["GET", "POST"]) 

121 def withdraw(self, request, pk=None): 

122 """Endpoint to withdraw on space. 

123 

124 GET: Return all {ticker: amount} which can be withdrawn in the space. 

125 POST: Withdraw from the space. 

126 """ 

127 space: NapseSpace = self.get_object() 

128 if not space.testing: 

129 return Response(status=status.HTTP_501_NOT_IMPLEMENTED) 

130 

131 match request.method: 

132 case "GET": 

133 return Response(status=status.HTTP_200_OK) 

134 case "POST": 

135 return Response(status=status.HTTP_501_NOT_IMPLEMENTED) 

136 case _: 

137 return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)