OnlineJudge/contest/views/admin.py

188 lines
8.0 KiB
Python
Raw Normal View History

from ipaddress import ip_network
2017-01-26 04:33:00 +00:00
import dateutil.parser
2017-01-26 09:06:24 +00:00
2017-01-26 04:33:00 +00:00
from utils.api import APIView, validate_serializer
2017-12-03 07:39:02 +00:00
from utils.cache import cache
from utils.constants import CacheKey
2017-04-18 17:37:10 +00:00
2018-01-04 11:27:41 +00:00
from account.decorators import check_contest_permission, ensure_created_by
2017-12-03 07:39:02 +00:00
from ..models import Contest, ContestAnnouncement, ACMContestRank
from ..serializers import (ContestAnnouncementSerializer, ContestAdminSerializer,
2017-12-03 07:39:02 +00:00
CreateConetestSeriaizer, CreateContestAnnouncementSerializer,
EditConetestSeriaizer, EditContestAnnouncementSerializer,
ACMContesHelperSerializer, )
2017-01-26 04:33:00 +00:00
class ContestAPI(APIView):
@validate_serializer(CreateConetestSeriaizer)
def post(self, request):
data = request.data
data["start_time"] = dateutil.parser.parse(data["start_time"])
data["end_time"] = dateutil.parser.parse(data["end_time"])
data["created_by"] = request.user
2017-01-26 05:45:39 +00:00
if data["end_time"] <= data["start_time"]:
return self.error("Start time must occur earlier than end time")
if data.get("password") and data["password"] == "":
2017-01-26 05:45:39 +00:00
data["password"] = None
for ip_range in data["allowed_ip_ranges"]:
try:
ip_network(ip_range, strict=False)
except ValueError:
return self.error(f"{ip_range} is not a valid cidr network")
2017-02-27 04:18:22 +00:00
contest = Contest.objects.create(**data)
return self.success(ContestAdminSerializer(contest).data)
2017-01-26 04:33:00 +00:00
2017-01-27 15:20:56 +00:00
@validate_serializer(EditConetestSeriaizer)
def put(self, request):
data = request.data
try:
contest = Contest.objects.get(id=data.pop("id"))
2018-01-04 11:27:41 +00:00
ensure_created_by(contest, request.user)
2017-01-27 15:20:56 +00:00
except Contest.DoesNotExist:
return self.error("Contest does not exist")
data["start_time"] = dateutil.parser.parse(data["start_time"])
data["end_time"] = dateutil.parser.parse(data["end_time"])
if data["end_time"] <= data["start_time"]:
return self.error("Start time must occur earlier than end time")
if not data["password"]:
data["password"] = None
for ip_range in data["allowed_ip_ranges"]:
try:
ip_network(ip_range, strict=False)
except ValueError as e:
return self.error(f"{ip_range} is not a valid cidr network")
2017-12-03 07:39:02 +00:00
if not contest.real_time_rank and data.get("real_time_rank"):
cache_key = f"{CacheKey.contest_rank_cache}:{contest.id}"
cache.delete(cache_key)
2017-01-27 15:20:56 +00:00
for k, v in data.items():
setattr(contest, k, v)
contest.save()
return self.success(ContestAdminSerializer(contest).data)
2017-01-27 15:20:56 +00:00
2017-01-26 04:33:00 +00:00
def get(self, request):
2017-01-26 05:45:39 +00:00
contest_id = request.GET.get("id")
if contest_id:
try:
contest = Contest.objects.get(id=contest_id)
2018-01-04 11:27:41 +00:00
ensure_created_by(contest, request.user)
return self.success(ContestAdminSerializer(contest).data)
2017-01-26 05:45:39 +00:00
except Contest.DoesNotExist:
return self.error("Contest does not exist")
2017-01-26 09:59:41 +00:00
2017-01-26 05:45:39 +00:00
contests = Contest.objects.all().order_by("-create_time")
2018-01-04 11:27:41 +00:00
if request.user.is_admin():
contests = contests.filter(created_by=request.user)
2017-01-26 09:59:41 +00:00
keyword = request.GET.get("keyword")
if keyword:
contests = contests.filter(title__contains=keyword)
return self.success(self.paginate_data(request, contests, ContestAdminSerializer))
2017-01-29 09:04:56 +00:00
class ContestAnnouncementAPI(APIView):
@validate_serializer(CreateContestAnnouncementSerializer)
def post(self, request):
"""
Create one contest_announcement.
"""
2017-01-29 09:04:56 +00:00
data = request.data
try:
contest = Contest.objects.get(id=data.pop("contest_id"))
2018-01-04 11:27:41 +00:00
ensure_created_by(contest, request.user)
2017-01-29 09:04:56 +00:00
data["contest"] = contest
data["created_by"] = request.user
except Contest.DoesNotExist:
return self.error("Contest does not exist")
announcement = ContestAnnouncement.objects.create(**data)
return self.success(ContestAnnouncementSerializer(announcement).data)
@validate_serializer(EditContestAnnouncementSerializer)
def put(self, request):
"""
update contest_announcement
"""
data = request.data
try:
contest_announcement = ContestAnnouncement.objects.get(id=data.pop("id"))
2018-01-04 11:27:41 +00:00
ensure_created_by(contest_announcement, request.user)
except ContestAnnouncement.DoesNotExist:
return self.error("Contest announcement does not exist")
for k, v in data.items():
setattr(contest_announcement, k, v)
contest_announcement.save()
return self.success()
2017-01-29 09:04:56 +00:00
def delete(self, request):
"""
Delete one contest_announcement.
"""
contest_announcement_id = request.GET.get("id")
if contest_announcement_id:
if request.user.is_admin():
2017-02-27 04:18:22 +00:00
ContestAnnouncement.objects.filter(id=contest_announcement_id,
contest__created_by=request.user).delete()
2017-01-29 09:04:56 +00:00
else:
ContestAnnouncement.objects.filter(id=contest_announcement_id).delete()
2017-01-29 09:04:56 +00:00
return self.success()
def get(self, request):
"""
Get one contest_announcement or contest_announcement list.
"""
contest_announcement_id = request.GET.get("id")
if contest_announcement_id:
try:
contest_announcement = ContestAnnouncement.objects.get(id=contest_announcement_id)
2018-01-04 11:27:41 +00:00
ensure_created_by(contest_announcement, request.user)
return self.success(ContestAnnouncementSerializer(contest_announcement).data)
except ContestAnnouncement.DoesNotExist:
return self.error("Contest announcement does not exist")
2017-10-30 07:07:52 +00:00
contest_id = request.GET.get("contest_id")
if not contest_id:
2018-01-04 11:27:41 +00:00
return self.error("Parameter error")
2017-10-30 07:07:52 +00:00
contest_announcements = ContestAnnouncement.objects.filter(contest_id=contest_id)
if request.user.is_admin():
contest_announcements = contest_announcements.filter(created_by=request.user)
keyword = request.GET.get("keyword")
if keyword:
contest_announcements = contest_announcements.filter(title__contains=keyword)
2017-10-30 07:07:52 +00:00
return self.success(ContestAnnouncementSerializer(contest_announcements, many=True).data)
2017-12-03 07:39:02 +00:00
class ACMContestHelper(APIView):
@check_contest_permission(check_type="ranks")
def get(self, request):
ranks = ACMContestRank.objects.filter(contest=self.contest, accepted_number__gt=0) \
.values("id", "user__username", "user__userprofile__real_name", "submission_info")
results = []
for rank in ranks:
for problem_id, info in rank["submission_info"].items():
if info["is_ac"]:
results.append({
"id": rank["id"],
"username": rank["user__username"],
"real_name": rank["user__userprofile__real_name"],
"problem_id": problem_id,
"ac_info": info,
"checked": info.get("checked", False)
})
results.sort(key=lambda x: -x["ac_info"]["ac_time"])
return self.success(results)
@check_contest_permission(check_type="ranks")
2018-01-04 11:27:41 +00:00
@validate_serializer(ACMContesHelperSerializer)
2017-12-03 07:39:02 +00:00
def put(self, request):
data = request.data
try:
rank = ACMContestRank.objects.get(pk=data["rank_id"])
except ACMContestRank.DoesNotExist:
return self.error("Rank id does not exist")
problem_rank_status = rank.submission_info.get(data["problem_id"])
if not problem_rank_status:
return self.error("Problem id does not exist")
problem_rank_status["checked"] = data["checked"]
rank.save(update_fields=("submission_info",))
return self.success()