Add github login functionality to the Auth API

remotes/origin/enhancement/email-actions
David Barragán Merino 2014-06-11 14:18:49 +02:00
parent fa68d034e5
commit 4860c7cbb9
3 changed files with 69 additions and 20 deletions

View File

@ -28,6 +28,7 @@ from rest_framework import serializers
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,6 +38,7 @@ 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
@ -130,11 +132,34 @@ class AuthViewSet(viewsets.ViewSet):
return self._private_register(request)
raise exc.BadRequest(_("invalid register type"))
# Login view: /api/v1/auth
def create(self, request, **kwargs):
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):
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"))

View File

@ -63,14 +63,18 @@ def send_private_register_email(user, **kwargs) -> bool:
return bool(email.send())
def is_user_already_registred(*, username:str, email:str) -> bool:
def is_user_already_registred(*, username:str, email:str, github_id:int=None) -> bool:
"""
Checks if a specified user is already registred.
"""
user_model = get_model("users", "User")
qs = user_model.objects.filter(Q(username=username) |
Q(email=email))
or_expr = Q(username=username) | Q(email=email)
if github_id:
or_expr = or_expr | Q(email=email)
qs = user_model.objects.filter(or_expr)
return qs.exists()
@ -90,7 +94,7 @@ def get_membership_by_token(token:str):
@tx.atomic
def public_register(username:str, password:str, email:str, first_name:str, last_name:str):
def public_register(username:str, password:str, email:str, full_name:str):
"""
Given a parsed parameters, try register a new user
knowing that it follows a public register flow.
@ -107,8 +111,7 @@ def public_register(username:str, password:str, email:str, first_name:str, last_
user_model = get_model("users", "User")
user = user_model(username=username,
email=email,
first_name=first_name,
last_name=last_name)
full_name=full_name)
user.set_password(password)
user.save()
@ -138,21 +141,18 @@ def private_register_for_existing_user(token:str, username:str, password:str):
@tx.atomic
def private_register_for_new_user(token:str, username:str, email:str,
first_name:str, last_name:str, password:str):
full_name:str, password:str):
"""
Given a inviation token, try register new user matching
the invitation token.
"""
user_model = get_model("users", "User")
if is_user_already_registred(username=username, email=email):
raise exc.WrongArguments(_("Username or Email is already in use."))
user_model = get_model("users", "User")
user = user_model(username=username,
email=email,
first_name=first_name,
last_name=last_name)
full_name=full_name)
user.set_password(password)
try:
@ -167,6 +167,30 @@ 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 = get_model("users", "User")
user, created = user_model.objects.get_or_create(github_id=github_id,
defaults={"username": username,
"email": email,
"full_name": full_name,
"bio": bio})
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

View File

@ -79,7 +79,7 @@ def _get(url:str, headers:dict) -> dict:
data = response.json()
if response.status_code != 200:
raise exc.GitHubApiErrorApiError({"status_code": response.status_code,
raise exc.GitHubApiError({"status_code": response.status_code,
"error": data.get("error", "")})
return data
@ -92,7 +92,7 @@ def _post(url:str, params:dict, headers:dict) -> dict:
data = response.json()
if response.status_code != 200 or "error" in data:
raise exc.GitHubApiErrorApiError({"status_code": response.status_code,
raise exc.GitHubApiError({"status_code": response.status_code,
"error": data.get("error", "")})
return data
@ -136,7 +136,7 @@ def get_user_emails(headers:dict=HEADERS) -> list:
"""
url = _build_url("user", "emails")
data = _get(url, headers=headers)
return [Email(email=e.get("email", None), is_primary=e.get("primary", None))
return [Email(email=e.get("email", None), is_primary=e.get("primary", False))
for e in data]