From c517a8519cf258a0d64fa4b8220a29cd4f29f9bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Mon, 9 Feb 2015 17:08:37 +0100 Subject: [PATCH] Allow auth plugins --- requirements-devel.txt | 1 + settings/testing.py | 5 +- taiga/auth/api.py | 36 +--- taiga/auth/services.py | 69 +++----- taiga/base/connectors/exceptions.py | 4 - taiga/base/connectors/github.py | 166 ------------------ .../migrations/0007_auto_20150209_1611.py | 46 +++++ taiga/users/models.py | 14 +- taiga/users/serializers.py | 4 +- tests/integration/test_auth_api.py | 83 +++++---- tests/unit/test_connectors_github.py | 39 ++-- 11 files changed, 163 insertions(+), 304 deletions(-) delete mode 100644 taiga/base/connectors/github.py create mode 100644 taiga/users/migrations/0007_auto_20150209_1611.py diff --git a/requirements-devel.txt b/requirements-devel.txt index 908c44562..78044b669 100644 --- a/requirements-devel.txt +++ b/requirements-devel.txt @@ -9,3 +9,4 @@ pytest-pythonpath==0.3 coverage==3.7.1 coveralls==0.4.2 django-slowdown==0.0.1 +taiga-contrib-github-auth==0.0.2 diff --git a/settings/testing.py b/settings/testing.py index c20da9eb0..f32cb405d 100644 --- a/settings/testing.py +++ b/settings/testing.py @@ -24,7 +24,10 @@ MEDIA_ROOT = "/tmp" EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend" -INSTALLED_APPS = INSTALLED_APPS + ["tests"] +INSTALLED_APPS = INSTALLED_APPS + [ + "tests", + "taiga_contrib_github_auth", +] REST_FRAMEWORK["DEFAULT_THROTTLE_RATES"] = { "anon": None, diff --git a/taiga/auth/api.py b/taiga/auth/api.py index b0d0365d2..e2393868d 100644 --- a/taiga/auth/api.py +++ b/taiga/auth/api.py @@ -27,7 +27,6 @@ from taiga.base.api import viewsets from taiga.base.decorators import list_route from taiga.base import exceptions as exc -from taiga.base.connectors import github from taiga.users.services import get_and_validate_user from .serializers import PublicRegisterSerializer @@ -37,8 +36,8 @@ from .services import private_register_for_existing_user from .services import private_register_for_new_user from .services import public_register -from .services import github_register from .services import make_auth_response_data +from .services import get_auth_plugins from .permissions import AuthPermission @@ -135,36 +134,15 @@ def register(self, request, **kwargs): return self._private_register(request) raise exc.BadRequest(_("invalid register type")) - def _login(self, request): - username = request.DATA.get('username', None) - password = request.DATA.get('password', None) - - user = get_and_validate_user(username=username, password=password) - data = make_auth_response_data(user) - return Response(data, status=status.HTTP_200_OK) - - def _github_login(self, request): - code = request.DATA.get('code', None) - token = request.DATA.get('token', None) - - email, user_info = github.me(code) - - user = github_register(username=user_info.username, - email=email, - full_name=user_info.full_name, - github_id=user_info.id, - bio=user_info.bio, - token=token) - data = make_auth_response_data(user) - return Response(data, status=status.HTTP_200_OK) # Login view: /api/v1/auth def create(self, request, **kwargs): self.check_permissions(request, 'create', None) + auth_plugins = get_auth_plugins() + + login_type = request.DATA.get("type", None) + + if login_type in auth_plugins: + return auth_plugins[login_type]['login_func'](request) - type = request.DATA.get("type", None) - if type == "normal": - return self._login(request) - elif type == "github": - return self._github_login(request) raise exc.BadRequest(_("invalid login type")) diff --git a/taiga/auth/services.py b/taiga/auth/services.py index 1c0f64deb..19bb6ebe3 100644 --- a/taiga/auth/services.py +++ b/taiga/auth/services.py @@ -29,6 +29,9 @@ from django.db import IntegrityError from django.utils.translation import ugettext as _ +from rest_framework.response import Response +from rest_framework import status + from djmail.template_mail import MagicMailBuilder, InlineCSSTemplateMail from taiga.base import exceptions as exc @@ -39,6 +42,19 @@ from .tokens import get_token_for_user from .signals import user_registered as user_registered_signal +auth_plugins = {} + + +def register_auth_plugin(name, login_func): + auth_plugins[name] = { + "login_func": login_func, + } + + +def get_auth_plugins(): + return auth_plugins + + def send_register_email(user) -> bool: """ Given a user, send register welcome email @@ -169,47 +185,6 @@ def private_register_for_new_user(token:str, username:str, email:str, return user -@tx.atomic -def github_register(username:str, email:str, full_name:str, github_id:int, bio:str, token:str=None): - """ - Register a new user from github. - - This can raise `exc.IntegrityError` exceptions in - case of conflics found. - - :returns: User - """ - user_model = apps.get_model("users", "User") - - try: - # Github user association exist? - user = user_model.objects.get(github_id=github_id) - except user_model.DoesNotExist: - try: - # Is a user with the same email as the github user? - user = user_model.objects.get(email=email) - user.github_id = github_id - user.save(update_fields=["github_id"]) - except user_model.DoesNotExist: - # Create a new user - username_unique = slugify_uniquely(username, user_model, slugfield="username") - user = user_model.objects.create(email=email, - username=username_unique, - github_id=github_id, - full_name=full_name, - bio=bio) - - send_register_email(user) - user_registered_signal.send(sender=user.__class__, user=user) - - if token: - membership = get_membership_by_token(token) - membership.user = user - membership.save(update_fields=["user"]) - - return user - - def make_auth_response_data(user) -> dict: """ Given a domain and user, creates data structure @@ -220,3 +195,15 @@ def make_auth_response_data(user) -> dict: data = dict(serializer.data) data["auth_token"] = get_token_for_user(user, "authentication") return data + + +def normal_login_func(request): + username = request.DATA.get('username', None) + password = request.DATA.get('password', None) + + user = get_and_validate_user(username=username, password=password) + data = make_auth_response_data(user) + return Response(data, status=status.HTTP_200_OK) + + +register_auth_plugin("normal", normal_login_func); diff --git a/taiga/base/connectors/exceptions.py b/taiga/base/connectors/exceptions.py index b7647e674..ae2cf2bb6 100644 --- a/taiga/base/connectors/exceptions.py +++ b/taiga/base/connectors/exceptions.py @@ -21,7 +21,3 @@ class ConnectorBaseException(BaseException): status_code = 400 default_detail = _("Connection error.") - - -class GitHubApiError(ConnectorBaseException): - pass diff --git a/taiga/base/connectors/github.py b/taiga/base/connectors/github.py deleted file mode 100644 index c60cb1d17..000000000 --- a/taiga/base/connectors/github.py +++ /dev/null @@ -1,166 +0,0 @@ -# Copyright (C) 2014 Andrey Antukh -# Copyright (C) 2014 Jesús Espino -# Copyright (C) 2014 David Barragán -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as -# published by the Free Software Foundation, either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . - -import requests -import json - -from collections import namedtuple -from urllib.parse import urljoin - -from django.conf import settings -from django.utils.translation import ugettext_lazy as _ - -from . import exceptions as exc - - -###################################################### -## Data -###################################################### - -CLIENT_ID = getattr(settings, "GITHUB_API_CLIENT_ID", None) -CLIENT_SECRET = getattr(settings, "GITHUB_API_CLIENT_SECRET", None) - -URL = getattr(settings, "GITHUB_URL", "https://github.com/") -API_URL = getattr(settings, "GITHUB_API_URL", "https://api.github.com/") -API_RESOURCES_URLS = { - "login": { - "authorize": "login/oauth/authorize", - "access-token": "login/oauth/access_token" - }, - "user": { - "profile": "user", - "emails": "user/emails" - } -} - - -HEADERS = {"Accept": "application/json",} - -AuthInfo = namedtuple("AuthInfo", ["access_token"]) -User = namedtuple("User", ["id", "username", "full_name", "bio"]) -Email = namedtuple("Email", ["email", "is_primary"]) - - -###################################################### -## utils -###################################################### - -def _build_url(*args, **kwargs) -> str: - """ - Return a valid url. - """ - resource_url = API_RESOURCES_URLS - for key in args: - resource_url = resource_url[key] - - if kwargs: - resource_url = resource_url.format(**kwargs) - - return urljoin(API_URL, resource_url) - - -def _get(url:str, headers:dict) -> dict: - """ - Make a GET call. - """ - response = requests.get(url, headers=headers) - - data = response.json() - if response.status_code != 200: - raise exc.GitHubApiError({"status_code": response.status_code, - "error": data.get("error", "")}) - return data - - -def _post(url:str, params:dict, headers:dict) -> dict: - """ - Make a POST call. - """ - response = requests.post(url, params=params, headers=headers) - - data = response.json() - if response.status_code != 200 or "error" in data: - raise exc.GitHubApiError({"status_code": response.status_code, - "error": data.get("error", "")}) - return data - - -###################################################### -## Simple calls -###################################################### - -def login(access_code:str, client_id:str=CLIENT_ID, client_secret:str=CLIENT_SECRET, - headers:dict=HEADERS): - """ - Get access_token fron an user authorized code, the client id and the client secret key. - (See https://developer.github.com/v3/oauth/#web-application-flow). - """ - if not CLIENT_ID or not CLIENT_SECRET: - raise exc.GitHubApiError({"error_message": _("Login with github account is disabled. Contact " - "with the sysadmins. Maybe they're snoozing in a " - "secret hideout of the data center.")}) - - url = urljoin(URL, "login/oauth/access_token") - params={"code": access_code, - "client_id": client_id, - "client_secret": client_secret, - "scope": "user:emails"} - data = _post(url, params=params, headers=headers) - return AuthInfo(access_token=data.get("access_token", None)) - - -def get_user_profile(headers:dict=HEADERS): - """ - Get authenticated user info. - (See https://developer.github.com/v3/users/#get-the-authenticated-user). - """ - url = _build_url("user", "profile") - data = _get(url, headers=headers) - return User(id=data.get("id", None), - username=data.get("login", None), - full_name=(data.get("name", None) or ""), - bio=(data.get("bio", None) or "")) - - -def get_user_emails(headers:dict=HEADERS) -> list: - """ - Get a list with all emails of the authenticated user. - (See https://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user). - """ - url = _build_url("user", "emails") - data = _get(url, headers=headers) - return [Email(email=e.get("email", None), is_primary=e.get("primary", False)) - for e in data] - - -###################################################### -## Convined calls -###################################################### - -def me(access_code:str) -> tuple: - """ - Connect to a github account and get all personal info (profile and the primary email). - """ - auth_info = login(access_code) - - headers = HEADERS.copy() - headers["Authorization"] = "token {}".format(auth_info.access_token) - - user = get_user_profile(headers=headers) - emails = get_user_emails(headers=headers) - - primary_email = next(filter(lambda x: x.is_primary, emails)) - return primary_email.email, user diff --git a/taiga/users/migrations/0007_auto_20150209_1611.py b/taiga/users/migrations/0007_auto_20150209_1611.py new file mode 100644 index 000000000..4f1bc2caf --- /dev/null +++ b/taiga/users/migrations/0007_auto_20150209_1611.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations +from django.conf import settings +import django_pgjson.fields + + +def migrate_github_id(apps, schema_editor): + AuthData = apps.get_model("users", "AuthData") + User = apps.get_model("users", "User") + for user in User.objects.all(): + if user.github_id: + AuthData.objects.create(user=user, key="github", value=user.github_id, extra={}) + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0006_auto_20141030_1132'), + ] + + operations = [ + migrations.CreateModel( + name='AuthData', + fields=[ + ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=False, auto_created=True)), + ('key', models.SlugField()), + ('value', models.CharField(max_length=300)), + ('extra', django_pgjson.fields.JsonField()), + ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ], + options={ + }, + bases=(models.Model,), + ), + migrations.AlterUniqueTogether( + name='authdata', + unique_together=set([('key', 'value')]), + ), + migrations.RunPython(migrate_github_id), + migrations.RemoveField( + model_name='user', + name='github_id', + ), + ] diff --git a/taiga/users/models.py b/taiga/users/models.py index 693225898..832267250 100644 --- a/taiga/users/models.py +++ b/taiga/users/models.py @@ -32,6 +32,7 @@ from django.utils.encoding import force_bytes from django.template.defaultfilters import slugify +from django_pgjson.fields import JsonField from djorm_pgarray.fields import TextArrayField from taiga.auth.tokens import get_token_for_user @@ -129,7 +130,6 @@ class User(AbstractBaseUser, PermissionsMixin): new_email = models.EmailField(_('new email address'), null=True, blank=True) - github_id = models.IntegerField(null=True, blank=True, verbose_name=_("github ID"), db_index=True) is_system = models.BooleanField(null=False, blank=False, default=False) USERNAME_FIELD = 'username' @@ -170,9 +170,9 @@ def cancel(self): self.default_timezone = "" self.colorize_tags = True self.token = None - self.github_id = None self.set_unusable_password() self.save() + self.auth_data.all().delete() class Role(models.Model): name = models.CharField(max_length=200, null=False, blank=False, @@ -211,6 +211,16 @@ def __str__(self): return self.name +class AuthData(models.Model): + user = models.ForeignKey('users.User', related_name="auth_data") + key = models.SlugField(max_length=50) + value = models.CharField(max_length=300) + extra = JsonField() + + class Meta: + unique_together = ["key", "value"] + + # On Role object is changed, update all membership # related to current role. @receiver(models.signals.post_save, sender=Role, diff --git a/taiga/users/serializers.py b/taiga/users/serializers.py index 8132c7db2..5fb28310b 100644 --- a/taiga/users/serializers.py +++ b/taiga/users/serializers.py @@ -33,9 +33,9 @@ class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ("id", "username", "full_name", "full_name_display", "email", - "github_id", "color", "bio", "default_language", + "color", "bio", "default_language", "default_timezone", "is_active", "photo", "big_photo") - read_only_fields = ("id", "email", "github_id") + read_only_fields = ("id", "email") def validate_username(self, attrs, source): value = attrs[source] diff --git a/tests/integration/test_auth_api.py b/tests/integration/test_auth_api.py index 793d73d1a..d7d0261c8 100644 --- a/tests/integration/test_auth_api.py +++ b/tests/integration/test_auth_api.py @@ -24,11 +24,12 @@ from .. import factories -from taiga.base.connectors import github from taiga.front import resolve as resolve_front_url from taiga.users import models from taiga.auth.tokens import get_token_for_user +from taiga_contrib_github_auth import connector as github_connector + pytestmark = pytest.mark.django_db @@ -95,12 +96,14 @@ def test_response_200_in_registration_with_github_account(client, settings): form = {"type": "github", "code": "xxxxxx"} - with patch("taiga.base.connectors.github.me") as m_me: + auth_data_model = apps.get_model("users", "AuthData") + + with patch("taiga_contrib_github_auth.connector.me") as m_me: m_me.return_value = ("mmcfly@bttf.com", - github.User(id=1955, - username="mmcfly", - full_name="martin seamus mcfly", - bio="time traveler")) + github_connector.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) response = client.post(reverse("auth-list"), form) assert response.status_code == 200 @@ -109,7 +112,7 @@ def test_response_200_in_registration_with_github_account(client, settings): assert response.data["email"] == "mmcfly@bttf.com" assert response.data["full_name"] == "martin seamus mcfly" assert response.data["bio"] == "time traveler" - assert response.data["github_id"] == 1955 + assert auth_data_model.objects.filter(user__username="mmcfly", key="github", value="1955").count() == 1 def test_response_200_in_registration_with_github_account_and_existed_user_by_email(client, settings): settings.PUBLIC_REGISTER_ENABLED = False @@ -117,15 +120,14 @@ def test_response_200_in_registration_with_github_account_and_existed_user_by_em "code": "xxxxxx"} user = factories.UserFactory() user.email = "mmcfly@bttf.com" - user.github_id = None user.save() - with patch("taiga.base.connectors.github.me") as m_me: + with patch("taiga_contrib_github_auth.connector.me") as m_me: m_me.return_value = ("mmcfly@bttf.com", - github.User(id=1955, - username="mmcfly", - full_name="martin seamus mcfly", - bio="time traveler")) + github_connector.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) response = client.post(reverse("auth-list"), form) assert response.status_code == 200 @@ -134,22 +136,24 @@ def test_response_200_in_registration_with_github_account_and_existed_user_by_em assert response.data["email"] == user.email assert response.data["full_name"] == user.full_name assert response.data["bio"] == user.bio - assert response.data["github_id"] == 1955 + assert user.auth_data.filter(key="github", value="1955").count() == 1 def test_response_200_in_registration_with_github_account_and_existed_user_by_github_id(client, settings): settings.PUBLIC_REGISTER_ENABLED = False form = {"type": "github", "code": "xxxxxx"} - user = factories.UserFactory() - user.github_id = 1955 - user.save() + user = factories.UserFactory.create() - with patch("taiga.base.connectors.github.me") as m_me: + auth_data_model = apps.get_model("users", "AuthData") + auth_data_model.objects.create(user=user, key="github", value="1955", extra={}) + + + with patch("taiga_contrib_github_auth.connector.me") as m_me: m_me.return_value = ("mmcfly@bttf.com", - github.User(id=1955, - username="mmcfly", - full_name="martin seamus mcfly", - bio="time traveler")) + github_connector.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) response = client.post(reverse("auth-list"), form) assert response.status_code == 200 @@ -158,7 +162,6 @@ def test_response_200_in_registration_with_github_account_and_existed_user_by_gi assert response.data["email"] != "mmcfly@bttf.com" assert response.data["full_name"] != "martin seamus mcfly" assert response.data["bio"] != "time traveler" - assert response.data["github_id"] == user.github_id def test_response_200_in_registration_with_github_account_and_change_github_username(client, settings): settings.PUBLIC_REGISTER_ENABLED = False @@ -168,12 +171,14 @@ def test_response_200_in_registration_with_github_account_and_change_github_user user.username = "mmcfly" user.save() - with patch("taiga.base.connectors.github.me") as m_me: + auth_data_model = apps.get_model("users", "AuthData") + + with patch("taiga_contrib_github_auth.connector.me") as m_me: m_me.return_value = ("mmcfly@bttf.com", - github.User(id=1955, - username="mmcfly", - full_name="martin seamus mcfly", - bio="time traveler")) + github_connector.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) response = client.post(reverse("auth-list"), form) assert response.status_code == 200 @@ -182,7 +187,7 @@ def test_response_200_in_registration_with_github_account_and_change_github_user assert response.data["email"] == "mmcfly@bttf.com" assert response.data["full_name"] == "martin seamus mcfly" assert response.data["bio"] == "time traveler" - assert response.data["github_id"] == 1955 + assert auth_data_model.objects.filter(user__username="mmcfly-1", key="github", value="1955").count() == 1 def test_response_200_in_registration_with_github_account_in_a_project(client, settings): settings.PUBLIC_REGISTER_ENABLED = False @@ -192,12 +197,12 @@ def test_response_200_in_registration_with_github_account_in_a_project(client, s "code": "xxxxxx", "token": membership.token} - with patch("taiga.base.connectors.github.me") as m_me: + with patch("taiga_contrib_github_auth.connector.me") as m_me: m_me.return_value = ("mmcfly@bttf.com", - github.User(id=1955, - username="mmcfly", - full_name="martin seamus mcfly", - bio="time traveler")) + github_connector.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) response = client.post(reverse("auth-list"), form) assert response.status_code == 200 @@ -210,12 +215,12 @@ def test_response_404_in_registration_with_github_in_a_project_with_invalid_toke "code": "xxxxxx", "token": "123456"} - with patch("taiga.base.connectors.github.me") as m_me: + with patch("taiga_contrib_github_auth.connector.me") as m_me: m_me.return_value = ("mmcfly@bttf.com", - github.User(id=1955, - username="mmcfly", - full_name="martin seamus mcfly", - bio="time traveler")) + github_connector.User(id=1955, + username="mmcfly", + full_name="martin seamus mcfly", + bio="time traveler")) response = client.post(reverse("auth-list"), form) assert response.status_code == 404 diff --git a/tests/unit/test_connectors_github.py b/tests/unit/test_connectors_github.py index f27a2f8aa..abf35d7f4 100644 --- a/tests/unit/test_connectors_github.py +++ b/tests/unit/test_connectors_github.py @@ -18,8 +18,7 @@ import pytest from unittest.mock import patch, Mock -from taiga.base.connectors import github -from taiga.base.connectors import exceptions as exc +from taiga_contrib_github_auth import connector as github def test_url_builder(): @@ -34,8 +33,8 @@ def test_url_builder(): def test_login_without_settings_params(): - with pytest.raises(exc.GitHubApiError) as e, \ - patch("taiga.base.connectors.github.requests") as m_requests: + with pytest.raises(github.GitHubApiError) as e, \ + patch("taiga_contrib_github_auth.connector.requests") as m_requests: m_requests.post.return_value = m_response = Mock() m_response.status_code = 200 m_response.json.return_value = {"access_token": "xxxxxxxx"} @@ -46,9 +45,9 @@ def test_login_without_settings_params(): def test_login_success(): - with patch("taiga.base.connectors.github.requests") as m_requests, \ - patch("taiga.base.connectors.github.CLIENT_ID") as CLIENT_ID, \ - patch("taiga.base.connectors.github.CLIENT_SECRET") as CLIENT_SECRET: + with patch("taiga_contrib_github_auth.connector.requests") as m_requests, \ + patch("taiga_contrib_github_auth.connector.CLIENT_ID") as CLIENT_ID, \ + patch("taiga_contrib_github_auth.connector.CLIENT_SECRET") as CLIENT_SECRET: CLIENT_ID = "*CLIENT_ID*" CLIENT_SECRET = "*CLIENT_SECRET*" m_requests.post.return_value = m_response = Mock() @@ -67,10 +66,10 @@ def test_login_success(): def test_login_whit_errors(): - with pytest.raises(exc.GitHubApiError) as e, \ - patch("taiga.base.connectors.github.requests") as m_requests, \ - patch("taiga.base.connectors.github.CLIENT_ID") as CLIENT_ID, \ - patch("taiga.base.connectors.github.CLIENT_SECRET") as CLIENT_SECRET: + with pytest.raises(github.GitHubApiError) as e, \ + patch("taiga_contrib_github_auth.connector.requests") as m_requests, \ + patch("taiga_contrib_github_auth.connector.CLIENT_ID") as CLIENT_ID, \ + patch("taiga_contrib_github_auth.connector.CLIENT_SECRET") as CLIENT_SECRET: CLIENT_ID = "*CLIENT_ID*" CLIENT_SECRET = "*CLIENT_SECRET*" m_requests.post.return_value = m_response = Mock() @@ -84,7 +83,7 @@ def test_login_whit_errors(): def test_get_user_profile_success(): - with patch("taiga.base.connectors.github.requests") as m_requests: + with patch("taiga_contrib_github_auth.connector.requests") as m_requests: m_requests.get.return_value = m_response = Mock() m_response.status_code = 200 m_response.json.return_value = {"id": 1955, @@ -103,8 +102,8 @@ def test_get_user_profile_success(): def test_get_user_profile_whit_errors(): - with pytest.raises(exc.GitHubApiError) as e, \ - patch("taiga.base.connectors.github.requests") as m_requests: + with pytest.raises(github.GitHubApiError) as e, \ + patch("taiga_contrib_github_auth.connector.requests") as m_requests: m_requests.get.return_value = m_response = Mock() m_response.status_code = 401 m_response.json.return_value = {"error": "Invalid credentials"} @@ -116,7 +115,7 @@ def test_get_user_profile_whit_errors(): def test_get_user_emails_success(): - with patch("taiga.base.connectors.github.requests") as m_requests: + with patch("taiga_contrib_github_auth.connector.requests") as m_requests: m_requests.get.return_value = m_response = Mock() m_response.status_code = 200 m_response.json.return_value = [{"email": "darth-vader@bttf.com", "primary": False}, @@ -134,8 +133,8 @@ def test_get_user_emails_success(): def test_get_user_emails_whit_errors(): - with pytest.raises(exc.GitHubApiError) as e, \ - patch("taiga.base.connectors.github.requests") as m_requests: + with pytest.raises(github.GitHubApiError) as e, \ + patch("taiga_contrib_github_auth.connector.requests") as m_requests: m_requests.get.return_value = m_response = Mock() m_response.status_code = 401 m_response.json.return_value = {"error": "Invalid credentials"} @@ -147,9 +146,9 @@ def test_get_user_emails_whit_errors(): def test_me(): - with patch("taiga.base.connectors.github.login") as m_login, \ - patch("taiga.base.connectors.github.get_user_profile") as m_get_user_profile, \ - patch("taiga.base.connectors.github.get_user_emails") as m_get_user_emails: + with patch("taiga_contrib_github_auth.connector.login") as m_login, \ + patch("taiga_contrib_github_auth.connector.get_user_profile") as m_get_user_profile, \ + patch("taiga_contrib_github_auth.connector.get_user_emails") as m_get_user_emails: m_login.return_value = github.AuthInfo(access_token="xxxxxxxx") m_get_user_profile.return_value = github.User(id=1955, username="mmcfly",