Skip to content

Commit

Permalink
Custom routes + Further notification cleanup (#309)
Browse files Browse the repository at this point in the history
* Further notification cleanup

* Catch any errors getting the user for metrics + add doc for INIT_CUSTOM_ROUTES

* Revert change to _build_metrics
  • Loading branch information
ttannis authored Oct 14, 2019
1 parent f7fc132 commit 213ec0d
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 77 deletions.
4 changes: 4 additions & 0 deletions frontend/amundsen_application/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,8 @@ def create_app(config_module_class: str, template_folder: str = None) -> Flask:
app.register_blueprint(search_blueprint)
init_routes(app)

init_custom_routes = app.config.get('INIT_CUSTOM_ROUTES')
if init_custom_routes:
init_custom_routes(app)

return app
43 changes: 33 additions & 10 deletions frontend/amundsen_application/api/utils/notification_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging

from http import HTTPStatus
from enum import Enum

from flask import current_app as app
from flask import jsonify, make_response, Response
Expand All @@ -9,8 +10,27 @@
from amundsen_application.api.exceptions import MailClientNotImplemented
from amundsen_application.log.action_log import action_logging


class NotificationType(str, Enum):
"""
Enum to describe supported notification types. Must match NotificationType interface defined in:
https://github.com/lyft/amundsenfrontendlibrary/blob/master/amundsen_application/static/js/interfaces/Notifications.ts
"""
OWNER_ADDED = 'owner_added'
OWNER_REMOVED = 'owner_removed'
METADATA_EDITED = 'metadata_edited'
METADATA_REQUESTED = 'metadata_requested'

@classmethod
def has_value(cls, value: str) -> bool:
for key in cls:
if key.value == value:
return True
return False


NOTIFICATION_STRINGS = {
'added': {
NotificationType.OWNER_ADDED.value: {
'comment': ('<br/>What is expected of you?<br/>As an owner, you take an important part in making '
'sure that the datasets you own can be used as swiftly as possible across the company.<br/>'
'Make sure the metadata is correct and up to date.<br/>'),
Expand All @@ -20,14 +40,14 @@
'notification': ('<br/>You have been added to the owners list of the <a href="{resource_url}">'
'{resource_name}</a> dataset by {sender}.<br/>'),
},
'removed': {
NotificationType.OWNER_REMOVED.value: {
'comment': '',
'end_note': ('<br/>If you think you have been incorrectly removed as an owner, '
'add yourself back to the owners list.<br/>'),
'notification': ('<br/>You have been removed from the owners list of the <a href="{resource_url}">'
'{resource_name}</a> dataset by {sender}.<br/>'),
},
'requested': {
NotificationType.METADATA_REQUESTED.value: {
'comment': '',
'end_note': '<br/>Please visit the provided link and improve descriptions on that resource.<br/>',
'notification': '<br/>{sender} is trying to use <a href="{resource_url}">{resource_name}</a>, ',
Expand Down Expand Up @@ -84,7 +104,7 @@ def get_notification_html(*, notification_type: str, options: Dict, sender: str)
end_note = notification_strings.get('end_note', '')
salutation = '<br/>Thanks,<br/>Amundsen Team'

if notification_type == 'requested':
if notification_type == NotificationType.METADATA_REQUESTED:
options_comment = options.get('comment')
need_resource_description = options.get('description_requested')
need_fields_descriptions = options.get('fields_requested')
Expand Down Expand Up @@ -118,12 +138,15 @@ def get_notification_subject(*, notification_type: str, options: Dict) -> str:
"""
resource_name = options.get('resource_name')
notification_subject_dict = {
'added': 'You are now an owner of {}'.format(resource_name),
'removed': 'You have been removed as an owner of {}'.format(resource_name),
'edited': 'Your dataset {}\'s metadata has been edited'.format(resource_name),
'requested': 'Request for metadata on {}'.format(resource_name),
NotificationType.OWNER_ADDED.value: 'You are now an owner of {}'.format(resource_name),
NotificationType.OWNER_REMOVED.value: 'You have been removed as an owner of {}'.format(resource_name),
NotificationType.METADATA_EDITED.value: 'Your dataset {}\'s metadata has been edited'.format(resource_name),
NotificationType.METADATA_REQUESTED.value: 'Request for metadata on {}'.format(resource_name),
}
return notification_subject_dict.get(notification_type, '')
subject = notification_subject_dict.get(notification_type)
if subject is None:
raise Exception('Unsupported notification_type')
return subject


def send_notification(*, notification_type: str, options: Dict, recipients: List, sender: str) -> Response:
Expand Down Expand Up @@ -174,7 +197,7 @@ def _log_send_notification(*, notification_type: str, options: Dict, recipients:
subject=subject,
html=html,
optional_data={
'email_type': 'notification'
'email_type': notification_type,
},
)
status_code = response.status_code
Expand Down
8 changes: 7 additions & 1 deletion frontend/amundsen_application/config.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import os
from typing import Dict, Optional, Set # noqa: F401
from typing import Callable, Dict, Optional, Set # noqa: F401

from flask import Flask # noqa: F401

from amundsen_application.tests.test_utils import get_test_user


Expand All @@ -22,6 +25,9 @@ class Config:
MAIL_CLIENT = None
NOTIFICATIONS_ENABLED = False

# Initialize custom routes
INIT_CUSTOM_ROUTES = None # type: Callable[[Flask], None]


class LocalConfig(Config):
DEBUG = False
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// TODO: Remove notification types that can be triggered in flask layer if necessary
export enum NotificationType {
OWNER_ADDED = 'added',
OWNER_REMOVED = 'removed',
METADATA_EDITED = 'edited',
METADATA_REQUESTED = 'requested',
OWNER_ADDED = 'owner_added',
OWNER_REMOVED = 'owner_removed',
METADATA_EDITED = 'metadata_edited',
METADATA_REQUESTED = 'metadata_requested',
}

export enum RequestMetadataType {
Expand Down
12 changes: 12 additions & 0 deletions frontend/docs/flask_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ After modifying any variable in [config.py](https://github.com/lyft/amundsenfron

**NOTE: This document is a work in progress and does not include 100% of features. We welcome PRs to complete this document**

## Custom Routes
In order to add any custom Flask endpoints to Amundsen's frontend application, configure a function on the `INIT_CUSTOM_ROUTES` variable. This function takes the created Flask application and can leverage Flask's [add_url_rule](https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.add_url_rule) method to add custom routes.

Example: Setting `INIT_CUSTOM_ROUTES` to the `init_custom_routes` method below will expose a `/custom_route` endpoint on the frontend application.
```bash
def init_custom_routes(app: Flask) -> None:
app.add_url_rule('/custom_route', 'custom_route', custom_route)

def custom_route():
pass
```

## Mail Client Features
Amundsen has two features that leverage the custom mail client -- the feedback tool and notifications. For these features a custom implementation of [base_mail_client](https://github.com/lyft/amundsenfrontendlibrary/blob/master/amundsen_application/base/base_mail_client.py) must be mapped to the `MAIL_CLIENT` configuration variable.

Expand Down
Loading

0 comments on commit 213ec0d

Please sign in to comment.