From 7a8d8fe62ed62e4c650acf1334c96de926b01bc0 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Wed, 1 Nov 2023 14:51:44 +0100 Subject: [PATCH 01/14] function to join a room --- cdci_data_analysis/analysis/matrix_helper.py | 38 ++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/cdci_data_analysis/analysis/matrix_helper.py b/cdci_data_analysis/analysis/matrix_helper.py index 92e2513e2..5ee31f97f 100644 --- a/cdci_data_analysis/analysis/matrix_helper.py +++ b/cdci_data_analysis/analysis/matrix_helper.py @@ -277,6 +277,44 @@ def send_job_message( return res_content +def join_room( + logger, + url_server=None, + sender_access_token=None, + room_id=None, +): + logger.info(f"Joining room wth id: {room_id}") + url = os.path.join(url_server, f'_matrix/client/v3/rooms/{room_id}/join') + + headers = { + 'Authorization': ' '.join(['Bearer', sender_access_token]), + 'Content-type': 'application/json' + } + + res = requests.post(url, headers=headers) + + msg_response_data = None + if res.status_code in [403, 429]: + msg_response_data = res.json() + error_code = "" + if "errcode" in msg_response_data: + error_code = msg_response_data["errcode"] + error = "" + if "error" in msg_response_data: + error = msg_response_data["error"] + logger.info(f"Could not join the room: {room_id}, for the following reason: {error_code} - {error}") + + sentry.capture_message(f"Could not join the room: {room_id}, for the following reason: {error_code}: {error}") + raise MatrixMessageNotSent(f"Could not join the room: {room_id}, for the following reason: {error_code}: {error}", + status_code=res.status_code, + payload={'matrix_error_message': f"{error_code} - {error}"}) + + elif res.status_code == 200: + logger.info(f"Successfully joined the room: {room_id}") + + return msg_response_data + + def send_message( logger, url_server=None, From 370ebc01db3592783e2f17ad8bda436db107f095 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Wed, 1 Nov 2023 16:33:00 +0100 Subject: [PATCH 02/14] detailed returned object from sending job message on matrix --- cdci_data_analysis/analysis/matrix_helper.py | 70 +++++--- .../flask_app/dispatcher_query.py | 150 ++++++++++-------- 2 files changed, 125 insertions(+), 95 deletions(-) diff --git a/cdci_data_analysis/analysis/matrix_helper.py b/cdci_data_analysis/analysis/matrix_helper.py index 5ee31f97f..ff545fd1d 100644 --- a/cdci_data_analysis/analysis/matrix_helper.py +++ b/cdci_data_analysis/analysis/matrix_helper.py @@ -233,44 +233,64 @@ def send_job_message( message_body_html = template.render(**matrix_message_data) message_text = textify_matrix_message(message_body_html) res_content = { - 'res_content_bcc_users': [] + 'res_content_bcc_users': [], + 'res_content_bcc_users_failed': [] } message_data = { 'message_data_bcc_users': [] } if receiver_room_id is not None and receiver_room_id != "": - res_data_message_token_user = send_message( - logger, - url_server=matrix_server_url, - sender_access_token=matrix_sender_access_token, - room_id=receiver_room_id, - message_text=message_text, - message_body_html=message_body_html - ) - message_data_token_user = res_data_message_token_user['message_data'] - res_content_token_user = res_data_message_token_user['res_content'] - message_data['message_data_token_user'] = message_data_token_user - res_content['res_content_token_user'] = res_content_token_user - else: - logger.warning('a matrix message could not be sent to the token user as no personal room id was ' - 'provided within the token') - - for bcc_receiver_room_id in bcc_receivers_room_ids: - if bcc_receiver_room_id is not None and bcc_receiver_room_id != "": - res_data_message_cc_user = send_message( + try: + join_room( + logger, + url_server=matrix_server_url, + sender_access_token=matrix_sender_access_token, + room_id=receiver_room_id + ) + res_data_message_token_user = send_message( logger, url_server=matrix_server_url, sender_access_token=matrix_sender_access_token, - room_id=bcc_receiver_room_id, + room_id=receiver_room_id, message_text=message_text, message_body_html=message_body_html ) - message_data_cc_user = res_data_message_cc_user['message_data'] - message_data['message_data_bcc_users'].append(message_data_cc_user) - res_content_cc_user = res_data_message_cc_user['res_content'] - res_content['res_content_bcc_users'].append(res_content_cc_user) + message_data_token_user = res_data_message_token_user['message_data'] + res_content_token_user = res_data_message_token_user['res_content'] + message_data['message_data_token_user'] = message_data_token_user + res_content['res_content_token_user'] = res_content_token_user + except MatrixMessageNotSent as e: + logger.warning(f"Issue in sending a message in the room {receiver_room_id} using matrix: {e.message}") + res_content['res_content_token_user_failure'] = f"Issue in sending a message in the room {receiver_room_id} using matrix: {e.message}" + else: + logger.warning('a matrix message could not be sent to the token user as no personal room id was ' + 'provided within the token') + for bcc_receiver_room_id in bcc_receivers_room_ids: + if bcc_receiver_room_id is not None and bcc_receiver_room_id != "": + try: + join_room( + logger, + url_server=matrix_server_url, + sender_access_token=matrix_sender_access_token, + room_id=bcc_receiver_room_id + ) + res_data_message_cc_user = send_message( + logger, + url_server=matrix_server_url, + sender_access_token=matrix_sender_access_token, + room_id=bcc_receiver_room_id, + message_text=message_text, + message_body_html=message_body_html + ) + message_data_cc_user = res_data_message_cc_user['message_data'] + message_data['message_data_bcc_users'].append(message_data_cc_user) + res_content_cc_user = res_data_message_cc_user['res_content'] + res_content['res_content_bcc_users'].append(res_content_cc_user) + except MatrixMessageNotSent as e: + logger.warning(f"Issue in sending a message in the room {bcc_receiver_room_id} using matrix: {e.message}") + res_content['res_content_bcc_users_failed'].append(f"Issue in sending a message in the room {bcc_receiver_room_id} using matrix: {e.message}") store_status_matrix_message_info(message_data, status, scratch_dir, logger, sending_time=sending_time, first_submitted_time=time_request) diff --git a/cdci_data_analysis/flask_app/dispatcher_query.py b/cdci_data_analysis/flask_app/dispatcher_query.py index 131e88f49..76cf96a07 100644 --- a/cdci_data_analysis/flask_app/dispatcher_query.py +++ b/cdci_data_analysis/flask_app/dispatcher_query.py @@ -1151,49 +1151,53 @@ def run_call_back(self, status_kw_name='action') -> typing.Tuple[str, typing.Uni logging.warning(f'issue when {step}: {e}') sentry.capture_message(f'issue when {step}: {e}') - try: - if is_message_to_send: - time_request = time_original_request - time_request_first_submitted = matrix_helper.get_first_submitted_matrix_message_time(self.scratch_dir) - if time_request_first_submitted is not None: - time_request = time_request_first_submitted - - res_content = matrix_helper.send_job_message( - config=self.app.config['conf'], - logger=self.logger, - decoded_token=self.decoded_token, - token=self.token, - job_id=self.job_id, - session_id=self.par_dic['session_id'], - status=status, - instrument=self.instrument_name, - status_details=status_details, - product_type=product_type, - time_request=time_request, - request_url=products_url, - api_code=email_api_code, - scratch_dir=self.scratch_dir) - - matrix_message_status_details = { - "res_content": res_content - } - if status_details is not None: - matrix_message_status_details['status_details'] = status_details + # try: + if is_message_to_send: + time_request = time_original_request + time_request_first_submitted = matrix_helper.get_first_submitted_matrix_message_time(self.scratch_dir) + if time_request_first_submitted is not None: + time_request = time_request_first_submitted + + res_content = matrix_helper.send_job_message( + config=self.app.config['conf'], + logger=self.logger, + decoded_token=self.decoded_token, + token=self.token, + job_id=self.job_id, + session_id=self.par_dic['session_id'], + status=status, + instrument=self.instrument_name, + status_details=status_details, + product_type=product_type, + time_request=time_request, + request_url=products_url, + api_code=email_api_code, + scratch_dir=self.scratch_dir) + + matrix_message_status_details = { + "res_content": res_content + } + if status_details is not None: + matrix_message_status_details['status_details'] = status_details - job.write_dataserver_status(status_dictionary_value=status, - full_dict=self.par_dic, - matrix_message_status='matrix message sent', - matrix_message_status_details=json.dumps(matrix_message_status_details)) - else: - job.write_dataserver_status(status_dictionary_value=status, full_dict=self.par_dic) + matrix_message_status = 'matrix message sent' + if 'res_content_token_user_failure' in res_content or len(res_content['res_content_bcc_users_failed']) > 1: + matrix_message_status = 'sending message via matrix failed' - except matrix_helper.MatrixMessageNotSent as e: job.write_dataserver_status(status_dictionary_value=status, full_dict=self.par_dic, - matrix_message_status='sending message via matrix failed', - matrix_message_status_details=e.payload) - logging.warning(f'matrix message sending failed: {e}') - sentry.capture_message(f'sending matrix message failed {e.message}') + matrix_message_status=matrix_message_status, + matrix_message_status_details=json.dumps(matrix_message_status_details)) + else: + job.write_dataserver_status(status_dictionary_value=status, full_dict=self.par_dic) + + # except matrix_helper.MatrixMessageNotSent as e: + # job.write_dataserver_status(status_dictionary_value=status, + # full_dict=self.par_dic, + # matrix_message_status='sending message via matrix failed', + # matrix_message_status_details=e.payload) + # logging.warning(f'matrix message sending failed: {e}') + # sentry.capture_message(f'sending matrix message failed {e.message}') try: # TODO for a future implementation @@ -1973,37 +1977,43 @@ def run_query(self, off_line=False, disp_conf=None): self.job_id, self.app.config['conf'], decoded_token=self.decoded_token): - try: - time_request = self.time_request - time_request_first_submitted = matrix_helper.get_first_submitted_matrix_message_time(self.scratch_dir) - if time_request_first_submitted is not None: - time_request = time_request_first_submitted - - res_content = matrix_helper.send_job_message( - config=self.app.config['conf'], - logger=self.logger, - decoded_token=self.decoded_token, - token=self.token, - job_id=self.job_id, - session_id=self.par_dic['session_id'], - status=query_new_status, - instrument=self.instrument.name, - product_type=product_type, - time_request=time_request, - request_url=products_url, - api_code=email_api_code, - scratch_dir=self.scratch_dir) - - matrix_message_status_details = json.dumps({ - "res_content": res_content - }) - query_out.set_status_field('matrix_message_status', 'matrix message sent') - query_out.set_status_field('matrix_message_status_details', matrix_message_status_details) - except matrix_helper.MatrixMessageNotSent as e: - query_out.set_status_field('matrix_message_status', 'sending matrix message failed') - query_out.set_status_field('matrix_message_status_details', e.payload) - logging.warning(f'matrix message sending failed: {e}') - sentry.capture_message(f'sending matrix message failed {e.message}') + # try: + time_request = self.time_request + time_request_first_submitted = matrix_helper.get_first_submitted_matrix_message_time(self.scratch_dir) + if time_request_first_submitted is not None: + time_request = time_request_first_submitted + + res_content = matrix_helper.send_job_message( + config=self.app.config['conf'], + logger=self.logger, + decoded_token=self.decoded_token, + token=self.token, + job_id=self.job_id, + session_id=self.par_dic['session_id'], + status=query_new_status, + instrument=self.instrument.name, + product_type=product_type, + time_request=time_request, + request_url=products_url, + api_code=email_api_code, + scratch_dir=self.scratch_dir) + + matrix_message_status_details = json.dumps({ + "res_content": res_content + }) + + matrix_message_status = 'matrix message sent' + if 'res_content_token_user_failure' in res_content or len( + res_content['res_content_bcc_users_failed']) > 1: + matrix_message_status = 'sending message via matrix failed' + + query_out.set_status_field('matrix_message_status', matrix_message_status) + query_out.set_status_field('matrix_message_status_details', matrix_message_status_details) + # except matrix_helper.MatrixMessageNotSent as e: + # query_out.set_status_field('matrix_message_status', 'sending matrix message failed') + # query_out.set_status_field('matrix_message_status_details', e.payload) + # logging.warning(f'matrix message sending failed: {e}') + # sentry.capture_message(f'sending matrix message failed {e.message}') if email_helper.is_email_to_send_run_query(self.logger, query_new_status, From d9385072bde3d19976c8ef82d0685e93f5734737 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Wed, 1 Nov 2023 16:42:26 +0100 Subject: [PATCH 03/14] detailed returned object from sending incident report message on matrix --- cdci_data_analysis/analysis/matrix_helper.py | 37 ++++++++++++++------ cdci_data_analysis/flask_app/app.py | 14 +++++--- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/cdci_data_analysis/analysis/matrix_helper.py b/cdci_data_analysis/analysis/matrix_helper.py index ff545fd1d..6bf055a91 100644 --- a/cdci_data_analysis/analysis/matrix_helper.py +++ b/cdci_data_analysis/analysis/matrix_helper.py @@ -129,7 +129,8 @@ def send_incident_report_message( # open("debug_email_lines_too_long.text", "w").write(email_text) # raise MatrixMessageNotSent(f"message not sent on matrix, lines too long!") res_content = { - 'res_content_incident_reports': [] + 'res_content_incident_reports': [], + 'res_content_incident_reports_failed': [] } message_data = { @@ -137,16 +138,30 @@ def send_incident_report_message( } for incident_report_receiver_room_id in incident_report_receivers_room_ids: - res_data_message_receiver = send_message( - logger, - url_server=matrix_server_url, - sender_access_token=incident_report_sender_personal_access_token, - room_id=incident_report_receiver_room_id, - message_text=message_text, - message_body_html=message_body_html - ) - message_data['message_data_incident_reports'].append(res_data_message_receiver['message_data']) - res_content['res_content_incident_reports'].append(res_data_message_receiver['res_content']) + if incident_report_receiver_room_id is not None and incident_report_receiver_room_id != "": + try: + join_room( + logger, + url_server=matrix_server_url, + sender_access_token=incident_report_sender_personal_access_token, + room_id=incident_report_receiver_room_id + ) + res_data_message_receiver = send_message( + logger, + url_server=matrix_server_url, + sender_access_token=incident_report_sender_personal_access_token, + room_id=incident_report_receiver_room_id, + message_text=message_text, + message_body_html=message_body_html + ) + message_data['message_data_incident_reports'].append(res_data_message_receiver['message_data']) + res_content['res_content_incident_reports'].append(res_data_message_receiver['res_content']) + except MatrixMessageNotSent as e: + sentry.capture_message(f'message sending via matrix failed {e}') + logger.warning(f"Issue in sending a message in the room {incident_report_receiver_room_id} using matrix: {e.message}") + res_content['res_content_incident_reports_failed'].append(f"Issue in sending a message in the room {incident_report_receiver_room_id} using matrix: {e.message}") + else: + logger.warning('a incident report matrix message could not be sent as an invalid room id was provided') store_incident_report_matrix_message(message_data, scratch_dir, sending_time=sending_time) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index b48cdbbec..d50019f05 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -1054,14 +1054,18 @@ def report_incident(): scratch_dir=scratch_dir ) - report_incident_status['martix_message_report_status'] = 'incident report message successfully sent via matrix' + matrix_message_report_status = 'incident report message successfully sent via matrix' + if 'res_content_token_user_failure' in res_content or len(res_content['res_content_bcc_users_failed']) > 1: + matrix_message_report_status = 'incident report message successfully sent via matrix failed' + + report_incident_status['martix_message_report_status'] = matrix_message_report_status report_incident_status['martix_message_report_status_details'] = { "res_content": res_content } - except matrix_helper.MatrixMessageNotSent as e: - report_incident_status['martix_message_report_status'] = 'sending message via matrix failed' - logging.warning(f'message sending via matrix failed: {e}') - sentry.capture_message(f'message sending via matrix failed {e}') + # except matrix_helper.MatrixMessageNotSent as e: + # report_incident_status['martix_message_report_status'] = 'sending message via matrix failed' + # logging.warning(f'message sending via matrix failed: {e}') + # sentry.capture_message(f'message sending via matrix failed {e}') except MissingRequestParameter as e: report_incident_status['martix_message_report_status'] = 'sending message via matrix failed' From b01fbb63c30ee51cd220bd42f415c982da3247d1 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Wed, 1 Nov 2023 17:44:57 +0100 Subject: [PATCH 04/14] invite_to_room function --- cdci_data_analysis/pytest_fixtures.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/cdci_data_analysis/pytest_fixtures.py b/cdci_data_analysis/pytest_fixtures.py index bcf234318..db701f550 100644 --- a/cdci_data_analysis/pytest_fixtures.py +++ b/cdci_data_analysis/pytest_fixtures.py @@ -325,6 +325,28 @@ def __init__(self, self.matrix_sender_access_token = matrix_sender_access_token self.room_id = self.create_room() + + def invite_to_room(self, user_id=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token']): + url = os.path.join(self.matrix_server_url, f'_matrix/client/v3/rooms/{self.room_id}/invite') + headers = { + 'Authorization': ' '.join(['Bearer', self.matrix_sender_access_token]), + 'Content-type': 'application/json' + } + + room_data = { + 'reason': 'test', + 'user_id': user_id + } + + res = requests.post(url, json=room_data, headers=headers) + + if res.status_code == 200: + res_content = res.json() + if res_content == {}: + return True + + return False + def create_room(self): url = os.path.join(self.matrix_server_url, f'_matrix/client/v3/createRoom') headers = { @@ -401,6 +423,7 @@ def get_matrix_message_record(self, room_id, event_id=None): matrix_server_url=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_server_url'], matrix_sender_access_token=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token'] ) + matrix_message_controller.invite_to_room() yield matrix_message_controller matrix_message_controller.leave_room() matrix_message_controller.forget_room() From 1b67fff5ba8342c9f6a0bc47a6598f1439ef8251 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Wed, 1 Nov 2023 18:24:42 +0100 Subject: [PATCH 05/14] invite_to_room default arg --- cdci_data_analysis/pytest_fixtures.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdci_data_analysis/pytest_fixtures.py b/cdci_data_analysis/pytest_fixtures.py index db701f550..1bea8cee8 100644 --- a/cdci_data_analysis/pytest_fixtures.py +++ b/cdci_data_analysis/pytest_fixtures.py @@ -423,7 +423,7 @@ def get_matrix_message_record(self, room_id, event_id=None): matrix_server_url=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_server_url'], matrix_sender_access_token=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token'] ) - matrix_message_controller.invite_to_room() + matrix_message_controller.invite_to_room(user_id=os.getenv("MATRIX_INVITEE_USER_ID", dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token'])) yield matrix_message_controller matrix_message_controller.leave_room() matrix_message_controller.forget_room() From a539ec366f2115ea762439529c24ddc1c00ce852 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Wed, 1 Nov 2023 18:31:24 +0100 Subject: [PATCH 06/14] fixture no invitee_user_id --- cdci_data_analysis/pytest_fixtures.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cdci_data_analysis/pytest_fixtures.py b/cdci_data_analysis/pytest_fixtures.py index 1bea8cee8..000fb078d 100644 --- a/cdci_data_analysis/pytest_fixtures.py +++ b/cdci_data_analysis/pytest_fixtures.py @@ -604,6 +604,10 @@ def dispatcher_test_conf_with_matrix_options_fn(dispatcher_test_conf_fn): def dispatcher_no_bcc_matrix_room_ids(monkeypatch): monkeypatch.delenv('MATRIX_CC_RECEIVER_ROOM_ID', raising=False) +@pytest.fixture +def dispatcher_no_invitee_user_id(monkeypatch): + monkeypatch.delenv('MATRIX_INVITEE_USER_ID', raising=False) + @pytest.fixture def dispatcher_test_conf_with_gallery_no_resolver_fn(dispatcher_test_conf_fn): From 229d54d0d67a56d3d338d06df50b5ab6c17c3f80 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Wed, 1 Nov 2023 19:47:01 +0100 Subject: [PATCH 07/14] more specific tests --- cdci_data_analysis/pytest_fixtures.py | 2 +- tests/test_matrix_messages.py | 76 +++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) diff --git a/cdci_data_analysis/pytest_fixtures.py b/cdci_data_analysis/pytest_fixtures.py index 000fb078d..1e46d370a 100644 --- a/cdci_data_analysis/pytest_fixtures.py +++ b/cdci_data_analysis/pytest_fixtures.py @@ -421,7 +421,7 @@ def get_matrix_message_record(self, room_id, event_id=None): matrix_message_controller = MatrixMessageController( matrix_server_url=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_server_url'], - matrix_sender_access_token=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token'] + matrix_sender_access_token=os.getenv("MATRIX_CREATOR_ACCESS_TOKEN", dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token']) ) matrix_message_controller.invite_to_room(user_id=os.getenv("MATRIX_INVITEE_USER_ID", dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token'])) yield matrix_message_controller diff --git a/tests/test_matrix_messages.py b/tests/test_matrix_messages.py index 3b97cc9f3..5223809c9 100644 --- a/tests/test_matrix_messages.py +++ b/tests/test_matrix_messages.py @@ -826,6 +826,82 @@ def test_matrix_message_submitted_multiple_requests(dispatcher_live_fixture_with assert len(list_overall_matrix_message_files) == 2 +@pytest.mark.test_matrix +@pytest.mark.not_safe_parallel +def test_matrix_message_no_invitee(gunicorn_dispatcher_long_living_fixture_with_matrix_options, + dispatcher_local_matrix_message_server): + DispatcherJobState.remove_scratch_folders() + DataServerQuery.set_status('submitted') + + server = gunicorn_dispatcher_long_living_fixture_with_matrix_options + logger.info("constructed server: %s", server) + + token_payload = { + **default_token_payload, + "mxroomid": dispatcher_local_matrix_message_server.room_id, + "tmx": 0 + } + + encoded_token = jwt.encode(token_payload, secret_key, algorithm='HS256') + + dict_param = dict( + query_status="new", + query_type="Real", + instrument="empty-async", + product_type="dummy", + token=encoded_token + ) + + # this should return status submitted, so matrix message sent + c = requests.get(os.path.join(server, "run_analysis"), + dict_param + ) + + logger.info("response from run_analysis: %s", json.dumps(c.json(), indent=4)) + jdata = c.json() + + dispatcher_job_state = DispatcherJobState.from_run_analysis_response(c.json()) + + # check the matrix_messages log in the matrix-message folders, and that the first one was produced + matrix_message_history_log_files = glob.glob( + os.path.join(dispatcher_job_state.scratch_dir, 'matrix_message_history', 'matrix_message_history_log_*.log')) + latest_file_matrix_message_history_log_file = max(matrix_message_history_log_files, key=os.path.getctime) + with open(latest_file_matrix_message_history_log_file) as matrix_message_history_log_content_fn: + history_log_content = json.loads(matrix_message_history_log_content_fn.read()) + logger.info("content matrix message history logging: %s", history_log_content) + assert history_log_content['job_id'] == dispatcher_job_state.job_id + assert isinstance(history_log_content['additional_information']['submitted_matrix_message_files'], list) + assert len(history_log_content['additional_information']['submitted_matrix_message_files']) == 0 + assert history_log_content['additional_information'][ + 'check_result_message'] == 'the message will be sent via matrix' + + time_request = jdata['time_request'] + DataServerQuery.set_status('done') + + c = requests.get(os.path.join(server, "call_back"), + params=dict( + job_id=dispatcher_job_state.job_id, + session_id=dispatcher_job_state.session_id, + instrument_name="empty-async", + action='done', + node_id='node_final', + message='done', + token=encoded_token, + time_original_request=time_request + )) + assert c.status_code == 200 + + jdata = dispatcher_job_state.load_job_state_record('node_final', 'done') + assert 'matrix_message_status' in jdata + assert jdata['matrix_message_status'] == 'sending message via matrix failed' + matrix_message_status_details_obj = json.loads(jdata['matrix_message_status_details']) + assert 'res_content' in matrix_message_status_details_obj + assert 'res_content_token_user_failure' in matrix_message_status_details_obj['res_content'] + assert matrix_message_status_details_obj['res_content']['res_content_token_user_failure'] == \ + (f"Issue in sending a message in the room {dispatcher_local_matrix_message_server.room_id} using matrix: " + f"Could not join the room: {dispatcher_local_matrix_message_server.room_id}, for the following reason: M_FORBIDDEN: You are not invited to this room.") + + @pytest.mark.test_matrix @pytest.mark.not_safe_parallel def test_matrix_message_done(gunicorn_dispatcher_long_living_fixture_with_matrix_options, From 3cc508ea89c8c32f14bf776191f029348743629c Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 2 Nov 2023 10:42:40 +0100 Subject: [PATCH 08/14] bugfix incident report if --- cdci_data_analysis/flask_app/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index d50019f05..c31cf5f20 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -1055,8 +1055,8 @@ def report_incident(): ) matrix_message_report_status = 'incident report message successfully sent via matrix' - if 'res_content_token_user_failure' in res_content or len(res_content['res_content_bcc_users_failed']) > 1: - matrix_message_report_status = 'incident report message successfully sent via matrix failed' + if len(res_content['res_content_incident_reports_failed']) > 1: + matrix_message_report_status = 'sending of an incident report message via matrix failed' report_incident_status['martix_message_report_status'] = matrix_message_report_status report_incident_status['martix_message_report_status_details'] = { From 09abefc137915fb8c7bdad0737b6b64b154f10f4 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 2 Nov 2023 10:56:51 +0100 Subject: [PATCH 09/14] removed comments --- cdci_data_analysis/flask_app/app.py | 6 ------ cdci_data_analysis/flask_app/dispatcher_query.py | 16 +--------------- 2 files changed, 1 insertion(+), 21 deletions(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index c31cf5f20..bcebafb5b 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -1062,17 +1062,11 @@ def report_incident(): report_incident_status['martix_message_report_status_details'] = { "res_content": res_content } - # except matrix_helper.MatrixMessageNotSent as e: - # report_incident_status['martix_message_report_status'] = 'sending message via matrix failed' - # logging.warning(f'message sending via matrix failed: {e}') - # sentry.capture_message(f'message sending via matrix failed {e}') except MissingRequestParameter as e: report_incident_status['martix_message_report_status'] = 'sending message via matrix failed' logging.warning(f'parameter missing during call back: {e}') - # response = jsonify({'report_incident_status': report_incident_status}) - return report_incident_status diff --git a/cdci_data_analysis/flask_app/dispatcher_query.py b/cdci_data_analysis/flask_app/dispatcher_query.py index 76cf96a07..0683f0e05 100644 --- a/cdci_data_analysis/flask_app/dispatcher_query.py +++ b/cdci_data_analysis/flask_app/dispatcher_query.py @@ -1151,7 +1151,6 @@ def run_call_back(self, status_kw_name='action') -> typing.Tuple[str, typing.Uni logging.warning(f'issue when {step}: {e}') sentry.capture_message(f'issue when {step}: {e}') - # try: if is_message_to_send: time_request = time_original_request time_request_first_submitted = matrix_helper.get_first_submitted_matrix_message_time(self.scratch_dir) @@ -1191,14 +1190,6 @@ def run_call_back(self, status_kw_name='action') -> typing.Tuple[str, typing.Uni else: job.write_dataserver_status(status_dictionary_value=status, full_dict=self.par_dic) - # except matrix_helper.MatrixMessageNotSent as e: - # job.write_dataserver_status(status_dictionary_value=status, - # full_dict=self.par_dic, - # matrix_message_status='sending message via matrix failed', - # matrix_message_status_details=e.payload) - # logging.warning(f'matrix message sending failed: {e}') - # sentry.capture_message(f'sending matrix message failed {e.message}') - try: # TODO for a future implementation # self.validate_job_id() @@ -1977,7 +1968,7 @@ def run_query(self, off_line=False, disp_conf=None): self.job_id, self.app.config['conf'], decoded_token=self.decoded_token): - # try: + time_request = self.time_request time_request_first_submitted = matrix_helper.get_first_submitted_matrix_message_time(self.scratch_dir) if time_request_first_submitted is not None: @@ -2009,11 +2000,6 @@ def run_query(self, off_line=False, disp_conf=None): query_out.set_status_field('matrix_message_status', matrix_message_status) query_out.set_status_field('matrix_message_status_details', matrix_message_status_details) - # except matrix_helper.MatrixMessageNotSent as e: - # query_out.set_status_field('matrix_message_status', 'sending matrix message failed') - # query_out.set_status_field('matrix_message_status_details', e.payload) - # logging.warning(f'matrix message sending failed: {e}') - # sentry.capture_message(f'sending matrix message failed {e.message}') if email_helper.is_email_to_send_run_query(self.logger, query_new_status, From 2a046dd6572d5c589526822ead5224e756ebeacc Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 2 Nov 2023 12:31:11 +0100 Subject: [PATCH 10/14] bugfix: number minimum failures for messages sent --- cdci_data_analysis/flask_app/app.py | 2 +- cdci_data_analysis/flask_app/dispatcher_query.py | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index bcebafb5b..73d36960b 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -1055,7 +1055,7 @@ def report_incident(): ) matrix_message_report_status = 'incident report message successfully sent via matrix' - if len(res_content['res_content_incident_reports_failed']) > 1: + if len(res_content['res_content_incident_reports_failed']) >= 1: matrix_message_report_status = 'sending of an incident report message via matrix failed' report_incident_status['martix_message_report_status'] = matrix_message_report_status diff --git a/cdci_data_analysis/flask_app/dispatcher_query.py b/cdci_data_analysis/flask_app/dispatcher_query.py index 0683f0e05..a24eb4efb 100644 --- a/cdci_data_analysis/flask_app/dispatcher_query.py +++ b/cdci_data_analysis/flask_app/dispatcher_query.py @@ -1180,7 +1180,7 @@ def run_call_back(self, status_kw_name='action') -> typing.Tuple[str, typing.Uni matrix_message_status_details['status_details'] = status_details matrix_message_status = 'matrix message sent' - if 'res_content_token_user_failure' in res_content or len(res_content['res_content_bcc_users_failed']) > 1: + if 'res_content_token_user_failure' in res_content or len(res_content['res_content_bcc_users_failed']) >= 1: matrix_message_status = 'sending message via matrix failed' job.write_dataserver_status(status_dictionary_value=status, @@ -1994,8 +1994,7 @@ def run_query(self, off_line=False, disp_conf=None): }) matrix_message_status = 'matrix message sent' - if 'res_content_token_user_failure' in res_content or len( - res_content['res_content_bcc_users_failed']) > 1: + if 'res_content_token_user_failure' in res_content or len(res_content['res_content_bcc_users_failed']) >= 1: matrix_message_status = 'sending message via matrix failed' query_out.set_status_field('matrix_message_status', matrix_message_status) From 685933d79f1ff9df6a034d1a9a84ec683e4f6ed7 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 2 Nov 2023 12:31:29 +0100 Subject: [PATCH 11/14] test incident report user not invited to the room --- cdci_data_analysis/pytest_fixtures.py | 14 +++-- tests/test_matrix_messages.py | 73 ++++++++++++++++++++++++++- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/cdci_data_analysis/pytest_fixtures.py b/cdci_data_analysis/pytest_fixtures.py index 1e46d370a..5cd5d81f9 100644 --- a/cdci_data_analysis/pytest_fixtures.py +++ b/cdci_data_analysis/pytest_fixtures.py @@ -326,8 +326,14 @@ def __init__(self, self.room_id = self.create_room() - def invite_to_room(self, user_id=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token']): - url = os.path.join(self.matrix_server_url, f'_matrix/client/v3/rooms/{self.room_id}/invite') + def invite_to_room(self, + room_id=None, + user_id=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token']): + + if room_id is None: + room_id = self.room_id + + url = os.path.join(self.matrix_server_url, f'_matrix/client/v3/rooms/{room_id}/invite') headers = { 'Authorization': ' '.join(['Bearer', self.matrix_sender_access_token]), 'Content-type': 'application/json' @@ -423,7 +429,9 @@ def get_matrix_message_record(self, room_id, event_id=None): matrix_server_url=dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_server_url'], matrix_sender_access_token=os.getenv("MATRIX_CREATOR_ACCESS_TOKEN", dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token']) ) - matrix_message_controller.invite_to_room(user_id=os.getenv("MATRIX_INVITEE_USER_ID", dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token'])) + matrix_message_controller.invite_to_room( + room_id=os.getenv("MATRIX_INCIDENT_REPORT_RECEIVER_ROOM_ID", matrix_message_controller.room_id), + user_id=os.getenv("MATRIX_INVITEE_USER_ID", dispatcher_test_conf_with_matrix_options['matrix_options']['matrix_sender_access_token'])) yield matrix_message_controller matrix_message_controller.leave_room() matrix_message_controller.forget_room() diff --git a/tests/test_matrix_messages.py b/tests/test_matrix_messages.py index 5223809c9..6f07e58db 100644 --- a/tests/test_matrix_messages.py +++ b/tests/test_matrix_messages.py @@ -1189,6 +1189,76 @@ def test_matrix_message_and_email(gunicorn_dispatcher_long_living_fixture_with_m assert jdata['email_status'] == 'email sent' +@pytest.mark.test_matrix +def test_incident_report_no_invitee(dispatcher_live_fixture_with_matrix_options, + dispatcher_test_conf_with_matrix_options, + dispatcher_local_matrix_message_server, + dispatcher_test_conf): + server = dispatcher_live_fixture_with_matrix_options + + logger.info("constructed server: %s", server) + + params = { + 'query_status': 'new', + 'product_type': 'dummy', + 'query_type': "Dummy", + 'instrument': 'empty', + } + + decoded_token = { + **default_token_payload, + "mxroomid": dispatcher_local_matrix_message_server.room_id + } + encoded_token = jwt.encode(decoded_token, secret_key, algorithm='HS256') + params['token'] = encoded_token + + + jdata = ask(server, + params, + expected_query_status=["done"], + max_time_s=150, + ) + + dispatcher_job_state = DispatcherJobState.from_run_analysis_response(jdata) + time_request = jdata['time_request'] + time_request_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(time_request))) + + scratch_dir_fn_list = glob.glob(f'scratch_sid_{dispatcher_job_state.session_id}_jid_{dispatcher_job_state.job_id}*') + scratch_dir_fn = max(scratch_dir_fn_list, key=os.path.getctime) + + incident_content = 'test incident' + + # for the email we only use the first 8 characters + c = requests.post(os.path.join(server, "report_incident"), + params=dict( + job_id=dispatcher_job_state.job_id, + session_id=dispatcher_job_state.session_id, + token=encoded_token, + incident_content=incident_content, + incident_time=time_request, + scratch_dir=scratch_dir_fn + )) + + jdata_incident_report = c.json() + + assert 'martix_message_report_status' in jdata_incident_report + assert jdata_incident_report[ + 'martix_message_report_status'] == 'sending of an incident report message via matrix failed' + assert 'martix_message_report_status_details' in jdata_incident_report + assert 'res_content' in jdata_incident_report['martix_message_report_status_details'] + assert 'res_content_incident_reports' in jdata_incident_report['martix_message_report_status_details'][ + 'res_content'] + assert len(jdata_incident_report['martix_message_report_status_details']['res_content'][ + 'res_content_incident_reports']) == 0 + assert 'res_content_incident_reports_failed' in jdata_incident_report['martix_message_report_status_details'][ + 'res_content'] + assert len(jdata_incident_report['martix_message_report_status_details']['res_content'][ + 'res_content_incident_reports_failed']) == 1 + assert jdata_incident_report['martix_message_report_status_details']['res_content'][ + 'res_content_incident_reports_failed'][0] == (f'Issue in sending a message in the room {os.getenv("MATRIX_INCIDENT_REPORT_RECEIVER_ROOM_ID", "")} ' + f'using matrix: Could not join the room: {os.getenv("MATRIX_INCIDENT_REPORT_RECEIVER_ROOM_ID", "")}, ' + f'for the following reason: M_FORBIDDEN: You are not invited to this room.') + @pytest.mark.test_matrix @pytest.mark.parametrize("request_cred", ['public', 'valid_token', 'invalid_token']) def test_incident_report(dispatcher_live_fixture_with_matrix_options, @@ -1218,8 +1288,7 @@ def test_incident_report(dispatcher_live_fixture_with_matrix_options, error_message = 'A token must be provided.' elif request_cred == 'valid_token': decoded_token = { - **default_token_payload, - "mxroomid": dispatcher_local_matrix_message_server.room_id + **default_token_payload } encoded_token = jwt.encode(decoded_token, secret_key, algorithm='HS256') params['token'] = encoded_token From 9996fb72f08ff71df160d4b05baf8cf748be1181 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 2 Nov 2023 13:32:00 +0100 Subject: [PATCH 12/14] removed unused comment and test renaming --- tests/test_matrix_messages.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/test_matrix_messages.py b/tests/test_matrix_messages.py index 6f07e58db..da191be33 100644 --- a/tests/test_matrix_messages.py +++ b/tests/test_matrix_messages.py @@ -828,8 +828,8 @@ def test_matrix_message_submitted_multiple_requests(dispatcher_live_fixture_with @pytest.mark.test_matrix @pytest.mark.not_safe_parallel -def test_matrix_message_no_invitee(gunicorn_dispatcher_long_living_fixture_with_matrix_options, - dispatcher_local_matrix_message_server): +def test_matrix_message_sender_not_invited(gunicorn_dispatcher_long_living_fixture_with_matrix_options, + dispatcher_local_matrix_message_server): DispatcherJobState.remove_scratch_folders() DataServerQuery.set_status('submitted') @@ -1190,10 +1190,10 @@ def test_matrix_message_and_email(gunicorn_dispatcher_long_living_fixture_with_m @pytest.mark.test_matrix -def test_incident_report_no_invitee(dispatcher_live_fixture_with_matrix_options, - dispatcher_test_conf_with_matrix_options, - dispatcher_local_matrix_message_server, - dispatcher_test_conf): +def test_incident_report_sender_not_invited(dispatcher_live_fixture_with_matrix_options, + dispatcher_test_conf_with_matrix_options, + dispatcher_local_matrix_message_server, + dispatcher_test_conf): server = dispatcher_live_fixture_with_matrix_options logger.info("constructed server: %s", server) @@ -1221,7 +1221,6 @@ def test_incident_report_no_invitee(dispatcher_live_fixture_with_matrix_options, dispatcher_job_state = DispatcherJobState.from_run_analysis_response(jdata) time_request = jdata['time_request'] - time_request_str = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(time_request))) scratch_dir_fn_list = glob.glob(f'scratch_sid_{dispatcher_job_state.session_id}_jid_{dispatcher_job_state.job_id}*') scratch_dir_fn = max(scratch_dir_fn_list, key=os.path.getctime) From b91d1590a9e02abcc0485ad4e01c96c3a70c6f0f Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 2 Nov 2023 17:40:05 +0100 Subject: [PATCH 13/14] use test oda_api branch --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 650d5089b..4ae1bde93 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,7 +29,7 @@ GitPython nbformat sentry-sdk pytest-sentry --e git+https://github.com/oda-hub/oda_api.git#egg=oda_api +-e git+https://github.com/oda-hub/oda_api.git@adapt-to-new-dummy-instrument#egg=oda_api MarkupSafe==2.0.1 From 61e118753b57ee7597adaa5af284886ac88095da Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 2 Nov 2023 17:41:07 +0100 Subject: [PATCH 14/14] revert erroneous push --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 4ae1bde93..650d5089b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,7 +29,7 @@ GitPython nbformat sentry-sdk pytest-sentry --e git+https://github.com/oda-hub/oda_api.git@adapt-to-new-dummy-instrument#egg=oda_api +-e git+https://github.com/oda-hub/oda_api.git#egg=oda_api MarkupSafe==2.0.1