Skip to content

Commit

Permalink
feat: profile api save extranfo arabic fields
Browse files Browse the repository at this point in the history
  • Loading branch information
johanseto committed Jul 10, 2024
1 parent 531c386 commit f7710cf
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 17 deletions.
19 changes: 3 additions & 16 deletions eox_nelp/one_time_password/view_decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
import functools
import logging

from custom_reg_form.models import ExtraInfo
from django.conf import settings
from django.core.cache import cache
from django.http import HttpResponseForbidden, JsonResponse
from rest_framework import status

from eox_nelp.utils import save_extrainfo_field

logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -56,23 +57,9 @@ def wrapper(request):
if not proposed_user_otp == cache.get(user_otp_key):
return HttpResponseForbidden(reason="Forbidden - wrong code")

save_successfull_phone_validation(request.user)
save_extrainfo_field(request.user, "is_phone_validated", True)
cache.delete(user_otp_key)

return func(request)

return wrapper


def save_successfull_phone_validation(user):
"""Save in db the successfull phone_validation field with `True`
in extrainfo model of the user.
Args:
user (User): User instance to check
"""
if extra_info := getattr(user, "extrainfo", None):
setattr(extra_info, "is_phone_validated", True)
extra_info.save()
else:
ExtraInfo.objects.create(user=user, is_phone_validated=True) # pylint: disable=no-member
53 changes: 52 additions & 1 deletion eox_nelp/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@
GetCourseFromIdTestCase: Tests cases for the get_course_from_id method.
"""
from ddt import data, ddt
from django.contrib.auth import get_user_model
from django.test import TestCase
from mock import Mock, patch
from opaque_keys.edx.keys import CourseKey

from eox_nelp.utils import camel_to_snake, extract_course_id_from_string, get_course_from_id, get_item_label
from eox_nelp.utils import (
camel_to_snake,
extract_course_id_from_string,
get_course_from_id,
get_item_label,
save_extrainfo_field,
)

User = get_user_model()


@ddt
Expand Down Expand Up @@ -222,3 +231,45 @@ def test_invalid_input(self, input_value):
- TypeError is raised
"""
self.assertRaises(TypeError, camel_to_snake, input_value)


@ddt
class SaveExtraInfoFieldTestCase(TestCase):
"""Test class for the save_extrainfo_field method."""
@data(
("arabic_name", "أناكين سكاي ووكر"),
("is_phone_validated", True),
("arabic_first_name", " أناكين"),
("arabic_last_name", "سكاي ووكر"),
)
def test_save_extrainfo_field(self, test_data):
""" Test right functionality.
Expected behavior:
- Extrainfo related objed has the expected value.
"""
field = test_data[0]
value = test_data[1]
user, _ = User.objects.get_or_create(username="vader1798")

save_extrainfo_field(user, field, value)

self.assertEqual(getattr(user.extrainfo, field), value)

@data(
("arabic_name2", "loool"),
("otp-crazy", True),
)
def test_wrong_extra_info_field(self, test_data):
""" Test when the input is not a extra info field.
Expected behavior:
- The user has no extra info model.
"""
field = test_data[0]
value = test_data[1]
user, _ = User.objects.get_or_create(username="vader19")

save_extrainfo_field(user, field, value)

self.assertFalse(hasattr(user, "extrainfo"))
34 changes: 34 additions & 0 deletions eox_nelp/user_profile/api/v1/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,37 @@ def test_account_update_extra_fields(self, cdd_task_mock):
self.assertEqual(self.user.first_name, payload["first_name"])
self.assertEqual(self.user.last_name, payload["last_name"])
cdd_task_mock.delay.assert_called_with(user_id=self.user.id)

@override_settings(
ENABLE_OTP_VALIDATION=False,
REQUIRED_USER_EXTRA_INFO_FIELDS=["arabic_first_name", "arabic_last_name"],
PEARSON_RTI_ACTIVATE_GRADED_GATE=True,
)
@patch("eox_nelp.user_profile.api.v1.views.cdd_task")
def test_update_extra_info_fields(self, cdd_task_mock):
"""
Test that extra account user fields has been set.
Expected behavior:
- Check the response says that the field has been updated.
- Status code 200.
- Check that update_account_settings method has called once.
- Check that user first_name has been updated.
- Check that user last_name has been updated.
- Check cdd_task async task is called with user.id
"""
payload = {
"arabic_first_name": "أناكين",
"arabic_last_name": "سكاي ووكر",
"one_time_password": "correct26",
}
url_endpoint = reverse(self.reverse_viewname)

response = self.client.post(url_endpoint, payload, format="json")

self.assertDictEqual(response.json(), {"message": "User's fields has been updated successfully"})
self.assertEqual(response.status_code, status.HTTP_200_OK)
accounts.api.update_account_settings.assert_called_once_with(self.user, payload)
self.assertEqual(self.user.extrainfo.arabic_first_name, payload["arabic_first_name"])
self.assertEqual(self.user.extrainfo.arabic_last_name, payload["arabic_last_name"])
cdd_task_mock.delay.assert_called_with(user_id=self.user.id)
10 changes: 10 additions & 0 deletions eox_nelp/user_profile/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from eox_nelp.edxapp_wrapper.user_api import accounts, errors
from eox_nelp.one_time_password.view_decorators import validate_otp
from eox_nelp.pearson_vue.tasks import cdd_task
from eox_nelp.utils import save_extrainfo_field

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -65,6 +66,15 @@ def update_user_data(request):

request.user.save()

# This extra code block is required since the method update_account_settings just
# allows to update fields defined in the AccountUserSerializer and the AccountLegacyProfileSerializer
# so some fields related ExtraInfo are not editable in the standad implementation.
required_user_extra_info_fields = getattr(settings, 'REQUIRED_USER_EXTRA_INFO_FIELDS', [])
if required_user_extra_info_fields:
for field, value in request.data.items():
if field in required_user_extra_info_fields:
save_extrainfo_field(request.user, field, value)

except errors.AccountValidationError as err:
return Response({"field_errors": err.field_errors}, status=status.HTTP_400_BAD_REQUEST)
except errors.AccountUpdateError as err:
Expand Down
20 changes: 20 additions & 0 deletions eox_nelp/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import re
from copy import copy

from custom_reg_form.models import ExtraInfo
from opaque_keys.edx.keys import CourseKey

from eox_nelp.edxapp_wrapper.course_overviews import get_course_overviews
Expand Down Expand Up @@ -154,3 +155,22 @@ def camel_to_snake(string):
String in snake case.
"""
return re.sub(r'(?<!^)(?=[A-Z])', '_', string).lower()


def save_extrainfo_field(user, field, value):
"""Given a user save in extrainfo a value in the desired field.
If the extrainfo doesnt exist, the extrainfo model is created
Args:
user (User):
field (string):
value (any):
"""
if not hasattr(ExtraInfo, field):
return

if extra_info := getattr(user, "extrainfo", None):
setattr(extra_info, field, value)
extra_info.save()
else:
ExtraInfo.objects.create(user=user, **{field: value}) # pylint: disable=no-member

0 comments on commit f7710cf

Please sign in to comment.