This repository has been archived on 2020-03-24. You can view files and clone it, but cannot push or open issues or pull requests.
quay/endpoints/notificationmethod.py
Joseph Schorr 54ee94754e - Add support for orgs in the entity search and the notification system
- Fix the titles/names of the different notification types
- Fix the styling of the options buttons on the notifications
2014-07-22 13:39:41 -04:00

152 lines
4.3 KiB
Python

import logging
import io
import os.path
import tarfile
import base64
import json
from flask.ext.mail import Message
from app import mail, app
from data import model
logger = logging.getLogger(__name__)
class InvalidNotificationMethodException(Exception):
pass
class NotificationMethod(object):
def __init__(self):
pass
@classmethod
def method_name(cls):
"""
Particular method implemented by subclasses.
"""
raise NotImplementedError
def perform(self, notification, event_handler, notification_data):
"""
Performs the notification method.
notification: The noticication record itself.
event_handler: The NotificationEvent handler.
notification_data: The dict of notification data placed in the queue.
"""
raise NotImplementedError
@classmethod
def get_method(cls, methodname):
for subc in cls.__subclasses__():
if subc.method_name() == methodname:
return subc()
raise InvalidNotificationMethodException('Unable to find method: %s' % methodname)
class QuayNotificationMethod(NotificationMethod):
@classmethod
def method_name(cls):
return 'quay_notification'
def perform(self, notification, event_handler, notification_data):
config_data = json.loads(notification.config_json)
repository_id = notification_data['repository_id']
repository = model.lookup_repository(repository_id)
if not repository:
# Probably deleted.
return True
# Lookup the target user or team to which we'll send the notification.
target_info = config_data['target']
target_users = []
if target_info['kind'] == 'user':
target = model.get_user(target_info['name'])
if not target:
# Just to be safe.
return True
target_users.append(target)
elif target_info['kind'] == 'org':
target = model.get_organization(target_info['name'])
if not target:
# Just to be safe.
return True
# Only repositories under the organization can cause notifications to that org.
if target_info['name'] != repository.namespace:
return False
target_users.append(target)
elif target_info['kind'] == 'team':
# Lookup the team.
team = None
try:
team = model.get_organization_team(repository.namespace, target_info['name'])
except model.InvalidTeamException:
# Probably deleted.
return True
# Lookup the team's members
target_users = model.get_organization_team_members(team.id)
# For each of the target users, create a notification.
for target_user in set(target_users):
model.create_notification(event_handler.event_name(), target_user,
metadata=notification_data['event_data'])
return True
class EmailMethod(NotificationMethod):
@classmethod
def method_name(cls):
return 'email'
def perform(self, notification, event_handler, notification_data):
config_data = json.loads(notification.config_json)
email = config_data.get('email', '')
if not email:
return False
msg = Message(event_handler.get_summary(notification_data['event_data'], notification_data),
sender='support@quay.io',
recipients=[email])
msg.html = event_handler.get_message(notification_data['event_data'], notification_data)
try:
with app.app_context():
mail.send(msg)
except Exception as ex:
logger.exception('Email was unable to be sent: %s' % ex.message)
return False
return True
class WebhookMethod(NotificationMethod):
@classmethod
def method_name(cls):
return 'webhook'
def perform(self, notification, event_handler, notification_data):
config_data = json.loads(notification.config_json)
url = config_data.get('url', '')
if not url:
return False
payload = notification_data['event_data']
headers = {'Content-type': 'application/json'}
try:
resp = requests.post(url, data=json.dumps(payload), headers=headers)
if resp.status_code/100 != 2:
logger.error('%s response for webhook to url: %s' % (resp.status_code,
url))
return False
except requests.exceptions.RequestException as ex:
logger.exception('Webhook was unable to be sent: %s' % ex.message)
return False
return True