This repository was archived by the owner on Jun 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 32
Expand file tree
/
Copy pathapis.py
More file actions
92 lines (63 loc) · 3.35 KB
/
apis.py
File metadata and controls
92 lines (63 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
from urllib.parse import urlencode
from rest_framework import status, serializers
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_jwt.views import ObtainJSONWebTokenView
from django.urls import reverse
from django.conf import settings
from django.shortcuts import redirect
from api.mixins import ApiErrorsMixin, PublicApiMixin, ApiAuthMixin
from users.services import user_record_login, user_change_secret_key, user_get_or_create
from auth.services import jwt_login, google_get_access_token, google_get_user_info
class LoginApi(ApiErrorsMixin, ObtainJSONWebTokenView):
def post(self, request, *args, **kwargs):
# Reference: https://github.com/Styria-Digital/django-rest-framework-jwt/blob/master/src/rest_framework_jwt/views.py#L44
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
user = serializer.object.get('user') or request.user
user_record_login(user=user)
return super().post(request, *args, **kwargs)
class GoogleLoginApi(PublicApiMixin, ApiErrorsMixin, APIView):
class InputSerializer(serializers.Serializer):
code = serializers.CharField(required=False)
error = serializers.CharField(required=False)
def get(self, request, *args, **kwargs):
input_serializer = self.InputSerializer(data=request.GET)
input_serializer.is_valid(raise_exception=True)
validated_data = input_serializer.validated_data
code = validated_data.get('code')
error = validated_data.get('error')
login_url = f'{settings.BASE_FRONTEND_URL}/login'
if error or not code:
params = urlencode({'error': error})
return redirect(f'{login_url}?{params}')
domain = settings.BASE_BACKEND_URL
api_uri = reverse('api:v1:auth:login-with-google')
# Note that this redirect_uri has a trailing slash coming from api_uri above,
# if your authorized redirect uri in google console does not have a trailing slash,
# you can remove the one in api_uri above by replacing api_uri definition above with:
# api_uri = reverse('api:v1:auth:login-with-google')[:-1],
# otherwise you'll get a 400 redirect_uri mismatch error while trying to get the access token
redirect_uri = f'{domain}{api_uri}'
access_token = google_get_access_token(code=code, redirect_uri=redirect_uri)
user_data = google_get_user_info(access_token=access_token)
profile_data = {
'email': user_data['email'],
'first_name': user_data.get('given_name', ''),
'last_name': user_data.get('family_name', ''),
}
# We use get-or-create logic here for the sake of the example.
# We don't have a sign-up flow.
user, _ = user_get_or_create(**profile_data)
response = redirect(settings.BASE_FRONTEND_URL)
response = jwt_login(response=response, user=user)
return response
class LogoutApi(ApiAuthMixin, ApiErrorsMixin, APIView):
def post(self, request):
"""
Logs out user by removing JWT cookie header.
"""
user_change_secret_key(user=request.user)
response = Response(status=status.HTTP_202_ACCEPTED)
response.delete_cookie(settings.JWT_AUTH['JWT_AUTH_COOKIE'])
return response