Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add filter backends and limit the list view to super or staff u… #203

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions eox_nelp/pearson_vue/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from eox_core.edxapp_wrapper.bearer_authentication import BearerAuthentication
from rest_framework import status
from rest_framework.filters import SearchFilter
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
Expand Down Expand Up @@ -59,6 +60,8 @@ class PearsonRTENBaseView(CreateModelMixin, ListModelMixin, GenericViewSet):
serializer_class = PearsonRTENSerializer
queryset = PearsonRTENEvent.objects.all() # pylint: disable=no-member
authentication_classes = [BearerAuthentication, JwtAuthentication]
filter_backends = [SearchFilter]
search_fields = ["candidate__username", "course__id"]

def dispatch(self, request, *args, **kwargs):
"""
Expand Down Expand Up @@ -133,6 +136,30 @@ def create(self, request, *args, **kwargs):

return response

def list(self, request, *args, **kwargs):
"""
Retrieve a list of objects if the user has the necessary permissions.

This method overrides the default list method to add a permission check.
Only users who are superusers or staff members are allowed to retrieve the list of objects.
If the user does not have the necessary permissions, an HTTP 404 error is raised.

Args:
request (HttpRequest): The request object containing user information.
*args: Additional positional arguments.
**kwargs: Additional keyword arguments.

Returns:
Response: The response object containing the list of objects if the user has the necessary permissions.

Raises:
Http404: If the user does not have the necessary permissions.
"""
if request.user.is_superuser or request.user.is_staff:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this force that the User used for the application to get the token, needs to be staff?
I think that only creating the application was enough to get a token and use the API.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you are not staff you shouldn't be able to get data from another users

return super().list(request, *args, **kwargs)

raise Http404

def get_candidate(self):
"""
Retrieves the candidate user based on the client candidate ID provided in the request data.
Expand Down
21 changes: 20 additions & 1 deletion eox_nelp/pearson_vue/tests/api/v1/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def setUp(self): # pylint: disable=invalid-name
Set up test client.
"""
self.client = APIClient()
self.user, _ = User.objects.get_or_create(username='testuser', password='12345')
self.user, _ = User.objects.get_or_create(username='testuser', password='12345', is_staff=True)
self.client.force_authenticate(user=self.user)
self.course_key = CourseKey.from_string("course-v1:test+CS501+2022_T4")
self.course, _ = CourseOverview.objects.get_or_create(id=self.course_key)
Expand Down Expand Up @@ -191,6 +191,25 @@ def test_get_event(self):
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data["count"], len(events))

def test_get_event_no_permission(self):
"""
Test retrieving an event without the necessary permissions.

Expected behavior:
- The response returns a 404 status code.
"""
# Create a record to ensure there is at least one element
PearsonRTENEvent.objects.create(event_type=self.event_type, content={}) # pylint: disable=no-member

# Create non staff user
non_staff_user, _ = User.objects.get_or_create(username='non_staff', password='12345')
self.client.force_authenticate(user=non_staff_user)

# Attempt to retrieve all the events of the same type
response = self.client.get(reverse(f"pearson-vue-api:v1:{self.event_type}-list"), format="json")

self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

@override_settings(PEARSON_RTEN_API_ENABLED=False)
def test_create_result_notification_event_disabled(self):
"""
Expand Down
Loading