Merge pull request #908 from taigaio/issue/4841-invitation-login-with-plugins

Fix #4841: Use the plugins login for invitations
remotes/origin/github-import
Alejandro 2017-01-04 14:50:52 +01:00 committed by GitHub
commit b5fefb8f0f
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 .validators import PublicRegisterValidator
from .validators import PrivateRegisterForExistingUserValidator
from .validators import PrivateRegisterForNewUserValidator
from .validators import PrivateRegisterValidator
from .services import private_register_for_existing_user
from .services import private_register_for_new_user
from .services import public_register
from .services import make_auth_response_data
from .services import get_auth_plugins
from .services import accept_invitation_by_existing_user
from .permissions import AuthPermission
@ -61,37 +60,8 @@ def _parse_data(data:dict, *, cls):
# Parse public register data
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_for_new_user_data = \
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
parse_private_register_data = partial(_parse_data, cls=PrivateRegisterValidator)
class AuthViewSet(viewsets.ViewSet):
@ -111,13 +81,7 @@ class AuthViewSet(viewsets.ViewSet):
return response.Created(data)
def _private_register(self, request):
register_type = parse_register_type(request.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)
data = parse_private_register_data(request.DATA)
user = private_register_for_new_user(**data)
data = make_auth_response_data(user)
@ -140,9 +104,13 @@ class AuthViewSet(viewsets.ViewSet):
auth_plugins = get_auth_plugins()
login_type = request.DATA.get("type", None)
invitation_token = request.DATA.get("invitation_token", None)
if login_type in auth_plugins:
data = auth_plugins[login_type]['login_func'](request)
if invitation_token:
accept_invitation_by_existing_user(invitation_token, data['id'])
return response.Ok(data)
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
def private_register_for_existing_user(token:str, username:str, password:str):
"""
Register works not only for register users, also serves for accept
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)
def accept_invitation_by_existing_user(token:str, user_id:int):
user_model = get_user_model()
user = user_model.objects.get(id=user_id)
membership = get_membership_by_token(token)
try:
@ -145,8 +138,6 @@ def private_register_for_existing_user(token:str, username:str, password:str):
membership.save(update_fields=["user"])
except IntegrityError:
raise exc.IntegrityError(_("This user is already a member of the project."))
send_register_email(user)
return user

View File

@ -48,11 +48,5 @@ class PublicRegisterValidator(BaseRegisterValidator):
pass
class PrivateRegisterForNewUserValidator(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)
class PrivateRegisterValidator(BaseRegisterValidator):
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
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
user = factories.UserFactory()
membership = factories.MembershipFactory(user=user)
register_form.update({
"type": "private",
"existing": "1",
"token": membership.token,
auth_data = {
"type": "normal",
"invitation_token": membership.token,
"username": user.username,
"email": user.email,
"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):