def get_organization_scope_from_slug(slug: str) -> SessionLocal: """Iterate all organizations looking for a relevant channel_id.""" db_session = SessionLocal() organization = organization_service.get_by_slug(db_session=db_session, slug=slug) db_session.close() if organization: schema_engine = engine.execution_options( schema_translate_map={ None: f"dispatch_organization_{slug}", }) return sessionmaker(bind=schema_engine)() raise ValidationError( [ ErrorWrapper( NotFoundError( msg= f"Organization slug '{slug}' not found. Check your spelling." ), loc="organization", ) ], model=BaseModel, )
def remove_participant(user_email: str, incident: Incident, db_session: SessionLocal): """Removes a participant.""" inactivated = inactivate_participant(user_email, incident, db_session) if inactivated: participant = get_by_incident_id_and_email(db_session=db_session, incident_id=incident.id, email=user_email) log.debug( f"Removing {participant.individual.name} from {incident.name} incident..." ) participant.service = None db_session.add(participant) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description=f"{participant.individual.name} has been removed", incident_id=incident.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 get_default_organization_scope() -> str: """Iterate all organizations looking for matching organization.""" db_session = SessionLocal() organization = organization_service.get_default(db_session=db_session) db_session.close() schema_engine = engine.execution_options( schema_translate_map={ None: f"dispatch_organization_{organization.slug}", }) return sessionmaker(bind=schema_engine)()
def calculate_incidents_response_cost(db_session: SessionLocal, project: Project): """Calculates and saves the response cost for all incidents.""" response_cost_type = incident_cost_type_service.get_default( db_session=db_session, project_id=project.id) if response_cost_type is None: log.warning( f"A default cost type for response cost does not exist in the {project.name} project. Response costs won't be calculated." ) return # we want to update the response cost of all incidents, all the time incidents = incident_service.get_all(db_session=db_session, project_id=project.id) for incident in incidents: try: # we get the response cost for the given incident incident_response_cost = get_by_incident_id_and_incident_cost_type_id( db_session=db_session, incident_id=incident.id, incident_cost_type_id=response_cost_type.id, ) if incident_response_cost is None: # we create the response cost if it doesn't exist incident_cost_type = IncidentCostTypeRead.from_orm( response_cost_type) incident_cost_in = IncidentCostCreate( incident_cost_type=incident_cost_type, project=project) incident_response_cost = create( db_session=db_session, incident_cost_in=incident_cost_in) # we calculate the response cost amount amount = calculate_incident_response_cost(incident.id, db_session) # we don't need to update the cost amount if it hasn't changed if incident_response_cost.amount == amount: continue # we save the new incident cost amount incident_response_cost.amount = amount incident.incident_costs.append(incident_response_cost) db_session.add(incident) db_session.commit() log.debug( f"Response cost amount for {incident.name} incident has been updated in the database." ) except Exception as e: # we shouldn't fail to update all incidents when one fails log.exception(e)
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 remove_participant(user_email: str, incident_id: int, db_session: SessionLocal): """Removes a participant.""" # We load the incident incident = incident_service.get(db_session=db_session, incident_id=incident_id) # We get information about the individual contact_plugin = plugin_service.get_active(db_session=db_session, plugin_type="contact") individual_info = contact_plugin.instance.get(user_email) individual_fullname = individual_info["fullname"] log.debug( f"Removing {individual_fullname} from 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"Can't remove {individual_fullname}. They're not an active participant of incident {incident.name}." ) return False # We mark the participant as inactive participant.is_active = False # We make the participant renounce to their active roles participant_active_roles = participant_role_service.get_all_active_roles( db_session=db_session, participant_id=participant.id) for participant_active_role in participant_active_roles: participant_role_service.renounce_role( db_session=db_session, participant_role=participant_active_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"{participant.individual.name} removed from incident", incident_id=incident_id, ) return True
def reactivate_participant(user_email: str, incident_id: int, db_session: SessionLocal): """Reactivates a participant.""" # We load the incident incident = incident_service.get(db_session=db_session, incident_id=incident_id) # We get information about the individual contact_plugin = plugin_service.get_active(db_session=db_session, 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 list_plugins(): """Shows all available plugins.""" from tabulate import tabulate from dispatch.database.core import SessionLocal from dispatch.plugin import service as plugin_service db_session = SessionLocal() table = [] for record in plugin_service.get_all(db_session=db_session): table.append([ record.title, record.slug, record.version, record.type, record.author, record.description, ]) click.secho( tabulate( table, headers=[ "Title", "Slug", "Version", "Type", "Author", "Description", ], ), fg="blue", )
async def process(client: SocketModeClient, req: SocketModeRequest): db_session = SessionLocal() background_tasks = BackgroundTasks() if req.type == "events_api": response = await handle_slack_event( db_session=db_session, client=client.web_client, event=EventEnvelope(**req.payload), background_tasks=background_tasks, ) if req.type == "slash_commands": response = await handle_slack_command( db_session=db_session, client=client.web_client, request=req.payload, background_tasks=background_tasks, ) if req.type == "interactive": response = await handle_slack_action( db_session=db_session, client=client.web_client, request=req.payload, background_tasks=background_tasks, ) response = SocketModeResponse(envelope_id=req.envelope_id, payload=response) await client.send_socket_mode_response(response) # run the background tasks await background_tasks()
def sync_document_terms(db_session: SessionLocal, project: Project): """Performs term extraction from known documents.""" p = plugin_service.get_active_instance( db_session=db_session, plugin_type="storage", project_id=project.id ) if not p: log.debug("Tried to sync document terms but couldn't find any active storage plugins.") return terms = term_service.get_all(db_session=db_session, project_id=project.id).all() log.debug(f"Fetched {len(terms)} terms from database.") term_strings = [t.text.lower() for t in terms if t.discoverable] phrases = build_term_vocab(term_strings) matcher = build_phrase_matcher("dispatch-term", phrases) documents = get_all(db_session=db_session) for doc in documents: log.debug(f"Processing document. Name: {doc.name}") try: if "sheet" in doc.resource_type: mime_type = "text/csv" else: mime_type = "text/plain" doc_text = p.instance.get(doc.resource_id, mime_type) extracted_terms = list(set(extract_terms_from_text(doc_text, matcher))) matched_terms = ( db_session.query(Term) .filter(func.upper(Term.text).in_([func.upper(t) for t in extracted_terms])) .all() ) log.debug(f"Extracted the following terms from {doc.weblink}. Terms: {extracted_terms}") if matched_terms: doc.terms = matched_terms db_session.commit() except Exception as e: # even if one document fails we don't want them to all fail log.exception(e)
def db(): if database_exists(str(config.SQLALCHEMY_DATABASE_URI)): drop_database(str(config.SQLALCHEMY_DATABASE_URI)) create_database(str(config.SQLALCHEMY_DATABASE_URI)) Base.metadata.create_all(engine) # Create the tables. _db = SessionLocal() yield _db drop_database(str(config.SQLALCHEMY_DATABASE_URI))
def reactivate_participant(user_email: str, incident: Incident, db_session: SessionLocal, service_id: int = None): """Reactivates a participant.""" participant = get_by_incident_id_and_email(db_session=db_session, incident_id=incident.id, email=user_email) if not participant: log.debug( f"{user_email} is not an inactive participant of {incident.name} incident." ) return False log.debug( f"Reactivating {participant.individual.name} on {incident.name} incident..." ) # we get the last active role participant_role = participant_role_service.get_last_active_role( db_session=db_session, participant_id=participant.id) # we create a new role based on the last active role participant_role_in = ParticipantRoleCreate(role=participant_role.role) participant_role = participant_role_service.create( db_session=db_session, participant_role_in=participant_role_in) participant.participant_roles.append(participant_role) if service_id: service = service_service.get(db_session=db_session, service_id=service_id) participant.service = service db_session.add(participant) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description=f"{participant.individual.name} has been reactivated", incident_id=incident.id, ) return True
def create_reminder( db_session: SessionLocal, project: Project, owner_email: str, documents: List[Document] ): """Contains the logic for document evergreen reminders.""" # send email contact_fullname = contact_weblink = DISPATCH_HELP_EMAIL plugin = plugin_service.get_active_instance( db_session=db_session, plugin_type="email", project_id=project.id ) if not plugin: log.warning("Document reminder not sent, no email plugin enabled.") return notification_template = DOCUMENT_EVERGREEN_REMINDER items = [] for doc in documents: items.append( { "name": doc.name, "description": doc.description, "weblink": doc.weblink, } ) notification_type = "document-evergreen-reminder" name = subject = notification_text = "Document Evergreen Reminder" plugin.instance.send( owner_email, notification_text, notification_template, notification_type, name=name, subject=subject, contact_fullname=contact_fullname, contact_weblink=contact_weblink, items=items, # plugin expect dicts ) for doc in documents: doc.evergreen_last_reminder_at = datetime.utcnow() db_session.add(doc) db_session.commit()
def add_participant( user_email: str, incident: Incident, db_session: SessionLocal, service_id: int = None, role: ParticipantRoleType = ParticipantRoleType.participant, ): """Adds a participant.""" # we get or create a new individual individual = individual_service.get_or_create(db_session=db_session, incident=incident, email=user_email) # we get or create a new participant participant_role = ParticipantRoleCreate(role=role) participant = get_or_create( db_session=db_session, incident_id=incident.id, individual_id=individual.id, service_id=service_id, participant_roles=[participant_role], ) individual.participant.append(participant) incident.participants.append(participant) # we update the commander, reporter, scribe, or liaison foreign key if role == ParticipantRoleType.incident_commander: incident.commander_id = participant.id incident.commanders_location = participant.location elif role == ParticipantRoleType.reporter: incident.reporter_id = participant.id incident.reporters_location = participant.location elif role == ParticipantRoleType.scribe: incident.scribe_id = participant.id elif role == ParticipantRoleType.liaison: incident.liaison_id = participant.id # we add and commit the changes db_session.add(participant) db_session.add(individual) db_session.add(incident) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description= f"{individual.name} added to incident with {participant_role.role} role", incident_id=incident.id, ) return participant
def auto_tagger(db_session: SessionLocal, project: Project): """Attempts to take existing tags and associate them with incidents.""" tags = tag_service.get_all(db_session=db_session, project_id=project.id).all() log.debug(f"Fetched {len(tags)} tags from database.") tag_strings = [t.name.lower() for t in tags if t.discoverable] phrases = build_term_vocab(tag_strings) matcher = build_phrase_matcher("dispatch-tag", phrases) for incident in get_all(db_session=db_session, project_id=project.id).all(): plugin = plugin_service.get_active_instance( db_session=db_session, project_id=incident.project.id, plugin_type="storage" ) log.debug(f"Processing incident. Name: {incident.name}") doc = incident.incident_document if doc: try: mime_type = "text/plain" text = plugin.instance.get(doc.resource_id, mime_type) except Exception as e: log.debug(f"Failed to get document. Reason: {e}") log.exception(e) continue extracted_tags = list(set(extract_terms_from_text(text, matcher))) matched_tags = ( db_session.query(Tag) .filter(func.upper(Tag.name).in_([func.upper(t) for t in extracted_tags])) .all() ) incident.tags.extend(matched_tags) db_session.commit() log.debug( f"Associating tags with incident. Incident: {incident.name}, Tags: {extracted_tags}" )
def get_organization_scope_from_channel_id(channel_id: str) -> SessionLocal: """Iterate all organizations looking for a relevant channel_id.""" db_session = SessionLocal() organization_slugs = [ o.slug for o in organization_service.get_all(db_session=db_session) ] db_session.close() for slug in organization_slugs: schema_engine = engine.execution_options( schema_translate_map={ None: f"dispatch_organization_{slug}", }) scoped_db_session = sessionmaker(bind=schema_engine)() conversation = conversation_service.get_by_channel_id_ignoring_channel_type( db_session=scoped_db_session, channel_id=channel_id) if conversation: return scoped_db_session scoped_db_session.close()
def update_user(email: str, role: str): """Updates a user's roles.""" from dispatch.database.core import SessionLocal from dispatch.auth import service as user_service from dispatch.auth.models import UserUpdate db_session = SessionLocal() user = user_service.get_by_email(email=email, db_session=db_session) if not user: click.secho(f"No user found. Email: {email}", fg="red") return user_service.update(user=user, user_in=UserUpdate(id=user.id, role=role), db_session=db_session) click.secho("User successfully updated.", fg="green")
def uninstall_plugins(plugins): """Uninstalls all plugins, or only one.""" from dispatch.database.core import SessionLocal from dispatch.plugin import service as plugin_service db_session = SessionLocal() for plugin_slug in plugins: plugin = plugin_service.get_by_slug(db_session=db_session, slug=plugin_slug) if not plugin: click.secho( f"Plugin slug {plugin_slug} does not exist. Make sure you're passing the plugin's slug.", fg="red", ) plugin_service.delete(db_session=db_session, plugin_id=plugin.id)
def wrapper(*args, **kwargs): background = False if not kwargs.get("db_session"): db_session = SessionLocal() background = True kwargs["db_session"] = db_session if not kwargs.get("slack_client"): slack_client = dispatch_slack_service.create_slack_client() kwargs["slack_client"] = slack_client try: metrics_provider.counter("function.call.counter", tags={ "function": fullname(func), "slack": True }) start = time.perf_counter() result = func(*args, **kwargs) elapsed_time = time.perf_counter() - start metrics_provider.timer( "function.elapsed.time", value=elapsed_time, tags={ "function": fullname(func), "slack": True }, ) return result except Exception as e: # we generate our own guid for now, maybe slack provides us something we can use? slack_interaction_guid = str(uuid.uuid4()) log.exception( e, extra=dict(slack_interaction_guid=slack_interaction_guid)) # notify the user the interaction failed user_id = args[0] channel_id = args[2] message = f"Sorry, we've run into an unexpected error. For help, please reach out to the incident commander and provide them with the following token: {slack_interaction_guid}." dispatch_slack_service.send_ephemeral_message( kwargs["slack_client"], channel_id, user_id, message) finally: if background: kwargs["db_session"].close()
def install_plugins(force): """Installs all plugins, or only one.""" from dispatch.database.core import SessionLocal from dispatch.plugin import service as plugin_service from dispatch.plugin.models import Plugin from dispatch.common.utils.cli import install_plugins from dispatch.plugins.base import plugins install_plugins() db_session = SessionLocal() for p in plugins.all(): record = plugin_service.get_by_slug(db_session=db_session, slug=p.slug) if not record: click.secho( f"Installing plugin... Slug: {p.slug} Version: {p.version}", fg="blue") record = Plugin( title=p.title, slug=p.slug, type=p.type, version=p.version, author=p.author, author_url=p.author_url, multiple=p.multiple, description=p.description, ) db_session.add(record) if force: click.secho( f"Updating plugin... Slug: {p.slug} Version: {p.version}", fg="blue") # we only update values that should change record.title = p.title record.version = p.version record.author = p.author record.author_url = p.author_url record.description = p.description record.type = p.type db_session.add(record) db_session.commit()
def init_database(): """Initializes a new database.""" from sqlalchemy_utils import create_database, database_exists from dispatch.database.core import SessionLocal from dispatch.organization.models import OrganizationCreate from dispatch.organization import service as organization_service from dispatch.project.models import ProjectCreate from dispatch.project import service as project_service db_session = SessionLocal() if not database_exists(str(config.SQLALCHEMY_DATABASE_URI)): create_database(str(config.SQLALCHEMY_DATABASE_URI)) Base.metadata.create_all(engine) alembic_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "alembic.ini") alembic_cfg = AlembicConfig(alembic_path) alembic_command.stamp(alembic_cfg, "head") sync_triggers() # create any required default values in database # default organization click.secho("Creating default organization...", fg="blue") default_org = organization_service.get_or_create( db_session=db_session, organization_in=OrganizationCreate( name="default", default=True, description="Default dispatch organization.", ), ) click.secho("Creating default project...", fg="blue") project_service.get_or_create( db_session=db_session, project_in=ProjectCreate( name="default", default=True, description="Default dispatch project.", organization=default_org, ), ) click.secho("Success.", fg="green")
def add_participant( user_email: str, incident: Incident, db_session: SessionLocal, service_id: int = None, role: ParticipantRoleType = ParticipantRoleType.participant, ): """Adds a participant.""" # We get or create a new individual individual = individual_service.get_or_create(db_session=db_session, incident=incident, email=user_email) # We get or create a new participant participant_role = ParticipantRoleCreate(role=role) participant = get_or_create( db_session=db_session, incident_id=incident.id, individual_id=individual.id, service_id=service_id, participant_roles=[participant_role], ) individual.participant.append(participant) incident.participants.append(participant) # We add and commit the changes db_session.add(participant) db_session.add(individual) db_session.add(incident) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description= f"{individual.name} added to incident with {participant_role.role} role", incident_id=incident.id, ) return participant
def list_plugins(): """Shows all available plugins""" from dispatch.database.core import SessionLocal from dispatch.plugin import service as plugin_service db_session = SessionLocal() table = [] for p in plugins.all(): record = plugin_service.get_by_slug(db_session=db_session, slug=p.slug) if not record: log.warning( f"Plugin {p.slug} available, but not installed. Run `dispatch plugins install` to install it." ) continue table.append( [ record.title, record.slug, record.version, record.enabled, record.type, record.author, record.description, ] ) click.secho( tabulate( table, headers=[ "Title", "Slug", "Version", "Enabled", "Type", "Author", "Description", ], ), fg="blue", )
def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column("incident_cost_type", sa.Column("category", sa.String(), nullable=True)) # we set the category of the default response incident cost type db_session = SessionLocal() incident_cost_type = incident_cost_type_service.get_default( db_session=db_session) if incident_cost_type: incident_cost_type_in = IncidentCostTypeUpdate( id=incident_cost_type.id, name=incident_cost_type.name, category="Primary") incident_cost_type_service.update( db_session=db_session, incident_cost_type=incident_cost_type, incident_cost_type_in=incident_cost_type_in, )
class Meta: """Factory configuration.""" abstract = True sqlalchemy_session = SessionLocal() sqlalchemy_session_persistence = "commit"
def list_tasks(client: Any, file_id: str): """Returns all tasks in file.""" doc = get_file(client, file_id) document_meta = {"document": {"id": file_id, "name": doc["name"]}} all_comments = list_comments(client, file_id) task_comments = filter_comments(all_comments) tasks = [] for t in task_comments: status = get_task_status(t) assignees = [{ "individual": { "email": x } } for x in get_assignees(t["content"])] description = t.get("quotedFileContent", {}).get("value", "") tickets = get_tickets(t["replies"]) task_meta = { "task": { "resource_id": t["id"], "description": description, "created_at": t["createdTime"], "assignees": assignees, "tickets": tickets, "weblink": f'https://docs.google.com/a/{GOOGLE_DOMAIN}/document/d/{file_id}/edit?disco={t["id"]}', } } # this is a dirty hack because google doesn't return emailAddresses for comments # complete with conflicting docs # https://developers.google.com/drive/api/v2/reference/comments#resource from dispatch.database.core import SessionLocal from dispatch.individual.models import IndividualContact db_session = SessionLocal() owner = (db_session.query(IndividualContact).filter( IndividualContact.name == t["author"]["displayName"]).first()) if owner: task_meta["task"].update( {"owner": { "individual": { "email": owner.email } }}) db_session.close() task_meta["task"].update(status) tasks.append({**document_meta, **task_meta}) return tasks
def assign_role_flow(incident: "Incident", assignee_email: str, assignee_role: str, db_session: SessionLocal): """Attempts to assign a role to a participant. Returns: str: - "role_assigned", if role assigned. - "role_not_assigned", if not role assigned. - "assignee_has_role", if assignee already has the role. """ # we get the participant that holds the role assigned to the assignee participant_with_assignee_role = participant_service.get_by_incident_id_and_role( db_session=db_session, incident_id=incident.id, role=assignee_role) # we get the participant for the assignee assignee_participant = participant_service.get_by_incident_id_and_email( db_session=db_session, incident_id=incident.id, email=assignee_email) if participant_with_assignee_role is assignee_participant: return "assignee_has_role" if participant_with_assignee_role: # we make the participant renounce to the role that has been given to the assignee participant_active_roles = get_all_active_roles( db_session=db_session, participant_id=participant_with_assignee_role.id) for participant_active_role in participant_active_roles: if participant_active_role.role == assignee_role: renounce_role(db_session=db_session, participant_role=participant_active_role) break # we check if the participant has other active roles participant_active_roles = get_all_active_roles( db_session=db_session, participant_id=participant_with_assignee_role.id) if participant_active_roles.count() == 0: # we give the participant a new participant role add_role( db_session=db_session, participant_id=participant_with_assignee_role.id, participant_role=ParticipantRoleType.participant, ) log.debug( f"We made {participant_with_assignee_role.individual.name} renounce to their {assignee_role} role." ) if assignee_participant: # we make the assignee renounce to the participant role, if they have it participant_active_roles = get_all_active_roles( db_session=db_session, participant_id=assignee_participant.id) for participant_active_role in participant_active_roles: if participant_active_role.role == ParticipantRoleType.participant: renounce_role(db_session=db_session, participant_role=participant_active_role) break # we give the assignee the new role add_role( db_session=db_session, participant_id=assignee_participant.id, participant_role=assignee_role, ) # we update the commander, reporter, scribe, or liaison foreign key if assignee_role == ParticipantRoleType.incident_commander: incident.commander_id = assignee_participant.id elif assignee_role == ParticipantRoleType.reporter: incident.reporter_id = assignee_participant.id elif assignee_role == ParticipantRoleType.scribe: incident.scribe_id = assignee_participant.id elif assignee_role == ParticipantRoleType.liaison: incident.liaison_id = assignee_participant.id # we add and commit the changes db_session.add(incident) db_session.commit() event_service.log( db_session=db_session, source="Dispatch Core App", description= f"{assignee_participant.individual.name} has been assigned the role of {assignee_role}", incident_id=incident.id, ) return "role_assigned" log.debug( f"We were not able to assign the {assignee_role} role to {assignee_email}." ) return "role_not_assigned"