mirror of
https://github.com/QingdaoU/OnlineJudge.git
synced 2024-09-21 16:33:22 +00:00
Merge branch 'new-arch' into otp-auth
* new-arch: fix error package name and add pip mirrorwq 废弃 huey,多数据库连接的时候存在 connection 无法释放的问题,回到 celery 修复 huey 队列不会释放数据库连接的问题,是用法不对 修复typo 完善 sso 登录部分 修复typo 规范配置文件写法;数据库用户名也在环境变量中取 个人博客链接前面也增加图标 修改判题机器的配置文件 删除不再使用的配置文件 Conflicts: account/views.py
This commit is contained in:
commit
23f804476a
2
.gitignore
vendored
2
.gitignore
vendored
@ -52,7 +52,7 @@ db.db
|
|||||||
#redis dump
|
#redis dump
|
||||||
*.rdb
|
*.rdb
|
||||||
#*.out
|
#*.out
|
||||||
db.sqlite3
|
*.sqlite3
|
||||||
.DS_Store
|
.DS_Store
|
||||||
log/
|
log/
|
||||||
static/release/css
|
static/release/css
|
||||||
|
8
account/tasks.py
Normal file
8
account/tasks.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
from celery import shared_task
|
||||||
|
from utils.mail import send_email
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def _send_email(from_name, to_email, to_name, subject, content):
|
||||||
|
send_email(from_name, to_email, to_name, subject, content)
|
@ -16,9 +16,10 @@ from rest_framework.response import Response
|
|||||||
from utils.shortcuts import (serializer_invalid_response, error_response,
|
from utils.shortcuts import (serializer_invalid_response, error_response,
|
||||||
success_response, error_page, paginate, rand_str)
|
success_response, error_page, paginate, rand_str)
|
||||||
from utils.captcha import Captcha
|
from utils.captcha import Captcha
|
||||||
from utils.mail import send_email
|
|
||||||
from utils.otp_auth import OtpAuth
|
from utils.otp_auth import OtpAuth
|
||||||
|
|
||||||
|
from .tasks import _send_email
|
||||||
|
|
||||||
from .decorators import login_required
|
from .decorators import login_required
|
||||||
from .models import User, UserProfile
|
from .models import User, UserProfile
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ def index_page(request):
|
|||||||
return render(request, "oj/index.html")
|
return render(request, "oj/index.html")
|
||||||
|
|
||||||
if request.META.get('HTTP_REFERER') or request.GET.get("index"):
|
if request.META.get('HTTP_REFERER') or request.GET.get("index"):
|
||||||
return render(request, "oj/index.html")
|
return render(request, "oj/index.html")
|
||||||
else:
|
else:
|
||||||
return http.HttpResponseRedirect('/problems/')
|
return http.HttpResponseRedirect('/problems/')
|
||||||
|
|
||||||
@ -300,22 +301,25 @@ class ApplyResetPasswordAPIView(APIView):
|
|||||||
user = User.objects.get(email=data["email"])
|
user = User.objects.get(email=data["email"])
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return error_response(u"用户不存在")
|
return error_response(u"用户不存在")
|
||||||
if user.reset_password_token_create_time and (now() - user.reset_password_token_create_time).total_seconds() < 20 * 60:
|
if user.reset_password_token_create_time and (
|
||||||
|
now() - user.reset_password_token_create_time).total_seconds() < 20 * 60:
|
||||||
return error_response(u"20分钟内只能找回一次密码")
|
return error_response(u"20分钟内只能找回一次密码")
|
||||||
user.reset_password_token = rand_str()
|
user.reset_password_token = rand_str()
|
||||||
user.reset_password_token_create_time = now()
|
user.reset_password_token_create_time = now()
|
||||||
user.save()
|
user.save()
|
||||||
email_template = codecs.open(settings.TEMPLATES[0]["DIRS"][0] + "utils/reset_password_email.html", "r", "utf-8").read()
|
email_template = codecs.open(settings.TEMPLATES[0]["DIRS"][0] + "utils/reset_password_email.html", "r",
|
||||||
|
"utf-8").read()
|
||||||
|
|
||||||
email_template = email_template.replace("{{ username }}", user.username).\
|
email_template = email_template.replace("{{ username }}", user.username). \
|
||||||
replace("{{ website_name }}", settings.WEBSITE_INFO["website_name"]).\
|
replace("{{ website_name }}", settings.WEBSITE_INFO["website_name"]). \
|
||||||
replace("{{ link }}", request.scheme + "://" + request.META['HTTP_HOST'] + "/reset_password/t/" + user.reset_password_token)
|
replace("{{ link }}", request.scheme + "://" + request.META[
|
||||||
|
'HTTP_HOST'] + "/reset_password/t/" + user.reset_password_token)
|
||||||
|
|
||||||
send_email(settings.WEBSITE_INFO["website_name"],
|
_send_email.delay(settings.WEBSITE_INFO["website_name"],
|
||||||
user.email,
|
user.email,
|
||||||
user.username,
|
user.username,
|
||||||
settings.WEBSITE_INFO["website_name"] + u" 登录信息找回邮件",
|
settings.WEBSITE_INFO["website_name"] + u" 登录信息找回邮件",
|
||||||
email_template)
|
email_template)
|
||||||
return success_response(u"邮件发送成功,请前往您的邮箱查收")
|
return success_response(u"邮件发送成功,请前往您的邮箱查收")
|
||||||
else:
|
else:
|
||||||
return serializer_invalid_response(serializer)
|
return serializer_invalid_response(serializer)
|
||||||
@ -363,7 +367,10 @@ class SSOAPIView(APIView):
|
|||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
try:
|
try:
|
||||||
user = User.objects.get(auth_token=serializer.data["token"])
|
user = User.objects.get(auth_token=serializer.data["token"])
|
||||||
return success_response({"username": user.username})
|
user.auth_token = None
|
||||||
|
user.save()
|
||||||
|
return success_response(
|
||||||
|
{"username": user.username, "admin_type": user.admin_type, "avatar": user.userprofile.avatar})
|
||||||
except User.DoesNotExist:
|
except User.DoesNotExist:
|
||||||
return error_response(u"用户不存在")
|
return error_response(u"用户不存在")
|
||||||
else:
|
else:
|
||||||
@ -377,7 +384,8 @@ class SSOAPIView(APIView):
|
|||||||
token = rand_str()
|
token = rand_str()
|
||||||
request.user.auth_token = token
|
request.user.auth_token = token
|
||||||
request.user.save()
|
request.user.save()
|
||||||
return render(request, "oj/account/sso.html", {"redirect_url": callback + "?token=" + token, "callback": callback})
|
return render(request, "oj/account/sso.html",
|
||||||
|
{"redirect_url": callback + "?token=" + token, "callback": callback})
|
||||||
|
|
||||||
|
|
||||||
def reset_password_page(request, token):
|
def reset_password_page(request, token):
|
||||||
|
@ -3,6 +3,6 @@ ENV PYTHONBUFFERED 1
|
|||||||
RUN mkdir -p /code/log /code/test_case /code/upload
|
RUN mkdir -p /code/log /code/test_case /code/upload
|
||||||
WORKDIR /code
|
WORKDIR /code
|
||||||
ADD requirements.txt /code/
|
ADD requirements.txt /code/
|
||||||
RUN pip install -r requirements.txt
|
RUN pip install -i http://pypi.douban.com/simple -r requirements.txt --trusted-host pypi.douban.com
|
||||||
EXPOSE 8010
|
EXPOSE 8010
|
||||||
CMD supervisord
|
CMD supervisord
|
@ -11,4 +11,5 @@ supervisor
|
|||||||
pillow
|
pillow
|
||||||
jsonfield
|
jsonfield
|
||||||
Envelopes
|
Envelopes
|
||||||
huey
|
celery
|
||||||
|
django-celery
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[program:mq]
|
[program:task_queue]
|
||||||
|
|
||||||
command=python manage.py run_huey
|
command=python manage.py celeryd -B -l DEBUG
|
||||||
|
|
||||||
directory=/code/
|
directory=/code/
|
||||||
user=root
|
user=root
|
||||||
|
@ -22,7 +22,7 @@ class GroupAPIViewBase(object):
|
|||||||
def get_group(self, request, group_id):
|
def get_group(self, request, group_id):
|
||||||
"""
|
"""
|
||||||
根据group_id查询指定的小组的信息,结合判断用户权限
|
根据group_id查询指定的小组的信息,结合判断用户权限
|
||||||
管理员可以查询所有的小组,其他用户查询自己创建的自傲组
|
管理员可以查询所有的小组,其他用户查询自己创建的小组
|
||||||
"""
|
"""
|
||||||
if request.user.admin_type == SUPER_ADMIN:
|
if request.user.admin_type == SUPER_ADMIN:
|
||||||
group = Group.objects.get(id=group_id)
|
group = Group.objects.get(id=group_id)
|
||||||
|
@ -32,7 +32,7 @@ class JudgeDispatcher(object):
|
|||||||
if servers.exists():
|
if servers.exists():
|
||||||
return servers.first()
|
return servers.first()
|
||||||
|
|
||||||
def judge(self, is_waiting_task=False):
|
def judge(self):
|
||||||
self.submission.judge_start_time = int(time.time() * 1000)
|
self.submission.judge_start_time = int(time.time() * 1000)
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
@ -89,7 +89,7 @@ class JudgeDispatcher(object):
|
|||||||
submission = Submission.objects.get(id=waiting_submission.submission_id)
|
submission = Submission.objects.get(id=waiting_submission.submission_id)
|
||||||
waiting_submission.delete()
|
waiting_submission.delete()
|
||||||
|
|
||||||
_judge(submission, time_limit=waiting_submission.time_limit,
|
_judge.delay(submission, time_limit=waiting_submission.time_limit,
|
||||||
memory_limit=waiting_submission.memory_limit, test_case_id=waiting_submission.test_case_id,
|
memory_limit=waiting_submission.memory_limit, test_case_id=waiting_submission.test_case_id,
|
||||||
is_waiting_task=True)
|
is_waiting_task=True)
|
||||||
|
|
||||||
|
@ -7,3 +7,8 @@
|
|||||||
|___/ |___/ |_|
|
|___/ |___/ |_|
|
||||||
https://github.com/QingdaoU/OnlineJudge
|
https://github.com/QingdaoU/OnlineJudge
|
||||||
"""
|
"""
|
||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
# This will make sure the app is always imported when
|
||||||
|
# Django starts so that shared_task will use this app.
|
||||||
|
from .celery import app as celery_app
|
19
oj/celery.py
Normal file
19
oj/celery.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
# set the default Django settings module for the 'celery' program.
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'oj.settings')
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
app = Celery('oj')
|
||||||
|
|
||||||
|
# Using a string here means the worker will not have to
|
||||||
|
# pickle the object when using Windows.
|
||||||
|
app.config_from_object('django.conf:settings')
|
||||||
|
|
||||||
|
# load task modules from all registered Django app configs.
|
||||||
|
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
@ -28,6 +28,12 @@ REDIS_QUEUE = {
|
|||||||
"db": 2
|
"db": 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# for celery
|
||||||
|
BROKER_URL = 'redis://%s:%s/%s' % (REDIS_QUEUE["host"], str(REDIS_QUEUE["port"]), str(REDIS_QUEUE["db"]))
|
||||||
|
ACCEPT_CONTENT = ['json']
|
||||||
|
|
||||||
|
|
||||||
DEBUG = True
|
DEBUG = True
|
||||||
|
|
||||||
ALLOWED_HOSTS = []
|
ALLOWED_HOSTS = []
|
||||||
|
@ -37,6 +37,12 @@ REDIS_QUEUE = {
|
|||||||
"db": 2
|
"db": 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# for celery
|
||||||
|
BROKER_URL = 'redis://%s:%s/%s' % (REDIS_QUEUE["host"], str(REDIS_QUEUE["port"]), str(REDIS_QUEUE["db"]))
|
||||||
|
ACCEPT_CONTENT = ['json']
|
||||||
|
|
||||||
|
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['*']
|
ALLOWED_HOSTS = ['*']
|
||||||
|
@ -10,7 +10,7 @@ https://docs.djangoproject.com/en/1.8/topics/settings/
|
|||||||
For the full list of settings and their values, see
|
For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/1.8/ref/settings/
|
https://docs.djangoproject.com/en/1.8/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
from __future__ import absolute_import
|
||||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -22,6 +22,9 @@ if ENV == "local":
|
|||||||
elif ENV == "server":
|
elif ENV == "server":
|
||||||
from .server_settings import *
|
from .server_settings import *
|
||||||
|
|
||||||
|
import djcelery
|
||||||
|
djcelery.setup_loader()
|
||||||
|
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
|
||||||
@ -53,7 +56,7 @@ INSTALLED_APPS = (
|
|||||||
'judge_dispatcher',
|
'judge_dispatcher',
|
||||||
|
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'huey.djhuey',
|
'djcelery',
|
||||||
)
|
)
|
||||||
|
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
@ -186,14 +189,6 @@ WEBSITE_INFO = {"website_name": "qduoj",
|
|||||||
"website_footer": u"青岛大学信息工程学院 创新实验室 <a href=\"http://www.miibeian.gov.cn/\">京ICP备15062075号-1</a>",
|
"website_footer": u"青岛大学信息工程学院 创新实验室 <a href=\"http://www.miibeian.gov.cn/\">京ICP备15062075号-1</a>",
|
||||||
"url": "https://qduoj.com"}
|
"url": "https://qduoj.com"}
|
||||||
|
|
||||||
HUEY = {
|
|
||||||
'backend': 'huey.backends.redis_backend',
|
|
||||||
'name': 'task_queue',
|
|
||||||
'connection': {'host': REDIS_QUEUE["host"], 'port': REDIS_QUEUE["port"], 'db': REDIS_QUEUE["db"]},
|
|
||||||
'always_eager': False, # Defaults to False when running via manage.py run_huey
|
|
||||||
# Options to pass into the consumer when running ``manage.py run_huey``
|
|
||||||
'consumer_options': {'workers': 50},
|
|
||||||
}
|
|
||||||
|
|
||||||
SMTP_CONFIG = {"smtp_server": "smtp.mxhichina.com",
|
SMTP_CONFIG = {"smtp_server": "smtp.mxhichina.com",
|
||||||
"email": "noreply@qduoj.com",
|
"email": "noreply@qduoj.com",
|
||||||
|
@ -2,8 +2,8 @@ require(["jquery", "bsAlert", "csrfToken", "validator"], function ($, bsAlert, c
|
|||||||
var applied_captcha = false;
|
var applied_captcha = false;
|
||||||
$('form').validator().on('submit', function (e) {
|
$('form').validator().on('submit', function (e) {
|
||||||
if (!e.isDefaultPrevented()) {
|
if (!e.isDefaultPrevented()) {
|
||||||
var loca = location.href.split("/");
|
var splited_location = location.href.split("/");
|
||||||
var token = loca[loca.length-2];
|
var token = splited_location[splited_location.length-2];
|
||||||
var captcha = $("#captcha").val();
|
var captcha = $("#captcha").val();
|
||||||
var password = $("#new_password").val();
|
var password = $("#new_password").val();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
# coding=utf-8
|
# coding=utf-8
|
||||||
from huey.djhuey import task
|
from __future__ import absolute_import
|
||||||
|
from celery import shared_task
|
||||||
from judge_dispatcher.tasks import JudgeDispatcher
|
from judge_dispatcher.tasks import JudgeDispatcher
|
||||||
|
|
||||||
|
|
||||||
@task()
|
@shared_task
|
||||||
def _judge(submission, time_limit, memory_limit, test_case_id, is_waiting_task=False):
|
def _judge(submission, time_limit, memory_limit, test_case_id):
|
||||||
JudgeDispatcher(submission, time_limit, memory_limit, test_case_id).judge(is_waiting_task)
|
JudgeDispatcher(submission, time_limit, memory_limit, test_case_id).judge()
|
@ -43,7 +43,7 @@ class SubmissionAPIView(APIView):
|
|||||||
problem_id=problem.id)
|
problem_id=problem.id)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_judge(submission, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
_judge.delay(submission, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
return error_response(u"提交判题任务失败")
|
return error_response(u"提交判题任务失败")
|
||||||
@ -88,7 +88,7 @@ class ContestSubmissionAPIView(APIView):
|
|||||||
code=data["code"],
|
code=data["code"],
|
||||||
problem_id=problem.id)
|
problem_id=problem.id)
|
||||||
try:
|
try:
|
||||||
_judge(submission, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
_judge.delay(submission, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
return error_response(u"提交判题任务失败")
|
return error_response(u"提交判题任务失败")
|
||||||
@ -273,7 +273,7 @@ class SubmissionRejudgeAdminAPIView(APIView):
|
|||||||
except Problem.DoesNotExist:
|
except Problem.DoesNotExist:
|
||||||
return error_response(u"题目不存在")
|
return error_response(u"题目不存在")
|
||||||
try:
|
try:
|
||||||
_judge(submission, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
_judge.delay(submission, problem.time_limit, problem.memory_limit, problem.test_case_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
return error_response(u"提交判题任务失败")
|
return error_response(u"提交判题任务失败")
|
||||||
|
Loading…
Reference in New Issue
Block a user