Esempio n. 1
0
def update_report_incident_modal(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict = None,
    db_session=None,
    slack_client=None,
):
    """Creates a modal for reporting an incident."""
    trigger_id = action["trigger_id"]

    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    # we must pass existing values if they exist
    modal_update_template = report_incident(
        db_session=db_session,
        channel_id=channel_id,
        title=parsed_form_data[IncidentBlockId.title],
        description=parsed_form_data[IncidentBlockId.description],
        project_name=parsed_form_data[IncidentBlockId.project]["value"],
    )

    update_modal_with_user(
        client=slack_client,
        trigger_id=trigger_id,
        view_id=action["view"]["id"],
        modal=modal_update_template,
    )
Esempio n. 2
0
def update_update_participant_modal(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    db_session=None,
    slack_client=None,
):
    """Pushes an updated view to the update participant modal."""
    trigger_id = action["trigger_id"]

    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    participant_id = parsed_form_data[UpdateParticipantBlockId.participant]["value"]

    selected_participant = participant_service.get(
        db_session=db_session, participant_id=participant_id
    )
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)
    modal_update_template = update_participant(incident=incident, participant=selected_participant)

    update_modal_with_user(
        client=slack_client,
        trigger_id=trigger_id,
        view_id=action["view"]["id"],
        modal=modal_update_template,
    )
Esempio n. 3
0
def update_participant_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    db_session=None,
    slack_client=None,
):
    """Saves form data."""
    submitted_form = action.get("view")

    parsed_form_data = parse_submitted_form(submitted_form)

    added_reason = parsed_form_data.get(UpdateParticipantBlockId.reason_added)
    participant_id = int(parsed_form_data.get(UpdateParticipantBlockId.participant)["value"])
    selected_participant = participant_service.get(
        db_session=db_session, participant_id=participant_id
    )
    participant_service.update(
        db_session=db_session,
        participant=selected_participant,
        participant_in=ParticipantUpdate(added_reason=added_reason),
    )

    send_ephemeral_message(
        client=slack_client,
        conversation_id=channel_id,
        user_id=user_id,
        text="You have successfully updated the participant.",
    )
Esempio n. 4
0
def run_workflow_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    db_session=None,
    slack_client=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(RunWorkflowBlockId.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(
        RunWorkflowBlockId.workflow_select)["value"]
    run_reason = parsed_form_data.get(RunWorkflowBlockId.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,
    )
Esempio n. 5
0
def report_incident_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    config: SlackConversationConfiguration = None,
    db_session: SessionLocal = None,
    slack_client=None,
):
    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    # Send a confirmation to the user
    blocks = create_incident_reported_confirmation_message(
        title=parsed_form_data[IncidentBlockId.title],
        description=parsed_form_data[IncidentBlockId.description],
        incident_type=parsed_form_data[IncidentBlockId.type]["value"],
        incident_priority=parsed_form_data[IncidentBlockId.priority]["value"],
    )

    send_ephemeral_message(
        client=slack_client,
        conversation_id=channel_id,
        user_id=user_id,
        text="",
        blocks=blocks,
    )

    tags = []
    for t in parsed_form_data.get(IncidentBlockId.tags, []):
        # we have to fetch as only the IDs are embedded in slack
        tag = tag_service.get(db_session=db_session, tag_id=int(t["value"]))
        tags.append(tag)

    project = {"name": parsed_form_data[IncidentBlockId.project]["value"]}
    incident_in = IncidentCreate(
        title=parsed_form_data[IncidentBlockId.title],
        description=parsed_form_data[IncidentBlockId.description],
        incident_type={"name": parsed_form_data[IncidentBlockId.type]["value"]},
        incident_priority={"name": parsed_form_data[IncidentBlockId.priority]["value"]},
        project=project,
        tags=tags,
    )

    if not incident_in.reporter:
        incident_in.reporter = ParticipantUpdate(individual=IndividualContactRead(email=user_email))

    # Create the incident
    incident = incident_service.create(db_session=db_session, incident_in=incident_in)

    incident_flows.incident_create_flow(
        incident_id=incident.id,
        db_session=db_session,
        organization_slug=incident.project.organization.slug,
    )
Esempio n. 6
0
def update_incident_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    config: SlackConversationConfiguration = None,
    db_session=None,
    slack_client=None,
):
    """Massages slack dialog data into something that Dispatch can use."""
    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

    tags = []
    for t in parsed_form_data.get(IncidentBlockId.tags, []):
        # we have to fetch as only the IDs are embedded in slack
        tag = tag_service.get(db_session=db_session, tag_id=int(t["value"]))
        tags.append(tag)

    incident_in = IncidentUpdate(
        title=parsed_form_data[IncidentBlockId.title],
        description=parsed_form_data[IncidentBlockId.description],
        resolution=parsed_form_data[IncidentBlockId.resolution],
        incident_type={"name": parsed_form_data[IncidentBlockId.type]["value"]},
        incident_priority={"name": parsed_form_data[IncidentBlockId.priority]["value"]},
        status=parsed_form_data[IncidentBlockId.status]["value"],
        tags=tags,
    )

    previous_incident = IncidentRead.from_orm(incident)

    # we don't allow visibility to be set in slack so we copy it over
    incident_in.visibility = incident.visibility

    updated_incident = incident_service.update(
        db_session=db_session, incident=incident, incident_in=incident_in
    )

    commander_email = updated_incident.commander.individual.email
    reporter_email = updated_incident.reporter.individual.email
    incident_flows.incident_update_flow(
        user_email,
        commander_email,
        reporter_email,
        incident_id,
        previous_incident,
        db_session=db_session,
    )

    if updated_incident.status != IncidentStatus.closed:
        send_ephemeral_message(
            slack_client, channel_id, user_id, "You have sucessfully updated the incident."
        )
