MST-157 Part 3 Create the Program Enrollments Inspector tool UI and link to the Support tool index page
This commit is contained in:
@@ -59,7 +59,7 @@ class ProgramEnrollmentSerializer(serializers.Serializer):
|
||||
model = ProgramEnrollment
|
||||
|
||||
|
||||
def serialize_user_info(user, user_social_auth=None):
|
||||
def serialize_user_info(user, user_social_auths=None):
|
||||
"""
|
||||
Helper method to serialize resulting in user_info_object
|
||||
based on passed in django models
|
||||
@@ -68,11 +68,9 @@ def serialize_user_info(user, user_social_auth=None):
|
||||
'username': user.username,
|
||||
'email': user.email,
|
||||
}
|
||||
if user_social_auth:
|
||||
_, external_key = user_social_auth.uid.split(':', 1)
|
||||
user_info['external_user_key'] = external_key
|
||||
user_info['sso'] = {
|
||||
'uid': user_social_auth.uid,
|
||||
'provider': user_social_auth.provider
|
||||
}
|
||||
if user_social_auths:
|
||||
for user_social_auth in user_social_auths:
|
||||
user_info.setdefault('sso_list', []).append({
|
||||
'uid': user_social_auth.uid,
|
||||
})
|
||||
return user_info
|
||||
|
||||
@@ -2,59 +2,227 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, InputText, StatusAlert, InputSelect } from '@edx/paragon';
|
||||
|
||||
export const ProgramEnrollmentsInspectorPage = props => (
|
||||
<form method="get">
|
||||
{props.errors.map(errorItem => (
|
||||
<StatusAlert
|
||||
open
|
||||
dismissible={false}
|
||||
alertType="danger"
|
||||
dialog={errorItem}
|
||||
/>
|
||||
))}
|
||||
<div key="edX_accounts">
|
||||
<InputText
|
||||
name="edx_user"
|
||||
label="edX account username or email"
|
||||
value={(props.learnerInfo && props.learnerInfo.user && props.learnerInfo.user.username) || ''}
|
||||
/>
|
||||
/*
|
||||
To improve the UI here, we should move this tool to the support Micro-Frontend.
|
||||
This work will be groomed and covered by MST-180
|
||||
*/
|
||||
const renderUserSection = userObj => (
|
||||
<div>
|
||||
<h3>edX account Info</h3>
|
||||
<div className="ml-5">
|
||||
<div><span className="font-weight-bold">Username</span>: {userObj.username}</div>
|
||||
<div><span className="font-weight-bold">Email</span>: {userObj.email}</div>
|
||||
{userObj.external_user_key && (
|
||||
<div>
|
||||
<span className="font-weight-bold">External User Key</span>
|
||||
: {userObj.external_user_key}
|
||||
</div>
|
||||
)}
|
||||
{userObj.sso_list ? (
|
||||
<div>
|
||||
<h4>List of Single Sign On Records: </h4>
|
||||
<ul>
|
||||
{userObj.sso_list.map(sso => (
|
||||
<li>{sso.uid}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
) : (
|
||||
<div> There is no Single Sign On record associated with this user!</div>
|
||||
)}
|
||||
</div>
|
||||
<div key="school_accounts">
|
||||
<InputSelect
|
||||
name="IdPSelect"
|
||||
label="Learner Account Providers"
|
||||
value="Select One"
|
||||
options={
|
||||
props.orgKeys
|
||||
}
|
||||
/>
|
||||
<hr />
|
||||
</div>
|
||||
);
|
||||
|
||||
<InputText
|
||||
name="external_user_key"
|
||||
label="Institution user key from school. For example, GTPersonDirectoryId for GT students"
|
||||
value={(props.learnerInfo && props.learnerInfo.user && props.learnerInfo.user.external_user_key) || ''}
|
||||
/>
|
||||
|
||||
const renderVerificationSection = verificationStatus => (
|
||||
<div>
|
||||
<h3>ID Verification</h3>
|
||||
<div className="ml-5">
|
||||
<div><span className="font-weight-bold">Status</span>: {verificationStatus.status}</div>
|
||||
{verificationStatus.error && (
|
||||
<div>
|
||||
<span className="font-weight-bold">Verification Error</span>: {verificationStatus.error}
|
||||
</div>
|
||||
)}
|
||||
{verificationStatus.verification_expiry && (
|
||||
<div>
|
||||
<span className="font-weight-bold">Verification Expiration Date</span>
|
||||
: {verificationStatus.verification_expiry}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Button label="Search" type="submit" className={['btn', 'btn-primary']} />
|
||||
</form>
|
||||
<hr />
|
||||
</div>
|
||||
);
|
||||
|
||||
const renderEnrollmentsSection = enrollments => (
|
||||
<div>
|
||||
<h3>Program Enrollments</h3>
|
||||
{enrollments.map(enrollment => (
|
||||
<div key={enrollment.program_uuid} className="ml-5">
|
||||
<h4>Program {enrollment.program_uuid} Enrollment</h4>
|
||||
<div> <span className="font-weight-bold">Status</span>: {enrollment.status} </div>
|
||||
<div> <span className="font-weight-bold">Created</span>: {enrollment.created} </div>
|
||||
<div> <span className="font-weight-bold">Last updated</span>: {enrollment.modified} </div>
|
||||
<div>
|
||||
<span className="font-weight-bold">External User Key</span>
|
||||
: {enrollment.external_user_key}
|
||||
</div>
|
||||
{enrollment.program_course_enrollments && enrollment.program_course_enrollments.map(
|
||||
programCourseEnrollment => (
|
||||
<div key={programCourseEnrollment.course_key} className="ml-5">
|
||||
<h4>Course {programCourseEnrollment.course_key}</h4>
|
||||
<div>
|
||||
<span className="font-weight-bold">Status</span>
|
||||
: {programCourseEnrollment.status}
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-weight-bold">Created</span>
|
||||
: {programCourseEnrollment.created}
|
||||
</div>
|
||||
<div>
|
||||
<span className="font-weight-bold">Last updated</span>
|
||||
: {programCourseEnrollment.modified}
|
||||
</div>
|
||||
{programCourseEnrollment.course_enrollment && (
|
||||
<div className="ml-5">
|
||||
<h4>Linked course enrollment</h4>
|
||||
<div><span className="font-weight-bold">Course ID</span>
|
||||
: {programCourseEnrollment.course_enrollment.course_id}
|
||||
</div>
|
||||
<div> <span className="font-weight-bold">Is Active</span>
|
||||
: {String(programCourseEnrollment.course_enrollment.is_active)}
|
||||
</div>
|
||||
<div> <span className="font-weight-bold">Mode / Track</span>
|
||||
: {programCourseEnrollment.course_enrollment.mode}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
<hr />
|
||||
</div>
|
||||
);
|
||||
|
||||
const validateInputs = () => {
|
||||
const inputEdxUser = self.document.getElementById('edx_user');
|
||||
const inputExternalKey = self.document.getElementById('external_key');
|
||||
const inputAlert = self.document.getElementById('input_alert');
|
||||
if (inputEdxUser.value && inputExternalKey.value) {
|
||||
inputAlert.removeAttribute('hidden');
|
||||
self.button.disabled = true;
|
||||
} else {
|
||||
inputAlert.setAttribute('hidden', '');
|
||||
self.button.disabled = false;
|
||||
}
|
||||
};
|
||||
|
||||
export const ProgramEnrollmentsInspectorPage = props => (
|
||||
<div>
|
||||
{JSON.stringify(props.learnerInfo) !== '{}' && (<h2> Search Results </h2>)}
|
||||
{props.learnerInfo.user &&
|
||||
renderUserSection(props.learnerInfo.user)}
|
||||
{props.learnerInfo.id_verification &&
|
||||
renderVerificationSection(props.learnerInfo.id_verification)}
|
||||
{props.learnerInfo.enrollments &&
|
||||
renderEnrollmentsSection(props.learnerInfo.enrollments)}
|
||||
<form method="get">
|
||||
<h2>Search For A Masters Learner Below</h2>
|
||||
{props.error && (
|
||||
<StatusAlert
|
||||
open
|
||||
dismissible={false}
|
||||
alertType="danger"
|
||||
dialog={props.error}
|
||||
/>
|
||||
)}
|
||||
<div id="input_alert" className={'alert alert-danger'} hidden>
|
||||
Search either by edx username or email, or Institution user key, but not both
|
||||
</div>
|
||||
<div key="edX_accounts">
|
||||
<InputText
|
||||
id="edx_user"
|
||||
name="edx_user"
|
||||
label="edX account username or email"
|
||||
onChange={validateInputs}
|
||||
/>
|
||||
</div>
|
||||
<div key="school_accounts">
|
||||
<InputSelect
|
||||
name="org_key"
|
||||
required
|
||||
label="Identity-providing institution"
|
||||
options={
|
||||
props.orgKeys
|
||||
}
|
||||
/>
|
||||
<InputText
|
||||
id="external_key"
|
||||
name="external_user_key"
|
||||
label="Institution user key from school. For example, GTPersonDirectoryId for GT students"
|
||||
onChange={validateInputs}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
id="search_button"
|
||||
label="Search"
|
||||
type="submit"
|
||||
className={['btn', 'btn-primary']}
|
||||
inputRef={(input) => { self.button = input; }}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
|
||||
ProgramEnrollmentsInspectorPage.propTypes = {
|
||||
errors: PropTypes.arrayOf(PropTypes.string),
|
||||
error: PropTypes.string,
|
||||
learnerInfo: PropTypes.shape({
|
||||
user: PropTypes.shape({
|
||||
external_user_key: PropTypes.string,
|
||||
username: PropTypes.string,
|
||||
email: PropTypes.email,
|
||||
external_user_key: PropTypes.string,
|
||||
sso_list: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
uid: PropTypes.string,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
id_verification: PropTypes.shape({
|
||||
status: PropTypes.string,
|
||||
error: PropTypes.string,
|
||||
verification_expiry: PropTypes.string,
|
||||
}),
|
||||
enrollments: PropTypes.arrayOf(
|
||||
PropTypes.string,
|
||||
PropTypes.shape({
|
||||
created: PropTypes.string,
|
||||
modified: PropTypes.string,
|
||||
program_uuid: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
external_user_key: PropTypes.string,
|
||||
program_course_enrollments: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
course_key: PropTypes.string,
|
||||
created: PropTypes.string,
|
||||
modified: PropTypes.string,
|
||||
status: PropTypes.string,
|
||||
course_enrollment: PropTypes.shape({
|
||||
course_id: PropTypes.string,
|
||||
is_active: PropTypes.bool,
|
||||
mode: PropTypes.string,
|
||||
}),
|
||||
})),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
orgKeys: PropTypes.arrayOf(PropTypes.object),
|
||||
orgKeys: PropTypes.arrayOf(PropTypes.string),
|
||||
};
|
||||
|
||||
ProgramEnrollmentsInspectorPage.defaultProps = {
|
||||
errors: [],
|
||||
error: '',
|
||||
learnerInfo: {},
|
||||
orgKeys: [],
|
||||
};
|
||||
|
||||
@@ -587,7 +587,9 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
def test_initial_rendering(self):
|
||||
response = self.client.get(self.url)
|
||||
content = six.text_type(response.content, encoding='utf-8')
|
||||
expected_organization_serialized = '"orgKeys": {}'.format(json.dumps(self.org_key_list))
|
||||
expected_organization_serialized = '"orgKeys": {}'.format(
|
||||
json.dumps(sorted(self.org_key_list))
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert expected_organization_serialized in content
|
||||
assert '"learnerInfo": {}' in content
|
||||
@@ -609,11 +611,9 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
uid='{0}:{1}'.format(org_key, external_user_key),
|
||||
provider='tpa-saml'
|
||||
)
|
||||
user_info['external_user_key'] = external_user_key
|
||||
user_info['sso'] = {
|
||||
'uid': user_social_auth.uid,
|
||||
'provider': user_social_auth.provider
|
||||
}
|
||||
user_info['sso_list'] = [{
|
||||
'uid': user_social_auth.uid
|
||||
}]
|
||||
return user, user_info
|
||||
|
||||
def _construct_enrollments(self, program_uuids, course_ids, external_user_key, edx_user=None):
|
||||
@@ -678,7 +678,8 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
created_user
|
||||
)
|
||||
self.client.get(self.url, data={
|
||||
'edx_user': created_user.username
|
||||
'edx_user': created_user.username,
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
expected_info = {
|
||||
'user': expected_user_info,
|
||||
@@ -693,7 +694,8 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
def test_search_username_user_not_connected(self, mocked_render):
|
||||
created_user, expected_user_info = self._construct_user('user_not_connected')
|
||||
self.client.get(self.url, data={
|
||||
'edx_user': created_user.email
|
||||
'edx_user': created_user.email,
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
expected_info = {
|
||||
'user': expected_user_info,
|
||||
@@ -711,7 +713,8 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
self.external_user_key
|
||||
)
|
||||
self.client.get(self.url, data={
|
||||
'edx_user': created_user.email
|
||||
'edx_user': created_user.email,
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
expected_info = {
|
||||
'user': expected_user_info,
|
||||
@@ -735,7 +738,8 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
created_user,
|
||||
)
|
||||
self.client.get(self.url, data={
|
||||
'edx_user': created_user.email
|
||||
'edx_user': created_user.email,
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
expected_info = {
|
||||
'user': expected_user_info,
|
||||
@@ -757,7 +761,8 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
self.external_user_key,
|
||||
)
|
||||
self.client.get(self.url, data={
|
||||
'edx_user': created_user.email
|
||||
'edx_user': created_user.email,
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
expected_info = {
|
||||
'user': expected_user_info,
|
||||
@@ -779,7 +784,8 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
}
|
||||
|
||||
self.client.get(self.url, data={
|
||||
'edx_user': created_user.email
|
||||
'edx_user': created_user.email,
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
|
||||
render_call_dict = mocked_render.call_args[0][1]
|
||||
@@ -801,7 +807,7 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
id_verified = self._construct_id_verification(created_user)
|
||||
self.client.get(self.url, data={
|
||||
'external_user_key': self.external_user_key,
|
||||
'IdPSelect': self.org_key_list[0]
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
expected_info = {
|
||||
'user': expected_user_info,
|
||||
@@ -813,27 +819,27 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
assert expected_info == render_call_dict['learner_program_enrollments']
|
||||
|
||||
@ddt.data(
|
||||
('aabbcc', ''),
|
||||
('', 'test_org')
|
||||
('', 'test_org'),
|
||||
('bad_key', '')
|
||||
)
|
||||
@ddt.unpack
|
||||
@patch_render
|
||||
def test_search_external_key_no_idp(self, user_key_input, idp_input, mocked_render):
|
||||
def test_search_no_external_user_key(self, user_key, org_key, mocked_render):
|
||||
self.client.get(self.url, data={
|
||||
'external_user_key': user_key_input,
|
||||
'IdPSelect': idp_input,
|
||||
'external_user_key': user_key,
|
||||
'org_key': org_key,
|
||||
})
|
||||
|
||||
expected_errors = [
|
||||
expected_error = (
|
||||
"To perform a search, you must provide either the student's "
|
||||
"(a) edX username, "
|
||||
"(b) email address associated with their edX account, or "
|
||||
"(c) Identity-providing institution and external key!"
|
||||
]
|
||||
)
|
||||
|
||||
render_call_dict = mocked_render.call_args[0][1]
|
||||
assert {} == render_call_dict['learner_program_enrollments']
|
||||
assert expected_errors == render_call_dict['errors']
|
||||
assert expected_error == render_call_dict['error']
|
||||
|
||||
@patch_render
|
||||
def test_search_external_user_not_connected(self, mocked_render):
|
||||
@@ -844,9 +850,12 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
)
|
||||
self.client.get(self.url, data={
|
||||
'external_user_key': self.external_user_key,
|
||||
'IdPSelect': self.org_key_list[0]
|
||||
'org_key': self.org_key_list[0]
|
||||
})
|
||||
expected_info = {
|
||||
'user': {
|
||||
'external_user_key': self.external_user_key,
|
||||
},
|
||||
'enrollments': expected_enrollments
|
||||
}
|
||||
|
||||
@@ -858,13 +867,11 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase):
|
||||
external_user_key = 'not_in_system'
|
||||
self.client.get(self.url, data={
|
||||
'external_user_key': external_user_key,
|
||||
'IdPSelect': self.org_key_list[0],
|
||||
'org_key': self.org_key_list[0],
|
||||
})
|
||||
|
||||
expected_errors = [
|
||||
'No user found for external key {} for institution {}'.format(
|
||||
external_user_key, self.org_key_list[0]
|
||||
)
|
||||
]
|
||||
expected_error = 'No user found for external key {} for institution {}'.format(
|
||||
external_user_key, self.org_key_list[0]
|
||||
)
|
||||
render_call_dict = mocked_render.call_args[0][1]
|
||||
assert expected_errors == render_call_dict['errors']
|
||||
assert expected_error == render_call_dict['error']
|
||||
|
||||
@@ -48,6 +48,11 @@ SUPPORT_INDEX_URLS = [
|
||||
"name": _("Link Program Enrollments"),
|
||||
"description": _("Link LMS users to program enrollments"),
|
||||
},
|
||||
{
|
||||
"url": reverse_lazy("support:program_enrollments_inspector"),
|
||||
"name": _("Program Enrollments Inspector Tool"),
|
||||
"description": _("Find information related to a learner's program enrollments"),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -134,28 +134,35 @@ class ProgramEnrollmentsInspectorView(View):
|
||||
Search the data store for information about ProgramEnrollment and
|
||||
SSO linkage with the user.
|
||||
"""
|
||||
errors = []
|
||||
search_error = ''
|
||||
edx_username_or_email = request.GET.get('edx_user', '').strip()
|
||||
org_key = request.GET.get('IdPSelect', '').strip()
|
||||
org_key = request.GET.get('org_key', '').strip()
|
||||
external_user_key = request.GET.get('external_user_key', '').strip()
|
||||
learner_program_enrollments = {}
|
||||
saml_providers_with_org_key = self._get_org_keys_and_idps()
|
||||
selected_provider = None
|
||||
if org_key:
|
||||
selected_provider = saml_providers_with_org_key.get(org_key)
|
||||
if edx_username_or_email:
|
||||
learner_program_enrollments, error = self._get_account_info(edx_username_or_email)
|
||||
if error:
|
||||
errors.append(error)
|
||||
learner_program_enrollments, search_error = self._get_account_info(
|
||||
edx_username_or_email,
|
||||
selected_provider,
|
||||
)
|
||||
elif org_key and external_user_key:
|
||||
learner_program_enrollments = self._get_external_user_info(
|
||||
external_user_key,
|
||||
org_key
|
||||
org_key,
|
||||
selected_provider,
|
||||
)
|
||||
if not learner_program_enrollments:
|
||||
errors.append(
|
||||
'No user found for external key {} for institution {}'.format(
|
||||
external_user_key, org_key
|
||||
)
|
||||
search_error = 'No user found for external key {} for institution {}'.format(
|
||||
external_user_key, org_key
|
||||
)
|
||||
elif not org_key and not external_user_key:
|
||||
# This is initial rendering state.
|
||||
pass
|
||||
else:
|
||||
errors.append(
|
||||
search_error = (
|
||||
"To perform a search, you must provide either the student's "
|
||||
"(a) edX username, "
|
||||
"(b) email address associated with their edX account, or "
|
||||
@@ -165,38 +172,39 @@ class ProgramEnrollmentsInspectorView(View):
|
||||
return render_to_response(
|
||||
self.CONSOLE_TEMPLATE_PATH,
|
||||
{
|
||||
'errors': errors,
|
||||
'error': search_error,
|
||||
'learner_program_enrollments': learner_program_enrollments,
|
||||
'org_keys': self._get_org_keys_with_idp(),
|
||||
'org_keys': sorted(saml_providers_with_org_key.keys()),
|
||||
}
|
||||
)
|
||||
|
||||
def _get_org_keys_with_idp(self):
|
||||
def _get_org_keys_and_idps(self):
|
||||
"""
|
||||
From our Third_party_auth models, return a list
|
||||
of organizations whose SAMLProviders are active and configured
|
||||
From our Third_party_auth models, return a dictionary of
|
||||
of organizations keys and their correspondingactive and configured SAMLProviders
|
||||
"""
|
||||
saml_providers = SAMLProviderConfig.objects.current_set().filter(
|
||||
enabled=True,
|
||||
organization__isnull=False
|
||||
).select_related('organization')
|
||||
|
||||
return [saml_provider.organization.short_name for saml_provider in saml_providers]
|
||||
return {
|
||||
saml_provider.organization.short_name: saml_provider for saml_provider in saml_providers
|
||||
}
|
||||
|
||||
def _get_account_info(self, username_or_email):
|
||||
def _get_account_info(self, username_or_email, idp_provider=None):
|
||||
"""
|
||||
Provided the edx account username or email, return edx account info
|
||||
and program_enrollments_info. If we cannot identify the user, return
|
||||
empty object and error.
|
||||
Provided the edx account username or email, and the SAML provider selected,
|
||||
return edx account info and program_enrollments_info.
|
||||
If we cannot identify the user, return empty object and error.
|
||||
"""
|
||||
try:
|
||||
user = User.objects.get(Q(username=username_or_email) | Q(email=username_or_email))
|
||||
user_social_auth = None
|
||||
try:
|
||||
user_social_auth = UserSocialAuth.objects.get(user=user)
|
||||
except UserSocialAuth.DoesNotExist:
|
||||
pass
|
||||
user_info = serialize_user_info(user, user_social_auth)
|
||||
user_social_auths = None
|
||||
user_social_auths = UserSocialAuth.objects.filter(user=user)
|
||||
if idp_provider:
|
||||
user_social_auths = user_social_auths.filter(provider=idp_provider.backend_name)
|
||||
user_info = serialize_user_info(user, user_social_auths)
|
||||
enrollments = self._get_enrollments(user=user)
|
||||
result = {'user': user_info}
|
||||
if enrollments:
|
||||
@@ -207,7 +215,7 @@ class ProgramEnrollmentsInspectorView(View):
|
||||
except User.DoesNotExist:
|
||||
return {}, 'Could not find edx account with {}'.format(username_or_email)
|
||||
|
||||
def _get_external_user_info(self, external_user_key, org_key):
|
||||
def _get_external_user_info(self, external_user_key, org_key, idp_provider=None):
|
||||
"""
|
||||
Provided the external_user_key and org_key, return edx account info
|
||||
and program_enrollments_info if any. If we cannot identify the data,
|
||||
@@ -229,17 +237,19 @@ class ProgramEnrollmentsInspectorView(View):
|
||||
# We cannot identify edX user from external_user_key and org_key pair
|
||||
pass
|
||||
|
||||
if found_user:
|
||||
try:
|
||||
user_social_auth = UserSocialAuth.objects.get(user=found_user)
|
||||
except UserSocialAuth.DoesNotExist:
|
||||
user_social_auth = None
|
||||
user_info = serialize_user_info(found_user, user_social_auth)
|
||||
result['user'] = user_info
|
||||
result['id_verification'] = IDVerificationService.user_status(found_user)
|
||||
enrollments = self._get_enrollments(external_user_key=external_user_key)
|
||||
if enrollments:
|
||||
result['enrollments'] = enrollments
|
||||
if found_user:
|
||||
user_social_auths = UserSocialAuth.objects.filter(user=found_user)
|
||||
if idp_provider:
|
||||
user_social_auths = user_social_auths.filter(provider=idp_provider.backend_name)
|
||||
user_info = serialize_user_info(found_user, user_social_auths)
|
||||
result['user'] = user_info
|
||||
result['id_verification'] = IDVerificationService.user_status(found_user)
|
||||
elif 'enrollments' in result:
|
||||
result['user'] = {'external_user_key': external_user_key}
|
||||
|
||||
return result
|
||||
|
||||
def _get_enrollments(self, user=None, external_user_key=None):
|
||||
|
||||
@@ -21,16 +21,15 @@ from openedx.core.djangolib.js_utils import js_escaped_string
|
||||
|
||||
<%block name="content">
|
||||
<section class="container outside-app">
|
||||
<h3> Program Enrollments Inspector </h3>
|
||||
<h1> Program Enrollments Inspector </h1>
|
||||
${static.renderReact(
|
||||
component="ProgramEnrollmentsInspectorPage",
|
||||
id="entitlement-support-page",
|
||||
id="program-enrollments-inspector-page",
|
||||
props={
|
||||
'errors': errors,
|
||||
'error': error,
|
||||
'learnerInfo': learner_program_enrollments,
|
||||
'orgKeys': org_keys
|
||||
}
|
||||
)
|
||||
}
|
||||
)}
|
||||
</section>
|
||||
</%block>
|
||||
|
||||
Reference in New Issue
Block a user