diff --git a/common/test/acceptance/pages/lms/dashboard.py b/common/test/acceptance/pages/lms/dashboard.py index 4404a8f7ad..9aaeee09e8 100644 --- a/common/test/acceptance/pages/lms/dashboard.py +++ b/common/test/acceptance/pages/lms/dashboard.py @@ -51,6 +51,21 @@ class DashboardPage(PageObject): return self.q(css='section.info > hgroup > h3 > a').map(_get_course_name).results + @property + def full_name(self): + """Return the displayed value for the user's full name""" + return self.q(css='li.info--username .data').text[0] + + @property + def email(self): + """Return the displayed value for the user's email address""" + return self.q(css='li.info--email .data').text[0] + + @property + def username(self): + """Return the displayed value for the user's username""" + return self.q(css='h1.user-name').text[0] + def get_enrollment_mode(self, course_name): """Get the enrollment mode for a given course on the dashboard. diff --git a/common/test/acceptance/tests/lms/test_lms.py b/common/test/acceptance/tests/lms/test_lms.py index 567efc79ed..9d1a33ac33 100644 --- a/common/test/acceptance/tests/lms/test_lms.py +++ b/common/test/acceptance/tests/lms/test_lms.py @@ -170,6 +170,10 @@ class RegisterFromCombinedPageTest(UniqueCourseTest): course_names = self.dashboard_page.wait_for_page().available_courses self.assertIn(self.course_info["display_name"], course_names) + self.assertEqual("Test User", self.dashboard_page.full_name) + self.assertEqual(email, self.dashboard_page.email) + self.assertEqual(username, self.dashboard_page.username) + def test_register_failure(self): # Navigate to the registration page self.register_page.visit() diff --git a/lms/envs/common.py b/lms/envs/common.py index c48ea4724e..38c7f3ea1a 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -2051,7 +2051,7 @@ SEARCH_RESULT_PROCESSOR = "lms.lib.courseware_search.lms_result_processor.LmsSea PROFILE_CONFIGURATION = { # Default visibility level for accounts without a specified value # The value is one of: 'all_users', 'private' - "default_visibility": 'all_users', + "default_visibility": "private", # The list of all fields that can be shown on a learner's profile "all_fields": [ diff --git a/openedx/core/djangoapps/content/course_structures/models.py b/openedx/core/djangoapps/content/course_structures/models.py index 7819aec3fc..ebbd320c4f 100644 --- a/openedx/core/djangoapps/content/course_structures/models.py +++ b/openedx/core/djangoapps/content/course_structures/models.py @@ -63,7 +63,7 @@ def listen_for_course_publish(sender, course_key, **kwargs): update_course_structure.delay(unicode(course_key), countdown=0) -@task() +@task(name=u'openedx.core.djangoapps.content.course_structures.models.update_course_structure') def update_course_structure(course_key): """ Regenerates and updates the course structure (in the database) for the specified course. diff --git a/openedx/core/djangoapps/user_api/api/profile.py b/openedx/core/djangoapps/user_api/api/profile.py index 28de57068c..371e4a4186 100644 --- a/openedx/core/djangoapps/user_api/api/profile.py +++ b/openedx/core/djangoapps/user_api/api/profile.py @@ -14,6 +14,7 @@ from pytz import UTC import analytics from eventtracking import tracker +from ..accounts import NAME_MIN_LENGTH from ..accounts.views import AccountView from ..models import User, UserPreference, UserOrgTag from ..helpers import intercept_errors @@ -36,6 +37,10 @@ class ProfileInternalError(Exception): pass +FULL_NAME_MAX_LENGTH = 255 +FULL_NAME_MIN_LENGTH = NAME_MIN_LENGTH + + @intercept_errors(ProfileInternalError, ignore_errors=[ProfileRequestError]) def preference_info(username): """Retrieve information about a user's preferences. diff --git a/openedx/core/djangoapps/user_api/profiles/tests/test_views.py b/openedx/core/djangoapps/user_api/profiles/tests/test_views.py index 8341988d74..28e4377861 100644 --- a/openedx/core/djangoapps/user_api/profiles/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/profiles/tests/test_views.py @@ -7,6 +7,7 @@ import unittest from django.conf import settings from django.core.urlresolvers import reverse +from mock import patch from openedx.core.djangoapps.user_api.accounts.tests.test_views import UserAPITestCase from openedx.core.djangoapps.user_api.models import UserPreference @@ -59,6 +60,10 @@ class TestProfileAPI(UserAPITestCase): ("staff_client", "staff_user"), ) @ddt.unpack + # Note: using getattr so that the patching works even if there is no configuration. + # This is needed when testing CMS as the patching is still executed even though the + # suite is skipped. + @patch.dict(getattr(settings, "PROFILE_CONFIGURATION", {}), {"default_visibility": "all_users"}) def test_get_default_profile(self, api_client, username): """ Test that any logged in user can get the main test user's public profile information. @@ -68,6 +73,26 @@ class TestProfileAPI(UserAPITestCase): response = self.send_get(client) self._verify_full_profile_response(response) + @ddt.data( + ("client", "user"), + ("different_client", "different_user"), + ("staff_client", "staff_user"), + ) + @ddt.unpack + # Note: using getattr so that the patching works even if there is no configuration. + # This is needed when testing CMS as the patching is still executed even though the + # suite is skipped. + @patch.dict(getattr(settings, "PROFILE_CONFIGURATION", {}), {"default_visibility": "private"}) + def test_get_default_private_profile(self, api_client, username): + """ + Test that any logged in user gets only the public fields for a profile + if the default visibility is 'private'. + """ + client = self.login_client(api_client, username) + self.create_mock_profile(self.user) + response = self.send_get(client) + self._verify_private_profile_response(response) + @ddt.data( ("client", "user"), ("different_client", "different_user"), diff --git a/openedx/core/djangoapps/user_api/tests/test_views.py b/openedx/core/djangoapps/user_api/tests/test_views.py index c9c841527e..3d11542e38 100644 --- a/openedx/core/djangoapps/user_api/tests/test_views.py +++ b/openedx/core/djangoapps/user_api/tests/test_views.py @@ -28,7 +28,6 @@ from ..api import account as account_api, profile as profile_api from ..models import UserOrgTag from ..tests.factories import UserPreferenceFactory from ..tests.test_constants import SORTED_COUNTRIES -from openedx.core.djangoapps.user_api.accounts import NAME_MIN_LENGTH TEST_API_KEY = "test_api_key" @@ -842,7 +841,7 @@ class RegistrationViewTest(ApiTestCase): u"label": u"Full name", u"instructions": u"The name that will appear on your certificates", u"restrictions": { - "max_length": NAME_MIN_LENGTH, + "max_length": profile_api.FULL_NAME_MAX_LENGTH, }, } ) @@ -922,7 +921,7 @@ class RegistrationViewTest(ApiTestCase): u"label": u"Full name", u"instructions": u"The name that will appear on your certificates", u"restrictions": { - "max_length": NAME_MIN_LENGTH + "max_length": profile_api.FULL_NAME_MAX_LENGTH, } } ) diff --git a/openedx/core/djangoapps/user_api/views.py b/openedx/core/djangoapps/user_api/views.py index 0a93898c5a..929c7133d1 100644 --- a/openedx/core/djangoapps/user_api/views.py +++ b/openedx/core/djangoapps/user_api/views.py @@ -33,8 +33,6 @@ from .helpers import FormDescription, shim_student_view, require_post_params from .models import UserPreference, UserProfile from .serializers import UserSerializer, UserPreferenceSerializer -from openedx.core.djangoapps.user_api.accounts import NAME_MIN_LENGTH - class LoginSessionView(APIView): """HTTP end-points for logging in users. """ @@ -352,7 +350,7 @@ class RegistrationView(APIView): label=name_label, instructions=name_instructions, restrictions={ - "max_length": NAME_MIN_LENGTH, + "max_length": profile_api.FULL_NAME_MAX_LENGTH, }, required=required )