Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear cache and refresh user profile on email verification #1970

Merged
merged 5 commits into from
Dec 17, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 32 additions & 19 deletions onadata/apps/api/tests/viewsets/test_user_profile_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
from onadata.libs.authentication import DigestAuthentication
from onadata.libs.serializers.user_profile_serializer import \
_get_first_last_names
from onadata.libs.utils.cache_tools import USER_PROFILE_PREFIX, safe_key


def _profile_data():
Expand Down Expand Up @@ -205,24 +204,6 @@ def test_profiles_get(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, self.user_profile_data())

def test_retrieve_user_profile_from_cache(self):
"""
Test that user_profiles are cached on retrieve
"""
view = UserProfileViewSet.as_view({
'get': 'retrieve'
})

# clear cache
cache.delete(safe_key(f'{USER_PROFILE_PREFIX}bob'))

self.assertIsNone(cache.get(safe_key(f'{USER_PROFILE_PREFIX}bob')))

request = self.factory.get('/', **self.extra)
view(request, user='bob')

self.assertIsNotNone(cache.get(f'{USER_PROFILE_PREFIX}bob'))

def test_profiles_get_anon(self):
view = UserProfileViewSet.as_view({
'get': 'retrieve'
Expand Down Expand Up @@ -1208,6 +1189,38 @@ def test_monthly_submissions_with_year_param(self):
self.assertFalse(self.xform.shared)
self.assertEquals(response.data, {'private': count})

@override_settings(ENABLE_EMAIL_VERIFICATION=True)
@patch(
'onadata.apps.api.viewsets.user_profile_viewset.RegistrationProfile')
def test_reads_from_master(self, mock_rp_class):
"""
Test that on failure to retrieve a UserProfile in the first
try a second query is run on the master database
"""
data = _profile_data()
self._create_user_using_profiles_endpoint(data)

view = UserProfileViewSet.as_view({'get': 'verify_email'})
rp = RegistrationProfile.objects.get(
user__username=data.get('username')
)
_data = {'verification_key': rp.activation_key}
mock_rp_class.DoesNotExist = RegistrationProfile.DoesNotExist
mock_rp_class.objects.select_related(
'user', 'user__profile'
).get.side_effect = [RegistrationProfile.DoesNotExist, rp]
request = self.factory.get('/', data=_data)
response = view(request)
self.assertEquals(response.status_code, 200)
self.assertIn('is_email_verified', response.data)
self.assertIn('username', response.data)
self.assertTrue(response.data.get('is_email_verified'))
self.assertEquals(
response.data.get('username'), data.get('username'))
self.assertEqual(
mock_rp_class.objects.select_related(
'user', 'user__profile').get.call_count, 2)

def test_change_password_attempts(self):
view = UserProfileViewSet.as_view(
{'post': 'change_password'})
Expand Down
26 changes: 19 additions & 7 deletions onadata/apps/api/viewsets/user_profile_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from rest_framework.generics import get_object_or_404
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from multidb.pinning import use_master

from onadata.apps.api.tasks import send_verification_email
from onadata.apps.api.permissions import UserProfilePermissions
Expand Down Expand Up @@ -100,7 +101,7 @@ def serializer_from_settings():


def set_is_email_verified(profile, is_email_verified):
profile.metadata.update({"is_email_verified": is_email_verified})
profile.metadata.update({'is_email_verified': is_email_verified})
profile.save()


Expand Down Expand Up @@ -214,7 +215,6 @@ def retrieve(self, request, *args, **kwargs):
return Response(cached_user)
response = super(UserProfileViewSet, self)\
.retrieve(request, *args, **kwargs)
cache.set(f'{USER_PROFILE_PREFIX}{username}', response.data)
return response

def create(self, request, *args, **kwargs):
Expand Down Expand Up @@ -337,19 +337,31 @@ def verify_email(self, request, *args, **kwargs):
verification_key = request.query_params.get('verification_key')
response_message = _("Missing or invalid verification key")
if verification_key:
rp = None
try:
rp = RegistrationProfile.objects.get(
activation_key=verification_key)
rp = RegistrationProfile.objects.select_related(
'user', 'user__profile').get(
activation_key=verification_key)
except RegistrationProfile.DoesNotExist:
pass
else:
with use_master:
try:
rp = RegistrationProfile.objects.select_related(
'user', 'user__profile').get(
activation_key=verification_key)
except RegistrationProfile.DoesNotExist:
pass

if rp:
rp.activation_key = verified_key_text
rp.save()

username = rp.user.username
set_is_email_verified(rp.user.profile, True)
# Clear profiles cache
safe_delete(f'{USER_PROFILE_PREFIX}{username}')

response_data = {
'username': rp.user.username,
'username': username,
'is_email_verified': True
}

Expand Down