Skip to content

Destinations need to be decoupled better from Media-plugins #1792

@hmpf

Description

@hmpf

We currently have a destination for email that uses a plugin for email that talks SMTP. The destination has an email address in its setting-field in the DestinationConfig, the email server settings are in Django settings. If we are to support sending email via API, the easy way to do it would be to create a new media plugin with a new media slug which would need a new DestinationConfig with whatever the API needs in the setting-field. If we use apprise, it's something that looks like an url, not an email address.

Say we want to send email via AWS SES. Apprise supports this, but if we use an apprise url directly we will store AWS credentials in plain text accessible via the web... and each user will need their own AWS account. If we instead reuse the "email" DestinationConfig but have them use the "AWS SES" media plugin instead, we can have one AWS account with credentials 12 factored in an envvar, and the end-user only needs care about an email-address.

As per today, each media plugin has a slug hardcoded, Plugin.MEDIA_SLUG. We load media plugins via the "MEDIA_PLUGINS"-setting, a list of plugins in dotted path string format. We use the list to build a MEDIA_CLASSES_DICT of the format {Plugin.MEDIA_SLUG, Plugin}. We could do similarly as we have done with incident list columns: Add a setting "DESTINATIONS" (name to be argued about) of the format {"name_of_destination_type": dotted path string format}, and combine this and "MEDIA_PLUGINS" when building up the MEDIA_CLASSES_DICT. The stuff in "DESTINATIONS" would override the stuff set in "MEDIA_PLUGINS". We could then say that the "email" destination type is handed by the AWS SES plugin, not the included SMTP plugin. The AWS SES plugin would get a single email address from a DestinationConfig instance, and other credentials from Django settings.

AWS SES with apprise

If we use the apprise AWS SES-support, we could have settings of the form APPRISE_AWS_SES_FROM, APPRISE_AWS_SES_ACCESS_KEY, APPRISE_AWS_SES_SECRET_KEY, APPRISE_AWS_REGION or

APPRISE_AWS_SES = {
    "from": "a@b.ca",
    "access_key": "hjkkj",
    "secret_key": "gfhfh",
    "region": "eu-north-1",
}

or even a partial apprise url: APPRISE_AWS_SES_URL = "ses://a@b.ca/hjkkj/gfhfh/eu-north-1/".

Validation of the settings-field

For every type of destination where it makes sense to have a pluggable, replaceable backend, the code that deals with the contents of the settings-field (validation etc.) should be in its own mixin-class to be reused by plugin classes that have an actual implementation.

Compiling MEDIA_CLASSES_DICT

This is currently done directly in the module since it is a short one liner. It will be too complex for a one liner when merging info from MEDIA_PLUGINS and DESTINATIONS, so it should be a testable function instead, returning the finished MEDIA_CLASSES_DICT. Since MEDIA_CLASSES_DICT is a wholly internal name we could also rename it to something better.

The fate of MEDIA_SLUG

Rename MEDIA_SLUG to DEFAULT_MEDIA_SLUG. MEDIA_SLUG should be an instance attribute while DEFAULT_MEDIA_SLUG should be a class attribute. This also means that MEDIA_CLASSES_DICT should have instantiated classes.

When compiling media classes from MEDIA_PLUGINS, copy DEFAULT_MEDIA_SLUG to MEDIA_SLUG. To access the media slug from the plugin, have a method get_media_slug() (we could keep using MEDIA_SLUG if the class is always instantiated). When compiling media classes from DESTINATIONS, set MEDIA_SLUG to the destination key in the setting.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status

    📋 Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions