Skip to content

Commit

Permalink
Merge pull request #1914 from ResearchHub/moderation
Browse files Browse the repository at this point in the history
Adding Moderator view with user_details endpoint
  • Loading branch information
yattias authored Oct 13, 2024
2 parents 81a7779 + 51937ac commit f059e6e
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 4 deletions.
4 changes: 3 additions & 1 deletion src/researchhub/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
from researchhub.settings import INSTALLED_APPS, USE_DEBUG_TOOLBAR
from researchhub_comment.views.rh_comment_view import RhCommentViewSet
from review.views.review_view import ReviewViewSet
from user.views import author_views, editor_views, persona_webhook_view
from user.views import author_views, editor_views, moderator_view, persona_webhook_view

router = routers.DefaultRouter()

Expand Down Expand Up @@ -127,6 +127,8 @@

router.register(r"bounty", reputation.views.BountyViewSet)

router.register(r"moderator", moderator_view.ModeratorView, basename="moderator")

router.register(
r"author_claim_case",
researchhub_case_views.AuthorClaimCaseViewSet,
Expand Down
4 changes: 2 additions & 2 deletions src/user/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class IsModerator(AuthorizationBasedPermission):
message = "Need to be a moderator."

def has_permission(self, request, view):
return request.user.moderator
return request.user.is_authenticated and request.user.moderator

def is_authorized(self, request, view, obj):
return request.user.moderator
return request.user.is_authenticated and request.user.moderator


class CreateOrViewOrRevokeUserApiToken(BasePermission):
Expand Down
32 changes: 32 additions & 0 deletions src/user/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,38 @@
from utils import sentry


class ModeratorUserSerializer(ModelSerializer):
verification = SerializerMethodField()

class Meta:
model = User
fields = [
"id",
"email",
"probable_spammer",
"is_suspended",
"verification",
"created_date",
"sift_risk_score",
]

def get_verification(self, user):

user_verification = UserVerification.objects.filter(user=user).last()

if user_verification is None:
return None

return {
"first_name": user_verification.first_name,
"last_name": user_verification.last_name,
"created_date": user_verification.created_date,
"verified_by": user_verification.verified_by,
"external_id": user_verification.external_id,
"status": user_verification.status,
}


class UniversitySerializer(ModelSerializer):
class Meta:
model = University
Expand Down
53 changes: 53 additions & 0 deletions src/user/tests/test_moderator_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import json
from unittest.mock import patch

from django.test import TestCase
from rest_framework.test import APITestCase

from paper.openalex_util import process_openalex_works
from paper.related_models.authorship_model import Authorship
from paper.related_models.paper_model import Paper
from reputation.models import Score
from user.models import UserVerification
from user.related_models.author_model import Author
from user.tests.helpers import (
create_random_authenticated_user,
create_random_default_user,
create_user,
)
from utils.openalex import OpenAlex
from utils.test_helpers import (
get_authenticated_get_response,
get_authenticated_patch_response,
)


class ModeratorTests(APITestCase):

def test_moderator_can_view_details(self):
self.user = create_user(
email="mod@example.com",
first_name="Moderator",
last_name="mod",
moderator=True,
)

self.client.force_authenticate(user=self.user)

url = f"/api/moderator/{self.user.id}/user_details/"
response = self.client.get(url, {})
self.assertIn("id", response.data)

def test_non_moderator_cannot_view_details(self):
self.user = create_user(
email="user@example.com",
first_name="Moderator",
last_name="user",
moderator=False,
)

self.client.force_authenticate(user=self.user)

url = f"/api/moderator/{self.user.id}/user_details/"
response = self.client.get(url, {})
self.assertNotIn("id", response.data)
3 changes: 2 additions & 1 deletion src/user/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
from user.views.contribution_views import ContributionViewSet
from user.views.editor_views import *
from user.views.gatekeeper_view import GatekeeperViewSet
from user.views.moderator_view import *
from user.views.organization_view import OrganizationViewSet
from user.views.persona_webhook_view import *
from user.views.user_api_token_view import UserApiTokenViewSet
from user.views.user_views import *
from user.views.persona_webhook_view import *
21 changes: 21 additions & 0 deletions src/user/views/moderator_view.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet

from user.permissions import IsModerator, UserIsEditor
from user.serializers import ModeratorUserSerializer


class ModeratorView(ModelViewSet):

@action(
detail=True, methods=["get"], permission_classes=[UserIsEditor | IsModerator]
)
def user_details(self, request, pk=None, **kwargs):
from user.models import User

user = User.objects.get(id=pk)
serializer = ModeratorUserSerializer(user)

return Response(serializer.data)

0 comments on commit f059e6e

Please sign in to comment.