Skip to content

Commit

Permalink
Merge pull request #2598 from carpentries/feature/2527-context-json-f…
Browse files Browse the repository at this point in the history
…or-the-worker

[Emails] Context JSON for email worker
  • Loading branch information
pbanaszkiewicz authored Apr 8, 2024
2 parents 157e9fe + 0b9c5fe commit 0f512b8
Show file tree
Hide file tree
Showing 60 changed files with 2,692 additions and 875 deletions.
4 changes: 3 additions & 1 deletion Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ django-reversion-compare = "~=0.15"
django-redis = "~=5.0.0"
django-rq = "~=2.8.1"
django-select2 = "~=7.10.0"
djangorestframework = "~=3.12"
djangorestframework = "~=3.15"
djangorestframework-csv = "~=2.1.1"
drf-nested-routers = "~=0.93.4"
django-formset-js-improved = "~=0.5.0.2"
Expand All @@ -40,6 +40,8 @@ django-better-admin-arrayfield = "==1.4.2"
django-test-migrations = "~=1.3.0"
typing-extensions = "*"
django-flags = "~=5.0.13"
pydantic = "~=2.5.2"
django-rest-knox = "~=4.2.0"

[dev-packages]
django-webtest = "~=1.9.8"
Expand Down
1,259 changes: 646 additions & 613 deletions Pipfile.lock

Large diffs are not rendered by default.

File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion amy/api/renderers.py → amy/api/v1/renderers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from rest_framework_csv.renderers import CSVRenderer