Esempio n. 7
0
def add_timeline_event_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    config: SlackConversationConfiguration = None,
    db_session=None,
    slack_client=None,
):
    """Adds event to incident timeline based on submitted form data."""
    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    event_date = parsed_form_data.get(AddTimelineEventBlockId.date)
    event_hour = parsed_form_data.get(AddTimelineEventBlockId.hour)["value"]
    event_minute = parsed_form_data.get(AddTimelineEventBlockId.minute)["value"]
    event_timezone_selection = parsed_form_data.get(AddTimelineEventBlockId.timezone)["value"]
    event_description = parsed_form_data.get(AddTimelineEventBlockId.description)

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

    event_timezone = event_timezone_selection
    if event_timezone_selection == "profile":
        participant_profile = get_user_profile_by_email(slack_client, user_email)
        if participant_profile.get("tz"):
            event_timezone = participant_profile.get("tz")

    event_dt = datetime.fromisoformat(f"{event_date}T{event_hour}:{event_minute}")
    event_dt_utc = pytz.timezone(event_timezone).localize(event_dt).astimezone(pytz.utc)

    event_service.log(
        db_session=db_session,
        source="Slack Plugin - Conversation Management",
        started_at=event_dt_utc,
        description=f'"{event_description}," said {participant.individual.name}',
        incident_id=incident_id,
        individual_id=participant.individual.id,
    )

    send_ephemeral_message(
        client=slack_client,
        conversation_id=channel_id,
        user_id=user_id,
        text="Event sucessfully added to timeline.",
    )
Esempio n. 8
0
def report_incident_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    db_session: SessionLocal = None,
    slack_client=None,
):
    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    # Send a confirmation to the user
    blocks = create_incident_reported_confirmation_message(
        title=parsed_form_data[IncidentBlockId.title],
        description=parsed_form_data[IncidentBlockId.description],
        incident_type=parsed_form_data[IncidentBlockId.type]["value"],
        incident_priority=parsed_form_data[IncidentBlockId.priority]["value"],
    )

    send_ephemeral_message(
        client=slack_client,
        conversation_id=channel_id,
        user_id=user_id,
        text="",
        blocks=blocks,
    )

    tags = []
    for t in parsed_form_data.get(IncidentBlockId.tags, []):
        tags.append({"id": t["value"]})

    incident_in = IncidentCreate(
        title=parsed_form_data[IncidentBlockId.title],
        description=parsed_form_data[IncidentBlockId.description],
        incident_type={"name": parsed_form_data[IncidentBlockId.type]["value"]},
        incident_priority={"name": parsed_form_data[IncidentBlockId.priority]["value"]},
        project={"name": parsed_form_data[IncidentBlockId.project]["value"]},
        reporter=IndividualContactCreate(email=user_email),
        tags=tags,
    )

    # Create the incident
    incident = incident_service.create(db_session=db_session, incident_in=incident_in)

    incident_flows.incident_create_flow(incident_id=incident.id, db_session=db_session)
Esempio n. 9
0
def rating_feedback_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    config: SlackConversationConfiguration = None,
    db_session=None,
    slack_client=None,
):
    """Adds rating and feeback to incident based on submitted form data."""
    incident = incident_service.get(db_session=db_session, incident_id=incident_id)

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

    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    feedback = parsed_form_data.get(RatingFeedbackBlockId.feedback)
    rating = parsed_form_data.get(RatingFeedbackBlockId.rating, {}).get("value")

    feedback_in = FeedbackCreate(
        rating=rating, feedback=feedback, project=incident.project, incident=incident
    )
    feedback = feedback_service.create(db_session=db_session, feedback_in=feedback_in)

    incident.feedback.append(feedback)

    # we only really care if this exists, if it doesn't then flag is false
    if not parsed_form_data.get(RatingFeedbackBlockId.anonymous):
        participant.feedback.append(feedback)
        db_session.add(participant)

    db_session.add(incident)
    db_session.commit()

    send_message(
        client=slack_client,
        conversation_id=user_id,
        text="Thank you for your feedback!",
    )
