mirror of
https://github.com/mediacms-io/mediacms.git
synced 2026-04-30 18:36:13 -04:00
course remove
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
# Generated by Django 5.2.6 on 2026-04-27 17:43
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('files', '0017_mediapermission_source'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='EmbedMediaCourse',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('category', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='embedded_media', to='files.category')),
|
||||
('media', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='embed_courses', to='files.media')),
|
||||
],
|
||||
options={
|
||||
'unique_together': {('media', 'category')},
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -3,7 +3,7 @@ from .category import Category, Tag # noqa: F401
|
||||
from .comment import Comment # noqa: F401
|
||||
from .encoding import EncodeProfile, Encoding # noqa: F401
|
||||
from .license import License # noqa: F401
|
||||
from .media import Media, MediaPermission # noqa: F401
|
||||
from .media import EmbedMediaCourse, Media, MediaPermission # noqa: F401
|
||||
from .page import Page, TinyMCEMedia # noqa: F401
|
||||
from .playlist import Playlist, PlaylistMedia # noqa: F401
|
||||
from .rating import Rating, RatingCategory # noqa: F401
|
||||
|
||||
@@ -1002,6 +1002,29 @@ class MediaPermission(models.Model):
|
||||
return f"{self.user.username} - {self.media.title} ({self.permission})"
|
||||
|
||||
|
||||
class EmbedMediaCourse(models.Model):
|
||||
"""
|
||||
Records that a user shared a media item into a course during an LTI session.
|
||||
|
||||
This is a pure audit/tracking table used by the course cleanup bulk action to
|
||||
identify which MediaPermission records were created via LTI embedding and should
|
||||
be removed when the course is cleaned up.
|
||||
|
||||
It does NOT add the media to the category (Media.category M2M is untouched),
|
||||
so no m2m_changed signals fire and no category counts are affected.
|
||||
"""
|
||||
|
||||
media = models.ForeignKey('Media', on_delete=models.CASCADE, related_name='embed_courses')
|
||||
category = models.ForeignKey('Category', on_delete=models.CASCADE, related_name='embedded_media')
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('media', 'category')
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.media.title} in {self.category.title}"
|
||||
|
||||
|
||||
@receiver(post_save, sender=Media)
|
||||
def media_save(sender, instance, created, **kwargs):
|
||||
# media_file path is not set correctly until mode is saved
|
||||
|
||||
+29
-11
@@ -36,6 +36,7 @@ from ..methods import (
|
||||
from ..models import (
|
||||
Category,
|
||||
Comment,
|
||||
EmbedMediaCourse,
|
||||
EncodeProfile,
|
||||
Media,
|
||||
MediaPermission,
|
||||
@@ -743,7 +744,7 @@ class MediaBulkUserActions(APIView):
|
||||
def _handle_course_cleanup(self, request, media_ids):
|
||||
category_uids = request.data.get('category_uids', [])
|
||||
remove_permissions = request.data.get('remove_permissions', False)
|
||||
remove_tags = request.data.get('remove_tags', False)
|
||||
remove_comments = request.data.get('remove_comments', False)
|
||||
apply_to_all = request.data.get('apply_to_all', False)
|
||||
|
||||
if not category_uids:
|
||||
@@ -764,24 +765,33 @@ class MediaBulkUserActions(APIView):
|
||||
# All users who are members of any group linked to this category
|
||||
group_users = User.objects.filter(rbac_groups__in=category.rbac_groups.all()).distinct()
|
||||
|
||||
course_tag = Tag.objects.filter(title=category.title[:100]).first() if remove_tags else None
|
||||
# Get media explicitly embedded into this course via LTI
|
||||
embed_qs = EmbedMediaCourse.objects.filter(category=category)
|
||||
embedded_media_ids = list(embed_qs.values_list('media_id', flat=True))
|
||||
|
||||
all_course_media = Media.objects.filter(category=category)
|
||||
|
||||
if has_media:
|
||||
if remove_permissions:
|
||||
MediaPermission.objects.filter(media__in=selected_media, user__in=group_users).delete()
|
||||
if remove_tags and course_tag:
|
||||
for m in selected_media:
|
||||
m.tags.remove(course_tag)
|
||||
# Delete EmbedMediaCourse records and owner MediaPermissions for embedded media
|
||||
selected_embedded = embed_qs.filter(media__in=selected_media)
|
||||
selected_embedded_media_ids = list(selected_embedded.values_list('media_id', flat=True))
|
||||
selected_embedded.delete()
|
||||
MediaPermission.objects.filter(media_id__in=selected_embedded_media_ids).delete()
|
||||
if remove_comments:
|
||||
Comment.objects.filter(media__in=selected_media).delete()
|
||||
|
||||
if apply_to_all:
|
||||
other_course_media = all_course_media.exclude(friendly_token__in=media_ids)
|
||||
if remove_permissions:
|
||||
MediaPermission.objects.filter(media__in=other_course_media, user__in=group_users).delete()
|
||||
if remove_tags and course_tag:
|
||||
for m in other_course_media:
|
||||
m.tags.remove(course_tag)
|
||||
other_embedded = embed_qs.filter(media__in=other_course_media)
|
||||
other_embedded_media_ids = list(other_embedded.values_list('media_id', flat=True))
|
||||
other_embedded.delete()
|
||||
MediaPermission.objects.filter(media_id__in=other_embedded_media_ids).delete()
|
||||
if remove_comments:
|
||||
Comment.objects.filter(media__in=other_course_media).delete()
|
||||
for m in other_course_media:
|
||||
m.category.remove(category)
|
||||
|
||||
@@ -790,9 +800,10 @@ class MediaBulkUserActions(APIView):
|
||||
else:
|
||||
if remove_permissions:
|
||||
MediaPermission.objects.filter(media__in=all_course_media, user__in=group_users).delete()
|
||||
if remove_tags and course_tag:
|
||||
for m in all_course_media:
|
||||
m.tags.remove(course_tag)
|
||||
MediaPermission.objects.filter(media_id__in=embedded_media_ids).delete()
|
||||
embed_qs.delete()
|
||||
if remove_comments:
|
||||
Comment.objects.filter(media__in=all_course_media).delete()
|
||||
for m in all_course_media:
|
||||
m.category.remove(category)
|
||||
|
||||
@@ -1241,4 +1252,11 @@ class MediaShare(APIView):
|
||||
defaults={'owner_user': request.user, 'permission': 'owner'},
|
||||
)
|
||||
|
||||
lti_session = request.session.get('lti_session', {})
|
||||
context_id = lti_session.get('context_id')
|
||||
if context_id:
|
||||
category = Category.objects.filter(lti_context_id=context_id, is_rbac_category=True).first()
|
||||
if category:
|
||||
EmbedMediaCourse.objects.get_or_create(media=media, category=category)
|
||||
|
||||
return Response({'status': 'ok'})
|
||||
|
||||
Reference in New Issue
Block a user