feat: add course session permissions

This commit is contained in:
Reto Aebersold 2024-02-08 10:04:17 +01:00
parent 9a405b6900
commit 8cff12fc10
8 changed files with 85 additions and 7 deletions

View File

@ -3,9 +3,11 @@ import { useTranslation } from "i18next-vue";
import { useRouteLookups } from "@/utils/route";
import { useCurrentCourseSession } from "@/composables";
import { getCompetenceNaviUrl, getLearningPathUrl } from "@/utils/utils";
import { useCockpitStore } from "@/stores/cockpit";
const { inCompetenceProfile, inLearningPath } = useRouteLookups();
const courseSession = useCurrentCourseSession();
const cockpit = useCockpitStore();
const { t } = useTranslation();
</script>
@ -32,6 +34,7 @@ const { t } = useTranslation();
</router-link>
<router-link
v-if="cockpit.hasExpertCockpitType"
data-cy="preview-competence-profile-link"
:to="getCompetenceNaviUrl(courseSession.course.slug)"
class="preview-nav-item"

View File

@ -83,7 +83,9 @@ const hasCockpitMenu = computed(() => {
});
const hasPreviewMenu = computed(() => {
return useCockpitStore().hasExpertCockpitType;
return (
useCockpitStore().hasExpertCockpitType || useCockpitStore().hasMentorCockpitType
);
});
const hasAppointmentsMenu = computed(() => {

View File

@ -52,6 +52,11 @@ const circleExperts = computed(() => {
return [];
});
const learningContentReadonly = computed(() => {
const actions = courseSession.value.actions;
return props.readonly || !actions.includes("complete-learning-content");
});
const duration = computed(() => {
// if (circleStore.circle) {
// const minutes = sumBy(circleStore.circle.learningSequences, "minutes");
@ -293,7 +298,7 @@ watch(
:course-slug="props.courseSlug"
:circle="circle"
:learning-sequence="learningSequence"
:readonly="props.readonly"
:readonly="learningContentReadonly"
></LearningSequence>
</li>
</ol>

View File

@ -448,6 +448,7 @@ export interface CourseSession {
start_date: string;
end_date: string;
due_dates: DueDate[];
actions: string[];
}
export type CourseSessionUser = CourseSessionUserObjectsType;

View File

@ -11,6 +11,7 @@ from vbv_lernwelt.course.models import (
)
from vbv_lernwelt.duedate.models import DueDate
from vbv_lernwelt.duedate.serializers import DueDateSerializer
from vbv_lernwelt.iam.permissions import course_session_permissions
class CourseSerializer(serializers.ModelSerializer):
@ -54,15 +55,12 @@ class CourseSessionSerializer(serializers.ModelSerializer):
id = StringIDField()
course = serializers.SerializerMethodField()
# course_url = serializers.SerializerMethodField()
due_dates = serializers.SerializerMethodField()
actions = serializers.SerializerMethodField()
def get_course(self, obj):
return CourseSerializer(obj.course).data
# def get_course_url(self, obj):
# return obj.course.get_course_url()
def get_due_dates(self, obj):
due_dates = DueDate.objects.filter(
Q(start__isnull=False) | Q(end__isnull=False), course_session=obj
@ -80,7 +78,15 @@ class CourseSessionSerializer(serializers.ModelSerializer):
"start_date",
"end_date",
"due_dates",
"actions",
]
read_only_fields = ["actions"]
def get_actions(self, obj):
user = self.context.get("user")
if user:
return course_session_permissions(user, obj.id)
return []
class CircleDocumentSerializer(serializers.ModelSerializer):

View File

@ -157,7 +157,10 @@ def get_course_sessions(request):
).distinct()
return Response(
status=200, data=CourseSessionSerializer(all_to_serialize, many=True).data
status=200,
data=CourseSessionSerializer(
all_to_serialize, many=True, context={"user": request.user}
).data,
)
except PermissionDenied as e:
raise e

View File

@ -207,3 +207,17 @@ def can_view_course_completions(
course_session_id=course_session_id,
)
)
def course_session_permissions(user: User, course_session_id: int) -> list[str]:
return _action_list(
{
"complete-learning-content": is_course_session_member(
user, course_session_id
),
}
)
def _action_list(actions: dict[str, bool]):
return [action for action, allowed in actions.items() if allowed]

View File

@ -0,0 +1,44 @@
from django.test import TestCase
from vbv_lernwelt.course.creators.test_utils import (
add_course_session_user,
create_course,
create_course_session,
create_user,
)
from vbv_lernwelt.course.models import CourseSessionUser
from vbv_lernwelt.iam.permissions import course_session_permissions
from vbv_lernwelt.learning_mentor.models import LearningMentor
class ActionTestCase(TestCase):
def setUp(self):
self.course, _ = create_course("Test Course")
self.course_session = create_course_session(
course=self.course, title="Test Session"
)
def test_course_session_permissions(self):
# GIVEN
lm = create_user("mentor")
LearningMentor.objects.create(
mentor=lm,
course=self.course,
)
participant = create_user("participant")
add_course_session_user(
self.course_session,
participant,
role=CourseSessionUser.Role.MEMBER,
)
# WHEN
mentor_actions = course_session_permissions(lm, self.course_session.id)
participant_actions = course_session_permissions(
participant, self.course_session.id
)
# THEN
self.assertEqual(len(mentor_actions), 0)
self.assertEqual(participant_actions, ["complete-learning-content"])