vbv/server/vbv_lernwelt/core/views.py

188 lines
5.9 KiB
Python

# Create your views here.
import glob
from pathlib import Path
import requests
import structlog
from django.conf import settings
from django.contrib.auth import authenticate, login, logout
from django.core.management import call_command
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render
from django.template import loader
from django.views.decorators.csrf import ensure_csrf_cookie
from django_ratelimit.decorators import ratelimit
from rest_framework import authentication
from rest_framework.decorators import (
api_view,
authentication_classes,
permission_classes,
)
from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response
from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
from vbv_lernwelt.core.serializers import UserSerializer
logger = structlog.get_logger(__name__)
@django_view_authentication_exempt
@ensure_csrf_cookie
def vue_home(request, *args):
if settings.IT_SERVE_VUE:
try:
res = requests.get(f"{settings.IT_SERVE_VUE_URL}{request.get_full_path()}")
content = res.text
headers = res.headers
content_type = headers.get("content-type", "text/html")
return HttpResponse(content, content_type=content_type)
except Exception as e:
return HttpResponse(
f"Can not connect to vue dev server at {settings.IT_SERVE_VUE_URL}: {e}"
)
# render index.html from `npm run build`
content = loader.render_to_string("vue/index.html", context={}, request=request)
return HttpResponse(content)
@api_view(["POST"])
@ensure_csrf_cookie
def vue_login(request):
if settings.ALLOW_LOCAL_LOGIN:
try:
username = request.data.get("username")
password = request.data.get("password")
if username and password:
user = authenticate(request, username=username, password=password)
if user:
login(request, user)
logger.debug(
"login successful",
username=username,
email=user.email,
label="login",
)
return Response(UserSerializer(user).data)
except Exception as e:
logger.exception(e)
logger.debug("login failed", username=username, label="login")
return Response({"success": False}, status=401)
else:
return Response(
{"success": False, "message": "ALLOW_LOCAL_LOGIN=false"}, status=403
)
@api_view(["GET", "PUT"])
def me_user_view(request):
if not request.user.is_authenticated:
return Response(status=403)
if request.method == "GET":
return Response(UserSerializer(request.user).data)
if request.method == "PUT":
serializer = UserSerializer(
request.user,
data={"language": request.data.get("language", "de")},
partial=True,
)
if serializer.is_valid():
serializer.save()
return Response(UserSerializer(request.user).data)
return Response(status=400)
@api_view(["POST"])
def vue_logout(request):
logout(request)
return Response({"success": True}, 200)
def permission_denied_view(request, exception):
return render(request, "403.html", status=403)
def rate_limit_exceeded_view(request, exception):
return render(request, "429.html", status=429)
@django_view_authentication_exempt
def server_json_error(request, *args, **kwargs):
"""
Generic 500 error handler.
"""
data = {
"detail": "Server Error (500)",
"status_code": 500,
}
return JsonResponse(data, status=500)
@ratelimit(key="ip", rate="5/m", block=True)
@django_view_authentication_exempt
def check_rate_limit(request):
return HttpResponse(content=b"Hello")
@api_view(["POST"])
@authentication_classes((authentication.SessionAuthentication,))
@permission_classes((IsAdminUser,))
def cypress_reset_view(request):
if not settings.APP_ENVIRONMENT.startswith("prod"):
# Checking for the flags in the POST request
create_assignment_completion = (
request.data.get("create_assignment_completion") == "true"
)
create_assignment_evaluation = (
request.data.get("create_assignment_evaluation") == "true"
)
create_edoniq_test_results = (
request.data.get("create_edoniq_test_results") == "true"
)
# TODO: Handle the flags as needed. For example:
if create_assignment_completion:
# Logic for creating assignment completion
pass
if create_edoniq_test_results:
# Logic for creating Edoniq test results
pass
call_command(
"cypress_reset",
create_assignment_completion=create_assignment_completion,
create_assignment_evaluation=create_assignment_evaluation,
create_edoniq_test_results=create_edoniq_test_results,
)
return HttpResponseRedirect("/server/admin/")
@django_view_authentication_exempt
def generate_web_component_icons(request):
svg_files = []
for filepath in glob.iglob(f"{settings.APPS_DIR}/static/icons/*.svg"):
with open(filepath, "r") as f:
filename = Path(filepath).stem
elementname = "it-" + filename
svg_files.append(
{
"filepath": filepath,
"content": f.read(),
"filename": filename,
"elementname": elementname,
"classname": filename.replace("-", "_"),
}
)
return render(
request,
"core/icons.html",
context={"svg_files": svg_files},
content_type="application/javascript",
)