diff --git a/osmchadjango/users/tests/test_views.py b/osmchadjango/users/tests/test_views.py index 3d2b9581..32d39356 100644 --- a/osmchadjango/users/tests/test_views.py +++ b/osmchadjango/users/tests/test_views.py @@ -4,6 +4,8 @@ from social_django.models import UserSocialAuth from ..models import User, MappingTeam +from ...changeset.tests.modelfactories import ChangesetFactory +from ...changeset.models import Changeset class TestCurrentUserDetailAPIView(APITestCase): @@ -102,6 +104,7 @@ def test_receive_oauth_token(self): self.assertIn('oauth_token_secret', response.data.keys()) + class TestMappingTeamListCreateAPIView(APITestCase): def setUp(self): self.url = reverse('users:mapping-team') @@ -379,3 +382,105 @@ def test_with_other_user(self): self.assertEqual(MappingTeam.objects.filter(trusted=False).count(), 1) self.assertEqual(MappingTeam.objects.filter(trusted=True).count(), 0) + self.staff_user = User.objects.create_user( + username='staff', + password='password', + email='a@a.com', + is_staff=True + ) + UserSocialAuth.objects.create( + user=self.staff_user, + provider='openstreetmap', + uid='123456', + ) + + + +class TestUpdateDeletedUsersView(APITestCase): + def setUp(self): + self.url = reverse('users:update-deleted-users') + ChangesetFactory.create_batch(50, uid="1769", user="test_user") + ChangesetFactory.create_batch(50, uid="1234", user="old_user") + self.user = User.objects.create_user( + username='test', + password='password', + email='a@a.com' + ) + UserSocialAuth.objects.create( + user=self.user, + provider='openstreetmap', + uid='123123', + ) + self.staff_user = User.objects.create_user( + username='staff', + password='password', + email='a@a.com', + is_staff=True + ) + UserSocialAuth.objects.create( + user=self.staff_user, + provider='openstreetmap', + uid='123456', + ) + + def test_unauthenticated(self): + request = self.client.post(self.url, data={'uids': [1769, 1234]}) + self.assertEqual(request.status_code, 401) + + def test_non_staff_user(self): + self.client.login(username=self.user.username, password='password') + request = self.client.post(self.url, data={'uids': [1769, 1234]}) + self.assertEqual(request.status_code, 403) + + def test_bad_request(self): + self.client.login(username=self.staff_user.username, password='password') + request = self.client.post(self.url) + self.assertEqual(request.status_code, 400) + request = self.client.post(self.url, data={'uid': [1769, 1234]}) + self.assertEqual(request.status_code, 400) + + def test_view(self): + user = User.objects.create_user( + username='test_user', + password='password', + email='a@a.com' + ) + UserSocialAuth.objects.create( + user=user, + provider='openstreetmap', + uid='1769', + ) + user_2 = User.objects.create_user( + username='old_user', + password='password', + email='a@a.com' + ) + UserSocialAuth.objects.create( + user=user_2, + provider='openstreetmap', + uid='1234', + ) + self.client.login(username=self.staff_user.username, password='password') + request = self.client.post(self.url, data={'uids': [1769, 1234]}) + self.assertEqual(request.status_code, 200) + self.assertEqual(Changeset.objects.filter(uid='1769').count(), 50) + self.assertEqual(Changeset.objects.filter(user='user_1769').count(), 50) + self.assertEqual(Changeset.objects.filter(user='test_user').count(), 0) + self.assertEqual(Changeset.objects.filter(uid='1234').count(), 50) + self.assertEqual(Changeset.objects.filter(user='user_1234').count(), 50) + self.assertEqual(Changeset.objects.filter(user='old_user').count(), 0) + self.assertEqual(User.objects.filter(username='old_user').count(), 0) + self.assertEqual(User.objects.filter(username='test_user').count(), 0) + self.assertEqual(User.objects.filter(username='user_1234').count(), 1) + self.assertEqual(User.objects.filter(username='user_1769').count(), 1) + + def test_view_as_strings(self): + self.client.login(username=self.staff_user.username, password='password') + request = self.client.post(self.url, data={'uids': ['1769', '1234']}) + self.assertEqual(request.status_code, 200) + self.assertEqual(Changeset.objects.filter(uid='1769').count(), 50) + self.assertEqual(Changeset.objects.filter(user='user_1769').count(), 50) + self.assertEqual(Changeset.objects.filter(user='test_user').count(), 0) + self.assertEqual(Changeset.objects.filter(uid='1234').count(), 50) + self.assertEqual(Changeset.objects.filter(user='user_1234').count(), 50) + self.assertEqual(Changeset.objects.filter(user='old_user').count(), 0) diff --git a/osmchadjango/users/urls.py b/osmchadjango/users/urls.py index a2ebbcb8..280b92b1 100644 --- a/osmchadjango/users/urls.py +++ b/osmchadjango/users/urls.py @@ -15,9 +15,14 @@ ), re_path( r'^social-auth/$', - views.SocialAuthAPIView.as_view(), + view=views.SocialAuthAPIView.as_view(), name="social-auth" ), + re_path( + r'^update-deleted-users/$', + view=views.update_deleted_users, + name="update-deleted-users" + ), re_path( r'^mapping-team/$', views.MappingTeamListCreateAPIView.as_view(), diff --git a/osmchadjango/users/views.py b/osmchadjango/users/views.py index 9e2e91cf..096fa450 100644 --- a/osmchadjango/users/views.py +++ b/osmchadjango/users/views.py @@ -13,8 +13,11 @@ from rest_framework.permissions import ( IsAuthenticated, IsAdminUser, BasePermission, SAFE_METHODS ) -from rest_framework.decorators import detail_route from rest_framework import status +from rest_framework.decorators import ( + api_view, parser_classes, permission_classes, detail_route + ) +from rest_framework.parsers import JSONParser, MultiPartParser, FormParser from rest_framework.response import Response from social_django.utils import load_strategy, load_backend from requests_oauthlib import OAuth1Session @@ -25,6 +28,7 @@ UserSerializer, SocialSignUpSerializer, MappingTeamSerializer ) from .models import MappingTeam +from ..changeset.models import Changeset User = get_user_model() @@ -201,3 +205,37 @@ def set_untrusted(self, request, pk): status=status.HTTP_403_FORBIDDEN ) return self.update_team(team, request, trusted=False) + + +@api_view(['POST']) +@parser_classes((JSONParser, MultiPartParser, FormParser)) +@permission_classes((IsAuthenticated, IsAdminUser)) +def update_deleted_users(request): + """Receive a list of user ids and remove the related user metadata. It will + replace the username in the changesets by the string 'user_' and also + rename it on the User model. It's intended to receive the list of uids of + the users that deleted themselves in the OpenStreetMap website. Only staff + users have permissions to use this endpoint. + """ + + if request.data and request.data.get('uids'): + uids = [str(uid) for uid in request.data.get('uids')] + for uid in uids: + Changeset.objects.filter(uid=uid).update( + user='user_{}'.format(uid) + ) + try: + user = User.objects.get(social_auth__uid=uid) + user.username = 'user_{}'.format(uid) + user.save() + except User.DoesNotExist: + pass + return Response( + {'detail': 'Changesets updated and user renamed.'}, + status=status.HTTP_200_OK + ) + else: + return Response( + {'detail': 'Payload is missing the `uids` field or it has an incorrect value.'}, + status=status.HTTP_400_BAD_REQUEST + )