Fix #4841: Use the plugins login for invitations

remotes/origin/github-import
Jesús Espino 2017-01-03 19:40:36 +01:00 committed by Alejandro Alonso
parent 3d5b98d2a9
commit 78abcab6d5
4 changed files with 20 additions and 69 deletions

View File

@ -30,14 +30,13 @@ from taiga.base import exceptions as exc
from taiga.base import response from taiga.base import response
from .validators import PublicRegisterValidator from .validators import PublicRegisterValidator
from .validators import PrivateRegisterForExistingUserValidator from .validators import PrivateRegisterValidator
from .validators import PrivateRegisterForNewUserValidator
from .services import private_register_for_existing_user
from .services import private_register_for_new_user from .services import private_register_for_new_user
from .services import public_register from .services import public_register
from .services import make_auth_response_data from .services import make_auth_response_data
from .services import get_auth_plugins from .services import get_auth_plugins
from .services import accept_invitation_by_existing_user
from .permissions import AuthPermission from .permissions import AuthPermission
@ -61,37 +60,8 @@ def _parse_data(data:dict, *, cls):
# Parse public register data # Parse public register data
parse_public_register_data = partial(_parse_data, cls=PublicRegisterValidator) parse_public_register_data = partial(_parse_data, cls=PublicRegisterValidator)
# Parse private register data for existing user
parse_private_register_for_existing_user_data = \
partial(_parse_data, cls=PrivateRegisterForExistingUserValidator)
# Parse private register data for new user # Parse private register data for new user
parse_private_register_for_new_user_data = \ parse_private_register_data = partial(_parse_data, cls=PrivateRegisterValidator)
partial(_parse_data, cls=PrivateRegisterForNewUserValidator)
class RegisterTypeEnum(Enum):
new_user = 1
existing_user = 2
def parse_register_type(userdata:dict) -> str:
"""
Parses user data and detects that register type is.
It returns RegisterTypeEnum value.
"""
# Create adhoc inner serializer for avoid parse
# manually the user data.
class _validator(validators.Validator):
existing = serializers.BooleanField()
instance = _validator(data=userdata)
if not instance.is_valid():
raise exc.RequestValidationError(instance.errors)
if instance.data["existing"]:
return RegisterTypeEnum.existing_user
return RegisterTypeEnum.new_user
class AuthViewSet(viewsets.ViewSet): class AuthViewSet(viewsets.ViewSet):
@ -111,14 +81,8 @@ class AuthViewSet(viewsets.ViewSet):
return response.Created(data) return response.Created(data)
def _private_register(self, request): def _private_register(self, request):
register_type = parse_register_type(request.DATA) data = parse_private_register_data(request.DATA)
user = private_register_for_new_user(**data)
if register_type is RegisterTypeEnum.existing_user:
data = parse_private_register_for_existing_user_data(request.DATA)
user = private_register_for_existing_user(**data)
else:
data = parse_private_register_for_new_user_data(request.DATA)
user = private_register_for_new_user(**data)
data = make_auth_response_data(user) data = make_auth_response_data(user)
return response.Created(data) return response.Created(data)
@ -140,9 +104,13 @@ class AuthViewSet(viewsets.ViewSet):
auth_plugins = get_auth_plugins() auth_plugins = get_auth_plugins()
login_type = request.DATA.get("type", None) login_type = request.DATA.get("type", None)
invitation_token = request.DATA.get("invitation_token", None)
if login_type in auth_plugins: if login_type in auth_plugins:
data = auth_plugins[login_type]['login_func'](request) data = auth_plugins[login_type]['login_func'](request)
if invitation_token:
accept_invitation_by_existing_user(invitation_token, data['id'])
return response.Ok(data) return response.Ok(data)
raise exc.BadRequest(_("invalid login type")) raise exc.BadRequest(_("invalid login type"))

View File

@ -128,16 +128,9 @@ def public_register(username:str, password:str, email:str, full_name:str):
@tx.atomic @tx.atomic
def private_register_for_existing_user(token:str, username:str, password:str): def accept_invitation_by_existing_user(token:str, user_id:int):
""" user_model = get_user_model()
Register works not only for register users, also serves for accept user = user_model.objects.get(id=user_id)
inviatations for projects as existing user.
Given a invitation token with parsed parameters, accept inviation
as existing user.
"""
user = get_and_validate_user(username=username, password=password)
membership = get_membership_by_token(token) membership = get_membership_by_token(token)
try: try:
@ -145,8 +138,6 @@ def private_register_for_existing_user(token:str, username:str, password:str):
membership.save(update_fields=["user"]) membership.save(update_fields=["user"])
except IntegrityError: except IntegrityError:
raise exc.IntegrityError(_("This user is already a member of the project.")) raise exc.IntegrityError(_("This user is already a member of the project."))
send_register_email(user)
return user return user

View File

@ -48,11 +48,5 @@ class PublicRegisterValidator(BaseRegisterValidator):
pass pass
class PrivateRegisterForNewUserValidator(BaseRegisterValidator): class PrivateRegisterValidator(BaseRegisterValidator):
token = serializers.CharField(max_length=255, required=True)
class PrivateRegisterForExistingUserValidator(validators.Validator):
username = serializers.CharField(max_length=255)
password = serializers.CharField(min_length=4)
token = serializers.CharField(max_length=255, required=True) token = serializers.CharField(max_length=255, required=True)

View File

@ -62,23 +62,21 @@ def test_respond_201_when_the_email_domain_is_in_allowed_domains(client, setting
assert response.status_code == 201 assert response.status_code == 201
def test_respond_201_with_invitation_without_public_registration(client, register_form, settings): def test_respond_201_with_invitation_login(client, settings):
settings.PUBLIC_REGISTER_ENABLED = False settings.PUBLIC_REGISTER_ENABLED = False
user = factories.UserFactory() user = factories.UserFactory()
membership = factories.MembershipFactory(user=user) membership = factories.MembershipFactory(user=user)
register_form.update({ auth_data = {
"type": "private", "type": "normal",
"existing": "1", "invitation_token": membership.token,
"token": membership.token,
"username": user.username, "username": user.username,
"email": user.email,
"password": user.username, "password": user.username,
}) }
response = client.post(reverse("auth-register"), register_form) response = client.post(reverse("auth-list"), auth_data)
assert response.status_code == 201, response.data assert response.status_code == 200, response.data
def test_response_200_in_public_registration(client, settings): def test_response_200_in_public_registration(client, settings):