Add user_id validation for LOS and assignment candidates

This commit is contained in:
Finn Stutzenstein 2020-11-09 08:54:41 +01:00
parent 7b0f8e3c25
commit 72dc55558f
No known key found for this signature in database
GPG Key ID: 9042F605C6324654
5 changed files with 34 additions and 33 deletions

View File

@ -346,6 +346,9 @@ class ListOfSpeakersViewSet(
raise ValidationError({"detail": "The list of speakers is closed."}) raise ValidationError({"detail": "The list of speakers is closed."})
user = self.request.user user = self.request.user
else: else:
if not isinstance(user_id, int):
raise ValidationError({"detail": "user_id has to be an int."})
point_of_order = False # not for someone else point_of_order = False # not for someone else
# Add someone else. # Add someone else.
if not has_perm( if not has_perm(
@ -353,8 +356,8 @@ class ListOfSpeakersViewSet(
): ):
self.permission_denied(request) self.permission_denied(request)
try: try:
user = get_user_model().objects.get(pk=int(user_id)) user = get_user_model().objects.get(pk=user_id)
except (ValueError, get_user_model().DoesNotExist): except get_user_model().DoesNotExist:
raise ValidationError({"detail": "User does not exist."}) raise ValidationError({"detail": "User does not exist."})
# Try to add the user. This ensurse that a user is not twice in the # Try to add the user. This ensurse that a user is not twice in the

View File

@ -126,46 +126,29 @@ class AssignmentViewSet(ModelViewSet):
assignment.remove_candidate(request.user) assignment.remove_candidate(request.user)
return "You have withdrawn your candidature successfully." return "You have withdrawn your candidature successfully."
def get_user_from_request_data(self, request):
"""
Helper method to get a specific user from request data (not the
request.user) so that the view self.candidature_other can play with it.
"""
if not isinstance(request.data, dict):
raise ValidationError(
{
"detail": "Invalid data. Expected dictionary, got {0}.",
"args": [type(request.data)],
}
)
user_str = request.data.get("user", "")
try:
user_pk = int(user_str)
except ValueError:
raise ValidationError(
{"detail": 'Invalid data. Expected something like {"user": <id>}.'}
)
try:
user = get_user_model().objects.get(pk=user_pk)
except get_user_model().DoesNotExist:
raise ValidationError(
{"detail": "Invalid data. User {0} does not exist.", "args": [user_pk]}
)
return user
@detail_route(methods=["post", "delete"]) @detail_route(methods=["post", "delete"])
def candidature_other(self, request, pk=None): def candidature_other(self, request, pk=None):
""" """
View to nominate other users (POST) or delete their candidature View to nominate other users (POST) or delete their candidature
status (DELETE). The client has to send {'user': <id>}. status (DELETE). The client has to send {'user': <id>}.
""" """
user = self.get_user_from_request_data(request) user_id = request.data.get("user")
if not isinstance(user_id, int):
raise ValidationError({"detail": "user_id must be an int."})
try:
user = get_user_model().objects.get(pk=user_id)
except get_user_model().DoesNotExist:
raise ValidationError(
{"detail": "Invalid data. User {0} does not exist.", "args": [user_id]}
)
assignment = self.get_object() assignment = self.get_object()
if request.method == "POST": if request.method == "POST":
return self.nominate_other(request, user, assignment) return self.nominate_other(request, user, assignment)
else: else:
# request.method == 'DELETE' # request.method == 'DELETE'
return self.delete_other(request, user, assignment) return self.withdraw_other(request, user, assignment)
def nominate_other(self, request, user, assignment): def nominate_other(self, request, user, assignment):
if assignment.phase == assignment.PHASE_FINISHED: if assignment.phase == assignment.PHASE_FINISHED:
@ -191,7 +174,7 @@ class AssignmentViewSet(ModelViewSet):
{"detail": "User {0} was nominated successfully.", "args": [str(user)]} {"detail": "User {0} was nominated successfully.", "args": [str(user)]}
) )
def delete_other(self, request, user, assignment): def withdraw_other(self, request, user, assignment):
# To delete candidature status you have to be a manager. # To delete candidature status you have to be a manager.
if not has_perm(request.user, "assignments.can_manage"): if not has_perm(request.user, "assignments.can_manage"):
self.permission_denied(request) self.permission_denied(request)

View File

@ -356,6 +356,13 @@ class ManageSpeaker(TestCase):
).exists() ).exists()
) )
def test_add_someone_else_no_id(self):
response = self.client.post(
reverse("listofspeakers-manage-speaker", args=[self.list_of_speakers.pk]),
{"user": ["not valid"]},
)
self.assertEqual(response.status_code, 400)
def test_point_of_order_single(self): def test_point_of_order_single(self):
config["agenda_enable_point_of_order_speakers"] = True config["agenda_enable_point_of_order_speakers"] = True
self.assertEqual(Speaker.objects.all().count(), 0) self.assertEqual(Speaker.objects.all().count(), 0)

View File

@ -279,6 +279,14 @@ class CandidatureOther(TestCase):
.exists() .exists()
) )
def test_nominate_other_invalid_id(self):
response = self.client.post(
reverse("assignment-candidature-other", args=[self.assignment.pk]),
{"user": ["not valid"]},
)
self.assertEqual(response.status_code, 400)
def test_nominate_other_twice(self): def test_nominate_other_twice(self):
self.assignment.add_candidate( self.assignment.add_candidate(
get_user_model().objects.get(username="test_user_eeheekai4Phue6cahtho") get_user_model().objects.get(username="test_user_eeheekai4Phue6cahtho")

View File

@ -46,7 +46,7 @@ class ListOfSpeakersViewSetManageSpeaker(TestCase):
self.request.method = "POST" self.request.method = "POST"
self.request.user = 1 self.request.user = 1
self.request.data = { self.request.data = {
"user": "2" "user": 2
} # It is assumed that the request user has pk!=2. } # It is assumed that the request user has pk!=2.
mock_get_user_model.return_value = MockUser = MagicMock() mock_get_user_model.return_value = MockUser = MagicMock()
MockUser.objects.get.return_value = mock_user = MagicMock() MockUser.objects.get.return_value = mock_user = MagicMock()