예제 #1
0
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,
    )
예제 #2
0
파일: flows.py 프로젝트: Netflix/dispatch
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,
        )
예제 #3
0
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()
예제 #4
0
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)()
예제 #5
0
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)
예제 #6
0
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}")
예제 #7
0
파일: flows.py 프로젝트: terry-sm/dispatch
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
예제 #8
0
파일: flows.py 프로젝트: terry-sm/dispatch
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
예제 #9
0
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",
    )
예제 #10
0
    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()
예제 #11
0
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)
예제 #12
0
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))
예제 #13
0
파일: flows.py 프로젝트: Netflix/dispatch
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
예제 #14
0
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()
예제 #15
0
파일: flows.py 프로젝트: Netflix/dispatch
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
예제 #16
0
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}"
            )
예제 #17
0
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()
예제 #18
0
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")
예제 #19
0
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)
예제 #20
0
    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()
예제 #21
0
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()
예제 #22
0
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")
예제 #23
0
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
예제 #24
0
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",
    )
예제 #25
0
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,
        )
예제 #26
0
    class Meta:
        """Factory configuration."""

        abstract = True
        sqlalchemy_session = SessionLocal()
        sqlalchemy_session_persistence = "commit"
예제 #27
0
파일: task.py 프로젝트: wuchong718/dispatch
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
예제 #28
0
파일: flows.py 프로젝트: Netflix/dispatch
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"