From 3774928141eba4f7d4c008ae2d85c76c819a79ac Mon Sep 17 00:00:00 2001 From: DonHaul Date: Mon, 18 Nov 2024 13:55:21 +0100 Subject: [PATCH] airflow: fixing snowticket workflow * ref: cern-sis/issues-inspire/issues/614 --- .../backoffice/authors/airflow_utils.py | 11 +- backoffice/backoffice/authors/api/views.py | 8 +- .../author_create/author_create_approved.py | 111 ++++++++++-------- .../author_create/author_create_init.py | 60 ++++++---- .../author_create/author_create_rejected.py | 21 +++- .../dags/author/author_create/shared_tasks.py | 17 --- .../author/author_update/author_update.py | 57 +++++---- .../backoffice/workflow_management_hook.py | 17 +-- .../hooks/inspirehep/inspire_http_hook.py | 69 ++++++++++- workflows/plugins/include/utils/tickets.py | 12 ++ 10 files changed, 246 insertions(+), 137 deletions(-) delete mode 100644 workflows/dags/author/author_create/shared_tasks.py create mode 100644 workflows/plugins/include/utils/tickets.py diff --git a/backoffice/backoffice/authors/airflow_utils.py b/backoffice/backoffice/authors/airflow_utils.py index 80a6404ab..a4732f27d 100644 --- a/backoffice/backoffice/authors/airflow_utils.py +++ b/backoffice/backoffice/authors/airflow_utils.py @@ -5,6 +5,8 @@ from django.http import JsonResponse from requests.exceptions import RequestException from rest_framework import status +import json +from django.core.serializers.json import DjangoJSONEncoder from backoffice.authors.constants import WORKFLOW_DAGS @@ -12,12 +14,13 @@ AIRFLOW_HEADERS = { "Authorization": f"Basic {environ.get('AIRFLOW_TOKEN')}", + "Content-Type": "application/json", } logger = logging.getLogger(__name__) -def trigger_airflow_dag(dag_id, workflow_id, extra_data=None): +def trigger_airflow_dag(dag_id, workflow_id, extra_data=None, workflow=None): """Triggers an airflow dag. :param dag_id: name of the dag to run @@ -29,6 +32,8 @@ def trigger_airflow_dag(dag_id, workflow_id, extra_data=None): if extra_data is not None: data["conf"]["data"] = extra_data + if workflow is not None: + data["conf"]["workflow"] = workflow url = f"{AIRFLOW_BASE_URL}/api/v1/dags/{dag_id}/dagRuns" @@ -39,7 +44,9 @@ def trigger_airflow_dag(dag_id, workflow_id, extra_data=None): data, url, ) - response = requests.post(url, json=data, headers=AIRFLOW_HEADERS) + response = requests.post( + url, data=json.dumps(data, cls=DjangoJSONEncoder), headers=AIRFLOW_HEADERS + ) response.raise_for_status() return JsonResponse(response.json()) except RequestException: diff --git a/backoffice/backoffice/authors/api/views.py b/backoffice/backoffice/authors/api/views.py index fe81f3f85..89496ecdf 100644 --- a/backoffice/backoffice/authors/api/views.py +++ b/backoffice/backoffice/authors/api/views.py @@ -140,7 +140,7 @@ def create(self, request): airflow_utils.trigger_airflow_dag( WORKFLOW_DAGS[workflow.workflow_type].initialize, str(workflow.id), - workflow.data, + workflow=serializer.data, ) return Response(serializer.data, status=status.HTTP_201_CREATED) @@ -177,7 +177,6 @@ def resolve(self, request, pk=None): logger.info("Resolving data: %s", request.data) serializer = self.resolution_serializer(data=request.data) if serializer.is_valid(raise_exception=True): - extra_data = serializer.validated_data logger.info( "Trigger Airflow DAG: %s for %s", AuthorResolutionDags[serializer.validated_data["value"]], @@ -185,10 +184,13 @@ def resolve(self, request, pk=None): ) utils.add_decision(pk, request.user, serializer.validated_data["value"]) + workflow = self.get_serializer(AuthorWorkflow.objects.get(pk=pk)).data + airflow_utils.trigger_airflow_dag( AuthorResolutionDags[serializer.validated_data["value"]].label, pk, - extra_data, + serializer.data, + workflow=workflow, ) workflow_serializer = self.serializer_class( get_object_or_404(AuthorWorkflow, pk=pk) diff --git a/workflows/dags/author/author_create/author_create_approved.py b/workflows/dags/author/author_create/author_create_approved.py index 6509e654a..109d0e2a4 100644 --- a/workflows/dags/author/author_create/author_create_approved.py +++ b/workflows/dags/author/author_create/author_create_approved.py @@ -1,9 +1,10 @@ import datetime import logging +from airflow.utils.trigger_rule import TriggerRule +from include.utils.tickets import get_ticket_by_type from airflow.decorators import dag, task from airflow.models.param import Param -from author.author_create.shared_tasks import close_author_create_user_ticket from hooks.backoffice.workflow_management_hook import AUTHORS, WorkflowManagementHook from hooks.backoffice.workflow_ticket_management_hook import ( AuthorWorkflowTicketManagementHook, @@ -30,6 +31,7 @@ schedule=None, catchup=False, on_failure_callback=set_workflow_status_to_error, # TODO: what if callback fails? Data in backoffice not up to date! + tags=["authors"] ) def author_create_approved_dag(): """Defines the DAG for the author creation workflow after curator's approval. @@ -48,7 +50,7 @@ def author_create_approved_dag(): """ inspire_http_hook = InspireHttpHook() inspire_http_record_management_hook = InspireHTTPRecordManagementHook() - workflow_management_hook = WorkflowManagementHook() + workflow_management_hook = WorkflowManagementHook(AUTHORS) workflow_ticket_management_hook = AuthorWorkflowTicketManagementHook() @task() @@ -56,35 +58,39 @@ def set_workflow_status_to_running(**context): status_name = "running" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) @task.branch() def author_check_approval_branch(**context: dict) -> None: - """Branching for the workflow: based on create_ticket parameter + """Branching for the workflow: based on value parameter dag goes either to create_ticket_on_author_approval task or directly to create_author_on_inspire """ - if context["params"]["create_ticket"]: + if "accept_curate" == context["params"]["data"]["value"]: return "create_author_create_curation_ticket" else: - return "empty_task" + return "close_author_create_user_ticket" @task def create_author_create_curation_ticket(**context: dict) -> None: - endpoint = "api/tickets/create" - request_data = { - "functional_category": "", - "workflow_id": context["params"]["workflow_id"], - "subject": "test", # TODO: update subject and description - "description": "test", - "caller_email": "", # leave empty - "template": "curation_needed_author", # TODO: check template - } - response = inspire_http_hook.call_api( - endpoint=endpoint, data=request_data, method="POST" - ) + + workflow_data = context["params"]["workflow"]["data"] + email = workflow_data["acquisition_source"]["email"] + + bai = "[{}]".format(workflow_data.get("bai")) if workflow_data.get("bai") else "" + control_number = context["ti"].xcom_pull(task_ids="create_author_on_inspire", key="control_number") + response = inspire_http_hook.create_ticket( + "Author curation", + "curation_needed_author", + f"Curation needed for author {workflow_data.get('name').get('preferred_name')} {bai}", + email, + {"email": email, "record_url": f"{inspire_http_hook.base_url}/authors/{control_number}"}) + + + + + workflow_ticket_management_hook.create_ticket_entry( workflow_id=context["params"]["workflow_id"], ticket_id=response.json()["ticket_id"], @@ -102,13 +108,14 @@ def create_author_on_inspire(**context: dict) -> str: status = get_wf_status_from_inspire_response(response) if response.ok: control_number = response.json()["metadata"]["control_number"] + context["ti"].xcom_push(key="control_number", value=control_number) logger.info(f"Created author with control number: {control_number}") workflow_data["data"]["control_number"] = control_number workflow_management_hook.partial_update_workflow( workflow_id=context["params"]["workflow_id"], - workflow_partial_update_data={"data": workflow_data["data"]}, - collection=AUTHORS, + workflow_partial_update_data={"data": workflow_data["data"]} ) + logger.info(f"Workflow status: {status}") return status @task.branch() @@ -125,14 +132,25 @@ def set_author_create_workflow_status_to_completed(**context: dict) -> None: status_name = "completed" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) - @task - def empty_task() -> None: - # Logic to combine the results of branches - pass + @task(trigger_rule=TriggerRule.NONE_FAILED_MIN_ONE_SUCCESS) + def close_author_create_user_ticket(**context: dict) -> None: + ticket_id=get_ticket_by_type(context["params"]["workflow"],"author_create_user")["ticket_id"] + + workflow_data = context["params"]["workflow"]["data"] + email = workflow_data["acquisition_source"]["email"] + control_number = context["ti"].xcom_pull(task_ids='create_author_on_inspire', key='control_number') + + inspire_http_hook.get_backoffice_url(context["params"]["workflow_id"]) + + request_data = { + "user_name":workflow_data["acquisition_source"].get('given_names',email), + "author_name": workflow_data.get("name").get("preferred_name"), + "record_url": f"{inspire_http_hook.base_url}/authors/{control_number}" + } + inspire_http_hook.close_ticket(ticket_id,"user_accepted_author", request_data) @task() def set_author_create_workflow_status_to_error(**context: dict) -> None: @@ -142,7 +160,6 @@ def set_author_create_workflow_status_to_error(**context: dict) -> None: workflow_management_hook.set_workflow_status( status_name=status_name, workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, ) # task definitions @@ -153,36 +170,28 @@ def set_author_create_workflow_status_to_error(**context: dict) -> None: close_author_create_user_ticket_task = close_author_create_user_ticket() create_author_create_curation_ticket_task = create_author_create_curation_ticket() set_workflow_status_to_completed_task = ( - set_author_create_workflow_status_to_completed() + set_author_create_workflow_status_to_completed() ) set_workflow_status_to_error_task = set_author_create_workflow_status_to_error() - combine_ticket_and_no_ticket_task = empty_task() - # task dependencies - ticket_branch = create_author_create_curation_ticket_task - ( - ticket_branch - >> close_author_create_user_ticket_task - >> set_workflow_status_to_completed_task - ) + - no_ticket_branch = combine_ticket_and_no_ticket_task - ( - no_ticket_branch - >> close_author_create_user_ticket_task - >> set_workflow_status_to_completed_task - ) - - author_check_approval_branch_task >> [ticket_branch, no_ticket_branch] + # task dependencies ( - set_status_to_running_task - >> create_author_on_inspire_task - >> author_create_success_branch_task + set_status_to_running_task + >> create_author_on_inspire_task + >> author_create_success_branch_task ) author_create_success_branch_task >> [ - author_check_approval_branch_task, - set_workflow_status_to_error_task, + author_check_approval_branch_task, + set_workflow_status_to_error_task, ] - + ( + [author_check_approval_branch_task >> create_author_create_curation_ticket_task, + author_check_approval_branch_task, + ] + >> close_author_create_user_ticket_task + >> set_workflow_status_to_completed_task + ) author_create_approved_dag() diff --git a/workflows/dags/author/author_create/author_create_init.py b/workflows/dags/author/author_create/author_create_init.py index effa88f92..abc0a062f 100644 --- a/workflows/dags/author/author_create/author_create_init.py +++ b/workflows/dags/author/author_create/author_create_init.py @@ -1,6 +1,6 @@ import datetime import logging - +from airflow.hooks.base import BaseHook from airflow.decorators import dag, task from airflow.models import Variable from airflow.models.param import Param @@ -8,7 +8,7 @@ from hooks.backoffice.workflow_ticket_management_hook import ( AuthorWorkflowTicketManagementHook, ) -from hooks.inspirehep.inspire_http_hook import InspireHttpHook +from hooks.inspirehep.inspire_http_hook import InspireHttpHook, AUTHOR_SUBMIT_FUNCTIONAL_CATEGORY from include.utils.set_workflow_status import set_workflow_status_to_error logger = logging.getLogger(__name__) @@ -24,6 +24,7 @@ catchup=False, # TODO: what if callback fails? Data in backoffice not up to date! on_failure_callback=set_workflow_status_to_error, + tags=["authors"] ) def author_create_initialization_dag(): """ @@ -37,7 +38,7 @@ def author_create_initialization_dag(): """ inspire_http_hook = InspireHttpHook() - workflow_management_hook = WorkflowManagementHook() + workflow_management_hook = WorkflowManagementHook(AUTHORS) workflow_ticket_management_hook = AuthorWorkflowTicketManagementHook() @task() @@ -45,8 +46,7 @@ def set_workflow_status_to_running(**context): status_name = "running" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) @task() @@ -55,31 +55,42 @@ def set_schema(**context): workflow_management_hook.partial_update_workflow( workflow_id=context["params"]["workflow_id"], workflow_partial_update_data={ - "data": {**context["params"]["data"], "$schema": schema} - }, - collection=AUTHORS, + "data": {**context["params"]["workflow"]["data"], "$schema": schema} + } ) @task() def create_author_create_user_ticket(**context: dict) -> None: - endpoint = "/api/tickets/create" - request_data = { - "functional_category": "Author curation", - "template": "user_new_author", - "workflow_id": context["params"]["workflow_id"], - "subject": "test", # TODO: set the subject and description - "description": "test", - "caller_email": "", # leave empty - } - response = inspire_http_hook.call_api( - endpoint=endpoint, data=request_data, method="POST" - ) - logger.info(f"Ticket created. Response status code: {response.status_code}") - logger.info(response.json()) + + workflow_data = context["params"]["workflow"]["data"] + email = workflow_data["acquisition_source"]["email"] + + response = inspire_http_hook.create_ticket( + AUTHOR_SUBMIT_FUNCTIONAL_CATEGORY, + "curator_new_author", + f"Your suggestion to INSPIRE: author {workflow_data.get('name').get('preferred_name')}", + workflow_data["acquisition_source"]["email"], + { + "email": email, + "obj_url":inspire_http_hook.get_backoffice_url(context["params"]["workflow_id"]) + }) + + ticket_id = response.json()["ticket_id"] + + response = inspire_http_hook.reply_ticket( + ticket_id, + "user_new_author", + { + "user_name":workflow_data["acquisition_source"].get('given_names',email), + "author_name": workflow_data.get("name").get("preferred_name") + }, + email) + + workflow_ticket_management_hook.create_ticket_entry( workflow_id=context["params"]["workflow_id"], ticket_type="author_create_user", - ticket_id=response.json()["ticket_id"], + ticket_id=ticket_id, ) @task() @@ -87,8 +98,7 @@ def set_author_create_workflow_status_to_approval(**context: dict) -> None: status_name = "approval" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) # task dependencies diff --git a/workflows/dags/author/author_create/author_create_rejected.py b/workflows/dags/author/author_create/author_create_rejected.py index 9de52a1b8..adb7033ff 100644 --- a/workflows/dags/author/author_create/author_create_rejected.py +++ b/workflows/dags/author/author_create/author_create_rejected.py @@ -1,11 +1,14 @@ import datetime +import logging from airflow.decorators import dag, task from airflow.models.param import Param -from author.author_create.shared_tasks import close_author_create_user_ticket +from hooks.inspirehep.inspire_http_hook import InspireHttpHook from hooks.backoffice.workflow_management_hook import AUTHORS, WorkflowManagementHook from include.utils.set_workflow_status import set_workflow_status_to_error +from include.utils.tickets import get_ticket_by_type +logger = logging.getLogger(__name__) @dag( params={ @@ -17,6 +20,7 @@ catchup=False, # TODO: what if callback fails? Data in backoffice not up to date! on_failure_callback=set_workflow_status_to_error, + tags=["authors"] ) def author_create_rejected_dag() -> None: """ @@ -28,15 +32,15 @@ def author_create_rejected_dag() -> None: 2. set_author_create_workflow_status_to_completed: Sets the status of the author creation workflow to 'completed'. """ - workflow_management_hook = WorkflowManagementHook() + inspire_http_hook = InspireHttpHook() + workflow_management_hook = WorkflowManagementHook(AUTHORS) @task() def set_author_create_workflow_status_to_completed(**context: dict) -> None: status_name = "completed" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) @task() @@ -44,10 +48,15 @@ def set_workflow_status_to_running(**context): status_name = "running" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) + @task() + def close_author_create_user_ticket(**context: dict) -> None: + logger.info("Closing ticket for rejected author") + ticket_id=get_ticket_by_type(context["params"]["workflow"],"author_create_user")["ticket_id"] + inspire_http_hook.close_ticket(ticket_id) + # task definitions set_status_to_running_task = set_workflow_status_to_running() close_ticket_task = close_author_create_user_ticket() diff --git a/workflows/dags/author/author_create/shared_tasks.py b/workflows/dags/author/author_create/shared_tasks.py deleted file mode 100644 index 9657dd81d..000000000 --- a/workflows/dags/author/author_create/shared_tasks.py +++ /dev/null @@ -1,17 +0,0 @@ -from airflow.decorators import task -from airflow.utils.trigger_rule import TriggerRule -from hooks.backoffice.workflow_ticket_management_hook import ( - AuthorWorkflowTicketManagementHook, -) -from hooks.inspirehep.inspire_http_hook import InspireHttpHook - - -@task(trigger_rule=TriggerRule.NONE_FAILED_MIN_ONE_SUCCESS) -def close_author_create_user_ticket(**context: dict) -> None: - ticket_type = "author_create_user" - ticket_id = AuthorWorkflowTicketManagementHook().get_ticket( - workflow_id=context["params"]["workflow_id"], ticket_type=ticket_type - )["ticket_id"] - endpoint = "api/tickets/resolve" - request_data = {"ticket_id": ticket_id} - InspireHttpHook().call_api(endpoint=endpoint, data=request_data, method="POST") diff --git a/workflows/dags/author/author_update/author_update.py b/workflows/dags/author/author_update/author_update.py index 6576af941..09edf8e28 100644 --- a/workflows/dags/author/author_update/author_update.py +++ b/workflows/dags/author/author_update/author_update.py @@ -2,10 +2,9 @@ from airflow.decorators import dag, task from airflow.models.param import Param -from hooks.backoffice.workflow_management_hook import AUTHORS, WorkflowManagementHook -from hooks.backoffice.workflow_ticket_management_hook import ( - AuthorWorkflowTicketManagementHook, -) +from hooks.backoffice.workflow_management_hook import AUTHORS, WorkflowManagementHook,AuthorWorkflowTicketManagementHook + + from hooks.inspirehep.inspire_http_hook import InspireHttpHook from hooks.inspirehep.inspire_http_record_management_hook import ( InspireHTTPRecordManagementHook, @@ -25,6 +24,7 @@ }, catchup=False, on_failure_callback=set_workflow_status_to_error, # TODO: what if callback fails? Data in backoffice not up to date! + tags=["authors"] ) def author_update_dag(): """ @@ -39,7 +39,7 @@ def author_update_dag(): """ inspire_http_hook = InspireHttpHook() inspire_http_record_management_hook = InspireHTTPRecordManagementHook() - workflow_management_hook = WorkflowManagementHook() + workflow_management_hook = WorkflowManagementHook(AUTHORS) workflow_ticket_management_hook = AuthorWorkflowTicketManagementHook() @task() @@ -47,29 +47,40 @@ def set_author_update_workflow_status_to_running(**context): status_name = "running" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) @task() def create_ticket_on_author_update(**context): - endpoint = "/api/tickets/create" - request_data = { - "functional_category": "Author updates", - "template": "curator_update_author", - "workflow_id": context["params"]["workflow_id"], - "subject": "test", - "description": "test", - "caller_email": "", + + + workflow_data = context["params"]["workflow"]["data"] + email = workflow_data["acquisition_source"]["email"] + + subject = f"Update to author {workflow_data.get("name").get("preferred_name")} on INSPIRE" + recid = workflow_data['control_number'] + template_context = { + "url":f"{inspire_http_hook.get_url()}/{"authors"}/{recid}", + "bibedit_url":f"{inspire_http_hook.get_url()}/record/{recid}", + "url_author_form":f"{inspire_http_hook.get_url()}/submissions/authors/{recid}" } - response = inspire_http_hook.call_api( - endpoint=endpoint, data=request_data, method="POST" - ) + + response = inspire_http_hook.create_ticket( + "Author updates", + "curator_update_author", + subject, + email, + template_context) + + ticket_id = response.json()["ticket_id"] + workflow_ticket_management_hook.create_ticket_entry( workflow_id=context["params"]["workflow_id"], - ticket_type="author_update_curation", - ticket_id=response.json()["ticket_id"], + ticket_type="author_update_user", + ticket_id=ticket_id, ) + + return response.json() @task() def update_author_on_inspire(**context): @@ -95,8 +106,7 @@ def set_author_update_workflow_status_to_completed(**context): status_name = "completed" workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) @task.branch() @@ -115,8 +125,7 @@ def set_author_update_workflow_status_to_error(**context): status_name = ti.xcom_pull(task_ids="update_author_on_inspire") workflow_management_hook.set_workflow_status( status_name=status_name, - workflow_id=context["params"]["workflow_id"], - collection=AUTHORS, + workflow_id=context["params"]["workflow_id"] ) # task definitions diff --git a/workflows/plugins/hooks/backoffice/workflow_management_hook.py b/workflows/plugins/hooks/backoffice/workflow_management_hook.py index 7df0c7209..d6bd87223 100644 --- a/workflows/plugins/hooks/backoffice/workflow_management_hook.py +++ b/workflows/plugins/hooks/backoffice/workflow_management_hook.py @@ -16,8 +16,12 @@ class WorkflowManagementHook(BackofficeHook): :type http_conn_id: str """ + def __init__(self,collection): + super().__init__() + self.collection = collection + def set_workflow_status( - self, status_name: str, workflow_id: str, collection: str + self, status_name: str, workflow_id: str ) -> Response: """ Updates the status of a workflow in the backoffice system. @@ -33,12 +37,11 @@ def set_workflow_status( } return self.partial_update_workflow( workflow_partial_update_data=request_data, - workflow_id=workflow_id, - collection=collection, + workflow_id=workflow_id ) def get_workflow(self, workflow_id: str) -> dict: - endpoint = f"api/workflows/{workflow_id}" + endpoint = f"api/workflows/{self.collection}/{workflow_id}" response = self.run_with_advanced_retry( _retry_args=self.tenacity_retry_kwargs, method="GET", endpoint=endpoint ) @@ -46,7 +49,7 @@ def get_workflow(self, workflow_id: str) -> dict: return response.json() def update_workflow(self, workflow_id: str, workflow_data: dict) -> Response: - endpoint = f"api/workflows/{workflow_id}/" + endpoint = f"api/workflows/{self.collection}/{workflow_id}/" return self.run_with_advanced_retry( _retry_args=self.tenacity_retry_kwargs, method="PUT", @@ -55,9 +58,9 @@ def update_workflow(self, workflow_id: str, workflow_data: dict) -> Response: ) def partial_update_workflow( - self, workflow_id: str, workflow_partial_update_data: dict, collection: str + self, workflow_id: str, workflow_partial_update_data: dict ) -> Response: - endpoint = f"api/workflows/{collection}/{workflow_id}/" + endpoint = f"api/workflows/{self.collection}/{workflow_id}/" return self.run_with_advanced_retry( _retry_args=self.tenacity_retry_kwargs, method="PATCH", diff --git a/workflows/plugins/hooks/inspirehep/inspire_http_hook.py b/workflows/plugins/hooks/inspirehep/inspire_http_hook.py index 15b93fd9f..765b2b01c 100644 --- a/workflows/plugins/hooks/inspirehep/inspire_http_hook.py +++ b/workflows/plugins/hooks/inspirehep/inspire_http_hook.py @@ -9,6 +9,11 @@ logger = logging.getLogger() +AUTHOR_SUBMIT_FUNCTIONAL_CATEGORY = "Author submissions" +AUTHOR_CURATION_FUNCTIONAL_CATEGORY = "Author curation" +AUTHOR_UPDATE_FUNCTIONAL_CATEGORY = "Author updates" + + class InspireHttpHook(HttpHook): """ Hook to interact with Inspire API @@ -54,11 +59,71 @@ def run( self.log.info("Sending '%s' to url: %s", method, url) return self.run_and_check(session, prepped_request, extra_options) - def call_api(self, method: str, endpoint: str, data: dict) -> Response: + def call_api(self, method: str, endpoint: str, data:dict) -> Response: return self.run_with_advanced_retry( _retry_args=self.tenacity_retry_kwargs, endpoint=endpoint, headers=self.headers, - data=data, + json=data, method=method, ) + + def get_backoffice_url(self, workflow_id: str) -> str: + self.get_conn() + return f"{self.base_url}/backoffice/{workflow_id}" + + def get_url(self) -> str: + self.get_conn() + return self.base_url + + def create_ticket(self,functional_category, template_name, subject,email, template_context): + # TODO add docstring + endpoint = "/api/tickets/create" + + request_data = { + "functional_category": functional_category, + "template": template_name, + "subject": subject, + "template_context":template_context, + "caller_email": email + } + + return self.call_api( + endpoint=endpoint, data=request_data, method="POST" + ) + + def reply_ticket(self,ticket_id, template, template_context,email): + # TODO add docstring + endpoint = "/api/tickets/reply" + + request_data = { + "ticket_id": str(ticket_id), + "template": template, + "template_context": template_context, + "user_email": email + } + logging.info(f"Replying to ticket {ticket_id}") + + return self.call_api( + endpoint=endpoint, data=request_data, method="POST" + ) + + def close_ticket(self,ticket_id, template=None, template_context=None): + # TODO add docstring + endpoint = "/api/tickets/resolve" + + request_data = { + "ticket_id": str(ticket_id) + } + if template is not None: + request_data.update({ + "template": template, + "template_context": template_context, + }) + + logging.info(f"Closing ticket {ticket_id}") + print(request_data) + + return self.call_api( + endpoint=endpoint, data=request_data, method="POST" + ) diff --git a/workflows/plugins/include/utils/tickets.py b/workflows/plugins/include/utils/tickets.py new file mode 100644 index 000000000..0d963a6e7 --- /dev/null +++ b/workflows/plugins/include/utils/tickets.py @@ -0,0 +1,12 @@ +import logging + +from hooks.backoffice.workflow_management_hook import AUTHORS, WorkflowManagementHook +from requests import Response + +logger = logging.getLogger(__name__) + + +def get_ticket_by_type(workflow,ticket_type): + for ticket in workflow["tickets"]: + if ticket["ticket_type"] == ticket_type: + return ticket