Allow auth plugins
parent
dd5cff35cf
commit
c517a8519c
|
@ -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
|
||||
|
|
|
@ -24,7 +24,10 @@ CELERY_ENABLED = False
|
|||
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,
|
||||
|
|
|
@ -27,7 +27,6 @@ from rest_framework import serializers
|
|||
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 .serializers import PrivateRegisterForNewUserSerializer
|
|||
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 @@ class AuthViewSet(viewsets.ViewSet):
|
|||
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"))
|
||||
|
|
|
@ -29,6 +29,9 @@ from django.db import transaction as tx
|
|||
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 taiga.base.utils.slug import slugify_uniquely
|
|||
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);
|
||||
|
|
|
@ -21,7 +21,3 @@ from django.utils.translation import ugettext_lazy as _
|
|||
class ConnectorBaseException(BaseException):
|
||||
status_code = 400
|
||||
default_detail = _("Connection error.")
|
||||
|
||||
|
||||
class GitHubApiError(ConnectorBaseException):
|
||||
pass
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
# Copyright (C) 2014 Andrey Antukh <niwi@niwi.be>
|
||||
# Copyright (C) 2014 Jesús Espino <jespinog@gmail.com>
|
||||
# Copyright (C) 2014 David Barragán <bameda@dbarragan.com>
|
||||
# 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
|
@ -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',
|
||||
),
|
||||
]
|
|
@ -32,6 +32,7 @@ from django.utils import timezone
|
|||
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 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|||
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 @@ class Role(models.Model):
|
|||
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,
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -24,11 +24,12 @@ from django.core import mail
|
|||
|
||||
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,9 +96,11 @@ 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,
|
||||
github_connector.User(id=1955,
|
||||
username="mmcfly",
|
||||
full_name="martin seamus mcfly",
|
||||
bio="time traveler"))
|
||||
|
@ -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,12 +120,11 @@ 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,
|
||||
github_connector.User(id=1955,
|
||||
username="mmcfly",
|
||||
full_name="martin seamus mcfly",
|
||||
bio="time traveler"))
|
||||
|
@ -134,19 +136,21 @@ 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,
|
||||
github_connector.User(id=1955,
|
||||
username="mmcfly",
|
||||
full_name="martin seamus mcfly",
|
||||
bio="time traveler"))
|
||||
|
@ -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,9 +171,11 @@ 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,
|
||||
github_connector.User(id=1955,
|
||||
username="mmcfly",
|
||||
full_name="martin seamus mcfly",
|
||||
bio="time traveler"))
|
||||
|
@ -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,9 +197,9 @@ 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,
|
||||
github_connector.User(id=1955,
|
||||
username="mmcfly",
|
||||
full_name="martin seamus mcfly",
|
||||
bio="time traveler"))
|
||||
|
@ -210,9 +215,9 @@ 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,
|
||||
github_connector.User(id=1955,
|
||||
username="mmcfly",
|
||||
full_name="martin seamus mcfly",
|
||||
bio="time traveler"))
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue