Exemplo n.º 1
0
    def test_api_update_state_video_processing(self):
        """Setting a video's `upload_state` to processing should not affect its `uploaded_on`."""
        video = VideoFactory(id="9eeef843-bc43-4e01-825d-658aa5bca49f")
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_add)(
            VIDEO_ROOM_NAME.format(video_id=str(video.id)), "test_channel")
        async_to_sync(channel_layer.group_add)(
            VIDEO_ADMIN_ROOM_NAME.format(video_id=str(video.id)),
            "test_channel_admin")
        data = {
            "extraParameters": {},
            "key": f"{video.pk}/video/{video.pk}/1533686400",
            "state": "processing",
        }
        signature = generate_hash("shared secret",
                                  json.dumps(data).encode("utf-8"))
        response = self.client.post(
            "/api/update-state",
            data,
            content_type="application/json",
            HTTP_X_MARSHA_SIGNATURE=signature,
        )
        video.refresh_from_db()

        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content), {"success": True})
        self.assertEqual(video.uploaded_on, None)
        self.assertEqual(video.upload_state, "processing")
        self.assertEqual(video.resolutions, None)
        message = async_to_sync(channel_layer.receive)("test_channel")
        self.assertEqual(message["type"], "video_updated")
        message = async_to_sync(channel_layer.receive)("test_channel_admin")
        self.assertEqual(message["type"], "video_updated")
Exemplo n.º 2
0
    def test_api_update_state_video_multiple_secrets(self):
        """Confirming the failed upload of a video using the any of the existing secrets."""
        video = VideoFactory(id="c804e019-c622-4b76-aa43-33f2317bdc7e")
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_add)(
            VIDEO_ROOM_NAME.format(video_id=str(video.id)), "test_channel")
        async_to_sync(channel_layer.group_add)(
            VIDEO_ADMIN_ROOM_NAME.format(video_id=str(video.id)),
            "test_channel_admin")
        data = {
            "extraParameters": {},
            "key": f"{video.pk}/video/{video.pk}/1533686400",
            "state": "error",
        }
        signature = generate_hash(
            random.choice(["previous secret", "current secret"]),
            json.dumps(data).encode("utf-8"),
        )
        response = self.client.post(
            "/api/update-state",
            data,
            content_type="application/json",
            HTTP_X_MARSHA_SIGNATURE=signature,
        )
        video.refresh_from_db()

        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content), {"success": True})
        self.assertEqual(video.uploaded_on, None)
        self.assertEqual(video.upload_state, "error")
        message = async_to_sync(channel_layer.receive)("test_channel")
        self.assertEqual(message["type"], "video_updated")
        message = async_to_sync(channel_layer.receive)("test_channel_admin")
        self.assertEqual(message["type"], "video_updated")
Exemplo n.º 3
0
    async def test_timed_text_track_update_channel_layer(self):
        """Message received on timed_text_track_updated event."""
        timed_text_track = await self._get_timed_text_track()

        jwt_token = AccessToken()
        jwt_token.payload["resource_id"] = str(timed_text_track.video_id)
        jwt_token.payload["consumer_site"] = str(
            timed_text_track.video.consumer_site.id)
        jwt_token.payload["context_id"] = "Maths"
        jwt_token.payload["roles"] = ["student"]
        jwt_token.payload["permissions"] = {"can_update": False}
        jwt_token.payload["user"] = {
            "id": "444444",
        }

        communicator = WebsocketCommunicator(
            base_application,
            f"ws/video/{timed_text_track.video_id}/?jwt={jwt_token}",
        )

        connected, _ = await communicator.connect()

        self.assertTrue(connected)

        channel_layer = get_channel_layer()

        await channel_layer.group_send(
            VIDEO_ROOM_NAME.format(video_id=str(timed_text_track.video_id)),
            {
                "type":
                "timed_text_track_updated",
                "timed_text_track":
                await
                self._get_timed_text_track_serializer_data(timed_text_track),
            },
        )

        response = await communicator.receive_from()
        self.assertEqual(
            json.loads(response),
            {
                "type": "timedtexttracks",
                "resource": {
                    "active_stamp": None,
                    "id": str(timed_text_track.id),
                    "is_ready_to_show": False,
                    "language": timed_text_track.language,
                    "mode": timed_text_track.mode,
                    "source_url": None,
                    "upload_state": "pending",
                    "url": None,
                    "video": str(timed_text_track.video_id),
                },
            },
        )
