add lms user id in accounts endpoint
This commit is contained in:
@@ -3885,6 +3885,7 @@ ACCOUNT_VISIBILITY_CONFIGURATION["custom_shareable_fields"] = (
|
|||||||
ACCOUNT_VISIBILITY_CONFIGURATION["admin_fields"] = (
|
ACCOUNT_VISIBILITY_CONFIGURATION["admin_fields"] = (
|
||||||
ACCOUNT_VISIBILITY_CONFIGURATION["custom_shareable_fields"] + [
|
ACCOUNT_VISIBILITY_CONFIGURATION["custom_shareable_fields"] + [
|
||||||
"email",
|
"email",
|
||||||
|
"id",
|
||||||
"extended_profile",
|
"extended_profile",
|
||||||
"gender",
|
"gender",
|
||||||
"state",
|
"state",
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ class PhoneNumberSerializer(serializers.BaseSerializer): # lint-amnesty, pylint
|
|||||||
"""
|
"""
|
||||||
Class to serialize phone number into a digit only representation
|
Class to serialize phone number into a digit only representation
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
def to_internal_value(self, data):
|
||||||
"""Remove all non numeric characters in phone number"""
|
"""Remove all non numeric characters in phone number"""
|
||||||
return re.sub("[^0-9]", "", data) or None
|
return re.sub("[^0-9]", "", data) or None
|
||||||
@@ -94,6 +95,7 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
|
|||||||
"""
|
"""
|
||||||
Class that serializes the User model and UserProfile model together.
|
Class that serializes the User model and UserProfile model together.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
# Don't pass the 'configuration' arg up to the superclass
|
# Don't pass the 'configuration' arg up to the superclass
|
||||||
self.configuration = kwargs.pop('configuration', None)
|
self.configuration = kwargs.pop('configuration', None)
|
||||||
@@ -129,6 +131,7 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
|
|||||||
reverse('accounts_api', kwargs={'username': user.username})
|
reverse('accounts_api', kwargs={'username': user.username})
|
||||||
),
|
),
|
||||||
"email": user.email,
|
"email": user.email,
|
||||||
|
"id": user.id,
|
||||||
# For backwards compatibility: Tables created after the upgrade to Django 1.8 will save microseconds.
|
# For backwards compatibility: Tables created after the upgrade to Django 1.8 will save microseconds.
|
||||||
# However, mobile apps are not expecting microsecond in the serialized value. If we set it to zero the
|
# However, mobile apps are not expecting microsecond in the serialized value. If we set it to zero the
|
||||||
# DRF JSONEncoder will not include it in the serialized value.
|
# DRF JSONEncoder will not include it in the serialized value.
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ class TestAccountApi(UserSettingsEventTestMixin, EmailTemplateTagMixin, CreateAc
|
|||||||
|
|
||||||
account_settings = get_account_settings(self.default_request)[0]
|
account_settings = get_account_settings(self.default_request)[0]
|
||||||
assert account_settings['social_links'] == \
|
assert account_settings['social_links'] == \
|
||||||
sorted((original_social_links + extra_social_links), key=(lambda s: s['platform']))
|
sorted((original_social_links + extra_social_links), key=(lambda s: s['platform']))
|
||||||
|
|
||||||
def test_replace_social_links(self):
|
def test_replace_social_links(self):
|
||||||
original_facebook_link = dict(platform="facebook", social_link="https://www.facebook.com/myself")
|
original_facebook_link = dict(platform="facebook", social_link="https://www.facebook.com/myself")
|
||||||
@@ -505,12 +505,14 @@ class AccountSettingsOnCreationTest(CreateAccountMixin, TestCase):
|
|||||||
USERNAME = u'frank-underwood'
|
USERNAME = u'frank-underwood'
|
||||||
PASSWORD = u'ṕáśśẃőŕd'
|
PASSWORD = u'ṕáśśẃőŕd'
|
||||||
EMAIL = u'frank+underwood@example.com'
|
EMAIL = u'frank+underwood@example.com'
|
||||||
|
ID = -1
|
||||||
|
|
||||||
def test_create_account(self):
|
def test_create_account(self):
|
||||||
# Create a new account, which should have empty account settings by default.
|
# Create a new account, which should have empty account settings by default.
|
||||||
self.create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
|
self.create_account(self.USERNAME, self.PASSWORD, self.EMAIL)
|
||||||
# Retrieve the account settings
|
# Retrieve the account settings
|
||||||
user = User.objects.get(username=self.USERNAME)
|
user = User.objects.get(username=self.USERNAME)
|
||||||
|
self.ID = user.id
|
||||||
request = RequestFactory().get("/api/user/v1/accounts/")
|
request = RequestFactory().get("/api/user/v1/accounts/")
|
||||||
request.user = user
|
request.user = user
|
||||||
account_settings = get_account_settings(request)[0]
|
account_settings = get_account_settings(request)[0]
|
||||||
@@ -522,32 +524,36 @@ class AccountSettingsOnCreationTest(CreateAccountMixin, TestCase):
|
|||||||
del account_settings['last_login']
|
del account_settings['last_login']
|
||||||
|
|
||||||
# Expect all the values to be defaulted
|
# Expect all the values to be defaulted
|
||||||
assert account_settings ==\
|
assert account_settings == {
|
||||||
{'username': self.USERNAME,
|
'username': self.USERNAME,
|
||||||
'email': self.EMAIL,
|
'email': self.EMAIL,
|
||||||
'name': self.USERNAME,
|
'id': self.ID,
|
||||||
'gender': None, 'goals': u'',
|
'name': self.USERNAME,
|
||||||
'is_active': False,
|
'gender': None, 'goals': u'',
|
||||||
'level_of_education': None,
|
'is_active': False,
|
||||||
'mailing_address': u'',
|
'level_of_education': None,
|
||||||
'year_of_birth': None,
|
'mailing_address': u'',
|
||||||
'country': None,
|
'year_of_birth': None,
|
||||||
'state': None,
|
'country': None,
|
||||||
'social_links': [],
|
'state': None,
|
||||||
'bio': None,
|
'social_links': [],
|
||||||
'profile_image': {'has_image': False,
|
'bio': None,
|
||||||
'image_url_full': request.build_absolute_uri('/static/default_50.png'),
|
'profile_image': {
|
||||||
'image_url_small': request.build_absolute_uri('/static/default_10.png')},
|
'has_image': False,
|
||||||
'requires_parental_consent': True,
|
'image_url_full': request.build_absolute_uri('/static/default_50.png'),
|
||||||
'language_proficiencies': [],
|
'image_url_small': request.build_absolute_uri('/static/default_10.png')
|
||||||
'account_privacy': PRIVATE_VISIBILITY,
|
},
|
||||||
'accomplishments_shared': False,
|
'requires_parental_consent': True,
|
||||||
'extended_profile': [],
|
'language_proficiencies': [],
|
||||||
'secondary_email': None,
|
'account_privacy': PRIVATE_VISIBILITY,
|
||||||
'secondary_email_enabled': None,
|
'accomplishments_shared': False,
|
||||||
'time_zone': None,
|
'extended_profile': [],
|
||||||
'course_certificates': None,
|
'secondary_email': None,
|
||||||
'phone_number': None}
|
'secondary_email_enabled': None,
|
||||||
|
'time_zone': None,
|
||||||
|
'course_certificates': None,
|
||||||
|
'phone_number': None
|
||||||
|
}
|
||||||
|
|
||||||
def test_normalize_password(self):
|
def test_normalize_password(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
|||||||
Verify that all account fields are returned (even those that are not shareable).
|
Verify that all account fields are returned (even those that are not shareable).
|
||||||
"""
|
"""
|
||||||
data = response.data
|
data = response.data
|
||||||
assert 26 == len(data)
|
assert 27 == len(data)
|
||||||
|
|
||||||
# public fields (3)
|
# public fields (3)
|
||||||
expected_account_privacy = (
|
expected_account_privacy = (
|
||||||
@@ -285,8 +285,9 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
|||||||
assert data['accomplishments_shared'] is not None
|
assert data['accomplishments_shared'] is not None
|
||||||
assert ((self.user.first_name + ' ') + self.user.last_name) == data['name']
|
assert ((self.user.first_name + ' ') + self.user.last_name) == data['name']
|
||||||
|
|
||||||
# additional admin fields (10)
|
# additional admin fields (11)
|
||||||
assert self.user.email == data['email']
|
assert self.user.email == data['email']
|
||||||
|
assert self.user.id == data['id']
|
||||||
assert data['extended_profile'] is not None
|
assert data['extended_profile'] is not None
|
||||||
assert 'MA' == data['state']
|
assert 'MA' == data['state']
|
||||||
assert 'f' == data['gender']
|
assert 'f' == data['gender']
|
||||||
@@ -493,7 +494,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
|||||||
with self.assertNumQueries(queries):
|
with self.assertNumQueries(queries):
|
||||||
response = self.send_get(self.client)
|
response = self.send_get(self.client)
|
||||||
data = response.data
|
data = response.data
|
||||||
assert 26 == len(data)
|
assert 27 == len(data)
|
||||||
assert self.user.username == data['username']
|
assert self.user.username == data['username']
|
||||||
assert ((self.user.first_name + ' ') + self.user.last_name) == data['name']
|
assert ((self.user.first_name + ' ') + self.user.last_name) == data['name']
|
||||||
for empty_field in ("year_of_birth", "level_of_education", "mailing_address", "bio"):
|
for empty_field in ("year_of_birth", "level_of_education", "mailing_address", "bio"):
|
||||||
@@ -503,6 +504,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
|||||||
assert 'm' == data['gender']
|
assert 'm' == data['gender']
|
||||||
assert 'Learn a lot' == data['goals']
|
assert 'Learn a lot' == data['goals']
|
||||||
assert self.user.email == data['email']
|
assert self.user.email == data['email']
|
||||||
|
assert self.user.id == data['id']
|
||||||
assert data['date_joined'] is not None
|
assert data['date_joined'] is not None
|
||||||
assert data['last_login'] is not None
|
assert data['last_login'] is not None
|
||||||
assert self.user.is_active == data['is_active']
|
assert self.user.is_active == data['is_active']
|
||||||
@@ -846,7 +848,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
|||||||
client = self.login_client("client", "user")
|
client = self.login_client("client", "user")
|
||||||
response = self.send_patch(client, {"language_proficiencies": patch_value}, expected_status=400)
|
response = self.send_patch(client, {"language_proficiencies": patch_value}, expected_status=400)
|
||||||
assert response.data['field_errors']['language_proficiencies']['developer_message'] == \
|
assert response.data['field_errors']['language_proficiencies']['developer_message'] == \
|
||||||
f"Value '{patch_value}' is not valid for field 'language_proficiencies': {expected_error_message}"
|
f"Value '{patch_value}' is not valid for field 'language_proficiencies': {expected_error_message}"
|
||||||
|
|
||||||
@mock.patch('openedx.core.djangoapps.user_api.accounts.serializers.AccountUserSerializer.save')
|
@mock.patch('openedx.core.djangoapps.user_api.accounts.serializers.AccountUserSerializer.save')
|
||||||
def test_patch_serializer_save_fails(self, serializer_save):
|
def test_patch_serializer_save_fails(self, serializer_save):
|
||||||
@@ -869,8 +871,8 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
|||||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||||
response = self.send_get(self.client)
|
response = self.send_get(self.client)
|
||||||
assert response.data['profile_image'] ==\
|
assert response.data['profile_image'] ==\
|
||||||
{'has_image': False,
|
{'has_image': False,
|
||||||
'image_url_full': 'http://testserver/static/default_50.png',
|
'image_url_full': 'http://testserver/static/default_50.png',
|
||||||
'image_url_small': 'http://testserver/static/default_10.png'}
|
'image_url_small': 'http://testserver/static/default_10.png'}
|
||||||
|
|
||||||
@ddt.data(
|
@ddt.data(
|
||||||
@@ -892,10 +894,11 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
|||||||
response = self.send_get(client)
|
response = self.send_get(client)
|
||||||
if has_full_access:
|
if has_full_access:
|
||||||
data = response.data
|
data = response.data
|
||||||
assert 26 == len(data)
|
assert 27 == len(data)
|
||||||
assert self.user.username == data['username']
|
assert self.user.username == data['username']
|
||||||
assert ((self.user.first_name + ' ') + self.user.last_name) == data['name']
|
assert ((self.user.first_name + ' ') + self.user.last_name) == data['name']
|
||||||
assert self.user.email == data['email']
|
assert self.user.email == data['email']
|
||||||
|
assert self.user.id == data['id']
|
||||||
assert year_of_birth == data['year_of_birth']
|
assert year_of_birth == data['year_of_birth']
|
||||||
for empty_field in ("country", "level_of_education", "mailing_address", "bio", "state",):
|
for empty_field in ("country", "level_of_education", "mailing_address", "bio", "state",):
|
||||||
assert data[empty_field] is None
|
assert data[empty_field] is None
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ class AccountViewSet(ViewSet):
|
|||||||
"OK" response is returned. The response contains the following
|
"OK" response is returned. The response contains the following
|
||||||
values.
|
values.
|
||||||
|
|
||||||
|
* id: numerical lms user id in db
|
||||||
* bio: null or textual representation of user biographical
|
* bio: null or textual representation of user biographical
|
||||||
information ("about me").
|
information ("about me").
|
||||||
* country: An ISO 3166 country code or null.
|
* country: An ISO 3166 country code or null.
|
||||||
|
|||||||
Reference in New Issue
Block a user