Skip to content

Commit

Permalink
feat(report): report articles
Browse files Browse the repository at this point in the history
- add endpoint for reporting articles
- add endpoint for getting reported articles

[#161966626]
  • Loading branch information
actlikewill committed Dec 13, 2018
1 parent 8e2bd92 commit f2f22aa
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 7 deletions.
29 changes: 29 additions & 0 deletions authors/apps/articles/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,32 @@ def save(self, *args, **kwargs):
"""
self.article_slug = self.create_slug()
super().save(*args,**kwargs)


class ReportArticle(models.Model):
class Meta:
verbose_name = "Reported Article"
verbose_name_plural = "Reported Articles"

REPORT_CHOICES = (
(0, 'None'),
(1, 'Incites Violence'),
(2, 'Duplicate content'),
(3, 'Indecent Content'),
(4, 'Poorly Written')
)
article = models.ForeignKey(Article, on_delete=models.CASCADE)
reported_by = models.ForeignKey(User, on_delete=models.CASCADE)
report = models.IntegerField(blank=False, null=False, choices=REPORT_CHOICES)
timestamp = models.DateTimeField(auto_now_add=True)

def show_report(self):
choice = int(self.report)
return self.REPORT_CHOICES[choice]

def __str__(self):
user = self.reported_by
report = self.show_report()
article = self.article.title
return """Article Titled: "{}" was reported By User: {} for Report: {}""".format(article, user, report)

26 changes: 24 additions & 2 deletions authors/apps/articles/serializers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from rest_framework import serializers

from ..authentication.serializers import UserSerializer
from .models import Article
from .models import Article, ReportArticle
from ..authentication.models import User


class ArticleSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -58,4 +59,25 @@ class ArticleAuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = '__all__'


class ArticleAuthorSerializer(serializers.ModelSerializer):
"""
Class to serialize article and return the full owner information.
"""
title = serializers.CharField(max_length=200)
description = serializers.CharField()
body = serializers.CharField()
author = UserSerializer(read_only = True)
class Meta:
model = Article
fields = '__all__'


class ReportArticleSerializer(serializers.ModelSerializer):
article = serializers.PrimaryKeyRelatedField(queryset=Article.objects.all())
reported_by = serializers.PrimaryKeyRelatedField(queryset=User.objects.all())
report = serializers.ChoiceField(choices=ReportArticle.REPORT_CHOICES)

class Meta:
model = ReportArticle
fields = ('article', 'reported_by', 'report')
15 changes: 15 additions & 0 deletions authors/apps/articles/tests/base_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ def setUp(self):
"body": " "
}}

self.valid_report_data = {
"report":1
}

self.invalid_report_data = {
"report": "not_valid"
}

def user_signup(self):
""" Method for registering ba user for testing. """
res = self.test_client.post(
Expand Down Expand Up @@ -140,3 +148,10 @@ def create_article_user2(self):
login = self.test_client.post(self.login_url ,self.login_data2, format='json')
token = 'Token ' + login.data['token']
return token

def create_report(self, report):
article_url, response, token = self.create_article()
report_response = self.test_client.post(reverse('articles:report', kwargs={"slug": response.data['slug']}), data=report, format='json',
HTTP_AUTHORIZATION=token)
return report_response

38 changes: 38 additions & 0 deletions authors/apps/articles/tests/test_report_article.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from django.urls import reverse
from authors.apps.authentication.models import User
from .base_test import BaseTestCase
from rest_framework import status


class TestReports(BaseTestCase):
def test_report_article_with_valid_data(self):
response = self.create_report(self.valid_report_data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)

def test_report_article_with_invalid_data(self):
response = self.create_report(self.invalid_report_data)
resp = str(response.data.get("errors", {}).get("report", ''))
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual('is not a valid choice' in resp, True)

def test_get_report_as_not_admin(self):
article_url, response, token = self.create_article()
response = self.test_client.post(reverse('articles:report-list'), format='json',
HTTP_AUTHORIZATION=token)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)

def test_get_report_as_admin(self):
User.objects.create_superuser('admin', 'admin@admin.com', 'adminp@ssw0rd')
login_data = {"user": {
"email": "admin@admin.com",
"password": "adminp@ssw0rd"
}
}
admin = self.test_client.post(
self.login_url,
login_data,
format='json')
admin_token = 'Token ' + admin.data['token']
response = self.test_client.get(reverse('articles:report-list'), format='json',
HTTP_AUTHORIZATION=admin_token)
self.assertEqual(response.status_code, status.HTTP_200_OK)
6 changes: 4 additions & 2 deletions authors/apps/articles/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.urls import path

from .views import ArticleAPIView, SpecificArticleAPIView
from .views import ArticleAPIView, SpecificArticleAPIView, ReportListAPIView, ReportArticleAPIView


urlpatterns = [
path('articles/', ArticleAPIView.as_view(), name='articles'),
path('articles/<slug>', SpecificArticleAPIView.as_view(), name='get_article')
path('articles/<slug>', SpecificArticleAPIView.as_view(), name='get_article'),
path('articles/<str:slug>/report/', ReportArticleAPIView.as_view(), name='report'),
path('articles/reports/', ReportListAPIView.as_view(), name='report-list'),
]
48 changes: 45 additions & 3 deletions authors/apps/articles/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
from rest_framework import status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import AllowAny, IsAuthenticated, IsAuthenticatedOrReadOnly
from rest_framework.permissions import AllowAny, IsAuthenticated, IsAuthenticatedOrReadOnly, IsAdminUser
from requests.exceptions import HTTPError

from .permissions import IsOwnerOrReadOnly
from .models import Article
from .serializers import ArticleSerializer, ArticleAuthorSerializer
from .models import Article, ReportArticle
from ..authentication.models import User
from .serializers import ArticleSerializer, ArticleAuthorSerializer, ReportArticleSerializer


class ArticleAPIView(APIView):
Expand Down Expand Up @@ -101,3 +102,44 @@ def delete(self, request, slug):
return Response(message, status=status.HTTP_200_OK)
except Exception:
return Response({'message':"article not found."})

class ReportListAPIView(APIView):
permission_classes = (IsAdminUser,)
serializer_class = ReportArticleSerializer

def get(self, request):
# TODO: Catch empty result errors
query_set = ReportArticle.objects.all()
serializer = self.serializer_class(query_set, many=True)
reports = []
for i in range(len(serializer.data)):
single_report = {
"article": Article.objects.get(id=serializer.data[i]['article']).title,
"reported_by": User.objects.get(id=serializer.data[i]['reported_by']).username,
"report": ReportArticle.REPORT_CHOICES[serializer.data[i]['report']][1]
}
reports.append(single_report)
return Response({"reports": reports}, status=status.HTTP_200_OK)


class ReportArticleAPIView(APIView):
permission_classes = (IsAuthenticated,)
serializer_class = ReportArticleSerializer

def post(self, request, **kwargs):
try:
article_slug = kwargs.get('slug')
article = Article.objects.get(article_slug=article_slug)
reported_by = request.user
report = request.data.get('report')
data = {"article": article.pk, "reported_by": reported_by.pk, "report": report}
serializer = self.serializer_class(data=data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response({"Success": "You have submitted a report",
"article": article.title,
"report": ReportArticle.REPORT_CHOICES[int(report)][1]
}, status=status.HTTP_201_CREATED)
except Article.DoesNotExist:
return Response({"Error": "That article does not exist"}, status=status.HTTP_404_NOT_FOUND)

0 comments on commit f2f22aa

Please sign in to comment.