diff --git a/contest/decorators.py b/contest/decorators.py new file mode 100644 index 0000000..06a8b70 --- /dev/null +++ b/contest/decorators.py @@ -0,0 +1,86 @@ +# coding=utf-8 +from functools import wraps + +from django.http import HttpResponse +from django.shortcuts import render +from django.utils.timezone import now + +from utils.shortcuts import error_response, error_page + +from account.models import SUPER_ADMIN +from .models import Contest + + +def check_user_contest_permission(func): + @wraps(func) + def _check_user_contest_permission(*args, **kwargs): + """ + 这个函数检查当前的这个比赛对于 request 的用户来说能不能参加 + 需要比较:比赛的开始和结束时间、比赛是否有密码、比赛是不是限定指定小组参加 + 如果是有密码或者限定指定小组参加的话,即使比赛已经结束,那么也是可以看到所有的题目和结果的 + 否则不能看到这个比赛的题目结果排名等等 + """ + # CBV 的情况,第一个参数是self,第二个参数是request + if len(args) == 2: + request = args[-1] + else: + request = args[0] + + if not request.user.is_authenticated(): + if request.is_ajax(): + return error_response(u"请先登录") + else: + return error_page(request, u"请先登录") + + # kwargs 就包含了url 里面的播或参数 + if "contest_id" in kwargs: + contest_id = kwargs["contest_id"] + elif "contest_id" in request.data: + contest_id = request.data["contest_id"] + else: + if request.is_ajax(): + return error_response(u"参数错误") + else: + return error_page(request, u"参数错误") + + try: + contest = Contest.objects.get(id=contest_id) + except Contest.DoesNotExist: + if request.is_ajax(): + return error_response(u"比赛不存在") + else: + return error_page(request, u"比赛不存在") + + if request.user.admin_type == SUPER_ADMIN or request.user == contest.created_by: + return func(*args, **kwargs) + + # 有密码的公开赛 + if contest.contest_type == 2: + # 没有输入过密码 + if contest.id not in request.session.get("contests", []): + if request.is_ajax(): + return error_response(u"请先输入密码") + else: + return render(request, "oj/contest/no_contest_permission.html", + {"reason": "password_protect", "show_tab": False, "contest": contest}) + + # 指定小组参加的 + if contest.contest_type == 0: + if not contest.groups.filter(id__in=request.user.group_set.all()).exists(): + if request.is_ajax(): + return error_response(u"只有指定小组的可以参加这场比赛") + else: + return render(request, "oj/contest/no_contest_permission.html", + {"reason": "group_limited", "show_tab": False, "contest": contest}) + + # 比赛没有开始 + if contest.start_time > now(): + if request.is_ajax(): + return error_response(u"比赛还没有开始") + else: + return render(request, "oj/contest/no_contest_permission.html", + {"reason": "contest_not_start", "show_tab": False, "contest": contest}) + + return func(*args, **kwargs) + + return _check_user_contest_permission diff --git a/contest/views.py b/contest/views.py index d166a80..fd816f6 100644 --- a/contest/views.py +++ b/contest/views.py @@ -1,7 +1,8 @@ # coding=utf-8 import json import datetime -from django.utils.timezone import localtime +from functools import wraps +from django.utils.timezone import now from django.shortcuts import render from django.db import IntegrityError from django.utils import dateparse @@ -17,6 +18,7 @@ from group.models import Group from announcement.models import Announcement from .models import Contest, ContestProblem +from .decorators import check_user_contest_permission from .serializers import (CreateContestSerializer, ContestSerializer, EditContestSerializer, CreateContestProblemSerializer, ContestProblemSerializer, EditContestProblemSerializer, ContestPasswordVerifySerializer, @@ -251,33 +253,13 @@ class ContestPasswordVerifyAPIView(APIView): return serializer_invalid_response(serializer) -def check_user_contest_permission(request, contest): - # 有密码的公开赛 - if contest.contest_type == 2: - # 没有输入过密码 - if contest.id not in request.session.get("contests", []): - return {"result": False, "reason": "password_protect"} - - # 指定小组参加的 - if contest.contest_type == 0: - if not contest.groups.filter(id__in=request.user.group_set.all()).exists(): - return {"result": False, "reason": "limited_group"} - return {"result": True} - - -@login_required +@check_user_contest_permission def contest_page(request, contest_id): try: contest = Contest.objects.get(id=contest_id) except Contest.DoesNotExist: return error_page(request, u"比赛不存在") - Contest.objects.filter(Q(contest_type__in=[1, 2]) | Q(groups__in=request.user.group_set.all())) - - result = check_user_contest_permission(request, contest) - if not result["result"]: - return render(request, "oj/contest/contest_no_privilege.html", {"contest": contest, "reason": result["reason"]}) - return render(request, "oj/contest/contest_index.html", {"contest": contest}) diff --git a/template/oj/contest/contest_no_privilege.html b/template/oj/contest/no_contest_permission.html similarity index 100% rename from template/oj/contest/contest_no_privilege.html rename to template/oj/contest/no_contest_permission.html