Exemplo n.º 4
0
    def test_send_video_to_simple_user(self):
        """A message containing serialized video is dispatched to the regular group."""
        video = VideoFactory()

        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_add)(
            VIDEO_ROOM_NAME.format(video_id=str(video.id)), "test_channel")

        channel_layers_utils.dispatch_video(video, to_admin=False)

        message = async_to_sync(channel_layer.receive)("test_channel")
        self.assertEqual(message["type"], "video_updated")
        self.assertEqual(
            message["video"],
            VideoSerializer(video, context={
                "is_admin": False
            }).data)
Exemplo n.º 5
0
    async def test_thumbnail_update_channel_layer(self):
        """Message received on thumbnail_updated event."""
        thumbnail = await self._get_thumbnail()

        jwt_token = AccessToken()
        jwt_token.payload["resource_id"] = str(thumbnail.video_id)

        communicator = WebsocketCommunicator(
            base_application,
            f"ws/video/{thumbnail.video_id}/?jwt={jwt_token}",
        )

        connected, _ = await communicator.connect()

        self.assertTrue(connected)

        channel_layer = get_channel_layer()

        await channel_layer.group_send(
            VIDEO_ROOM_NAME.format(video_id=str(thumbnail.video_id)),
            {
                "type": "thumbnail_updated",
                "thumbnail": await
                self._get_thumbnail_serializer_data(thumbnail),
            },
        )

        response = await communicator.receive_from()
        self.assertEqual(
            json.loads(response),
            {
                "type": "thumbnails",
                "resource": {
                    "active_stamp": None,
                    "id": str(thumbnail.id),
                    "is_ready_to_show": False,
                    "upload_state": "pending",
                    "urls": None,
                    "video": str(thumbnail.video_id),
                },
            },
        )
Exemplo n.º 6
0
    def test_api_update_state_video(self):
        """Confirming the successful upload of a video using the sole existing secret."""
        video = VideoFactory(id="f87b5f26-da60-49f2-9d71-a816e68a207f")
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_add)(
            VIDEO_ROOM_NAME.format(video_id=str(video.id)), "test_channel")
        async_to_sync(channel_layer.group_add)(
            VIDEO_ADMIN_ROOM_NAME.format(video_id=str(video.id)),
            "test_channel_admin")
        data = {
            "extraParameters": {
                "resolutions": [144, 240, 480]
            },
            "key": f"{video.pk}/video/{video.pk}/1533686400",
            "state": "ready",
        }
        signature = generate_hash("shared secret",
                                  json.dumps(data).encode("utf-8"))
        response = self.client.post(
            "/api/update-state",
            data,
            content_type="application/json",
            HTTP_X_MARSHA_SIGNATURE=signature,
        )
        video.refresh_from_db()

        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content), {"success": True})
        self.assertEqual(video.uploaded_on,
                         datetime(2018, 8, 8, tzinfo=timezone.utc))
        self.assertEqual(video.upload_state, "ready")
        self.assertEqual(video.resolutions, [144, 240, 480])
        message = async_to_sync(channel_layer.receive)("test_channel")
        self.assertEqual(message["type"], "video_updated")
        message = async_to_sync(channel_layer.receive)("test_channel_admin")
        self.assertEqual(message["type"], "video_updated")
