Merge pull request #17920 from edx/bmedx/fix_retirement_apis
Update retirement APIs to match spec
This commit is contained in:
@@ -28,6 +28,7 @@ from discussion_api.tests.utils import (
|
||||
)
|
||||
from django_comment_client.tests.utils import ForumsEnableMixin
|
||||
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_storage
|
||||
from openedx.core.djangoapps.user_api.models import RetirementState, UserRetirementStatus
|
||||
from openedx.core.lib.token_utils import JwtBuilder
|
||||
from student.models import get_retired_username_by_username
|
||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory, SuperuserFactory
|
||||
@@ -163,12 +164,16 @@ class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""Tests for CourseView"""
|
||||
def setUp(self):
|
||||
super(RetireViewTest, self).setUp()
|
||||
RetirementState.objects.create(state_name='PENDING', state_execution_order=1)
|
||||
self.retire_forums_state = RetirementState.objects.create(state_name='RETIRE_FORUMS', state_execution_order=11)
|
||||
|
||||
self.retirement = UserRetirementStatus.create_retirement(self.user)
|
||||
self.retirement.current_state = self.retire_forums_state
|
||||
self.retirement.save()
|
||||
|
||||
self.superuser = SuperuserFactory()
|
||||
self.retired_username = get_retired_username_by_username(self.user.username)
|
||||
self.url = reverse(
|
||||
"retire_discussion_user",
|
||||
kwargs={"username": text_type(self.user.username)}
|
||||
)
|
||||
self.url = reverse("retire_discussion_user")
|
||||
|
||||
def assert_response_correct(self, response, expected_status, expected_content):
|
||||
"""
|
||||
@@ -193,24 +198,18 @@ class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
"""
|
||||
self.register_get_user_retire_response(self.user)
|
||||
headers = self.build_jwt_headers(self.superuser)
|
||||
response = self.client.post(self.url, {'retired_username': self.retired_username}, **headers)
|
||||
data = {'username': self.user.username}
|
||||
response = self.client.post(self.url, data, **headers)
|
||||
self.assert_response_correct(response, 204, "")
|
||||
|
||||
def test_bad_hash(self):
|
||||
"""
|
||||
Check that we fail on a hash mismatch with an appropriate error
|
||||
"""
|
||||
headers = self.build_jwt_headers(self.superuser)
|
||||
response = self.client.post(self.url, {'retired_username': "this will never match"}, **headers)
|
||||
self.assert_response_correct(response, 500, '"Mismatched hashed_username, bad salt?"')
|
||||
|
||||
def test_downstream_forums_error(self):
|
||||
"""
|
||||
Check that we bubble up errors from the comments service
|
||||
"""
|
||||
self.register_get_user_retire_response(self.user, status=500, body="Server error")
|
||||
headers = self.build_jwt_headers(self.superuser)
|
||||
response = self.client.post(self.url, {'retired_username': self.retired_username}, **headers)
|
||||
data = {'username': self.user.username}
|
||||
response = self.client.post(self.url, data, **headers)
|
||||
self.assert_response_correct(response, 500, '"Server error"')
|
||||
|
||||
def test_nonexistent_user(self):
|
||||
@@ -218,19 +217,15 @@ class RetireViewTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
|
||||
Check that we handle unknown users appropriately
|
||||
"""
|
||||
nonexistent_username = "nonexistent user"
|
||||
self.url = reverse(
|
||||
"retire_discussion_user",
|
||||
kwargs={"username": nonexistent_username}
|
||||
)
|
||||
self.retired_username = get_retired_username_by_username(nonexistent_username)
|
||||
|
||||
data = {'username': nonexistent_username}
|
||||
headers = self.build_jwt_headers(self.superuser)
|
||||
response = self.client.post(self.url, {'retired_username': self.retired_username}, **headers)
|
||||
response = self.client.post(self.url, data, **headers)
|
||||
self.assert_response_correct(response, 404, None)
|
||||
|
||||
def test_not_authenticated(self):
|
||||
"""
|
||||
Override the parent implementation of this, we auth differently
|
||||
Override the parent implementation of this, we JWT auth for this API
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ urlpatterns = [
|
||||
CourseView.as_view(),
|
||||
name="discussion_course"
|
||||
),
|
||||
url(r"^v1/users/{}".format(settings.USERNAME_PATTERN), RetireUserView.as_view(), name="retire_discussion_user"),
|
||||
url(r"^v1/accounts/retire_forum", RetireUserView.as_view(), name="retire_discussion_user"),
|
||||
url(
|
||||
r"^v1/course_topics/{}".format(settings.COURSE_ID_PATTERN),
|
||||
CourseTopicsView.as_view(),
|
||||
|
||||
@@ -33,7 +33,7 @@ from discussion_api.forms import CommentGetForm, CommentListGetForm, ThreadListG
|
||||
from openedx.core.lib.api.parsers import MergePatchParser
|
||||
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
|
||||
from openedx.core.djangoapps.user_api.accounts.permissions import CanRetireUser
|
||||
from student.models import get_potentially_retired_user_by_username_and_hash
|
||||
from openedx.core.djangoapps.user_api.models import UserRetirementStatus
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
@@ -543,23 +543,22 @@ class RetireUserView(APIView):
|
||||
authentication_classes = (JwtAuthentication,)
|
||||
permission_classes = (permissions.IsAuthenticated, CanRetireUser)
|
||||
|
||||
def post(self, request, username):
|
||||
def post(self, request):
|
||||
"""
|
||||
Implements the retirement endpoint.
|
||||
"""
|
||||
user_model = get_user_model()
|
||||
retired_username = request.data['retired_username']
|
||||
username = request.data['username']
|
||||
|
||||
try:
|
||||
user = get_potentially_retired_user_by_username_and_hash(username, retired_username)
|
||||
cc_user = comment_client.User.from_django_user(user)
|
||||
retirement = UserRetirementStatus.get_retirement_for_retirement_action(username)
|
||||
cc_user = comment_client.User.from_django_user(retirement.user)
|
||||
|
||||
# We can't count on the LMS username being un-retired at this point,
|
||||
# so we pass the old username as a parameter to describe which
|
||||
# user to retire. This will either succeed or throw an error which
|
||||
# should be good to raise from here.
|
||||
cc_user.retire(username)
|
||||
except user_model.DoesNotExist:
|
||||
except UserRetirementStatus.DoesNotExist:
|
||||
return Response(status=status.HTTP_404_NOT_FOUND)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
return Response(text_type(exc), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
Reference in New Issue
Block a user