views.py 4.03 KB
Newer Older
Lukas Burgey's avatar
Lukas Burgey committed
1
import logging
2
from django.shortcuts import get_object_or_404
3
from django.core.exceptions import ObjectDoesNotExist
Lukas Burgey's avatar
Lukas Burgey committed
4
5
6
7
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
8
9
10
11
from . import serializers
from .. import models

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

Lukas Burgey's avatar
Lukas Burgey committed
13

Lukas Burgey's avatar
Lukas Burgey committed
14
15
16
17
18
19
20
21
22
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
23
24
25

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


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

36

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

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

47
48
49
    return Response(response)


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

Lukas Burgey's avatar
Lukas Burgey committed
53
    def get(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
54
        return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
55
56


57
# pylint: disable=too-many-ancestors
Lukas Burgey's avatar
Lukas Burgey committed
58
59
60
61
62
63
class ServiceViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.ServiceSerializer
    queryset = models.Service.objects.all()


class SSHPublicKeyView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
64
    def post(self, request):
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
        if 'type' in request.data:
            if request.data['type'] == 'remove':
                if 'id' in request.data:
                    key = get_object_or_404(
                        models.SSHPublicKey,
                        id=request.data['id']
                    )
                    # we do not delete ssh keys directly, as we need to keep track
                    # of them until all clients have also deleted them
                    key.delete_key()
                    return _api_state_response(request)
            elif request.data['type'] == 'add':
                if 'key' in request.data:
                    key = models.SSHPublicKey(
                        user=request.user,
                        name=request.data['key']['name'],
                        key=request.data['key']['key'],
                    )
                    key.save()
                    return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
85

86
        LOGGER.error('SSHPublicKeyView: malformed request %s', request)
Lukas Burgey's avatar
Lukas Burgey committed
87
        return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
88

Lukas Burgey's avatar
Lukas Burgey committed
89
90

class DeploymentView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
91
    def post(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
92
93
94
95
        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
96
        ):
97
            LOGGER.error('Deployment api got invalid request %s', request.data)
Lukas Burgey's avatar
Lukas Burgey committed
98
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
99
100

        request_type = request.data['type']
101
102
        request_service = models.Service.objects.get(
            id=request.data['service'],
Lukas Burgey's avatar
Lukas Burgey committed
103
        )
104
105
        request_key = models.SSHPublicKey.objects.get(
            id=request.data['key'],
Lukas Burgey's avatar
Lukas Burgey committed
106
        )
Lukas Burgey's avatar
Lukas Burgey committed
107
108

        # check if there is already an deployment
Lukas Burgey's avatar
Lukas Burgey committed
109
        # if not request.user.deployments.filter(service=request_service).exists():
Lukas Burgey's avatar
Lukas Burgey committed
110
111
        try:
            deployment = request.user.deployments.get(service=request_service)
112
        except ObjectDoesNotExist:
Lukas Burgey's avatar
Lukas Burgey committed
113
            if request_type == 'remove':
Lukas Burgey's avatar
Lukas Burgey committed
114
                return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
115
116

            deployment = models.Deployment(
Lukas Burgey's avatar
Lukas Burgey committed
117
118
119
                user=request.user,
                service=request_service,
            )
Lukas Burgey's avatar
Lukas Burgey committed
120
121
122
            deployment.save()

        if request_type == 'add':
123
            deployment.deploy_key(request_key)
Lukas Burgey's avatar
Lukas Burgey committed
124
        elif request_type == 'remove':
125
126
            deployment.withdraw_key(request_key)
        else:
Lukas Burgey's avatar
Lukas Burgey committed
127
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
128

129
        deployment.save()
Lukas Burgey's avatar
Lukas Burgey committed
130
        return _api_state_response(request)