Exemplo n.º 7
0
    async def test_video_update_instructor_channel_layer(self):
        """Admin user should receive message only from the admin channel."""
        video = await self._get_video(
            live_state=RUNNING,
            live_type=JITSI,
            live_info={
                "medialive": {
                    "input": {
                        "id":
                        "medialive_input_1",
                        "endpoints": [
                            "https://live_endpoint1",
                            "https://live_endpoint2",
                        ],
                    },
                    "channel": {
                        "id": "medialive_channel_1"
                    },
                },
                "mediapackage": {
                    "id": "mediapackage_channel_1",
                    "endpoints": {
                        "hls": {
                            "id": "endpoint1",
                            "url": "https://channel_endpoint1/live.m3u8",
                        },
                    },
                },
            },
        )

        jwt_token = AccessToken()
        jwt_token.payload["resource_id"] = str(video.id)
        jwt_token.payload["roles"] = [
            random.choice(["instructor", "administrator"])
        ]
        jwt_token.payload["permissions"] = {"can_update": True}

        communicator = WebsocketCommunicator(
            base_application,
            f"ws/video/{video.id}/?jwt={jwt_token}",
        )

        connected, _ = await communicator.connect()

        self.assertTrue(connected)

        channel_layer = get_channel_layer()

        await channel_layer.group_send(
            VIDEO_ROOM_NAME.format(video_id=str(video.id)),
            {
                "type":
                "video_updated",
                "video":
                await self._get_serializer_data(video, {"is_admin": False}),
            },
        )

        self.assertTrue(await communicator.receive_nothing())

        await channel_layer.group_send(
            VIDEO_ADMIN_ROOM_NAME.format(video_id=str(video.id)),
            {
                "type":
                "video_updated",
                "video":
                await self._get_serializer_data(video, {"is_admin": True}),
            },
        )

        response = await communicator.receive_from()
        self.assertEqual(
            json.loads(response),
            {
                "type": "videos",
                "resource": {
                    "active_shared_live_media": None,
                    "active_shared_live_media_page": None,
                    "active_stamp": None,
                    "allow_recording": True,
                    "description": video.description,
                    "estimated_duration": None,
                    "has_chat": True,
                    "has_live_media": True,
                    "has_transcript": False,
                    "id": str(video.id),
                    "is_public": False,
                    "is_ready_to_show": True,
                    "is_scheduled": False,
                    "timed_text_tracks": [],
                    "thumbnail": None,
                    "title": video.title,
                    "upload_state": "pending",
                    "urls": {
                        "manifests": {
                            "hls": "https://channel_endpoint1/live.m3u8"
                        },
                        "mp4": {},
                        "thumbnails": {},
                    },
                    "show_download": True,
                    "should_use_subtitle_as_transcript": False,
                    "starting_at": None,
                    "playlist": {
                        "id": str(video.playlist.id),
                        "title": video.playlist.title,
                        "lti_id": video.playlist.lti_id,
                    },
                    "live_info": {
                        "jitsi": {
                            "config_overwrite": {},
                            "domain": "meet.jit.si",
                            "external_api_url":
                            "https://meet.jit.si/external_api.js",
                            "interface_config_overwrite": {},
                        },
                        "medialive": {
                            "input": {
                                "endpoints": [
                                    "https://live_endpoint1",
                                    "https://live_endpoint2",
                                ],
                            },
                        },
                    },
                    "live_state": RUNNING,
                    "live_type": JITSI,
                    "xmpp": None,
                    "shared_live_medias": [],
                },
            },
        )

        await communicator.disconnect()
Exemplo n.º 8
0
    def test_api_update_state_video_harvested(self):
        """Video `upload_state` to `harvested` should reset live state and live info."""
        video = VideoFactory(
            id="1c5a998a-5bb9-41ea-836e-22be0cdeb834",
            upload_state=PENDING,
            live_state=STOPPED,
            live_info={
                "medialive": {
                    "input": {
                        "id":
                        "medialive_input_1",
                        "endpoints": [
                            "https://live_endpoint1",
                            "https://live_endpoint2",
                        ],
                    },
                    "channel": {
                        "id": "medialive_channel_1"
                    },
                },
                "mediapackage": {
                    "id": "mediapackage_channel_1",
                    "endpoints": {
                        "hls": {
                            "id": "endpoint1",
                            "url": "https://channel_endpoint1/live.m3u8",
                        },
                    },
                },
            },
            live_type=RAW,
        )
        channel_layer = get_channel_layer()
        async_to_sync(channel_layer.group_add)(
            VIDEO_ROOM_NAME.format(video_id=str(video.id)), "test_channel")
        async_to_sync(channel_layer.group_add)(
            VIDEO_ADMIN_ROOM_NAME.format(video_id=str(video.id)),
            "test_channel_admin")
        data = {
            "extraParameters": {
                "resolutions": [240, 480, 720]
            },
            "key": f"{video.pk}/video/{video.pk}/1533686400",
            "state": "harvested",
        }
        signature = generate_hash("shared secret",
                                  json.dumps(data).encode("utf-8"))
        response = self.client.post(
            "/api/update-state",
            data,
            content_type="application/json",
            HTTP_X_MARSHA_SIGNATURE=signature,
        )
        video.refresh_from_db()

        self.assertEqual(response.status_code, 200)
        self.assertEqual(json.loads(response.content), {"success": True})
        self.assertEqual(video.uploaded_on,
                         datetime(2018, 8, 8, tzinfo=timezone.utc))
        self.assertEqual(video.upload_state, HARVESTED)
        self.assertEqual(video.resolutions, [240, 480, 720])
        self.assertIsNone(video.live_state)
        self.assertIsNone(video.live_info)
        message = async_to_sync(channel_layer.receive)("test_channel")
        self.assertEqual(message["type"], "video_updated")
        message = async_to_sync(channel_layer.receive)("test_channel_admin")
        self.assertEqual(message["type"], "video_updated")
