Merge pull request #488 from edx/christina/emails
Send e-mails when course creator status changes.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
5
cms/templates/emails/course_creator_denied.txt
Normal file
5
cms/templates/emails/course_creator_denied.txt
Normal file
@@ -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 }
|
||||
9
cms/templates/emails/course_creator_granted.txt
Normal file
9
cms/templates/emails/course_creator_granted.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
<%! 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
|
||||
5
cms/templates/emails/course_creator_revoked.txt
Normal file
5
cms/templates/emails/course_creator_revoked.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
${_("Your course creation rights to edX Studio have been revoked. If you believe this was in error, please contact: ")}
|
||||
|
||||
${ studio_request_email }
|
||||
2
cms/templates/emails/course_creator_subject.txt
Normal file
2
cms/templates/emails/course_creator_subject.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
${_("Your course creator status for edX Studio")}
|
||||
@@ -79,8 +79,8 @@
|
||||
% if course_creator_status=='granted':
|
||||
<a href="#" class="button new-button new-course-button"><i class="icon-plus icon-inline"></i>
|
||||
${_("New Course")}</a>
|
||||
% elif course_creator_status=='disallowed_for_this_site' and settings.MITX_FEATURES.get('STAFF_EMAIL',''):
|
||||
<a href="mailto:${settings.MITX_FEATURES.get('STAFF_EMAIL','')}">${_("Email staff to create course")}</a>
|
||||
% elif course_creator_status=='disallowed_for_this_site' and settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL',''):
|
||||
<a href="mailto:${settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL','')}">${_("Email staff to create course")}</a>
|
||||
% endif
|
||||
</li>
|
||||
</ul>
|
||||
@@ -252,10 +252,10 @@
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
% 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',''):
|
||||
<div class="bit">
|
||||
<h3 class="title title-3">${_('Can I create courses in Studio?')}</h3>
|
||||
<p>${_('In order to create courses in Studio, you must')} <a href="mailto:${settings.MITX_FEATURES.get('STAFF_EMAIL','')}">${_("contact edX staff to help you create a course")}</a></p>
|
||||
<p>${_('In order to create courses in Studio, you must')} <a href="mailto:${settings.MITX_FEATURES.get('STUDIO_REQUEST_EMAIL','')}">${_("contact edX staff to help you create a course")}</a></p>
|
||||
</div>
|
||||
% endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user