mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2025-11-04 14:49:58 +08:00
fix permission
This commit is contained in:
parent
41f248091e
commit
8454b36792
@ -1,10 +1,7 @@
|
|||||||
import functools
|
import functools
|
||||||
|
|
||||||
from utils.api import JSONResponse
|
|
||||||
|
|
||||||
from .models import ProblemPermission
|
|
||||||
|
|
||||||
from contest.models import Contest, ContestType, ContestStatus, ContestRuleType
|
from contest.models import Contest, ContestType, ContestStatus, ContestRuleType
|
||||||
|
from utils.api import JSONResponse, APIError
|
||||||
|
from .models import ProblemPermission
|
||||||
|
|
||||||
|
|
||||||
class BasePermissionDecorator(object):
|
class BasePermissionDecorator(object):
|
||||||
@ -90,8 +87,7 @@ def check_contest_permission(check_type="details"):
|
|||||||
if not user.is_authenticated():
|
if not user.is_authenticated():
|
||||||
return self.error("Please login first.")
|
return self.error("Please login first.")
|
||||||
# password error
|
# password error
|
||||||
if ("accessible_contests" not in request.session) or \
|
if self.contest.id not in request.session.get("accessible_contests", []):
|
||||||
(self.contest.id not in request.session["accessible_contests"]):
|
|
||||||
return self.error("Password is required.")
|
return self.error("Password is required.")
|
||||||
|
|
||||||
# regular user get contest problems, ranks etc. before contest started
|
# regular user get contest problems, ranks etc. before contest started
|
||||||
@ -104,7 +100,10 @@ def check_contest_permission(check_type="details"):
|
|||||||
return self.error(f"No permission to get {check_type}")
|
return self.error(f"No permission to get {check_type}")
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return _check_permission
|
return _check_permission
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_created_by(obj, user):
|
||||||
|
if not user.is_admin_role() or (user.is_admin() and obj.created_by != user):
|
||||||
|
raise APIError(msg=f"{obj.__class__.__name__} does not exist")
|
||||||
|
|||||||
@ -30,14 +30,14 @@ class SMTPAPI(APIView):
|
|||||||
smtp.pop("password")
|
smtp.pop("password")
|
||||||
return self.success(smtp)
|
return self.success(smtp)
|
||||||
|
|
||||||
@validate_serializer(CreateSMTPConfigSerializer)
|
|
||||||
@super_admin_required
|
@super_admin_required
|
||||||
|
@validate_serializer(CreateSMTPConfigSerializer)
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
SysOptions.smtp_config = request.data
|
SysOptions.smtp_config = request.data
|
||||||
return self.success()
|
return self.success()
|
||||||
|
|
||||||
@validate_serializer(EditSMTPConfigSerializer)
|
|
||||||
@super_admin_required
|
@super_admin_required
|
||||||
|
@validate_serializer(EditSMTPConfigSerializer)
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
smtp = SysOptions.smtp_config
|
smtp = SysOptions.smtp_config
|
||||||
data = request.data
|
data = request.data
|
||||||
@ -81,8 +81,8 @@ class WebsiteConfigAPI(APIView):
|
|||||||
"website_footer", "allow_register", "submission_list_show_all"]}
|
"website_footer", "allow_register", "submission_list_show_all"]}
|
||||||
return self.success(ret)
|
return self.success(ret)
|
||||||
|
|
||||||
@validate_serializer(CreateEditWebsiteConfigSerializer)
|
|
||||||
@super_admin_required
|
@super_admin_required
|
||||||
|
@validate_serializer(CreateEditWebsiteConfigSerializer)
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
for k, v in request.data.items():
|
for k, v in request.data.items():
|
||||||
if k == "website_footer":
|
if k == "website_footer":
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from utils.api import APIView, validate_serializer
|
|||||||
from utils.cache import cache
|
from utils.cache import cache
|
||||||
from utils.constants import CacheKey
|
from utils.constants import CacheKey
|
||||||
|
|
||||||
from account.decorators import check_contest_permission
|
from account.decorators import check_contest_permission, ensure_created_by
|
||||||
from ..models import Contest, ContestAnnouncement, ACMContestRank
|
from ..models import Contest, ContestAnnouncement, ACMContestRank
|
||||||
from ..serializers import (ContestAnnouncementSerializer, ContestAdminSerializer,
|
from ..serializers import (ContestAnnouncementSerializer, ContestAdminSerializer,
|
||||||
CreateConetestSeriaizer, CreateContestAnnouncementSerializer,
|
CreateConetestSeriaizer, CreateContestAnnouncementSerializer,
|
||||||
@ -37,8 +37,7 @@ class ContestAPI(APIView):
|
|||||||
data = request.data
|
data = request.data
|
||||||
try:
|
try:
|
||||||
contest = Contest.objects.get(id=data.pop("id"))
|
contest = Contest.objects.get(id=data.pop("id"))
|
||||||
if request.user.is_admin() and contest.created_by != request.user:
|
ensure_created_by(contest, request.user)
|
||||||
return self.error("Contest does not exist")
|
|
||||||
except Contest.DoesNotExist:
|
except Contest.DoesNotExist:
|
||||||
return self.error("Contest does not exist")
|
return self.error("Contest does not exist")
|
||||||
data["start_time"] = dateutil.parser.parse(data["start_time"])
|
data["start_time"] = dateutil.parser.parse(data["start_time"])
|
||||||
@ -66,20 +65,18 @@ class ContestAPI(APIView):
|
|||||||
if contest_id:
|
if contest_id:
|
||||||
try:
|
try:
|
||||||
contest = Contest.objects.get(id=contest_id)
|
contest = Contest.objects.get(id=contest_id)
|
||||||
if request.user.is_admin() and contest.created_by != request.user:
|
ensure_created_by(contest, request.user)
|
||||||
return self.error("Contest does not exist")
|
|
||||||
return self.success(ContestAdminSerializer(contest).data)
|
return self.success(ContestAdminSerializer(contest).data)
|
||||||
except Contest.DoesNotExist:
|
except Contest.DoesNotExist:
|
||||||
return self.error("Contest does not exist")
|
return self.error("Contest does not exist")
|
||||||
|
|
||||||
contests = Contest.objects.all().order_by("-create_time")
|
contests = Contest.objects.all().order_by("-create_time")
|
||||||
|
if request.user.is_admin():
|
||||||
|
contests = contests.filter(created_by=request.user)
|
||||||
|
|
||||||
keyword = request.GET.get("keyword")
|
keyword = request.GET.get("keyword")
|
||||||
if keyword:
|
if keyword:
|
||||||
contests = contests.filter(title__contains=keyword)
|
contests = contests.filter(title__contains=keyword)
|
||||||
|
|
||||||
if request.user.is_admin():
|
|
||||||
contests = contests.filter(created_by=request.user)
|
|
||||||
return self.success(self.paginate_data(request, contests, ContestAdminSerializer))
|
return self.success(self.paginate_data(request, contests, ContestAdminSerializer))
|
||||||
|
|
||||||
|
|
||||||
@ -92,8 +89,7 @@ class ContestAnnouncementAPI(APIView):
|
|||||||
data = request.data
|
data = request.data
|
||||||
try:
|
try:
|
||||||
contest = Contest.objects.get(id=data.pop("contest_id"))
|
contest = Contest.objects.get(id=data.pop("contest_id"))
|
||||||
if request.user.is_admin() and contest.created_by != request.user:
|
ensure_created_by(contest, request.user)
|
||||||
return self.error("Contest does not exist")
|
|
||||||
data["contest"] = contest
|
data["contest"] = contest
|
||||||
data["created_by"] = request.user
|
data["created_by"] = request.user
|
||||||
except Contest.DoesNotExist:
|
except Contest.DoesNotExist:
|
||||||
@ -109,8 +105,7 @@ class ContestAnnouncementAPI(APIView):
|
|||||||
data = request.data
|
data = request.data
|
||||||
try:
|
try:
|
||||||
contest_announcement = ContestAnnouncement.objects.get(id=data.pop("id"))
|
contest_announcement = ContestAnnouncement.objects.get(id=data.pop("id"))
|
||||||
if request.user.is_admin() and contest_announcement.created_by != request.user:
|
ensure_created_by(contest_announcement, request.user)
|
||||||
return self.error("Contest announcement does not exist")
|
|
||||||
except ContestAnnouncement.DoesNotExist:
|
except ContestAnnouncement.DoesNotExist:
|
||||||
return self.error("Contest announcement does not exist")
|
return self.error("Contest announcement does not exist")
|
||||||
for k, v in data.items():
|
for k, v in data.items():
|
||||||
@ -139,15 +134,14 @@ class ContestAnnouncementAPI(APIView):
|
|||||||
if contest_announcement_id:
|
if contest_announcement_id:
|
||||||
try:
|
try:
|
||||||
contest_announcement = ContestAnnouncement.objects.get(id=contest_announcement_id)
|
contest_announcement = ContestAnnouncement.objects.get(id=contest_announcement_id)
|
||||||
if request.user.is_admin() and contest_announcement.created_by != request.user:
|
ensure_created_by(contest_announcement, request.user)
|
||||||
return self.error("Contest announcement does not exist")
|
|
||||||
return self.success(ContestAnnouncementSerializer(contest_announcement).data)
|
return self.success(ContestAnnouncementSerializer(contest_announcement).data)
|
||||||
except ContestAnnouncement.DoesNotExist:
|
except ContestAnnouncement.DoesNotExist:
|
||||||
return self.error("Contest announcement does not exist")
|
return self.error("Contest announcement does not exist")
|
||||||
|
|
||||||
contest_id = request.GET.get("contest_id")
|
contest_id = request.GET.get("contest_id")
|
||||||
if not contest_id:
|
if not contest_id:
|
||||||
return self.error("Paramater error")
|
return self.error("Parameter error")
|
||||||
contest_announcements = ContestAnnouncement.objects.filter(contest_id=contest_id)
|
contest_announcements = ContestAnnouncement.objects.filter(contest_id=contest_id)
|
||||||
if request.user.is_admin():
|
if request.user.is_admin():
|
||||||
contest_announcements = contest_announcements.filter(created_by=request.user)
|
contest_announcements = contest_announcements.filter(created_by=request.user)
|
||||||
@ -177,12 +171,10 @@ class ACMContestHelper(APIView):
|
|||||||
results.sort(key=lambda x: -x["ac_info"]["ac_time"])
|
results.sort(key=lambda x: -x["ac_info"]["ac_time"])
|
||||||
return self.success(results)
|
return self.success(results)
|
||||||
|
|
||||||
@validate_serializer(ACMContesHelperSerializer)
|
|
||||||
@check_contest_permission(check_type="ranks")
|
@check_contest_permission(check_type="ranks")
|
||||||
|
@validate_serializer(ACMContesHelperSerializer)
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
data = request.data
|
data = request.data
|
||||||
if not request.user.is_contest_admin(self.contest):
|
|
||||||
return self.error("You are not contest admin")
|
|
||||||
try:
|
try:
|
||||||
rank = ACMContestRank.objects.get(pk=data["rank_id"])
|
rank = ACMContestRank.objects.get(pk=data["rank_id"])
|
||||||
except ACMContestRank.DoesNotExist:
|
except ACMContestRank.DoesNotExist:
|
||||||
|
|||||||
@ -8,7 +8,7 @@ from wsgiref.util import FileWrapper
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import StreamingHttpResponse, HttpResponse
|
from django.http import StreamingHttpResponse, HttpResponse
|
||||||
|
|
||||||
from account.decorators import problem_permission_required
|
from account.decorators import problem_permission_required, ensure_created_by
|
||||||
from judge.dispatcher import SPJCompiler
|
from judge.dispatcher import SPJCompiler
|
||||||
from contest.models import Contest, ContestStatus
|
from contest.models import Contest, ContestStatus
|
||||||
from submission.models import Submission
|
from submission.models import Submission
|
||||||
@ -49,7 +49,6 @@ class TestCaseAPI(CSRFExemptAPIView):
|
|||||||
else:
|
else:
|
||||||
return sorted(ret, key=natural_sort_key)
|
return sorted(ret, key=natural_sort_key)
|
||||||
|
|
||||||
@problem_permission_required
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
problem_id = request.GET.get("problem_id")
|
problem_id = request.GET.get("problem_id")
|
||||||
if not problem_id:
|
if not problem_id:
|
||||||
@ -59,6 +58,11 @@ class TestCaseAPI(CSRFExemptAPIView):
|
|||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exists")
|
return self.error("Problem does not exists")
|
||||||
|
|
||||||
|
if problem.contest:
|
||||||
|
ensure_created_by(problem.contest, request.user)
|
||||||
|
else:
|
||||||
|
ensure_created_by(problem, request.user)
|
||||||
|
|
||||||
test_case_dir = os.path.join(settings.TEST_CASE_DIR, problem.test_case_id)
|
test_case_dir = os.path.join(settings.TEST_CASE_DIR, problem.test_case_id)
|
||||||
if not os.path.isdir(test_case_dir):
|
if not os.path.isdir(test_case_dir):
|
||||||
return self.error("Test case does not exists")
|
return self.error("Test case does not exists")
|
||||||
@ -79,7 +83,6 @@ class TestCaseAPI(CSRFExemptAPIView):
|
|||||||
response["Content-Length"] = os.path.getsize(file_name)
|
response["Content-Length"] = os.path.getsize(file_name)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@problem_permission_required
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
form = TestCaseUploadForm(request.POST, request.FILES)
|
form = TestCaseUploadForm(request.POST, request.FILES)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
@ -147,7 +150,6 @@ class TestCaseAPI(CSRFExemptAPIView):
|
|||||||
|
|
||||||
class CompileSPJAPI(APIView):
|
class CompileSPJAPI(APIView):
|
||||||
@validate_serializer(CompileSPJSerializer)
|
@validate_serializer(CompileSPJSerializer)
|
||||||
@problem_permission_required
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
data = request.data
|
data = request.data
|
||||||
spj_version = rand_str(8)
|
spj_version = rand_str(8)
|
||||||
@ -186,11 +188,12 @@ class ProblemBase(APIView):
|
|||||||
def delete(self, request):
|
def delete(self, request):
|
||||||
id = request.GET.get("id")
|
id = request.GET.get("id")
|
||||||
if not id:
|
if not id:
|
||||||
return self.error("Invalid parameter, id is requred")
|
return self.error("Invalid parameter, id is required")
|
||||||
try:
|
try:
|
||||||
problem = Problem.objects.get(id=id)
|
problem = Problem.objects.get(id=id, contest_id__isnull=True)
|
||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exists")
|
return self.error("Problem does not exists")
|
||||||
|
ensure_created_by(problem, request.user)
|
||||||
if Submission.objects.filter(problem=problem).exists():
|
if Submission.objects.filter(problem=problem).exists():
|
||||||
return self.error("Can't delete the problem as it has submissions")
|
return self.error("Can't delete the problem as it has submissions")
|
||||||
d = os.path.join(settings.TEST_CASE_DIR, problem.test_case_id)
|
d = os.path.join(settings.TEST_CASE_DIR, problem.test_case_id)
|
||||||
@ -201,11 +204,10 @@ class ProblemBase(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class ProblemAPI(ProblemBase):
|
class ProblemAPI(ProblemBase):
|
||||||
@validate_serializer(CreateProblemSerializer)
|
|
||||||
@problem_permission_required
|
@problem_permission_required
|
||||||
|
@validate_serializer(CreateProblemSerializer)
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
data = request.data
|
data = request.data
|
||||||
|
|
||||||
_id = data["_id"]
|
_id = data["_id"]
|
||||||
if not _id:
|
if not _id:
|
||||||
return self.error("Display ID is required")
|
return self.error("Display ID is required")
|
||||||
@ -236,8 +238,7 @@ class ProblemAPI(ProblemBase):
|
|||||||
if problem_id:
|
if problem_id:
|
||||||
try:
|
try:
|
||||||
problem = Problem.objects.get(id=problem_id)
|
problem = Problem.objects.get(id=problem_id)
|
||||||
if not user.can_mgmt_all_problem() and problem.created_by != user:
|
ensure_created_by(problem, request.user)
|
||||||
return self.error("Problem does not exist")
|
|
||||||
return self.success(ProblemAdminSerializer(problem).data)
|
return self.success(ProblemAdminSerializer(problem).data)
|
||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exist")
|
return self.error("Problem does not exist")
|
||||||
@ -256,17 +257,15 @@ class ProblemAPI(ProblemBase):
|
|||||||
problems = problems.filter(title__contains=keyword)
|
problems = problems.filter(title__contains=keyword)
|
||||||
return self.success(self.paginate_data(request, problems, ProblemAdminSerializer))
|
return self.success(self.paginate_data(request, problems, ProblemAdminSerializer))
|
||||||
|
|
||||||
@validate_serializer(EditProblemSerializer)
|
|
||||||
@problem_permission_required
|
@problem_permission_required
|
||||||
|
@validate_serializer(EditProblemSerializer)
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
data = request.data
|
data = request.data
|
||||||
problem_id = data.pop("id")
|
problem_id = data.pop("id")
|
||||||
user = request.user
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
problem = Problem.objects.get(id=problem_id)
|
problem = Problem.objects.get(id=problem_id)
|
||||||
if not user.can_mgmt_all_problem() and problem.created_by != user:
|
ensure_created_by(problem, request.user)
|
||||||
return self.error("Problem does not exist")
|
|
||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exist")
|
return self.error("Problem does not exist")
|
||||||
|
|
||||||
@ -300,13 +299,11 @@ class ProblemAPI(ProblemBase):
|
|||||||
|
|
||||||
class ContestProblemAPI(ProblemBase):
|
class ContestProblemAPI(ProblemBase):
|
||||||
@validate_serializer(CreateContestProblemSerializer)
|
@validate_serializer(CreateContestProblemSerializer)
|
||||||
@problem_permission_required
|
|
||||||
def post(self, request):
|
def post(self, request):
|
||||||
data = request.data
|
data = request.data
|
||||||
try:
|
try:
|
||||||
contest = Contest.objects.get(id=data.pop("contest_id"))
|
contest = Contest.objects.get(id=data.pop("contest_id"))
|
||||||
if request.user.is_admin() and contest.created_by != request.user:
|
ensure_created_by(contest, request.user)
|
||||||
return self.error("Contest does not exist")
|
|
||||||
except Contest.DoesNotExist:
|
except Contest.DoesNotExist:
|
||||||
return self.error("Contest does not exist")
|
return self.error("Contest does not exist")
|
||||||
|
|
||||||
@ -345,8 +342,7 @@ class ContestProblemAPI(ProblemBase):
|
|||||||
if problem_id:
|
if problem_id:
|
||||||
try:
|
try:
|
||||||
problem = Problem.objects.get(id=problem_id)
|
problem = Problem.objects.get(id=problem_id)
|
||||||
if user.is_admin() and problem.contest.created_by != user:
|
ensure_created_by(problem, user)
|
||||||
return self.error("Problem does not exist")
|
|
||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exist")
|
return self.error("Problem does not exist")
|
||||||
return self.success(ProblemAdminSerializer(problem).data)
|
return self.success(ProblemAdminSerializer(problem).data)
|
||||||
@ -366,10 +362,11 @@ class ContestProblemAPI(ProblemBase):
|
|||||||
@problem_permission_required
|
@problem_permission_required
|
||||||
def put(self, request):
|
def put(self, request):
|
||||||
data = request.data
|
data = request.data
|
||||||
|
user = request.user
|
||||||
|
|
||||||
try:
|
try:
|
||||||
contest = Contest.objects.get(id=data.pop("contest_id"))
|
contest = Contest.objects.get(id=data.pop("contest_id"))
|
||||||
if request.user.is_admin() and contest.created_by != request.user:
|
ensure_created_by(contest, user)
|
||||||
return self.error("Contest does not exist")
|
|
||||||
except Contest.DoesNotExist:
|
except Contest.DoesNotExist:
|
||||||
return self.error("Contest does not exist")
|
return self.error("Contest does not exist")
|
||||||
|
|
||||||
@ -377,12 +374,10 @@ class ContestProblemAPI(ProblemBase):
|
|||||||
return self.error("Invalid rule type")
|
return self.error("Invalid rule type")
|
||||||
|
|
||||||
problem_id = data.pop("id")
|
problem_id = data.pop("id")
|
||||||
user = request.user
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
problem = Problem.objects.get(id=problem_id)
|
problem = Problem.objects.get(id=problem_id)
|
||||||
if not user.can_mgmt_all_problem() and problem.created_by != user:
|
ensure_created_by(problem, user)
|
||||||
return self.error("Problem does not exist")
|
|
||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return self.error("Problem does not exist")
|
return self.error("Problem does not exist")
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,13 @@ from django.views.generic import View
|
|||||||
logger = logging.getLogger("")
|
logger = logging.getLogger("")
|
||||||
|
|
||||||
|
|
||||||
|
class APIError(Exception):
|
||||||
|
def __init__(self, msg, err=None):
|
||||||
|
self.err = err
|
||||||
|
self.msg = msg
|
||||||
|
super().__init__(err, msg)
|
||||||
|
|
||||||
|
|
||||||
class ContentType(object):
|
class ContentType(object):
|
||||||
json_request = "application/json"
|
json_request = "application/json"
|
||||||
json_response = "application/json;charset=UTF-8"
|
json_response = "application/json;charset=UTF-8"
|
||||||
@ -137,6 +144,11 @@ class APIView(View):
|
|||||||
return self.error(err="invalid-request", msg=str(e))
|
return self.error(err="invalid-request", msg=str(e))
|
||||||
try:
|
try:
|
||||||
return super(APIView, self).dispatch(request, *args, **kwargs)
|
return super(APIView, self).dispatch(request, *args, **kwargs)
|
||||||
|
except APIError as e:
|
||||||
|
ret = {"msg": e.msg}
|
||||||
|
if e.err:
|
||||||
|
ret["err"] = e.err
|
||||||
|
return self.error(**ret)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
return self.server_error()
|
return self.server_error()
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user