Exemple #1
0
def create_tactical_report(user_id: str,
                           user_email: str,
                           incident_id: int,
                           action: dict,
                           db_session=None):
    """Creates and sends a new tactical report to a conversation."""
    conditions = action["submission"]["conditions"]
    actions = action["submission"]["actions"]
    needs = action["submission"]["needs"]

    # we load the incident instance
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # we create a new tactical report
    details = {"conditions": conditions, "actions": actions, "needs": needs}
    tactical_report_in = ReportCreate(details=details,
                                      type=ReportTypes.tactical_report)
    tactical_report = create(db_session=db_session,
                             report_in=tactical_report_in)

    # we load the participant
    participant = participant_service.get_by_incident_id_and_email(
        db_session=db_session, incident_id=incident_id, email=user_email)

    # we save the tactical report
    participant.reports.append(tactical_report)
    incident.reports.append(tactical_report)

    db_session.add(participant)
    db_session.add(incident)
    db_session.commit()

    event_service.log(
        db_session=db_session,
        source="Incident Participant",
        description=
        f"{participant.individual.name} created a new tactical report",
        details={
            "conditions": conditions,
            "actions": actions,
            "needs": needs
        },
        incident_id=incident_id,
        individual_id=participant.individual.id,
    )

    # we send the tactical report to the conversation
    send_tactical_report_to_conversation(incident_id, conditions, actions,
                                         needs, db_session)

    return tactical_report
Exemple #2
0
def send_welcome_ephemeral_message_to_participant(
    participant_email: str, incident_id: int, db_session: SessionLocal
):
    """Sends an ephemeral message to the participant."""
    # we load the incident instance
    plugin = plugin_service.get_active(db_session=db_session, plugin_type="conversation")
    if not plugin:
        log.warning("Incident welcome message not sent, not conversation plugin enabled.")
        return

    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    # we send the ephemeral message
    message_kwargs = {
        "name": incident.name,
        "title": incident.title,
        "status": incident.status,
        "type": incident.incident_type.name,
        "type_description": incident.incident_type.description,
        "priority": incident.incident_priority.name,
        "priority_description": incident.incident_priority.description,
        "commander_fullname": incident.commander.individual.name,
        "commander_weblink": incident.commander.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session
    )
    if conversation_reference:
        message_kwargs.update(
            {"conversation_commands_reference_document_weblink": conversation_reference.weblink}
        )

    plugin.instance.send_ephemeral(
        incident.conversation.channel_id,
        participant_email,
        "Incident Welcome Message",
        INCIDENT_PARTICIPANT_WELCOME_MESSAGE,
        MessageType.incident_participant_welcome,
        **message_kwargs,
    )

    log.debug(f"Welcome ephemeral message sent to {participant_email}.")
Exemple #3
0
def create(*, db_session, feedback_in: FeedbackCreate) -> Feedback:
    """Creates a new piece of feedback."""
    incident = incident_service.get(
        db_session=db_session,
        incident_id=feedback_in.incident.id,
    )
    feedback = Feedback(
        **feedback_in.dict(exclude={"incident"}),
        incident=incident,
    )
    db_session.add(feedback)
    db_session.commit()
    return feedback
Exemple #4
0
def incident_active_flow(incident_id: int,
                         command: Optional[dict] = None,
                         db_session=None):
    """Runs the incident active flow."""
    # we load the incident instance
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # we remind the incident commander to write a tactical report
    send_incident_report_reminder(incident, ReportTypes.tactical_report)

    # we update the status of the external ticket
    update_external_incident_ticket(incident, db_session)
Exemple #5
0
def add_user_to_conversation(user_email: str,
                             incident_id: int,
                             action: dict,
                             db_session=None):
    """Adds a user to a conversation."""
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    user_id = dispatch_slack_service.resolve_user(slack_client,
                                                  user_email)["id"]

    dispatch_slack_service.add_users_to_conversation(
        slack_client, incident.conversation.channel_id, user_id)
Exemple #6
0
 def has_required_permissions(
     self,
     request: Request,
 ) -> bool:
     current_incident = incident_service.get(
         db_session=request.state.db, incident_id=request.path_params.id)
     if current_incident.visibility == Visibility.restricted:
         return any(
             AdminPermission(request=request),
             IncidentCommanderPermission(request=request),
             IncidentReporterPermission(request=request),
         )
     return True
