예제 #1
0
def update_task_status(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    db_session=None,
    slack_client=None,
):
    """Updates a task based on user input."""
    action_type, external_task_id_b64 = action["actions"][0]["value"].split(
        "-")
    external_task_id = base64_decode(external_task_id_b64)

    resolve = True
    if action_type == "reopen":
        resolve = False

    # we only update the external task allowing syncing to care of propagation to dispatch
    task = task_service.get_by_resource_id(db_session=db_session,
                                           resource_id=external_task_id)

    # avoid external calls if we are already in the desired state
    if resolve and task.status == TaskStatus.resolved:
        message = "Task is already resolved."
        dispatch_slack_service.send_ephemeral_message(slack_client, channel_id,
                                                      user_id, message)
        return

    if not resolve and task.status == TaskStatus.open:
        message = "Task is already open."
        dispatch_slack_service.send_ephemeral_message(slack_client, channel_id,
                                                      user_id, message)
        return

    # we don't currently have a good way to get the correct file_id (we don't store a task <-> relationship)
    # lets try in both the incident doc and PIR doc
    drive_task_plugin = plugin_service.get_active(
        db_session=db_session,
        project_id=task.incident.project.id,
        plugin_type="task")

    try:
        file_id = task.incident.incident_document.resource_id
        drive_task_plugin.instance.update(file_id,
                                          external_task_id,
                                          resolved=resolve)
    except Exception:
        file_id = task.incident.incident_review_document.resource_id
        drive_task_plugin.instance.update(file_id,
                                          external_task_id,
                                          resolved=resolve)

    status = "resolved" if task.status == TaskStatus.open else "re-opened"
    message = f"Task successfully {status}."
    dispatch_slack_service.send_ephemeral_message(slack_client, channel_id,
                                                  user_id, message)
예제 #2
0
def create_or_update_task(db_session,
                          incident,
                          task: dict,
                          notify: bool = False,
                          sync_external: bool = True):
    """Creates a new task in the database or updates an existing one."""
    existing_task = task_service.get_by_resource_id(
        db_session=db_session, resource_id=task["resource_id"])

    if existing_task:
        # we save the existing task status before we attempt to update the record
        existing_status = existing_task.status
        task = task_service.update(
            db_session=db_session,
            task=existing_task,
            task_in=TaskUpdate(
                **task,
                incident=incident,
            ),
            sync_external=sync_external,
        )

        if notify:
            # determine if task was previously resolved
            if task.status == TaskStatus.resolved:
                if existing_status != TaskStatus.resolved:
                    send_task_notification(
                        incident,
                        INCIDENT_TASK_RESOLVED_NOTIFICATION,
                        task.creator,
                        task.assignees,
                        task.description,
                        task.weblink,
                        db_session,
                    )
    else:
        # we don't attempt to create new tasks if the incident is currently closed
        if incident.status == IncidentStatus.closed:
            return

        task = task_service.create(
            db_session=db_session,
            task_in=TaskCreate(**task, incident=incident),
        )

        if notify:
            send_task_notification(
                incident,
                INCIDENT_TASK_NEW_NOTIFICATION,
                task.creator,
                task.assignees,
                task.description,
                task.weblink,
                db_session,
            )

    db_session.commit()
예제 #3
0
파일: flows.py 프로젝트: waoywssy/dispatch
def create_or_update_task(db_session,
                          incident,
                          task: dict,
                          notify: bool = False):
    """Creates a new task in the database or updates an existing one."""
    existing_task = task_service.get_by_resource_id(
        db_session=db_session, resource_id=task["resource_id"])

    if existing_task:
        # save the status before we attempt to update the record
        existing_status = existing_task.status
        task = task_service.update(db_session=db_session,
                                   task=existing_task,
                                   task_in=TaskUpdate(**task))

        if notify:
            # determine if task was previously resolved
            if task.status == TaskStatus.resolved.value:
                if existing_status != TaskStatus.resolved.value:
                    send_task_notification(
                        incident.conversation.channel_id,
                        INCIDENT_TASK_RESOLVED_NOTIFICATION,
                        task.assignees,
                        task.description,
                        task.weblink,
                        db_session,
                    )
    else:
        task = task_service.create(
            db_session=db_session,
            incident=incident,
            task_in=TaskCreate(**task),
        )

        if notify:
            send_task_notification(
                incident.conversation.channel_id,
                INCIDENT_TASK_NEW_NOTIFICATION,
                task.assignees,
                task.description,
                task.weblink,
                db_session,
            )

    db_session.commit()
