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
# pylint: disable=too-many-ancestors
Lukas Burgey's avatar
Lukas Burgey committed
56
57
58
59
60
61
class ServiceViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.ServiceSerializer
    queryset = models.Service.objects.all()


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

        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
71
72
73
                    models.SSHPublicKey,
                    name=request.data['name']
                )
Lukas Burgey's avatar
Lukas Burgey committed
74
75
                # we do not delete ssh keys directly, as we need to keep track
                # of them until all clients have also deleted them
76
77
78

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

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

Lukas Burgey's avatar
Lukas Burgey committed
94
95

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

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

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

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

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

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