From ca44a913c97d66a285cab7e24ca5807732f084a1 Mon Sep 17 00:00:00 2001 From: Livio Bieri Date: Tue, 24 Oct 2023 12:05:55 +0200 Subject: [PATCH] wip: session group statistics w/ permission --- .../assignment/graphql/mutations.py | 2 +- .../vbv_lernwelt/assignment/graphql/types.py | 2 +- server/vbv_lernwelt/assignment/views.py | 2 +- server/vbv_lernwelt/course/graphql/queries.py | 2 +- server/vbv_lernwelt/course/graphql/types.py | 2 +- server/vbv_lernwelt/course/views.py | 15 ++-- .../course_session/graphql/mutations.py | 2 +- .../course_session/graphql/queries.py | 2 +- .../course_session/graphql/types.py | 2 +- server/vbv_lernwelt/course_session/views.py | 2 +- .../vbv_lernwelt/dashboard/graphql/queries.py | 68 +++++++++++++++---- .../dashboard/graphql/types/assignment.py | 6 +- .../dashboard/graphql/types/attendance.py | 6 +- .../dashboard/graphql/types/competence.py | 6 +- .../dashboard/graphql/types/dashboard.py | 17 +++-- .../dashboard/graphql/types/feedback.py | 6 +- .../dashboard/tests/graphql/test_dashboard.py | 61 +++++++++++++++++ .../dashboard/tests/graphql/utils.py | 14 ++++ server/vbv_lernwelt/edoniq_test/views.py | 2 +- .../feedback/graphql/mutations.py | 2 +- server/vbv_lernwelt/feedback/views.py | 2 +- server/vbv_lernwelt/iam/__init__.py | 0 .../{course => iam}/permissions.py | 48 ++++++++----- 23 files changed, 208 insertions(+), 63 deletions(-) create mode 100644 server/vbv_lernwelt/iam/__init__.py rename server/vbv_lernwelt/{course => iam}/permissions.py (65%) diff --git a/server/vbv_lernwelt/assignment/graphql/mutations.py b/server/vbv_lernwelt/assignment/graphql/mutations.py index 73b6de7f..2d9394ca 100644 --- a/server/vbv_lernwelt/assignment/graphql/mutations.py +++ b/server/vbv_lernwelt/assignment/graphql/mutations.py @@ -10,7 +10,7 @@ from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletionStatu from vbv_lernwelt.assignment.services import update_assignment_completion from vbv_lernwelt.core.models import User from vbv_lernwelt.course.models import CourseSession, CourseSessionUser -from vbv_lernwelt.course.permissions import has_course_access, is_course_session_expert +from vbv_lernwelt.iam.permissions import has_course_access, is_course_session_expert logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/assignment/graphql/types.py b/server/vbv_lernwelt/assignment/graphql/types.py index 33687377..021a2226 100644 --- a/server/vbv_lernwelt/assignment/graphql/types.py +++ b/server/vbv_lernwelt/assignment/graphql/types.py @@ -7,7 +7,7 @@ from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion from vbv_lernwelt.core.graphql.types import JSONStreamField from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface from vbv_lernwelt.course.models import CourseSession -from vbv_lernwelt.course.permissions import has_course_access, is_course_session_expert +from vbv_lernwelt.iam.permissions import has_course_access, is_course_session_expert from vbv_lernwelt.learnpath.graphql.types import LearningContentInterface diff --git a/server/vbv_lernwelt/assignment/views.py b/server/vbv_lernwelt/assignment/views.py index 205c1321..f686ae51 100644 --- a/server/vbv_lernwelt/assignment/views.py +++ b/server/vbv_lernwelt/assignment/views.py @@ -4,7 +4,7 @@ from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response from vbv_lernwelt.assignment.models import AssignmentCompletion -from vbv_lernwelt.course.permissions import is_course_session_expert +from vbv_lernwelt.iam.permissions import is_course_session_expert logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/course/graphql/queries.py b/server/vbv_lernwelt/course/graphql/queries.py index b12b45e8..c81e0567 100644 --- a/server/vbv_lernwelt/course/graphql/queries.py +++ b/server/vbv_lernwelt/course/graphql/queries.py @@ -4,7 +4,7 @@ from graphql import GraphQLError from vbv_lernwelt.course.graphql.types import CourseObjectType, CourseSessionObjectType from vbv_lernwelt.course.models import Course, CourseSession -from vbv_lernwelt.course.permissions import has_course_access +from vbv_lernwelt.iam.permissions import has_course_access from vbv_lernwelt.learnpath.graphql.types import ( LearningContentAssignmentObjectType, LearningContentAttendanceCourseObjectType, diff --git a/server/vbv_lernwelt/course/graphql/types.py b/server/vbv_lernwelt/course/graphql/types.py index cb3883b2..923c5eed 100644 --- a/server/vbv_lernwelt/course/graphql/types.py +++ b/server/vbv_lernwelt/course/graphql/types.py @@ -16,7 +16,6 @@ from vbv_lernwelt.course.models import ( CourseSession, CourseSessionUser, ) -from vbv_lernwelt.course.permissions import has_course_access from vbv_lernwelt.course_session.graphql.types import ( CourseSessionAssignmentObjectType, CourseSessionAttendanceCourseObjectType, @@ -27,6 +26,7 @@ from vbv_lernwelt.course_session.models import ( CourseSessionAttendanceCourse, CourseSessionEdoniqTest, ) +from vbv_lernwelt.iam.permissions import has_course_access from vbv_lernwelt.learnpath.graphql.types import LearningPathObjectType logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/course/views.py b/server/vbv_lernwelt/course/views.py index 3fce8b6b..627ab7a8 100644 --- a/server/vbv_lernwelt/course/views.py +++ b/server/vbv_lernwelt/course/views.py @@ -10,14 +10,6 @@ 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, @@ -28,6 +20,13 @@ from vbv_lernwelt.course.serializers import ( from vbv_lernwelt.course.services import mark_course_completion from vbv_lernwelt.files.models import UploadFile from vbv_lernwelt.files.services import FileDirectUploadService +from vbv_lernwelt.iam.permissions import ( + has_course_access_by_page_request, + has_course_access, + is_course_session_expert, + course_sessions_for_user_qs, + is_circle_expert, +) logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/course_session/graphql/mutations.py b/server/vbv_lernwelt/course_session/graphql/mutations.py index 189817db..1d00013b 100644 --- a/server/vbv_lernwelt/course_session/graphql/mutations.py +++ b/server/vbv_lernwelt/course_session/graphql/mutations.py @@ -2,7 +2,6 @@ import graphene import structlog from rest_framework.exceptions import PermissionDenied -from vbv_lernwelt.course.permissions import has_course_access from vbv_lernwelt.course_session.graphql.types import ( CourseSessionAttendanceCourseObjectType, ) @@ -11,6 +10,7 @@ from vbv_lernwelt.course_session.services.attendance import ( AttendanceUserStatus, update_attendance_list, ) +from vbv_lernwelt.iam.permissions import has_course_access logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/course_session/graphql/queries.py b/server/vbv_lernwelt/course_session/graphql/queries.py index 899cd93a..33c544e4 100644 --- a/server/vbv_lernwelt/course_session/graphql/queries.py +++ b/server/vbv_lernwelt/course_session/graphql/queries.py @@ -2,11 +2,11 @@ import graphene from rest_framework.exceptions import PermissionDenied from vbv_lernwelt.course.models import CourseSession -from vbv_lernwelt.course.permissions import has_course_access, is_course_session_expert from vbv_lernwelt.course_session.graphql.types import ( CourseSessionAttendanceCourseObjectType, ) from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse +from vbv_lernwelt.iam.permissions import has_course_access, is_course_session_expert class CourseSessionQuery(object): diff --git a/server/vbv_lernwelt/course_session/graphql/types.py b/server/vbv_lernwelt/course_session/graphql/types.py index 56360a23..d4f4d3ac 100644 --- a/server/vbv_lernwelt/course_session/graphql/types.py +++ b/server/vbv_lernwelt/course_session/graphql/types.py @@ -1,7 +1,6 @@ import graphene from graphene_django import DjangoObjectType -from vbv_lernwelt.course.permissions import is_course_session_expert from vbv_lernwelt.course_session.models import ( CourseSessionAssignment, CourseSessionAttendanceCourse, @@ -9,6 +8,7 @@ from vbv_lernwelt.course_session.models import ( ) from vbv_lernwelt.course_session.services.attendance import AttendanceUserStatus from vbv_lernwelt.duedate.graphql.types import DueDateObjectType +from vbv_lernwelt.iam.permissions import is_course_session_expert from vbv_lernwelt.learnpath.graphql.types import ( LearningContentAssignmentObjectType, LearningContentAttendanceCourseObjectType, diff --git a/server/vbv_lernwelt/course_session/views.py b/server/vbv_lernwelt/course_session/views.py index 6cf3dbfc..ac4af629 100644 --- a/server/vbv_lernwelt/course_session/views.py +++ b/server/vbv_lernwelt/course_session/views.py @@ -3,8 +3,8 @@ from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response from vbv_lernwelt.course.models import CircleDocument -from vbv_lernwelt.course.permissions import has_course_session_access from vbv_lernwelt.course.serializers import CircleDocumentSerializer +from vbv_lernwelt.iam.permissions import has_course_session_access @api_view(["GET"]) diff --git a/server/vbv_lernwelt/dashboard/graphql/queries.py b/server/vbv_lernwelt/dashboard/graphql/queries.py index a708ca45..ae4c31cf 100644 --- a/server/vbv_lernwelt/dashboard/graphql/queries.py +++ b/server/vbv_lernwelt/dashboard/graphql/queries.py @@ -1,22 +1,64 @@ import graphene -from vbv_lernwelt.course.models import Course -from vbv_lernwelt.dashboard.graphql.types.dashboard import CourseStatisticsType +from vbv_lernwelt.course.models import CourseSession, Course +from vbv_lernwelt.course_session_group.models import CourseSessionGroup +from vbv_lernwelt.dashboard.graphql.types.dashboard import CourseStatisticsType, DashboardConfigType +from vbv_lernwelt.iam.permissions import can_view_course_session_group_statistics, can_view_course_session class DashboardQuery(graphene.ObjectType): - course_statistics = graphene.List( - CourseStatisticsType, course_id=graphene.ID(required=True) + course_statistics = graphene.Field(CourseStatisticsType, course_id=graphene.ID(required=True)) + + dashboard_config = graphene.List( + DashboardConfigType ) - def resolve_course_statistics(root, info, course_id: str): - query = Course.objects.filter( - id=course_id - ) + def resolve_course_statistics(root, info, course_id: str): # noqa + user = info.context.user + course = Course.objects.get(id=course_id) - courses = query.distinct() + course_session_ids = set() - return [ - CourseStatisticsType(course_id=course.id, course_title=course.title) # noqa - for course in courses - ] + for group in CourseSessionGroup.objects.filter(course=course): + if can_view_course_session_group_statistics(user=user, group=group): + course_session_ids.update(group.course_session.all().values_list("id", flat=True)) + + if not course_session_ids: + return None + + + return CourseStatisticsType(course_id=course.id, course_title=course.title, # noqa + course_session_selection_ids=list(course_session_ids)) # noqa + + + + def resolve_dashboard_config(root, info): # noqa + user = info.context.user + + course_index = set() + dashboards = [] + + for group in CourseSessionGroup.objects.all(): + if can_view_course_session_group_statistics(user=user, group=group): + course = group.course + course_index.add(course) + dashboards.append( + { + "id": str(course.id), + "title": course.title, + "dashboard_type": "StatisticsDashboard", + } + ) + + for course_session in CourseSession.objects.exclude(course__in=course_index): + if can_view_course_session(user=user, course_session=course_session): + course = course_session.course + dashboards.append( + { + "id": str(course.id), + "title": course.title, + "dashboard_type": "SimpleDashboard", + } + ) + + return dashboards diff --git a/server/vbv_lernwelt/dashboard/graphql/types/assignment.py b/server/vbv_lernwelt/dashboard/graphql/types/assignment.py index d42d14ad..8baa650b 100644 --- a/server/vbv_lernwelt/dashboard/graphql/types/assignment.py +++ b/server/vbv_lernwelt/dashboard/graphql/types/assignment.py @@ -124,9 +124,11 @@ def create_record( ) -def assignments(course_id) -> Assignments: +def assignments( + course_session_selection_ids: graphene.List(graphene.ID), +) -> Assignments: course_sessions = CourseSession.objects.filter( - course_id=course_id, + id_in=course_session_selection_ids, ) records: List[AssignmentRecord] = [] diff --git a/server/vbv_lernwelt/dashboard/graphql/types/attendance.py b/server/vbv_lernwelt/dashboard/graphql/types/attendance.py index 40620769..01b41ac4 100644 --- a/server/vbv_lernwelt/dashboard/graphql/types/attendance.py +++ b/server/vbv_lernwelt/dashboard/graphql/types/attendance.py @@ -30,9 +30,11 @@ class AttendanceDayPresences(graphene.ObjectType): summary = graphene.Field(AttendanceSummary) -def attendance_day_presences(course_id: graphene.String()) -> AttendanceDayPresences: +def attendance_day_presences( + course_session_selection_ids: graphene.List(graphene.ID), +) -> AttendanceDayPresences: completed = CourseSessionAttendanceCourse.objects.filter( - course_session__course_id=course_id, + course_session_id__in=course_session_selection_ids, due_date__end__lt=timezone.now(), ).order_by("-due_date__end") diff --git a/server/vbv_lernwelt/dashboard/graphql/types/competence.py b/server/vbv_lernwelt/dashboard/graphql/types/competence.py index 07823dd2..42826e0a 100644 --- a/server/vbv_lernwelt/dashboard/graphql/types/competence.py +++ b/server/vbv_lernwelt/dashboard/graphql/types/competence.py @@ -21,9 +21,11 @@ class Competences(graphene.ObjectType): summary = graphene.Field(CompletionSummary) -def competences(course_id: graphene.String()) -> Competences: +def competences( + course_session_selection_ids: graphene.List(graphene.ID), +) -> Competences: completions = CourseCompletion.objects.filter( - course_session__course_id=course_id, + course_session_id__in=course_session_selection_ids, page_type="competence.PerformanceCriteria", ) diff --git a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py index a69cdfc6..23392429 100644 --- a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py +++ b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py @@ -31,9 +31,16 @@ class CourseSessionProperties(graphene.ObjectType): circles = graphene.List(CircleData) +class DashboardConfigType(graphene.ObjectType): + id = graphene.ID() + title = graphene.String() + dashboard_type = graphene.String() + + class CourseStatisticsType(graphene.ObjectType): - course_id = graphene.String() + course_id = graphene.ID() course_title = graphene.String() + course_session_selection_ids = graphene.List(graphene.ID) course_session_properties = graphene.Field(CourseSessionProperties) attendance_day_presences = graphene.Field(AttendanceDayPresences) feedback_responses = graphene.Field(FeedbackResponses) @@ -41,16 +48,16 @@ class CourseStatisticsType(graphene.ObjectType): competences = graphene.Field(Competences) def resolve_attendance_day_presences(root, info) -> AttendanceDayPresences: - return attendance_day_presences(root.course_id) + return attendance_day_presences(root.course_session_selection_ids) def resolve_feedback_responses(root, info) -> FeedbackResponses: - return feedback_responses(root.course_id) + return feedback_responses(root.course_session_selection_ids) def resolve_competences(root, info) -> Competences: - return competences(root.course_id) + return competences(root.course_session_selection_ids) def resolve_assignments(root, info) -> Assignments: - return assignments(root.course_id) + return assignments(root.course_session_selection_ids) def resolve_course_session_properties(root, info): course_session_data = [] diff --git a/server/vbv_lernwelt/dashboard/graphql/types/feedback.py b/server/vbv_lernwelt/dashboard/graphql/types/feedback.py index c04199e5..1a1b35c9 100644 --- a/server/vbv_lernwelt/dashboard/graphql/types/feedback.py +++ b/server/vbv_lernwelt/dashboard/graphql/types/feedback.py @@ -26,10 +26,12 @@ class FeedbackResponses(graphene.ObjectType): summary = graphene.Field(FeedbackSummary) -def feedback_responses(course_id: graphene.String()) -> FeedbackResponses: +def feedback_responses( + course_session_selection_ids: graphene.List(graphene.ID), +) -> FeedbackResponses: # Get all course sessions for this user in the given course course_sessions = CourseSession.objects.filter( - course_id=course_id, + id_in=course_session_selection_ids, ) circle_feedbacks = [] diff --git a/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py b/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py index cd86629e..08bd44c1 100644 --- a/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py +++ b/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py @@ -1,15 +1,70 @@ from graphene_django.utils import GraphQLTestCase +from vbv_lernwelt.course.models import CourseSessionUser from vbv_lernwelt.dashboard.tests.graphql.utils import ( create_course, create_course_session, create_user, + add_course_session_user, + create_course_session_group, ) class DashboardTestCase(GraphQLTestCase): GRAPHQL_URL = "/server/graphql/" + def test_dashboard_config(self): + # GIVEN + course_1, _ = create_course("Test Course 1") + course_2, _ = create_course("Test Course 2") + + cs_1 = create_course_session(course=course_1, title="Test Course 1 Session") + cs_2 = create_course_session(course=course_2, title="Test Course 2 Session") + + # Member of course 1 (via cs_1) + # Supervisor of course 2 (via cs_2) + supervisor = create_user("supervisor") + + add_course_session_user( + course_session=cs_1, user=supervisor, role=CourseSessionUser.Role.MEMBER + ) + + create_course_session_group(course_session=cs_2, user=supervisor) + + self.client.force_login(supervisor) + + # WHEN + query = """query { + dashboard_config { + id + title + dashboard_type + } + } + """ + + response = self.query(query) + + # THEN + self.assertResponseNoErrors(response) + + dashboard_config = response.json()["data"]["dashboard_config"] + self.assertEqual(len(dashboard_config), 2) + + course_1_config = find_dashboard_config_by_course_id( + dashboard_config, course_1.id + ) + self.assertIsNotNone(course_1_config) + self.assertEqual(course_1_config["title"], course_1.title) + self.assertEqual(course_1_config["dashboard_type"], "SimpleDashboard") + + course_2_config = find_dashboard_config_by_course_id( + dashboard_config, course_2.id + ) + self.assertIsNotNone(course_2_config) + self.assertEqual(course_2_config["title"], course_2.title) + self.assertEqual(course_2_config["dashboard_type"], "StatisticsDashboard") + def test_course_statistics_id(self): # GIVEN @@ -41,3 +96,9 @@ class DashboardTestCase(GraphQLTestCase): self.assertEqual(len(course_statistics), 1) self.assertEqual(course_statistics[0]["course_id"], str(course_2.id)) + + +def find_dashboard_config_by_course_id(dashboard_configs, course_id): + return next( + (config for config in dashboard_configs if config["id"] == str(course_id)), None + ) diff --git a/server/vbv_lernwelt/dashboard/tests/graphql/utils.py b/server/vbv_lernwelt/dashboard/tests/graphql/utils.py index f5921fa9..c1625e25 100644 --- a/server/vbv_lernwelt/dashboard/tests/graphql/utils.py +++ b/server/vbv_lernwelt/dashboard/tests/graphql/utils.py @@ -36,6 +36,7 @@ from vbv_lernwelt.course_session.models import ( CourseSessionAttendanceCourse, CourseSessionEdoniqTest, ) +from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.duedate.models import DueDate from vbv_lernwelt.learnpath.models import ( Circle, @@ -99,6 +100,19 @@ def add_course_session_user( ) +def create_course_session_group( + course_session: CourseSession, user: User +) -> CourseSessionGroup: + g = CourseSessionGroup.objects.create( + course=course_session.course, + ) + + g.course_session.add(course_session) + g.supervisor.add(user) + + return g + + def create_circle( title: str, course_page: CoursePage, learning_path: LearningPath | None = None ) -> Tuple[Circle, LearningPath]: diff --git a/server/vbv_lernwelt/edoniq_test/views.py b/server/vbv_lernwelt/edoniq_test/views.py index f70dec12..00d8ff7b 100644 --- a/server/vbv_lernwelt/edoniq_test/views.py +++ b/server/vbv_lernwelt/edoniq_test/views.py @@ -14,8 +14,8 @@ from rest_framework.decorators import api_view from vbv_lernwelt.core.models import User from vbv_lernwelt.course.consts import COURSE_UK, COURSE_UK_FR, COURSE_UK_IT from vbv_lernwelt.course.models import CourseSessionUser -from vbv_lernwelt.course.permissions import has_course_access_by_page_request from vbv_lernwelt.edoniq_test.edoniq_sso import create_token +from vbv_lernwelt.iam.permissions import has_course_access_by_page_request from vbv_lernwelt.learnpath.models import LearningContentEdoniqTest logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/feedback/graphql/mutations.py b/server/vbv_lernwelt/feedback/graphql/mutations.py index 9a569d39..e36ad651 100644 --- a/server/vbv_lernwelt/feedback/graphql/mutations.py +++ b/server/vbv_lernwelt/feedback/graphql/mutations.py @@ -4,12 +4,12 @@ from graphene.types.generic import GenericScalar from graphene_django.types import ErrorType from vbv_lernwelt.course.models import CourseSession -from vbv_lernwelt.course.permissions import has_course_session_access from vbv_lernwelt.feedback.graphql.types import ( FeedbackResponseObjectType as FeedbackResponseType, ) from vbv_lernwelt.feedback.serializers import CourseFeedbackSerializer from vbv_lernwelt.feedback.services import update_feedback_response +from vbv_lernwelt.iam.permissions import has_course_session_access from vbv_lernwelt.learnpath.models import LearningContentFeedback logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/feedback/views.py b/server/vbv_lernwelt/feedback/views.py index ebfd27cf..7d3bb27f 100644 --- a/server/vbv_lernwelt/feedback/views.py +++ b/server/vbv_lernwelt/feedback/views.py @@ -5,9 +5,9 @@ from rest_framework.decorators import api_view from rest_framework.exceptions import PermissionDenied from rest_framework.response import Response -from vbv_lernwelt.course.permissions import is_course_session_expert from vbv_lernwelt.feedback.models import FeedbackResponse from vbv_lernwelt.feedback.utils import feedback_users +from vbv_lernwelt.iam.permissions import is_course_session_expert logger = structlog.get_logger(__name__) diff --git a/server/vbv_lernwelt/iam/__init__.py b/server/vbv_lernwelt/iam/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/server/vbv_lernwelt/course/permissions.py b/server/vbv_lernwelt/iam/permissions.py similarity index 65% rename from server/vbv_lernwelt/course/permissions.py rename to server/vbv_lernwelt/iam/permissions.py index 35e79b7f..fb75507e 100644 --- a/server/vbv_lernwelt/course/permissions.py +++ b/server/vbv_lernwelt/iam/permissions.py @@ -1,4 +1,6 @@ +from vbv_lernwelt.core.models import User from vbv_lernwelt.course.models import CourseSession, CourseSessionUser +from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.learnpath.models import LearningSequence @@ -10,38 +12,29 @@ def has_course_access(user, course_id): if user.is_superuser: return True - if CourseSessionUser.objects.filter( + return CourseSessionUser.objects.filter( course_session__course_id=course_id, user=user - ).exists(): - return True - - return False + ).exists() def has_course_session_access(user, course_session_id: int): if user.is_superuser: return True - if CourseSessionUser.objects.filter( + return CourseSessionUser.objects.filter( course_session_id=course_session_id, user=user - ).exists(): - return True - - return False + ).exists() def is_course_session_expert(user, course_session_id: int): if user.is_superuser: return True - if CourseSessionUser.objects.filter( + return CourseSessionUser.objects.filter( course_session_id=course_session_id, user=user, role=CourseSessionUser.Role.EXPERT, - ).exists(): - return True - - return False + ).exists() def course_sessions_for_user_qs(user): @@ -64,12 +57,33 @@ def is_circle_expert(user, course_session_id: int, learning_sequence_id: int) -> circle_id = learning_sequence.get_parent().circle.id - if CourseSessionUser.objects.filter( + return CourseSessionUser.objects.filter( course_session_id=course_session_id, user=user, role=CourseSessionUser.Role.EXPERT, expert__id=circle_id, + ).exists() + + +def can_view_course_session_group_statistics( + user: User, group: CourseSessionGroup +) -> bool: + if user.is_superuser: + return True + + return user in group.supervisor.all() + + +def can_view_course_session(user: User, course_session: CourseSession) -> bool: + if user.is_superuser: + return True + + if CourseSessionGroup.objects.filter( + course_session=course_session, supervisor=user ).exists(): return True - return False + return CourseSessionUser.objects.filter( + course_session=course_session, + user=user, + ).exists()