Fix #4841: Use the plugins login for invitations
parent
3d5b98d2a9
commit
78abcab6d5
|
@ -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,14 +81,8 @@ 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)
|
||||
user = private_register_for_new_user(**data)
|
||||
data = parse_private_register_data(request.DATA)
|
||||
user = private_register_for_new_user(**data)
|
||||
|
||||
data = make_auth_response_data(user)
|
||||
return response.Created(data)
|
||||
|
@ -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"))
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue