From 0f0006ad9baafcd14529eed939cd60d1fb979735 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 20 Jul 2021 16:03:01 +0200 Subject: [PATCH] misc: fix override of trace emails recipients for Django 2 (#55687) --- passerelle/base/models.py | 13 ++++----- passerelle/log.py | 59 +++++++++++++++++++++++++++++++++++++++ passerelle/settings.py | 5 ++++ tests/test_misc.py | 2 +- 4 files changed, 71 insertions(+), 8 deletions(-) create mode 100644 passerelle/log.py diff --git a/passerelle/base/models.py b/passerelle/base/models.py index e6628880..ab73a8dc 100644 --- a/passerelle/base/models.py +++ b/passerelle/base/models.py @@ -23,7 +23,6 @@ from django.db import connection, models, transaction from django.db.models import Q from django.forms.models import modelform_factory from django.forms.widgets import ClearableFileInput -from django.test import override_settings from django.urls import reverse from django.utils import six, timezone from django.utils.encoding import force_text @@ -35,6 +34,7 @@ from model_utils.managers import InheritanceManager as ModelUtilsInheritanceMana import passerelle from passerelle.forms import GenericConnectorForm +from passerelle.log import AddResourceFilter, AdminEmailHandler from passerelle.utils.api import endpoint from passerelle.utils.jsonresponse import APIError from passerelle.utils.sftp import SFTP, SFTPField @@ -158,6 +158,10 @@ class BaseResource(models.Model): def __init__(self, *args, **kwargs): super(BaseResource, self).__init__(*args, **kwargs) self.logger = ProxyLogger(connector=self, transaction_id=str(uuid.uuid4())) + root_logger = logging.getLogger() + for handler in root_logger.handlers: + if isinstance(handler, AdminEmailHandler): + handler.addFilter(AddResourceFilter(resource=self)) def __str__(self): return self.title @@ -969,12 +973,7 @@ class ProxyLogger(object): ResourceLog.objects.create(**attr) - admins = settings.ADMINS - logging_parameters = self.connector.logging_parameters - if logging_parameters.trace_emails: - admins = [('', x) for x in logging_parameters.trace_emails.splitlines()] - with override_settings(ADMINS=admins): - getattr(self._logger, levelname.lower())(message, *args, **kwargs) + getattr(self._logger, levelname.lower())(message, *args, **kwargs) def exception(self, message, *args, **kwargs): kwargs['exc_info'] = 1 diff --git a/passerelle/log.py b/passerelle/log.py new file mode 100644 index 00000000..f52304d5 --- /dev/null +++ b/passerelle/log.py @@ -0,0 +1,59 @@ +# Copyright (C) 2021 Entr'ouvert +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +import logging + +import django.utils.log +from django.conf import settings +from django.core.mail.message import EmailMultiAlternatives + + +class AddResourceFilter(logging.Filter): + def __init__(self, *args, resource=None, **kwargs): + self.resource = resource + super().__init__(*args, **kwargs) + + def filter(self, record): + record.resource = self.resource + return True + + +class AdminEmailHandler(django.utils.log.AdminEmailHandler): + def __init__(self, *args, **kwargs): + self.emails = [] + super().__init__(*args, **kwargs) + + def emit(self, record): + if hasattr(record, 'resource'): + logging_parameters = record.resource.logging_parameters + self.emails = logging_parameters.trace_emails.splitlines() + elif settings.ADMINS: + self.emails = [a[1] for a in settings.ADMINS] + return super().emit(record) + + def send_mail(self, subject, message, *args, **kwargs): + if not self.emails: + return + + mail = EmailMultiAlternatives( + '%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject), + message, + settings.SERVER_EMAIL, + self.emails, + connection=self.connection(), + ) + if 'html_message' in kwargs: + mail.attach_alternative(kwargs['html_message'], 'text/html') + + mail.send(fail_silently=kwargs.get('fail_silently', False)) diff --git a/passerelle/settings.py b/passerelle/settings.py index 3750c8f0..78011980 100644 --- a/passerelle/settings.py +++ b/passerelle/settings.py @@ -244,6 +244,11 @@ LOGGING = { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, + 'mail_admins': { + 'level': 'ERROR', + 'class': 'passerelle.log.AdminEmailHandler', + 'include_html': True, + }, }, 'loggers': { 'django.request': { diff --git a/tests/test_misc.py b/tests/test_misc.py index 05f2df94..62216fae 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -88,7 +88,7 @@ def test_log_cleaning(app, db, admin_user, settings): def email_handler(): import logging - from django.utils.log import AdminEmailHandler + from passerelle.log import AdminEmailHandler root = logging.getLogger() handler = AdminEmailHandler(include_html=True) -- 2.20.1