Skip to content

Commit

Permalink
Merge with master
Browse files Browse the repository at this point in the history
  • Loading branch information
whitdog47 committed Sep 29, 2023
2 parents 417d581 + 8dfae58 commit bc6e2a6
Show file tree
Hide file tree
Showing 29 changed files with 779 additions and 262 deletions.
12 changes: 6 additions & 6 deletions requirements-base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,15 @@ email-validator==2.0.0.post2
# via -r requirements-base.in
emails==0.6
# via -r requirements-base.in
fastapi==0.103.1
fastapi==0.103.2
# via -r requirements-base.in
frozenlist==1.4.0
# via
# aiohttp
# aiosignal
google-api-core==2.11.1
# via google-api-python-client
google-api-python-client==2.100.0
google-api-python-client==2.101.0
# via -r requirements-base.in
google-auth==2.22.0
# via
Expand Down Expand Up @@ -207,7 +207,7 @@ markupsafe==2.1.3
# jinja2
# mako
# werkzeug
msal==1.24.0
msal==1.24.1
# via -r requirements-base.in
multidict==6.0.4
# via
Expand Down Expand Up @@ -235,7 +235,7 @@ oauthlib[signedtoken]==3.2.2
# atlassian-python-api
# jira
# requests-oauthlib
openai==0.28.0
openai==0.28.1
# via -r requirements-base.in
packaging==23.1
# via
Expand Down Expand Up @@ -272,7 +272,7 @@ protobuf==4.24.3
# -r requirements-base.in
# google-api-core
# googleapis-common-protos
psycopg2-binary==2.9.7
psycopg2-binary==2.9.8
# via -r requirements-base.in
pyasn1==0.5.0
# via
Expand All @@ -286,7 +286,7 @@ pyasn1-modules==0.3.0
# oauth2client
pycparser==2.21
# via cffi
pydantic==1.10.12
pydantic==1.10.13
# via
# -r requirements-base.in
# blockkit
Expand Down
4 changes: 2 additions & 2 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ identify==2.5.27
# via pre-commit
iniconfig==2.0.0
# via pytest
ipython==8.15.0
ipython==8.16.0
# via -r requirements-dev.in
jedi==0.19.0
# via ipython
Expand Down Expand Up @@ -90,7 +90,7 @@ python-dateutil==2.8.2
# via faker
pyyaml==6.0.1
# via pre-commit
ruff==0.0.290
ruff==0.0.291
# via -r requirements-dev.in
six==1.16.0
# via
Expand Down
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 bc6e2a6

Please sign in to comment.