Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
… into Feature/#18
  • Loading branch information
yuri-0415 committed Jan 6, 2021
2 parents 04eca2b + 8ab4863 commit 41b8d0c
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 186 deletions.
12 changes: 6 additions & 6 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ cryptography==3.3.1
defusedxml==0.6.0
Django==3.1.3
django-allauth==0.44.0
django-cors-headers==3.6.0
django-debug-toolbar==3.1.1
django-redis==4.12.1
django-rest-framework==0.1.0
djangorestframework==3.12.2
idna==2.10
mailjet-rest==1.3.4
mysqlclient==2.0.1
oauthlib==3.1.0
python-dotenv==0.15.0
python3-openid==3.2.0
pycparser==2.20
PyJWT==2.0.0
python-dotenv==0.15.0
python3-openid==3.2.0
pytz==2020.4
redis==3.5.3
requests==2.25.1
requests-oauthlib==1.3.0
six==1.15.0
sqlparse==0.4.1
urllib3==1.26.2
django-redis==4.12.1
redis==3.5.3
django-cors-headers==3.6.0
urllib3==1.26.2
3 changes: 1 addition & 2 deletions wadium/user/providers/facebook/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from django.urls import path

from .views import oauth2_callback, oauth2_login
from .provider import FacebookProviderNoRedirect
from allauth.socialaccount.providers.oauth2.urls import default_urlpatterns

