From b33c7aa36c708d253705b97f7d42efee5bc67b88 Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Wed, 29 Mar 2023 18:40:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .coveragerc | 1 - oauth/oauthmanager.py | 3 +- oauth/tests.py | 224 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+), 3 deletions(-) diff --git a/.coveragerc b/.coveragerc index 7656c5a..9757484 100644 --- a/.coveragerc +++ b/.coveragerc @@ -6,6 +6,5 @@ omit = *tests* *.html *whoosh_cn_backend* - *oauth* *settings.py* *venv* diff --git a/oauth/oauthmanager.py b/oauth/oauthmanager.py index 339e042..285cee5 100644 --- a/oauth/oauthmanager.py +++ b/oauth/oauthmanager.py @@ -169,7 +169,6 @@ class GoogleOauthManager(BaseOauthManager): 'redirect_uri': self.callback_url, 'scope': 'openid email', } - # url = self.AUTH_URL + "?" + urllib.parse.urlencode(params, quote_via=urllib.parse.quote) url = self.AUTH_URL + "?" + urllib.parse.urlencode(params) return url @@ -412,7 +411,7 @@ class QQOauthManager(BaseOauthManager): d = urllib.parse.parse_qs(rsp) if 'access_token' in d: token = d['access_token'] - self.access_token = token + self.access_token = token[0] return token else: raise OAuthAccessTokenException(rsp) diff --git a/oauth/tests.py b/oauth/tests.py index fdd714f..31514cd 100644 --- a/oauth/tests.py +++ b/oauth/tests.py @@ -1,6 +1,14 @@ +import json +from unittest.mock import patch + +from django.conf import settings +from django.contrib import auth from django.test import Client, RequestFactory, TestCase +from django.urls import reverse +from djangoblog.utils import get_sha256 from oauth.models import OAuthConfig +from oauth.oauthmanager import BaseOauthManager # Create your tests here. @@ -23,3 +31,219 @@ class OAuthConfigTest(TestCase): response = self.client.get('/oauth/authorize?type=weibo&code=code') self.assertEqual(response.status_code, 302) self.assertEqual(response.url, '/') + + +class OauthLoginTest(TestCase): + def setUp(self) -> None: + self.client = Client() + self.factory = RequestFactory() + self.apps = self.init_apps() + + def init_apps(self): + applications = [p() for p in BaseOauthManager.__subclasses__()] + for application in applications: + c = OAuthConfig() + c.type = application.ICON_NAME.lower() + c.appkey = 'appkey' + c.appsecret = 'appsecret' + c.save() + return applications + + def get_app_by_type(self, type): + for app in self.apps: + if app.ICON_NAME.lower() == type: + return app + + @patch("oauth.oauthmanager.WBOauthManager.do_post") + @patch("oauth.oauthmanager.WBOauthManager.do_get") + def test_weibo_login(self, mock_do_get, mock_do_post): + weibo_app = self.get_app_by_type('weibo') + assert weibo_app + url = weibo_app.get_authorization_url() + mock_do_post.return_value = json.dumps({"access_token": "access_token", + "uid": "uid" + }) + mock_do_get.return_value = json.dumps({ + "avatar_large": "avatar_large", + "screen_name": "screen_name", + "id": "id", + "email": "email", + }) + userinfo = weibo_app.get_access_token_by_code('code') + self.assertEqual(userinfo.token, 'access_token') + self.assertEqual(userinfo.openid, 'id') + + @patch("oauth.oauthmanager.GoogleOauthManager.do_post") + @patch("oauth.oauthmanager.GoogleOauthManager.do_get") + def test_google_login(self, mock_do_get, mock_do_post): + google_app = self.get_app_by_type('google') + assert google_app + url = google_app.get_authorization_url() + mock_do_post.return_value = json.dumps({ + "access_token": "access_token", + "id_token": "id_token", + }) + mock_do_get.return_value = json.dumps({ + "picture": "picture", + "name": "name", + "sub": "sub", + "email": "email", + }) + token = google_app.get_access_token_by_code('code') + userinfo = google_app.get_oauth_userinfo() + self.assertEqual(userinfo.token, 'access_token') + self.assertEqual(userinfo.openid, 'sub') + + @patch("oauth.oauthmanager.GitHubOauthManager.do_post") + @patch("oauth.oauthmanager.GitHubOauthManager.do_get") + def test_github_login(self, mock_do_get, mock_do_post): + github_app = self.get_app_by_type('github') + assert github_app + url = github_app.get_authorization_url() + self.assertTrue("github.com" in url) + self.assertTrue("client_id" in url) + mock_do_post.return_value = "access_token=gho_16C7e42F292c6912E7710c838347Ae178B4a&scope=repo%2Cgist&token_type=bearer" + mock_do_get.return_value = json.dumps({ + "avatar_url": "avatar_url", + "name": "name", + "id": "id", + "email": "email", + }) + token = github_app.get_access_token_by_code('code') + userinfo = github_app.get_oauth_userinfo() + self.assertEqual(userinfo.token, 'gho_16C7e42F292c6912E7710c838347Ae178B4a') + self.assertEqual(userinfo.openid, 'id') + + @patch("oauth.oauthmanager.FaceBookOauthManager.do_post") + @patch("oauth.oauthmanager.FaceBookOauthManager.do_get") + def test_facebook_login(self, mock_do_get, mock_do_post): + facebook_app = self.get_app_by_type('facebook') + assert facebook_app + url = facebook_app.get_authorization_url() + self.assertTrue("facebook.com" in url) + mock_do_post.return_value = json.dumps({ + "access_token": "access_token", + }) + mock_do_get.return_value = json.dumps({ + "name": "name", + "id": "id", + "email": "email", + "picture": { + "data": { + "url": "url" + } + } + }) + token = facebook_app.get_access_token_by_code('code') + userinfo = facebook_app.get_oauth_userinfo() + self.assertEqual(userinfo.token, 'access_token') + + @patch("oauth.oauthmanager.QQOauthManager.do_get", side_effect=[ + 'access_token=access_token&expires_in=3600', + 'callback({"client_id":"appid","openid":"openid"} );', + json.dumps({ + "nickname": "nickname", + "email": "email", + "figureurl": "figureurl", + "openid": "openid", + }) + ]) + def test_qq_login(self, mock_do_get): + qq_app = self.get_app_by_type('qq') + assert qq_app + url = qq_app.get_authorization_url() + self.assertTrue("qq.com" in url) + token = qq_app.get_access_token_by_code('code') + userinfo = qq_app.get_oauth_userinfo() + self.assertEqual(userinfo.token, 'access_token') + + @patch("oauth.oauthmanager.WBOauthManager.do_post") + @patch("oauth.oauthmanager.WBOauthManager.do_get") + def test_weibo_authoriz_login_with_email(self, mock_do_get, mock_do_post): + + mock_do_post.return_value = json.dumps({"access_token": "access_token", + "uid": "uid" + }) + mock_user_info = { + "avatar_large": "avatar_large", + "screen_name": "screen_name1", + "id": "id", + "email": "email", + } + mock_do_get.return_value = json.dumps(mock_user_info) + + response = self.client.get('/oauth/oauthlogin?type=weibo') + self.assertEqual(response.status_code, 302) + self.assertTrue("api.weibo.com" in response.url) + + response = self.client.get('/oauth/authorize?type=weibo&code=code') + self.assertEqual(response.status_code, 302) + self.assertEqual(response.url, '/') + + user = auth.get_user(self.client) + assert user.is_authenticated + self.assertTrue(user.is_authenticated) + self.assertEqual(user.username, mock_user_info['screen_name']) + self.assertEqual(user.email, mock_user_info['email']) + self.client.logout() + + response = self.client.get('/oauth/authorize?type=weibo&code=code') + self.assertEqual(response.status_code, 302) + self.assertEqual(response.url, '/') + + user = auth.get_user(self.client) + assert user.is_authenticated + self.assertTrue(user.is_authenticated) + self.assertEqual(user.username, mock_user_info['screen_name']) + self.assertEqual(user.email, mock_user_info['email']) + + @patch("oauth.oauthmanager.WBOauthManager.do_post") + @patch("oauth.oauthmanager.WBOauthManager.do_get") + def test_weibo_authoriz_login_without_email(self, mock_do_get, mock_do_post): + + mock_do_post.return_value = json.dumps({"access_token": "access_token", + "uid": "uid" + }) + mock_user_info = { + "avatar_large": "avatar_large", + "screen_name": "screen_name1", + "id": "id", + } + mock_do_get.return_value = json.dumps(mock_user_info) + + response = self.client.get('/oauth/oauthlogin?type=weibo') + self.assertEqual(response.status_code, 302) + self.assertTrue("api.weibo.com" in response.url) + + response = self.client.get('/oauth/authorize?type=weibo&code=code') + + self.assertEqual(response.status_code, 302) + + oauth_user_id = int(response.url.split('/')[-1].split('.')[0]) + self.assertEqual(response.url, f'/oauth/requireemail/{oauth_user_id}.html') + + response = self.client.post(response.url, {'email': 'test@gmail.com', 'oauthid': oauth_user_id}) + + self.assertEqual(response.status_code, 302) + sign = get_sha256(settings.SECRET_KEY + + str(1) + settings.SECRET_KEY) + + url = reverse('oauth:bindsuccess', kwargs={ + 'oauthid': oauth_user_id, + }) + self.assertEqual(response.url, f'{url}?type=email') + + path = reverse('oauth:email_confirm', kwargs={ + 'id': oauth_user_id, + 'sign': sign + }) + response = self.client.get(path) + self.assertEqual(response.status_code, 302) + self.assertEqual(response.url, f'/oauth/bindsuccess/{oauth_user_id}.html?type=success') + user = auth.get_user(self.client) + from oauth.models import OAuthUser + oauth_user = OAuthUser.objects.get(author=user) + self.assertTrue(user.is_authenticated) + self.assertEqual(user.username, mock_user_info['screen_name']) + self.assertEqual(user.email, 'test@gmail.com') + self.assertEqual(oauth_user.pk, oauth_user_id) From f7a4b6464a874db40fd0eb0a34cad033db2a1afe Mon Sep 17 00:00:00 2001 From: liangliangyy Date: Wed, 29 Mar 2023 20:12:24 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8D=95=E5=85=83?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- oauth/tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/oauth/tests.py b/oauth/tests.py index 31514cd..bb23b9b 100644 --- a/oauth/tests.py +++ b/oauth/tests.py @@ -226,7 +226,7 @@ class OauthLoginTest(TestCase): self.assertEqual(response.status_code, 302) sign = get_sha256(settings.SECRET_KEY + - str(1) + settings.SECRET_KEY) + str(oauth_user_id) + settings.SECRET_KEY) url = reverse('oauth:bindsuccess', kwargs={ 'oauthid': oauth_user_id,