Projet

Général

Profil

0001-misc-fix-override-of-trace-emails-recipients-for-Dja.patch

Valentin Deniaud, 28 juillet 2021 10:51

Télécharger (8,53 ko)

Voir les différences:

Subject: [PATCH] misc: fix override of trace emails recipients for Django 2
 (#55687)

 debian/debian_config.py                     |  2 +
 passerelle/base/management/commands/cron.py |  3 +-
 passerelle/base/models.py                   | 26 ++++++---
 passerelle/log.py                           | 59 +++++++++++++++++++++
 passerelle/settings.py                      |  5 ++
 passerelle/views.py                         |  3 +-
 tests/test_misc.py                          |  2 +-
 7 files changed, 89 insertions(+), 11 deletions(-)
 create mode 100644 passerelle/log.py
debian/debian_config.py
36 36
    'propagate': True,
37 37
}
38 38

  
39
ADMIN_EMAIL_HANDLER_CLASS = 'passerelle.log.AdminEmailHandler'
40

  
39 41
exec(open('/etc/%s/settings.py' % PROJECT_NAME).read())
40 42

  
41 43
# run additional settings snippets
passerelle/base/management/commands/cron.py
57 57
                if options.get('slug') and connector.slug != options.get('slug'):
58 58
                    continue
59 59
                try:
60
                    getattr(connector, frequency)()
60
                    with connector.logger.mail_admin_filter():
61
                        getattr(connector, frequency)()
61 62
                except Exception as e:
62 63
                    connector.logger.exception(
63 64
                        'connector "%s.%s" error running %s job'
passerelle/base/models.py
24 24
from django.db.models import Q
25 25
from django.forms.models import modelform_factory
26 26
from django.forms.widgets import ClearableFileInput
27
from django.test import override_settings
28 27
from django.urls import reverse
29 28
from django.utils import six, timezone
30 29
from django.utils.encoding import force_text
......
37 36

  
38 37
import passerelle
39 38
from passerelle.forms import GenericConnectorForm
39
from passerelle.log import AddResourceFilter
40 40
from passerelle.utils.api import endpoint
41 41
from passerelle.utils.jsonresponse import APIError
42 42
from passerelle.utils.sftp import SFTP, SFTPField
......
820 820
        self.status = 'running'
821 821
        self.save()
822 822
        try:
823
            getattr(self.resource, self.method_name)(**self.parameters)
823
            with self.resource.logger.mail_admin_filter():
824
                getattr(self.resource, self.method_name)(**self.parameters)
824 825
        except SkipJob as e:
825 826
            self.status = 'registered'
826 827
            self.set_after_timestamp(e.after_timestamp)
......
922 923
            for handler in mail_admin_handlers:
923 924
                handler.setLevel(handler.previous_level)
924 925

  
926
    @contextmanager
927
    def mail_admin_filter(self):
928
        mail_admin_handlers = [
929
            handler for handler in self._logger.root.handlers if isinstance(handler, AdminEmailHandler)
930
        ]
931
        filter_ = AddResourceFilter(resource=self.connector)
932
        for handler in mail_admin_handlers:
933
            handler.addFilter(filter_)
934
        try:
935
            yield
936
        finally:
937
            for handler in mail_admin_handlers:
938
                handler.removeFilter(filter_)
939

  
925 940
    def _log(self, levelname, message, *args, **kwargs):
926 941
        force = kwargs.pop('force', False)
927 942
        if self.connector.down() and not force:
......
986 1001

  
987 1002
            ResourceLog.objects.create(**attr)
988 1003

  
989
        admins = settings.ADMINS
990
        logging_parameters = self.connector.logging_parameters
991
        if logging_parameters.trace_emails:
992
            admins = [('', x) for x in logging_parameters.trace_emails.splitlines()]
993
        with override_settings(ADMINS=admins):
994
            getattr(self._logger, levelname.lower())(message, *args, **kwargs)
1004
        getattr(self._logger, levelname.lower())(message, *args, **kwargs)
995 1005

  
996 1006
    def exception(self, message, *args, **kwargs):
997 1007
        kwargs['exc_info'] = 1
passerelle/log.py
1
# Copyright (C) 2021  Entr'ouvert
2
#
3
# This program is free software: you can redistribute it and/or modify it
4
# under the terms of the GNU Affero General Public License as published
5
# by the Free Software Foundation, either version 3 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU Affero General Public License for more details.
12
#
13
# You should have received a copy of the GNU Affero General Public License
14
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
import logging
16

  
17
import django.utils.log
18
from django.conf import settings
19
from django.core.mail.message import EmailMultiAlternatives
20

  
21

  
22
class AddResourceFilter(logging.Filter):
23
    def __init__(self, *args, resource=None, **kwargs):
24
        self.resource = resource
25
        super().__init__(*args, **kwargs)
26

  
27
    def filter(self, record):
28
        record.resource = self.resource
29
        return True
30

  
31

  
32
class AdminEmailHandler(django.utils.log.AdminEmailHandler):
33
    def __init__(self, *args, **kwargs):
34
        self.emails = []
35
        super().__init__(*args, **kwargs)
36

  
37
    def emit(self, record):
38
        if hasattr(record, 'resource'):
39
            logging_parameters = record.resource.logging_parameters
40
            self.emails = logging_parameters.trace_emails.splitlines()
41
        if not self.emails and settings.ADMINS:
42
            self.emails = [a[1] for a in settings.ADMINS]
43
        return super().emit(record)
44

  
45
    def send_mail(self, subject, message, *args, **kwargs):
46
        if not self.emails:
47
            return
48

  
49
        mail = EmailMultiAlternatives(
50
            '%s%s' % (settings.EMAIL_SUBJECT_PREFIX, subject),
51
            message,
52
            settings.SERVER_EMAIL,
53
            self.emails,
54
            connection=self.connection(),
55
        )
56
        if 'html_message' in kwargs:
57
            mail.attach_alternative(kwargs['html_message'], 'text/html')
58

  
59
        mail.send(fail_silently=kwargs.get('fail_silently', False))
passerelle/settings.py
244 244
            'level': 'DEBUG',
245 245
            'class': 'logging.StreamHandler',
246 246
        },
247
        'mail_admins': {
248
            'level': 'ERROR',
249
            'class': 'passerelle.log.AdminEmailHandler',
250
            'include_html': True,
251
        },
247 252
    },
248 253
    'loggers': {
249 254
        'django.request': {
passerelle/views.py
443 443
        if kwargs.get('endpoint') == 'up' and hasattr(self.connector.check_status, 'not_implemented'):
444 444
            # hide automatic up endpoint if check_status method is not implemented
445 445
            raise Http404()
446
        return super(GenericEndpointView, self).dispatch(request, *args, **kwargs)
446
        with self.connector.logger.mail_admin_filter():
447
            return super(GenericEndpointView, self).dispatch(request, *args, **kwargs)
447 448

  
448 449
    def _allowed_methods(self):
449 450
        return [x.upper() for x in self.endpoint.endpoint_info.methods]
tests/test_misc.py
91 91
def email_handler():
92 92
    import logging
93 93

  
94
    from django.utils.log import AdminEmailHandler
94
    from passerelle.log import AdminEmailHandler
95 95

  
96 96
    root = logging.getLogger()
97 97
    handler = AdminEmailHandler(include_html=True)
98
-