Skip to content

Commit f1dccca

Browse files
authored
Rework program filtering when an org_id is specified (#2696)
1 parent d49f38c commit f1dccca

File tree

4 files changed

+41
-9
lines changed

4 files changed

+41
-9
lines changed

courses/views/v2/__init__.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from drf_spectacular.utils import extend_schema
99
from rest_framework import viewsets
1010
from rest_framework.pagination import PageNumberPagination
11+
from rest_framework.permissions import IsAuthenticatedOrReadOnly
1112

1213
from courses.models import (
1314
Course,
@@ -53,12 +54,33 @@ class Meta:
5354
model = Program
5455
fields = ["id", "live", "readable_id", "page__live", "org_id"]
5556

56-
def __init__(self, *args, request_user=None, **kwargs):
57-
self.user = request_user
57+
def __init__(self, *args, **kwargs):
5858
super().__init__(*args, **kwargs)
5959

60+
@property
61+
def qs(self):
62+
"""If the request isn't explicitly filtering on org_id, exclude contracted courses."""
63+
64+
if "org_id" not in getattr(self.request, "GET", {}):
65+
program_requirements_with_contract_runs = ProgramRequirement.objects.filter(
66+
node_type=ProgramRequirementNodeType.COURSE,
67+
course__courseruns__b2b_contract__isnull=False,
68+
program_id=OuterRef("pk"),
69+
)
70+
return (
71+
super()
72+
.qs.annotate(
73+
has_contracted_courses=Exists(
74+
program_requirements_with_contract_runs
75+
)
76+
)
77+
.filter(has_contracted_courses=False)
78+
)
79+
80+
return super().qs
81+
6082
def filter_by_org_id(self, queryset, _, org_id):
61-
if user_has_org_access(self.user, org_id):
83+
if self.request and user_has_org_access(self.request.user, org_id):
6284
program_requirements_with_contract_runs = ProgramRequirement.objects.filter(
6385
node_type=ProgramRequirementNodeType.COURSE,
6486
course__courseruns__b2b_contract__organization_id=org_id,
@@ -82,29 +104,27 @@ def filter_by_org_id(self, queryset, _, org_id):
82104
class ProgramViewSet(viewsets.ReadOnlyModelViewSet):
83105
"""API viewset for Programs"""
84106

85-
permission_classes = []
107+
permission_classes = [IsAuthenticatedOrReadOnly]
86108
serializer_class = ProgramSerializer
87109
pagination_class = Pagination
88110
filter_backends = [DjangoFilterBackend]
89111
filterset_class = ProgramFilterSet
90112

91113
def get_queryset(self):
114+
"""Get the queryset"""
92115
return Program.objects.order_by("title").prefetch_related("departments")
93116

94-
def get_filterset_kwargs(self):
95-
kwargs = super().get_filterset_kwargs()
96-
kwargs["request_user"] = self.request.user
97-
return kwargs
98-
99117
@extend_schema(
100118
operation_id="programs_retrieve_v2",
101119
description="API view set for Programs - v2",
102120
)
103121
def retrieve(self, request, *args, **kwargs):
122+
"""Retrieve a specific program."""
104123
return super().retrieve(request, *args, **kwargs)
105124

106125
@extend_schema(operation_id="programs_list_v2", description="List Programs - v2")
107126
def list(self, request, *args, **kwargs):
127+
"""List the available programs."""
108128
return super().list(request, *args, **kwargs)
109129

110130

openapi/specs/v0.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,8 @@ paths:
970970
type: string
971971
tags:
972972
- programs
973+
security:
974+
- {}
973975
responses:
974976
'200':
975977
content:
@@ -990,6 +992,8 @@ paths:
990992
required: true
991993
tags:
992994
- programs
995+
security:
996+
- {}
993997
responses:
994998
'200':
995999
content:

openapi/specs/v1.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,8 @@ paths:
970970
type: string
971971
tags:
972972
- programs
973+
security:
974+
- {}
973975
responses:
974976
'200':
975977
content:
@@ -990,6 +992,8 @@ paths:
990992
required: true
991993
tags:
992994
- programs
995+
security:
996+
- {}
993997
responses:
994998
'200':
995999
content:

openapi/specs/v2.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,8 @@ paths:
970970
type: string
971971
tags:
972972
- programs
973+
security:
974+
- {}
973975
responses:
974976
'200':
975977
content:
@@ -990,6 +992,8 @@ paths:
990992
required: true
991993
tags:
992994
- programs
995+
security:
996+
- {}
993997
responses:
994998
'200':
995999
content:

0 commit comments

Comments
 (0)