Merge pull request #827 from dod-ccpo/stig-notifications

Create Notification System
This commit is contained in:
richard-dds
2019-05-20 09:51:09 -04:00
committed by GitHub
12 changed files with 159 additions and 7 deletions

View File

@@ -29,6 +29,7 @@ from atst.utils import mailer
from atst.utils.form_cache import FormCache
from atst.utils.json import CustomJSONEncoder
from atst.queue import queue
from atst.utils.notification_sender import NotificationSender
from logging.config import dictConfig
from atst.utils.logging import JsonFormatter, RequestContextFilter
@@ -63,6 +64,7 @@ def make_app(config):
make_csp_provider(app)
make_crl_validator(app)
make_mailer(app)
make_notification_sender(app)
queue.init_app(app)
db.init_app(app)
@@ -247,6 +249,10 @@ def make_mailer(app):
app.mailer = mailer.Mailer(mailer_connection, sender)
def make_notification_sender(app):
app.notification_sender = NotificationSender(queue)
def apply_json_logger():
dictConfig(
{

View File

@@ -17,5 +17,6 @@ from .portfolio_invitation import PortfolioInvitation
from .application_invitation import ApplicationInvitation
from .task_order import TaskOrder
from .dd_254 import DD254
from .notification_recipient import NotificationRecipient
from .mixins.invites import Status as InvitationStatus

View File

@@ -0,0 +1,10 @@
from sqlalchemy import String, Column
from atst.models import Base, types, mixins
class NotificationRecipient(Base, mixins.TimestampsMixin):
__tablename__ = "notification_recipients"
id = types.Id()
email = Column(String, nullable=False)

View File

@@ -30,6 +30,9 @@ class ATSTQueue(RQ):
def send_mail(self, recipients, subject, body):
self._queue_job(ATSTQueue._send_mail, recipients, subject, body)
def send_notification_mail(self, recipients, subject, body):
self._queue_job(ATSTQueue._send_notification_mail, recipients, subject, body)
# pylint: disable=pointless-string-statement
"""Class methods to actually perform the work.
@@ -41,5 +44,14 @@ class ATSTQueue(RQ):
def _send_mail(self, recipients, subject, body):
app.mailer.send(recipients, subject, body)
@classmethod
def _send_notification_mail(self, recipients, subject, body):
app.logger.info(
"Sending a notification to these recipients: {}\n\n{}".format(
recipients, body
)
)
app.mailer.send(recipients, subject, body)
queue = ATSTQueue()

View File

@@ -12,14 +12,22 @@ from atst.domain.authnid.crl import CRLInvalidException
from atst.domain.portfolios import PortfolioError
from atst.utils.flash import formatted_flash as flash
NO_NOTIFY_STATUS_CODES = set([404, 401])
def log_error(e):
error_message = e.message if hasattr(e, "message") else str(e)
current_app.logger.exception(error_message)
def notify(e, message, code):
if code not in NO_NOTIFY_STATUS_CODES:
current_app.notification_sender.send(message)
def handle_error(e, message="Not Found", code=404):
log_error(e)
notify(e, message, code)
return render_template("error.html", message=message), code
@@ -56,13 +64,9 @@ def make_error_pages(app):
@app.errorhandler(Exception)
# pylint: disable=unused-variable
def exception(e):
log_error(e)
if current_app.debug:
raise e
return (
render_template("error.html", message="An Unexpected Error Occurred"),
500,
)
return handle_error(e, message="An Unexpected Error Occurred", code=500)
@app.errorhandler(InvitationError)
@app.errorhandler(InvitationWrongUserError)

View File

@@ -0,0 +1,20 @@
from sqlalchemy import select
from atst.queue import ATSTQueue
from atst.database import db
from atst.models import NotificationRecipient
class NotificationSender(object):
EMAIL_SUBJECT = "ATST notification"
def __init__(self, queue: ATSTQueue):
self.queue = queue
def send(self, body, type_=None):
recipients = self._get_recipients(type_)
self.queue.send_notification_mail(recipients, self.EMAIL_SUBJECT, body)
def _get_recipients(self, type_):
query = select([NotificationRecipient.email])
return db.session.execute(query).fetchone()