Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds functionality to manually create missing incident and case resources. #3791

Merged
merged 47 commits into from
Sep 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e148554
Refactors resource creation to a separate function outside of the bac…
metroid-samus Sep 11, 2023
9d2bb76
Adds a button to the resources tab to initiate a retry for creating a…
metroid-samus Sep 19, 2023
de3f638
Adds a button to the resources tab to initiate a retry for creating a…
metroid-samus Sep 19, 2023
4883424
Fixes lint errors.
metroid-samus Sep 19, 2023
22fb3c6
Update src/dispatch/static/dispatch/src/case/ResourcesTab.vue
metroid-samus Sep 20, 2023
33c9c31
Plugin retrieval returns list of all enabled plugins instead of by in…
metroid-samus Sep 21, 2023
5d6f572
Fixes lint errors.
metroid-samus Sep 21, 2023
5e55ac9
Changes in client-side incident updates.
metroid-samus Sep 22, 2023
d17fe16
Removes success toast after resource creation.
metroid-samus Sep 22, 2023
dc1b7e8
Sets resource creation as a background task.
metroid-samus Sep 22, 2023
d3dd4a9
Bump jsonpath-ng from 1.5.3 to 1.6.0 (#3787)
dependabot[bot] Sep 19, 2023
7c248b6
Bump @playwright/test in /src/dispatch/static/dispatch (#3786)
dependabot[bot] Sep 19, 2023
56f5038
Bump google-api-python-client from 2.98.0 to 2.99.0 (#3784)
dependabot[bot] Sep 19, 2023
24f9059
Bump pdpyras from 5.1.1 to 5.1.2 (#3783)
dependabot[bot] Sep 19, 2023
154e487
Bump msal from 1.23.0 to 1.24.0 (#3782)
dependabot[bot] Sep 19, 2023
74d6da9
Bump sentry-sdk from 1.30.0 to 1.31.0 (#3781)
dependabot[bot] Sep 19, 2023
0eaf0e2
Do not run playwright with safar (#3797)
wssheldon Sep 20, 2023
0461a58
Appends outstanding incident tasks in tactical reports (#3798)
metroid-samus Sep 20, 2023
81d558e
Rework the way slack api errors are propagated (to the caller) (#3789)
kevgliss Sep 20, 2023
261de67
Only use stable priority if set (#3803)
whitdog47 Sep 21, 2023
219e0ef
Bump pandas from 2.1.0 to 2.1.1 (#3801)
dependabot[bot] Sep 21, 2023
9ff765d
Bump faker from 19.6.1 to 19.6.2 (#3800)
dependabot[bot] Sep 21, 2023
624c641
Bump numpy from 1.25.2 to 1.26.0 (#3794)
dependabot[bot] Sep 21, 2023
a771b8b
Bump google-api-python-client from 2.99.0 to 2.100.0 (#3793)
dependabot[bot] Sep 21, 2023
1b65590
Bump ruff from 0.0.289 to 0.0.290 (#3792)
dependabot[bot] Sep 21, 2023
06ccd3a
Making experience textbox from oncall end-of-shift feedback optional …
whitdog47 Sep 22, 2023
db874b3
Handles unexpected numbers of enabled plugins.
metroid-samus Sep 25, 2023
59ef45f
Adds front end polling for resource creation updates. Adds success no…
metroid-samus Sep 26, 2023
92fea99
Merge branch 'master' into enhancement/manual-resource-creation
metroid-samus Sep 26, 2023
a845967
Minor refactors for case and incident resource creation.
metroid-samus Sep 28, 2023
8204255
Bump google-api-python-client from 2.98.0 to 2.99.0 (#3784)
dependabot[bot] Sep 19, 2023
a36d4a0
Bump google-api-python-client from 2.100.0 to 2.101.0 (#3810)
dependabot[bot] Sep 27, 2023
f402a6f
Bump openai from 0.28.0 to 0.28.1 (#3809)
dependabot[bot] Sep 27, 2023
9b027c2
Bump ruff from 0.0.290 to 0.0.291 (#3808)
dependabot[bot] Sep 27, 2023
7cd1fcb
Bump eslint from 8.49.0 to 8.50.0 in /src/dispatch/static/dispatch (#…
dependabot[bot] Sep 27, 2023
23817bd
Revert "Making experience textbox from oncall end-of-shift feedback o…
whitdog47 Sep 28, 2023
f1ca893
Bump @playwright/test in /src/dispatch/static/dispatch (#3786)
dependabot[bot] Sep 19, 2023
81433b4
Update src/dispatch/case/views.py
metroid-samus Sep 28, 2023
2fd511f
Fixes lint error.
metroid-samus Sep 28, 2023
ce45d61
Bump @playwright/test in /src/dispatch/static/dispatch (#3786)
dependabot[bot] Sep 19, 2023
19b1319
Merge branch 'master' into enhancement/manual-resource-creation
metroid-samus Sep 28, 2023
c2ed3b3
Restores original package-lock file.
metroid-samus Sep 28, 2023
3ebb6c3
Removes irrelevant files.
metroid-samus Sep 28, 2023
e7f1c62
Removes irrelevant files.
metroid-samus Sep 28, 2023
423876a
Refactors converstion creation flow.
metroid-samus Sep 28, 2023
721a1bc
Fixes linting errors.
metroid-samus Sep 28, 2023
d4c2ac6
Merge branch 'master' into enhancement/manual-resource-creation
metroid-samus Sep 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(
metroid-samus marked this conversation as resolved.
Show resolved Hide resolved
"/{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
Loading