Skip to content
Snippets Groups Projects
Commit d003e759 authored by Chris Li's avatar Chris Li
Browse files

save intermeidate things.

parent 95867e99
No related branches found
No related tags found
No related merge requests found
from django.shortcuts import render
from django.urls import reverse
from rest_framework import generics
from rest_framework.response import Response
from dj_rest_auth.registration.views import SocialConnectView, SocialLoginView
from dj_rest_auth.social_serializers import TwitterLoginSerializer
from knox.models import AuthToken
from django.contrib.auth.backends import AllowAllUsersModelBackend
from allauth.socialaccount.providers.apple.client import AppleOAuth2Client
from allauth.socialaccount.providers.apple.views import AppleOAuth2Adapter
from allauth.socialaccount.providers.google.views import GoogleOAuth2Adapter
from allauth.socialaccount.providers.twitter.views import TwitterOAuthAdapter
from allauth.socialaccount.providers.oauth2.client import OAuth2Client
from core.serializers.login import LoginSerializer
from core.serializers.appleSocialLoginSerializer import AppleSocialLoginSerializer
from core.serializers.register import RegisterSerializer
from core.serializers.user import UserSerializer
......@@ -39,6 +47,29 @@ class LoginAPI(generics.GenericAPIView):
})
class AppleLogin(SocialLoginView):
adapter_class = AppleOAuth2Adapter
client_class = AppleOAuth2Client
@property
def callback_url(self):
return self.request.build_absolute_uri(reverse('apple_callback'))
class GoogleLogin(SocialLoginView): # if you want to use Authorization Code Grant, use this
adapter_class = GoogleOAuth2Adapter
client_class = OAuth2Client
@property
def callback_url(self):
return self.request.build_absolute_uri(reverse('google_callback'))
class TwitterLogin(SocialLoginView):
serializer_class = TwitterLoginSerializer
adapter_class = TwitterOAuthAdapter
def verify_user_and_activate(request, token):
try:
auth = AuthToken.objects.filter(digest=token).first()
......
from dj_rest_auth.registration.serializers import SocialLoginSerializer
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from requests.exceptions import HTTPError
try:
from allauth.account import app_settings as allauth_settings
from allauth.socialaccount.helpers import complete_social_login
except ImportError:
raise ImportError('allauth needs to be added to INSTALLED_APPS.')
class AppleSocialLoginSerializer(SocialLoginSerializer):
def validate(self, attrs):
view = self.context.get('view')
request = self._get_request()
if not view:
raise serializers.ValidationError(
_('View is not defined, pass it as a context variable')
)
adapter_class = getattr(view, 'adapter_class', None)
if not adapter_class:
raise serializers.ValidationError(_('Define adapter_class in view'))
adapter = adapter_class(request)
app = adapter.get_provider().get_app(request)
# More info on code vs access_token
# http://stackoverflow.com/questions/8666316/facebook-oauth-2-0-code-and-token
# Case 1: We received the access_token
if attrs.get('access_token'):
access_token = attrs.get('access_token')
token = {'access_token': access_token}
# Case 2: We received the authorization code
elif attrs.get('code'):
self.callback_url = getattr(view, 'callback_url', None)
self.client_class = getattr(view, 'client_class', None)
if not self.callback_url:
raise serializers.ValidationError(
_('Define callback_url in view')
)
if not self.client_class:
raise serializers.ValidationError(
_('Define client_class in view')
)
code = attrs.get('code')
provider = adapter.get_provider()
scope = provider.get_scope(request)
client = self.client_class(
request,
app.client_id,
app.secret,
adapter.access_token_method,
adapter.access_token_url,
self.callback_url,
scope,
key=app.key,
cert=app.cert,
)
token = client.get_access_token(code)
access_token = token['access_token']
else:
raise serializers.ValidationError(
_('Incorrect input. access_token or code is required.'))
social_token = adapter.parse_token(token) # The important change is here.
social_token.app = app
try:
login = self.get_social_login(adapter, app, social_token, access_token)
complete_social_login(request, login)
except HTTPError:
raise serializers.ValidationError(_('Incorrect value'))
if not login.is_existing:
# We have an account already signed up in a different flow
# with the same email address: raise an exception.
# This needs to be handled in the frontend. We can not just
# link up the accounts due to security constraints
if allauth_settings.UNIQUE_EMAIL:
# Do we have an account already with this email address?
if get_user_model().objects.filter(email=login.user.email).exists():
raise serializers.ValidationError(_('E-mail already registered using different signup method.'))
login.lookup()
login.save(request, connect=True)
attrs['user'] = login.account.user
return attrs
......@@ -2,7 +2,7 @@ from django.urls import path, include
from knox import views as knox_views
from rest_framework import routers
from core.api.auth import RegisterAPI, LoginAPI, verify_user_and_activate
from core.api.auth import RegisterAPI, LoginAPI, AppleLogin, GoogleLogin, TwitterLogin, verify_user_and_activate
from core.api.password import ChangePasswordView
from core.api.profile import ProfileViewSet
......@@ -16,6 +16,9 @@ urlpatterns += [
path('api/auth/activate/<token>', verify_user_and_activate, name='activate'),
path('api/auth/login', LoginAPI.as_view(), name='login'),
path('api/auth/logout', knox_views.LogoutView.as_view(), name='logout'),
path('api/auth/apple', AppleLogin.as_view(), name='apple_login'),
path('api/auth/google', GoogleLogin.as_view(), name='google_login'),
path('api/auth/twitter', TwitterLogin.as_view(), name='twitter_login'),
# passwd
path('api/change-password', ChangePasswordView.as_view(), name='change-password'),
path('api/password_reset/', include('django_rest_passwordreset.urls', namespace='password_reset')),
......
......@@ -36,19 +36,31 @@ INSTALLED_APPS = [
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django_extensions',
'rest_framework',
'django_rest_passwordreset',
'knox',
'dj_rest_auth',
'dj_rest_auth.registration',
'allauth',
'allauth.account',
'allauth.socialaccount',
'allauth.socialaccount.providers.apple',
'allauth.socialaccount.providers.google',
'allauth.socialaccount.providers.twitter',
'core',
]
SITE_ID = 1
REST_FRAMEWORK = {
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
'DEFAULT_AUTHENTICATION_CLASSES': [
'knox.auth.TokenAuthentication',
'dj_rest_auth.jwt_auth.JWTCookieAuthentication',
],
}
......@@ -57,6 +69,8 @@ REST_KNOX = {
'AUTO_REFRESH': True,
}
REST_USE_JWT = True
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
......@@ -129,7 +143,7 @@ TIME_ZONE = 'America/Toronto'
USE_I18N = True
USE_TZ = True
USE_TZ = False
# Static files (CSS, JavaScript, Images)
......@@ -148,3 +162,38 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
# Media Settings
MEDIA_URL = 'media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
SOCIALACCOUNT_PROVIDERS = {
"apple": {
"APP": {
# Your service identifier.
"client_id": "your.service.id",
# The Key ID (visible in the "View Key Details" page).
"secret": "KEYID",
# Member ID/App ID Prefix -- you can find it below your name
# at the top right corner of the page, or it’s your App ID
# Prefix in your App ID.
"key": "MEMAPPIDPREFIX",
# The certificate you downloaded when generating the key.
"certificate_key": """-----BEGIN PRIVATE KEY-----
s3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr
3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3
c3ts3cr3t
-----END PRIVATE KEY-----
"""
}
},
'google': {
'SCOPE': [
'profile',
'email',
],
'AUTH_PARAMS': {
'access_type': 'online',
},
'OAUTH_PKCE_ENABLED': True,
}
}
......@@ -11,6 +11,8 @@ urlpatterns = router.urls
urlpatterns += [
path('', include('core.urls')),
# path('dj-rest-auth/', include('dj_rest_auth.urls')),
# path('dj-rest-auth/registration/', include('dj_rest_auth.registration.urls')),
path('admin/', admin.site.urls),
path('docs/', include_docs_urls(title='ECE651 Backend API Document', description='This API document includes all ednpoints that has been implemented.')),
]
......
env.yml 0 → 100644
name: django
channels:
- defaults
dependencies:
- python=3.9
- django
- pyjwt
- cryptography
- djangorestframework
- django-extensions
- pillow
prefix: /Users/lichenyang/opt/anaconda3/envs/django
......@@ -38,3 +38,6 @@ dependencies:
- pygments
- django-filter
- django-guardian
- dj-rest-auth
- django-allauth
- djangorestframework-simplejwt
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment