import structlog from django.shortcuts import get_object_or_404 from rest_framework.decorators import api_view from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response from wagtail.models import Page from vbv_lernwelt.core.utils import get_django_content_type from vbv_lernwelt.course.models import ( CircleDocument, CourseCompletion, CourseSession, CourseSessionUser, ) from vbv_lernwelt.course.permissions import ( course_sessions_for_user_qs, has_course_access, has_course_access_by_page_request, is_circle_expert, is_course_session_expert, ) from vbv_lernwelt.course.serializers import ( CourseCompletionSerializer, CourseSessionSerializer, DocumentUploadFinishInputSerializer, DocumentUploadStartInputSerializer, ) from vbv_lernwelt.course.services import mark_course_completion from vbv_lernwelt.files.models import UploadFile from vbv_lernwelt.files.services import FileDirectUploadService logger = structlog.get_logger(__name__) @api_view(["GET"]) def course_page_api_view(request, slug_or_id): try: if slug_or_id.isdigit(): page = Page.objects.get(id=slug_or_id) else: page = Page.objects.get(slug=slug_or_id) if not has_course_access_by_page_request(request, page): raise PermissionDenied() data = page.specific.get_serializer_class()(page.specific).data return Response(data) except PermissionDenied as e: raise e except Exception as e: logger.exception(e) return Response({"error": str(e)}, status=404) def _request_course_completion(course_session_id, user_id): try: response_data = CourseCompletionSerializer( CourseCompletion.objects.filter( user_id=user_id, course_session_id=course_session_id ), many=True, ).data return Response(status=200, data=response_data) except PermissionDenied as e: raise e except Exception as e: logger.error(e) return Response({"error": str(e)}, status=404) @api_view(["GET"]) def request_course_completion(request, course_session_id): course_id = get_object_or_404(CourseSession, id=course_session_id).course_id if has_course_access(request.user, course_id): return _request_course_completion(course_session_id, request.user.id) raise PermissionDenied() @api_view(["GET"]) def request_course_completion_for_user(request, course_session_id, user_id): if request.user.id == user_id or is_course_session_expert( request.user, course_session_id ): return _request_course_completion(course_session_id, user_id) raise PermissionDenied() @api_view(["POST"]) def mark_course_completion_view(request): try: page_id = request.data.get("page_id") completion_status = request.data.get("completion_status", "SUCCESS") course_session_id = request.data.get("course_session_id") page = Page.objects.get(id=page_id) if not has_course_access_by_page_request(request, page): raise PermissionDenied() mark_course_completion( page=page, user=request.user, course_session=CourseSession.objects.get(id=course_session_id), completion_status=completion_status, ) response_data = CourseCompletionSerializer( CourseCompletion.objects.filter( user=request.user, course_session_id=course_session_id ), many=True, ).data logger.debug( "mark_course_completion successful", label="completion_api", page_id=page_id, page_type=get_django_content_type(page.specific), page_slug=page.slug, page_title=page.title, user_id=request.user.id, course_session_id=course_session_id, completion_status=completion_status, ) return Response(status=200, data=response_data) except PermissionDenied as e: raise e except Exception as e: logger.error(e, exc_info=True) return Response({"error": str(e)}, status=404) @api_view(["GET"]) def get_course_sessions(request): try: course_sessions = course_sessions_for_user_qs(request.user).prefetch_related( "course" ) return Response( status=200, data=CourseSessionSerializer(course_sessions, many=True).data ) except PermissionDenied as e: raise e except Exception as e: logger.error(e, exc_info=True) return Response({"error": str(e)}, status=404) @api_view(["POST"]) def document_upload_start(request): serializer = DocumentUploadStartInputSerializer(data=request.data) serializer.is_valid(raise_exception=True) if not is_circle_expert( request.user, serializer.validated_data["course_session"], serializer.validated_data["learning_sequence"], ): raise PermissionDenied() service = FileDirectUploadService(request.user) file, presigned_data = service.start( serializer.validated_data["file_name"], serializer.validated_data["file_type"] ) document = CircleDocument( file=file, name=serializer.validated_data["name"], course_session_id=serializer.validated_data["course_session"], learning_sequence_id=serializer.validated_data["learning_sequence"], ) document.save() presigned_data["id"] = document.id presigned_data["file_id"] = file.id return Response(data=presigned_data) @api_view(["POST"]) def document_upload_finish(request): serializer = DocumentUploadFinishInputSerializer(data=request.data) serializer.is_valid(raise_exception=True) file_id = serializer.validated_data["file_id"] file = get_object_or_404(UploadFile, id=file_id) if file.uploaded_by != request.user: raise PermissionDenied() service = FileDirectUploadService(request.user) service.finish(file=file) return Response({"url": file.url}) @api_view(["POST"]) def document_direct_upload(request, file_id): file = get_object_or_404(UploadFile, id=file_id) file_obj = request.FILES["file"] service = FileDirectUploadService(request.user) file = service.upload_local(file=file, file_obj=file_obj) return Response({"url": file.url}) @api_view(["DELETE"]) def document_delete(request, document_id): document = get_object_or_404(CircleDocument, id=document_id) if not is_circle_expert( request.user, document.course_session.id, document.learning_sequence.id ): raise PermissionDenied() document.delete() return Response(status=200)