From 3a48dd5bfaef6bf855b6c559d9be553f3c2a7657 Mon Sep 17 00:00:00 2001 From: Markos Gogoulos Date: Mon, 20 Apr 2026 10:21:36 +0300 Subject: [PATCH] a --- .../src/static/js/pages/ProfileMediaPage.js | 25 +++++++++++-------- lti/views.py | 22 ++++++---------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/frontend/src/static/js/pages/ProfileMediaPage.js b/frontend/src/static/js/pages/ProfileMediaPage.js index ef518ab0..dedb9579 100755 --- a/frontend/src/static/js/pages/ProfileMediaPage.js +++ b/frontend/src/static/js/pages/ProfileMediaPage.js @@ -168,25 +168,28 @@ class ProfileMediaPage extends Page { }); if (isSelected) { - if (window.parent !== window) { - const baseUrl = window.location.origin; - const embedUrl = `${baseUrl}/embed?m=${mediaId}`; + const baseUrl = window.location.origin; + const embedUrl = `${baseUrl}/embed?m=${mediaId}`; - window.parent.postMessage({ - type: 'videoSelected', - embedUrl: embedUrl, - videoId: mediaId, - }, '*'); - } + const sendPostMessage = () => { + if (window.parent !== window) { + window.parent.postMessage({ + type: 'videoSelected', + embedUrl: embedUrl, + videoId: mediaId, + }, '*'); + } + }; - // Mark media as shared so LTI users in the course can access it + // Share first, then notify parent — postMessage can cause parent to navigate away + // which would cancel an in-flight fetch if called in the wrong order fetch(`/api/v1/media/${mediaId}/share`, { method: 'POST', headers: { 'X-CSRFToken': this.props.bulkActions.getCsrfToken(), 'Content-Type': 'application/json', }, - }).catch(() => {}); + }).then(sendPostMessage).catch(sendPostMessage); } } diff --git a/lti/views.py b/lti/views.py index 868c276f..99bf6ff8 100644 --- a/lti/views.py +++ b/lti/views.py @@ -695,7 +695,10 @@ class EmbedMediaLTIView(View): media = get_object_or_404(Media, friendly_token=friendly_token) lti_session = validate_lti_session(request) - can_view = False + if media.state in ["public", "unlisted"]: + can_view = True + else: + can_view = False if lti_session and request.user.is_authenticated: context_id = lti_session.get('context_id') @@ -717,6 +720,7 @@ class EmbedMediaLTIView(View): rbac_group=resource_link.rbac_group, ).exists() if has_course_access: + # create an entry so it shows up under shared with me MediaPermission.objects.get_or_create( user=request.user, media=media, @@ -729,20 +733,8 @@ class EmbedMediaLTIView(View): except Exception: logger.exception('EmbedMediaLTIView: error checking course access for user=%s media=%s', request.user, friendly_token) - if not can_view and media.state == 'private': - has_rbac_access = media.category.filter( - is_rbac_category=True, - rbac_groups__members=request.user, - ).exists() - has_direct_permission = MediaPermission.objects.filter( - media=media, - user=request.user, - ).exists() - if has_rbac_access or has_direct_permission: - can_view = True - - if not can_view and media.state in ["public", "unlisted"]: - can_view = True + if not can_view and request.user.has_member_access_to_media(media): + can_view = True if not can_view: return JsonResponse({'error': 'Access denied', 'message': 'You do not have permission to view this media'}, status=403)