From e1d3b28f0fd61b474ada8a071d49e7a6afd2d190 Mon Sep 17 00:00:00 2001 From: Salman Ashraf Date: Wed, 24 Jul 2024 17:34:24 +0000 Subject: [PATCH] test login with github --- api/views/contributor.py | 7 +- api/views/contributor_test.py | 345 +++++++++++++++++++++++++++++----- 2 files changed, 309 insertions(+), 43 deletions(-) diff --git a/api/views/contributor.py b/api/views/contributor.py index fdcf4d4..f49b751 100644 --- a/api/views/contributor.py +++ b/api/views/contributor.py @@ -27,6 +27,11 @@ class ContributorViewSet(ModelViewSet[User, Contributor]): @action(detail=False, methods=["get"]) def log_into_github(self, request: Request): """Users can login using their existing github account""" + # Get code from login request + code = request.GET.get("code") + if not code: + return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR) + # Get user access Token access_token_request = requests.post( url="https://github.com/login/oauth/access_token", @@ -68,7 +73,7 @@ def log_into_github(self, request: Request): status=status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS, ) - # Check if user is already a contributor + # Check if user is already a contributor (TODO: Update user info) gh_id = user_data["id"] if Contributor.objects.filter(pk=gh_id): return Response(status=status.HTTP_409_CONFLICT) diff --git a/api/views/contributor_test.py b/api/views/contributor_test.py index 1d9bca3..51e6a89 100644 --- a/api/views/contributor_test.py +++ b/api/views/contributor_test.py @@ -3,10 +3,10 @@ Created on 16/07/2024 at 14:54:09(+01:00). """ +import json from unittest.mock import patch import requests -from codeforlife.request import Request from codeforlife.tests import ModelViewSetTestCase from codeforlife.user.models import User from rest_framework import status @@ -49,44 +49,305 @@ def test_create(self): } ) - # def test_log_into_github__no_code(self): - # """Login API call does not return a code.""" - # code = "3e074f3e12656707cf7f" - # request = Request - # # request.GET= {"code": code} - - # with patch.object(Request, "GET", return_value=request): - # self.client.get( - # self.reverse_action( - # "log_into_github", - # ), - # status_code_assertion=status.HTTP_500_INTERNAL_SERVER_ERROR, - # ) - - # def test_log_into_github__no_access_token(self): - # """POST API call did not return an access token""" - # code = "3e074f3e12656707cf7f" - # response = requests.Response() - # response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR - # request = Request - # request.GET = {"code": code} - # with patch.object( - # requests, "post", return_value=response - # ) as requests_get: - # self.client.get( - # self.reverse_action( - # "log_into_github", - # ), - # status_code_assertion=status.HTTP_500_INTERNAL_SERVER_ERROR, - # ) - - # requests_get.assert_called_once_with( - # url="https://github.com/login/oauth/access_token", - # headers={"Accept": "application/json"}, - # params={ - # "client_id": settings.GITHUB_CLIENT_ID, - # "client_secret": settings.GITHUB_CLIENT_SECRET, - # "code": code, - # }, - # timeout=5, - # ) + def test_log_into_github__no_code(self): + """Login API call does not return a code.""" + code = "" + self.client.get( + self.reverse_action( + "log_into_github", + ), + {"code": code}, + status_code_assertion=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) + + def test_log_into_github__no_access_token(self): + """POST API call did not return an access token""" + code = "3e074f3e12656707cf7f" + + response = requests.Response() + response.status_code = status.HTTP_500_INTERNAL_SERVER_ERROR + + with patch.object( + requests, "post", return_value=response + ) as requests_post: + self.client.get( + self.reverse_action( + "log_into_github", + ), + {"code": code}, + status_code_assertion=status.HTTP_500_INTERNAL_SERVER_ERROR, + ) + + requests_post.assert_called_once_with( + url="https://github.com/login/oauth/access_token", + headers={"Accept": "application/json"}, + params={ + "client_id": settings.GITHUB_CLIENT_ID, + "client_secret": settings.GITHUB_CLIENT_SECRET, + "code": code, + }, + timeout=5, + ) + + def test_log_into_github__code_expired(self): + """POST API call failed due to expired code.""" + code = "3e074f3e12656707cf7f" + + response = requests.Response() + response.status_code = status.HTTP_200_OK + response.encoding = "utf-8" + # pylint: disable-next=protected-access + response._content = json.dumps({}).encode("utf-8") + + with patch.object( + requests, "post", return_value=response + ) as requests_post: + self.client.get( + self.reverse_action( + "log_into_github", + ), + {"code": code}, + status_code_assertion=status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS, + ) + + requests_post.assert_called_once_with( + url="https://github.com/login/oauth/access_token", + headers={"Accept": "application/json"}, + params={ + "client_id": settings.GITHUB_CLIENT_ID, + "client_secret": settings.GITHUB_CLIENT_SECRET, + "code": code, + }, + timeout=5, + ) + + def test_log_into_github__null_email(self): + """User must have their email public on github""" + code = "3e074f3e12656707cf7f" + + response_post = requests.Response() + response_post.status_code = status.HTTP_200_OK + response_post.encoding = "utf-8" + # pylint: disable-next=protected-access + response_post._content = json.dumps( + {"access_token": "123254", "token_type": "Bearer"} + ).encode("utf-8") + + response_get = requests.Response() + response_get.status_code = status.HTTP_200_OK + response_get.encoding = "utf-8" + # pylint: disable-next=protected-access + response_get._content = json.dumps({"email": ""}).encode("utf-8") + + with patch.object( + requests, "post", return_value=response_post + ) as requests_post: + with patch.object( + requests, "get", return_value=response_get + ) as requests_get: + self.client.get( + self.reverse_action( + "log_into_github", + ), + {"code": code}, + status_code_assertion=status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS, + ) + + requests_post.assert_called_once_with( + url="https://github.com/login/oauth/access_token", + headers={"Accept": "application/json"}, + params={ + "client_id": settings.GITHUB_CLIENT_ID, + "client_secret": settings.GITHUB_CLIENT_SECRET, + "code": code, + }, + timeout=5, + ) + requests_get.assert_called_once_with( + url="https://api.github.com/user", + headers={ + "Accept": "application/json", + "Authorization": "Bearer 123254", + }, + timeout=5, + ) + + def test_log_into_github__existing_contributor(self): + """User already exists as a contributor""" + # TODO: update the user info + code = "3e074f3e12656707cf7f" + + response_post = requests.Response() + response_post.status_code = status.HTTP_200_OK + response_post.encoding = "utf-8" + # pylint: disable-next=protected-access + response_post._content = json.dumps( + {"access_token": "123254", "token_type": "Bearer"} + ).encode("utf-8") + + response_get = requests.Response() + response_get.status_code = status.HTTP_200_OK + response_get.encoding = "utf-8" + # pylint: disable-next=protected-access + response_get._content = json.dumps( + { + "id": 1, + "email": "contributor1@gmail.com", + "name": "contributor one", + "location": "London", + "html_url": "https://github.com/contributor1", + "avatar_url": "https://contributor1.github.io/", + } + ).encode("utf-8") + + with patch.object( + requests, "post", return_value=response_post + ) as requests_post: + with patch.object( + requests, "get", return_value=response_get + ) as requests_get: + self.client.get( + self.reverse_action( + "log_into_github", + ), + {"code": code}, + status_code_assertion=status.HTTP_409_CONFLICT, + ) + + requests_post.assert_called_once_with( + url="https://github.com/login/oauth/access_token", + headers={"Accept": "application/json"}, + params={ + "client_id": settings.GITHUB_CLIENT_ID, + "client_secret": settings.GITHUB_CLIENT_SECRET, + "code": code, + }, + timeout=5, + ) + requests_get.assert_called_once_with( + url="https://api.github.com/user", + headers={ + "Accept": "application/json", + "Authorization": "Bearer 123254", + }, + timeout=5, + ) + + def test_log_into_github__new_contributor(self): + """Add user to the contributor data table""" + code = "3e074f3e12656707cf7f" + + response_post = requests.Response() + response_post.status_code = status.HTTP_200_OK + response_post.encoding = "utf-8" + # pylint: disable-next=protected-access + response_post._content = json.dumps( + {"access_token": "123254", "token_type": "Bearer"} + ).encode("utf-8") + + response_get = requests.Response() + response_get.status_code = status.HTTP_200_OK + response_get.encoding = "utf-8" + # pylint: disable-next=protected-access + response_get._content = json.dumps( + { + "id": 999999999999999, + "email": "contributornew@gmail.com", + "name": "contributor new", + "location": "London", + "html_url": "https://github.com/contributornew", + "avatar_url": "https://contributornew.github.io/", + } + ).encode("utf-8") + + with patch.object( + requests, "post", return_value=response_post + ) as requests_post: + with patch.object( + requests, "get", return_value=response_get + ) as requests_get: + self.client.get( + self.reverse_action( + "log_into_github", + ), + {"code": code}, + ) + + requests_post.assert_called_once_with( + url="https://github.com/login/oauth/access_token", + headers={"Accept": "application/json"}, + params={ + "client_id": settings.GITHUB_CLIENT_ID, + "client_secret": settings.GITHUB_CLIENT_SECRET, + "code": code, + }, + timeout=5, + ) + requests_get.assert_called_once_with( + url="https://api.github.com/user", + headers={ + "Accept": "application/json", + "Authorization": "Bearer 123254", + }, + timeout=5, + ) + + def test_log_into_github__invalid_serializer(self): + """User data from Github is not in the valid format.""" + code = "3e074f3e12656707cf7f" + + response_post = requests.Response() + response_post.status_code = status.HTTP_200_OK + response_post.encoding = "utf-8" + # pylint: disable-next=protected-access + response_post._content = json.dumps( + {"access_token": "123254", "token_type": "Bearer"} + ).encode("utf-8") + + response_get = requests.Response() + response_get.status_code = status.HTTP_200_OK + response_get.encoding = "utf-8" + # pylint: disable-next=protected-access + response_get._content = json.dumps( + { + "id": 999999999999999, + "email": "1223533", + "name": "contributor new", + "location": "London", + "html_url": "https://github.com/contributornew", + "avatar_url": "https://contributornew.github.io/", + } + ).encode("utf-8") + + with patch.object( + requests, "post", return_value=response_post + ) as requests_post: + with patch.object( + requests, "get", return_value=response_get + ) as requests_get: + self.client.get( + self.reverse_action( + "log_into_github", + ), + {"code": code}, + status_code_assertion=status.HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS, + ) + + requests_post.assert_called_once_with( + url="https://github.com/login/oauth/access_token", + headers={"Accept": "application/json"}, + params={ + "client_id": settings.GITHUB_CLIENT_ID, + "client_secret": settings.GITHUB_CLIENT_SECRET, + "code": code, + }, + timeout=5, + ) + requests_get.assert_called_once_with( + url="https://api.github.com/user", + headers={ + "Accept": "application/json", + "Authorization": "Bearer 123254", + }, + timeout=5, + )