Commit 04ca94ea by Ahsan Ulhaq

Account settings page should load and create student user profile

ECOM-4776
parent be5c4fad
...@@ -214,6 +214,16 @@ class ReactivationEmailTests(EmailTestMixin, TestCase): ...@@ -214,6 +214,16 @@ class ReactivationEmailTests(EmailTestMixin, TestCase):
self.assertFalse(response_data['success']) self.assertFalse(response_data['success'])
def test_reactivation_for_no_user_profile(self, email_user):
"""
Test that trying to send a reactivation email to a user without
user profile fails without throwing 500 error.
"""
user = UserFactory.build(username='test_user', email='test_user@test.com')
user.save()
response_data = self.reactivation_email(user)
self.assertFalse(response_data['success'])
def test_reactivation_email_success(self, email_user): def test_reactivation_email_success(self, email_user):
response_data = self.reactivation_email(self.user) response_data = self.reactivation_email(self.user)
......
...@@ -18,7 +18,7 @@ from xmodule.modulestore.tests.factories import CourseFactory ...@@ -18,7 +18,7 @@ from xmodule.modulestore.tests.factories import CourseFactory
from student.cookies import get_user_info_cookie_data from student.cookies import get_user_info_cookie_data
from student.helpers import DISABLE_UNENROLL_CERT_STATES from student.helpers import DISABLE_UNENROLL_CERT_STATES
from student.models import CourseEnrollment, LogoutViewConfiguration from student.models import CourseEnrollment, LogoutViewConfiguration, UserProfile
from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory
PASSWORD = 'test' PASSWORD = 'test'
...@@ -221,3 +221,11 @@ class StudentDashboardTests(TestCase): ...@@ -221,3 +221,11 @@ class StudentDashboardTests(TestCase):
self.client.get(self.path) self.client.get(self.path)
actual = self.client.cookies[settings.EDXMKTG_USER_INFO_COOKIE_NAME].value actual = self.client.cookies[settings.EDXMKTG_USER_INFO_COOKIE_NAME].value
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
def test_redirect_account_settings(self):
"""
Verify if user does not have profile he/she is redirected to account_settings.
"""
UserProfile.objects.get(user=self.user).delete()
response = self.client.get(self.path)
self.assertRedirects(response, reverse('account_settings'))
...@@ -23,7 +23,7 @@ from django.contrib.auth.views import password_reset_confirm ...@@ -23,7 +23,7 @@ from django.contrib.auth.views import password_reset_confirm
from django.contrib import messages from django.contrib import messages
from django.core.context_processors import csrf from django.core.context_processors import csrf
from django.core import mail from django.core import mail
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied, ObjectDoesNotExist
from django.core.urlresolvers import reverse, NoReverseMatch, reverse_lazy from django.core.urlresolvers import reverse, NoReverseMatch, reverse_lazy
from django.core.validators import validate_email, ValidationError from django.core.validators import validate_email, ValidationError
from django.db import IntegrityError, transaction from django.db import IntegrityError, transaction
...@@ -624,6 +624,8 @@ def dashboard(request): ...@@ -624,6 +624,8 @@ def dashboard(request):
""" """
user = request.user user = request.user
if not UserProfile.objects.filter(user=user).exists():
return redirect(reverse('account_settings'))
platform_name = configuration_helpers.get_value("platform_name", settings.PLATFORM_NAME) platform_name = configuration_helpers.get_value("platform_name", settings.PLATFORM_NAME)
enable_verified_certificates = configuration_helpers.get_value( enable_verified_certificates = configuration_helpers.get_value(
...@@ -2436,10 +2438,21 @@ def reactivation_email_for_user(user): ...@@ -2436,10 +2438,21 @@ def reactivation_email_for_user(user):
"error": _('No inactive user with this e-mail exists'), "error": _('No inactive user with this e-mail exists'),
}) # TODO: this should be status code 400 # pylint: disable=fixme }) # TODO: this should be status code 400 # pylint: disable=fixme
context = { try:
'name': user.profile.name, context = {
'key': reg.activation_key, 'name': user.profile.name,
} 'key': reg.activation_key,
}
except ObjectDoesNotExist:
log.error(
u'Unable to send reactivation email due to unavailable profile for the user "%s"',
user.username,
exc_info=True
)
return JsonResponse({
"success": False,
"error": _('Unable to send reactivation email')
})
subject = render_to_string('emails/activation_email_subject.txt', context) subject = render_to_string('emails/activation_email_subject.txt', context)
subject = ''.join(subject.splitlines()) subject = ''.join(subject.splitlines())
......
...@@ -15,6 +15,7 @@ from nose.plugins.attrib import attr ...@@ -15,6 +15,7 @@ from nose.plugins.attrib import attr
from openedx.core.djangoapps.dark_lang.models import DarkLangConfig from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
from openedx.core.djangoapps.user_api.preferences.api import set_user_preference from openedx.core.djangoapps.user_api.preferences.api import set_user_preference
from student.models import UserProfile
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
...@@ -118,6 +119,7 @@ class I18nRegressionTests(BaseI18nTestCase): ...@@ -118,6 +119,7 @@ class I18nRegressionTests(BaseI18nTestCase):
def test_unreleased_lang_resolution(self): def test_unreleased_lang_resolution(self):
# Regression test; LOC-85 # Regression test; LOC-85
UserProfile.objects.create(user=self.user)
self.release_languages('fa') self.release_languages('fa')
self.user_login() self.user_login()
...@@ -134,6 +136,7 @@ class I18nRegressionTests(BaseI18nTestCase): ...@@ -134,6 +136,7 @@ class I18nRegressionTests(BaseI18nTestCase):
self.assert_tag_has_attr(response.content, "html", "lang", "fa-ir") self.assert_tag_has_attr(response.content, "html", "lang", "fa-ir")
def test_preview_lang(self): def test_preview_lang(self):
UserProfile.objects.create(user=self.user)
self.user_login() self.user_login()
# Regression test; LOC-87 # Regression test; LOC-87
...@@ -169,6 +172,7 @@ class I18nLangPrefTests(BaseI18nTestCase): ...@@ -169,6 +172,7 @@ class I18nLangPrefTests(BaseI18nTestCase):
""" """
def setUp(self): def setUp(self):
super(I18nLangPrefTests, self).setUp() super(I18nLangPrefTests, self).setUp()
UserProfile.objects.create(user=self.user)
self.user_login() self.user_login()
def test_lang_preference(self): def test_lang_preference(self):
......
...@@ -246,10 +246,11 @@ def _get_user_and_profile(username): ...@@ -246,10 +246,11 @@ def _get_user_and_profile(username):
""" """
try: try:
existing_user = User.objects.get(username=username) existing_user = User.objects.get(username=username)
existing_user_profile = UserProfile.objects.get(user=existing_user)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise UserNotFound() raise UserNotFound()
existing_user_profile, _ = UserProfile.objects.get_or_create(user=existing_user)
return existing_user, existing_user_profile return existing_user, existing_user_profile
......
""" """
Django REST Framework serializers for the User API Accounts sub-application Django REST Framework serializers for the User API Accounts sub-application
""" """
import logging
from rest_framework import serializers from rest_framework import serializers
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.conf import settings from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from lms.djangoapps.badges.utils import badges_enabled from lms.djangoapps.badges.utils import badges_enabled
...@@ -18,6 +21,7 @@ from .image_helpers import get_profile_image_urls_for_user ...@@ -18,6 +21,7 @@ from .image_helpers import get_profile_image_urls_for_user
PROFILE_IMAGE_KEY_PREFIX = 'image_url' PROFILE_IMAGE_KEY_PREFIX = 'image_url'
LOGGER = logging.getLogger(__name__)
class LanguageProficiencySerializer(serializers.ModelSerializer): class LanguageProficiencySerializer(serializers.ModelSerializer):
...@@ -63,7 +67,12 @@ class UserReadOnlySerializer(serializers.Serializer): ...@@ -63,7 +67,12 @@ class UserReadOnlySerializer(serializers.Serializer):
:param user: User object :param user: User object
:return: Dict serialized account :return: Dict serialized account
""" """
profile = user.profile try:
user_profile = user.profile
except ObjectDoesNotExist:
user_profile = None
LOGGER.warning("user profile for the user [%s] does not exist", user.username)
accomplishments_shared = badges_enabled() accomplishments_shared = badges_enabled()
data = { data = {
...@@ -78,32 +87,51 @@ class UserReadOnlySerializer(serializers.Serializer): ...@@ -78,32 +87,51 @@ class UserReadOnlySerializer(serializers.Serializer):
# https://docs.djangoproject.com/en/1.8/ref/databases/#fractional-seconds-support-for-time-and-datetime-fields # https://docs.djangoproject.com/en/1.8/ref/databases/#fractional-seconds-support-for-time-and-datetime-fields
"date_joined": user.date_joined.replace(microsecond=0), "date_joined": user.date_joined.replace(microsecond=0),
"is_active": user.is_active, "is_active": user.is_active,
"bio": AccountLegacyProfileSerializer.convert_empty_to_None(profile.bio), "bio": None,
"country": AccountLegacyProfileSerializer.convert_empty_to_None(profile.country.code), "country": None,
"profile_image": AccountLegacyProfileSerializer.get_profile_image( "profile_image": None,
profile, "language_proficiencies": None,
user, "name": None,
self.context.get('request') "gender": None,
), "goals": None,
"language_proficiencies": LanguageProficiencySerializer( "year_of_birth": None,
profile.language_proficiencies.all(), "level_of_education": None,
many=True "mailing_address": None,
).data, "requires_parental_consent": None,
"name": profile.name,
"gender": AccountLegacyProfileSerializer.convert_empty_to_None(profile.gender),
"goals": profile.goals,
"year_of_birth": profile.year_of_birth,
"level_of_education": AccountLegacyProfileSerializer.convert_empty_to_None(profile.level_of_education),
"mailing_address": profile.mailing_address,
"requires_parental_consent": profile.requires_parental_consent(),
"accomplishments_shared": accomplishments_shared, "accomplishments_shared": accomplishments_shared,
"account_privacy": get_profile_visibility(profile, user, self.configuration), "account_privacy": self.configuration.get('default_visibility')
} }
if user_profile:
data.update(
{
"bio": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.bio),
"country": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.country.code),
"profile_image": AccountLegacyProfileSerializer.get_profile_image(
user_profile, user, self.context.get('request')
),
"language_proficiencies": LanguageProficiencySerializer(
user_profile.language_proficiencies.all(), many=True
).data,
"name": user_profile.name,
"gender": AccountLegacyProfileSerializer.convert_empty_to_None(user_profile.gender),
"goals": user_profile.goals,
"year_of_birth": user_profile.year_of_birth,
"level_of_education": AccountLegacyProfileSerializer.convert_empty_to_None(
user_profile.level_of_education
),
"mailing_address": user_profile.mailing_address,
"requires_parental_consent": user_profile.requires_parental_consent(),
"account_privacy": get_profile_visibility(user_profile, user, self.configuration)
}
)
if self.custom_fields: if self.custom_fields:
fields = self.custom_fields fields = self.custom_fields
elif user_profile:
fields = _visible_fields(user_profile, user, self.configuration)
else: else:
fields = _visible_fields(profile, user, self.configuration) fields = self.configuration.get('public_fields')
return self._filter_fields( return self._filter_fields(
fields, fields,
......
"""
Test cases to cover Accounts-related serializers of the User API application
"""
import logging
from django.test import TestCase
from django.test.client import RequestFactory
from testfixtures import LogCapture
from student.models import UserProfile
from student.tests.factories import UserFactory
from openedx.core.djangoapps.user_api.accounts.serializers import UserReadOnlySerializer
LOGGER_NAME = "openedx.core.djangoapps.user_api.accounts.serializers"
class UserReadOnlySerializerTest(TestCase):
def setUp(self):
super(UserReadOnlySerializerTest, self).setUp()
request_factory = RequestFactory()
self.request = request_factory.get('/api/user/v1/accounts/')
self.user = UserFactory.build(username='test_user', email='test_user@test.com')
self.user.save()
self.config = {
"default_visibility": "public",
"shareable_fields": [
'name',
],
"public_fields": [
'email', 'name', 'username'
],
}
def test_serializer_data(self):
"""
Test serializer return data properly.
"""
UserProfile.objects.create(user=self.user, name='test name')
data = UserReadOnlySerializer(self.user, configuration=self.config, context={'request': self.request}).data
self.assertEqual(data['username'], self.user.username)
self.assertEqual(data['name'], 'test name')
self.assertEqual(data['email'], self.user.email)
def test_user_no_profile(self):
"""
Test serializer return data properly when user does not have profile.
"""
with LogCapture(LOGGER_NAME, level=logging.DEBUG) as logger:
data = UserReadOnlySerializer(self.user, configuration=self.config, context={'request': self.request}).data
logger.check(
(LOGGER_NAME, 'WARNING', 'user profile for the user [test_user] does not exist')
)
self.assertEqual(data['username'], self.user.username)
self.assertEqual(data['name'], None)
...@@ -20,9 +20,13 @@ class UserSerializer(serializers.HyperlinkedModelSerializer): ...@@ -20,9 +20,13 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
def get_name(self, user): def get_name(self, user):
""" """
Return the name attribute from the user profile object Return the name attribute from the user profile object if profile exists else none
""" """
profile = UserProfile.objects.get(user=user) try:
profile = UserProfile.objects.get(user=user)
except UserProfile.DoesNotExist:
return None
return profile.name return profile.name
def get_preferences(self, user): def get_preferences(self, user):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment