Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
21 changes: 21 additions & 0 deletions problem/decorator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404
from problem.models import Problem


def view_hidden_problem_permission_required():
def decorator(func):
def _wrapped_view(request, pid, *args, **kwargs):
problem = get_object_or_404(Problem, pid=pid)

if not problem.enabled and not request.user.has_perm("problem.view_hidden"):
return Response(
{"detail": "Problem is hidden."}, status=status.HTTP_403_FORBIDDEN
)

return func(request, pid=pid, *args, **kwargs)

return _wrapped_view

return decorator
30 changes: 23 additions & 7 deletions problem/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,38 @@
from segmentoj import tools

class ProblemSerializer(serializers.ModelSerializer):

class Meta:
model = Problem
fields = [
"pid",
"date_added",
"title",
"pid",
"date_added",
"title",
"description",
"allow_html",
"tags",
"enabled",
"memory_limit",
"allow_html",
"tags",
"enabled",
"memory_limit",
"time_limit",
]

depth = 0
read_only_fields = ["id", "date_added"]
extra_kwargs = {
"description": {"write_only": True},
}

class ProblemDescriptionSerializer(serializers.ModelSerializer):

class Meta:
model = Problem
fields = [
"pid",
"description",
]

depth = 0
read_only_fields = ["id"]

class TagSerializer(serializers.ModelSerializer):

Expand Down
26 changes: 23 additions & 3 deletions problem/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from rest_framework.test import APIRequestFactory, force_authenticate

from .models import Problem
from .views import ProblemView, TagView, TagListView
from .views import ProblemView, ProblemDescriptionView, TagView, TagListView
from account.models import User

# Create your tests here.
Expand All @@ -21,7 +21,6 @@ def setUp(self):
def testZ_get_problem(self):
ac_data = {
"title": "Simple Problem",
"description": "This is description",
"pid": 5,
"allow_html": False,
"enabled": True,
Expand All @@ -38,7 +37,6 @@ def testZ_get_problem(self):
self.assertIsNotNone(data)

self.assertEqual(data.get("title"), ac_data["title"])
self.assertEqual(data.get("description"), ac_data["description"])
self.assertEqual(data.get("pid"), ac_data["pid"])
self.assertEqual(data.get("allow_html"), ac_data["allow_html"])
self.assertEqual(data.get("enabled"), ac_data["enabled"])
Expand Down Expand Up @@ -87,6 +85,28 @@ def testW_change_problem(self):
self.assertEqual(target.enabled, ac_data["enabled"])


class ProblemDescriptionViewTest(TestCase):
fixtures = ["testdatabase.yaml"]

def setUp(self):
self.base_url = "/api/problem/{pid}/description"
self.factory = APIRequestFactory()
self.view = ProblemDescriptionView.as_view()

def testZ_get_problem_description(self):
ac_data = {
"description": "This is description"
}

request = self.factory.get(self.base_url.format(pid=5))
response = self.view(request, pid=5)
self.assertEqual(response.status_code, status.HTTP_200_OK)

data = response.data.get("res")
self.assertIsNotNone(data)
self.assertEqual(data.get("description"), ac_data["description"])


class TagViewTest(TestCase):
fixtures = ["testdatabase.yaml"]

Expand Down
29 changes: 21 additions & 8 deletions problem/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,26 @@

from segmentoj import tools
from problem.models import Problem, Tag
from .serializers import ProblemSerializer, ProblemListSerializer, TagSerializer
from segmentoj.decorator import syllable_required, parameter_required
from .serializers import (
ProblemSerializer,
ProblemDescriptionSerializer,
ProblemListSerializer,
TagSerializer,
)
from segmentoj.decorator import (
parameter_required,
)
from status.models import Status
from .decorator import view_hidden_problem_permission_required


class ProblemView(APIView):
@method_decorator(parameter_required("pid"))
@method_decorator(view_hidden_problem_permission_required())
def get(self, request, pid):
# Get the content of a problem
problem = get_object_or_404(Problem, pid=pid)

if not problem.enabled and not request.user.has_perm("problem.view_hidden"):
return Response(
{"detail": "Problem is hidden."}, status=status.HTTP_403_FORBIDDEN
)

ps = ProblemSerializer(problem)
return Response({"res": ps.data}, status=status.HTTP_200_OK)

Expand Down Expand Up @@ -60,6 +64,16 @@ def delete(self, request, pid):
return Response(status=status.HTTP_204_NO_CONTENT)


class ProblemDescriptionView(APIView):
@method_decorator(parameter_required("pid"))
@method_decorator(view_hidden_problem_permission_required())
def get(self, request, pid):
problem = get_object_or_404(Problem, pid=pid)

pds = ProblemDescriptionSerializer(problem)
return Response({"res": pds.data}, status=status.HTTP_200_OK)


class TagView(APIView):
@method_decorator(parameter_required("tid"))
def get(self, request, tid):
Expand Down Expand Up @@ -126,7 +140,6 @@ def process_data(x):
status=status.HTTP_200_OK,
)


class ProblemListCountView(APIView):
def get(self, request):

Expand Down
1 change: 1 addition & 0 deletions segmentoj/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
# Problem
path("api/problem", problem.views.ProblemView.as_view()),
path("api/problem/<int:pid>", problem.views.ProblemView.as_view()),
path("api/problem/<int:pid>/description", problem.views.ProblemDescriptionView.as_view()),
path("api/problem/tag", problem.views.TagView.as_view()),
path("api/problem/tag/<int:tid>", problem.views.TagView.as_view()),
path("api/problem/list", problem.views.ProblemListView.as_view()),
Expand Down