Django: Привяжите социальный аккаунт к текущему зарегистрированному пользователю
По существу:
Я хочу, чтобы пользователь мог зарегистрироваться, указав свой email, а после аутентификации он мог добавить социальный аккаунт, и чтобы социальный аккаунт был связан (ассоциирован) с текущим аутентифицированным пользователем. Связь должна происходить, даже если email разные (между пользователем и социальным аккаунтом).
- A social account cant be linked to more than one user.
- I am not really interested in user FB account data but rather I want access to their page(s) metrics.
- I am using Django with Django rest Framework.
- I also got a custom user model with email instead of username as key
Ниже приведена моя первоначальная попытка (моя наиболее значимая часть);
Структура файла
[app]/
├── [app]/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── facebook/
│ |── __init__.py
| ├── urls.py
| ├── serializer.py
| └── views.py
├── manage.py
├── README.txt
├── static/
└── README
Settings.py
facebook\view.py
from django.contrib.auth import login
from django.http import JsonResponse
from rest_framework import generics, permissions, status, views
from rest_framework.response import Response
from requests.exceptions import HTTPError
from rest_framework_simplejwt.settings import api_settings
from social_django.utils import load_strategy, load_backend
from social_core.backends.oauth import BaseOAuth2
from social_core.exceptions import MissingBackend, AuthTokenError, AuthForbidden
from . import serializer
class SocialLoginView(generics.GenericAPIView):
"""Log in using facebook"""
serializer_class = serializer.SocialSerializer
permission_classes = [permissions.AllowAny]
def post(self, request):
"""Authenticate user through the provider and access_token"""
serializer = self.serializer_class(data=request.data)
serializer.is_valid(raise_exception=True)
provider = serializer.data.get('provider', None)
strategy = load_strategy(request)
try:
backend = load_backend(strategy=strategy, name=provider,
redirect_uri=None)
except MissingBackend:
return Response({'error': 'Please provide a valid provider'},
status=status.HTTP_400_BAD_REQUEST)
try:
if isinstance(backend, BaseOAuth2):
access_token = serializer.data.get('access_token')
user = backend.do_auth(access_token)
except HTTPError as error:
return Response({
"error": {
"access_token": "Invalid token",
"details": str(error)
}
}, status=status.HTTP_400_BAD_REQUEST)
except AuthTokenError as error:
return Response({
"error": "Invalid credentials",
"details": str(error)
}, status=status.HTTP_400_BAD_REQUEST)
try:
authenticated_user = backend.do_auth(access_token, user=user)
except HTTPError as error:
return Response({
"error":"invalid token",
"details": str(error)
}, status=status.HTTP_400_BAD_REQUEST)
except AuthForbidden as error:
return Response({
"error":"invalid token",
"details": str(error)
}, status=status.HTTP_400_BAD_REQUEST)
if authenticated_user and authenticated_user.is_active:
#generate JWT token
login(request, authenticated_user)
data={
"token": api_settings.jwt_encode_handler(
api_settings.jwt_payload_handler(user)
)}
#customize the response to your needs
response = {
"email": authenticated_user.email,
"token": data.get('token')
}
return Response(status=status.HTTP_200_OK, data=response)
facebook\serializer.py
from rest_framework.serializers import CharField, Serializer
class SocialSerializer(Serializer):
"""
Serializer which accepts an OAuth2 access token and provider.
"""
provider = CharField(max_length=255, required=True)
access_token = CharField(max_length=4096, required=True, trim_whitespace=True)
facebook\urls.py
from django.urls import path, include
from .views import SocialLoginView
urlpatterns = [
path('login/', SocialLoginView.as_view())
]
Спасибо, что посмотрели, а также, пожалуйста, будьте добры, я все еще младший разработчик 😂🙌