Link program enrollments on social auth updates in add. to creation

See
lms/djangoapps/program_enrollments/docs/decisions/0002-matriculation-on-user_social_auth_change.rst
for more details

JIRA:EDUCATOR-4770
This commit is contained in:
Matt Hughes
2019-10-29 14:56:49 -04:00
committed by Matt Hughes
parent 3858036a4e
commit cfbfe35904
3 changed files with 84 additions and 3 deletions

View File

@@ -0,0 +1,60 @@
Matriculation on UserSocialAuth Changes
---------------------------------------
Status
======
Accepted (circa October 2019)
Context
=======
Georgia Tech has been enrolling learners into its Master's programs
for a long time, using enterprise-oriented APIs for the purpose. To
transition them to using our Master's-intended workflow, we've worked
out a plan with them to convert existing ``UserSocialAuth`` records to use
a different SAML-provided field as the canonical UID used elsewhere in
our system to identify the learner for program enrollment
purposes. Thus, we've already decided we'll need a one-time management
command to update these learners' User SocialAuth records to use the
new UID.
The scope of this decision is a particular snag in how program
enrollments are linked to learner accounts. Namely, this linking only
occurs on the creation of a ``UserSocialAuth`` record, and not in
response to the kind of update we're proposing to perform with our
management command.
Decisions
=========
To address this concern and to achieve greater flexibility of program
enrollments into the future, we will attempt to link program
enrollments to learner accounts upon any change to a
``UserSocialAuth`` record, rather than solely on creation.
Consequences
============
This may have a performance impact, since updates to
``UserSocialAuth`` records happen often at times which would not
benefit us. We anticipate this performance impact will be fairly
minimal given the current indices on the table, however.
This does enable us to keep the management command simple. It also
enables us to re-trigger program enrollment linking on demand by
making trivial changes to the ``UserSocialAuth`` record, which may be
helpful for support purposes.
Alternatives
============
We also considered, but rejected the following possibilities:
1) Switch our ``post_save`` signal handler to ``pre_save``, and diff
the model fields on updates to determine whether we've changed the
UID.
2) Make the management command more complex, and have it call the
program enrollment-linking code itself rather than relying on these
signals.

View File

@@ -33,9 +33,6 @@ def listen_for_social_auth_creation(sender, instance, created, **kwargs): # pyl
"""
Post-save signal that will attempt to link a social auth entry with waiting enrollments
"""
if not created:
return
try:
matriculate_learner(instance.user, instance.uid)
except Exception as e:

View File

@@ -171,6 +171,30 @@ class SocialAuthEnrollmentCompletionSignalTest(CacheIsolationTestCase):
self.assertEqual(student_course_enrollment.course.id, program_course_enrollment.course_key)
self.assertEqual(student_course_enrollment.mode, mode)
def test_update_social_auth(self):
"""
Makes sure we can update a social_auth row to trigger the same program enrollments
"""
program_enrollment = self._create_waiting_program_enrollment()
program_course_enrollments = self._create_waiting_course_enrollments(program_enrollment)
user_social_auth = UserSocialAuth.objects.create(
user=self.user,
uid='{0}:{1}'.format(self.provider_slug, 'gobbledegook')
)
# Not yet a thing, didn't match
program_enrollment.refresh_from_db()
self.assertIsNone(program_enrollment.user)
user_social_auth.uid = '{0}:{1}'.format(self.provider_slug, self.external_id)
user_social_auth.save()
# now we see the enrollments realized
self._assert_program_enrollment_user(program_enrollment, self.user)
for program_course_enrollment in program_course_enrollments:
self._assert_program_course_enrollment(program_course_enrollment)
def test_waiting_course_enrollments_completed(self):
program_enrollment = self._create_waiting_program_enrollment()
program_course_enrollments = self._create_waiting_course_enrollments(program_enrollment)