Exemple #7
0
def get_or_create(
    *,
    db_session,
    incident_id: int,
    individual_id: int,
    service_id: int,
    participant_roles: List[ParticipantRoleCreate],
) -> Participant:
    """Gets an existing participant object or creates a new one."""
    participant = (db_session.query(Participant).filter(
        Participant.incident_id == incident_id).filter(
            Participant.individual_contact_id == individual_id).one_or_none())

    if not participant:
        incident = incident_service.get(db_session=db_session,
                                        incident_id=incident_id)

        # We get information about the individual
        individual_contact = individual_service.get(
            db_session=db_session, individual_contact_id=individual_id)

        individual_info = {}
        contact_plugin = plugin_service.get_active_instance(
            db_session=db_session,
            project_id=incident.project.id,
            plugin_type="contact")
        if contact_plugin:
            individual_info = contact_plugin.instance.get(
                individual_contact.email, db_session=db_session)

        location = individual_info.get("location", "Unknown")
        team = individual_info.get("team", "Unknown")
        department = individual_info.get("department", "Unknown")

        participant_in = ParticipantCreate(
            participant_roles=participant_roles,
            team=team,
            department=department,
            location=location,
        )

        if service_id:
            participant_in.service = {"id": service_id}

        participant = create(db_session=db_session,
                             participant_in=participant_in)
    else:
        participant.participant_roles += participant_roles
        participant.service_id = service_id

    return participant
Exemple #8
0
def run_workflow_submitted_form(action: dict, db_session=None):
    """Runs an external flow."""
    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    params = {}
    named_params = []
    for i in parsed_form_data.keys():
        if i.startswith(RunWorkflowBlockFields.param):
            key = i.split("-")[1]
            value = parsed_form_data[i]
            params.update({key: value})
            named_params.append({"key": key, "value": value})

    workflow_id = parsed_form_data.get(
        RunWorkflowBlockFields.workflow_select)["value"]
    incident_id = action["view"]["private_metadata"]["incident_id"]
    run_reason = parsed_form_data.get(RunWorkflowBlockFields.run_reason)
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)
    workflow = workflow_service.get(db_session=db_session,
                                    workflow_id=workflow_id)

    creator_email = get_user_email(slack_client, action["user"]["id"])

    instance = workflow_service.create_instance(
        db_session=db_session,
        instance_in=WorkflowInstanceCreate(
            workflow={"id": workflow.id},
            incident={"id": incident.id},
            creator={"email": creator_email},
            run_reason=run_reason,
            parameters=named_params,
        ),
    )
    params.update({
        "incident_id": incident.id,
        "incident_name": incident.name,
        "instance_id": instance.id
    })

    workflow.plugin.instance.run(workflow.resource_id, params)

    send_workflow_notification(
        incident.conversation.channel_id,
        INCIDENT_WORKFLOW_CREATED_NOTIFICATION,
        db_session,
        instance_creator_name=instance.creator.individual.name,
        workflow_name=instance.workflow.name,
        workflow_description=instance.workflow.description,
    )
Exemple #9
0
def after_hours(user_email: str, incident_id: int, db_session=None):
    """Notifies the user that this incident is current in after hours mode."""
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    user_id = dispatch_slack_service.resolve_user(slack_client,
                                                  user_email)["id"]

    # NOTE Limitations: Does not sync across instances. Does not survive webserver restart
    cache_key = create_cache_key(user_id, incident.conversation.channel_id)
    try:
        once_a_day_cache[cache_key]
        return
    except Exception:
        pass  # we don't care if there is nothing here

    # bail early if we don't care for a given severity
    priority_types = [
        IncidentPriorityType.info,
        IncidentPriorityType.low,
        IncidentPriorityType.medium,
    ]
    if incident.incident_priority.name.lower() not in priority_types:
        return

    # get their timezone from slack
    commander_info = dispatch_slack_service.get_user_info_by_email(
        slack_client, email=incident.commander.email)

    commander_tz = commander_info["tz"]

    if not is_business_hours(commander_tz):
        # send ephermal message
        blocks = [{
            "type": "section",
            "text": {
                "type":
                "mrkdwn",
                "text":
                ((f"Responses may be delayed. The current incident severity is *{incident.incident_severity.name}*"
                  f" and your message was sent outside of the incident commander's working hours (Weekdays, 9am-5pm, {commander_tz})."
                  )),
            },
        }]
        dispatch_slack_service.send_ephemeral_message(
            slack_client,
            incident.conversation.channel_id,
            user_id,
            "",
            blocks=blocks)
        once_a_day_cache[cache_key] = True
