Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send IDV approval email in approve_id_verifications management command #34875

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions lms/djangoapps/verify_student/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
API module.
"""
from django.conf import settings
from django.utils.translation import gettext as _

from lms.djangoapps.verify_student.emails import send_verification_approved_email
from lms.djangoapps.verify_student.tasks import send_verification_status_email


def send_approval_email(attempt):
"""
Send an approval email to the learner associated with the IDV attempt.
"""
verification_status_email_vars = {
'platform_name': settings.PLATFORM_NAME,
}

expiration_datetime = attempt.expiration_datetime.date()
if settings.VERIFY_STUDENT.get('USE_DJANGO_MAIL'):
verification_status_email_vars['expiration_datetime'] = expiration_datetime.strftime("%m/%d/%Y")
verification_status_email_vars['full_name'] = attempt.user.profile.name
subject = _("Your {platform_name} ID verification was approved!").format(
platform_name=settings.PLATFORM_NAME
)
context = {
'subject': subject,
'template': 'emails/passed_verification_email.txt',
'email': attempt.user.email,
'email_vars': verification_status_email_vars
}
send_verification_status_email.delay(context)
else:
email_context = {'user': attempt.user, 'expiration_datetime': expiration_datetime.strftime("%m/%d/%Y")}
send_verification_approved_email(context=email_context)
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
from django.core.management.base import BaseCommand, CommandError

from lms.djangoapps.verify_student.api import send_approval_email
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
from lms.djangoapps.verify_student.utils import earliest_allowed_verification_date

Expand Down Expand Up @@ -125,8 +126,8 @@ def _approve_verifications_from_file(self, user_ids_file, batch_size, sleep_time

def _approve_id_verifications(self, user_ids):
"""
This command manually approves ID verification attempts for a provided set of learners whose ID verification
attempt is in the submitted or must_retry state.
This method manually approves ID verification attempts for a provided set of user IDs so long as the attempt
is in the submitted or must_retry state. This method also send an IDV approval email to the user.

Arguments:
user_ids (list): user IDs of the users whose ID verification attempt should be manually approved
Expand All @@ -148,5 +149,6 @@ def _approve_id_verifications(self, user_ids):

for verification in existing_id_verifications:
verification.approve(service='idv_verifications command')
send_approval_email(verification)

return list(failed_user_ids)
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import tempfile

import pytest
from django.core import mail
from django.core.management import CommandError, call_command
from django.test import TestCase
from testfixtures import LogCapture
Expand Down Expand Up @@ -70,6 +71,35 @@ def test_approve_id_verifications(self, status):

assert SoftwareSecurePhotoVerification.objects.filter(status='approved').count() == 3

@ddt.data('submitted', 'must_retry')
def test_approve_id_verifications_email(self, status):
"""
Tests that the approve_id_verifications management command correctly sends approval emails.
"""
# Create SoftwareSecurePhotoVerification instances for the users.
for user in [self.user1_profile, self.user2_profile]:
SoftwareSecurePhotoVerification.objects.create(
user=user.user,
name=user.name,
status=status,
)
SoftwareSecurePhotoVerification.objects.create(
user=self.user3_profile.user,
name=self.user3_profile.name,
status='denied',
)

call_command('approve_id_verifications', self.tmp_file_path)

assert len(mail.outbox) == 2

# All three emails should have equal expiration dates, so just pick one from an attempt.
expiration_date = SoftwareSecurePhotoVerification.objects.first().expiration_datetime
for email in mail.outbox:
assert email.subject == 'Your édX ID verification was approved!'
assert 'Your édX ID verification photos have been approved' in email.body
assert expiration_date.strftime("%m/%d/%Y") in email.body

def test_user_does_not_exist_log(self):
"""
Tests that the approve_id_verifications management command logs an error when an invalid user ID is
Expand Down
43 changes: 43 additions & 0 deletions lms/djangoapps/verify_student/tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""
Tests of API module.
"""
from unittest.mock import patch

import ddt
from django.conf import settings
from django.core import mail
from django.test import TestCase

from common.djangoapps.student.tests.factories import UserFactory
from lms.djangoapps.verify_student.api import send_approval_email
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification


@ddt.ddt
class TestSendApprovalEmail(TestCase):
"""
Test cases for the send_approval_email API method.
"""
def setUp(self):
super().setUp()

self.user = UserFactory.create()
self.attempt = SoftwareSecurePhotoVerification(
status="submitted",
user=self.user
)
self.attempt.save()

def _assert_verification_approved_email(self, expiration_date):
"""Check that a verification approved email was sent."""
assert len(mail.outbox) == 1
email = mail.outbox[0]
assert email.subject == 'Your édX ID verification was approved!'
assert 'Your édX ID verification photos have been approved' in email.body
assert expiration_date.strftime("%m/%d/%Y") in email.body

@ddt.data(True, False)
def test_send_approval(self, use_ace):
with patch.dict(settings.VERIFY_STUDENT, {'USE_DJANGO_MAIL': use_ace}):
send_approval_email(self.attempt)
self._assert_verification_approved_email(self.attempt.expiration_datetime)
22 changes: 3 additions & 19 deletions lms/djangoapps/verify_student/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
from common.djangoapps.util.json_request import JsonResponse
from common.djangoapps.util.views import require_global_staff
from lms.djangoapps.commerce.utils import EcommerceService, is_account_activation_requirement_disabled
from lms.djangoapps.verify_student.emails import send_verification_approved_email, send_verification_confirmation_email
from lms.djangoapps.verify_student.api import send_approval_email
from lms.djangoapps.verify_student.emails import send_verification_confirmation_email
from lms.djangoapps.verify_student.image import InvalidImageData, decode_image_data
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification, VerificationDeadline
from lms.djangoapps.verify_student.tasks import send_verification_status_email
Expand Down Expand Up @@ -1117,24 +1118,7 @@ def results_callback(request): # lint-amnesty, pylint: disable=too-many-stateme
log.info("[COSMO-184] Approved verification for receipt_id={receipt_id}.".format(receipt_id=receipt_id))
attempt.approve()

expiration_datetime = attempt.expiration_datetime.date()
if settings.VERIFY_STUDENT.get('USE_DJANGO_MAIL'):
verification_status_email_vars['expiration_datetime'] = expiration_datetime.strftime("%m/%d/%Y")
verification_status_email_vars['full_name'] = user.profile.name
subject = _("Your {platform_name} ID verification was approved!").format(
platform_name=settings.PLATFORM_NAME
)
context = {
'subject': subject,
'template': 'emails/passed_verification_email.txt',
'email': user.email,
'email_vars': verification_status_email_vars
}
send_verification_status_email.delay(context)
else:
email_context = {'user': user, 'expiration_datetime': expiration_datetime.strftime("%m/%d/%Y")}
send_verification_approved_email(context=email_context)

send_approval_email(attempt)
elif result == "FAIL":
log.debug("Denying verification for %s", receipt_id)

Expand Down
Loading