Fakultas Ilmu Komputer UI

accounts.py 11.4 KB
Newer Older
1
import requests
2
from django.contrib.auth import authenticate, login
3
from django.contrib.auth.models import User
Zamil Majdy's avatar
Zamil Majdy committed
4
from django.shortcuts import get_object_or_404
5
from rest_framework import viewsets, status
6
from rest_framework.decorators import list_route, detail_route
Zamil Majdy's avatar
Zamil Majdy committed
7
from rest_framework.exceptions import PermissionDenied
8
from rest_framework.parsers import FormParser,MultiPartParser
9
from rest_framework.permissions import AllowAny
10
from rest_framework.permissions import IsAdminUser, IsAuthenticated
11
12
from rest_framework.response import Response

13
from core.lib.permissions import IsAdminOrStudent, IsAdminOrSelfOrReadOnly, IsAdminOrCompany, IsAdminOrSupervisor, \
14
    IsAdminOrSupervisorOrCompanyOrSelf
15
from core.models.accounts import Student, Company, Supervisor
16
from core.serializers.accounts import BasicUserSerializer, UserSerializer, StudentSerializer, CompanySerializer, \
Zamil Majdy's avatar
Zamil Majdy committed
17
    SupervisorSerializer, RegisterSerializer, StudentUpdateSerializer, CompanyUpdateSerializer
Zamil Majdy's avatar
Zamil Majdy committed
18
from kape import settings
19

20

21
22
23
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
24
    permission_classes = [IsAdminUser]
25

26
    @list_route(methods=['get'], permission_classes=[IsAuthenticated])
27
    def me(self, request):
28
29
30
        """
        Get current user's details
        """
31
        user = self.request.user
32
        serializer = BasicUserSerializer(user, context={"request": request})
33
34
        return Response(serializer.data)

35
    def get_permissions(self):
Zamil Majdy's avatar
Zamil Majdy committed
36
        if self.action == "update" or self.action == "partial_update":
37
38
39
40
41
            return [IsAdminOrSelfOrReadOnly(), IsAuthenticated()]
        if self.action == "create":
            return [AllowAny()]
        return super(UserViewSet, self).get_permissions()

42

43
44
45
class StudentViewSet(viewsets.ModelViewSet):
    queryset = Student.objects.all()
    serializer_class = StudentSerializer
46
47
48
    permission_classes = [IsAdminUser]

    def get_permissions(self):
Zamil Majdy's avatar
Zamil Majdy committed
49
        if self.action == "update" or self.action == "partial_update":
50
            return [IsAdminOrSelfOrReadOnly(), IsAdminOrStudent()]
51
        if self.action == "list":
52
            return [IsAuthenticated(), IsAdminOrSupervisor()]
53
54
        if self.action == "retrieve":
            return [IsAuthenticated(), IsAdminOrSupervisorOrCompanyOrSelf()]