Exemple #10
0
def create_update_participant_modal(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    command: dict,
    db_session=None,
    slack_client=None,
):
    """Creates a modal for updating a participant."""
    trigger_id = command["trigger_id"]
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)
    modal_create_template = update_participant(incident=incident)
    open_modal_with_user(client=slack_client, trigger_id=trigger_id, modal=modal_create_template)
Exemple #11
0
def send_incident_resources_ephemeral_message_to_participant(
    user_id: str, incident_id: int, db_session: SessionLocal
):
    """Sends the list of incident resources to the participant via an ephemeral message."""
    # we load the incident instance
    plugin = plugin_service.get_active(db_session=db_session, plugin_type="conversation")
    if not plugin:
        log.warning("Incident resource message not sent, no conversation plugin enabled.")
        return

    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    message_kwargs = {
        "commander_fullname": incident.commander.individual.name,
        "commander_weblink": incident.commander.individual.weblink,
        "document_weblink": resolve_attr(incident, "incident_document.weblink"),
        "storage_weblink": resolve_attr(incident, "storage.weblink"),
        "ticket_weblink": resolve_attr(incident, "ticket.weblink"),
        "conference_weblink": resolve_attr(incident, "conference.weblink"),
        "conference_challenge": resolve_attr(incident, "conference.conference_challenge"),
    }

    if incident.incident_review_document:
        message_kwargs.update(
            {"review_document_weblink": incident.incident_review_document.weblink}
        )

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session
    )
    if conversation_reference:
        message_kwargs.update(
            {"conversation_commands_reference_document_weblink": conversation_reference.weblink}
        )

    # we send the ephemeral message
    plugin.instance.send_ephemeral(
        incident.conversation.channel_id,
        user_id,
        "Incident Resources Message",
        INCIDENT_RESOURCES_MESSAGE,
        MessageType.incident_resources_message,
        **message_kwargs,
    )

    log.debug(f"List of incident resources sent to {user_id} via ephemeral message.")
Exemple #12
0
def send_welcome_ephemeral_message_to_participant(participant_email: str,
                                                  incident_id: int,
                                                  db_session: SessionLocal):
    """Sends an ephemeral message to the participant."""
    # we load the incident instance
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # we send the ephemeral message
    convo_plugin = plugins.get(INCIDENT_PLUGIN_CONVERSATION_SLUG)

    message_kwargs = {
        "name": incident.name,
        "title": incident.title,
        "status": incident.status,
        "type": incident.incident_type.name,
        "type_description": incident.incident_type.description,
        "priority": incident.incident_priority.name,
        "priority_description": incident.incident_priority.description,
        "commander_fullname": incident.commander.name,
        "commander_weblink": incident.commander.weblink,
        "document_weblink": incident.incident_document.weblink,
        "storage_weblink": incident.storage.weblink,
        "ticket_weblink": incident.ticket.weblink,
        "conference_weblink": incident.conference.weblink,
        "conference_challenge": incident.conference.conference_challenge,
    }

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session)
    if conversation_reference:
        message_kwargs.update({
            "conversation_commands_reference_document_weblink":
            conversation_reference.weblink
        })

    convo_plugin.send_ephemeral(
        incident.conversation.channel_id,
        participant_email,
        "Incident Welcome Message",
        INCIDENT_PARTICIPANT_WELCOME_MESSAGE,
        MessageType.incident_participant_welcome,
        **message_kwargs,
    )

    log.debug(f"Welcome ephemeral message sent to {participant_email}.")