Exemplo n.º 9
0
    async def test_video_update_channel_layer(self):
        """Messages sent on the admin channel should not be received by a regular user."""
        video = await self._get_video(
            live_state=RUNNING,
            live_type=JITSI,
            live_info={
                "medialive": {
                    "input": {
                        "id":
                        "medialive_input_1",
                        "endpoints": [
                            "https://live_endpoint1",
                            "https://live_endpoint2",
                        ],
                    },
                    "channel": {
                        "id": "medialive_channel_1"
                    },
                },
                "mediapackage": {
                    "id": "mediapackage_channel_1",
                    "endpoints": {
                        "hls": {
                            "id": "endpoint1",
                            "url": "https://channel_endpoint1/live.m3u8",
                        },
                    },
                },
            },
        )

        jwt_token = AccessToken()
        jwt_token.payload["resource_id"] = str(video.id)
        jwt_token.payload["consumer_site"] = str(video.consumer_site.id)
        jwt_token.payload["context_id"] = "Maths"
        jwt_token.payload["roles"] = ["student"]
        jwt_token.payload["permissions"] = {"can_update": False}
        jwt_token.payload["user"] = {
            "id": "444444",
        }

        communicator = WebsocketCommunicator(
            base_application,
            f"ws/video/{video.id}/?jwt={jwt_token}",
        )

        connected, _ = await communicator.connect()

        self.assertTrue(connected)

        channel_layer = get_channel_layer()

        await channel_layer.group_send(
            VIDEO_ROOM_NAME.format(video_id=str(video.id)),
            {
                "type":
                "video_updated",
                "video":
                await self._get_serializer_data(video, {"is_admin": False}),
            },
        )

        response = await communicator.receive_from()
        self.assertEqual(
            json.loads(response),
            {
                "type": "videos",
                "resource": {
                    "active_shared_live_media": None,
                    "active_shared_live_media_page": None,
                    "active_stamp": None,
                    "allow_recording": True,
                    "description": video.description,
                    "estimated_duration": None,
                    "has_chat": True,
                    "has_live_media": True,
                    "has_transcript": False,
                    "id": str(video.id),
                    "is_public": False,
                    "is_ready_to_show": True,
                    "is_recording": False,
                    "is_scheduled": False,
                    "join_mode": "approval",
                    "timed_text_tracks": [],
                    "thumbnail": None,
                    "title": video.title,
                    "upload_state": "pending",
                    "urls": {
                        "manifests": {
                            "hls": "https://channel_endpoint1/live.m3u8"
                        },
                        "mp4": {},
                        "thumbnails": {},
                    },
                    "show_download": True,
                    "should_use_subtitle_as_transcript": False,
                    "starting_at": None,
                    "participants_asking_to_join": [],
                    "participants_in_discussion": [],
                    "playlist": {
                        "id": str(video.playlist.id),
                        "title": video.playlist.title,
                        "lti_id": video.playlist.lti_id,
                    },
                    "recording_time": 0,
                    "live_info": {},
                    "live_state": RUNNING,
                    "live_type": JITSI,
                    "xmpp": None,
                    "shared_live_medias": [],
                },
            },
        )

        await channel_layer.group_send(
            VIDEO_ADMIN_ROOM_NAME.format(video_id=str(video.id)),
            {
                "type":
                "video_updated",
                "video":
                await self._get_serializer_data(video, {"is_admin": True}),
            },
        )

        self.assertTrue(await communicator.receive_nothing())

        await communicator.disconnect()