Verify permissions

This commit is contained in:
Christian Cueni 2022-12-28 16:16:28 +01:00
parent 8ad84cc778
commit fc017961ab
7 changed files with 58 additions and 24 deletions

View File

@ -481,7 +481,7 @@
"value": {
"first_name": "Patrizia",
"last_name": "Huggel",
"email": "patrizia.huggel@example.com",
"email": "patrizia.huggel@eiger-versicherungen.ch",
"photo": null,
"biography": ""
},

View File

@ -3,7 +3,7 @@ import { getCookieValue } from "@/router/guards";
import type { CircleDocument, DocumentUploadData } from "@/types";
async function startFileUpload(fileData: DocumentUploadData, courseSessionId: number) {
return await itPost(`/api/core/document/start`, {
return await itPost(`/api/core/document/start/`, {
file_type: fileData.file.type,
file_name: fileData.file.name,
name: fileData.name,
@ -70,7 +70,7 @@ export async function uploadCircleDocument(
const startData = await startFileUpload(data, courseSessionId);
await uploadFile(startData, data.file);
const response = await itPost(`/api/core/file/finish`, {
const response = await itPost(`/api/core/file/finish/`, {
file_id: startData.file_id,
});

View File

@ -83,11 +83,11 @@ urlpatterns = [
name="request_course_completion_for_user"),
# test
path(r'api/core/document/start', document_upload_start,
path(r'api/core/document/start/', document_upload_start,
name='file_upload_start'),
path(r'api/core/document/<str:document_id>/', document_delete,
name='document_delete'),
path(r'api/core/file/finish', document_upload_finish,
path(r'api/core/file/finish/', document_upload_finish,
name='file_upload_finish'),
path(r"api/core/document/local/<str:file_id>/", document_direct_upload,
name='file_upload_local'),

View File

@ -138,7 +138,7 @@ def create_test_learning_path(user=None, skip_locales=True):
{
"last_name": "Huggel",
"first_name": "Patrizia",
"email": "patrizia.huggel@example.com",
"email": "patrizia.huggel@eiger-versicherungen.ch",
},
),
],

View File

@ -1,4 +1,5 @@
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
from vbv_lernwelt.learnpath.models import LearningSequence
def has_course_access_by_page_request(request, obj):
@ -24,3 +25,24 @@ def course_sessions_for_user_qs(user):
course_sessions = CourseSession.objects.filter(coursesessionuser__user=user)
return course_sessions
def is_circle_expert(user, learning_sequence, course) -> bool:
if user.is_superuser:
return True
try:
ls = LearningSequence.objects.get(id=learning_sequence)
except LearningSequence.DoesNotExist:
return False
if not CourseSession.objects.filter(
id=course, coursesessionuser__user=user
).exists():
return False
for expert in ls.get_parent().circle.experts.raw_data:
if expert["value"]["email"] == user.email:
return True
return False

View File

@ -6,7 +6,7 @@ from vbv_lernwelt.course.consts import COURSE_TEST_ID
from vbv_lernwelt.course.creators.test_course import create_test_course
from vbv_lernwelt.course.models import CircleDocument, CourseSession, CourseSessionUser
from vbv_lernwelt.files.models import File
from vbv_lernwelt.learnpath.models import Circle, LearningSequence
from vbv_lernwelt.learnpath.models import LearningSequence
class DocumentUploadApiTestCase(APITestCase):
@ -29,7 +29,6 @@ class DocumentUploadApiTestCase(APITestCase):
user=User.objects.get(username="patrizia.huggel@eiger-versicherungen.ch"),
role=CourseSessionUser.Role.EXPERT,
)
csu.expert.add(Circle.objects.get(slug="test-lehrgang-lp-circle-basis"))
self.test_data = {
"file_name": "test.pdf",
@ -44,10 +43,11 @@ class DocumentUploadApiTestCase(APITestCase):
def test_can_start_upload(self):
ls = LearningSequence.objects.get(
slug="test-lehrgang-lp-circle-basis-ls-starten"
slug="test-lehrgang-lp-circle-analyse-ls-beobachten"
)
self.test_data["learning_sequence"] = ls.id
response = self.client.post(f"/api/core/document/start", self.test_data)
response = self.client.post(f"/api/core/document/start/", self.test_data)
self.assertEqual(response.status_code, 200)
self.assertNotEqual(response.data["url"], "")
@ -66,12 +66,12 @@ class DocumentUploadApiTestCase(APITestCase):
def test_cannot_start_upload_in_other_circle(self):
ls = LearningSequence.objects.get(
slug="test-lehrgang-lp-circle-analyse-ls-beenden"
slug="test-lehrgang-lp-circle-basis-ls-starten"
)
self.test_data["learning_sequence"] = ls.id
response = self.client.post(f"/api/core/document/start", self.test_data)
response = self.client.post(f"/api/core/document/start/", self.test_data)
self.assertEqual(response.status_code, 401)
self.assertEqual(response.status_code, 403)
def test_student_cannot_start_uploads(self):
self.client.login(username="student", password="test")
@ -79,24 +79,24 @@ class DocumentUploadApiTestCase(APITestCase):
slug="test-lehrgang-lp-circle-basis-ls-starten"
)
self.test_data["learning_sequence"] = ls.id
response = self.client.post(f"/api/core/document/start", self.test_data)
response = self.client.post(f"/api/core/document/start/", self.test_data)
self.assertEqual(response.status_code, 401)
self.assertEqual(response.status_code, 403)
def test_expert_can_finish_own_upload(self):
ls = LearningSequence.objects.get(
slug="test-lehrgang-lp-circle-basis-ls-starten"
slug="test-lehrgang-lp-circle-analyse-ls-beobachten"
)
self.test_data["learning_sequence"] = ls.id
response = self.client.post(f"/api/core/document/start", self.test_data)
response = self.client.post(f"/api/core/document/start/", self.test_data)
self.assertEqual(response.status_code, 200)
file_id = response.data["file_id"]
response = self.client.post(
f"/api/core/file/finish",
f"/api/core/file/finish/",
{
"file_id": response.data["id"],
"file_id": file_id,
},
)
@ -119,11 +119,11 @@ class DocumentUploadApiTestCase(APITestCase):
response = self.client.post(f"/api/core/file/finish/", {"file_id": file.id})
self.assertEqual(response.status_code, 401)
self.assertEqual(response.status_code, 403)
def test_can_delete_document(self):
ls = LearningSequence.objects.get(
slug="test-lehrgang-lp-circle-basis-ls-starten"
slug="test-lehrgang-lp-circle-analyse-ls-beobachten"
)
file = File(
original_file_name="test.pdf",
@ -155,8 +155,9 @@ class DocumentUploadApiTestCase(APITestCase):
self.assertIsNone(file.upload_finished_at)
def test_student_cannot_delete_document(self):
self.client.login(username="student", password="test")
ls = LearningSequence.objects.get(
slug="test-lehrgang-lp-circle-basis-ls-starten"
slug="test-lehrgang-lp-circle-analyse-ls-beobachten"
)
file = File(
original_file_name="test.pdf",
@ -181,3 +182,4 @@ class DocumentUploadApiTestCase(APITestCase):
# expert cannot upload in other course
# expert cannot delete other upload
# exper cannot change course

View File

@ -14,6 +14,7 @@ from vbv_lernwelt.course.models import (
from vbv_lernwelt.course.permissions import (
course_sessions_for_user_qs,
has_course_access_by_page_request,
is_circle_expert,
)
from vbv_lernwelt.course.serializers import (
CourseCompletionSerializer,
@ -165,10 +166,16 @@ def get_course_session_users(request, course_slug):
@api_view(["POST"])
def document_upload_start(request):
# todo: check permissions
serializer = DocumentUploadStartInputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
if not is_circle_expert(
request.user,
serializer.validated_data["learning_sequence"],
serializer.validated_data["course_session"],
):
raise PermissionDenied()
service = FileDirectUploadService(request.user)
file, presigned_data = service.start(
serializer.validated_data["file_name"], serializer.validated_data["file_type"]
@ -219,7 +226,10 @@ def document_direct_upload(request, file_id):
@api_view(["DELETE"])
def document_delete(request, document_id):
document = get_object_or_404(CircleDocument, id=document_id)
# todo: check real permissoin
if not is_circle_expert(
request.user, document.learning_sequence_id, document.course_session_id
):
raise PermissionDenied()
document.delete()