views.py 4.09 KB
Newer Older
Lukas Burgey's avatar
Lukas Burgey committed
1
import logging
2
from django.shortcuts import get_object_or_404
Lukas Burgey's avatar
Lukas Burgey committed
3
4
5
6
from rest_framework import views, viewsets
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework import status
Lukas Burgey's avatar
Lukas Burgey committed
7
8
9
10
from . import serializers
from .. import models

LOGGER = logging.getLogger(__name__)
Lukas Burgey's avatar
Lukas Burgey committed
11

Lukas Burgey's avatar
Lukas Burgey committed
12

Lukas Burgey's avatar
Lukas Burgey committed
13
14
15
16
17
18
19
20
21
def user_services(user):
    if user.is_authenticated:
        return (
            models.Service.objects
            .filter(groups__user=user)
            .distinct()
        )

    return []
Lukas Burgey's avatar
Lukas Burgey committed
22
23
24

def _api_error_response():
    return Response({'ok': False}, status=status.HTTP_400_BAD_REQUEST)
Lukas Burgey's avatar
Lukas Burgey committed
25
26


27
# Response for StateView, LogoutView, and all post requests
Lukas Burgey's avatar
Lukas Burgey committed
28
def _api_state_response(request):
29
    response = {
Lukas Burgey's avatar
Lukas Burgey committed
30
31
        'logged_in': request.user.is_authenticated()
    }
32
33
34
    if request.user.is_authenticated():
        response['user'] = serializers.UserSerializer(request.user).data

Lukas Burgey's avatar
Lukas Burgey committed
35
36
37
38
    response['services'] = serializers.ServiceSerializer(
        user_services(request.user),
        many=True,
    ).data
39

40
41
42
43
44
    if 'error' in request.session:
        response['error'] = request.session['error']
        # we display errors only once
        del request.session['error']

45
46
47
    return Response(response)


Lukas Burgey's avatar
Lukas Burgey committed
48
49
50
class StateView(views.APIView):
    permission_classes = (AllowAny,)

Lukas Burgey's avatar
Lukas Burgey committed
51
    def get(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
52
        return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
53
54
55
56
57
58
59
60


class ServiceViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.ServiceSerializer
    queryset = models.Service.objects.all()


class SSHPublicKeyView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
61
    def post(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
62
        if 'type' not in request.data:
Lukas Burgey's avatar
Lukas Burgey committed
63
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
64
65
66
67
68
69

        request_type = request.data['type']

        if request_type == 'remove':
            if 'name' in request.data:
                key = get_object_or_404(
Lukas Burgey's avatar
Lukas Burgey committed
70
71
72
                    models.SSHPublicKey,
                    name=request.data['name']
                )
Lukas Burgey's avatar
Lukas Burgey committed
73
74
                # we do not delete ssh keys directly, as we need to keep track
                # of them until all clients have also deleted them
75
76
77

                # key state: -> (1), if there are no deployments
                # key state: -> (5), if there are deployments
78
                key.delete_key()
Lukas Burgey's avatar
Lukas Burgey committed
79
                return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
80
81
82
        elif request_type == 'add':
            if 'key' in request.data:
                key = models.SSHPublicKey(
Lukas Burgey's avatar
Lukas Burgey committed
83
84
85
86
                    user=request.user,
                    name=request.data['key']['name'],
                    key=request.data['key']['key'],
                )
87
                # key state: -> (2)
Lukas Burgey's avatar
Lukas Burgey committed
88
                key.save()
Lukas Burgey's avatar
Lukas Burgey committed
89
                return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
90

Lukas Burgey's avatar
Lukas Burgey committed
91
        return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
92

Lukas Burgey's avatar
Lukas Burgey committed
93
94

class DeploymentView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
95
    def post(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
96
97
98
99
        if (
                'type' not in request.data or
                'key' not in request.data or
                'service' not in request.data
Lukas Burgey's avatar
Lukas Burgey committed
100
        ):
Lukas Burgey's avatar
Lukas Burgey committed
101
            LOGGER.error(
Lukas Burgey's avatar
Lukas Burgey committed
102
103
                'Deployment api got invalid request {}'.format(
                    request.data))
Lukas Burgey's avatar
Lukas Burgey committed
104
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
105
106
107

        request_type = request.data['type']
        request_service = get_object_or_404(
Lukas Burgey's avatar
Lukas Burgey committed
108
109
            models.Service, name=request.data['service']
        )
Lukas Burgey's avatar
Lukas Burgey committed
110
        request_key = get_object_or_404(
Lukas Burgey's avatar
Lukas Burgey committed
111
112
113
            models.SSHPublicKey,
            name=request.data['key'],
        )
Lukas Burgey's avatar
Lukas Burgey committed
114
115

        # check if there is already an deployment
Lukas Burgey's avatar
Lukas Burgey committed
116
        # if not request.user.deployments.filter(service=request_service).exists():
Lukas Burgey's avatar
Lukas Burgey committed
117
118
119
        try:
            deployment = request.user.deployments.get(service=request_service)
        except Exception:
Lukas Burgey's avatar
Lukas Burgey committed
120
            if request_type == 'remove':
Lukas Burgey's avatar
Lukas Burgey committed
121
                return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
122
123

            deployment = models.Deployment(
Lukas Burgey's avatar
Lukas Burgey committed
124
125
126
                user=request.user,
                service=request_service,
            )
Lukas Burgey's avatar
Lukas Burgey committed
127
128
129
            deployment.save()

        if request_type == 'add':
130
            deployment.deploy_key(request_key)
Lukas Burgey's avatar
Lukas Burgey committed
131
        elif request_type == 'remove':
132
133
            deployment.withdraw_key(request_key)
        else:
Lukas Burgey's avatar
Lukas Burgey committed
134
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
135

136
        deployment.save()
Lukas Burgey's avatar
Lukas Burgey committed
137
        return _api_state_response(request)