From 23894d20f8f8f0b5f9db615e10607031b5476347 Mon Sep 17 00:00:00 2001 From: cahrens Date: Wed, 24 Jul 2013 12:45:16 -0400 Subject: [PATCH 1/4] E-mail notifications to users when course creator status changes. --- .../contentstore/tests/test_users.py | 2 +- cms/djangoapps/course_creators/admin.py | 29 +++++++++++++++- cms/djangoapps/course_creators/models.py | 2 +- .../course_creators/tests/test_admin.py | 34 +++++++++++++++++-- cms/envs/common.py | 4 +-- .../emails/course_creator_denied.txt | 5 +++ .../emails/course_creator_granted.txt | 10 ++++++ .../emails/course_creator_revoked.txt | 5 +++ .../emails/course_creator_subject.txt | 2 ++ cms/templates/index.html | 8 ++--- 10 files changed, 89 insertions(+), 12 deletions(-) create mode 100644 cms/templates/emails/course_creator_denied.txt create mode 100644 cms/templates/emails/course_creator_granted.txt create mode 100644 cms/templates/emails/course_creator_revoked.txt create mode 100644 cms/templates/emails/course_creator_subject.txt diff --git a/cms/djangoapps/contentstore/tests/test_users.py b/cms/djangoapps/contentstore/tests/test_users.py index 701dd246d8..8fea4004dd 100644 --- a/cms/djangoapps/contentstore/tests/test_users.py +++ b/cms/djangoapps/contentstore/tests/test_users.py @@ -42,7 +42,7 @@ class IndexCourseCreatorTests(CourseTestCase): self.disable_course_creation = { "DISABLE_COURSE_CREATION": True, "ENABLE_CREATOR_GROUP": True, - 'STAFF_EMAIL': 'mark@marky.mark', + 'STUDIO_REQUEST_EMAIL': 'mark@marky.mark', } self.enable_creator_group = {"ENABLE_CREATOR_GROUP": True} diff --git a/cms/djangoapps/course_creators/admin.py b/cms/djangoapps/course_creators/admin.py index 7518946270..65473d8bde 100644 --- a/cms/djangoapps/course_creators/admin.py +++ b/cms/djangoapps/course_creators/admin.py @@ -6,7 +6,13 @@ from course_creators.models import CourseCreator, update_creator_state from course_creators.views import update_course_creator_group from django.contrib import admin +from django.conf import settings from django.dispatch import receiver +from mitxmako.shortcuts import render_to_string + +import logging + +log = logging.getLogger("studio.coursecreatoradmin") def get_email(obj): @@ -60,4 +66,25 @@ def update_creator_group_callback(sender, **kwargs): """ Callback for when the model's creator status has changed. """ - update_course_creator_group(kwargs['caller'], kwargs['user'], kwargs['add']) + user = kwargs['user'] + updated_state = kwargs['state'] + update_course_creator_group(kwargs['caller'], user, updated_state == CourseCreator.GRANTED) + + studio_request_email = settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL','') + context = {'studio_request_email': studio_request_email} + + subject = render_to_string('emails/course_creator_subject.txt', context) + subject = ''.join(subject.splitlines()) + if updated_state == CourseCreator.GRANTED: + message_template = 'emails/course_creator_granted.txt' + elif updated_state == CourseCreator.DENIED: + message_template = 'emails/course_creator_denied.txt' + else: + # changed to unrequested or pending + message_template = 'emails/course_creator_revoked.txt' + message = render_to_string(message_template, context) + + try: + user.email_user(subject, message, studio_request_email) + except: + log.warning("Unable to send course creator status e-mail to %s", user.email) diff --git a/cms/djangoapps/course_creators/models.py b/cms/djangoapps/course_creators/models.py index 4975705407..ba434c9140 100644 --- a/cms/djangoapps/course_creators/models.py +++ b/cms/djangoapps/course_creators/models.py @@ -68,7 +68,7 @@ def post_save_callback(sender, **kwargs): sender=sender, caller=instance.admin, user=instance.user, - add=instance.state == CourseCreator.GRANTED + state=instance.state ) instance.state_changed = timezone.now() diff --git a/cms/djangoapps/course_creators/tests/test_admin.py b/cms/djangoapps/course_creators/tests/test_admin.py index 6ef48746e7..91a28d77ae 100644 --- a/cms/djangoapps/course_creators/tests/test_admin.py +++ b/cms/djangoapps/course_creators/tests/test_admin.py @@ -13,6 +13,11 @@ from course_creators.models import CourseCreator from auth.authz import is_user_in_creator_group +def mock_render_to_string(template_name, context): + """Return a string that encodes template_name and context""" + return str((template_name, context)) + + class CourseCreatorAdminTest(TestCase): """ Tests for course creator admin. @@ -32,17 +37,40 @@ class CourseCreatorAdminTest(TestCase): self.creator_admin = CourseCreatorAdmin(self.table_entry, AdminSite()) - def test_change_status(self): + @mock.patch('course_creators.admin.render_to_string', mock.Mock(side_effect=mock_render_to_string, autospec=True)) + @mock.patch('django.contrib.auth.models.User.email_user') + def test_change_status(self, email_user): """ - Tests that updates to state impact the creator group maintained in authz.py. + Tests that updates to state impact the creator group maintained in authz.py and that e-mails are sent. """ + STUDIO_REQUEST_EMAIL = 'mark@marky.mark' + def change_state(state, is_creator): """ Helper method for changing state """ self.table_entry.state = state self.creator_admin.save_model(self.request, self.table_entry, None, True) self.assertEqual(is_creator, is_user_in_creator_group(self.user)) + + context = {'studio_request_email': STUDIO_REQUEST_EMAIL} + if state == CourseCreator.GRANTED: + template = 'emails/course_creator_granted.txt' + elif state == CourseCreator.DENIED: + template = 'emails/course_creator_denied.txt' + else: + template = 'emails/course_creator_revoked.txt' + email_user.assert_called_with( + mock_render_to_string('emails/course_creator_subject.txt', context), + mock_render_to_string(template, context), + STUDIO_REQUEST_EMAIL + ) + + with mock.patch.dict( + 'django.conf.settings.MITX_FEATURES', + { + "ENABLE_CREATOR_GROUP": True, + "STUDIO_REQUEST_EMAIL": STUDIO_REQUEST_EMAIL + }): - with mock.patch.dict('django.conf.settings.MITX_FEATURES', {"ENABLE_CREATOR_GROUP": True}): # User is initially unrequested. self.assertFalse(is_user_in_creator_group(self.user)) diff --git a/cms/envs/common.py b/cms/envs/common.py index 0ca0d1b65f..f5baa3211b 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -42,8 +42,8 @@ MITX_FEATURES = { # do not display video when running automated acceptance tests 'STUB_VIDEO_FOR_TESTING': False, - # email address for staff (eg to request course creation) - 'STAFF_EMAIL': '', + # email address for studio staff (eg to request course creation) + 'STUDIO_REQUEST_EMAIL': '', 'STUDIO_NPS_SURVEY': True, diff --git a/cms/templates/emails/course_creator_denied.txt b/cms/templates/emails/course_creator_denied.txt new file mode 100644 index 0000000000..a2780ade74 --- /dev/null +++ b/cms/templates/emails/course_creator_denied.txt @@ -0,0 +1,5 @@ +<%! from django.utils.translation import ugettext as _ %> + +${_("Your request for course creation rights to edX Studio have been denied. If you believe this was in error, please contact: ")} + +${ studio_request_email } \ No newline at end of file diff --git a/cms/templates/emails/course_creator_granted.txt b/cms/templates/emails/course_creator_granted.txt new file mode 100644 index 0000000000..3c99fb3154 --- /dev/null +++ b/cms/templates/emails/course_creator_granted.txt @@ -0,0 +1,10 @@ +<%! from django.utils.translation import ugettext as _ %> + +${_("Your request for course creation rights to edX Studio have been granted! To create your first course, visit:")} + +% if is_secure: + https://${ site } +% else: + http://${ site } +% endif + diff --git a/cms/templates/emails/course_creator_revoked.txt b/cms/templates/emails/course_creator_revoked.txt new file mode 100644 index 0000000000..f9740b497b --- /dev/null +++ b/cms/templates/emails/course_creator_revoked.txt @@ -0,0 +1,5 @@ +<%! from django.utils.translation import ugettext as _ %> + +${_("Your request for course creation rights to edX Studio have been revoked. If you believe this was in error, please contact: ")} + +${ studio_request_email } \ No newline at end of file diff --git a/cms/templates/emails/course_creator_subject.txt b/cms/templates/emails/course_creator_subject.txt new file mode 100644 index 0000000000..35ec0ecc48 --- /dev/null +++ b/cms/templates/emails/course_creator_subject.txt @@ -0,0 +1,2 @@ +<%! from django.utils.translation import ugettext as _ %> +${_("Your course creator status for edX Studio")} diff --git a/cms/templates/index.html b/cms/templates/index.html index df3e467200..53c744c780 100644 --- a/cms/templates/index.html +++ b/cms/templates/index.html @@ -79,8 +79,8 @@ % if course_creator_status=='granted': ${_("New Course")} - % elif course_creator_status=='disallowed_for_this_site' and settings.MITX_FEATURES.get('STAFF_EMAIL',''): - ${_("Email staff to create course")} + % elif course_creator_status=='disallowed_for_this_site' and settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL',''): + ${_("Email staff to create course")} % endif @@ -252,10 +252,10 @@ - % if course_creator_status=='disallowed_for_this_site' and settings.MITX_FEATURES.get('STAFF_EMAIL',''): + % if course_creator_status=='disallowed_for_this_site' and settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL',''):

