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

Open api #2549

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
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
29 changes: 27 additions & 2 deletions authentication/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from django.shortcuts import render, reverse
from rest_framework import status
from rest_framework.decorators import api_view, permission_classes, renderer_classes
from rest_framework.generics import GenericAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
Expand Down Expand Up @@ -105,13 +106,37 @@ def post(self, request):
return super().post(request)


class RegisterConfirmView(SocialAuthAPIView):
class RegisterConfirmView(SocialAuthAPIView, GenericAPIView):
"""Email registration confirmation view"""

serializer_class = RegisterConfirmSerializer
permission_classes = []
authentication_classes = []

def get_serializer_cls(self):
"""Return the serializer cls"""
"""Return the serializer class"""
return RegisterConfirmSerializer

def post(self, request):
"""
Handle POST requests to confirm email registration
"""
if bool(request.session.get("hijack_history")):
return Response(status=status.HTTP_403_FORBIDDEN)

serializer_cls = self.get_serializer_cls()
strategy = load_drf_strategy(request)
backend = load_backend(strategy, EmailAuth.name, None)
serializer = serializer_cls(
data=request.data,
context={"request": request, "strategy": strategy, "backend": backend},
)

if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class RegisterDetailsView(SocialAuthAPIView):
"""Email registration details view"""
Expand Down
14 changes: 14 additions & 0 deletions cms/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import bleach
from django.templatetags.static import static
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_field

from cms import models
from cms.api import get_wagtail_img_src
Expand All @@ -19,6 +20,7 @@ class BaseCoursePageSerializer(serializers.ModelSerializer):
effort = serializers.SerializerMethodField()
length = serializers.SerializerMethodField()

@extend_schema_field(str)
def get_feature_image_src(self, instance):
"""Serializes the source of the feature_image"""
feature_img_src = None
Expand All @@ -27,19 +29,23 @@ def get_feature_image_src(self, instance):

return feature_img_src or static(DEFAULT_COURSE_IMG_PATH)

@extend_schema_field(serializers.URLField)
def get_page_url(self, instance):
return instance.get_url()

@extend_schema_field(str)
def get_description(self, instance):
return bleach.clean(instance.description, tags=[], strip=True)

@extend_schema_field(str)
def get_effort(self, instance):
return (
bleach.clean(instance.effort, tags=[], strip=True)
if instance.effort
else None
)

@extend_schema_field(str)
def get_length(self, instance):
return (
bleach.clean(instance.length, tags=[], strip=True)
Expand All @@ -66,6 +72,7 @@ class CoursePageSerializer(BaseCoursePageSerializer):
instructors = serializers.SerializerMethodField()
current_price = serializers.SerializerMethodField()

@extend_schema_field(serializers.URLField)
def get_financial_assistance_form_url(self, instance):
"""
Returns URL of the Financial Assistance Form.
Expand Down Expand Up @@ -116,6 +123,7 @@ def get_financial_assistance_form_url(self, instance):
else ""
)

@extend_schema_field(int)
def get_current_price(self, instance):
relevant_product = (
instance.product.active_products.filter().order_by("-price").first()
Expand All @@ -124,6 +132,7 @@ def get_current_price(self, instance):
)
return relevant_product.price if relevant_product else None

@extend_schema_field(list)
def get_instructors(self, instance):
members = [
member.linked_instructor_page
Expand Down Expand Up @@ -160,6 +169,7 @@ class ProgramPageSerializer(serializers.ModelSerializer):
price = serializers.SerializerMethodField()
financial_assistance_form_url = serializers.SerializerMethodField()

@extend_schema_field(str)
def get_feature_image_src(self, instance):
"""Serializes the source of the feature_image"""
feature_img_src = None
Expand All @@ -168,12 +178,15 @@ def get_feature_image_src(self, instance):

return feature_img_src or static(DEFAULT_COURSE_IMG_PATH)

@extend_schema_field(serializers.URLField)
def get_page_url(self, instance):
return instance.get_url()

@extend_schema_field(str)
def get_price(self, instance):
return instance.price[0].value["text"] if len(instance.price) > 0 else None

@extend_schema_field(serializers.URLField)
def get_financial_assistance_form_url(self, instance):
"""
Returns URL of the Financial Assistance Form.
Expand Down Expand Up @@ -235,6 +248,7 @@ class InstructorPageSerializer(serializers.ModelSerializer):

feature_image_src = serializers.SerializerMethodField()

@extend_schema_field(str)
def get_feature_image_src(self, instance):
"""Serializes the source of the feature_image"""
feature_img_src = None
Expand Down
40 changes: 30 additions & 10 deletions courses/serializers/v1/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from rest_framework import serializers
from drf_spectacular.utils import extend_schema_field, extend_schema

from cms.serializers import CoursePageSerializer
from courses import models
Expand Down Expand Up @@ -32,15 +33,33 @@ class Meta:
"type",
]


