0001-commands-prevent-duplicated-log-messages-in-sync-lda.patch
src/authentic2/management/commands/sync-ldap-users.py | ||
---|---|---|
22 | 22 |
ldap = None |
23 | 23 | |
24 | 24 |
import logging |
25 |
import os |
|
26 |
from contextlib import contextmanager |
|
25 | 27 | |
26 | 28 |
from django.core.management.base import BaseCommand |
27 | 29 | |
28 | 30 |
from authentic2.backends.ldap_backend import LDAPBackend |
29 | 31 | |
30 | 32 | |
31 |
class Command(BaseCommand): |
|
32 |
def add_arguments(self, parser): |
|
33 |
parser.add_argument('--realm', help='Limit sync to this realm') |
|
34 | ||
35 |
def handle(self, *args, **kwargs): |
|
36 |
root_logger = logging.getLogger() |
|
37 |
ldap_logger = logging.getLogger('authentic2.backends.ldap_backend') |
|
38 | ||
39 |
# ensure log messages are displayed only once on terminal |
|
40 |
stream_handlers = [ |
|
41 |
x for x in root_logger.handlers if isinstance(x, logging.StreamHandler) if x.stream.isatty() |
|
42 |
] |
|
43 |
if stream_handlers: |
|
44 |
handler = stream_handlers[0] |
|
45 |
else: |
|
46 |
handler = logging.StreamHandler() |
|
47 |
ldap_logger.addHandler(handler) |
|
48 | ||
33 |
@contextmanager |
|
34 |
def log_ldap_to_console(verbosity): |
|
35 |
if 'TERM' not in os.environ: |
|
36 |
yield |
|
37 |
else: |
|
38 |
handler = logging.StreamHandler() |
|
49 | 39 |
# add timestamp to messages |
50 | 40 |
formatter = logging.Formatter(fmt='%(asctime)s %(message)s', datefmt='%Y-%m-%d %H:%M:%S') |
51 | 41 |
handler.setFormatter(formatter) |
52 | 42 | |
53 |
verbosity = int(kwargs['verbosity']) |
|
54 | 43 |
if verbosity == 1: |
55 |
ldap_logger.setLevel(logging.ERROR)
|
|
44 |
handler.setLevel(logging.ERROR)
|
|
56 | 45 |
elif verbosity == 2: |
57 |
ldap_logger.setLevel(logging.INFO)
|
|
46 |
handler.setLevel(logging.INFO)
|
|
58 | 47 |
elif verbosity == 3: |
59 |
ldap_logger.setLevel(logging.DEBUG) |
|
48 |
handler.setLevel(logging.DEBUG) |
|
49 | ||
50 |
logger = logging.getLogger('authentic2.backends.ldap_backend') |
|
51 |
initial_level = logger.level |
|
52 |
try: |
|
53 |
logger.propagate = False |
|
54 |
logger.setLevel(logging.DEBUG) |
|
55 |
logger.addHandler(handler) |
|
56 |
yield |
|
57 |
finally: |
|
58 |
logger.propagate = True |
|
59 |
logger.setLevel(initial_level) |
|
60 |
logger.removeHandler(handler) |
|
61 | ||
62 | ||
63 |
class Command(BaseCommand): |
|
64 |
def add_arguments(self, parser): |
|
65 |
parser.add_argument('--realm', help='Limit sync to this realm') |
|
66 | ||
67 |
def handle(self, *args, **kwargs): |
|
68 |
verbosity = int(kwargs['verbosity']) |
|
60 | 69 | |
61 |
for dummy in LDAPBackend.get_users(realm=kwargs['realm']): |
|
62 |
continue |
|
70 |
with log_ldap_to_console(verbosity): |
|
71 |
for dummy in LDAPBackend.get_users(realm=kwargs['realm']): |
|
72 |
continue |
tests/test_ldap.py | ||
---|---|---|
1755 | 1755 |
assert '_auth_user_id' in app.session |
1756 | 1756 | |
1757 | 1757 | |
1758 |
def test_sync_ldap_users(slapd, settings, app, db, caplog): |
|
1759 |
caplog.set_level(logging.DEBUG) # force pytest to reset log level after test |
|
1760 | ||
1758 |
@mock.patch.dict(os.environ, {'TERM': 'xterm-256color'}) |
|
1759 |
@mock.patch('authentic2.backends.ldap_backend.logging.StreamHandler.emit') |
|
1760 |
def test_sync_ldap_users(mocked_emit, slapd, settings, app, db): |
|
1761 | 1761 |
management.call_command('sync-ldap-users') |
1762 |
assert len(caplog.records) == 0
|
|
1762 |
assert mocked_emit.call_count == 0
|
|
1763 | 1763 | |
1764 | 1764 |
management.call_command('sync-ldap-users', verbosity=2) |
1765 |
assert len(caplog.records) == 1
|
|
1766 |
assert caplog.records[0].message == 'No LDAP server configured.'
|
|
1765 |
assert mocked_emit.call_count == 1
|
|
1766 |
assert mocked_emit.call_args[0][0].getMessage() == 'No LDAP server configured.'
|
|
1767 | 1767 | |
1768 | 1768 |
settings.LDAP_AUTH_SETTINGS = [ |
1769 | 1769 |
{ |
... | ... | |
1792 | 1792 |
) |
1793 | 1793 | |
1794 | 1794 |
assert User.objects.count() == 0 |
1795 |
caplog.clear()
|
|
1795 |
mocked_emit.reset_mock()
|
|
1796 | 1796 |
management.call_command('sync-ldap-users', verbosity=2) |
1797 |
assert len(caplog.records) == 11 |
|
1798 |
assert caplog.messages[0] == 'Synchronising users from realm "ldap"' |
|
1799 |
assert caplog.messages[1] == 'Binding to server %s (anonymously)' % slapd.ldap_url |
|
1797 |
assert mocked_emit.call_count == 11 |
|
1798 |
assert mocked_emit.call_args_list[0][0][0].getMessage() == 'Synchronising users from realm "ldap"' |
|
1799 |
assert ( |
|
1800 |
mocked_emit.call_args_list[1][0][0].getMessage() |
|
1801 |
== 'Binding to server %s (anonymously)' % slapd.ldap_url |
|
1802 |
) |
|
1800 | 1803 |
assert ( |
1801 |
caplog.messages[2]
|
|
1804 |
mocked_emit.call_args_list[2][0][0].getMessage()
|
|
1802 | 1805 |
== ( |
1803 | 1806 |
"Updated user etienne.michu@ldap (uuid %s) from dn=cn=Étienne Michu,o=ôrga, uid=['etienne.michu'], " |
1804 | 1807 |
"sn=['Michu'], givenname=['Étienne'], l=['Paris'], mail=['etienne.michu@example.net']" |
1805 | 1808 |
) |
1806 | 1809 |
% User.objects.first().uuid |
1807 | 1810 |
) |
1808 |
assert caplog.messages[-1] == 'Search for (|(mail=*)(uid=*)) returned 7 users.' |
|
1811 |
assert ( |
|
1812 |
mocked_emit.call_args_list[-1][0][0].getMessage() == 'Search for (|(mail=*)(uid=*)) returned 7 users.' |
|
1813 |
) |
|
1809 | 1814 | |
1810 | 1815 |
assert User.objects.count() == 6 |
1811 | 1816 |
assert all(user.first_name == 'Étienne' for user in User.objects.all()) |
... | ... | |
1825 | 1830 |
) |
1826 | 1831 | |
1827 | 1832 |
User.objects.update(first_name='John') |
1828 |
caplog.clear()
|
|
1833 |
mocked_emit.reset_mock()
|
|
1829 | 1834 |
management.call_command('sync-ldap-users', verbosity=3) |
1830 |
assert len(caplog.records) == 42
|
|
1835 |
assert mocked_emit.call_count == 42
|
|
1831 | 1836 | |
1832 | 1837 | |
1833 | 1838 |
def test_get_users_select_realm(slapd, settings, db, caplog): |
1834 |
- |