예제 #4
0
def create_or_update_task(db_session,
                          incident,
                          task: dict,
                          notify: bool = False):
    """Creates a new task in the database or updates an existing one."""
    incident_task = task_service.get_by_resource_id(db_session=db_session,
                                                    resource_id=task["id"])

    assignees = []
    for a in task["assignees"]:
        assignees.append(
            db_session.merge(
                incident_add_or_reactivate_participant_flow(
                    a, incident_id=incident.id, db_session=db_session)))

    description = task["description"][0]
    status = TaskStatus.open if not task["status"] else TaskStatus.resolved
    resource_id = task["id"]
    weblink = task["web_link"]

    # TODO we can build this out as our scraping gets more advanced
    tickets = [
        ticket_service.get_or_create_by_weblink(db_session=db_session,
                                                weblink=t["web_link"])
        for t in task["tickets"]
    ]

    if incident_task:
        # allways update tickets and assignees
        incident_task.assignees = assignees
        incident_task.tickets = tickets

        # only notify if it's newly resolved
        if status == TaskStatus.resolved:
            if incident_task.status != TaskStatus.resolved:
                incident_task.status = status

                if notify:
                    send_task_notification(
                        incident.conversation.channel_id,
                        INCIDENT_TASK_RESOLVED_NOTIFICATION,
                        assignees,
                        description,
                        weblink,
                    )

    else:
        # we add the task to the incident
        creator = db_session.merge(
            incident_add_or_reactivate_participant_flow(
                task["owner"], incident_id=incident.id, db_session=db_session))

        task = task_service.create(
            db_session=db_session,
            creator=creator,
            assignees=assignees,
            description=description,
            status=status,
            tickets=tickets,
            resource_id=resource_id,
            resource_type=INCIDENT_RESOURCE_INCIDENT_TASK,
            weblink=weblink,
        )
        incident.tasks.append(task)

        if notify:
            send_task_notification(
                incident.conversation.channel_id,
                INCIDENT_TASK_NEW_NOTIFICATION,
                assignees,
                description,
                weblink,
            )

    db_session.commit()
예제 #5
0
def create_or_update_task(db_session,
                          incident,
                          task: dict,
                          notify: bool = False):
    """Creates a new task in the database or updates an existing one."""
    # TODO we should standarize this interface (kglisson)
    creator = task["owner"]
    assignees = ", ".join(task["assignees"])
    description = task["description"][0]
    status = TaskStatus.open if not task["status"] else TaskStatus.resolved
    resource_id = task["id"]
    weblink = task["web_link"]

    incident_task = task_service.get_by_resource_id(db_session=db_session,
                                                    resource_id=task["id"])
    if incident_task:
        if status == TaskStatus.open:
            # we don't need to take any actions if the status of the task in the collaboration doc is open
            return
        else:
            if incident_task.status == TaskStatus.resolved:
                # we don't need to take any actions if the task has already been marked as resolved in the database
                return
            else:
                # we mark the task as resolved in the database
                incident_task.status = TaskStatus.resolved
                db_session.add(incident_task)
                db_session.commit()

                if notify:
                    send_task_notification(
                        incident.conversation.channel_id,
                        INCIDENT_TASK_RESOLVED_NOTIFICATION,
                        assignees,
                        description,
                        weblink,
                    )
    else:
        # we add the task to the incident
        task = task_service.create(
            db_session=db_session,
            creator=creator,
            assignees=assignees,
            description=description,
            status=status,
            resource_id=resource_id,
            resource_type=INCIDENT_RESOURCE_INCIDENT_TASK,
            weblink=weblink,
        )
        incident.tasks.append(task)
        db_session.add(incident)
        db_session.commit()

        if notify:
            send_task_notification(
                incident.conversation.channel_id,
                INCIDENT_TASK_NEW_NOTIFICATION,
                assignees,
                description,
                weblink,
            )
