Thursday, February 1, 2024

Starting with the lecture detail view

The list view where all the lectures of a course can be fetched is a more public view, as the list of lectures should be visible to the general public even without login and registration. The only constraint is that the course should be published. Unpublished courses should be visible only to admin and to instructors.

For this reason, the GET method handler in lecture view is:

def get(self, request, *args, **kwargs):
    try:
        self.authenticate(request)
    except Exception as e:
        pass
    if self.request.user is not None and self.request.user.is_staff:
        self.init_lecture()
    else:
        self.init_lecture(admin_only=False)
    if self.kwargs.get('id', None) is None:
        return self.list(request, *args, **kwargs)
    self.check_permissions(request)
    return self.retrieve(request, *args, **kwargs)

First I call the authenticate method which will insert the user object into the request body from the JWT in the header. But, I call it in a way that it does not throw an exception. If the user is a staff user, I extract the course even if it is unpublished. Otherwise, only published courses will be extracted. This is by modifying the init_lecture method to be:

def init_lecture(self, admin_only=True):
    '''
    Initialize lecture view
        - fetch course object
    '''
    course_slug = self.kwargs.get('slug', None)
    self.course = Course.objects.get_course_by_slug(
        course_slug,
        admin_only=admin_only
    )

Unless the method is called with admin_only=False, it will extract even unpublished courses. In the view method, this happens only when there are no credentials or when the user is not admin. If a course is unpublished, a normal user or anonymous user will get a 'Course not found' 404 error.

In the GET method handler, if an id is passed in the url, it will proceed to the detail view. Here, for now, I am only checking permissions in the sense that a user should be logged in. The method check_permissions is:

def check_permissions(self, request):
    if request.user is None:
        raise CustomAPIError(
            status_code=status.HTTP_403_FORBIDDEN,
            detail='Must be logged in to access a lecture'
    )

Later this will check for registration and payment. For example, it an instructor wishes to have a course completely paid, the check_permissions will ensure that the user has paid for the course. My plan is to keep a certain percentage of videos of a course to be free, and so this can check if a video can be watched for free or needs to be paid for. This of course also implies that the lectures need a sequence ID within a course, so that you can find out beyond which lecture, a user will need to pay for the course.

The next view will be the PATCH and DELETE view. The lecture model needs a few changes and so does the serializer, as the detail view will need more details including the video content and also other resources like .pdf attachments etc.

No comments:

Post a Comment