Exemple #13
0
def create_add_timeline_event_modal(incident_id: int,
                                    command: dict,
                                    db_session=None):
    """Creates a modal for adding events to the incident timeline."""
    trigger_id = command["trigger_id"]

    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    modal_create_template = build_add_timeline_event_blocks(incident=incident)

    dispatch_slack_service.open_modal_with_user(client=slack_client,
                                                trigger_id=trigger_id,
                                                modal=modal_create_template)
Exemple #14
0
def create_update_participant_modal(incident_id: int,
                                    command: dict,
                                    db_session=None):
    """Creates a modal for updating a participant."""
    trigger_id = command["trigger_id"]

    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    modal_create_template = build_update_participant_blocks(incident=incident)

    dispatch_slack_service.open_modal_with_user(client=slack_client,
                                                trigger_id=trigger_id,
                                                modal=modal_create_template)
Exemple #15
0
def create_add_timeline_event_modal(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    command: dict,
    db_session=None,
    slack_client=None,
):
    """Creates a modal for adding events to the incident timeline."""
    trigger_id = command["trigger_id"]
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)
    modal_create_template = add_timeline_event(incident=incident)
    open_modal_with_user(client=slack_client, trigger_id=trigger_id, modal=modal_create_template)
Exemple #16
0
    def has_required_permissions(
        self,
        request: Request,
    ) -> bool:
        current_user = get_current_user(db_session=request.state.db,
                                        request=request)
        current_incident = incident_service.get(
            db_session=request.state.db,
            incident_id=request.path_params["incident_id"])
        if not current_incident:
            return False

        if current_incident.commander.individual.email == current_user.email:
            return True
Exemple #17
0
def send_welcome_email_to_participant(participant_email: str, incident_id: int,
                                      db_session: SessionLocal):
    """Sends a welcome email to the participant."""
    # we load the incident instance
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # we get the incident documents
    incident_document = get_document(
        db_session=db_session,
        incident_id=incident_id,
        resource_type=INCIDENT_RESOURCE_INVESTIGATION_DOCUMENT,
    )

    incident_faq = get_document(db_session=db_session,
                                incident_id=incident_id,
                                resource_type=INCIDENT_RESOURCE_FAQ_DOCUMENT)

    incident_conversation_commands_reference_document = get_document(
        db_session=db_session,
        incident_id=incident_id,
        resource_type=
        INCIDENT_RESOURCE_CONVERSATION_COMMANDS_REFERENCE_DOCUMENT,
    )

    email_plugin = plugins.get(INCIDENT_PLUGIN_EMAIL_SLUG)
    email_plugin.send(
        participant_email,
        INCIDENT_PARTICIPANT_WELCOME_MESSAGE,
        MessageType.incident_participant_welcome,
        name=incident.name,
        title=incident.title,
        status=incident.status,
        type=incident.incident_type.name,
        type_description=incident.incident_type.description,
        priority=incident.incident_priority.name,
        priority_description=incident.incident_priority.description,
        commander_fullname=incident.commander.name,
        commander_weblink=incident.commander.weblink,
        document_weblink=incident_document.weblink,
        storage_weblink=incident.storage.weblink,
        ticket_weblink=incident.ticket.weblink,
        faq_weblink=incident_faq.weblink,
        conference_weblink=incident.conference.weblink,
        conference_challenge=incident.conference.conference_challenge,
        conversation_commands_reference_document_weblink=
        incident_conversation_commands_reference_document.weblink,
    )

    log.debug(f"Welcome email sent to {participant_email}.")
