Merge pull request #29952 from openedx/bseverino/name-affirmation-plugin
[MST-1360] Only enable verified name feature if Name Affirmation is installed
This commit is contained in:
@@ -11,7 +11,6 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.validators import ValidationError, validate_email
|
||||
from django.utils.translation import override as override_language
|
||||
from django.utils.translation import gettext as _
|
||||
from edx_name_affirmation.name_change_validator import NameChangeValidator
|
||||
from pytz import UTC
|
||||
from common.djangoapps.student import views as student_views
|
||||
from common.djangoapps.student.models import (
|
||||
@@ -38,8 +37,14 @@ from openedx.core.djangoapps.user_authn.utils import check_pwned_password
|
||||
from openedx.core.djangoapps.user_authn.views.registration_form import validate_name, validate_username
|
||||
from openedx.core.lib.api.view_utils import add_serializer_errors
|
||||
from openedx.features.enterprise_support.utils import get_enterprise_readonly_account_fields
|
||||
from openedx.features.name_affirmation_api.utils import is_name_affirmation_installed
|
||||
from .serializers import AccountLegacyProfileSerializer, AccountUserSerializer, UserReadOnlySerializer, _visible_fields
|
||||
|
||||
name_affirmation_installed = is_name_affirmation_installed()
|
||||
if name_affirmation_installed:
|
||||
# pylint: disable=import-error
|
||||
from edx_name_affirmation.name_change_validator import NameChangeValidator
|
||||
|
||||
# Public access point for this function.
|
||||
visible_fields = _visible_fields
|
||||
|
||||
@@ -274,6 +279,9 @@ def _does_name_change_require_verification(user_profile, old_name, new_name):
|
||||
"""
|
||||
If name change requires ID verification, do not update it through this API.
|
||||
"""
|
||||
if not name_affirmation_installed:
|
||||
return False
|
||||
|
||||
profile_meta = user_profile.get_meta()
|
||||
old_names_list = profile_meta['old_names'] if 'old_names' in profile_meta else []
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ from django.conf import settings
|
||||
from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.urls import reverse
|
||||
from edx_name_affirmation.api import get_verified_name
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
@@ -29,6 +28,7 @@ from openedx.core.djangoapps.user_api.accounts.utils import is_secondary_email_f
|
||||
from openedx.core.djangoapps.user_api.models import RetirementState, UserPreference, UserRetirementStatus
|
||||
from openedx.core.djangoapps.user_api.serializers import ReadOnlyFieldsSerializerMixin
|
||||
from openedx.core.djangoapps.user_authn.views.registration_form import contains_html, contains_url
|
||||
from openedx.features.name_affirmation_api.utils import get_name_affirmation_service
|
||||
|
||||
from . import (
|
||||
ACCOUNT_VISIBILITY_PREF_KEY,
|
||||
@@ -170,11 +170,10 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
|
||||
"extended_profile_fields": None,
|
||||
"phone_number": None,
|
||||
"pending_name_change": None,
|
||||
"verified_name": None,
|
||||
}
|
||||
|
||||
if user_profile:
|
||||
verified_name_obj = get_verified_name(user, is_verified=True)
|
||||
verified_name = verified_name_obj.verified_name if verified_name_obj else None
|
||||
data.update(
|
||||
{
|
||||
"bio": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.bio),
|
||||
@@ -187,7 +186,6 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
|
||||
user_profile.language_proficiencies.all().order_by('code'), many=True
|
||||
).data,
|
||||
"name": user_profile.name,
|
||||
"verified_name": verified_name,
|
||||
"gender": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.gender),
|
||||
"goals": user_profile.goals,
|
||||
"year_of_birth": user_profile.year_of_birth,
|
||||
@@ -211,6 +209,12 @@ class UserReadOnlySerializer(serializers.Serializer): # lint-amnesty, pylint: d
|
||||
except PendingNameChange.DoesNotExist:
|
||||
pass
|
||||
|
||||
name_affirmation_service = get_name_affirmation_service()
|
||||
if name_affirmation_service:
|
||||
verified_name_obj = name_affirmation_service.get_verified_name(user, is_verified=True)
|
||||
if verified_name_obj:
|
||||
data.update({"verified_name": verified_name_obj.verified_name})
|
||||
|
||||
if is_secondary_email_feature_enabled():
|
||||
data.update(
|
||||
{
|
||||
|
||||
@@ -14,8 +14,6 @@ from django.conf import settings
|
||||
from django.test.testcases import TransactionTestCase
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
from edx_name_affirmation.api import create_verified_name
|
||||
from edx_name_affirmation.statuses import VerifiedNameStatus
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient, APITestCase
|
||||
|
||||
@@ -26,6 +24,7 @@ from openedx.core.djangoapps.user_api.accounts import ACCOUNT_VISIBILITY_PREF_KE
|
||||
from openedx.core.djangoapps.user_api.models import UserPreference
|
||||
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
|
||||
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase, skip_unless_lms
|
||||
from openedx.features.name_affirmation_api.utils import get_name_affirmation_service
|
||||
|
||||
from .. import ALL_USERS_VISIBILITY, CUSTOM_VISIBILITY, PRIVATE_VISIBILITY
|
||||
|
||||
@@ -55,6 +54,7 @@ class UserAPITestCase(APITestCase):
|
||||
self.staff_user = UserFactory(is_staff=True, password=TEST_PASSWORD)
|
||||
self.staff_client = APIClient()
|
||||
self.user = UserFactory.create(password=TEST_PASSWORD) # will be assigned to self.client by default
|
||||
self.name_affirmation_service = get_name_affirmation_service()
|
||||
|
||||
def login_client(self, api_client, user):
|
||||
"""Helper method for getting the client and user and logging in. Returns client. """
|
||||
@@ -142,9 +142,16 @@ class UserAPITestCase(APITestCase):
|
||||
def create_mock_verified_name(self, user):
|
||||
"""
|
||||
Helper method to create an approved VerifiedName entry in name affirmation.
|
||||
Will not do anything if Name Affirmation is not installed.
|
||||
"""
|
||||
legacy_profile = UserProfile.objects.get(id=user.id)
|
||||
create_verified_name(user, self.VERIFIED_NAME, legacy_profile.name, status=VerifiedNameStatus.APPROVED)
|
||||
if self.name_affirmation_service:
|
||||
legacy_profile = UserProfile.objects.get(id=user.id)
|
||||
self.name_affirmation_service.create_verified_name(
|
||||
user,
|
||||
self.VERIFIED_NAME,
|
||||
legacy_profile.name,
|
||||
status='approved'
|
||||
)
|
||||
|
||||
def create_user_registration(self, user):
|
||||
"""
|
||||
@@ -152,6 +159,14 @@ class UserAPITestCase(APITestCase):
|
||||
"""
|
||||
RegistrationFactory(user=user)
|
||||
|
||||
def _get_num_queries(self, num_queries):
|
||||
"""
|
||||
If Name Affirmation is installed, it will add an extra query
|
||||
"""
|
||||
if self.name_affirmation_service:
|
||||
return num_queries + 1
|
||||
return num_queries
|
||||
|
||||
def _verify_profile_image_data(self, data, has_profile_image):
|
||||
"""
|
||||
Verify the profile image data in a GET response for self.user
|
||||
@@ -240,7 +255,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
||||
"""
|
||||
|
||||
ENABLED_CACHES = ['default']
|
||||
TOTAL_QUERY_COUNT = 27
|
||||
TOTAL_QUERY_COUNT = 26
|
||||
FULL_RESPONSE_FIELD_COUNT = 30
|
||||
|
||||
def setUp(self):
|
||||
@@ -324,7 +339,6 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
||||
# additional admin fields (13)
|
||||
assert self.user.email == data['email']
|
||||
assert self.user.id == data['id']
|
||||
assert self.VERIFIED_NAME == data['verified_name']
|
||||
assert data['extended_profile'] is not None
|
||||
assert 'MA' == data['state']
|
||||
assert 'f' == data['gender']
|
||||
@@ -335,6 +349,10 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
||||
assert data['secondary_email'] is None
|
||||
assert data['secondary_email_enabled'] is None
|
||||
assert year_of_birth == data['year_of_birth']
|
||||
if self.name_affirmation_service:
|
||||
assert self.VERIFIED_NAME == data['verified_name']
|
||||
else:
|
||||
assert data['verified_name'] is None
|
||||
|
||||
def test_anonymous_access(self):
|
||||
"""
|
||||
@@ -501,7 +519,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
||||
"""
|
||||
self.different_client.login(username=self.different_user.username, password=TEST_PASSWORD)
|
||||
self.create_mock_profile(self.user)
|
||||
with self.assertNumQueries(self.TOTAL_QUERY_COUNT):
|
||||
with self.assertNumQueries(self._get_num_queries(self.TOTAL_QUERY_COUNT)):
|
||||
response = self.send_get(self.different_client)
|
||||
self._verify_full_shareable_account_response(response, account_privacy=ALL_USERS_VISIBILITY)
|
||||
|
||||
@@ -516,7 +534,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
||||
"""
|
||||
self.different_client.login(username=self.different_user.username, password=TEST_PASSWORD)
|
||||
self.create_mock_profile(self.user)
|
||||
with self.assertNumQueries(self.TOTAL_QUERY_COUNT):
|
||||
with self.assertNumQueries(self._get_num_queries(self.TOTAL_QUERY_COUNT)):
|
||||
response = self.send_get(self.different_client)
|
||||
self._verify_private_account_response(response)
|
||||
|
||||
@@ -667,12 +685,12 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
||||
assert data['accomplishments_shared'] is False
|
||||
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
verify_get_own_information(25)
|
||||
verify_get_own_information(self._get_num_queries(24))
|
||||
|
||||
# Now make sure that the user can get the same information, even if not active
|
||||
self.user.is_active = False
|
||||
self.user.save()
|
||||
verify_get_own_information(17)
|
||||
verify_get_own_information(self._get_num_queries(16))
|
||||
|
||||
def test_get_account_empty_string(self):
|
||||
"""
|
||||
@@ -687,7 +705,7 @@ class TestAccountsAPI(CacheIsolationTestCase, UserAPITestCase):
|
||||
legacy_profile.save()
|
||||
|
||||
self.client.login(username=self.user.username, password=TEST_PASSWORD)
|
||||
with self.assertNumQueries(25):
|
||||
with self.assertNumQueries(self._get_num_queries(24)):
|
||||
response = self.send_get(self.client)
|
||||
for empty_field in ("level_of_education", "gender", "country", "state", "bio",):
|
||||
assert response.data[empty_field] is None
|
||||
|
||||
Reference in New Issue
Block a user