diff --git a/openedx/core/djangoapps/notifications/email/utils.py b/openedx/core/djangoapps/notifications/email/utils.py
index 1e0f4c81c7..da288750bb 100644
--- a/openedx/core/djangoapps/notifications/email/utils.py
+++ b/openedx/core/djangoapps/notifications/email/utils.py
@@ -7,7 +7,6 @@ import json
from django.conf import settings
from django.contrib.auth import get_user_model
from django.shortcuts import get_object_or_404
-from django.urls import reverse
from pytz import utc
from waffle import get_waffle_flag_model # pylint: disable=invalid-django-waffle-import
@@ -20,7 +19,10 @@ from openedx.core.djangoapps.notifications.base_notification import (
)
from openedx.core.djangoapps.notifications.config.waffle import ENABLE_EMAIL_NOTIFICATIONS
from openedx.core.djangoapps.notifications.email_notifications import EmailCadence
-from openedx.core.djangoapps.notifications.models import CourseNotificationPreference
+from openedx.core.djangoapps.notifications.models import (
+ CourseNotificationPreference,
+ get_course_notification_preference_config_version
+)
from xmodule.modulestore.django import modulestore
from .notification_icons import NotificationTypeIcons
@@ -71,15 +73,7 @@ def get_unsubscribe_link(username, patch):
"""
encrypted_username = encrypt_string(username)
encrypted_patch = encrypt_object(patch)
- kwargs = {
- 'username': encrypted_username,
- 'patch': encrypted_patch
- }
- relative_url = reverse('preference_update_from_encrypted_username_view', kwargs=kwargs)
- protocol = 'https://'
- if settings.DEBUG:
- protocol = 'http://'
- return f"{protocol}{settings.LMS_BASE}{relative_url}"
+ return f"{settings.LEARNING_MICROFRONTEND_URL}/preferences-unsubscribe/{encrypted_username}/{encrypted_patch}"
def create_email_template_context(username):
@@ -363,6 +357,14 @@ def update_user_preferences_from_patch(encrypted_username, encrypted_patch):
return COURSE_NOTIFICATION_APPS[app_name]['core_email_cadence']
return COURSE_NOTIFICATION_TYPES[notification_type]['email_cadence']
+ def get_updated_preference(pref):
+ """
+ Update preference if config version doesn't match
+ """
+ if pref.config_version != get_course_notification_preference_config_version():
+ pref = pref.get_user_course_preference(pref.user_id, pref.course_id)
+ return pref
+
course_ids = CourseEnrollment.objects.filter(user=user).values_list('course_id', flat=True)
CourseNotificationPreference.objects.bulk_create(
[
@@ -375,6 +377,7 @@ def update_user_preferences_from_patch(encrypted_username, encrypted_patch):
# pylint: disable=too-many-nested-blocks
for preference in preferences:
+ preference = get_updated_preference(preference)
preference_json = preference.notification_preference_config
for app_name, app_prefs in preference_json.items():
if not is_name_match(app_name, app_value):
diff --git a/openedx/core/djangoapps/notifications/templates/notifications/digest_footer.html b/openedx/core/djangoapps/notifications/templates/notifications/digest_footer.html
index 0419b25665..4fa903d127 100644
--- a/openedx/core/djangoapps/notifications/templates/notifications/digest_footer.html
+++ b/openedx/core/djangoapps/notifications/templates/notifications/digest_footer.html
@@ -38,7 +38,7 @@
Notification Settings
- Unsubscribe
+ Unsubscribe from email digest for learning activity
diff --git a/openedx/core/djangoapps/notifications/templates/notifications/digest_header.html b/openedx/core/djangoapps/notifications/templates/notifications/digest_header.html
index 7957524e8a..1f22ced200 100644
--- a/openedx/core/djangoapps/notifications/templates/notifications/digest_header.html
+++ b/openedx/core/djangoapps/notifications/templates/notifications/digest_header.html
@@ -5,6 +5,13 @@
style="background: #00262b; color: white; width: 100%; padding: 1.5rem"
>
+
+ |
+
+ Unsubscribe
+
+ |
+
diff --git a/openedx/core/djangoapps/notifications/tests/test_views.py b/openedx/core/djangoapps/notifications/tests/test_views.py
index d2968749ef..e40e520789 100644
--- a/openedx/core/djangoapps/notifications/tests/test_views.py
+++ b/openedx/core/djangoapps/notifications/tests/test_views.py
@@ -28,9 +28,13 @@ from openedx.core.djangoapps.django_comment_common.models import (
)
from openedx.core.djangoapps.notifications.config.waffle import ENABLE_NOTIFICATIONS
from openedx.core.djangoapps.notifications.email_notifications import EmailCadence
-from openedx.core.djangoapps.notifications.models import CourseNotificationPreference, Notification
+from openedx.core.djangoapps.notifications.models import (
+ CourseNotificationPreference,
+ Notification,
+ get_course_notification_preference_config_version
+)
from openedx.core.djangoapps.notifications.serializers import NotificationCourseEnrollmentSerializer
-from openedx.core.djangoapps.notifications.email.utils import get_unsubscribe_link
+from openedx.core.djangoapps.notifications.email.utils import encrypt_object, encrypt_string
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory
@@ -910,7 +914,13 @@ class UpdatePreferenceFromEncryptedDataView(ModuleStoreTestCase):
"""
Tests if preference is updated when url is hit
"""
- url = get_unsubscribe_link(self.user.username, {'channel': 'email', 'value': False})
+ user_hash = encrypt_string(self.user.username)
+ patch_hash = encrypt_object({'channel': 'email', 'value': False})
+ url_params = {
+ "username": user_hash,
+ "patch": patch_hash
+ }
+ url = reverse("preference_update_from_encrypted_username_view", kwargs=url_params)
func = getattr(self.client, request_type)
response = func(url)
assert response.status_code == status.HTTP_200_OK
@@ -921,6 +931,24 @@ class UpdatePreferenceFromEncryptedDataView(ModuleStoreTestCase):
assert type_prefs['email'] is False
assert type_prefs['email_cadence'] == EmailCadence.NEVER
+ def test_if_config_version_is_updated(self):
+ """
+ Tests if preference version is updated before applying patch data
+ """
+ preference = CourseNotificationPreference.objects.get(user=self.user, course_id=self.course.id)
+ preference.config_version -= 1
+ preference.save()
+ user_hash = encrypt_string(self.user.username)
+ patch_hash = encrypt_object({'channel': 'email', 'value': False})
+ url_params = {
+ "username": user_hash,
+ "patch": patch_hash
+ }
+ url = reverse("preference_update_from_encrypted_username_view", kwargs=url_params)
+ self.client.get(url)
+ preference = CourseNotificationPreference.objects.get(user=self.user, course_id=self.course.id)
+ assert preference.config_version == get_course_notification_preference_config_version()
+
def remove_notifications_with_visibility_settings(expected_response):
"""
diff --git a/openedx/core/djangoapps/notifications/views.py b/openedx/core/djangoapps/notifications/views.py
index ee5e282d90..fdc91c12a9 100644
--- a/openedx/core/djangoapps/notifications/views.py
+++ b/openedx/core/djangoapps/notifications/views.py
@@ -5,7 +5,7 @@ from datetime import datetime, timedelta
from django.conf import settings
from django.db.models import Count
-from django.shortcuts import get_object_or_404, render
+from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as _
from opaque_keys.edx.keys import CourseKey
from pytz import UTC
@@ -441,7 +441,4 @@ def preference_update_from_encrypted_username_view(request, username, patch):
username and patch must be string
"""
update_user_preferences_from_patch(username, patch)
- context = {
- "notification_preferences_url": f"{settings.ACCOUNT_MICROFRONTEND_URL}/notifications"
- }
- return render(request, "notifications/email_digest_preference_update.html", context=context)
+ return Response({"result": "success"}, status=status.HTTP_200_OK)
|