diff --git a/app.json b/app.json
index 3b7526f66..7be017ad5 100644
--- a/app.json
+++ b/app.json
@@ -409,10 +409,6 @@
"description": "The SL tracking ID",
"required": false
},
- "STATUS_TOKEN": {
- "description": "Token to access the status API.",
- "required": true
- },
"USE_X_FORWARDED_HOST": {
"description": "Set HOST header to original domain accessed by user",
"required": false
diff --git a/applications/__init__.py b/applications/__init__.py
index 891b6e15d..cd1e1174f 100644
--- a/applications/__init__.py
+++ b/applications/__init__.py
@@ -1,3 +1 @@
"""Initialize applications app"""
-
-default_app_config = "applications.apps.ApplicationConfig"
diff --git a/applications/admin.py b/applications/admin.py
index d86a62916..5e24c7612 100644
--- a/applications/admin.py
+++ b/applications/admin.py
@@ -10,30 +10,42 @@
from django.utils.safestring import mark_safe
from mitol.common.admin import TimestampedModelAdmin
-from applications import models
+from applications.models import (
+ ApplicationStep,
+ ApplicationStepSubmission,
+ BootcampRunApplicationStep,
+ BootcampApplication,
+ VideoInterviewSubmission,
+ QuizSubmission,
+ ApplicantLetter,
+ Interview,
+)
from ecommerce.models import Order
from main.utils import get_field_names
+@admin.register(ApplicationStep)
class ApplicationStepAdmin(admin.ModelAdmin):
"""Admin for ApplicationStep"""
- model = models.ApplicationStep
+ model = ApplicationStep
list_display = ("id", "get_bootcamp_title", "submission_type", "step_order")
ordering = ("bootcamp", "step_order")
+ @admin.display(
+ description="Bootcamp",
+ ordering="bootcamp__title",
+ )
def get_bootcamp_title(self, obj):
"""Returns the bootcamp title"""
return obj.bootcamp.title
- get_bootcamp_title.short_description = "Bootcamp"
- get_bootcamp_title.admin_order_field = "bootcamp__title"
-
+@admin.register(BootcampRunApplicationStep)
class BootcampRunApplicationStepAdmin(admin.ModelAdmin):
"""Admin for BootcampRunApplicationStep"""
- model = models.BootcampRunApplicationStep
+ model = BootcampRunApplicationStep
list_display = (
"id",
"get_run_display_title",
@@ -53,27 +65,30 @@ def get_queryset(self, request):
"""Overrides base queryset"""
return super().get_queryset(request).select_related("bootcamp_run__bootcamp")
+ @admin.display(
+ description="Bootcamp Run",
+ ordering="bootcamp_run__title",
+ )
def get_run_display_title(self, obj):
"""Returns the bootcamp run display title"""
return obj.bootcamp_run.display_title
- get_run_display_title.short_description = "Bootcamp Run"
- get_run_display_title.admin_order_field = "bootcamp_run__title"
-
+ @admin.display(
+ description="Submission Type",
+ ordering="application_step__submission_type",
+ )
def get_submission_type(self, obj):
"""Returns the application step submission type"""
return obj.application_step.submission_type
- get_submission_type.short_description = "Submission Type"
- get_submission_type.admin_order_field = "application_step__submission_type"
-
+ @admin.display(
+ description="Step Order",
+ ordering="application_step__step_order",
+ )
def get_step_order(self, obj):
"""Returns the application step order"""
return obj.application_step.step_order
- get_step_order.short_description = "Step Order"
- get_step_order.admin_order_field = "application_step__step_order"
-
class OrderInline(admin.StackedInline):
"""Inline form for Order"""
@@ -90,10 +105,11 @@ def has_add_permission(self, request, obj=None):
return False
+@admin.register(BootcampApplication)
class BootcampApplicationAdmin(TimestampedModelAdmin):
"""Admin for BootcampApplication"""
- model = models.BootcampApplication
+ model = BootcampApplication
include_timestamps_in_list = True
inlines = [OrderInline]
list_display = ("id", "get_user_email", "get_run_display_title", "state")
@@ -114,25 +130,27 @@ def get_queryset(self, request):
.select_related("user", "bootcamp_run__bootcamp")
)
+ @admin.display(
+ description="User",
+ ordering="user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
return obj.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "user__email"
-
+ @admin.display(
+ description="Bootcamp Run",
+ ordering="bootcamp_run__title",
+ )
def get_run_display_title(self, obj):
"""Returns the bootcamp run display title"""
return obj.bootcamp_run.display_title
- get_run_display_title.short_description = "Bootcamp Run"
- get_run_display_title.admin_order_field = "bootcamp_run__title"
-
class AppStepSubmissionInline(GenericTabularInline):
"""Admin class for ApplicationStepSubmission"""
- model = models.ApplicationStepSubmission
+ model = ApplicationStepSubmission
max_num = 1
raw_id_fields = ("bootcamp_application", "run_application_step")
@@ -170,6 +188,10 @@ def get_queryset(self, request):
)
)
+ @admin.display(
+ description="Application User",
+ ordering="app_step_submission__bootcamp_application__user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
app_step_submissions = obj.app_step_submissions.all()
@@ -179,11 +201,10 @@ def get_user_email(self, obj):
else app_step_submissions[0].bootcamp_application.user.email
)
- get_user_email.short_description = "Application User"
- get_user_email.admin_order_field = (
- "app_step_submission__bootcamp_application__user__email"
+ @admin.display(
+ description="App Bootcamp Run",
+ ordering="app_step_submission__bootcamp_application__bootcamp_run__title",
)
-
def get_run_display_title(self, obj):
"""Returns the bootcamp run display title"""
app_step_submissions = obj.app_step_submissions.all()
@@ -193,11 +214,7 @@ def get_run_display_title(self, obj):
else app_step_submissions[0].bootcamp_application.bootcamp_run.display_title
)
- get_run_display_title.short_description = "App Bootcamp Run"
- get_run_display_title.admin_order_field = (
- "app_step_submission__bootcamp_application__bootcamp_run__title"
- )
-
+ @admin.display(description="Submission")
def app_step_submission_link(self, obj):
"""Returns a link to the related bootcamp application"""
app_step_submissions = obj.app_step_submissions.all()
@@ -208,7 +225,7 @@ def app_step_submission_link(self, obj):
'Submission ({})'.format(
reverse(
"admin:applications_{}_change".format(
- models.ApplicationStepSubmission._meta.model_name
+ ApplicationStepSubmission._meta.model_name
),
args=(app_step_submission.id,),
), # pylint: disable=protected-access
@@ -216,19 +233,19 @@ def app_step_submission_link(self, obj):
)
)
- app_step_submission_link.short_description = "Submission"
-
+@admin.register(VideoInterviewSubmission)
class VideoInterviewSubmissionAdmin(SubmissionTypeAdmin):
"""Admin class for VideoInterviewSubmission"""
- model = models.VideoInterviewSubmission
+ model = VideoInterviewSubmission
raw_id_fields = ("interview",)
def get_list_display(self, request):
return tuple(super().get_list_display(request) or ()) + ("interview_link",)
+ @admin.display(description="Interview")
def interview_link(self, obj):
"""Returns a link to the related interview record"""
if not hasattr(obj, "interview") or obj.interview is None:
@@ -236,20 +253,19 @@ def interview_link(self, obj):
return mark_safe(
'Interview ({})'.format(
reverse(
- "admin:jobma_{}_change".format(models.Interview._meta.model_name),
+ "admin:jobma_{}_change".format(Interview._meta.model_name),
args=(obj.interview.id,),
), # pylint: disable=protected-access
obj.interview.id,
)
)
- interview_link.short_description = "Interview"
-
+@admin.register(QuizSubmission)
class QuizSubmissionAdmin(SubmissionTypeAdmin):
"""Admin for QuizSubmission"""
- model = models.QuizSubmission
+ model = QuizSubmission
def get_list_display(self, request):
return tuple(super().get_list_display(request) or ()) + ("started_date",)
@@ -272,10 +288,11 @@ def clean_object_id(self):
return object_id
+@admin.register(ApplicationStepSubmission)
class ApplicationStepSubmissionAdmin(TimestampedModelAdmin):
"""Admin for ApplicationStepSubmission"""
- model = models.ApplicationStepSubmission
+ model = ApplicationStepSubmission
form = ApplicationStepSubmissionForm
list_display = (
"id",
@@ -313,6 +330,7 @@ def get_readonly_fields(self, request, obj=None):
return tuple(self.readonly_fields or ()) + ("content_type", "object_id")
return self.readonly_fields
+ @admin.display(description="submission object")
def submission_content_obj_link(self, obj):
"""Returns a link to the content object"""
if obj.content_object is None:
@@ -329,27 +347,28 @@ def submission_content_obj_link(self, obj):
)
)
- submission_content_obj_link.short_description = "submission object"
-
+ @admin.display(
+ description="User",
+ ordering="user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
return obj.bootcamp_application.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "user__email"
-
+ @admin.display(
+ description="Bootcamp Run",
+ ordering="bootcamp_run__title",
+ )
def get_run_display_title(self, obj):
"""Returns the bootcamp run display title"""
return obj.bootcamp_application.bootcamp_run.display_title
- get_run_display_title.short_description = "Bootcamp Run"
- get_run_display_title.admin_order_field = "bootcamp_run__title"
-
+@admin.register(ApplicantLetter)
class ApplicantLetterAdmin(TimestampedModelAdmin):
"""Admin for ApplicantLetter"""
- model = models.ApplicantLetter
+ model = ApplicantLetter
list_display = ("id", "letter_type", "get_user_email", "get_run_display_title")
list_filter = ("letter_type",)
raw_id_fields = ("application",)
@@ -358,27 +377,20 @@ class ApplicantLetterAdmin(TimestampedModelAdmin):
"application__bootcamp_run__title",
"application__bootcamp_run__bootcamp__title",
)
- readonly_fields = get_field_names(models.ApplicantLetter)
+ readonly_fields = get_field_names(ApplicantLetter)
+ @admin.display(
+ description="User",
+ ordering="user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
return obj.application.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "user__email"
-
+ @admin.display(
+ description="Bootcamp Run",
+ ordering="bootcamp_run__title",
+ )
def get_run_display_title(self, obj):
"""Returns the bootcamp run display title"""
return obj.application.bootcamp_run.display_title
-
- get_run_display_title.short_description = "Bootcamp Run"
- get_run_display_title.admin_order_field = "bootcamp_run__title"
-
-
-admin.site.register(models.ApplicationStep, ApplicationStepAdmin)
-admin.site.register(models.BootcampRunApplicationStep, BootcampRunApplicationStepAdmin)
-admin.site.register(models.BootcampApplication, BootcampApplicationAdmin)
-admin.site.register(models.VideoInterviewSubmission, VideoInterviewSubmissionAdmin)
-admin.site.register(models.QuizSubmission, QuizSubmissionAdmin)
-admin.site.register(models.ApplicationStepSubmission, ApplicationStepSubmissionAdmin)
-admin.site.register(models.ApplicantLetter, ApplicantLetterAdmin)
diff --git a/applications/urls.py b/applications/urls.py
index b8b658475..b0475246b 100644
--- a/applications/urls.py
+++ b/applications/urls.py
@@ -3,7 +3,7 @@
"""
from django.urls import path
-from django.conf.urls import url, include
+from django.urls import include
from rest_framework import routers
from applications.views import (
@@ -20,9 +20,9 @@
router.register(r"submissions", ReviewSubmissionViewSet, basename="submissions_api")
urlpatterns = [
- url(r"^api/", include(router.urls)),
- url(
- r"^api/applications/(?P\d+)/resume/$",
+ path("api/", include(router.urls)),
+ path(
+ "api/applications//resume/",
UploadResumeView.as_view(),
name="upload-resume",
),
diff --git a/authentication/middleware.py b/authentication/middleware.py
index 9993d4e94..66cf5a453 100644
--- a/authentication/middleware.py
+++ b/authentication/middleware.py
@@ -1,7 +1,7 @@
"""Authentication middleware"""
+from urllib.parse import quote
from django.shortcuts import redirect
-from django.utils.http import urlquote
from social_core.exceptions import SocialAuthBaseException
from social_django.middleware import SocialAuthExceptionMiddleware
@@ -31,6 +31,6 @@ def process_exception(self, request, exception):
if url:
url += ("?" in url and "&" or "?") + "message={0}&backend={1}".format(
- urlquote(message), backend_name
+ quote(message), backend_name
)
return redirect(url)
diff --git a/authentication/middleware_test.py b/authentication/middleware_test.py
index 61baef1a3..f5ec0e8ff 100644
--- a/authentication/middleware_test.py
+++ b/authentication/middleware_test.py
@@ -2,7 +2,7 @@
from django.contrib.sessions.middleware import SessionMiddleware
from django.shortcuts import reverse
-from django.utils.http import urlquote
+from urllib.parse import quote
from rest_framework import status
from social_core.exceptions import AuthAlreadyAssociated
from social_django.utils import load_backend, load_strategy
@@ -23,7 +23,7 @@ def test_process_exception(mocker, rf, settings):
settings.DEBUG = False
request = rf.get(reverse("social:complete", args=("email",)))
# social_django depends on request.sesssion, so use the middleware to set that
- SessionMiddleware().process_request(request)
+ SessionMiddleware(get_response=mocker.Mock()).process_request(request)
strategy = load_strategy(request)
backend = load_backend(strategy, "email", None)
request.social_strategy = strategy
@@ -34,7 +34,7 @@ def test_process_exception(mocker, rf, settings):
result = middleware.process_exception(request, error)
assert result.status_code == status.HTTP_302_FOUND
assert result.url == "{}?message={}&backend={}".format(
- reverse("login"), urlquote(error.__str__()), backend.name
+ reverse("login"), quote(error.__str__()), backend.name
)
@@ -43,7 +43,7 @@ def test_process_exception_non_auth_error(mocker, rf, settings):
settings.DEBUG = False
request = rf.get(reverse("social:complete", args=("email",)))
# social_django depends on request.sesssion, so use the middleware to set that
- SessionMiddleware().process_request(request)
+ SessionMiddleware(get_response=mocker.Mock()).process_request(request)
strategy = load_strategy(request)
backend = load_backend(strategy, "email", None)
request.social_strategy = strategy
diff --git a/authentication/pipeline/user_test.py b/authentication/pipeline/user_test.py
index cb277e25a..8e6669d77 100644
--- a/authentication/pipeline/user_test.py
+++ b/authentication/pipeline/user_test.py
@@ -46,10 +46,10 @@ def validate_email_auth_request_not_email_backend(mocker):
"has_user,expected", [(True, {"flow": SocialAuthState.FLOW_LOGIN}), (False, {})]
)
@pytest.mark.django_db
-def test_validate_email_auth_request(rf, has_user, expected):
+def test_validate_email_auth_request(rf, has_user, expected, mocker):
"""Test that validate_email_auth_request returns correctly given the input"""
request = rf.post("/complete/email")
- middleware = SessionMiddleware()
+ middleware = SessionMiddleware(get_response=mocker.Mock())
middleware.process_request(request)
request.session.save()
strategy = load_strategy(request)
@@ -105,7 +105,7 @@ def test_user_password_not_email_backend(mocker):
@pytest.mark.parametrize("user_password", ["abc123", "def456"])
-def test_user_password_login(rf, user, user_password):
+def test_user_password_login(rf, user, user_password, mocker):
"""Tests that user_password works for login case"""
request_password = "abc123"
user.set_password(user_password)
@@ -113,7 +113,7 @@ def test_user_password_login(rf, user, user_password):
request = rf.post(
"/complete/email", {"password": request_password, "email": user.email}
)
- middleware = SessionMiddleware()
+ middleware = SessionMiddleware(get_response=mocker.Mock())
middleware.process_request(request)
request.session.save()
strategy = load_strategy(request)
@@ -141,7 +141,7 @@ def test_user_password_login(rf, user, user_password):
)
-def test_user_password_not_login(rf, user):
+def test_user_password_not_login(rf, user, mocker):
"""
Tests that user_password performs denies authentication
for an existing user if password not provided regardless of auth_type
@@ -149,7 +149,7 @@ def test_user_password_not_login(rf, user):
user.set_password("abc123")
user.save()
request = rf.post("/complete/email", {"email": user.email})
- middleware = SessionMiddleware()
+ middleware = SessionMiddleware(get_response=mocker.Mock())
middleware.process_request(request)
request.session.save()
strategy = load_strategy(request)
@@ -165,12 +165,12 @@ def test_user_password_not_login(rf, user):
)
-def test_user_password_not_exists(rf):
+def test_user_password_not_exists(rf, mocker):
"""Tests that user_password raises auth error for nonexistent user"""
request = rf.post(
"/complete/email", {"password": "abc123", "email": "doesntexist@localhost"}
)
- middleware = SessionMiddleware()
+ middleware = SessionMiddleware(get_response=mocker.Mock())
middleware.process_request(request)
request.session.save()
strategy = load_strategy(request)
diff --git a/authentication/views.py b/authentication/views.py
index d798c00a6..43ccc7092 100644
--- a/authentication/views.py
+++ b/authentication/views.py
@@ -41,7 +41,7 @@ def get_serializer_cls(self): # pragma: no cover
def post(self, request, backend_name=EmailAuth.name):
"""Processes a request"""
- if request.session.get("is_hijacked_user", False):
+ if bool(request.session.get("hijack_history")):
return Response(status=status.HTTP_403_FORBIDDEN)
serializer_cls = self.get_serializer_cls()
@@ -83,7 +83,7 @@ def get_serializer_cls(self):
def post(self, request, backend_name=EmailAuth.name):
"""Verify recaptcha response before proceeding"""
- if request.session.get("is_hijacked_user", False):
+ if bool(request.session.get("hijack_history")):
return Response(status=status.HTTP_403_FORBIDDEN)
if settings.RECAPTCHA_SITE_KEY:
r = requests.post(
diff --git a/authentication/views_test.py b/authentication/views_test.py
index 55c029381..10cb1d52a 100644
--- a/authentication/views_test.py
+++ b/authentication/views_test.py
@@ -829,7 +829,7 @@ def test_login_email_error(client, mocker):
def test_login_email_hijacked(client, user, admin_user):
"""Test that a 403 response is returned for email login view if user is hijacked"""
client.force_login(admin_user)
- client.post("/hijack/{}/".format(user.id))
+ client.post("/hijack/acquire/", {"user_pk": user.id})
response = client.post(
reverse("psa-login-email"),
{"flow": SocialAuthState.FLOW_LOGIN, "email": "anything@example.com"},
@@ -840,7 +840,7 @@ def test_login_email_hijacked(client, user, admin_user):
def test_register_email_hijacked(client, user, admin_user):
"""Test that a 403 response is returned for email register view if user is hijacked"""
client.force_login(admin_user)
- client.post("/hijack/{}/".format(user.id))
+ client.post("/hijack/acquire/", {"user_pk": user.id})
response = client.post(
reverse("psa-register-email"),
{"flow": SocialAuthState.FLOW_LOGIN, "email": "anything@example.com"},
diff --git a/cms/__init__.py b/cms/__init__.py
index df7b240ba..850a660df 100644
--- a/cms/__init__.py
+++ b/cms/__init__.py
@@ -1,3 +1 @@
"""Initialize cms app"""
-
-default_app_config = "cms.apps.CMSConfig"
diff --git a/compliance/admin.py b/compliance/admin.py
index 22a486413..2acb11daf 100644
--- a/compliance/admin.py
+++ b/compliance/admin.py
@@ -13,6 +13,7 @@
from .models import ExportsInquiryLog
+@admin.register(ExportsInquiryLog)
class ExportsInquiryLogAdmin(admin.ModelAdmin):
"""Admin for ExportsInquiryLog"""
@@ -33,6 +34,7 @@ def country(self, instance):
"""generate country name from pycountry"""
return pycountry.countries.get(alpha_2=instance.user.legal_address.country).name
+ @admin.action(description="Manually approve selected records")
def manually_approve_inquiry(self, request, queryset):
"""Admin action to manually approve export compliance inquiry records"""
eligible_objects = queryset.exclude(
@@ -42,8 +44,6 @@ def manually_approve_inquiry(self, request, queryset):
ensure_active_user(obj.user)
eligible_objects.update(computed_result=RESULT_MANUALLY_APPROVED)
- manually_approve_inquiry.short_description = "Manually approve selected records"
-
def has_add_permission(self, request):
# We want to allow this while debugging
return settings.DEBUG
@@ -51,6 +51,3 @@ def has_add_permission(self, request):
def has_delete_permission(self, request, obj=None):
# We want to allow this while debugging
return settings.DEBUG
-
-
-admin.site.register(ExportsInquiryLog, ExportsInquiryLogAdmin)
diff --git a/ecommerce/admin.py b/ecommerce/admin.py
index ddbfbe649..9f787925b 100644
--- a/ecommerce/admin.py
+++ b/ecommerce/admin.py
@@ -12,6 +12,7 @@
from applications import models as application_models
+@admin.register(Line)
class LineAdmin(TimestampedModelAdmin):
"""Admin for Line"""
@@ -41,6 +42,7 @@ def has_add_permission(self, request, obj=None):
return False
+@admin.register(Order)
class OrderAdmin(TimestampedModelAdmin):
"""Admin for Order"""
@@ -78,13 +80,15 @@ def get_queryset(self, request):
"""Overrides base queryset"""
return super().get_queryset(request).select_related("user")
+ @admin.display(
+ description="User",
+ ordering="user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
return obj.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "user__email"
-
+ @admin.display(description="Application")
def application_link(self, obj):
"""Returns a link to the related application"""
if not hasattr(obj, "application") or obj.application is None:
@@ -101,9 +105,8 @@ def application_link(self, obj):
)
)
- application_link.short_description = "Application"
-
+@admin.register(OrderAudit)
class OrderAuditAdmin(admin.ModelAdmin):
"""Admin for OrderAudit"""
@@ -117,6 +120,7 @@ def has_delete_permission(self, request, obj=None):
return False
+@admin.register(Receipt)
class ReceiptAdmin(TimestampedModelAdmin):
"""Admin for Receipt"""
@@ -136,24 +140,27 @@ def get_queryset(self, request):
"""Overrides base queryset"""
return super().get_queryset(request).select_related("order__user")
+ @admin.display(
+ description="User",
+ ordering="order__user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
if obj.order is None:
return None
return obj.order.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "order__user__email"
-
+ @admin.display(
+ description="Status",
+ ordering="order__status",
+ )
def get_order_status(self, obj):
"""Returns the order status"""
if obj.order is None:
return None
return obj.order.status
- get_order_status.short_description = "Status"
- get_order_status.admin_order_field = "order__status"
-
+ @admin.display(description="Order")
def order_link(self, obj):
"""Returns a link to the related order"""
if obj.order is None:
@@ -168,9 +175,8 @@ def order_link(self, obj):
)
)
- order_link.short_description = "Order"
-
+@admin.register(WireTransferReceipt)
class WireTransferReceiptAdmin(TimestampedModelAdmin):
"""Admin for WireTransferReceipt"""
@@ -193,24 +199,27 @@ def get_queryset(self, request):
"""Overrides base queryset"""
return super().get_queryset(request).select_related("order__user")
+ @admin.display(
+ description="User",
+ ordering="order__user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
if obj.order is None:
return None
return obj.order.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "order__user__email"
-
+ @admin.display(
+ description="Status",
+ ordering="order__status",
+ )
def get_order_status(self, obj):
"""Returns the order status"""
if obj.order is None:
return None
return obj.order.status
- get_order_status.short_description = "Status"
- get_order_status.admin_order_field = "order__status"
-
+ @admin.display(description="Order")
def order_link(self, obj):
"""Returns a link to the related order"""
if obj.order is None:
@@ -224,12 +233,3 @@ def order_link(self, obj):
obj.order.id,
)
)
-
- order_link.short_description = "Order"
-
-
-admin.site.register(Line, LineAdmin)
-admin.site.register(Order, OrderAdmin)
-admin.site.register(OrderAudit, OrderAuditAdmin)
-admin.site.register(Receipt, ReceiptAdmin)
-admin.site.register(WireTransferReceipt, WireTransferReceiptAdmin)
diff --git a/ecommerce/migrations/0001_initial.py b/ecommerce/migrations/0001_initial.py
index 4e773f084..a1283b12b 100644
--- a/ecommerce/migrations/0001_initial.py
+++ b/ecommerce/migrations/0001_initial.py
@@ -3,7 +3,6 @@
from __future__ import unicode_literals
from django.conf import settings
-import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
@@ -91,15 +90,11 @@ class Migration(migrations.Migration):
("updated_on", models.DateTimeField(auto_now=True)),
(
"data_before",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"data_after",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"acting_user",
@@ -134,7 +129,7 @@ class Migration(migrations.Migration):
),
("created_on", models.DateTimeField(auto_now_add=True)),
("updated_on", models.DateTimeField(auto_now=True)),
- ("data", django.contrib.postgres.fields.jsonb.JSONField()),
+ ("data", models.JSONField()),
(
"order",
models.ForeignKey(
diff --git a/ecommerce/migrations/0010_wire_transfers.py b/ecommerce/migrations/0010_wire_transfers.py
index 07a7b977d..69e00556e 100644
--- a/ecommerce/migrations/0010_wire_transfers.py
+++ b/ecommerce/migrations/0010_wire_transfers.py
@@ -1,6 +1,5 @@
# Generated by Django 2.2.13 on 2020-07-15 19:33
-import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
@@ -37,7 +36,7 @@ class Migration(migrations.Migration):
("created_on", models.DateTimeField(auto_now_add=True)),
("updated_on", models.DateTimeField(auto_now=True)),
("wire_transfer_id", models.IntegerField()),
- ("data", django.contrib.postgres.fields.jsonb.JSONField()),
+ ("data", models.JSONField()),
(
"order",
models.ForeignKey(
diff --git a/ecommerce/urls.py b/ecommerce/urls.py
index 60d519919..fe41e0df8 100644
--- a/ecommerce/urls.py
+++ b/ecommerce/urls.py
@@ -2,8 +2,7 @@
URLs for ecommerce
"""
-from django.conf.urls import url
-from django.urls import path
+from django.urls import path, re_path
from ecommerce.views import (
CheckoutDataView,
@@ -17,27 +16,27 @@
urlpatterns = [
- url(r"^api/v0/payment/$", PaymentView.as_view(), name="create-payment"),
- url(
- r"^api/v0/order_fulfillment/$",
+ path("api/v0/payment/", PaymentView.as_view(), name="create-payment"),
+ path(
+ "api/v0/order_fulfillment/",
OrderFulfillmentView.as_view(),
name="order-fulfillment",
),
- url(
+ re_path(
r"^api/v0/bootcamps/(?P[-\w.]+)/$",
UserBootcampRunList.as_view(),
name="bootcamp-run-list",
),
- url(
+ re_path(
r"^api/v0/bootcamps/(?P[-\w.]+)/(?P[\d]+)/$",
UserBootcampRunDetail.as_view(),
name="bootcamp-run-detail",
),
- url(
- r"statement/(?P[0-9]+)/$",
+ path(
+ "statement//",
UserBootcampRunStatement.as_view(),
name="bootcamp-run-statement",
),
- url(r"api/orders/(?P[0-9]+)/$", OrderView.as_view(), name="order-api"),
+ path("api/orders//", OrderView.as_view(), name="order-api"),
path("api/checkout/", CheckoutDataView.as_view(), name="checkout-data-detail"),
]
diff --git a/jobma/admin.py b/jobma/admin.py
index 3f1db6a2f..845fb7c42 100644
--- a/jobma/admin.py
+++ b/jobma/admin.py
@@ -7,6 +7,7 @@
from jobma.models import Interview, Job, InterviewAudit
+@admin.register(Interview)
class InterviewAdmin(admin.ModelAdmin):
"""Admin for Interview"""
@@ -29,21 +30,24 @@ def get_fields(self, request, obj=None):
fields.insert(applicant_index + 1, "status")
return fields
+ @admin.display(
+ description="Applicant",
+ ordering="applicant__email",
+ )
def get_applicant_email(self, obj):
"""Returns the user email"""
return obj.applicant.email
- get_applicant_email.short_description = "Applicant"
- get_applicant_email.admin_order_field = "applicant__email"
-
+ @admin.display(
+ description="Job Title",
+ ordering="job__job_title",
+ )
def get_job_title(self, obj):
"""Returns the job title"""
return obj.job.job_title
- get_job_title.short_description = "Job Title"
- get_job_title.admin_order_field = "job__job_title"
-
+@admin.register(Job)
class JobAdmin(admin.ModelAdmin):
"""Admin for Job"""
@@ -58,14 +62,16 @@ def get_queryset(self, request):
"""Overrides base queryset"""
return super().get_queryset(request).select_related("run__bootcamp")
+ @admin.display(
+ description="Bootcamp Run",
+ ordering="run__title",
+ )
def get_run_display_title(self, obj):
"""Returns the bootcamp run display title"""
return obj.run.display_title
- get_run_display_title.short_description = "Bootcamp Run"
- get_run_display_title.admin_order_field = "run__title"
-
+@admin.register(InterviewAudit)
class InterviewAuditAdmin(admin.ModelAdmin):
"""Admin for Interview Audit model"""
@@ -79,8 +85,3 @@ def has_delete_permission(self, request, obj=None):
def has_change_permission(self, request, obj=None):
return False
-
-
-admin.site.register(Interview, InterviewAdmin)
-admin.site.register(Job, JobAdmin)
-admin.site.register(InterviewAudit, InterviewAuditAdmin)
diff --git a/jobma/migrations/0001_initial.py b/jobma/migrations/0001_initial.py
index 346f8d885..132f04769 100644
--- a/jobma/migrations/0001_initial.py
+++ b/jobma/migrations/0001_initial.py
@@ -1,7 +1,6 @@
# Generated by Django 2.2.10 on 2020-05-01 16:29
from django.conf import settings
-import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
@@ -88,15 +87,11 @@ class Migration(migrations.Migration):
("updated_on", models.DateTimeField(auto_now=True)),
(
"data_before",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"data_after",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"acting_user",
@@ -133,15 +128,11 @@ class Migration(migrations.Migration):
("updated_on", models.DateTimeField(auto_now=True)),
(
"data_before",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"data_after",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"acting_user",
diff --git a/jobma/urls.py b/jobma/urls.py
index 44d33d705..92d752506 100644
--- a/jobma/urls.py
+++ b/jobma/urls.py
@@ -1,12 +1,12 @@
"""urls for jobma"""
-from django.conf.urls import url
+from django.urls import path
from jobma.views import JobmaWebhookView
urlpatterns = [
- url(
- r"api/v0/jobma_webhook/(?P\d+)/$",
+ path(
+ "api/v0/jobma_webhook//",
JobmaWebhookView.as_view(),
name="jobma-webhook",
)
diff --git a/klasses/__init__.py b/klasses/__init__.py
index f23d9ed8c..e1d7b8317 100644
--- a/klasses/__init__.py
+++ b/klasses/__init__.py
@@ -1,3 +1 @@
"""Initialize klasses app"""
-
-default_app_config = "klasses.apps.KlassesConfig"
diff --git a/klasses/admin.py b/klasses/admin.py
index a402a636c..9c59e5dc1 100644
--- a/klasses/admin.py
+++ b/klasses/admin.py
@@ -5,13 +5,20 @@
from django.contrib import admin
from mitol.common.admin import TimestampedModelAdmin
-from klasses import models
+from klasses.models import (
+ Bootcamp,
+ BootcampRun,
+ BootcampRunCertificate,
+ BootcampRunEnrollment,
+ Installment,
+ PersonalPrice,
+)
class BootcampRunInline(admin.StackedInline):
"""Admin Inline for BootcampRun objects"""
- model = models.BootcampRun
+ model = BootcampRun
extra = 1
show_change_link = True
@@ -19,15 +26,16 @@ class BootcampRunInline(admin.StackedInline):
class InstallmentInline(admin.StackedInline):
"""Admin Inline for Installment objects"""
- model = models.Installment
+ model = Installment
extra = 1
show_change_link = True
+@admin.register(Bootcamp)
class BootcampAdmin(admin.ModelAdmin):
"""Admin for Bootcamp"""
- model = models.Bootcamp
+ model = Bootcamp
list_display = (
"title",
"readable_id",
@@ -39,10 +47,11 @@ class BootcampAdmin(admin.ModelAdmin):
inlines = [BootcampRunInline]
+@admin.register(BootcampRun)
class BootcampRunAdmin(admin.ModelAdmin):
"""Admin for BootcampRun"""
- model = models.BootcampRun
+ model = BootcampRun
list_display = (
"display_title",
"bootcamp_run_id",
@@ -60,10 +69,11 @@ class BootcampRunAdmin(admin.ModelAdmin):
inlines = [InstallmentInline]
+@admin.register(BootcampRunEnrollment)
class BootcampRunEnrollmentAdmin(TimestampedModelAdmin):
"""Admin for BootcampRunEnrollment"""
- model = models.BootcampRunEnrollment
+ model = BootcampRunEnrollment
include_created_on_in_list = True
list_display = (
"id",
@@ -96,18 +106,20 @@ def get_queryset(self, request):
.select_related("user", "bootcamp_run__bootcamp")
)
+ @admin.display(
+ description="User",
+ ordering="user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
return obj.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "user__email"
-
+@admin.register(Installment)
class InstallmentAdmin(admin.ModelAdmin):
"""Admin for Installment"""
- model = models.Installment
+ model = Installment
list_display = ("id", "bootcamp_run", "deadline", "amount")
raw_id_fields = ("bootcamp_run",)
search_fields = (
@@ -116,10 +128,11 @@ class InstallmentAdmin(admin.ModelAdmin):
)
+@admin.register(PersonalPrice)
class PersonalPriceAdmin(admin.ModelAdmin):
"""Admin for PersonalPrice"""
- model = models.PersonalPrice
+ model = PersonalPrice
list_display = ("id", "get_user_email", "bootcamp_run", "price")
list_filter = ("bootcamp_run__bootcamp",)
raw_id_fields = ("bootcamp_run", "user")
@@ -141,18 +154,20 @@ def get_queryset(self, request):
.select_related("user", "bootcamp_run__bootcamp")
)
+ @admin.display(
+ description="User",
+ ordering="user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
return obj.user.email
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "user__email"
-
+@admin.register(BootcampRunCertificate)
class BootcampRunCertificateAdmin(TimestampedModelAdmin):
"""Admin for BootcampRunCertificate"""
- model = models.BootcampRunCertificate
+ model = BootcampRunCertificate
include_timestamps_in_list = True
list_display = ["uuid", "get_user_email", "bootcamp_run", "get_revoked_state"]
search_fields = [
@@ -168,24 +183,18 @@ def get_queryset(self, request):
"user", "bootcamp_run"
)
+ @admin.display(
+ description="Active",
+ boolean=True,
+ )
def get_revoked_state(self, obj):
"""return the revoked state"""
return obj.is_revoked is not True
- get_revoked_state.short_description = "Active"
- get_revoked_state.boolean = True
-
+ @admin.display(
+ description="User",
+ ordering="user__email",
+ )
def get_user_email(self, obj):
"""Returns the user email"""
return obj.user.email
-
- get_user_email.short_description = "User"
- get_user_email.admin_order_field = "user__email"
-
-
-admin.site.register(models.Bootcamp, BootcampAdmin)
-admin.site.register(models.BootcampRun, BootcampRunAdmin)
-admin.site.register(models.Installment, InstallmentAdmin)
-admin.site.register(models.PersonalPrice, PersonalPriceAdmin)
-admin.site.register(models.BootcampRunEnrollment, BootcampRunEnrollmentAdmin)
-admin.site.register(models.BootcampRunCertificate, BootcampRunCertificateAdmin)
diff --git a/klasses/migrations/0004_admission_cache.py b/klasses/migrations/0004_admission_cache.py
index a8cf7fd2a..3cb6bcef0 100644
--- a/klasses/migrations/0004_admission_cache.py
+++ b/klasses/migrations/0004_admission_cache.py
@@ -3,7 +3,6 @@
from __future__ import unicode_literals
from django.conf import settings
-import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
@@ -27,7 +26,7 @@ class Migration(migrations.Migration):
verbose_name="ID",
),
),
- ("data", django.contrib.postgres.fields.jsonb.JSONField()),
+ ("data", models.JSONField()),
(
"klass",
models.ForeignKey(
diff --git a/klasses/migrations/0026_add_bootcamprunenrollmentaudit_defer_enrollment_field.py b/klasses/migrations/0026_add_bootcamprunenrollmentaudit_defer_enrollment_field.py
index 6372dc8e4..1762839ac 100644
--- a/klasses/migrations/0026_add_bootcamprunenrollmentaudit_defer_enrollment_field.py
+++ b/klasses/migrations/0026_add_bootcamprunenrollmentaudit_defer_enrollment_field.py
@@ -1,7 +1,6 @@
# Generated by Django 2.2.18 on 2021-04-26 09:07
from django.conf import settings
-import django.contrib.postgres.fields.jsonb
from django.db import migrations, models
import django.db.models.deletion
@@ -39,15 +38,11 @@ class Migration(migrations.Migration):
("updated_on", models.DateTimeField(auto_now=True)),
(
"data_before",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"data_after",
- django.contrib.postgres.fields.jsonb.JSONField(
- blank=True, null=True
- ),
+ models.JSONField(blank=True, null=True),
),
(
"acting_user",
diff --git a/klasses/models_test.py b/klasses/models_test.py
index c999b96ad..d10b229af 100644
--- a/klasses/models_test.py
+++ b/klasses/models_test.py
@@ -138,7 +138,7 @@ def test_bootcamp_run_is_payable(future_start_date, expected_result):
bootcamp_run = None
if future_start_date is None:
start_date = None
- bootcamp_run = BootcampRunFactory.build(start_date=start_date)
+ bootcamp_run = BootcampRunFactory.create(start_date=start_date)
elif future_start_date:
start_date = now_in_utc() + timedelta(days=10)
else:
diff --git a/mail/urls.py b/mail/urls.py
index 6683e00b6..1e6aa8fbd 100644
--- a/mail/urls.py
+++ b/mail/urls.py
@@ -1,7 +1,7 @@
"""URL configurations for mail"""
from django.conf import settings
-from django.conf.urls import url
+from django.urls import path
from mail.views import EmailDebuggerView
@@ -9,5 +9,5 @@
if settings.DEBUG:
urlpatterns += [
- url(r"^__emaildebugger__/$", EmailDebuggerView.as_view(), name="email-debugger")
+ path("__emaildebugger__/", EmailDebuggerView.as_view(), name="email-debugger")
]
diff --git a/mail/v2/verification_api_test.py b/mail/v2/verification_api_test.py
index 992d1a4a4..18d704bb4 100644
--- a/mail/v2/verification_api_test.py
+++ b/mail/v2/verification_api_test.py
@@ -24,7 +24,7 @@ def test_send_verification_email(mocker, rf):
email = "test@localhost"
request = rf.post(reverse("social:complete", args=("email",)), {"email": email})
# social_django depends on request.sesssion, so use the middleware to set that
- SessionMiddleware().process_request(request)
+ SessionMiddleware(get_response=mocker.Mock()).process_request(request)
strategy = load_strategy(request)
backend = load_backend(strategy, EmailAuth.name, None)
code = mocker.Mock(code="abc")
diff --git a/main/hijack_support_middleware.py b/main/hijack_support_middleware.py
new file mode 100644
index 000000000..a431b750d
--- /dev/null
+++ b/main/hijack_support_middleware.py
@@ -0,0 +1,18 @@
+from django.utils.deprecation import MiddlewareMixin
+
+
+class HijackSupportMiddleware(MiddlewareMixin):
+ """Middleware to support HijackMiddleware"""
+
+ def process_request(self, request):
+ """
+ HijackMiddleware needs the session to be in accessed state in order to work properly. However, It doesn't work properly
+ with our current architecture and django-hijack implementation because when the request reaches HijackMiddleware the
+ session is not in accessed state. As a result it is unable to add the notification in DOM.
+
+ This middleware is written to ensure that the request session has accessed=True when the request reaches HijackMiddleware.
+
+ We will probably need to add a more robust solution to django-hijack package.
+ """
+ if hasattr(request, "session"):
+ request.session.get("hijack_history", [])
diff --git a/main/middleware_test.py b/main/middleware_test.py
index 822578e35..09b83fb39 100644
--- a/main/middleware_test.py
+++ b/main/middleware_test.py
@@ -15,11 +15,11 @@
],
)
def test_cacheless_api_middleware(
- rf, view, cache_value, cacheable_endpoints_cache_value
+ rf, view, cache_value, cacheable_endpoints_cache_value, mocker
):
"""Tests that the response has a cache-control header for API URLs"""
request = rf.get(reverse(view))
- middleware = CachelessAPIMiddleware()
+ middleware = CachelessAPIMiddleware(get_response=mocker.Mock())
assert (
middleware.process_response(request, {}).get("Cache-Control", None)
== cache_value
diff --git a/main/settings.py b/main/settings.py
index aed1711df..62f0d4c6c 100644
--- a/main/settings.py
+++ b/main/settings.py
@@ -127,13 +127,10 @@
"django.contrib.humanize",
"rest_framework",
"rest_framework.authtoken",
- "server_status",
"social_django",
"mathfilters",
- # Hijack
"hijack",
- "compat",
- "hijack_admin",
+ "hijack.contrib.admin",
# other third party APPS
# wagtail
"wagtail.contrib.forms",
@@ -195,6 +192,8 @@
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
+ "hijack.middleware.HijackUserMiddleware",
+ "main.hijack_support_middleware.HijackSupportMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
"social_django.middleware.SocialAuthExceptionMiddleware",
@@ -401,8 +400,7 @@
WSGI_APPLICATION = "main.wsgi.application"
# Hijack
-HIJACK_ALLOW_GET_REQUESTS = True
-HIJACK_LOGOUT_REDIRECT_URL = "/admin/auth/user"
+HIJACK_INSERT_BEFORE = "
- {% hijack_notification %}
{% include "gtm_body.html" %}
{% latest_notification %}
{% block headercontent %}
diff --git a/main/urls.py b/main/urls.py
index dc93dc58b..f54cb4126 100644
--- a/main/urls.py
+++ b/main/urls.py
@@ -3,7 +3,7 @@
"""
from django.conf import settings
-from django.conf.urls import url
+from django.urls import re_path
from django.conf.urls.static import static
from django.urls import re_path, include, path
from django.contrib import admin
@@ -16,23 +16,22 @@
from main.views import react, BackgroundImagesCSSView, cms_login_redirect_view
-root_urlpatterns = [url("", include(wagtail_urls))]
+root_urlpatterns = [path("", include(wagtail_urls))]
urlpatterns = (
[
- url(r"^status/", include("server_status.urls")),
- url(r"^admin/", admin.site.urls),
- url(r"^hijack/", include("hijack.urls", namespace="hijack")),
- url("", include("applications.urls")),
- url("", include("ecommerce.urls")),
- url("", include("social_django.urls", namespace="social")),
+ path("admin/", admin.site.urls),
+ path("hijack/", include("hijack.urls")),
+ path("", include("applications.urls")),
+ path("", include("ecommerce.urls")),
+ path("", include("social_django.urls", namespace="social")),
path("", include("authentication.urls")),
path("", include("mail.urls")),
path("", include("profiles.urls")),
path("", include("klasses.urls")),
- url("", include("jobma.urls")),
- url(r"^logout/$", auth_views.LogoutView.as_view(), name="logout"),
- url(
+ path("", include("jobma.urls")),
+ path("logout/", auth_views.LogoutView.as_view(), name="logout"),
+ re_path(
r"^background-images\.css$",
BackgroundImagesCSSView.as_view(),
name="background-images-css",
@@ -40,7 +39,7 @@
# named routes mapped to the react app
path("signin/", react, name="login"),
path("signin/password/", react, name="login-password"),
- re_path(r"^signin/forgot-password/$", react, name="password-reset"),
+ path("signin/forgot-password/", react, name="password-reset"),
path(
"signin/forgot-password/confirm///",
react,
@@ -75,9 +74,9 @@
name="wagtailimages_serve",
),
re_path(r"^cms/login", cms_login_redirect_view, name="wagtailadmin_login"),
- re_path(r"^cms/", include(wagtailadmin_urls)),
- re_path(r"^documents/", include(wagtaildocs_urls)),
- re_path(r"^idp/", include("djangosaml2idp.urls")),
+ path("cms/", include(wagtailadmin_urls)),
+ path("documents/", include(wagtaildocs_urls)),
+ path("idp/", include("djangosaml2idp.urls")),
]
+ root_urlpatterns
+ (
diff --git a/poetry.lock b/poetry.lock
index a66a9e50f..81e71ff21 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -919,19 +919,19 @@ static3 = "*"
[[package]]
name = "django"
-version = "3.2.25"
-description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
+version = "4.2.13"
+description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "Django-3.2.25-py3-none-any.whl", hash = "sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38"},
- {file = "Django-3.2.25.tar.gz", hash = "sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777"},
+ {file = "Django-4.2.13-py3-none-any.whl", hash = "sha256:a17fcba2aad3fc7d46fdb23215095dbbd64e6174bf4589171e732b18b07e426a"},
+ {file = "Django-4.2.13.tar.gz", hash = "sha256:837e3cf1f6c31347a1396a3f6b65688f2b4bb4a11c580dcb628b5afe527b68a5"},
]
[package.dependencies]
-asgiref = ">=3.3.2,<4"
-pytz = "*"
-sqlparse = ">=0.2.2"
+asgiref = ">=3.6.0,<4"
+sqlparse = ">=0.3.1"
+tzdata = {version = "*", markers = "sys_platform == \"win32\""}
[package.extras]
argon2 = ["argon2-cffi (>=19.1.0)"]
@@ -973,30 +973,17 @@ dev = ["black", "flake8", "therapist", "tox", "twine"]
[[package]]
name = "django-classy-tags"
-version = "1.0.0"
+version = "4.1.0"
description = "Class based template tags for Django"
optional = false
-python-versions = "*"
-files = [
- {file = "django-classy-tags-1.0.0.tar.gz", hash = "sha256:ad6a25fc2b58a098f00d86bd5e5dad47922f5ca4e744bc3cccb7b4be5bc35eb1"},
-]
-
-[package.dependencies]
-django = ">=1.11"
-six = "*"
-
-[[package]]
-name = "django-compat"
-version = "1.0.15"
-description = "For- and backwards compatibility layer for Django 1.4, 1.7, 1.8, 1.9, 1.10, and 1.11"
-optional = false
-python-versions = "*"
+python-versions = ">=3.8"
files = [
- {file = "django-compat-1.0.15.tar.gz", hash = "sha256:3ac9a3bedc56b9365d9eb241bc5157d0c193769bf995f9a78dc1bc24e7c2331b"},
+ {file = "django-classy-tags-4.1.0.tar.gz", hash = "sha256:c8d9d1aa2fa6e71c4d866df4dd11d23a69b8d25bbb750b2490a17b161774ee59"},
+ {file = "django_classy_tags-4.1.0-py3-none-any.whl", hash = "sha256:1c784cf1bac49c20a77b8f7d1541867c64076642a160a847ff449588d4e01e55"},
]
[package.dependencies]
-six = ">=1.10.0"
+django = ">=3.2"
[[package]]
name = "django-debug-toolbar"
@@ -1040,34 +1027,20 @@ files = [
[[package]]
name = "django-hijack"
-version = "2.3.0"
+version = "3.4.5"
description = "django-hijack allows superusers to hijack (=login as) and work on behalf of another user."
optional = false
python-versions = "*"
files = [
- {file = "django-hijack-2.3.0.tar.gz", hash = "sha256:216de6ff863b5f48314795083e96267ff0829ff7f7180c26ca3c17d8a134e1cf"},
- {file = "django_hijack-2.3.0-py3-none-any.whl", hash = "sha256:8b820b6fe605cf2f3b50817985d7245285a18c027b7e3eb424d18b7908ecd2e1"},
+ {file = "django-hijack-3.4.5.tar.gz", hash = "sha256:7e45b1de786bdc130628e4230b359dde6d8744ecd3bcd668d2b27c5d614a071c"},
+ {file = "django_hijack-3.4.5-py3-none-any.whl", hash = "sha256:129cbe75444b163135871a947d38ffb72181f4f2583544703fc9efe083c9ddad"},
]
[package.dependencies]
-django = ">=2.2"
-
-[[package]]
-name = "django-hijack-admin"
-version = "2.1.10"
-description = "Django admin integration for Django Hijack (https://github.com/arteria/django-hijack/)"
-optional = false
-python-versions = "*"
-files = [
- {file = "django-hijack-admin-2.1.10.tar.gz", hash = "sha256:330f9be331ada831248c9cee5a21202aea70fb9911b443249ce4c28d57d9e2e3"},
-]
-
-[package.dependencies]
-django-compat = ">=1.0.13"
-django-hijack = ">=2.1.5"
+django = ">=3.2"
[package.extras]
-dev = ["flake8"]
+test = ["pytest", "pytest-cov", "pytest-django"]
[[package]]
name = "django-ipware"
@@ -1141,20 +1114,6 @@ files = [
Django = ">=2.2"
redis = ">=3.0.0"
-[[package]]
-name = "django-server-status"
-version = "0.7.3"
-description = "Monitor server status with a healthcheck."
-optional = false
-python-versions = "*"
-files = [
- {file = "django-server-status-0.7.3.tar.gz", hash = "sha256:9126e20d78c88f62ffe382c1a5c73f1206ba8dca07a8039e81e3f35f1f75941a"},
- {file = "django_server_status-0.7.3-py3-none-any.whl", hash = "sha256:2a018c731504a3c82d45717bca011c4f6b1d547f5384c9b0a04b439e9e5c3552"},
-]
-
-[package.dependencies]
-django = "*"
-
[[package]]
name = "django-storages"
version = "1.14.3"
@@ -1230,17 +1189,17 @@ files = [
[[package]]
name = "djangorestframework"
-version = "3.15.1"
+version = "3.15.2"
description = "Web APIs for Django, made easy."
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "djangorestframework-3.15.1-py3-none-any.whl", hash = "sha256:3ccc0475bce968608cf30d07fb17d8e52d1d7fc8bfe779c905463200750cbca6"},
- {file = "djangorestframework-3.15.1.tar.gz", hash = "sha256:f88fad74183dfc7144b2756d0d2ac716ea5b4c7c9840995ac3bfd8ec034333c1"},
+ {file = "djangorestframework-3.15.2-py3-none-any.whl", hash = "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20"},
+ {file = "djangorestframework-3.15.2.tar.gz", hash = "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad"},
]
[package.dependencies]
-django = ">=3.0"
+django = ">=4.2"
[[package]]
name = "djangorestframework-serializer-extensions"
diff --git a/profiles/admin.py b/profiles/admin.py
index 56fb0eea3..fa4e7d13a 100644
--- a/profiles/admin.py
+++ b/profiles/admin.py
@@ -6,7 +6,7 @@
from django.contrib.auth.admin import UserAdmin as ContribUserAdmin
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _
-from hijack_admin.admin import HijackUserAdminMixin
+from hijack.contrib.admin import HijackUserAdminMixin
from profiles.models import LegalAddress, Profile
@@ -51,7 +51,7 @@ def has_delete_permission(self, request, obj=None):
return True
-class UserAdmin(ContribUserAdmin, HijackUserAdminMixin):
+class UserAdmin(ContribUserAdmin):
"""Admin views for user"""
fieldsets = (
@@ -71,7 +71,7 @@ class UserAdmin(ContribUserAdmin, HijackUserAdminMixin):
},
),
)
- list_display = ("username", "email", "is_staff", "hijack_field", "last_login")
+ list_display = ("username", "email", "is_staff", "last_login")
list_filter = ("is_staff", "is_superuser", "is_active", "groups")
search_fields = ("username", "email")
ordering = ("email",)
diff --git a/profiles/migrations/0004_profile_smapply_user_data.py b/profiles/migrations/0004_profile_smapply_user_data.py
index 6bd9e06d8..4972dca9d 100644
--- a/profiles/migrations/0004_profile_smapply_user_data.py
+++ b/profiles/migrations/0004_profile_smapply_user_data.py
@@ -2,8 +2,7 @@
# Generated by Django 1.11.20 on 2019-09-13 18:42
from __future__ import unicode_literals
-import django.contrib.postgres.fields.jsonb
-from django.db import migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
@@ -13,6 +12,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name="profile",
name="smapply_user_data",
- field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True),
+ field=models.JSONField(blank=True, null=True),
)
]
diff --git a/profiles/migrations/0005_profile_smapply_demographic_data.py b/profiles/migrations/0005_profile_smapply_demographic_data.py
index 0b3dbb0ab..282bdf71c 100644
--- a/profiles/migrations/0005_profile_smapply_demographic_data.py
+++ b/profiles/migrations/0005_profile_smapply_demographic_data.py
@@ -2,8 +2,7 @@
# Generated by Django 1.11.20 on 2019-09-23 17:26
from __future__ import unicode_literals
-import django.contrib.postgres.fields.jsonb
-from django.db import migrations
+from django.db import migrations, models
class Migration(migrations.Migration):
@@ -13,6 +12,6 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name="profile",
name="smapply_demographic_data",
- field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, null=True),
+ field=models.JSONField(blank=True, null=True),
)
]
diff --git a/profiles/urls.py b/profiles/urls.py
index 3f19cfa55..67096ad52 100644
--- a/profiles/urls.py
+++ b/profiles/urls.py
@@ -1,6 +1,6 @@
"""User url routes"""
-from django.conf.urls import include
+from django.urls import include
from django.urls import path
from rest_framework import routers
diff --git a/pyproject.toml b/pyproject.toml
index 490a0efa6..2d57486e0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -33,28 +33,24 @@ authors = ["MIT ODL"]
[tool.poetry.dependencies]
python = "3.10.13"
-django = "^3.2.25"
-celery = {extras = ["redis"], version = "^5.2.7"}
+django = "^4.2.13"
+celery = {extras = ["redis"], version = "^5.3.6"}
boto3 = "^1.16.63"
dj-database-url = "^0.5.0"
django-anymail = {extras = ["mailgun"], version = "^8.4"}
dj-static = "^0.0.6"
django-cache-memoize = "^0.2.0"
-django-classy-tags = "^1.0.0"
-django-compat = "^1.0.15"
-django-hijack = "^2.1.10"
-django-hijack-admin = "^2.1.7"
+django-classy-tags = "^4.1.0"
+django-hijack = "^3.4.5"
django-filter = "^23.4"
django-fsm = "^2.8.0"
django-ipware = "^4.0.0"
django-mathfilters = "^1.0.0"
django-redis = "^5.0.0"
-django-server-status = "^0.7.3"
django-webpack-loader = "^0.7.0"
-djangorestframework = "^3.11.2"
+djangorestframework = "^3.15.2"
djangorestframework-serializer-extensions = "^2.0.0"
djangosaml2idp = { git = "https://github.com/OTA-Insight/djangosaml2idp.git", rev = "0b4325782a6fd2c034677b5923041b5df10087ec" } # pragma: allowlist secret
-djoser = "^2.1.0"
dynamic-rest = "^2.1.2"
html5lib = "^1.1"
hubspot-api-client = "^6.1.0"
@@ -98,7 +94,7 @@ pdbpp = "^0.10.2"
pip-tools = "^7.1.0"
pylint = "~2.17.0"
pylint-django = "~2.5.0"
-pytest = "^7.0.0"
+pytest = "^7.4.4"
pytest-cov = "^2.6.1"
pytest-env = "^0.8.0"
pytest-django = "^4.0.0"
"
# Database
# https://github.com/kennethreitz/dj-database-url
@@ -443,7 +441,6 @@
USE_I18N = True
-USE_L10N = True
USE_TZ = True
@@ -683,15 +680,6 @@
LOGGING["loggers"]["ui"]["handlers"] = ["console"]
LOGGING["loggers"]["django"]["handlers"] = ["console"]
-# server-status
-STATUS_TOKEN = get_string(
- name="STATUS_TOKEN",
- default="",
- description="Token to access the status API.",
- required=True,
-)
-HEALTH_CHECK = ["CELERY", "REDIS", "POSTGRES", "ELASTIC_SEARCH"]
-
ADWORDS_CONVERSION_ID = get_string(
name="ADWORDS_CONVERSION_ID", default="", description="Id for adwords conversion"
)
diff --git a/main/templates/base.html b/main/templates/base.html
index d0a6436b8..049576e3d 100644
--- a/main/templates/base.html
+++ b/main/templates/base.html
@@ -3,7 +3,7 @@
{% spaceless %}
{% load static %}
- {% load hijack_tags %}
+ {% load hijack %}
{% include "gtm_head.html" %}
@@ -17,11 +17,6 @@
type="text/css"
href="{% url 'background-images-css' %}"
/>
-