예제 #6
0
파일: scheduled.py 프로젝트: sibis/dispatch
def sync_tasks(db_session=None):
    """Syncs incident tasks."""
    # we get all active and stable incidents
    active_incidents = incident_service.get_all_by_status(
        db_session=db_session, status=IncidentStatus.active)
    stable_incidents = incident_service.get_all_by_status(
        db_session=db_session, status=IncidentStatus.stable)
    incidents = active_incidents + stable_incidents

    # we create an instance of the drive task plugin
    drive_task_plugin = plugins.get(INCIDENT_PLUGIN_TASK_SLUG)

    for incident in incidents:
        for doc_type in [
                INCIDENT_RESOURCE_INVESTIGATION_DOCUMENT,
                INCIDENT_RESOURCE_INCIDENT_REVIEW_DOCUMENT,
        ]:
            # we get the document object
            document = get_document(db_session=db_session,
                                    incident_id=incident.id,
                                    resource_type=doc_type)

            if not document:
                # the document may have not been created yet (e.g. incident review document)
                break

            # we get the list of tasks in the document
            tasks = drive_task_plugin.list(file_id=document.resource_id)

            for t in tasks:
                # we get the task information
                creator = t["task"]["owner"]
                assignees = ", ".join(t["task"]["assignees"])
                description = t["task"]["description"][0]
                status = TaskStatus.open if not t["task"][
                    "status"] else TaskStatus.resolved
                resource_id = t["task"]["id"]
                weblink = t["task"]["web_link"]

                incident_task = task_service.get_by_resource_id(
                    db_session=db_session, resource_id=t["task"]["id"])
                if incident_task:
                    if status == TaskStatus.open:
                        # we don't need to take any actions if the status of the task in the collaboration doc is open
                        break
                    else:
                        if incident_task.status == TaskStatus.resolved:
                            # we don't need to take any actions if the task has already been marked as resolved in the database
                            break
                        else:
                            # we mark the task as resolved in the database
                            incident_task.status = TaskStatus.resolved
                            db_session.add(incident_task)
                            db_session.commit()

                            # we send a notification to the incident conversation
                            notification_text = "Incident Notification"
                            notification_type = "incident-notification"
                            convo_plugin = plugins.get(
                                INCIDENT_PLUGIN_CONVERSATION_SLUG)
                            convo_plugin.send(
                                incident.conversation.channel_id,
                                notification_text,
                                INCIDENT_TASK_RESOLVED_NOTIFICATION,
                                notification_type,
                                task_assignees=assignees,
                                task_description=description,
                                task_weblink=weblink,
                            )
                else:
                    # we add the task to the incident
                    task = task_service.create(
                        db_session=db_session,
                        creator=creator,
                        assignees=assignees,
                        description=description,
                        status=status,
                        resource_id=resource_id,
                        resource_type=INCIDENT_RESOURCE_INCIDENT_TASK,
                        weblink=weblink,
                    )
                    incident.tasks.append(task)
                    db_session.add(incident)
                    db_session.commit()

                    # we send a notification to the incident conversation
                    notification_text = "Incident Notification"
                    notification_type = "incident-notification"
                    convo_plugin = plugins.get(
                        INCIDENT_PLUGIN_CONVERSATION_SLUG)
                    convo_plugin.send(
                        incident.conversation.channel_id,
                        notification_text,
                        INCIDENT_TASK_NEW_NOTIFICATION,
                        notification_type,
                        task_assignees=assignees,
                        task_description=description,
                        task_weblink=weblink,
                    )