def send_incident_close_reminder(incident: Incident, db_session: SessionLocal): """Sends a direct message to the incident commander reminding them to close the incident if possible.""" message_text = "Incident Status Reminder" message_template = INCIDENT_STATUS_REMINDER plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="conversation" ) if not plugin: log.warning("Incident close reminder message not sent, no conversation plugin enabled.") return update_command = plugin.instance.get_command_name(ConversationCommands.update_incident) items = [ { "command": update_command, "name": incident.name, "ticket_weblink": incident.ticket.weblink, "title": incident.title, "status": incident.status, } ] plugin.instance.send_direct( incident.commander.individual.email, message_text, message_template, MessageType.incident_status_reminder, items=items, ) log.debug(f"Incident close reminder sent to {incident.commander.individual.email}.")
def send_incident_suggested_reading_messages(incident: Incident, items: list, participant_email: str, db_session: SessionLocal): """Sends a suggested reading message to a participant.""" if items: plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="conversation") if not plugin: log.warning( "Suggested reading message not sent, no conversation plugin enabled." ) return plugin.instance.send_ephemeral( incident.conversation.channel_id, participant_email, "Suggested Reading", [INCIDENT_PARTICIPANT_SUGGESTED_READING_ITEM], MessageType.incident_participant_suggested_reading, items=items, ) log.debug( f"Suggested reading ephemeral message sent to {participant_email}." )
def update_notifications_group_from_submitted_form(action: dict, db_session=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( UpdateNotificationsGroupBlockFields.update_members).replace( " ", "").split(",")) members_added = list(set(updated_members) - set(current_members)) members_removed = list(set(current_members) - set(updated_members)) incident_id = action["view"]["private_metadata"]["incident_id"] 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)
def send_incident_review_document_notification(conversation_id: str, review_document_weblink: str, incident: Incident, db_session: SessionLocal): """Sends the review document notification.""" notification_text = "Incident Notification" notification_type = MessageType.incident_notification plugin = plugin_service.get_active_instance(db_session=db_session, project_id=incident.project.id, plugin_type="conversation") if not plugin: log.warning( "Incident review document not sent, no conversation enabled.") return plugin.instance.send( conversation_id, notification_text, [INCIDENT_REVIEW_DOCUMENT], notification_type, review_document_weblink=review_document_weblink, ) log.debug("Incident review document notification sent.")
def resolve_and_associate_role( db_session: SessionLocal, incident: Incident, role: ParticipantRoleType ): """For a given role type resolve which individual email should be assigned that role.""" email_address = None service_id = None incident_role = resolve_role(db_session=db_session, role=role, incident=incident) if not incident_role: log.info( f"We were not able to resolve the email address for {role} via incident role policies." ) return email_address, service_id if incident_role.service: service_id = incident_role.service.id service_external_id = incident_role.service.external_id oncall_plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="oncall" ) if not oncall_plugin: log.warning("Resolved incident role associated with a plugin that is not active.") return email_address, service_id email_address = oncall_plugin.instance.get(service_id=service_external_id) return email_address, service_id
def sync_sources(db_session: SessionLocal, project: Project): """Syncs sources from external sources.""" plugin = plugin_service.get_active_instance( db_session=db_session, plugin_type="source", project_id=project.id ) if not plugin: log.debug(f"No active plugins were found. PluginType: 'source' ProjectId: {project.id}") return log.debug(f"Getting source information via: {plugin.plugin.slug}") sources = source_service.get_all(db_session=db_session, project_id=project.id) for s in sources: log.debug(f"Syncing Source. Source: {s}") if not s.external_id: log.debug(f"Skipping source, no externalId Source: {s}") continue data = plugin.instance.get(external_id=s.external_id) if data: for k, v in data.items(): setattr(s, k, v) db_session.commit()
def sync_active_stable_tasks(db_session: SessionLocal, project: Project): """Syncs incident tasks.""" task_plugin = plugin_service.get_active_instance(db_session=db_session, project_id=project.id, plugin_type="task") if not task_plugin: log.warning( f"Skipping task sync no task plugin enabled. ProjectId: {project.id}" ) return # we get all active and stable incidents active_incidents = incident_service.get_all_by_status( db_session=db_session, project_id=project.id, status=IncidentStatus.active) stable_incidents = incident_service.get_all_by_status( db_session=db_session, project_id=project.id, status=IncidentStatus.stable) incidents = active_incidents + stable_incidents lookback = 60 * 5 # 5 min sync_tasks(db_session, task_plugin, incidents, lookback=lookback, notify=True)
def send_incident_participant_has_role_ephemeral_message( assigner_email: str, assignee_contact_info: dict, assignee_role: str, incident: Incident, db_session: SessionLocal, ): """Sends an ephemeral message to the assigner to let them know that the assignee already has the role.""" notification_text = "Incident Assign Role Notification" plugin = plugin_service.get_active_instance(db_session=db_session, project_id=incident.project.id, plugin_type="conversation") if not plugin: log.warning( "Unabled to send incident participant has role message, no conversation plugin enabled." ) return plugin.instance.send_ephemeral( incident.conversation.channel_id, assigner_email, notification_text, blocks=[{ "type": "section", "text": { "type": "plain_text", "text": f"{assignee_contact_info['fullname']} already has the {assignee_role} role.", }, }], ) log.debug("Incident participant has role message sent.")
def send_tactical_report_to_conversation(incident_id: int, conditions: str, actions: str, needs: str, db_session: SessionLocal): """Sends a tactical report to the conversation.""" # we load the incident instance incident = incident_service.get(db_session=db_session, incident_id=incident_id) plugin = plugin_service.get_active_instance(db_session=db_session, project_id=incident.project.id, plugin_type="conversation") if not plugin: log.warning( "Tactical report not sent, no conversation plugin enabled.") return plugin.instance.send( incident.conversation.channel_id, "Incident Tactical Report", INCIDENT_TACTICAL_REPORT, notification_type=MessageType.incident_tactical_report, persist=True, conditions=conditions, actions=actions, needs=needs, ) log.debug( "Tactical report sent to conversation {incident.conversation.channel_id}." )
def send_incident_rating_feedback_message(incident: Incident, db_session: SessionLocal): """ Sends a direct message to all incident participants asking them to rate and provide feedback about the incident. """ notification_text = "Incident Rating and Feedback" notification_template = INCIDENT_CLOSED_RATING_FEEDBACK_NOTIFICATION plugin = plugin_service.get_active_instance(db_session=db_session, project_id=incident.project.id, plugin_type="conversation") if not plugin: log.warning( "Incident rating and feedback message not sent, no conversation plugin enabled." ) return items = [{ "incident_id": incident.id, "name": incident.name, "title": incident.title, "ticket_weblink": incident.ticket.weblink, }] for participant in incident.participants: plugin.instance.send_direct( participant.individual.email, notification_text, notification_template, MessageType.incident_rating_feedback, items=items, ) log.debug("Incident rating and feedback message sent to all participants.")
def get_or_create(*, db_session, email: str, incident: Incident = None, **kwargs) -> IndividualContact: """Gets or creates an individual.""" contact = get_by_email(db_session=db_session, email=email) if not contact: contact_plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="contact") individual_info = {} if contact_plugin: individual_info = contact_plugin.instance.get( email, db_session=db_session) kwargs["email"] = individual_info.get("email", email) kwargs["name"] = individual_info.get("fullname", "Unknown") kwargs["weblink"] = individual_info.get("weblink", "Unknown") individual_contact_in = IndividualContactCreate( **kwargs, project=incident.project) contact = create(db_session=db_session, individual_contact_in=individual_contact_in) return contact
def send_task_notification( incident, message_template, creator, assignees, description, weblink, db_session: SessionLocal, ): """Sends a task notification.""" # we send a notification to the incident conversation notification_text = "Incident Notification" notification_type = "incident-notification" plugin = plugin_service.get_active_instance(db_session=db_session, project_id=incident.project.id, plugin_type="conversation") plugin.instance.send( incident.conversation.channel_id, notification_text, message_template, notification_type, task_creator=creator.individual.email, task_assignees=[x.individual.email for x in assignees], task_description=description, task_weblink=weblink, )
def send_welcome_email_to_participant( participant_email: str, incident: Incident, db_session: SessionLocal ): """Sends a welcome email to the participant.""" # we load the incident instance plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="email" ) if not plugin: log.warning("Participant welcome email not sent, not email plugin configured.") return message_kwargs = { "name": incident.name, "title": incident.title, "description": incident.description, "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_team": incident.commander.team, "commander_weblink": incident.commander.individual.weblink, "reporter_fullname": incident.reporter.individual.name, "reporter_team": incident.reporter.team, "reporter_weblink": incident.reporter.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"), "contact_fullname": incident.commander.individual.name, "contact_weblink": incident.commander.individual.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} ) notification_text = "Incident Notification" plugin.instance.send( participant_email, notification_text, INCIDENT_PARTICIPANT_WELCOME_MESSAGE, MessageType.incident_participant_welcome, **message_kwargs, ) log.debug(f"Welcome email sent to {participant_email}.")
def create_task_reminders(db_session: SessionLocal, project: Project): """Creates multiple task reminders.""" tasks = task_service.get_overdue_tasks(db_session=db_session, project_id=project.id) log.debug(f"New tasks that need reminders. NumTasks: {len(tasks)}") # let's only remind for active incidents for now tasks = [t for t in tasks if t.incident.status == IncidentStatus.active] if tasks: contact_fullname = contact_weblink = DISPATCH_HELP_EMAIL # NOTE INCIDENT_ONCALL_SERVICE_ID is optional if INCIDENT_ONCALL_SERVICE_ID: oncall_service = service_service.get_by_external_id( db_session=db_session, external_id=INCIDENT_ONCALL_SERVICE_ID) if not oncall_service: log.warning( "INCIDENT_ONCALL_SERVICE_ID configured in the .env file, but not found in the database. Did you create the oncall service in the UI?" ) return oncall_plugin = plugin_service.get_active_instance( db_session=db_session, project_id=project.id, plugin_type="oncall") if not oncall_plugin: log.warning( f"Unable to resolve oncall. No oncall plugin is enabled. Project: {project.name}" ) if oncall_plugin.plugin.slug != oncall_service.type: log.warning( f"Unable to resolve the oncall. Oncall plugin enabled not of type {oncall_plugin.plugin.slug}." ) return if not oncall_plugin: log.warning( f"Unable to resolve the oncall, INCIDENT_ONCALL_SERVICE_ID configured, but associated plugin ({oncall_plugin.plugin.slug}) is not enabled." ) contact_fullname = "Unknown" contact_weblink = None else: oncall_email = oncall_plugin.instance.get( service_id=INCIDENT_ONCALL_SERVICE_ID) oncall_individual = individual_service.resolve_user_by_email( oncall_email, db_session) contact_fullname = oncall_individual["fullname"] contact_weblink = oncall_individual["weblink"] grouped_tasks = group_tasks_by_assignee(tasks) for assignee, tasks in grouped_tasks.items(): create_reminder(db_session, assignee, tasks, contact_fullname, contact_weblink)
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_instance( 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)
def update(*, db_session, task: Task, task_in: TaskUpdate, sync_external: bool = True) -> Task: """Update an existing task.""" # ensure we add assignee as participant if they are not one already assignees = [] for i in task_in.assignees: assignees.append( incident_flows.incident_add_or_reactivate_participant_flow( db_session=db_session, incident_id=task.incident.id, user_email=i.individual.email, ) ) task.assignees = assignees # we add owner as a participant if they are not one already if task_in.owner: # don't reactive participants if the tasks is already resolved if task_in.status != TaskStatus.resolved: task.owner = incident_flows.incident_add_or_reactivate_participant_flow( db_session=db_session, incident_id=task.incident.id, user_email=task_in.owner.individual.email, ) update_data = task_in.dict( skip_defaults=True, exclude={"assignees", "owner", "creator", "incident", "tickets"} ) for field in update_data.keys(): setattr(task, field, update_data[field]) # if we have an external task plugin enabled, attempt to update the external resource as well # 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_instance( db_session=db_session, project_id=task.incident.project.id, plugin_type="task" ) if drive_task_plugin: if sync_external: try: if task.incident.incident_document: file_id = task.incident.incident_document.resource_id drive_task_plugin.instance.update( file_id, task.resource_id, resolved=task.status ) except Exception: if task.incident.incident_review_document: file_id = task.incident.incident_review_document.resource_id drive_task_plugin.instance.update( file_id, task.resource_id, resolved=task.status ) db_session.add(task) db_session.commit() return task
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.""" from dispatch.incident import service as incident_service 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: for participant_role in participant_roles: participant.participant_roles.append( participant_role_service.create( db_session=db_session, participant_role_in=participant_role)) participant.service_id = service_id return participant
def send_workflow_notification(conversation_id, message_template, db_session, **kwargs): """Sends a workflow notification.""" notification_text = "Incident Notification" notification_type = "incident-notification" plugin = plugin_service.get_active_instance(db_session=db_session, plugin_type="conversation") plugin.instance.send(conversation_id, notification_text, message_template, notification_type, **kwargs)
def send_incident_resources_ephemeral_message_to_participant( user_id: str, incident: Incident, db_session: SessionLocal ): """Sends the list of incident resources to the participant via an ephemeral message.""" plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="conversation" ) if not plugin: log.warning("Incident resource message not sent, no conversation plugin enabled.") return message_kwargs = { "title": incident.title, "description": incident.description, "commander_fullname": incident.commander.individual.name, "commander_team": incident.commander.team, "commander_weblink": incident.commander.individual.weblink, "reporter_fullname": incident.reporter.individual.name, "reporter_team": incident.reporter.team, "reporter_weblink": incident.reporter.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.")
def send_monitor_notification(project_id: int, conversation_id: int, message_template: str, db_session: SessionLocal, **kwargs): """Sends a monitor notification.""" notification_text = "Incident Notification" notification_type = "incident-notification" plugin = plugin_service.get_active_instance(db_session=db_session, plugin_type="conversation", project_id=project_id) plugin.instance.send(conversation_id, notification_text, message_template, notification_type, **kwargs)
def get_plugin_configuration_from_channel_id(db_session: SessionLocal, channel_id: str) -> Plugin: """Fetches the currently slack plugin configuration for this incident channel.""" conversation = conversation_service.get_by_channel_id_ignoring_channel_type( db_session, channel_id) if conversation: plugin_instance = plugin_service.get_active_instance( db_session=db_session, plugin_type="conversation", project_id=conversation.incident.project.id, ) return plugin_instance.configuration
def send_feedack_to_user(channel_id: str, project_id: int, user_id: str, message: str, db_session: SessionLocal): """Sends feedack to the user using an ephemeral message.""" blocks = [{"type": "section", "text": {"type": "mrkdwn", "text": message}}] plugin = plugin_service.get_active_instance(db_session=db_session, project_id=project_id, plugin_type="conversation") plugin.instance.send_ephemeral(channel_id, user_id, "Conversation Command Feedback", blocks=blocks)
def build_update_notifications_group_blocks(incident: Incident, db_session: SessionLocal): """Builds all blocks required to update the membership of the notifications group.""" modal_template = { "type": "modal", "title": {"type": "plain_text", "text": "Update Group Membership"}, "blocks": [ { "type": "context", "elements": [ { "type": "plain_text", "text": "Use this form to update the membership of the notifications group.", } ], }, ], "close": {"type": "plain_text", "text": "Cancel"}, "submit": {"type": "plain_text", "text": "Update"}, "callback_id": UpdateNotificationsGroupCallbacks.submit_form, "private_metadata": json.dumps( {"incident_id": str(incident.id), "channel_id": incident.conversation.channel_id} ), } group_plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="participant-group" ) members = group_plugin.instance.list(incident.notifications_group.email) members_block = { "type": "input", "block_id": UpdateNotificationsGroupBlockFields.update_members, "label": {"type": "plain_text", "text": "Members"}, "element": { "type": "plain_text_input", "action_id": UpdateNotificationsGroupBlockFields.update_members, "multiline": True, "initial_value": (", ").join(members), }, } modal_template["blocks"].append(members_block) modal_template["blocks"].append( { "type": "context", "elements": [{"type": "plain_text", "text": "Separate email addresses with commas."}], }, ) return modal_template
def send_incident_management_help_tips_message(incident: Incident, db_session: SessionLocal): """ Sends a direct message to the incident commander with help tips on how to manage the incident. """ notification_text = "Incident Management Help Tips" message_template = INCIDENT_MANAGEMENT_HELP_TIPS_MESSAGE plugin = plugin_service.get_active_instance(db_session=db_session, project_id=incident.project.id, plugin_type="conversation") if not plugin: log.warning( "Incident management help tips message not sent, no conversation plugin enabled." ) return engage_oncall_command = plugin.instance.get_command_name( ConversationCommands.engage_oncall) list_resources_command = plugin.instance.get_command_name( ConversationCommands.list_resources) executive_report_command = plugin.instance.get_command_name( ConversationCommands.executive_report) tactical_report_command = plugin.instance.get_command_name( ConversationCommands.tactical_report) update_command = plugin.instance.get_command_name( ConversationCommands.update_incident) items = [{ "name": incident.name, "title": incident.title, "engage_oncall_command": engage_oncall_command, "list_resources_command": list_resources_command, "executive_report_command": executive_report_command, "tactical_report_command": tactical_report_command, "update_command": update_command, }] plugin.instance.send_direct( incident.commander.individual.email, notification_text, message_template, MessageType.incident_management_help_tips, items=items, ) log.debug( f"Incident management help tips message sent to incident commander with email {incident.commander.individual.email}." )
def create_evergreen_reminder(db_session: SessionLocal, project: Project, owner_email: str, resource_groups: Any): """Contains the logic for evergreen reminders.""" plugin = plugin_service.get_active_instance(db_session=db_session, plugin_type="email", project_id=project.id) if not plugin: log.warning("Evergreen reminder not sent, no email plugin enabled.") return notification_template = EVERGREEN_REMINDER items = [] for resource_type, resources in resource_groups.items(): for resource in resources: weblink = getattr(resource, "weblink", None) if not weblink: weblink = DISPATCH_UI_URL items.append({ "resource_type": resource_type.replace("_", " ").title(), "name": resource.name, "description": getattr(resource, "description", None), "weblink": weblink, }) notification_type = "evergreen-reminder" name = subject = notification_text = "Evergreen Reminder" success = plugin.instance.send( owner_email, notification_text, notification_template, notification_type, name=name, subject=subject, items=items, # plugin expect dicts ) if success: for item in items: item.evergreen_last_reminder_at = datetime.utcnow() db_session.commit() else: log.error(f"Unable to send evergreen message. Email: {owner_email}")
def daily_sync_workflow(db_session: SessionLocal, project: Project): """Syncs all incident workflows daily.""" workflow_plugin = plugin_service.get_active_instance( db_session=db_session, project_id=project.id, plugin_type="workflow") if not workflow_plugin: log.warning(f"No workflow plugin is enabled. ProjectId: {project.id}") return incidents = incident_service.get_all(db_session=db_session, project_id=project.id).all() sync_workflows(db_session, project, workflow_plugin, incidents, notify=False)
def get_suggested_documents(db_session, incident: Incident) -> list: """Get additional incident documents based on priority, type, and description.""" plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="document-resolver" ) documents = [] if plugin: matches = plugin.instance.get(incident=incident, db_session=db_session) for m in matches: document = document_service.get(db_session=db_session, document_id=m.resource_state["id"]) documents.append(document) return documents
def assign_incident_role( db_session: SessionLocal, incident: Incident, reporter_email: str, role: ParticipantRoleType, ): """Assigns incident roles.""" # We resolve the incident role email # default to reporter if we don't have an oncall plugin enabled assignee_email = reporter_email oncall_plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="oncall") service_id = None if role == ParticipantRoleType.incident_commander: # default to reporter if incident.incident_type.commander_service: service = incident.incident_type.commander_service service_id = service.id if oncall_plugin: assignee_email = oncall_plugin.instance.get( service_id=service.external_id) if incident.incident_priority.page_commander: oncall_plugin.instance.page( service_id=service.external_id, incident_name=incident.name, incident_title=incident.title, incident_description=incident.description, ) elif role == ParticipantRoleType.liaison: if incident.incident_type.liaison_service: service = incident.incident_type.liaison_service service_id = service.id if oncall_plugin: assignee_email = oncall_plugin.instance.get( service_id=service.external_id) # Add a new participant (duplicate participants with different roles will be updated) participant_flows.add_participant( assignee_email, incident, db_session, service_id=service_id, role=role, )
def reactivate_participant(user_email: str, incident: Incident, db_session: SessionLocal): """Reactivates a participant.""" # We get information about the individual contact_plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, 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
def send_incident_closed_information_review_reminder(incident: Incident, db_session: SessionLocal): """ Sends a direct message to the incident commander asking them to review the incident's information and to tag the incident if appropriate. """ message_text = "Incident Closed Information Review Reminder" message_template = INCIDENT_CLOSED_INFORMATION_REVIEW_REMINDER_NOTIFICATION plugin = plugin_service.get_active_instance(db_session=db_session, project_id=incident.project.id, plugin_type="conversation") if not plugin: log.warning( "Incident closed information review reminder message not sent, no conversation plugin enabled." ) return items = [{ "name": incident.name, "title": incident.title, "description": f"{incident.description[:100]}", "resolution": f"{incident.resolution[:100]}", "type": incident.incident_type.name, "priority": incident.incident_priority.name, "dispatch_ui_incident_url": f"{DISPATCH_UI_URL}/{incident.project.organization.name}/incidents/{incident.name}", }] plugin.instance.send_direct( incident.commander.individual.email, message_text, message_template, MessageType.incident_closed_information_review_reminder, items=items, ) log.debug( f"Incident closed information review reminder sent to {incident.commander.individual.email}." )