Exemple #18
0
def handle_reaction_added_event(
    config: SlackConversationConfiguration,
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    event: EventEnvelope = None,
    db_session=None,
    slack_client=None,
):
    """Handles an event where a reaction is added to a message."""
    reaction = event.event.reaction

    if reaction == config.timeline_event_reaction:
        conversation_id = event.event.item.channel
        message_ts = event.event.item.ts
        message_ts_utc = datetime.datetime.utcfromtimestamp(float(message_ts))

        # we fetch the message information
        response = dispatch_slack_service.list_conversation_messages(
            slack_client,
            conversation_id,
            latest=message_ts,
            limit=1,
            inclusive=1)
        message_text = response["messages"][0]["text"]
        message_sender_id = response["messages"][0]["user"]

        # we fetch the incident
        incident = incident_service.get(db_session=db_session,
                                        incident_id=incident_id)

        # we fetch the individual who sent the message
        message_sender_email = get_user_email(client=slack_client,
                                              user_id=message_sender_id)
        individual = individual_service.get_by_email_and_project(
            db_session=db_session,
            email=message_sender_email,
            project_id=incident.project.id)

        # we log the event
        event_service.log(
            db_session=db_session,
            source="Slack Plugin - Conversation Management",
            description=f'"{message_text}," said {individual.name}',
            incident_id=incident_id,
            individual_id=individual.id,
            started_at=message_ts_utc,
        )
Exemple #19
0
def after_hours(
    config: SlackConversationConfiguration,
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    event: EventEnvelope = None,
    db_session=None,
    slack_client=None,
):
    """Notifies the user that this incident is current in after hours mode."""
    # we ignore user channel and group join messages
    if event.event.subtype in ["channel_join", "group_join"]:
        return

    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # get their timezone from slack
    commander_info = dispatch_slack_service.get_user_info_by_email(
        slack_client, email=incident.commander.individual.email)

    commander_tz = commander_info["tz"]

    if not is_business_hours(commander_tz):
        # send ephermal message
        blocks = [{
            "type": "section",
            "text": {
                "type":
                "mrkdwn",
                "text":
                ((f"Responses may be delayed. The current incident priority is *{incident.incident_priority.name}*"
                  f" and your message was sent outside of the Incident Commander's working hours (Weekdays, 9am-5pm, {commander_tz} timezone)."
                  )),
            },
        }]

        participant = participant_service.get_by_incident_id_and_email(
            db_session=db_session, incident_id=incident_id, email=user_email)
        if not participant.after_hours_notification:
            dispatch_slack_service.send_ephemeral_message(slack_client,
                                                          channel_id,
                                                          user_id,
                                                          "",
                                                          blocks=blocks)
            participant.after_hours_notification = True
            db_session.add(participant)
            db_session.commit()
Exemple #20
0
def create_update_notifications_group_modal(incident_id: int,
                                            command: dict,
                                            db_session=None):
    """Creates a modal for editing members of the notifications group."""
    trigger_id = command["trigger_id"]

    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    modal_create_template = build_update_notifications_group_blocks(
        incident=incident, db_session=db_session)

    dispatch_slack_service.open_modal_with_user(client=slack_client,
                                                trigger_id=trigger_id,
                                                modal=modal_create_template)
Exemple #21
0
def add_user_to_conversation(
    user_id: str, user_email: str, incident_id: int, action: dict, db_session=None
):
    """Adds a user to a conversation."""
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    if incident.status == IncidentStatus.closed:
        message = f"Sorry, we cannot add you to a closed incident. Please reach out to the incident commander ({incident.commander.name}) for details."
        dispatch_slack_service.send_ephemeral_message(
            slack_client, action["container"]["channel_id"], user_id, message
        )
    else:
        dispatch_slack_service.add_users_to_conversation(
            slack_client, incident.conversation.channel_id, [user_id]
        )
Exemple #22
0
def list_workflows(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    command: dict = None,
    db_session=None,
    slack_client=None,
):
    """Returns the list of incident workflows to the user as an ephemeral message."""
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    blocks = []
    blocks.append({
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "*Incident Workflows*"
        }
    })
    for w in incident.workflow_instances:
        artifact_links = ""
        for a in w.artifacts:
            artifact_links += f"- <{a.weblink}|{a.name}> \n"

        blocks.append({
            "type": "section",
            "text": {
                "type":
                "mrkdwn",
                "text": (f"*Name:* <{w.weblink}|{w.workflow.name}>\n"
                         f"*Workflow Description:* {w.workflow.description}\n"
                         f"*Run Reason:* {w.run_reason}\n"
                         f"*Creator:* {w.creator.individual.name}\n"
                         f"*Status:* {w.status}\n"
                         f"*Artifacts:* \n {artifact_links}"),
            },
        })
        blocks.append({"type": "divider"})

    dispatch_slack_service.send_ephemeral_message(
        slack_client,
        channel_id,
        user_id,
        "Incident Workflow List",
        blocks=blocks,
    )
