def test_map_user_joined_event(self): event = { "server_url": "mocked-server", "data": { "type": "event", "id": "user-joined", "attributes": { "meeting": { "external-meeting-id": "madeup-external-meeting-id", "internal-meeting-id": "madeup-internal-meeting-id", }, "user": { "name": "madeup-user", "role": "MODERATOR", "presenter": True, "internal-user-id": "madeup-internal-user-id", "external-user-id": "madeup-external-user-id", }, }, "event": { "ts": 1502810164922 }, }, } expected = WebhookEvent( event_type="user-joined", server_url="mocked-server", event=UserJoinedEvent( name="madeup-user", role="MODERATOR", internal_user_id="madeup-internal-user-id", external_user_id="madeup-external-user-id", internal_meeting_id="madeup-internal-meeting-id", external_meeting_id="madeup-external-meeting-id", join_time=1502810164922, is_presenter=True, userdata={}, ), ) with mock.patch( "mconf_aggr.webhook.event_mapper._map_user_joined_event" ) as _map_user_joined_event_mock: map_webhook_event(event) _map_user_joined_event_mock.assert_called_with( event, "user-joined", "mocked-server") got = map_webhook_event(event) self.assertEqual(got, expected)
def test_missing_event_type(self): event = { "data": { "type": "event", "attributes": { "meeting": {}, "event": { "ts": 1502810164922 } }, } } with self.assertRaises(InvalidWebhookMessageError): map_webhook_event(event)
def test_map_user_voice_enabled_event(self): event = { "server_url": "mocked-server", "data": { "type": "event", "id": "user-audio-voice-enabled", "attributes": { "meeting": { "internal-meeting-id": "madeup-internal-meeting-id", "external-meeting-id": "madeup-external-meeting-id", }, "user": { "internal-user-id": "madeup-internal-user-id", "external-user-id": "madeup-external-user-id", "sharing-mic": False, "listening-only": True, }, }, "event": { "ts": 1502810164922 }, }, } expected = WebhookEvent( event_type="user-audio-voice-enabled", server_url="mocked-server", event=UserVoiceEnabledEvent( internal_user_id="madeup-internal-user-id", external_user_id="madeup-external-user-id", internal_meeting_id="madeup-internal-meeting-id", external_meeting_id="madeup-external-meeting-id", has_joined_voice=False, is_listening_only=True, event_name="user-audio-voice-enabled", ), ) with mock.patch( "mconf_aggr.webhook.event_mapper._map_user_voice_enabled_event" ) as _map_user_voice_enabled_event_mock: map_webhook_event(event) _map_user_voice_enabled_event_mock.assert_called_with( event, "user-audio-voice-enabled", "mocked-server") got = map_webhook_event(event) self.assertEqual(got, expected)
def test_invalid_event_type(self): event = { "data": { "type": "event", "id": "invalid-event", "attributes": { "meeting": {}, "event": { "ts": 1502810164922 } }, }, "server_url": "mocked-server", } with self.assertRaises(InvalidWebhookEventError): map_webhook_event(event)
def test_map_user_left_event(self): event = { "server_url": "mocked-server", "data": { "type": "event", "id": "user-left", "attributes": { "meeting": { "external-meeting-id": "madeup-external-meeting-id", "internal-meeting-id": "madeup-internal-meeting-id", }, "user": { "internal-user-id": "madeup-internal-user-id", "external-user-id": "madeup-external-user-id", }, }, "event": { "ts": 1502810164922 }, }, } expected = WebhookEvent( event_type="user-left", server_url="mocked-server", event=UserLeftEvent( internal_user_id="madeup-internal-user-id", external_user_id="madeup-external-user-id", internal_meeting_id="madeup-internal-meeting-id", external_meeting_id="madeup-external-meeting-id", leave_time=1502810164922, userdata={}, ), ) with mock.patch("mconf_aggr.webhook.event_mapper._map_user_left_event" ) as _map_user_left_event_mock: map_webhook_event(event) _map_user_left_event_mock.assert_called_with( event, "user-left", "mocked-server") got = map_webhook_event(event) self.assertEqual(got, expected)
def test_map_rap_event(self): event = { "server_url": "mocked-server", "data": { "type": "event", "id": "rap-publish-started", "attributes": { "meeting": { "internal-meeting-id": "madeup-internal-meeting-id", "external-meeting-id": "madeup-external-meeting-id", } }, "event": { "ts": 1502810164922 }, }, } expected = WebhookEvent( event_type="rap-publish-started", server_url="mocked-server", event=RapPublishEvent( external_meeting_id="madeup-external-meeting-id", internal_meeting_id="madeup-internal-meeting-id", record_id="madeup-internal-meeting-id", current_step="rap-publish-started", workflow={}, ), ) with mock.patch( "mconf_aggr.webhook.event_mapper._map_rap_publish_event" ) as _map_rap_event_mock: map_webhook_event(event) _map_rap_event_mock.assert_called_with(event, "rap-publish-started", "mocked-server") got = map_webhook_event(event) self.assertEqual(got, expected)
def test_map_end_event(self): event = { "server_url": "mocked-server", "data": { "type": "event", "id": "meeting-ended", "attributes": { "meeting": { "external-meeting-id": "mock_e", "internal-meeting-id": "mock_i", } }, "event": { "ts": 1502810164922 }, }, } expected = WebhookEvent( event_type="meeting-ended", server_url="mocked-server", event=MeetingEndedEvent( external_meeting_id="mock_e", internal_meeting_id="mock_i", end_time=1502810164922, ), ) with mock.patch("mconf_aggr.webhook.event_mapper._map_end_event" ) as _map_end_event_mock: map_webhook_event(event) _map_end_event_mock.assert_called_with(event, "meeting-ended", "mocked-server") got = map_webhook_event(event) self.assertEqual(got, expected)
def test_map_create_event(self): event = { "server_url": "localhost", "data": { "type": "event", "id": "meeting-created", "attributes": { "meeting": { "external-meeting-id": "mock_e", "internal-meeting-id": "mock_i", "name": "mock_n", "create-time": 0000000, "create-date": "Mock Date", "dial-number": "000-000-0000", "moderator-pass": "******", "duration": 0, "recording": False, "max-users": 0, "is-breakout": False, "metadata": { "mock_data": "mock", "another_mock": "mocked" }, }, "event": { "ts": 1502810164922 }, }, }, } expected = WebhookEvent( event_type="meeting-created", server_url="localhost", event=MeetingCreatedEvent( server_url="localhost", external_meeting_id="mock_e", internal_meeting_id="mock_i", parent_meeting_id="", name="mock_n", create_time=0000000, create_date="Mock Date", voice_bridge="", dial_number="000-000-0000", attendee_pw="", moderator_pw="mp", duration=0, recording=False, max_users=0, is_breakout=False, meta_data={ "mock_data": "mock", "another_mock": "mocked" }, ), ) with mock.patch("mconf_aggr.webhook.event_mapper._map_create_event" ) as _map_create_event_mock: map_webhook_event(event) _map_create_event_mock.assert_called_with(event, "meeting-created", "localhost") got = map_webhook_event(event) self.assertEqual(got, expected)
def test_map_rap_publish_ended_event(self): event = { "server_url": "mocked-server", "data": { "type": "event", "id": "rap-publish-ended", "attributes": { "meeting": { "internal-meeting-id": "madeup-internal-meeting-id", "external-meeting-id": "madeup-external-meeting-id", }, "success": True, "step-time": 480, "recording": { "name": "madeup-recording-name", "isBreakout": False, "size": 213541, "raw-size": 213542, "start-time": 1, "end-time": 2, "metadata": { "meetingId": "madeup-external-meeting-id", "meetingName": "madeup-external-meeting-id", "isBreakout": False, }, "playback": { "format": "presentation", "link": "madeup-link", "processing_time": 2060, "duration": 5663, "extensions": { "preview": { "images": { "image": "madeup-image-link" } } }, "size": 213541, }, "download": {}, }, }, "event": { "ts": 1502810164922 }, }, } expected = WebhookEvent( event_type="rap-publish-ended", server_url="mocked-server", event=RapPublishEndedEvent( name="madeup-recording-name", is_breakout=False, start_time=1, end_time=2, size=213541, raw_size=213542, meta_data={ "meetingId": "madeup-external-meeting-id", "meetingName": "madeup-external-meeting-id", "isBreakout": False, }, playback={ "format": "presentation", "link": "madeup-link", "processing_time": 2060, "duration": 5663, "extensions": { "preview": { "images": { "image": "madeup-image-link" } } }, "size": 213541, }, download={}, workflow={}, external_meeting_id="madeup-external-meeting-id", internal_meeting_id="madeup-internal-meeting-id", current_step="rap-publish-ended", ), ) with mock.patch( "mconf_aggr.webhook.event_mapper._map_rap_publish_ended_event" ) as _map_rap_publish_ended_event_mock: map_webhook_event(event) _map_rap_publish_ended_event_mock.assert_called_with( event, "rap-publish-ended", "mocked-server") got = map_webhook_event(event) self.assertEqual(got, expected)
def process_event(self, server_url, event): """Parse and publish data to aggregator. Raises Exception If any error occur during event handling. Parameters ---------- server_url : str event origin's URL. event : str event to be parsed and published. """ logging_extra = { "code": "Parse and publish data", "site": "WebhookEventHandler.process_event", "server": server_url or "", "keywords": [ "WebhookEventHandler", "parse", "publish", "data", "process", "to aggregator", ], } # TODO(psv): verify if this is essential # unquoted_event = unquote(event) try: # decoded_events = self._decode(unquoted_event) logging_extra["code"] = "Decoding events" self.logger.debug( "Parsing events as a JSON file.", extra=dict(logging_extra, keywords=json.dumps(logging_extra["keywords"])), ) decoded_events = self._decode(event) except json.JSONDecodeError as err: logging_extra["code"] = "Invalid JSON" logging_extra["keywords"] += ["JSON", "error", "except"] self.logger.error( f"Error during event decoding: invalid JSON: {err}") raise RequestProcessingError("Event provided is not a valid JSON") if server_url: # In case the server URL does not contain a valid scheme. logging_extra["code"] = "Decoding url" self.logger.debug( "Normalizing server url.", extra=dict(logging_extra, keywords=json.dumps(logging_extra["keywords"])), ) server_url = _normalize_server_url(server_url) logging_extra["server"] = server_url deprecated_events = cfg.config["MCONF_WEBHOOK_DEPRECATED_EVENTS"] # We can handle more than one event at once. for webhook_event in decoded_events: with time_logger( self.logger.info, "Handling event took {elapsed}s.", extra=dict(logging_extra, keywords=json.dumps(logging_extra["keywords"])), ): webhook_event["server_url"] = server_url try: # Instance of WebhookEvent. webhook_event = map_webhook_event(webhook_event) except Exception as err: logging_extra["code"] = "Mapping error" logging_extra["keywords"] += ["mapper", "warning"] self.logger.warning(f"Something went wrong: {err}") webhook_event = None if webhook_event: if webhook_event.event_type in deprecated_events: logging_extra["code"] = "Event deprecated" logging_extra["event"] = webhook_event.event_type logging_extra["server"] = webhook_event.server_url logging_extra["keywords"] = [ "WebhookEventHandler", "parse", "publish", "data", "process", "to aggregator", ] self.logger.info( "Received event is in deprecated event list: '{}'". format(deprecated_events), extra=dict( logging_extra, keywords=json.dumps(logging_extra["keywords"]), ), ) else: try: logging_extra["event"] = webhook_event.event_type logging_extra["code"] = "Publishing webhook event" logging_extra["keywords"] = [ "WebhookEventHandler", "parse", "publish", "data", "process", "to aggregator", f"channel={self.channel}", ] self.logger.debug( "Publishing event.", extra=dict( logging_extra, keywords=json.dumps( logging_extra["keywords"]), ), ) self.publisher.publish(webhook_event, channel=self.channel) except PublishError: logging_extra["code"] = "Publish error" logging_extra["keywords"] = [ "WebhookEventHandler", "parse", "publish", "data", "process", "to aggregator", "exception", "error", ] self.logger.error( "Something went wrong while publishing.") continue else: logging_extra["code"] = "Not publishing" logging_extra["keywords"] = [ "WebhookEventHandler", "parse", "publish", "data", "process", "to aggregator", "warning", ] self.logger.warn( "Not publishing event from '{}'".format(server_url)) logging_extra["code"] = "HandlingEventTime" logging_extra["keywords"] = [ "event", "handle", "time", "map", "publish", ]