class BaseCourseRunSerializer(serializers.ModelSerializer):
"""Minimal CourseRun model serializer"""

is_archived = serializers.SerializerMethodField()

title = serializers.CharField()
start_date = serializers.DateTimeField()
end_date = serializers.DateTimeField()
enrollment_start = serializers.DateTimeField()
enrollment_end = serializers.DateTimeField()
expiration_date = serializers.DateTimeField()
courseware_url = serializers.URLField()
courseware_id = serializers.CharField()
certificate_available_date = serializers.DateTimeField()
upgrade_deadline = serializers.DateTimeField()
is_upgradable = serializers.BooleanField()
is_enrollable = serializers.BooleanField()
is_self_paced = serializers.BooleanField()
run_tag = serializers.CharField()
id = serializers.IntegerField()
live = serializers.BooleanField()
course_number = serializers.CharField()

@extend_schema_field(bool)
def get_is_archived(self, instance):
return instance.is_enrollable and instance.is_past


class Meta:
model = models.CourseRun
fields = [
Expand Down Expand Up @@ -79,6 +98,14 @@ class Meta:
fields = ["title", "readable_id", "id", "type"]


class CourseRunCertificateSerializer(serializers.ModelSerializer):
"""CourseRunCertificate model serializer"""

class Meta:
model = models.CourseRunCertificate
fields = ["uuid", "link"]


class BaseCourseRunEnrollmentSerializer(serializers.ModelSerializer):
certificate = serializers.SerializerMethodField(read_only=True)
enrollment_mode = serializers.ChoiceField(
Expand All @@ -87,6 +114,7 @@ class BaseCourseRunEnrollmentSerializer(serializers.ModelSerializer):
approved_flexible_price_exists = serializers.SerializerMethodField()
grades = serializers.SerializerMethodField(read_only=True)

@extend_schema_field(CourseRunCertificateSerializer)
def get_certificate(self, enrollment):
"""
Resolve a certificate for this enrollment if it exists
Expand Down Expand Up @@ -165,14 +193,6 @@ def to_representation(self, instance):
return serializer.data


class CourseRunCertificateSerializer(serializers.ModelSerializer):
"""CourseRunCertificate model serializer"""

class Meta:
model = models.CourseRunCertificate
fields = ["uuid", "link"]


class CourseRunGradeSerializer(serializers.ModelSerializer):
"""CourseRunGrade serializer"""

Expand Down
64 changes: 62 additions & 2 deletions courses/serializers/v1/courses.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from mitol.olposthog.features import is_enabled
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from drf_spectacular.utils import extend_schema

from cms.serializers import CoursePageSerializer
from courses import models
Expand All @@ -15,6 +16,8 @@
from flexiblepricing.api import is_courseware_flexible_price_approved
from main import features
from openedx.constants import EDX_ENROLLMENT_AUDIT_MODE, EDX_ENROLLMENT_VERIFIED_MODE
from typing import Optional, List
from drf_spectacular.utils import extend_schema_field, inline_serializer


class CourseSerializer(BaseCourseSerializer):
Expand All @@ -25,11 +28,22 @@ class CourseSerializer(BaseCourseSerializer):
page = CoursePageSerializer(read_only=True)
programs = serializers.SerializerMethodField()

@extend_schema_field(int)
def get_next_run_id(self, instance):
"""Get next run id"""
run = instance.first_unexpired_run
return run.id if run is not None else None

@extend_schema_field(
inline_serializer(
name="ProgramSerializer",
fields={
"id": serializers.IntegerField(),
"title": serializers.CharField(),
"readable_id": serializers.CharField(),
},
)
)
def get_programs(self, instance):
if self.context.get("all_runs", False):
from courses.serializers.v1.base import BaseProgramSerializer
Expand Down Expand Up @@ -82,6 +96,7 @@ def to_representation(self, instance):
}
return data

@extend_schema_field(bool)
def get_approved_flexible_price_exists(self, instance):
# Get the User object if it exists.
user = self.context["request"].user if "request" in self.context else None
Expand Down Expand Up @@ -110,18 +125,63 @@ class Meta:
"courseruns",
]


class CourseRunWithCourseSerializer(CourseRunSerializer):
"""
CourseRun model serializer - also serializes the parent Course.
"""

course = CourseSerializer(read_only=True, context={"include_page_fields": True})
courseware_url = serializers.SerializerMethodField()
is_upgradable = serializers.SerializerMethodField()
is_enrollable = serializers.SerializerMethodField()
is_archived = serializers.SerializerMethodField()
course_number = serializers.SerializerMethodField()
products = ProductRelatedField(
many=True,
read_only=True,
help_text="List of products associated with this course run"
)

@extend_schema_field(str)
def get_courseware_url(self, instance) -> Optional[str]:
"""Get the courseware URL"""
return instance.courseware_url

@extend_schema_field(bool)
def get_is_upgradable(self, instance) -> bool:
"""Check if the course run is upgradable"""
return instance.is_upgradable

@extend_schema_field(bool)
def get_is_enrollable(self, instance) -> bool:
"""Check if the course run is enrollable"""
return instance.is_enrollable

@extend_schema_field(bool)
def get_is_archived(self, instance) -> bool:
"""Check if the course run is archived"""
return instance.is_enrollable and instance.is_past

@extend_schema_field(str)
def get_course_number(self, instance) -> str:
"""Get the course number"""
return instance.course_number

@extend_schema_field(list[dict])
def get_products(self, instance) -> list[dict]:
"""Get products associated with this course run"""
return super().get_products(instance)

class Meta:
model = models.CourseRun
fields = CourseRunSerializer.Meta.fields + [ # noqa: RUF005
fields = CourseRunSerializer.Meta.fields + [
"course",
"courseware_url",
"is_upgradable",
"is_enrollable",
"is_archived",
"course_number",
"products"
]


Expand Down
5 changes: 4 additions & 1 deletion courses/serializers/v1/programs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from mitol.common.utils import now_in_utc
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from drf_spectacular.utils import extend_schema_serializer

from cms.serializers import ProgramPageSerializer
from courses import models
Expand All @@ -23,7 +24,9 @@
from openedx.constants import EDX_ENROLLMENT_VERIFIED_MODE
from users.models import User


@extend_schema_serializer(
component_name="V1ProgramSerializer" # Give it a unique name
)
class ProgramSerializer(serializers.ModelSerializer):
"""Program model serializer"""

Expand Down
18 changes: 2 additions & 16 deletions courses/serializers/v2/courses.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,28 +209,14 @@ def get_approved_flexible_price_exists(self, instance):
)
return flexible_price_exists # noqa: RET504


class CourseWithCourseRunsSerializer(CourseSerializer):
"""Course model serializer - also serializes child course runs"""

courseruns = serializers.SerializerMethodField(read_only=True)

def get_courseruns(self, instance):
context = {
"include_approved_financial_aid": self.context.get(
"include_approved_financial_aid", False
)
}

return CourseRunSerializer(
instance.courseruns.all(), many=True, read_only=True, context=context
).data
courseruns = CourseRunSerializer(many=True, read_only=True)

class Meta:
model = models.Course
fields = CourseSerializer.Meta.fields + [ # noqa: RUF005
"courseruns",
]
fields = CourseSerializer.Meta.fields + ["courseruns"]


class CourseRunWithCourseSerializer(CourseRunSerializer):
Expand Down
Loading