Skip to content

Commit

Permalink
feat: added unsubscribe url in digest header (#35319)
Browse files Browse the repository at this point in the history
  • Loading branch information
muhammadadeeltajamul authored Aug 19, 2024
1 parent ca46c20 commit 0077269
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 20 deletions.
25 changes: 14 additions & 11 deletions openedx/core/djangoapps/notifications/email/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
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

Expand All @@ -20,7 +19,10 @@
)
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
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -363,6 +357,14 @@ def get_default_cadence_value(app_name, notification_type):
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(
[
Expand All @@ -375,6 +377,7 @@ def get_default_cadence_value(app_name, notification_type):

# 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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
Notification Settings
</a>
<a href="{{unsubscribe_url}}" rel="noopener noreferrer" target="_blank" style="color: black; margin-left: 1rem">
Unsubscribe
Unsubscribe from email digest for learning activity
</a>
</p>
<p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
style="background: #00262b; color: white; width: 100%; padding: 1.5rem"
>
<tbody>
<tr align="right">
<td>
<a href="{{unsubscribe_url}}" rel="noopener noreferrer" target="_blank" style="color: white; text-decoration: none; font-size: 12px; line-height: 10px">
Unsubscribe
</a>
</td>
</tr>
<tr align="center">
<td>
<img src="{{ logo_url }}" style="width: 64px" height="auto" alt="logo_url" />
Expand Down
34 changes: 31 additions & 3 deletions openedx/core/djangoapps/notifications/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,13 @@
)
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

Expand Down Expand Up @@ -910,7 +914,13 @@ def test_if_preference_is_updated(self, request_type):
"""
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
Expand All @@ -921,6 +931,24 @@ def test_if_preference_is_updated(self, request_type):
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):
"""
Expand Down
7 changes: 2 additions & 5 deletions openedx/core/djangoapps/notifications/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

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
Expand Down Expand Up @@ -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)

0 comments on commit 0077269

Please sign in to comment.