webpage.py 5.26 KB
Newer Older
Lukas Burgey's avatar
Lukas Burgey committed
1

Lukas Burgey's avatar
Lukas Burgey committed
2
import logging
Lukas Burgey's avatar
Lukas Burgey committed
3
from django.contrib.auth import logout
4
from django.contrib.auth.models import Group
5
from django.shortcuts import get_object_or_404
Lukas Burgey's avatar
Lukas Burgey committed
6
from rest_framework import status
Lukas Burgey's avatar
Lukas Burgey committed
7
from rest_framework import views
Lukas Burgey's avatar
Lukas Burgey committed
8
9
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
Lukas Burgey's avatar
Lukas Burgey committed
10

11
12
13
from .. import models
from ..models.serializers import webpage as serializers
from ..models import serializers as model_serializers
Lukas Burgey's avatar
Lukas Burgey committed
14
15

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

Lukas Burgey's avatar
Lukas Burgey committed
17

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

Lukas Burgey's avatar
Lukas Burgey committed
28
29
def _api_error_response(error):
    return Response({'error': error}, status=status.HTTP_400_BAD_REQUEST)
Lukas Burgey's avatar
Lukas Burgey committed
30

Lukas Burgey's avatar
Lukas Burgey committed
31
32
33
34
35
36
37
38
39
def user_state(user):
    return serializers.UserStateSerializer(
        user,
    ).data

def _api_state_response_data(request):
    return {
        'user_state': user_state(request.user),
    }
Lukas Burgey's avatar
Lukas Burgey committed
40

Lukas Burgey's avatar
Lukas Burgey committed
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def state_view_data(request):
    data = {}
    if request.user.is_authenticated:
        data = _api_state_response_data(request)
        data['user'] = serializers.UserSerializer(
            request.user,
        ).data
        data['services'] = serializers.ServiceSerializer(
            user_services(request.user),
            many=True,
        ).data
    else:
        data['user'] = None
        data['user_state'] = None
        data['services'] = []
Lukas Burgey's avatar
Lukas Burgey committed
56
57
58
59
60
61

    if 'error' in request.session:
        data['error'] = request.session['error']

        # we display errors only once
        del request.session['error']
Lukas Burgey's avatar
Lukas Burgey committed
62
63
    return data

64

Lukas Burgey's avatar
Lukas Burgey committed
65
66
67
class StateView(views.APIView):
    permission_classes = (AllowAny,)

Lukas Burgey's avatar
Lukas Burgey committed
68
    def get(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
69
        return Response(state_view_data(request))
Lukas Burgey's avatar
Lukas Burgey committed
70
71
72


class SSHPublicKeyView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
73
    def post(self, request):
74
75
76
77
78
79
80
81
82
83
        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()
Lukas Burgey's avatar
Lukas Burgey committed
84
85
86
                    return Response({
                        'deleted': True,
                    })
87
88
89
90
91
92
93
94
            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()
Lukas Burgey's avatar
Lukas Burgey committed
95
96
97
98
99
                    return Response(
                        model_serializers.SSHPublicKeySerializer(
                            key,
                        ).data
                    )
Lukas Burgey's avatar
Lukas Burgey committed
100

101
        LOGGER.error('SSHPublicKeyView: malformed request %s', request)
Lukas Burgey's avatar
Lukas Burgey committed
102
        return _api_error_response("malformed request")
Lukas Burgey's avatar
Lukas Burgey committed
103

Lukas Burgey's avatar
Lukas Burgey committed
104
105

class DeploymentView(views.APIView):
Lukas Burgey's avatar
Lukas Burgey committed
106
    def post(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
107
108
109
        if (
                'type' not in request.data or
                'key' not in request.data or
110
111
112
113
                (
                    'service' not in request.data and
                    'group' not in request.data
                )
Lukas Burgey's avatar
Lukas Burgey committed
114
        ):
115
            LOGGER.error('Deployment api got invalid request %s', request.data)
Lukas Burgey's avatar
Lukas Burgey committed
116
            return _api_error_response(
117
                "request misses fields (should have: 'type', 'key', and ('service' or 'group'))"
Lukas Burgey's avatar
Lukas Burgey committed
118
            )
Lukas Burgey's avatar
Lukas Burgey committed
119
120

        request_type = request.data['type']
121
122
        request_key = models.SSHPublicKey.objects.get(
            id=request.data['key'],
Lukas Burgey's avatar
Lukas Burgey committed
123
        )
Lukas Burgey's avatar
Lukas Burgey committed
124

125
126
127
128
129
130
131
132
133
134
135
136
        deployment = None
        if 'group' in request.data:
            deployment = models.Deployment.get_deployment(
                request.user,
                group=Group.objects.get(id=request.data['group']),
            )
        elif 'service' in request.data:
            deployment = models.Deployment.get_deployment(
                request.user,
                service=models.Service.objects.get(id=request.data['service']),
            )

Lukas Burgey's avatar
Lukas Burgey committed
137
138

        if request_type == 'add':
139
            deployment.deploy_key(request_key)
Lukas Burgey's avatar
Lukas Burgey committed
140
        elif request_type == 'remove':
141
            deployment.remove_key(request_key)
142
        else:
Lukas Burgey's avatar
Lukas Burgey committed
143
            return _api_error_response("invalid value of field 'type'")
Lukas Burgey's avatar
Lukas Burgey committed
144

145
        deployment.save()
Lukas Burgey's avatar
Lukas Burgey committed
146
147
148
        return Response(
            serializers.DeploymentSerializer(deployment).data
        )
Lukas Burgey's avatar
Lukas Burgey committed
149

150

151
152
class QuestionnaireView(views.APIView):
    def post(self, request):
Lukas Burgey's avatar
Lukas Burgey committed
153
154
        state_item_id = request.query_params.get('id', '')
        if state_item_id != '':
Lukas Burgey's avatar
Lukas Burgey committed
155
156
157
            item = models.DeploymentStateItem.objects.filter(
                id=int(state_item_id),
            )
158
            if item.exists():
Lukas Burgey's avatar
Lukas Burgey committed
159
                item.first().user_answers(
160
161
162
163
164
                    answers=request.data,
                )
            else:
                LOGGER.error('Received questionnaire answer for non existing item')

Lukas Burgey's avatar
Lukas Burgey committed
165
        return Response(state_view_data(request))
166
167


Lukas Burgey's avatar
Lukas Burgey committed
168
169
170
171
172
class UserDeletionView(views.APIView):
    def delete(self, request):
        # this also logs out the user
        request.user.remove()
        logout(request)
Lukas Burgey's avatar
Lukas Burgey committed
173
        return Response({'deleted': True})