views.py 3.88 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
from django.contrib.auth import logout
Lukas Burgey's avatar
Lukas Burgey committed
5
6
7
8
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
9
10
11
12
from . import serializers
from .. import models

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

Lukas Burgey's avatar
Lukas Burgey committed
14

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

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


29
# Response for StateView, LogoutView, and all post requests
Lukas Burgey's avatar
Lukas Burgey committed
30
def _api_state_response(request):
31
    response = {
32
33
        'logged_in': request.user.is_authenticated

Lukas Burgey's avatar
Lukas Burgey committed
34
    }
35
    if request.user.is_authenticated:
36
37
        response['user'] = serializers.UserSerializer(request.user).data

38

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

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

49
50
51
    return Response(response)


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

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


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


class SSHPublicKeyView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
66
    def post(self, request):
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
        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
87

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

Lukas Burgey's avatar
Lukas Burgey committed
91
92

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

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

Lukas Burgey's avatar
Lukas Burgey committed
110
111
112
113
        deployment = models.Deployment.get_deployment(
            request.user,
            request_service,
        )
Lukas Burgey's avatar
Lukas Burgey committed
114
115

        if request_type == 'add':
116
            deployment.deploy_key(request_key)
Lukas Burgey's avatar
Lukas Burgey committed
117
        elif request_type == 'remove':
118
119
            deployment.withdraw_key(request_key)
        else:
Lukas Burgey's avatar
Lukas Burgey committed
120
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
121

122
        deployment.save()
Lukas Burgey's avatar
Lukas Burgey committed
123
        return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
124
125
126
127
128
129
130

class UserDeletionView(views.APIView):
    def delete(self, request):
        # this also logs out the user
        request.user.remove()
        logout(request)
        return _api_state_response(request)