This commit is contained in:
Egor Matveev 2022-03-18 22:43:13 +03:00
parent fad0b72bea
commit d45b5e9115
13 changed files with 124 additions and 125 deletions

View File

@ -1,22 +1,15 @@
import datetime
from typing import Optional
import pytz
from django.utils import timezone
from Checker.models import Checker
from Main.models import SetTask, Set
from Main.models import Set
from SprintLib.BaseView import BaseView, AccessError
from SprintLib.language import languages
class CheckersView(BaseView):
required_login = True
view_file = "checkers.html"
endpoint = "admin/checkers"
set: Set
def pre_handle(self):
self.current_set = self.entities.set
self.current_set = self.set
if (
self.request.user != self.current_set.creator
and self.request.user.username not in self.current_set.editors

View File

@ -1,5 +1,6 @@
from django.http import HttpResponse
from Main.models import Dump
from SprintLib.BaseView import BaseView, AccessError
from SprintLib.utils import get_bytes
@ -7,14 +8,14 @@ from SprintLib.utils import get_bytes
class DownloadFileView(BaseView):
endpoint = "download_file"
required_login = True
dump: Dump
def get(self):
dump = self.entities.dump
if dump.task:
if self.request.user == dump.task.creator or self.request.user.username in dump.task.editors:
if self.dump.task:
if self.request.user == self.dump.task.creator or self.request.user.username in self.dump.task.editors:
response = HttpResponse(
get_bytes(dump.fs_id), content_type='application/force-download'
get_bytes(self.dump.fs_id), content_type='application/force-download'
)
response['Content-Disposition'] = f'inline; filename={dump.filename}'
response['Content-Disposition'] = f'inline; filename={self.dump.filename}'
return response
raise AccessError()

View File

@ -1,5 +1,6 @@
from django.contrib.auth.models import User
from Main.models import Group
from SprintLib.BaseView import BaseView, AccessError
from SprintLib.utils import generate_token
@ -9,50 +10,51 @@ class GroupView(BaseView):
endpoint = 'group'
view_file = 'group.html'
owner = False
group: Group
def pre_handle(self):
self.owner = self.entities.group.creator == self.request.user or self.request.user.username in self.entities.group.editors
self.owner = self.group.creator == self.request.user or self.request.user.username in self.group.editors
def get(self):
if self.owner:
self.context['possible_users'] = set(self.entities.group.users.all()) | set(self.request.user.userinfo.verified_friends)
self.context['possible_users'] = set(self.group.users.all()) | set(self.request.user.userinfo.verified_friends)
def post_sets_edit(self):
if not self.owner:
raise AccessError()
current_sets = self.entities.group.sets.all()
current_sets = self.group.sets.all()
set_ids = [set.id for set in current_sets]
for key, value in self.request.POST.items():
if key.startswith("set_"):
i = int(key.split("_")[1])
if i not in set_ids:
self.entities.group.sets.add(i)
self.group.sets.add(i)
to_delete = [i for i in set_ids if "set_" + str(i) not in self.request.POST]
for t in to_delete:
self.entities.group.sets.remove(t)
return "/group?group_id=" + str(self.entities.group.id)
self.group.sets.remove(t)
return "/group?group_id=" + str(self.group.id)
def post_users_edit(self):
if not self.owner:
raise AccessError()
current_users = self.entities.group.users.all()
current_users = self.group.users.all()
users_ids = [user.id for user in current_users]
for key, value in self.request.POST.items():
if key.startswith("user_"):
i = int(key.split("_")[1])
if i not in users_ids:
self.entities.group.users.add(i)
self.group.users.add(i)
to_delete = [i for i in users_ids if "user_" + str(i) not in self.request.POST]
for t in to_delete:
self.entities.group.users.remove(t)
return "/group?group_id=" + str(self.entities.group.id)
self.group.users.remove(t)
return "/group?group_id=" + str(self.group.id)
def link_action(self, value):
if not self.owner:
raise AccessError()
self.entities.group.access_token = value
self.entities.group.save()
return "/group?group_id=" + str(self.entities.group.id)
self.group.access_token = value
self.group.save()
return "/group?group_id=" + str(self.group.id)
def post_open_link(self):
return self.link_action(generate_token())

View File

@ -1,5 +1,4 @@
import datetime
from typing import Optional
import pytz
from django.utils import timezone
@ -14,28 +13,27 @@ class SetSettingsView(BaseView):
required_login = True
view_file = "set_settings.html"
endpoint = "admin/set"
current_set: Optional[Set] = None
set: Set
def pre_handle(self):
self.current_set = self.entities.set
if (
self.request.user != self.current_set.creator
and self.request.user.username not in self.current_set.editors
self.request.user != self.set.creator
and self.request.user.username not in self.set.editors
):
raise AccessError()
def get(self):
self.context["settasks"] = SetTask.objects.filter(
set=self.current_set
set=self.set
).order_by("name")
self.context["start_time"] = (
self.current_set.start_time_format
if self.current_set.start_time
self.set.start_time_format
if self.set.start_time
else timezone.now().strftime("%Y-%m-%dT%H:%M")
)
self.context["end_time"] = (
self.current_set.end_time_format
if self.current_set.end_time
self.set.end_time_format
if self.set.end_time
else timezone.now().strftime("%Y-%m-%dT%H:%M")
)
self.context['languages'] = languages
@ -46,61 +44,61 @@ class SetSettingsView(BaseView):
st = SetTask.objects.get(id=key.split("_")[1])
st.name = value
st.save()
self.current_set.name = self.request.POST["name"]
self.current_set.description = self.request.POST['description']
self.current_set.save()
return "/admin/set?set_id=" + str(self.current_set.id)
self.set.name = self.request.POST["name"]
self.set.description = self.request.POST['description']
self.set.save()
return "/admin/set?set_id=" + str(self.set.id)
def post_edit(self):
current_tasks = self.entities.set.tasks
current_tasks = self.set.tasks
task_ids = [task.id for task in current_tasks]
for key, value in self.request.POST.items():
if key.startswith("task_"):
i = int(key.split("_")[1])
if i not in task_ids:
SetTask.objects.create(set=self.entities.set, task_id=i)
SetTask.objects.create(set=self.set, task_id=i)
to_delete = [i for i in task_ids if "task_" + str(i) not in self.request.POST]
SetTask.objects.filter(task_id__in=to_delete).delete()
return "/admin/set?set_id=" + str(self.entities.set.id)
return "/admin/set?set_id=" + str(self.set.id)
def post_time(self):
try:
tz = pytz.timezone("Europe/Moscow")
if "start_time_check" in self.request.POST:
self.current_set.start_time = None
self.set.start_time = None
else:
self.current_set.start_time = tz.localize(
self.set.start_time = tz.localize(
datetime.datetime.strptime(
self.request.POST["start_time"], "%Y-%m-%dT%H:%M"
)
)
if "end_time_check" in self.request.POST:
self.current_set.end_time = None
self.set.end_time = None
else:
self.current_set.end_time = tz.localize(
self.set.end_time = tz.localize(
datetime.datetime.strptime(
self.request.POST["end_time"], "%Y-%m-%dT%H:%M"
)
)
self.current_set.opened = 'opened' in self.request.POST.keys()
self.current_set.public = 'public' in self.request.POST.keys()
self.set.opened = 'opened' in self.request.POST.keys()
self.set.public = 'public' in self.request.POST.keys()
except ValueError:
return "/admin/set?set_id=" + str(self.current_set.id)
self.current_set.save()
return "/admin/set?set_id=" + str(self.current_set.id)
return "/admin/set?set_id=" + str(self.set.id)
self.set.save()
return "/admin/set?set_id=" + str(self.set.id)
def post_users_edit(self):
current_users = self.entities.set.editors
current_users = self.set.editors
for key, value in self.request.POST.items():
if key.startswith("user_"):
i = '_'.join(key.split("_")[1:])
if i not in current_users:
self.entities.set.editors.append(i)
self.set.editors.append(i)
to_delete = [i for i in current_users if "user_" + i not in self.request.POST and i != self.request.user.username]
for t in to_delete:
self.entities.set.editors.remove(t)
self.entities.set.save()
return "/admin/set?set_id=" + str(self.entities.set.id)
self.set.editors.remove(t)
self.set.save()
return "/admin/set?set_id=" + str(self.set.id)
def post_languages_edit(self):
current_languages = self.entities.set.languages

View File

@ -1,5 +1,6 @@
from django.utils import timezone
from Main.models import Set
from SprintLib.BaseView import BaseView, AccessError
@ -7,15 +8,16 @@ class SetView(BaseView):
required_login = True
endpoint = "set"
view_file = "set.html"
set: Set
def get(self):
if self.entities.set in self.request.user.userinfo.available_sets:
if self.set in self.request.user.userinfo.available_sets:
return
if (
not self.entities.set.opened
or self.entities.set.start_time is not None
and self.entities.set.start_time > timezone.now()
or self.entities.set.end_time is not None
and self.entities.set.end_time < timezone.now()
not self.set.opened
or self.set.start_time is not None
and self.set.start_time > timezone.now()
or self.set.end_time is not None
and self.set.end_time < timezone.now()
):
raise AccessError()

View File

@ -1,3 +1,4 @@
from Main.models import Solution
from SprintLib.BaseView import BaseView, AccessError
@ -5,9 +6,10 @@ class SolutionView(BaseView):
view_file = "solution.html"
required_login = True
endpoint = "solution"
solution: Solution
def pre_handle(self):
if self.request.user.is_superuser:
return
if self.entities.solution.user != self.request.user:
if self.solution.user != self.request.user:
raise AccessError()

View File

@ -1,4 +1,4 @@
from Main.models import Solution
from Main.models import Solution, Set, Task, SetTask
from SprintLib.BaseView import BaseView, AccessError
@ -8,6 +8,9 @@ class SolutionsTableView(BaseView):
endpoint = "solutions_table"
page_size = 20
page = None
set: Set
task: Task
setTask: SetTask
def pre_handle(self):
if 'page' not in self.request.GET:
@ -18,20 +21,20 @@ class SolutionsTableView(BaseView):
queryset = Solution.objects.all()
if 'teacher' in self.request.GET.keys():
if 'set_id' in self.request.GET.keys():
if self.request.user != self.entities.set.creator and self.request.user.username not in self.entities.set.editors:
if self.request.user != self.set.creator and self.request.user.username not in self.set.editors:
raise AccessError()
queryset = queryset.filter(set_id=self.request.GET['set_id'])
elif 'task_id' in self.request.GET.keys():
if self.request.user != self.entities.task.creator and self.request.user.username not in self.entities.task.editors:
if self.request.user != self.task.creator and self.request.user.username not in self.task.editors:
raise AccessError()
queryset = queryset.filter(task_id=self.request.GET['task_id'], set=None)
else:
raise AccessError()
else:
if hasattr(self.entities, 'setTask'):
queryset = queryset.filter(user=self.request.user, task=self.entities.setTask.task, set=self.entities.setTask.set)
queryset = queryset.filter(user=self.request.user, task=self.setTask.task, set=self.setTask.set)
else:
queryset = queryset.filter(user=self.request.user, task=self.entities.task, set=None)
queryset = queryset.filter(user=self.request.user, task=self.task, set=None)
offset = self.page_size * (self.page - 1)
limit = self.page_size
self.context["solutions"] = queryset.order_by("-id")[offset:offset + limit]

View File

@ -1,4 +1,4 @@
from Main.models import Progress
from Main.models import Progress, Task
from SprintLib.BaseView import BaseView
@ -6,7 +6,8 @@ class TaskRuntimeView(BaseView):
view_file = "task_runtime.html"
required_login = True
endpoint = "task_runtime"
task: Task
def get(self):
progress = Progress.objects.get(task=self.entities.task, user=self.request.user)
progress = Progress.objects.get(task=self.task, user=self.request.user)
self.context["progress"] = progress

View File

@ -1,6 +1,6 @@
from django.http import HttpResponse
from Main.models import ExtraFile, Dump
from Main.models import ExtraFile, Dump, Task
from SprintLib.BaseView import BaseView, AccessError
from SprintLib.queue import send_to_queue
@ -9,9 +9,10 @@ class TaskSettingsView(BaseView):
view_file = "task_settings.html"
required_login = True
endpoint = "admin/task"
task: Task
def pre_handle(self):
if self.request.user != self.entities.task.creator and self.request.user.username not in self.entities.task.editors:
if self.request.user != self.task.creator and self.request.user.username not in self.task.editors:
raise AccessError()
def get(self):
@ -19,15 +20,15 @@ class TaskSettingsView(BaseView):
def post(self):
for key, value in self.request.POST.items():
setattr(self.entities.task, key, value.strip())
self.entities.task.public = "public" in self.request.POST
self.entities.task.save()
return f"/admin/task?task_id={self.entities.task.id}"
setattr(self.task, key, value.strip())
self.task.public = "public" in self.request.POST
self.task.save()
return f"/admin/task?task_id={self.task.id}"
def post_dump(self):
dump = Dump.objects.create(executor=self.request.user, task=self.entities.task)
dump = Dump.objects.create(executor=self.request.user, task=self.task)
send_to_queue("files", {"id": dump.id})
return f"/admin/task?task_id={self.entities.task.id}"
return f"/admin/task?task_id={self.task.id}"
def _upload(self, is_test):
filename = self.request.FILES["file"].name
@ -35,17 +36,17 @@ class TaskSettingsView(BaseView):
if is_test:
name = filename.strip(".a")
if not name.isnumeric():
return f"/admin/task?task_id={self.entities.task.id}&error_message=Формат файла не соответствует тесту"
return f"/admin/task?task_id={self.task.id}&error_message=Формат файла не соответствует тесту"
ef, created = ExtraFile.objects.get_or_create(
task=self.entities.task, is_test=True, filename=filename
task=self.task, is_test=True, filename=filename
)
if not created:
ef.is_sample = False
ef.save()
return f"/admin/task?task_id={self.entities.task.id}"
return f"/admin/task?task_id={self.task.id}"
if ef is None or created is None:
ef, created = ExtraFile.objects.get_or_create(
task=self.entities.task, filename=filename, is_test=is_test
task=self.task, filename=filename, is_test=is_test
)
ef.write(self.request.FILES["file"].read())
try:
@ -54,7 +55,7 @@ class TaskSettingsView(BaseView):
except UnicodeDecodeError:
ef.readable = False
ef.save()
return "/admin/task?task_id=" + str(self.entities.task.id)
return "/admin/task?task_id=" + str(self.task.id)
def post_file_upload(self):
return self._upload(False)
@ -71,15 +72,15 @@ class TaskSettingsView(BaseView):
name = self.request.POST["newfile_name"]
ef, created = ExtraFile.objects.get_or_create(
filename=name, task=self.entities.task
filename=name, task=self.task
)
if not created:
return f"/admin/task?task_id={self.entities.task.id}&error_message=Файл с таким именем уже существует"
return f"/admin/task?task_id={self.task.id}&error_message=Файл с таким именем уже существует"
ef.write(b"")
ef.is_test = is_test
ef.readable = True
ef.save()
return f"/admin/task?task_id={self.entities.task.id}"
return f"/admin/task?task_id={self.task.id}"
def post_create_file(self):
return self._create(False)
@ -93,17 +94,17 @@ class TaskSettingsView(BaseView):
ef.write(self.request.POST["text"].encode("utf-8"))
ef.is_sample = "is_sample" in self.request.POST.keys()
ef.save()
return f"/admin/task?task_id={self.entities.task.id}"
return f"/admin/task?task_id={self.task.id}"
def post_users_edit(self):
current_users = self.entities.task.editors
current_users = self.task.editors
for key, value in self.request.POST.items():
if key.startswith("user_"):
i = '_'.join(key.split("_")[1:])
if i not in current_users:
self.entities.task.editors.append(i)
self.task.editors.append(i)
to_delete = [i for i in current_users if "user_" + i not in self.request.POST and i != self.request.user.username]
for t in to_delete:
self.entities.task.editors.remove(t)
self.entities.task.save()
return "/admin/task?task_id=" + str(self.entities.task.id)
self.task.editors.remove(t)
self.task.save()
return "/admin/task?task_id=" + str(self.task.id)

View File

@ -1,7 +1,8 @@
import io
from typing import Optional
from zipfile import ZipFile
from Main.models import Solution, Progress, SolutionFile
from Main.models import Solution, Progress, SolutionFile, SetTask, Task, Set
from SprintLib.BaseView import BaseView, AccessError
from SprintLib.language import languages
from SprintLib.queue import send_to_queue
@ -12,32 +13,37 @@ class TaskView(BaseView):
required_login = True
view_file = "task.html"
endpoint = "task"
setTask: Optional[SetTask] = None
task: Optional[Task] = None
set: Optional[Set] = None
def get(self):
progress, _ = Progress.objects.get_or_create(
user=self.request.user, task=self.entities.task
user=self.request.user, task=self.task
)
self.context["progress"] = progress
self.context["in_set"] = hasattr(self.entities, 'setTask')
self.context["in_set"] = self.set is not None
def pre_handle(self):
if hasattr(self.entities, 'setTask'):
self.entities.add('task', self.entities.setTask.task)
self.entities.add('set', self.entities.setTask.set)
self.context['languages'] = self.entities.set.language_models
if self.setTask:
self.set = self.setTask.set
self.task = self.setTask.task
self.context['set'] = self.set
self.context['task'] = self.task
self.context['languages'] = self.set.language_models
else:
if not self.entities.task.public and not self.entities.task.creator == self.request.user and not self.request.user.username in self.entities.task.editors:
if not self.task.public and self.task.creator != self.request.user and self.request.user.username not in self.task.editors:
raise AccessError()
self.context['languages'] = languages
if self.request.method == "GET":
return
if hasattr(self.entities, 'set') and int(self.request.POST["language"]) not in self.entities.set.languages:
if self.set and int(self.request.POST["language"]) not in self.set.languages:
raise AccessError()
self.solution = Solution.objects.create(
task=self.entities.task,
task=self.task,
user=self.request.user,
language_id=int(self.request.POST["language"]),
set=self.entities.set if hasattr(self.entities, 'setTask') else None,
set=self.set,
extras=dict(),
)
@ -50,12 +56,12 @@ class TaskView(BaseView):
fs_id=fs_id,
)
self.send_testing()
return ("/task?setTask_id=" + str(self.entities.setTask.id)) if hasattr(self.entities, 'setTask') else ("/task?task_id=" + str(self.entities.task.id))
return ("/task?setTask_id=" + str(self.setTask.id)) if self.set else ("/task?task_id=" + str(self.task.id))
def post_1(self):
# отправка решения через файл
if "file" not in self.request.FILES:
return "task?task_id=" + str(self.entities.task.id)
return "task?task_id=" + str(self.task.id)
filename = self.request.FILES["file"].name
if filename.endswith(".zip"):
archive = ZipFile(io.BytesIO(self.request.FILES["file"].read()))
@ -76,7 +82,7 @@ class TaskView(BaseView):
fs_id=fs_id,
)
self.send_testing()
return ("/task?setTask_id=" + str(self.entities.setTask.id)) if hasattr(self.entities, 'setTask') else ("/task?task_id=" + str(self.entities.task.id))
return ("/task?setTask_id=" + str(self.setTask.id)) if self.set else ("/task?task_id=" + str(self.task.id))
def send_testing(self):
if self.solution.set is not None and len(self.solution.set.checkers.all()) != 0:

View File

@ -5,8 +5,6 @@ from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from django.utils import timezone
from SprintLib.EntityStorage import EntityStorage
class AccessError(Exception):
pass
@ -15,14 +13,12 @@ class AccessError(Exception):
class BaseView:
request: WSGIRequest = None
context: Optional[dict] = None
entities: Optional[EntityStorage] = None
required_login: Optional[bool] = None
view_file: Optional[str] = None
endpoint: Optional[str] = None
def __init__(self, request):
self.context = {}
self.entities = EntityStorage()
self.request = request
@classmethod
@ -40,16 +36,18 @@ class BaseView:
return HttpResponseRedirect("/")
request_method = request.method.lower()
exec("from Main.models import *")
context = {}
for key in request.GET.keys():
if key.endswith("_id"):
model_name = key.rstrip("_id")
c.entities.add(
setattr(
c,
model_name,
eval(model_name[0].upper() + model_name[1:]).objects.get(
id=int(request.GET[key])
),
)
context = c.entities.entities
context[model_name] = getattr(c, model_name)
if "action" in request.POST.keys():
request_method += "_" + request.POST["action"]
method = getattr(c, request_method, None)
@ -66,7 +64,7 @@ class BaseView:
return data
context = {**context, **c.context}
res = render(request, c.view_file, context)
res.headers['X-Frame-Options'] = 'ALLOW'
res.headers["X-Frame-Options"] = "ALLOW"
return res
except AccessError:
return HttpResponseRedirect("/")

View File

@ -1,9 +0,0 @@
from django.db.models import Model
class EntityStorage:
entities: dict[str, Model] = {}
def add(self, name, entity):
self.entities[name] = entity
setattr(self, name, entity)

View File

@ -34,6 +34,7 @@
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary"><i class="fa fa-arrow-up"></i> Загрузить</button>
<button type="button" class="btn btn-danger" data-dismiss="modal"><i class="fa fa-times-circle"></i> Закрыть</button>
<button type="submit" class="btn btn-success"><i class="fa fa-plus-circle"></i> Создать</button>
</div>