55
        return super(StudentViewSet, self).get_permissions()
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    @detail_route(methods=['patch'], permission_classes=[IsAdminOrStudent],
                  serializer_class=StudentUpdateSerializer, parser_classes=(MultiPartParser, FormParser,))
    def profile(self, request, pk=None):
        """
        Update student {student_id}'s profile information
        ---
        """
        user = self.get_object()
        serializer = self.serializer_class(user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Zamil Majdy's avatar
Zamil Majdy committed
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
    @detail_route(methods=['get'], permission_classes=[IsAdminOrStudent])
    def transcript(self, request, pk):
        """
        Get student {student_id}'s academic transcript
        ---
        """
        student = get_object_or_404(Student.objects.all(), pk=pk)

        if hasattr(request.user, 'student') and request.user.student.pk != student.pk:
            raise PermissionDenied("You are not allowed to see other student's transcript")

        if student.show_transcript:
            s = requests.Session()
            credentials = settings.API_CS_CREDENTIALS
            s.get('https://api.cs.ui.ac.id/api-auth/login/')
            csrf = s.cookies['csrftoken']
            resp = s.post('https://api.cs.ui.ac.id/api-auth/login/',
                          data={'username': credentials["user"], 'password': credentials["password"],
                                'csrfmiddlewaretoken': csrf})
            response = s.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/' + str(student.npm) + '/riwayat/')
            return Response({'name': student.full_name, 'transcript': response.json()}, status=status.HTTP_200_OK)
        else:
            return Response({'name': student.full_name, 'error': 'student does not allow transcript to be shown'},
                            status=status.HTTP_200_OK)

97
98
99
100

class CompanyViewSet(viewsets.ModelViewSet):
    queryset = Company.objects.all()
    serializer_class = CompanySerializer
101
    permission_classes = [IsAdminOrSelfOrReadOnly, IsAdminOrCompany]
102
    filter_fields = ('status',)
103

Zamil Majdy's avatar
Zamil Majdy committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
    @detail_route(methods=['patch'], permission_classes=[IsAdminOrCompany],
                  serializer_class=CompanyUpdateSerializer, parser_classes=(MultiPartParser, FormParser,))
    def profile(self, request, pk=None):
        """
        Update student {student_id}'s profile information
        ---
        """
        user = self.get_object()
        serializer = self.serializer_class(user, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

119
120
121
122

class SupervisorViewSet(viewsets.ModelViewSet):
    queryset = Supervisor.objects.all()
    serializer_class = SupervisorSerializer
123
    permission_classes = [IsAdminOrSelfOrReadOnly, IsAdminOrSupervisor]
124

125

126
127
class LoginViewSet(viewsets.GenericViewSet):
    permission_classes = (AllowAny, )
128
    serializer_class = UserSerializer
129
130
131
132
    queryset = User.objects.all()

    def create(self, request):
        """
133
        Authentication for user by means of logging in
134
135
        ---
        parameters:
136
137
138
139
140
            - name: body
              description: JSON object containing three strings: username, password and login-type. login-type should be either 'sso-ui' or 'company'.
              required: true
              type: string
              paramType: body
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
        """
        username = request.data.get('username')
        password = request.data.get('password')
        login_type = request.data.get('login-type')
        if username is None or password is None or login_type is None:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        if login_type == "sso-ui":
            r = requests.post('https://api.cs.ui.ac.id/authentication/ldap/v2/',
                              json={"username": username, "password": password})
            resp = r.json()
            if resp.get('state') != 0:
                # create user
                name = resp.get('nama').split(" ")
                first_name = name[0]
                name.pop(0)
                last_name = " ".join(name)
                user, created = User.objects.get_or_create(
                    username=username,
159
160
161
162
163
                    defaults={
                        'email' : username + "@ui.ac.id",
                        'first_name' : first_name,
                        'last_name' : last_name
                    }
164
165
166
167
168
169
                )
                user.set_password(password)
                user.save()
                login(request, user)
                if created:
                    if resp.get('nama_role') == "mahasiswa":
170
171
                        student_detail = requests.get('https://api.cs.ui.ac.id/siakngcs/mahasiswa/{}/'.format(resp.get("kodeidentitas")))
                        resp_student_detail = student_detail.json()
172
173
174
                        student = Student.objects.create(
                            user=user,
                            npm=resp.get("kodeidentitas"),
175
176
177
178
                            birth_place=resp_student_detail.get('kota_lahir'),
                            birth_date=resp_student_detail.get('tgl_lahir'),
                            major=resp_student_detail.get('program')[0].get('nm_org'),
                            batch=resp_student_detail.get('program')[0].get('angkatan')
179
180
181
182
183
184
185
186
                        )
                        student.save()
                    else:
                        supervisor = Supervisor.objects.create(
                            user=user,
                            nip=resp.get("kodeidentitas")
                        )
                        supervisor.save()
187
                    serializer = UserSerializer(user, context={'request': request})
188
                    return Response(serializer.data, status=status.HTTP_201_CREATED)
189
                serializer = UserSerializer(user, context={'request': request})
190
                return Response(serializer.data, status=status.HTTP_200_OK)
191
192
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
193
        elif login_type == "company":
194
195
196
            user = authenticate(username = username, password = password)
            if user is not None:
                login(request, user)
197
                serializer = UserSerializer(user, context={'request': request})
198
                return Response(serializer.data, status=status.HTTP_200_OK)
199
200
            else:
                return Response(status=status.HTTP_401_UNAUTHORIZED)
201
202
        else:
            return Response(status=status.HTTP_400_BAD_REQUEST)
203
204
205
206
207
208
209
210
211


class CompanyRegisterViewSet(viewsets.GenericViewSet):
    permission_classes = (AllowAny,)
    serializer_class = RegisterSerializer
    queryset = Company.objects.all()
    parser_classes = (MultiPartParser, FormParser,)

    def create(self, request):
212
213
214
215
216
217
218
219
220
        """
        Create a new company user
        ---
        parameters:
            - name: username
              description: username of the new account 
              required: true
              type: string
            - name: password
Zamil Majdy's avatar
Zamil Majdy committed
221
              description: password of the new account
222
223
224
              required: true
              type: string
            - name: email
Zamil Majdy's avatar
Zamil Majdy committed
225
              description: email address of the new account
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
              required: true
              type: string
            - name: name
              description: the new company's name
              required: true
              type: string
            - name: description
              description: description of the new company
              required: true
              type: string
            - name: logo
              description: logo of the new company
              required: false
              type: image
            - name: address
Zamil Majdy's avatar
Zamil Majdy committed
241
              description: address of the new account
242
243
244
              required: false
              type: string
        """
245
246
247
248
        data = {}
        for attr in ['password', 'email', 'name', 'description', 'logo', 'address']:
            data[attr] = request.data.get(attr)
            if data[attr] is None:
249
                return Response({'error': attr+' is required'}, status=status.HTTP_400_BAD_REQUEST)
250
251
252
253
254
255
256
257
258
259
260
261
262
263

        user, created = User.objects.get_or_create(
            username=data['email'],
            email=data['email'],
            first_name=data['name'],
            last_name=""
        )
        if created:
            user.set_password(data['password'])
            company = Company.objects.create(
                user=user,
                description=data['description'],
                logo=data['logo'],
                address=data['address']
264
            )
265
266
267
            user.save()
            company.save()
            serializer = self.serializer_class(user, context={'request': request})
268
            login(request, user)
269
270
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
271
            return Response({'error': 'Company with email '+data['email']+' already exist'}, status=status.HTTP_409_CONFLICT)