Esempio n. 10
0
def rating_feedback_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    db_session=None,
    slack_client=None,
):
    """Adds rating and feeback to incident based on submitted form data."""
    incident = incident_service.get(db_session=db_session,
                                    incident_id=incident_id)

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

    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    feedback = parsed_form_data.get(RatingFeedbackBlockId.feedback)
    rating = parsed_form_data.get(RatingFeedbackBlockId.rating)["value"]
    anonymous = parsed_form_data.get(RatingFeedbackBlockId.anonymous)["value"]

    feedback_in = FeedbackCreate(rating=rating,
                                 feedback=feedback,
                                 project=incident.project)
    feedback = feedback_service.create(db_session=db_session,
                                       feedback_in=feedback_in)

    incident.feedback.append(feedback)

    if anonymous == "":
        participant.feedback.append(feedback)
        db_session.add(participant)

    db_session.add(incident)
    db_session.commit()

    send_message(
        client=slack_client,
        conversation_id=user_id,
        text="Thank you for your feedback!",
    )
Esempio n. 11
0
def update_incident_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    db_session=None,
    slack_client=None,
):
    """Massages slack dialog data into something that Dispatch can use."""
    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    tags = []
    for t in parsed_form_data.get(IncidentBlockId.tags, []):
        tags.append({"id": t["value"]})

    incident_in = IncidentUpdate(
        title=parsed_form_data[IncidentBlockId.title],
        description=parsed_form_data[IncidentBlockId.description],
        incident_type={"name": parsed_form_data[IncidentBlockId.type]["value"]},
        incident_priority={"name": parsed_form_data[IncidentBlockId.priority]["value"]},
        status=parsed_form_data[IncidentBlockId.status]["value"],
        tags=tags,
    )

    incident = incident_service.get(db_session=db_session, incident_id=incident_id)
    existing_incident = IncidentRead.from_orm(incident)

    # we don't allow visibility to be set in slack so we copy it over
    incident_in.visibility = incident.visibility

    updated_incident = incident_service.update(
        db_session=db_session, incident=incident, incident_in=incident_in
    )
    incident_flows.incident_update_flow(
        user_email, incident_id, existing_incident, db_session=db_session
    )

    if updated_incident.status != IncidentStatus.closed:
        send_ephemeral_message(
            slack_client, channel_id, user_id, "You have sucessfully updated the incident."
        )
Esempio n. 12
0
def update_notifications_group_from_submitted_form(
    user_id: str,
    user_email: str,
    channel_id: str,
    incident_id: int,
    action: dict,
    config: SlackConversationConfiguration = None,
    db_session=None,
    slack_client=None,
):
    """Updates notifications group based on submitted form data."""
    submitted_form = action.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)

    current_members = (
        submitted_form["blocks"][1]["element"]["initial_value"].replace(" ", "").split(",")
    )
    updated_members = (
        parsed_form_data.get(UpdateNotificationsGroupBlockId.update_members)
        .replace(" ", "")
        .split(",")
    )

    members_added = list(set(updated_members) - set(current_members))
    members_removed = list(set(current_members) - set(updated_members))

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

    group_plugin = plugin_service.get_active_instance(
        db_session=db_session, project_id=incident.project.id, plugin_type="participant-group"
    )

    group_plugin.instance.add(incident.notifications_group.email, members_added)
    group_plugin.instance.remove(incident.notifications_group.email, members_removed)

    send_ephemeral_message(
        client=slack_client,
        conversation_id=channel_id,
        user_id=user_id,
        text="You have successfully updated the notifications group.",
    )
Esempio n. 13
0
def get_tags(
    db_session: SessionLocal,
    user_id: int,
    user_email: str,
    channel_id: str,
    incident_id: str,
    query_str: str,
    request: Request,
):
    """Fetches tags based on the current query."""
    # use the project from the incident if available
    filter_spec = {}
    if incident_id:
        incident = incident_service.get(db_session=db_session,
                                        incident_id=incident_id)
        # scope to current incident project
        filter_spec = {
            "and": [{
                "model": "Project",
                "op": "==",
                "field": "id",
                "value": incident.project.id
            }]
        }

    submitted_form = request.get("view")
    parsed_form_data = parse_submitted_form(submitted_form)
    project = parsed_form_data.get(IncidentBlockId.project)

    if project:
        filter_spec = {
            "and": [{
                "model": "Project",
                "op": "==",
                "field": "name",
                "value": project["value"]
            }]
        }

    # attempt to filter by tag type
    if "/" in query_str:
        tag_type, tag_name = query_str.split("/")
        type_filter = {
            "model": "TagType",
            "op": "==",
            "field": "name",
            "value": tag_type
        }

        if filter_spec.get("and"):
            filter_spec["and"].append(type_filter)
        else:
            filter_spec = {"and": [type_filter]}

        if not tag_name:
            query_str = None

        tags = search_filter_sort_paginate(db_session=db_session,
                                           model="Tag",
                                           query_str=query_str,
                                           filter_spec=filter_spec)
    else:
        tags = search_filter_sort_paginate(db_session=db_session,
                                           model="Tag",
                                           query_str=query_str,
                                           filter_spec=filter_spec)

    options = []
    for t in tags["items"]:
        options.append({
            "text": {
                "type": "plain_text",
                "text": f"{t.tag_type.name}/{t.name}"
            },
            "value": str(
                t.id
            ),  # NOTE slack doesn't not accept int's as values (fails silently)
        })

    return {"options": options}