Skip to content

Commit

Permalink
Merge branch 'master' into enhancement/allow-filter-dashboard-by-comm…
Browse files Browse the repository at this point in the history
…ander
  • Loading branch information
whitdog47 authored Sep 29, 2023
2 parents fdd5d78 + 2e3f8e0 commit ee421cf
Show file tree
Hide file tree
Showing 22 changed files with 641 additions and 203 deletions.
4 changes: 4 additions & 0 deletions src/dispatch/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from dispatch.entity.views import router as entity_router
from dispatch.entity_type.views import router as entity_type_router
from dispatch.feedback.incident.views import router as feedback_router
from dispatch.feedback.service.views import router as service_feedback_router
from dispatch.incident.priority.views import router as incident_priority_router
from dispatch.incident.severity.views import router as incident_severity_router
from dispatch.incident.type.views import router as incident_type_router
Expand Down Expand Up @@ -203,6 +204,9 @@ def get_organization_path(organization: OrganizationSlug):
authenticated_organization_api_router.include_router(
feedback_router, prefix="/feedback", tags=["feedback"]
)
authenticated_organization_api_router.include_router(
service_feedback_router, prefix="/service_feedback", tags=["service_feedback"]
)
authenticated_organization_api_router.include_router(
notification_router, prefix="/notifications", tags=["notifications"]
)
Expand Down
206 changes: 90 additions & 116 deletions src/dispatch/case/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

from dispatch.case import service as case_service
from dispatch.case.models import CaseRead
from dispatch.conversation import service as conversation_service
from dispatch.conversation.models import ConversationCreate
from dispatch.conversation import flows as conversation_flows
from dispatch.database.core import SessionLocal
from dispatch.decorators import background_task
from dispatch.document import flows as document_flows
Expand Down Expand Up @@ -154,26 +153,6 @@ def case_add_or_reactivate_participant_flow(
return participant


def create_conversation(case: Case, conversation_target: str, db_session: SessionLocal):
"""Create external communication conversation."""
plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="conversation"
)
conversation = plugin.instance.create_threaded(
case=case, conversation_id=conversation_target, db_session=db_session
)
conversation.update({"resource_type": plugin.plugin.slug, "resource_id": conversation["id"]})

event_service.log_case_event(
db_session=db_session,
source=plugin.plugin.title,
description="Case conversation created",
case_id=case.id,
)

return conversation


def update_conversation(case: Case, db_session: SessionLocal):
"""Updates external communication conversation."""
plugin = plugin_service.get_active_instance(
Expand Down Expand Up @@ -217,6 +196,7 @@ def case_new_create_flow(
case_id=case.id,
individual_participants=individual_participants,
team_participants=team_participants,
conversation_target=conversation_target,
)

if case.case_priority.page_assignee:
Expand All @@ -241,67 +221,6 @@ def case_new_create_flow(
else:
log.warning("Case assignee not paged. No plugin of type oncall enabled.")

conversation_plugin = plugin_service.get_active_instance(
db_session=db_session, project_id=case.project.id, plugin_type="conversation"
)
if conversation_plugin:
if not conversation_target:
conversation_target = case.case_type.conversation_target
if conversation_target:
try:
# TODO: Refactor conversation creation using conversation_flows module
conversation = create_conversation(case, conversation_target, db_session)
conversation_in = ConversationCreate(
resource_id=conversation["resource_id"],
resource_type=conversation["resource_type"],
weblink=conversation["weblink"],
thread_id=conversation["timestamp"],
channel_id=conversation["id"],
)
case.conversation = conversation_service.create(
db_session=db_session, conversation_in=conversation_in
)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Conversation added to case",
case_id=case.id,
)
# wait until all resources are created before adding suggested participants
individual_participants = [x.email for x, _ in individual_participants]

for email in individual_participants:
# we don't rely on on this flow to add folks to the conversation because in this case
# we want to do it in bulk
case_add_or_reactivate_participant_flow(
db_session=db_session,
user_email=email,
case_id=case.id,
add_to_conversation=False,
)
# explicitly add the assignee to the conversation
all_participants = individual_participants + [case.assignee.individual.email]
conversation_plugin.instance.add_to_thread(
case.conversation.channel_id,
case.conversation.thread_id,
all_participants,
)
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Case participants added to conversation.",
case_id=case.id,
)
except Exception as e:
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description=f"Creation of case conversation failed. Reason: {e}",
case_id=case.id,
)
log.exception(e)

db_session.add(case)
db_session.commit()

