diff options
author | t3jasKharat | 2024-06-06 10:23:17 +0530 |
---|---|---|
committer | t3jasKharat | 2024-06-12 15:35:09 +0530 |
commit | 095415cec26711945eceda0e3e5a74250c8fba3c (patch) | |
tree | ab324ea7e5232f4ffc2a8d638c17411ede94942f | |
parent | e273a3245f9a52475dba75be909752d0e800c719 (diff) | |
download | Common-Interface-Project-095415cec26711945eceda0e3e5a74250c8fba3c.tar.gz Common-Interface-Project-095415cec26711945eceda0e3e5a74250c8fba3c.tar.bz2 Common-Interface-Project-095415cec26711945eceda0e3e5a74250c8fba3c.zip |
Login with github feature added
-rw-r--r-- | blocks/authAPI/templates/github_callback.html | 20 | ||||
-rw-r--r-- | blocks/authAPI/urls.py | 4 | ||||
-rw-r--r-- | blocks/authAPI/views.py | 64 | ||||
-rw-r--r-- | blocks/blocks/settings.py | 15 | ||||
-rw-r--r-- | blocks/eda-frontend/src/pages/Login.js | 22 | ||||
-rw-r--r-- | blocks/eda-frontend/src/pages/signUp.js | 22 | ||||
-rw-r--r-- | blocks/eda-frontend/src/redux/actions/authActions.js | 23 | ||||
-rw-r--r-- | blocks/eda-frontend/src/static/github-mark.png | bin | 0 -> 6393 bytes |
8 files changed, 154 insertions, 16 deletions
diff --git a/blocks/authAPI/templates/github_callback.html b/blocks/authAPI/templates/github_callback.html new file mode 100644 index 00000000..97efd1b2 --- /dev/null +++ b/blocks/authAPI/templates/github_callback.html @@ -0,0 +1,20 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Redirecting to the destination...</title> + <script> + window.localStorage.setItem('Xcos_token', '{{ token }}'); + var redirect_to = window.localStorage.getItem('ard_redurl'); + if (redirect_to) { + window.localStorage.removeItem('ard_redurl'); + window.open(redirect_to, '_self') + } else { + window.open('{{ url }}', '_self') + } + </script> +</head> +<body></body> +</html> diff --git a/blocks/authAPI/urls.py b/blocks/authAPI/urls.py index e38fb710..d9b6c00c 100644 --- a/blocks/authAPI/urls.py +++ b/blocks/authAPI/urls.py @@ -3,6 +3,10 @@ from authAPI import views as authAPI_views urlpatterns = [ + + # GitHub OAuth2 callback + url(r'^github-callback', authAPI_views.GitHubOAuth2, name='github-callback'), + url(r'^google-callback', authAPI_views.GoogleOAuth2), url(r'^users/activate/(?P<uid>[\w-]+)/(?P<token>[\w-]+)/$', authAPI_views.activate_user), diff --git a/blocks/authAPI/views.py b/blocks/authAPI/views.py index 7213775b..b782ecbb 100644 --- a/blocks/authAPI/views.py +++ b/blocks/authAPI/views.py @@ -1,10 +1,10 @@ +import logging from rest_framework import generics, status, permissions from rest_framework.response import Response from django.conf import settings from requests_oauthlib import OAuth2Session from django.contrib.auth import get_user_model from djoser.conf import settings as djoser_settings -from random import randint from django.shortcuts import render from django.http import HttpResponseNotFound from djoser import utils @@ -14,6 +14,8 @@ from blocks.settings import DOMAIN Token = djoser_settings.TOKEN_MODEL +# Set up logging +logger = logging.getLogger(__name__) def activate_user(request, uid, token): """ @@ -61,7 +63,6 @@ def GoogleOAuth2(request): user, created = get_user_model().objects.get_or_create( email=user_info['email']) if created: - # If User was created, set name to email user.username = user_info['email'] user.save() if not user.is_active: @@ -79,6 +80,61 @@ def GoogleOAuth2(request): }) +def GitHubOAuth2(request): + state = request.GET.get('state', None) + code = request.GET.get('code', None) + + if state is None or state == '' or code is None or code == '': + return HttpResponseNotFound("<h1>Page Not Found</h1>") + + client_id = settings.SOCIAL_AUTH_GITHUB_KEY + client_secret = settings.SOCIAL_AUTH_GITHUB_SECRET + + github = OAuth2Session( + client_id, + redirect_uri=settings.GITHUB_OAUTH_REDIRECT_URI, + state=state + ) + try: + github.fetch_token( + 'https://github.com/login/oauth/access_token', + client_secret=client_secret, + code=code + ) + except Exception as e: + logger.error(f"Failed to fetch token from GitHub: {e}") + return HttpResponseNotFound("<h1>Failed to authenticate with GitHub</h1>") + + try: + user_info = github.get('https://api.github.com/user').json() + except Exception as e: + logger.error(f"Failed to get user info from GitHub: {e}") + return HttpResponseNotFound("<h1>Failed to get user info from GitHub</h1>") + + primary_email = f"{user_info['id']}+{user_info['login']}@users.noreply.github.com" + + if primary_email: + user, created = get_user_model().objects.get_or_create(email=primary_email) + if created: + user.username = primary_email + user.save() + if not user.is_active: + user.is_active = True + user.save() + token, created = Token.objects.get_or_create(user=user) + + protocol = 'https://' if request.is_secure() else 'http://' + web_url = protocol + DOMAIN + '/#/dashboard' + + return render(request, 'github_callback.html', { + "token": token.key, + "url": web_url + }) + else: + logger.error("Primary email not found for GitHub user") + return HttpResponseNotFound("<h1>Email not found</h1>") + + class CustomTokenCreateView(utils.ActionViewMixin, generics.GenericAPIView): """ Use this endpoint to obtain user authentication token. @@ -94,6 +150,4 @@ class CustomTokenCreateView(utils.ActionViewMixin, generics.GenericAPIView): 'auth_token': token_serializer_class(token).data["auth_token"], 'user_id': serializer.user.id } - return Response( - data=data, status=status.HTTP_200_OK - ) + return Response(data=data, status=status.HTTP_200_OK) diff --git a/blocks/blocks/settings.py b/blocks/blocks/settings.py index c799a88a..e8147235 100644 --- a/blocks/blocks/settings.py +++ b/blocks/blocks/settings.py @@ -20,7 +20,6 @@ load_dotenv() # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve(strict=True).parent.parent - # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ @@ -97,7 +96,6 @@ WSGI_APPLICATION = 'blocks.wsgi.application' AUTH_USER_MODEL = 'authAPI.User' - # Database # https://docs.djangoproject.com/en/3.1/ref/settings/#databases @@ -108,7 +106,6 @@ DATABASES = { } } - # Password validation # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators @@ -127,7 +124,6 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] - # Mail server config # use this for console emails @@ -144,6 +140,9 @@ SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = os.environ.get('SOCIAL_AUTH_GOOGLE_OAUTH2_KEY', SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = os.environ.get('SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET', '') GOOGLE_OAUTH_REDIRECT_URI = os.environ.get('GOOGLE_OAUTH_REDIRECT_URI', 'http://localhost/api/auth/google-callback') +SOCIAL_AUTH_GITHUB_KEY = os.environ.get('SOCIAL_AUTH_GITHUB_KEY', '') +SOCIAL_AUTH_GITHUB_SECRET = os.environ.get('SOCIAL_AUTH_GITHUB_SECRET', '') +GITHUB_OAUTH_REDIRECT_URI = os.environ.get('GITHUB_OAUTH_REDIRECT_URI', 'http://localhost/api/auth/github-callback') POST_ACTIVATE_REDIRECT_URL = os.environ.get('POST_ACTIVATE_REDIRECT_URL', 'http://localhost/') DOMAIN = os.environ.get('EMAIL_DOMAIN', 'localhost') @@ -160,7 +159,10 @@ DJOSER = { 'ACTIVATION_URL': 'api/auth/users/activate/{uid}/{token}/', 'SEND_ACTIVATION_EMAIL': True, 'SOCIAL_AUTH_TOKEN_STRATEGY': 'authAPI.token.TokenStrategy', - 'SOCIAL_AUTH_ALLOWED_REDIRECT_URIS': [GOOGLE_OAUTH_REDIRECT_URI], + 'SOCIAL_AUTH_ALLOWED_REDIRECT_URIS': [ + GOOGLE_OAUTH_REDIRECT_URI, + GITHUB_OAUTH_REDIRECT_URI, + ], 'SERIALIZERS': { 'user_create': 'authAPI.serializers.UserCreateSerializer', 'user': 'authAPI.serializers.UserCreateSerializer', @@ -178,6 +180,7 @@ REST_FRAMEWORK = { AUTHENTICATION_BACKENDS = ( 'social_core.backends.google.GoogleOAuth2', + 'social_core.backends.github.GithubOAuth2', 'django.contrib.auth.backends.ModelBackend', ) @@ -194,7 +197,6 @@ USE_L10N = True USE_TZ = True - # Allow CORS for Public API CORS_ORIGIN_ALLOW_ALL = True CORS_ALLOWED_ORIGINS = [i for i in os.environ.get('CORS_ALLOWED_ORIGINS', '').split(',') if i != ''] @@ -219,7 +221,6 @@ CELERY_IMPORTS = ( 'simulationAPI.tasks', ) - LOGGING = { 'version': 1, 'disable_existing_loggers': False, diff --git a/blocks/eda-frontend/src/pages/Login.js b/blocks/eda-frontend/src/pages/Login.js index 1c081616..e14b26fb 100644 --- a/blocks/eda-frontend/src/pages/Login.js +++ b/blocks/eda-frontend/src/pages/Login.js @@ -22,8 +22,9 @@ import Visibility from '@material-ui/icons/Visibility' import VisibilityOff from '@material-ui/icons/VisibilityOff' import { Link as RouterLink } from 'react-router-dom' import { useSelector, useDispatch } from 'react-redux' -import { login, authDefault, googleLogin } from '../redux/actions/index' +import { login, authDefault, googleLogin, githubLogin } from '../redux/actions/index' import google from '../static/google.png' +import github from '../static/github-mark.png' const useStyles = makeStyles((theme) => ({ paper: { @@ -84,6 +85,13 @@ export default function SignIn (props) { dispatch(googleLogin(host)) } + // Function call for github login. + const handleGithubLogin = () => { + const host = window.location.origin + const toUrl = '' // Add any redirect URL logic if needed + dispatch(githubLogin(host, toUrl)) + } + return ( <Container component='main' maxWidth='xs'> <Card className={classes.paper}> @@ -177,7 +185,17 @@ export default function SignIn (props) { onClick={handleGoogleLogin} className={classes.submit} > - <img alt='G' src={google} height='20' />  Login With Google + <img alt='Google' src={google} height='20' />  Login With Google + </Button> + {/* Github Sign Up option */} + <Button + fullWidth + variant='outlined' + color='primary' + onClick={handleGithubLogin} + className={classes.submit} + > + <img alt='GitHub' src={github} height='20' />  Login With GitHub </Button> </Card> <Button diff --git a/blocks/eda-frontend/src/pages/signUp.js b/blocks/eda-frontend/src/pages/signUp.js index b60da8dc..38fd7ea0 100644 --- a/blocks/eda-frontend/src/pages/signUp.js +++ b/blocks/eda-frontend/src/pages/signUp.js @@ -20,8 +20,9 @@ import Visibility from '@material-ui/icons/Visibility' import VisibilityOff from '@material-ui/icons/VisibilityOff' import { Link as RouterLink, useHistory } from 'react-router-dom' import { useSelector, useDispatch } from 'react-redux' -import { signUp, authDefault, googleLogin } from '../redux/actions/index' +import { signUp, authDefault, googleLogin, githubLogin } from '../redux/actions/index' import google from '../static/google.png' +import github from '../static/github-mark.png' const useStyles = makeStyles((theme) => ({ paper: { @@ -76,6 +77,13 @@ export default function SignUp () { dispatch(googleLogin(host)) } + // Function call for github sign up. + const handleGithubLogin = () => { + const host = window.location.origin + const toUrl = '' // Add any redirect URL logic if needed + dispatch(githubLogin(host, toUrl)) + } + return ( <Container component='main' maxWidth='xs'> <Card className={classes.paper}> @@ -185,7 +193,17 @@ export default function SignUp () { onClick={handleGoogleSignup} className={classes.submit} > - <img alt='G' src={google} height='20' />  Sign Up With Google + <img alt='Google' src={google} height='20' />  Sign Up With Google + </Button> + {/* Github Sign Up option */} + <Button + fullWidth + variant='outlined' + color='primary' + onClick={handleGithubLogin} + className={classes.submit} + > + <img alt='GitHub' src={github} height='20' />  Sign Up With GitHub </Button> </form> diff --git a/blocks/eda-frontend/src/redux/actions/authActions.js b/blocks/eda-frontend/src/redux/actions/authActions.js index dd2677d9..7fff2eb9 100644 --- a/blocks/eda-frontend/src/redux/actions/authActions.js +++ b/blocks/eda-frontend/src/redux/actions/authActions.js @@ -251,3 +251,26 @@ export const googleLogin = (host, toUrl) => { }) } } + +// Api call for GitHub OAuth login or sign up +export const githubLogin = (host, toUrl) => { + return function (dispatch) { + api.get('auth/o/github/?redirect_uri=' + host + '/api/auth/github-callback') + .then((res) => { + if (res.status === 200) { + // Open GitHub login page + window.open(res.data.authorization_url, '_self') + } else { + dispatch(loginFailed('Something went wrong! Login Failed')) + } + }) + .catch((err) => { + const res = err.response + if (res && (res.status === 400 || res.status === 403 || res.status === 401)) { + dispatch(loginError('Incorrect Username or Password.')) + } else { + dispatch(loginError('Something went wrong! Login Failed')) + } + }) + } +} diff --git a/blocks/eda-frontend/src/static/github-mark.png b/blocks/eda-frontend/src/static/github-mark.png Binary files differnew file mode 100644 index 00000000..6cb3b705 --- /dev/null +++ b/blocks/eda-frontend/src/static/github-mark.png |