from api.serializers import (
from api.v1.serializers import (
TrainingRequestForManualScoringSerializer,
TrainingRequestWithPersonSerializer,
)
Expand Down
22 changes: 11 additions & 11 deletions amy/api/serializers.py → amy/api/v1/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Meta:
class AwardSerializer(serializers.ModelSerializer):
badge = serializers.SlugRelatedField(many=False, read_only=True, slug_field="name")
event = serializers.HyperlinkedRelatedField(
read_only=True, view_name="api:event-detail", lookup_field="slug"
read_only=True, view_name="api-v1:event-detail", lookup_field="slug"
)

class Meta:
Expand All @@ -82,24 +82,24 @@ class Meta:

class PersonSerializer(serializers.ModelSerializer):
airport = serializers.HyperlinkedRelatedField(
read_only=True, view_name="api:airport-detail", lookup_field="iata"
read_only=True, view_name="api-v1:airport-detail", lookup_field="iata"
)
country = serializers.CharField()
lessons = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name")
domains = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name")
badges = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name")
awards = serializers.HyperlinkedIdentityField(
view_name="api:person-awards-list",
view_name="api-v1:person-awards-list",
lookup_field="pk",
lookup_url_kwarg="person_pk",
)
tasks = serializers.HyperlinkedIdentityField(
view_name="api:person-tasks-list",
view_name="api-v1:person-tasks-list",
lookup_field="pk",
lookup_url_kwarg="person_pk",
)
consents = serializers.HyperlinkedIdentityField(
view_name="api:person-consents-list",
view_name="api-v1:person-consents-list",
lookup_field="pk",
lookup_url_kwarg="person_pk",
)
Expand Down Expand Up @@ -135,10 +135,10 @@ class Meta:

class TaskSerializer(serializers.ModelSerializer):
event = serializers.HyperlinkedRelatedField(
read_only=True, view_name="api:event-detail", lookup_field="slug"
read_only=True, view_name="api-v1:event-detail", lookup_field="slug"
)
person = serializers.HyperlinkedRelatedField(
read_only=True, view_name="api:person-detail"
read_only=True, view_name="api-v1:person-detail"
)
role = serializers.SlugRelatedField(many=False, read_only=True, slug_field="name")

Expand All @@ -153,19 +153,19 @@ class EventSerializer(serializers.ModelSerializer):
end = serializers.DateField(format=None)

host = serializers.HyperlinkedRelatedField(
read_only=True, view_name="api:organization-detail", lookup_field="domain"
read_only=True, view_name="api-v1:organization-detail", lookup_field="domain"
)
administrator = serializers.HyperlinkedRelatedField(
read_only=True, view_name="api:organization-detail", lookup_field="domain"
read_only=True, view_name="api-v1:organization-detail", lookup_field="domain"
)
tags = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name")
tasks = serializers.HyperlinkedIdentityField(
view_name="api:event-tasks-list",
view_name="api-v1:event-tasks-list",
lookup_field="slug",
lookup_url_kwarg="event_slug",
)
assigned_to = serializers.HyperlinkedRelatedField(
read_only=True, view_name="api:person-detail"
read_only=True, view_name="api-v1:person-detail"
)
attendance = serializers.IntegerField()

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -67,27 +67,27 @@ def test_structure_for_list_views(self):
# → organizations
# → airports
# → reports
index = self.client.get(reverse("api:root"))
index = self.client.get(reverse("api-v1:root"))
index_links = {
"person-list": reverse("api:person-list"),
"term-list": reverse("api:term-list"),
"event-list": reverse("api:event-list"),
"organization-list": reverse("api:organization-list"),
"airport-list": reverse("api:airport-list"),
"person-list": reverse("api-v1:person-list"),
"term-list": reverse("api-v1:term-list"),
"event-list": reverse("api-v1:event-list"),
"organization-list": reverse("api-v1:organization-list"),
"airport-list": reverse("api-v1:airport-list"),
}
for endpoint, link in index_links.items():
self.assertIn(link, index.data[endpoint])

person = self.client.get(reverse("api:person-detail", args=[self.admin.pk]))
person = self.client.get(reverse("api-v1:person-detail", args=[self.admin.pk]))
person_links = {
"awards": reverse("api:person-awards-list", args=[self.admin.pk]),
"awards": reverse("api-v1:person-awards-list", args=[self.admin.pk]),
}
for endpoint, link in person_links.items():
self.assertIn(link, person.data[endpoint])

event = self.client.get(reverse("api:event-detail", args=[self.event.slug]))
event = self.client.get(reverse("api-v1:event-detail", args=[self.event.slug]))
event_links = {
"tasks": reverse("api:event-tasks-list", args=[self.event.slug]),
"tasks": reverse("api-v1:event-tasks-list", args=[self.event.slug]),
}
for endpoint, link in event_links.items():
self.assertIn(link, event.data[endpoint])
Expand All @@ -110,44 +110,46 @@ def test_links_between_resources(self):
# airport (no links)
# award
# → event-detail
event = self.client.get(reverse("api:event-detail", args=[self.event.slug]))
event = self.client.get(reverse("api-v1:event-detail", args=[self.event.slug]))
event_links = {
"host": reverse("api:organization-detail", args=[self.event.host.domain]),
"host": reverse(
"api-v1:organization-detail", args=[self.event.host.domain]
),
"administrator": reverse(
"api:organization-detail", args=[self.event.administrator.domain]
"api-v1:organization-detail", args=[self.event.administrator.domain]
),
"tasks": reverse("api:event-tasks-list", args=[self.event.slug]),
"tasks": reverse("api-v1:event-tasks-list", args=[self.event.slug]),
"assigned_to": reverse(
"api:person-detail", args=[self.event.assigned_to.pk]
"api-v1:person-detail", args=[self.event.assigned_to.pk]
),
}
for attr, link in event_links.items():
self.assertIn(link, event.data[attr])

task = self.client.get(
reverse("api:event-tasks-detail", args=[self.event.slug, self.task.pk])
reverse("api-v1:event-tasks-detail", args=[self.event.slug, self.task.pk])
)
task_links = {
"person": reverse("api:person-detail", args=[self.admin.pk]),
"person": reverse("api-v1:person-detail", args=[self.admin.pk]),
}
for attr, link in task_links.items():
self.assertIn(link, task.data[attr])

person = self.client.get(reverse("api:person-detail", args=[self.admin.pk]))
person = self.client.get(reverse("api-v1:person-detail", args=[self.admin.pk]))
person_links = {
"airport": reverse("api:airport-detail", args=[self.admin.airport.iata]),
"awards": reverse("api:person-awards-list", args=[self.admin.pk]),
"tasks": reverse("api:person-tasks-list", args=[self.admin.pk]),
"consents": reverse("api:person-consents-list", args=[self.admin.pk]),
"airport": reverse("api-v1:airport-detail", args=[self.admin.airport.iata]),
"awards": reverse("api-v1:person-awards-list", args=[self.admin.pk]),
"tasks": reverse("api-v1:person-tasks-list", args=[self.admin.pk]),
"consents": reverse("api-v1:person-consents-list", args=[self.admin.pk]),
}
for attr, link in person_links.items():
self.assertIn(link, person.data[attr])

award = self.client.get(
reverse("api:person-awards-detail", args=[self.admin.pk, self.award.pk])
reverse("api-v1:person-awards-detail", args=[self.admin.pk, self.award.pk])
)
award_links = {
"event": reverse("api:event-detail", args=[self.award.event.slug]),
"event": reverse("api-v1:event-detail", args=[self.award.event.slug]),
}
for attr, link in award_links.items():
self.assertIn(link, award.data[attr])
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def setUp(self):
consent_to_all_required_consents(self.user)

# save API endpoint URL
self.url = reverse("api:export-person-data")
self.url = reverse("api-v1:export-person-data")

def login(self):
"""Overwrite BaseExportingTest's login method: instead of loggin in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def assert_data(data: Dict[str, Any], expected_people) -> None:
usernames, [person.username for person in expected_people]
)

person_api_url = reverse("api:person-list")
person_api_url = reverse("api-v1:person-list")

# no filter
people_response = self.client.get(person_api_url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from django.test import RequestFactory, TestCase
from django.views import View

from api.permissions import DjangoModelPermissionsWithView
from api.v1.permissions import DjangoModelPermissionsWithView
from recruitment.models import InstructorRecruitment
from workshops.models import Person

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from rest_framework import status
from rest_framework.test import APITestCase

from api.views import TrainingRequests
from api.v1.views import TrainingRequests
from workshops.models import (
Badge,
Event,
Expand All @@ -23,7 +23,7 @@

class TestListingTrainingRequests(APITestCase):
view = TrainingRequests
url = "api:training-requests"
url = "api-v1:training-requests"
maxDiff = None

def setUp(self):
Expand Down
4 changes: 2 additions & 2 deletions amy/api/urls.py → amy/api/v1/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from rest_framework.urlpatterns import format_suffix_patterns
from rest_framework_nested import routers

from api import views
from api.v1 import views

app_name = "api"
app_name = "api-v1"

# routers generate URLs for methods like `.list` or `.retrieve`
router = routers.SimpleRouter(trailing_slash=False)
Expand Down
33 changes: 19 additions & 14 deletions amy/api/views.py → amy/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@
from rest_framework.settings import api_settings
from rest_framework.views import APIView

from api.filters import EventFilter, PersonFilter, TaskFilter, TrainingRequestFilterIDs
from api.permissions import DjangoModelPermissionsWithView
from api.renderers import (
from api.v1.filters import (
EventFilter,
PersonFilter,
TaskFilter,
TrainingRequestFilterIDs,
)
from api.v1.permissions import DjangoModelPermissionsWithView
from api.v1.renderers import (
TrainingRequestCSVRenderer,
TrainingRequestManualScoreCSVRenderer,
)
from api.serializers import (
from api.v1.serializers import (
AirportSerializer,
AwardSerializer,
CommunityRoleConfigSerializer,
Expand Down Expand Up @@ -99,56 +104,56 @@ def get(self, request, format=None):
(
"export-person-data",
reverse(
"api:export-person-data", request=request, format=format
"api-v1:export-person-data", request=request, format=format
),
),
(
"training-requests",
reverse(
"api:training-requests", request=request, format=format
"api-v1:training-requests", request=request, format=format
),
),
# "new" API list-type endpoints below
(
"airport-list",
reverse("api:airport-list", request=request, format=format),
reverse("api-v1:airport-list", request=request, format=format),
),
(
"person-list",
reverse("api:person-list", request=request, format=format),
reverse("api-v1:person-list", request=request, format=format),
),
(
"event-list",
reverse("api:event-list", request=request, format=format),
reverse("api-v1:event-list", request=request, format=format),
),
(
"organization-list",
reverse(
"api:organization-list", request=request, format=format
"api-v1:organization-list", request=request, format=format
),
),
(
"emailtemplate-list",
reverse(
"api:emailtemplate-list", request=request, format=format
"api-v1:emailtemplate-list", request=request, format=format
),
),
(
"term-list",
reverse("api:term-list", request=request, format=format),
reverse("api-v1:term-list", request=request, format=format),
),
(
"communityroleconfig-list",
reverse(
"api:communityroleconfig-list",
"api-v1:communityroleconfig-list",
request=request,
format=format,
),
),
(
"instructorrecruitment-list",
reverse(
"api:instructorrecruitment-list",
"api-v1:instructorrecruitment-list",
request=request,
format=format,
),
Expand Down
Empty file added amy/api/v2/__init__.py
Empty file.
8 changes: 8 additions & 0 deletions amy/api/v2/permissions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from rest_framework.permissions import BasePermission


class ApiAccessPermission(BasePermission):
_permission_name = "knox.add_authtoken"

def has_permission(self, request, view):
return request.user.has_perm(self._permission_name)
Loading

0 comments on commit 0f512b8

Please sign in to comment.