Exemple #23
0
def send_incident_resources_ephemeral_message_to_participant(
        user_id: str, incident_id: int, db_session: SessionLocal):
    """Sends the list of incident resources to the participant via an ephemeral message."""
    # we load the incident instance
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    message_kwargs = {
        "commander_fullname": incident.commander.name,
        "commander_weblink": incident.commander.weblink,
        "document_weblink": incident.incident_document.weblink,
        "storage_weblink": incident.storage.weblink,
        "ticket_weblink": incident.ticket.weblink,
        "conference_weblink": incident.conference.weblink,
        "conference_challenge": incident.conference.conference_challenge,
    }

    if incident.incident_review_document:
        message_kwargs.update({
            "review_document_weblink":
            incident.incident_review_document.weblink
        })

    faq_doc = document_service.get_incident_faq_document(db_session=db_session)
    if faq_doc:
        message_kwargs.update({"faq_weblink": faq_doc.weblink})

    conversation_reference = document_service.get_conversation_reference_document(
        db_session=db_session)
    if conversation_reference:
        message_kwargs.update({
            "conversation_commands_reference_document_weblink":
            conversation_reference.weblink
        })

    # we send the ephemeral message
    convo_plugin = plugins.get(INCIDENT_PLUGIN_CONVERSATION_SLUG)
    convo_plugin.send_ephemeral(
        incident.conversation.channel_id,
        user_id,
        "Incident Resources Message",
        INCIDENT_RESOURCES_MESSAGE,
        MessageType.incident_resources_message,
        **message_kwargs,
    )

    log.debug(
        f"List of incident resources sent to {user_id} via ephemeral message.")
Exemple #24
0
def reactivate_participant(user_email: str, incident_id: int,
                           db_session: SessionLocal):
    """Reactivates a participant."""
    # We load the incident
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # We get information about the individual
    contact_plugin = plugin_service.get_active(db_session=db_session,
                                               plugin_type="contact")
    individual_info = contact_plugin.instance.get(user_email)
    individual_fullname = individual_info["fullname"]

    log.debug(
        f"Reactivating {individual_fullname} on incident {incident.name}...")

    participant = get_by_incident_id_and_email(db_session=db_session,
                                               incident_id=incident_id,
                                               email=user_email)

    if not participant:
        log.debug(
            f"{individual_fullname} is not an inactive participant of incident {incident.name}."
        )
        return False

    # We mark the participant as active
    participant.is_active = True

    # We create a role for the participant
    participant_role_in = ParticipantRoleCreate(
        role=ParticipantRoleType.participant)
    participant_role = participant_role_service.create(
        db_session=db_session, participant_role_in=participant_role_in)
    participant.participant_roles.append(participant_role)

    # We add and commit the changes
    db_session.add(participant)
    db_session.commit()

    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description=f"{individual_fullname} reactivated",
        incident_id=incident_id,
    )

    return True
Exemple #25
0
def add_participant(
    user_email: str,
    incident_id: id,
    db_session: SessionLocal,
    service: Service = None,
    role: ParticipantRoleType = None,
):
    """Adds a participant."""
    # We load the incident
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # We get or create a new individual
    individual = individual_service.get_or_create(db_session=db_session,
                                                  email=user_email)

    # We create a role for the participant
    participant_role_in = ParticipantRoleCreate(role=role)

    participant_role = participant_role_service.create(
        db_session=db_session, participant_role_in=participant_role_in)

    # We get or create a new participant
    participant = get_or_create(
        db_session=db_session,
        incident_id=incident.id,
        individual_id=individual.id,
        service=service,
        participant_roles=[participant_role],
    )

    individual.participant.append(participant)
    incident.participants.append(participant)

    # We add and commit the changes
    db_session.add(individual)
    db_session.add(incident)
    db_session.commit()

    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description=
        f"{individual.name} added to incident with {participant_role.role} role",
        incident_id=incident_id,
    )

    return participant
