feat: add course session permissions
This commit is contained in:
parent
9a405b6900
commit
8cff12fc10
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -83,7 +83,9 @@ const hasCockpitMenu = computed(() => {
|
|||
});
|
||||
|
||||
const hasPreviewMenu = computed(() => {
|
||||
return useCockpitStore().hasExpertCockpitType;
|
||||
return (
|
||||
useCockpitStore().hasExpertCockpitType || useCockpitStore().hasMentorCockpitType
|
||||
);
|
||||
});
|
||||
|
||||
const hasAppointmentsMenu = computed(() => {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -448,6 +448,7 @@ export interface CourseSession {
|
|||
start_date: string;
|
||||
end_date: string;
|
||||
due_dates: DueDate[];
|
||||
actions: string[];
|
||||
}
|
||||
|
||||
export type CourseSessionUser = CourseSessionUserObjectsType;
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
Loading…
Reference in New Issue