import hashlib from django.utils import timezone from account.decorators import super_admin_required from judge.dispatcher import process_pending_task from judge.languages import languages, spj_languages from options.options import SysOptions from utils.api import APIView, CSRFExemptAPIView, validate_serializer from .models import JudgeServer from .serializers import (CreateEditWebsiteConfigSerializer, CreateSMTPConfigSerializer, EditSMTPConfigSerializer, JudgeServerHeartbeatSerializer, JudgeServerSerializer, TestSMTPConfigSerializer) class SMTPAPI(APIView): @super_admin_required def get(self, request): smtp = SysOptions.smtp_config if not smtp: return self.success(None) smtp.pop("password") return self.success(smtp) @validate_serializer(CreateSMTPConfigSerializer) @super_admin_required def post(self, request): SysOptions.smtp_config = request.data return self.success() @validate_serializer(EditSMTPConfigSerializer) @super_admin_required def put(self, request): smtp = SysOptions.smtp_config data = request.data for item in ["server", "port", "email", "tls"]: smtp[item] = data[item] if "password" in data: smtp["password"] = data["password"] SysOptions.smtp_config = smtp return self.success() class SMTPTestAPI(APIView): @super_admin_required @validate_serializer(TestSMTPConfigSerializer) def post(self, request): return self.success({"result": True}) class WebsiteConfigAPI(APIView): def get(self, request): ret = {key: getattr(SysOptions, key) for key in ["website_base_url", "website_name", "website_name_shortcut", "website_footer", "allow_register", "submission_list_show_all"]} return self.success(ret) @validate_serializer(CreateEditWebsiteConfigSerializer) @super_admin_required def post(self, request): for k, v in request.data.items(): setattr(SysOptions, k, v) return self.success() class JudgeServerAPI(APIView): @super_admin_required def get(self, request): servers = JudgeServer.objects.all().order_by("-last_heartbeat") return self.success({"token": SysOptions.judge_server_token, "servers": JudgeServerSerializer(servers, many=True).data}) @super_admin_required def delete(self, request): hostname = request.GET.get("hostname") if hostname: JudgeServer.objects.filter(hostname=hostname).delete() return self.success() class JudgeServerHeartbeatAPI(CSRFExemptAPIView): @validate_serializer(JudgeServerHeartbeatSerializer) def post(self, request): data = request.data client_token = request.META.get("HTTP_X_JUDGE_SERVER_TOKEN") if hashlib.sha256(SysOptions.judge_server_token.encode("utf-8")).hexdigest() != client_token: return self.error("Invalid token") service_url = data.get("service_url") try: server = JudgeServer.objects.get(hostname=data["hostname"]) server.judger_version = data["judger_version"] server.cpu_core = data["cpu_core"] server.memory_usage = data["memory"] server.cpu_usage = data["cpu"] server.service_url = service_url server.ip = request.META["REMOTE_ADDR"] server.last_heartbeat = timezone.now() server.save() except JudgeServer.DoesNotExist: JudgeServer.objects.create(hostname=data["hostname"], judger_version=data["judger_version"], cpu_core=data["cpu_core"], memory_usage=data["memory"], cpu_usage=data["cpu"], ip=request.META["REMOTE_ADDR"], service_url=service_url, last_heartbeat=timezone.now(), ) # 新server上线 处理队列中的,防止没有新的提交而导致一直waiting process_pending_task() return self.success() class LanguagesAPI(APIView): def get(self, request): return self.success({"languages": languages, "spj_languages": spj_languages})