views.py 4.48 KB
Newer Older
Lukas Burgey's avatar
Lukas Burgey committed
1
2
from django.db import connections
from django.db.utils import OperationalError
3
from django.shortcuts import get_object_or_404
Lukas Burgey's avatar
Lukas Burgey committed
4
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

9
from . import serializers, models as frontend_models
Lukas Burgey's avatar
Lukas Burgey committed
10
11
12
from .. import models
import logging
logger = logging.getLogger(__name__)
Lukas Burgey's avatar
Lukas Burgey committed
13
14
15
16


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


19
# Response for StateView, LogoutView, and all post requests
Lukas Burgey's avatar
Lukas Burgey committed
20
def _api_state_response(request):
21
22
23
24
25
26
27
28
29
    response = {
            'logged_in': request.user.is_authenticated()
            }
    if request.user.is_authenticated():
        response['user'] = serializers.UserSerializer(request.user).data

    response['state'] = serializers.StateSerializer(
            frontend_models.State(request.user)).data

30
31
32
33
34
    if 'error' in request.session:
        response['error'] = request.session['error']
        # we display errors only once
        del request.session['error']

35
36
37
    return Response(response)


Lukas Burgey's avatar
Lukas Burgey committed
38
39
40
41
42
43
44
45
46
47
class OperationalView(views.APIView):
    authentication_classes = []
    permission_classes = (AllowAny,)

    def get(self, request, format=None):
        try:
            db_conn = connections['default']
            db_conn.cursor()
            # we check if we can access the state
            request.session
Lukas Burgey's avatar
Lukas Burgey committed
48
49
        except OperationalError as e:
            logging.log_exception(e)
Lukas Burgey's avatar
Lukas Burgey committed
50
51
52
53
54
55
56
57
58
59
60
            op = False
        else:
            op = True
        response = {'operational': op}
        return Response(response)


class StateView(views.APIView):
    permission_classes = (AllowAny,)

    def get(self, request, format=None):
Lukas Burgey's avatar
Lukas Burgey committed
61
        return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
62
63
64
65
66
67
68
69
70


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


class SSHPublicKeyView(views.APIView):
    def post(self, request, format=None):
Lukas Burgey's avatar
Lukas Burgey committed
71
        if 'type' not in request.data:
Lukas Burgey's avatar
Lukas Burgey committed
72
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
73
74
75
76
77
78
79
80

        request_type = request.data['type']

        if request_type == 'remove':
            if 'name' in request.data:
                key = get_object_or_404(
                        models.SSHPublicKey,
                        name=request.data['name'])
Lukas Burgey's avatar
Lukas Burgey committed
81
82
                # we do not delete ssh keys directly, as we need to keep track
                # of them until all clients have also deleted them
83
84
85

                # key state: -> (1), if there are no deployments
                # key state: -> (5), if there are deployments
86
                key.delete_key()
Lukas Burgey's avatar
Lukas Burgey committed
87
                return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
88
89
90
91
92
93
94
        elif request_type == 'add':
            if 'key' in request.data:
                key = models.SSHPublicKey(
                        user=request.user,
                        name=request.data['key']['name'],
                        key=request.data['key']['key'],
                        )
95
                # key state: -> (2)
Lukas Burgey's avatar
Lukas Burgey committed
96
                key.save()
Lukas Burgey's avatar
Lukas Burgey committed
97
                return _api_state_response(request)
Lukas Burgey's avatar
Lukas Burgey committed
98

Lukas Burgey's avatar
Lukas Burgey committed
99
        return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
100

Lukas Burgey's avatar
Lukas Burgey committed
101
102

class DeploymentView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
103

Lukas Burgey's avatar
Lukas Burgey committed
104
105
106
107
108
109
    def post(self, request, format=None):
        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
110
111
112
            logger.error(
                    'Deployment api got invalid request {}'.format(
                        request.data))
Lukas Burgey's avatar
Lukas Burgey committed
113
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
114
115
116
117
118
119
120
121
122
123
124
125

        request_type = request.data['type']
        request_service = get_object_or_404(
                models.Service, name=request.data['service'])
        request_key = get_object_or_404(
                models.SSHPublicKey,
                name=request.data['key'])

        # check if there is already an deployment
        try:
            deployment = request.user.deployments.get(service=request_service)
        except Exception:
Lukas Burgey's avatar
Lukas Burgey committed
126
            if request_type == 'remove':
Lukas Burgey's avatar
Lukas Burgey committed
127
                return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
128
129
130
131
132
133
134

            deployment = models.Deployment(
                    user=request.user,
                    service=request_service)
            deployment.save()

        if request_type == 'add':
135
            deployment.deploy_key(request_key)
Lukas Burgey's avatar
Lukas Burgey committed
136
        elif request_type == 'remove':
137
138
            deployment.withdraw_key(request_key)
        else:
Lukas Burgey's avatar
Lukas Burgey committed
139
            return _api_error_response()
Lukas Burgey's avatar
Lukas Burgey committed
140

141
        deployment.save()
Lukas Burgey's avatar
Lukas Burgey committed
142
        return _api_state_response(request)