def update(*, db_session, task: Task, task_in: TaskUpdate) -> 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: 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]) db_session.add(task) db_session.commit() return task
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(db_session=db_session, 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 member_joined_channel( user_email: str, incident_id: int, event: EventEnvelope, db_session=None, ): """Handles the member_joined_channel slack event.""" participant = incident_flows.incident_add_or_reactivate_participant_flow( user_email=user_email, incident_id=incident_id, db_session=db_session) if event.event.inviter: # we update the participant's metadata if not dispatch_slack_service.is_user(event.event.inviter): # we default to the incident commander when we don't know how the user was added added_by_participant = participant_service.get_by_incident_id_and_role( db_session=db_session, incident_id=incident_id, role=ParticipantRoleType.incident_commander, ) participant.added_by = added_by_participant participant.added_reason = ( f"Participant added by {added_by_participant.individual.name}") else: inviter_email = get_user_email(client=slack_client, user_id=event.event.inviter) added_by_participant = participant_service.get_by_incident_id_and_email( db_session=db_session, incident_id=incident_id, email=inviter_email) participant.added_by = added_by_participant participant.added_reason = event.event.text db_session.add(participant) db_session.commit()
def member_joined_channel( user_email: str, incident_id: int, event: EventEnvelope, db_session=None, ): """Handles the member_joined_channel slack event.""" participant = incident_flows.incident_add_or_reactivate_participant_flow( user_email=user_email, incident_id=incident_id, db_session=db_session) # update participant metadata inviter_email = get_user_email(client=slack_client, user_id=event.event.inviter) added_by_participant = participant_service.get_by_incident_id_and_email( db_session=db_session, incident_id=incident_id, email=inviter_email) # default to IC when we don't know how the user was added if not added_by_participant: participant.added_by = participant_service.get_by_incident_id_and_role( db_session=db_session, incident_id=incident_id, role=ParticipantRoleType.incident_commander, ) participant.added_reason = "User was automatically added by Dispatch." else: participant.added_by = added_by_participant participant.added_reason = event.event.text db_session.commit()
def member_joined_channel( user_email: str, incident_id: int, event: EventEnvelope, db_session=None, ): """Handles the member_joined_channel slack event.""" participant = incident_flows.incident_add_or_reactivate_participant_flow( user_email=user_email, incident_id=incident_id, db_session=db_session) # update participant metadata inviter_email = get_user_email(client=slack_client, user_id=event.event.inviter) added_by_participant = participant_service.get_by_incident_id_and_email( db_session=db_session, incident_id=incident_id, email=inviter_email) participant.added_by = added_by_participant participant.added_reason = event.event.text db_session.commit()
def create(*, db_session, task_in: TaskCreate) -> Task: """Create a new task.""" incident = incident_service.get(db_session=db_session, incident_id=task_in.incident.id) tickets = [ ticket_service.get_or_create_by_weblink(db_session=db_session, weblink=t.weblink, resource_type="task-ticket") for t in task_in.tickets ] assignees = [] for i in task_in.assignees: assignee = incident_flows.incident_add_or_reactivate_participant_flow( db_session=db_session, incident_id=incident.id, user_email=i.individual.email, ) # due to the freeform nature of task assignment, we can sometimes pick up other emails # e.g. a google group that we cannot resolve to an individual assignee if assignee: assignees.append(assignee) creator_email = None if not task_in.creator: creator_email = task_in.owner.individual.email else: creator_email = task_in.creator.individual.email # add creator as a participant if they are not one already creator = incident_flows.incident_add_or_reactivate_participant_flow( db_session=db_session, incident_id=incident.id, user_email=creator_email, ) # if we cannot find any assignees, the creator becomes the default assignee if not assignees: assignees.append(creator) # we add owner as a participant if they are not one already if task_in.owner: owner = incident_flows.incident_add_or_reactivate_participant_flow( db_session=db_session, incident_id=incident.id, user_email=task_in.owner.individual.email, ) else: owner = incident.commander task = Task( **task_in.dict( exclude={"assignees", "owner", "incident", "creator", "tickets"}), creator=creator, owner=owner, assignees=assignees, incident=incident, tickets=tickets, ) event_service.log( db_session=db_session, source="Dispatch Core App", description="New incident task created", details={"weblink": task.weblink}, incident_id=incident.id, ) db_session.add(task) db_session.commit() return task
def create_or_update_task(db_session, incident, task: dict, notify: bool = False): """Creates a new task in the database or updates an existing one.""" incident_task = task_service.get_by_resource_id(db_session=db_session, resource_id=task["id"]) assignees = [] for a in task["assignees"]: assignees.append( db_session.merge( incident_add_or_reactivate_participant_flow( a, incident_id=incident.id, db_session=db_session))) description = task["description"][0] status = TaskStatus.open if not task["status"] else TaskStatus.resolved resource_id = task["id"] weblink = task["web_link"] # TODO we can build this out as our scraping gets more advanced tickets = [ ticket_service.get_or_create_by_weblink(db_session=db_session, weblink=t["web_link"]) for t in task["tickets"] ] if incident_task: # allways update tickets and assignees incident_task.assignees = assignees incident_task.tickets = tickets # only notify if it's newly resolved if status == TaskStatus.resolved: if incident_task.status != TaskStatus.resolved: incident_task.status = status if notify: send_task_notification( incident.conversation.channel_id, INCIDENT_TASK_RESOLVED_NOTIFICATION, assignees, description, weblink, ) else: # we add the task to the incident creator = db_session.merge( incident_add_or_reactivate_participant_flow( task["owner"], incident_id=incident.id, db_session=db_session)) task = task_service.create( db_session=db_session, creator=creator, assignees=assignees, description=description, status=status, tickets=tickets, resource_id=resource_id, resource_type=INCIDENT_RESOURCE_INCIDENT_TASK, weblink=weblink, ) incident.tasks.append(task) if notify: send_task_notification( incident.conversation.channel_id, INCIDENT_TASK_NEW_NOTIFICATION, assignees, description, weblink, ) db_session.commit()