From abb81a5bfd85b466f26226963c55919ae2ee4074 Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Wed, 7 Jul 2021 16:11:27 +0200 Subject: [PATCH] ldap: record users ldap accounts (#51211) --- src/authentic2/backends/__init__.py | 4 -- src/authentic2/backends/apps.py | 29 +++++++++++++++ src/authentic2/backends/ldap_backend.py | 16 ++++++++ .../backends/manager_user_sidebar.html | 8 ++++ src/authentic2/migrations/0034_ldapaccount.py | 37 +++++++++++++++++++ 5 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 src/authentic2/backends/apps.py create mode 100644 src/authentic2/backends/templates/authentic2/backends/manager_user_sidebar.html create mode 100644 src/authentic2/migrations/0034_ldapaccount.py diff --git a/src/authentic2/backends/__init__.py b/src/authentic2/backends/__init__.py index cd1840c7..bc927822 100644 --- a/src/authentic2/backends/__init__.py +++ b/src/authentic2/backends/__init__.py @@ -42,7 +42,3 @@ def is_user_authenticable(user): if not app_settings.A2_USER_FILTER and not app_settings.A2_USER_EXCLUDE: return True return get_user_queryset().filter(pk=user.pk).exists() - - -from .ldap_backend import LDAPBackend # noqa: F401 -from .models_backend import ModelBackend # noqa: F401 diff --git a/src/authentic2/backends/apps.py b/src/authentic2/backends/apps.py new file mode 100644 index 00000000..5890530b --- /dev/null +++ b/src/authentic2/backends/apps.py @@ -0,0 +1,29 @@ +# authentic2 - versatile identity manager +# Copyright (C) 2010-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 django.apps +from django import template + + +class AppConfig(django.apps.AppConfig): + name = 'authentic2.backends' + verbose_name = _('Backends') + + def a2_hook_manager_user_data(self, view, user): + context = {'user': user} + return [ + template.loader.get_template('authentic2_auth_oidc/manager_user_sidebar.html').render(context) + ] diff --git a/src/authentic2/backends/ldap_backend.py b/src/authentic2/backends/ldap_backend.py index 88acccf4..f69f6446 100644 --- a/src/authentic2/backends/ldap_backend.py +++ b/src/authentic2/backends/ldap_backend.py @@ -44,6 +44,7 @@ from django.contrib.auth import get_user_model from django.contrib.auth.models import Group from django.core.cache import cache from django.core.exceptions import ImproperlyConfigured +from django.db import models from django.utils.encoding import force_bytes, force_text from django.utils.translation import ngettext from django.utils.translation import ugettext as _ @@ -1472,9 +1473,11 @@ class LDAPBackend(object): def _return_django_user(self, dn, username, password, conn, block, attributes): from authentic2.manager.journal_event_types import ManagerUserActivation + ldap_uri = conn.get_option(ldap.OPT_URI) user = self.lookup_existing_user(username, block, attributes) if user: log.debug('found existing user %r', user) + LDAPAccount.objects.get_or_create(user=user, origin=ldap_uri) else: user = LDAPUser(username=username) user.set_unusable_password() @@ -1483,6 +1486,7 @@ class LDAPBackend(object): self.populate_user(user, dn, username, conn, block, attributes) if not user.pk or getattr(user, '_changed', False): user.save() + LDAPAccount.objects.update_or_create(user=user, origin=ldap_uri) if not is_user_authenticable(user): return None @@ -1875,3 +1879,15 @@ class LDAPBackendPasswordLost(LDAPBackend): LDAPUser.ldap_backend = LDAPBackend LDAPBackendPasswordLost.ldap_backend = LDAPBackend + + +class LDAPAccount(models.Model): + created = models.DateTimeField(verbose_name=_('created'), auto_now_add=True) + modified = models.DateTimeField(verbose_name=_('modified'), auto_now=True) + origin = models.CharField(verbose_name=_('server url'), max_length=256) + user = models.OneToOneField( + to=settings.AUTH_USER_MODEL, + verbose_name=_('user'), + related_name='ldap_account', + on_delete=models.CASCADE, + ) diff --git a/src/authentic2/backends/templates/authentic2/backends/manager_user_sidebar.html b/src/authentic2/backends/templates/authentic2/backends/manager_user_sidebar.html new file mode 100644 index 00000000..2d4b1623 --- /dev/null +++ b/src/authentic2/backends/templates/authentic2/backends/manager_user_sidebar.html @@ -0,0 +1,8 @@ +{% load i18n %} +{% if user.ldap_account %} +

+{% blocktrans trimmed with modified=user.ldap_account.modified origin=user.ldap_account.origin %} +Linked with LDAP server {{ name }} (last modified on {{ modified }}). +{% endblocktrans %} +

+{% endif %} diff --git a/src/authentic2/migrations/0034_ldapaccount.py b/src/authentic2/migrations/0034_ldapaccount.py new file mode 100644 index 00000000..840c7336 --- /dev/null +++ b/src/authentic2/migrations/0034_ldapaccount.py @@ -0,0 +1,37 @@ +# Generated by Django 2.2.19 on 2021-07-07 14:15 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('authentic2', '0033_recreate_immutable_unaccent'), + ] + + operations = [ + migrations.CreateModel( + name='LDAPAccount', + fields=[ + ( + 'id', + models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'), + ), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='création')), + ('modified', models.DateTimeField(auto_now=True, verbose_name='modifié')), + ('origin', models.CharField(max_length=256, verbose_name='server url')), + ( + 'user', + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name='ldap_account', + to=settings.AUTH_USER_MODEL, + verbose_name='utilisateur', + ), + ), + ], + ), + ] -- 2.20.1