Exemple #26
0
def remove_participant(user_email: str, incident_id: int,
                       db_session: SessionLocal):
    """Removes a participant."""
    # We load the incident
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # We get information about the individual
    contact_plugin = plugin_service.get_active(db_session=db_session,
                                               plugin_type="contact")
    individual_info = contact_plugin.instance.get(user_email)
    individual_fullname = individual_info["fullname"]

    log.debug(
        f"Removing {individual_fullname} from incident {incident.name}...")

    participant = get_by_incident_id_and_email(db_session=db_session,
                                               incident_id=incident_id,
                                               email=user_email)

    if not participant:
        log.debug(
            f"Can't remove {individual_fullname}. They're not an active participant of incident {incident.name}."
        )
        return False

    # We mark the participant as inactive
    participant.is_active = False

    # We make the participant renounce to their active roles
    participant_active_roles = participant_role_service.get_all_active_roles(
        db_session=db_session, participant_id=participant.id)
    for participant_active_role in participant_active_roles:
        participant_role_service.renounce_role(
            db_session=db_session, participant_role=participant_active_role)

    # We add and commit the changes
    db_session.add(participant)
    db_session.commit()

    event_service.log(
        db_session=db_session,
        source="Dispatch Core App",
        description=f"{participant.individual.name} removed from incident",
        incident_id=incident_id,
    )

    return True
Exemple #27
0
def incident_remove_participant_flow(
    user_email: str, incident_id: int, event: dict = None, db_session=None
):
    """Runs the remove participant flow."""
    # we load the incident instance
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    if user_email == incident.commander.email:
        # we add the incident commander to the conversation again
        add_participant_to_conversation(user_email, incident_id, db_session)

        # we send a notification to the channel
        send_incident_commander_readded_notification(incident_id, db_session)
    else:
        # we remove the participant from the incident
        participant_flows.remove_participant(user_email, incident_id, db_session)
Exemple #28
0
def create_rating_feedback_modal(user_id: str,
                                 user_email: str,
                                 incident_id: int,
                                 action: dict,
                                 db_session=None):
    """Creates a modal for rating and providing feedback about an incident."""
    trigger_id = action["trigger_id"]

    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    modal_create_template = build_rating_feedback_blocks(incident=incident)

    dispatch_slack_service.open_modal_with_user(client=slack_client,
                                                trigger_id=trigger_id,
                                                modal=modal_create_template)
Exemple #29
0
def incident_create_closed_flow(*, incident_id: int, checkpoint: str = None, db_session=None):
    """Creates all resources necessary when an incident is created as 'closed'."""
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    ticket = create_incident_ticket(incident, db_session)
    if ticket:
        incident.ticket = ticket_service.create(
            db_session=db_session, ticket_in=TicketCreate(**ticket)
        )

        incident.name = ticket["resource_id"]
        update_external_incident_ticket(incident, db_session)

    db_session.add(incident)
    db_session.commit()
    return
Exemple #30
0
def incident_engage_oncall_flow(user_id: str,
                                user_email: str,
                                incident_id: int,
                                action: dict,
                                db_session=None):
    """Runs the incident engage oncall flow."""
    oncall_service_id = action["submission"]["oncall_service_id"]
    page = action["submission"]["page"]

    # we load the incident instance
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

    # we resolve the oncall service
    oncall_service = service_service.get_by_external_id(
        db_session=db_session, external_id=oncall_service_id)
    oncall_plugin = plugins.get(oncall_service.type)
    oncall_email = oncall_plugin.get(service_id=oncall_service_id)

    # we add the oncall to the incident
    incident_add_or_reactivate_participant_flow(oncall_email,
                                                incident.id,
                                                db_session=db_session)

    # we load the individual
    individual = individual_service.get_by_email(db_session=db_session,
                                                 email=user_email)

    event_service.log(
        db_session=db_session,
        source=oncall_plugin.title,
        description=
        f"{individual.name} engages oncall service {oncall_service.name}",
        incident_id=incident.id,
    )

    if page == "Yes":
        # we page the oncall
        oncall_plugin.page(oncall_service_id, incident.name, incident.title,
                           incident.description)

        event_service.log(
            db_session=db_session,
            source=oncall_plugin.title,
            description=f"{oncall_service.name} on-call paged",
            incident_id=incident.id,
        )