${_('Can I create courses in Studio?')}

-

${_('In order to create courses in Studio, you must')} ${_("contact edX staff to help you create a course")}

+

${_('In order to create courses in Studio, you must')} ${_("contact edX staff to help you create a course")}

% endif From 15665bbe5a7e3fb2539a6904a133db6aeb2803ad Mon Sep 17 00:00:00 2001 From: cahrens Date: Wed, 24 Jul 2013 13:02:25 -0400 Subject: [PATCH 2/4] Formatting updates. --- cms/templates/emails/course_creator_denied.txt | 2 +- cms/templates/emails/course_creator_granted.txt | 5 ++--- cms/templates/emails/course_creator_revoked.txt | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/cms/templates/emails/course_creator_denied.txt b/cms/templates/emails/course_creator_denied.txt index a2780ade74..739ece6b6f 100644 --- a/cms/templates/emails/course_creator_denied.txt +++ b/cms/templates/emails/course_creator_denied.txt @@ -2,4 +2,4 @@ ${_("Your request for course creation rights to edX Studio have been denied. If you believe this was in error, please contact: ")} -${ studio_request_email } \ No newline at end of file +${ studio_request_email } diff --git a/cms/templates/emails/course_creator_granted.txt b/cms/templates/emails/course_creator_granted.txt index 3c99fb3154..a33a9b9525 100644 --- a/cms/templates/emails/course_creator_granted.txt +++ b/cms/templates/emails/course_creator_granted.txt @@ -3,8 +3,7 @@ ${_("Your request for course creation rights to edX Studio have been granted! To create your first course, visit:")} % if is_secure: - https://${ site } +https://${ site } % else: - http://${ site } +http://${ site } % endif - diff --git a/cms/templates/emails/course_creator_revoked.txt b/cms/templates/emails/course_creator_revoked.txt index f9740b497b..f16f1ac328 100644 --- a/cms/templates/emails/course_creator_revoked.txt +++ b/cms/templates/emails/course_creator_revoked.txt @@ -2,4 +2,4 @@ ${_("Your request for course creation rights to edX Studio have been revoked. If you believe this was in error, please contact: ")} -${ studio_request_email } \ No newline at end of file +${ studio_request_email } From b5506cf20bbd5fee7a1204d2107d2dbc09a88218 Mon Sep 17 00:00:00 2001 From: cahrens Date: Mon, 29 Jul 2013 09:51:10 -0400 Subject: [PATCH 3/4] Copy changes. --- cms/templates/emails/course_creator_granted.txt | 2 +- cms/templates/emails/course_creator_revoked.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cms/templates/emails/course_creator_granted.txt b/cms/templates/emails/course_creator_granted.txt index a33a9b9525..a867f94334 100644 --- a/cms/templates/emails/course_creator_granted.txt +++ b/cms/templates/emails/course_creator_granted.txt @@ -1,6 +1,6 @@ <%! from django.utils.translation import ugettext as _ %> -${_("Your request for course creation rights to edX Studio have been granted! To create your first course, visit:")} +${_("Your request for course creation rights to edX Studio have been granted. To create your first course, visit:")} % if is_secure: https://${ site } diff --git a/cms/templates/emails/course_creator_revoked.txt b/cms/templates/emails/course_creator_revoked.txt index f16f1ac328..839c5a0d78 100644 --- a/cms/templates/emails/course_creator_revoked.txt +++ b/cms/templates/emails/course_creator_revoked.txt @@ -1,5 +1,5 @@ <%! from django.utils.translation import ugettext as _ %> -${_("Your request for course creation rights to edX Studio have been revoked. If you believe this was in error, please contact: ")} +${_("Your course creation rights to edX Studio have been revoked. If you believe this was in error, please contact: ")} ${ studio_request_email } From 087d35c95e7bfda31b406b9a3f0064b96955e0dc Mon Sep 17 00:00:00 2001 From: cahrens Date: Mon, 29 Jul 2013 13:01:37 -0400 Subject: [PATCH 4/4] Studio course creator e-mails. --- CHANGELOG.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 68308980ad..51a98f2de7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -5,6 +5,10 @@ These are notable changes in edx-platform. This is a rolling list of changes, in roughly chronological order, most recent first. Add your entries at or near the top. Include a label indicating the component affected. +Studio: Send e-mails to new Studio users (on edge only) when their course creator +status has changed. This will not be in use until the course creator table +is enabled. + LMS: Added user preferences (arbitrary user/key/value tuples, for which which user/key is unique) and a REST API for reading users and preferences. Access to the REST API is restricted by use of the