Expand Down Expand Up @@ -684,51 +603,106 @@ def case_assign_role_flow(


def case_create_resources_flow(
db_session: Session, case_id: int, individual_participants: list, team_participants: list
db_session: Session,
case_id: int,
individual_participants: List[str],
team_participants: List[str],
conversation_target: str = None,
create_resources: bool = True,
) -> None:
"""Runs the case resource creation flow."""
case = get(db_session=db_session, case_id=case_id)

if case.assignee:
individual_participants.append((case.assignee.individual, None))

# we create the tactical group
direct_participant_emails = [i.email for i, _ in individual_participants]
if create_resources:
# we create the tactical group
direct_participant_emails = [i.email for i, _ in individual_participants]

indirect_participant_emails = [t.email for t in team_participants]
indirect_participant_emails = [t.email for t in team_participants]

group = group_flows.create_group(
subject=case,
group_type=GroupType.tactical,
group_participants=list(set(direct_participant_emails + indirect_participant_emails)),
db_session=db_session,
)
if not case.groups:
group_flows.create_group(
subject=case,
group_type=GroupType.tactical,
group_participants=list(
set(direct_participant_emails + indirect_participant_emails)
),
db_session=db_session,
)

# we create the storage folder
storage_members = []
if group:
storage_members = [group.email]
# we create the storage folder
storage_members = []
if case.tactical_group:
storage_members = [case.tactical_group.email]
# direct add members if not group exists
else:
storage_members = direct_participant_emails

# direct add members if not group exists
else:
storage_members = direct_participant_emails
if not case.storage:
storage_flows.create_storage(
subject=case, storage_members=storage_members, db_session=db_session
)

case.storage = storage_flows.create_storage(
subject=case, storage_members=storage_members, db_session=db_session
)
# we create the investigation document
if not case.case_document:
document_flows.create_document(
subject=case,
document_type=DocumentResourceTypes.case,
document_template=case.case_type.case_template_document,
db_session=db_session,
)

# we create the investigation document
document = document_flows.create_document(
subject=case,
document_type=DocumentResourceTypes.case,
document_template=case.case_type.case_template_document,
db_session=db_session,
)
# we update the ticket
ticket_flows.update_case_ticket(case=case, db_session=db_session)

# we update the ticket
ticket_flows.update_case_ticket(case=case, db_session=db_session)
# we update the case document
document_flows.update_document(
document=case.case_document, project_id=case.project.id, db_session=db_session
)

# we update the case document
document_flows.update_document(
document=document, project_id=case.project.id, db_session=db_session
)
try:
# we create the conversation and add participants to the thread
conversation_flows.create_case_conversation(case, conversation_target, db_session)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Conversation added to case",
case_id=case.id,
)
# wait until all resources are created before adding suggested participants
individual_participants = [x.email for x, _ in individual_participants]

for email in individual_participants:
# we don't rely on on this flow to add folks to the conversation because in this case
# we want to do it in bulk
case_add_or_reactivate_participant_flow(
db_session=db_session,
user_email=email,
case_id=case.id,
add_to_conversation=False,
)
# explicitly add the assignee to the conversation
all_participants = individual_participants + [case.assignee.individual.email]

# # we add the participant to the conversation
conversation_flows.add_case_participants(
case=case, participant_emails=all_participants, db_session=db_session
)

event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description="Case participants added to conversation.",
case_id=case.id,
)
except Exception as e:
event_service.log_case_event(
db_session=db_session,
source="Dispatch Core App",
description=f"Creation of case conversation failed. Reason: {e}",
case_id=case.id,
)
log.exception(e)
28 changes: 28 additions & 0 deletions src/dispatch/case/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
case_new_create_flow,
case_triage_create_flow,
case_update_flow,
case_create_resources_flow,
get_case_participants,
)
from .models import Case, CaseCreate, CasePagination, CaseRead, CaseUpdate, CaseExpandedPagination
from .service import create, delete, get, update
Expand Down Expand Up @@ -145,6 +147,32 @@ def create_case(
return case


@router.post(
"/{case_id}/resources",
response_model=CaseRead,
summary="Creates resources for an existing case.",
)
def create_case_resources(
db_session: DbSession,
case_id: PrimaryKey,
current_case: CurrentCase,
background_tasks: BackgroundTasks,
):
"""Creates resources for an existing case."""
individual_participants, team_participants = get_case_participants(
case=current_case, db_session=db_session
)
background_tasks.add_task(
case_create_resources_flow,
db_session=db_session,
case_id=case_id,
individual_participants=individual_participants,
team_participants=team_participants,
)

return current_case


@router.put(
"/{case_id}",
response_model=CaseRead,
Expand Down
Loading

0 comments on commit ee421cf

Please sign in to comment.