urlpatterns = [
path("facebook/login/", oauth2_login, name='facebook_no_redirect_login'),
Expand Down
111 changes: 24 additions & 87 deletions wadium/user/providers/facebook/views.py
Original file line number Diff line number Diff line change
@@ -1,98 +1,35 @@
from allauth.socialaccount.providers.facebook.views import (
OAuth2CallbackView,
OAuth2LoginView,
FacebookOAuth2Adapter,
)
from django.http import HttpResponseRedirect
from django.conf import settings
from .provider import FacebookProviderNoRedirect
from user.serializers import UserSerializer
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status


class SocialLoginView(APIView):
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
request = self.initialize_request(request, *args, **kwargs)
self.request = request
self.headers = self.default_response_headers # deprecate?

try:
self.initial(request, *args, **kwargs)
except Exception as exc:
pass
import requests
from allauth.socialaccount import providers
from allauth.socialaccount.providers.facebook.provider import GRAPH_API_URL
from allauth.socialaccount.providers.facebook.views import FacebookOAuth2Adapter
from allauth.socialaccount.providers.facebook.views import compute_appsecret_proof

def render(self, response):
query_string = self.request.META.get('QUERY_STRING')
if query_string:
queries = query_string.split('&')
for i in range(len(queries)):
if 'state' in queries[i]:
queries[i] = 'state=' + 'x' * 12
elif 'code' in queries[i]:
queries[i] = 'code=' + 'x' * 75
self.request.META['QUERY_STRING'] = '&'.join(queries)
self.response = self.finalize_response(self.request, response, *self.args, **self.kwargs)
return self.response


class TokenOAuth2CallbackView(OAuth2CallbackView):
def dispatch(self, request, *args, **kwargs):
api_view = SocialLoginView()
api_view.dispatch(request, *args, **kwargs)
res = super(TokenOAuth2CallbackView, self).dispatch(request, *args, **kwargs)
if isinstance(res, HttpResponseRedirect) and res.url == settings.LOGIN_REDIRECT_URL:
assert hasattr(request, 'user')
# login success
data = UserSerializer(instance=request.user).data
token, created = Token.objects.get_or_create(user=request.user)
data['token'] = token.key
res = Response(data=data)
else:
res = Response({
'error': 'An error occurred in social login.',
}, status=status.HTTP_400_BAD_REQUEST)
return api_view.render(res)
from .provider import FacebookProviderNoRedirect
from ..google.views import TokenOAuth2LoginView, TokenOAuth2CallbackView


class TokenOAuth2LoginView(OAuth2LoginView):
def dispatch(self, request, *args, **kwargs):
api_view = SocialLoginView()
api_view.dispatch(request, *args, **kwargs)
res = super(TokenOAuth2LoginView, self).dispatch(request, *args, **kwargs)
if isinstance(res, HttpResponseRedirect) and res.url:
url = res.url
data = {
'url': url,
}
try:
queries = url.split('?')
queries = queries[1].split('&')
for query in queries:
if query[:6] == 'state=':
data['state'] = query[6:]
except:
pass
if 'state' not in data:
res = Response({
'error': 'An error occurred in social login.'
}, status=status.HTTP_400_BAD_REQUEST)
else:
res = Response(data)
else:
res = Response({
'error': 'An error occurred in social login.',
}, status=status.HTTP_400_BAD_REQUEST)
return api_view.render(res)
def fb_complete_login(request, app, token):
provider = providers.registry.by_id(FacebookProviderNoRedirect.id, request)
resp = requests.get(
GRAPH_API_URL + "/me",
params={
"fields": ",".join(provider.get_fields()),
"access_token": token.token,
"appsecret_proof": compute_appsecret_proof(app, token),
},
)
resp.raise_for_status()
extra_data = resp.json()
login = provider.sociallogin_from_response(request, extra_data)
return login


class FacebookOAuth2NoRedirectAdapter(FacebookOAuth2Adapter):
provider_id = FacebookProviderNoRedirect.id

def complete_login(self, request, app, access_token, **kwargs):
return fb_complete_login(request, app, access_token)


oauth2_callback = TokenOAuth2CallbackView.adapter_view(FacebookOAuth2NoRedirectAdapter)
oauth2_login = TokenOAuth2LoginView.adapter_view(FacebookOAuth2NoRedirectAdapter)
1 change: 1 addition & 0 deletions wadium/user/providers/google/urls.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.urls import path

from .views import oauth2_callback, oauth2_login

urlpatterns = [
Expand Down
17 changes: 12 additions & 5 deletions wadium/user/providers/google/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
OAuth2LoginView,
GoogleOAuth2Adapter,
)
from django.http import HttpResponseRedirect
from django.conf import settings
from .provider import GoogleProviderNoRedirect
from user.serializers import UserSerializer
from django.http import HttpResponseRedirect
from rest_framework import status
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status

from user.serializers import UserSerializer
from .provider import GoogleProviderNoRedirect


class SocialLoginView(APIView):
Expand Down Expand Up @@ -44,7 +45,13 @@ class TokenOAuth2CallbackView(OAuth2CallbackView):
def dispatch(self, request, *args, **kwargs):
api_view = SocialLoginView()
api_view.dispatch(request, *args, **kwargs)
res = super(TokenOAuth2CallbackView, self).dispatch(request, *args, **kwargs)
try:
res = super(TokenOAuth2CallbackView, self).dispatch(request, *args, **kwargs)
except:
res = Response({
'error': 'An error occurred in social login.',
}, status=status.HTTP_400_BAD_REQUEST)
return api_view.render(res)
if isinstance(res, HttpResponseRedirect) and res.url == settings.LOGIN_REDIRECT_URL:
assert hasattr(request, 'user')
# login success
Expand Down
8 changes: 2 additions & 6 deletions wadium/user/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def get_serializer_class(self):
return MyStorySerializer
else:
return UserStorySerializer
elif self.action == 'update' or self.action == 'retrieve':
return UserSelfSerializer
else:
return self.serializer_class

Expand Down Expand Up @@ -169,12 +171,6 @@ def update(self, request, pk=None):
serializer.update(profile, serializer.validated_data)
return Response(serializer.data, status=status.HTTP_200_OK)

def get_serializer_class(self):
if self.action == 'update' or self.action == 'retrieve':
return UserSelfSerializer
else:
return UserSerializer

@action(detail=True, methods=['GET'])
def story(self, request, pk=None):
if pk == 'me':
Expand Down
42 changes: 19 additions & 23 deletions wadium/wadium/adapters.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from allauth.account.adapter import DefaultAccountAdapter
from allauth.exceptions import ImmediateHttpResponse
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
from user.models import UserProfile, EmailAddress
from django.http import HttpResponseBadRequest
from rest_framework.authtoken.models import Token
from rest_framework.serializers import ValidationError
from allauth.exceptions import ImmediateHttpResponse
from django.http import HttpResponseBadRequest
from user.serializers import *

from user.models import UserProfile, EmailAddress


class WadiumAccountAdapter(DefaultAccountAdapter):
def is_open_for_signup(self, request):
Expand All @@ -18,6 +19,13 @@ def is_open_for_signup(self, request, sociallogin):

def save_user(self, request, sociallogin, form=None):
email = sociallogin.account.extra_data['email']
if sociallogin.account.provider == 'facebook_no_redirect':
picture = sociallogin.account.extra_data['picture']['data']['url']
elif sociallogin.account.provider == 'google_no_redirect':
picture = sociallogin.account.extra_data['picture']
else:
picture = ''

try:
email_address = EmailAddress.objects.get(email=email)
if not email_address.available:
Expand All @@ -29,32 +37,20 @@ def save_user(self, request, sociallogin, form=None):
except EmailAddress.DoesNotExist:
pass

if sociallogin.account.provider == 'google':
userprofile = {
'email': email,
'name': sociallogin.account.extra_data['name'],
'profile_image': sociallogin.account.extra_data['picture']
}

elif sociallogin.account.provider == "facebook":
userprofile = {
'email': email,
'name': sociallogin.account.extra_data['name'],
'profile_image': sociallogin.account.extra_data['picture']['data']['url']
}

userprofile = {
'email': email,
'name': sociallogin.account.extra_data['name'],
'profile_image': picture
}
try:
user = UserProfile.create_user(
UserProfile.get_unique_username(sociallogin.account.extra_data['email']), userprofile)
UserProfile.get_unique_username(sociallogin.account.extra_data['email']),
userprofile)
except ValidationError as e:
res = HttpResponseBadRequest(str(e.detail))
raise ImmediateHttpResponse(res)

Token.objects.create(user=user)
# print(sociallogin.account.provider)
# TODO create usergoogle(id, email_address, ...), userfacebook(id)
# TODO usergoogle은 처음에 인증 정보를 저장하기 위해 만든 model인데, allauth를 사용하면서 필요가 없어졌습니다.
# TODO connections 확인 용도 외에는 필요가 없어서 usergoogle이나 userfacebook 구현은 미뤄도 될 것 같습니다.
sociallogin.user = user
sociallogin.save(request)
return user
Loading

0 comments on commit 41b8d0c

Please sign in to comment.