完善contest权限控制
This commit is contained in:
@@ -45,13 +45,12 @@ class Contest(models.Model):
|
||||
def is_contest_admin(self, user):
|
||||
return user.is_authenticated() and (self.created_by == user or user.admin_type == AdminType.SUPER_ADMIN)
|
||||
|
||||
def check_oi_permission(self, user):
|
||||
if self.status != ContestStatus.CONTEST_ENDED and not self.real_time_rank:
|
||||
if self.is_contest_admin(user):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
# 是否有权查看problem 的一些统计信息 诸如submission_number, accepted_number 等
|
||||
def problem_details_permission(self, user):
|
||||
return self.rule_type == ContestRuleType.ACM or \
|
||||
self.status == ContestStatus.CONTEST_ENDED or \
|
||||
self.is_contest_admin(user) or \
|
||||
self.real_time_rank
|
||||
|
||||
class Meta:
|
||||
db_table = "contest"
|
||||
|
||||
@@ -58,43 +58,40 @@ class ContestAdminAPITest(APITestCase):
|
||||
class ContestAPITest(APITestCase):
|
||||
def setUp(self):
|
||||
self.create_admin()
|
||||
self.url = self.reverse("contest_api")
|
||||
|
||||
def create_contest(self):
|
||||
url = self.reverse("contest_admin_api")
|
||||
return self.client.post(url, data=DEFAULT_CONTEST_DATA)
|
||||
self.contest = self.client.post(url, data=DEFAULT_CONTEST_DATA).data["data"]
|
||||
self.url = self.reverse("contest_api") + "?contest_id=" + str(self.contest["id"])
|
||||
|
||||
def test_get_contest_list(self):
|
||||
self.create_contest()
|
||||
response = self.client.get(self.url)
|
||||
url = self.reverse("contest_list_api")
|
||||
response = self.client.get(url + "?limit=10")
|
||||
self.assertSuccess(response)
|
||||
self.assertEqual(len(response.data["data"]["results"]), 1)
|
||||
|
||||
def test_get_one_contest(self):
|
||||
contest_id = self.create_contest().data["data"]["id"]
|
||||
response = self.client.get("{}?id={}".format(self.url, contest_id))
|
||||
self.assertSuccess(response)
|
||||
resp = self.client.get(self.url)
|
||||
self.assertSuccess(resp)
|
||||
|
||||
def test_regular_user_validate_contest_password(self):
|
||||
contest_id = self.create_contest().data["data"]["id"]
|
||||
self.create_user("test", "test123")
|
||||
url = self.reverse("contest_password_api")
|
||||
resp = self.client.post(url, {"contest_id": contest_id, "password": "error_password"})
|
||||
resp = self.client.post(url, {"contest_id": self.contest["id"], "password": "error_password"})
|
||||
self.assertDictEqual(resp.data, {"error": "error", "data": "Wrong password"})
|
||||
|
||||
resp = self.client.post(url, {"contest_id": contest_id, "password": DEFAULT_CONTEST_DATA["password"]})
|
||||
resp = self.client.post(url, {"contest_id": self.contest["id"], "password": DEFAULT_CONTEST_DATA["password"]})
|
||||
self.assertSuccess(resp)
|
||||
|
||||
def test_regular_user_access_contest(self):
|
||||
contest_id = self.create_contest().data["data"]["id"]
|
||||
self.create_user("test", "test123")
|
||||
url = self.reverse("contest_access_api")
|
||||
resp = self.client.get(url + "?contest_id=" + str(contest_id))
|
||||
resp = self.client.get(url + "?contest_id=" + str(self.contest["id"]))
|
||||
self.assertFalse(resp.data["data"]["access"])
|
||||
|
||||
password_url = self.reverse("contest_password_api")
|
||||
resp = self.client.post(password_url, {"contest_id": contest_id, "password": DEFAULT_CONTEST_DATA["password"]})
|
||||
resp = self.client.post(password_url,
|
||||
{"contest_id": self.contest["id"], "password": DEFAULT_CONTEST_DATA["password"]})
|
||||
self.assertSuccess(resp)
|
||||
resp = self.client.get(url + "?contest_id=" + str(contest_id))
|
||||
resp = self.client.get(self.url)
|
||||
self.assertSuccess(resp)
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
from django.conf.urls import url
|
||||
|
||||
from ..views.oj import ContestAnnouncementListAPI, ContestAPI
|
||||
from ..views.oj import ContestAnnouncementListAPI
|
||||
from ..views.oj import ContestPasswordVerifyAPI, ContestAccessAPI
|
||||
from ..views.oj import ContestListAPI, ContestAPI
|
||||
from ..views.oj import ContestRankAPI
|
||||
|
||||
urlpatterns = [
|
||||
url(r"^contests/?$", ContestListAPI.as_view(), name="contest_list_api"),
|
||||
url(r"^contest/?$", ContestAPI.as_view(), name="contest_api"),
|
||||
url(r"^contest/password/?$", ContestPasswordVerifyAPI.as_view(), name="contest_password_api"),
|
||||
url(r"^contest/announcement/?$", ContestAnnouncementListAPI.as_view(), name="contest_announcement_api"),
|
||||
|
||||
@@ -12,6 +12,7 @@ from ..serializers import OIContestRankSerializer, ACMContestRankSerializer
|
||||
|
||||
|
||||
class ContestAnnouncementListAPI(APIView):
|
||||
@check_contest_permission(check_type="announcements")
|
||||
def get(self, request):
|
||||
contest_id = request.GET.get("contest_id")
|
||||
if not contest_id:
|
||||
@@ -24,15 +25,13 @@ class ContestAnnouncementListAPI(APIView):
|
||||
|
||||
|
||||
class ContestAPI(APIView):
|
||||
@check_contest_permission(check_type="details")
|
||||
def get(self, request):
|
||||
contest_id = request.GET.get("id")
|
||||
if contest_id:
|
||||
try:
|
||||
contest = Contest.objects.select_related("created_by").get(id=contest_id, visible=True)
|
||||
except Contest.DoesNotExist:
|
||||
return self.error("Contest does not exist")
|
||||
return self.success(ContestSerializer(contest).data)
|
||||
return self.success(ContestSerializer(self.contest).data)
|
||||
|
||||
|
||||
class ContestListAPI(APIView):
|
||||
def get(self, request):
|
||||
contests = Contest.objects.select_related("created_by").filter(visible=True)
|
||||
keyword = request.GET.get("keyword")
|
||||
rule_type = request.GET.get("rule_type")
|
||||
@@ -49,7 +48,8 @@ class ContestAPI(APIView):
|
||||
contests = contests.filter(end_time__lt=cur)
|
||||
else:
|
||||
contests = contests.filter(start_time__lte=cur, end_time__gte=cur)
|
||||
return self.success(self.paginate_data(request, contests, ContestSerializer))
|
||||
data = self.paginate_data(request, contests, ContestSerializer)
|
||||
return self.success(data)
|
||||
|
||||
|
||||
class ContestPasswordVerifyAPI(APIView):
|
||||
@@ -91,11 +91,9 @@ class ContestRankAPI(APIView):
|
||||
return OIContestRank.objects.filter(contest=self.contest). \
|
||||
select_related("user").order_by("-total_score")
|
||||
|
||||
@check_contest_permission
|
||||
@check_contest_permission(check_type="ranks")
|
||||
def get(self, request):
|
||||
if self.contest.rule_type == ContestRuleType.OI:
|
||||
if not self.contest.check_oi_permission(request.user):
|
||||
return self.error("You have no permission for ranks now")
|
||||
serializer = OIContestRankSerializer
|
||||
else:
|
||||
serializer = ACMContestRankSerializer
|
||||
@@ -105,5 +103,4 @@ class ContestRankAPI(APIView):
|
||||
if not qs:
|
||||
qs = self.get_rank()
|
||||
cache.set(cache_key, qs)
|
||||
|
||||
return self.success(self.paginate_data(request, qs, serializer))
|
||||
|
||||
Reference in New Issue
Block a user