forked from Github-Mirrors/canaille
refactor: ldap backend use a server control to re-read objects after update
This commit is contained in:
parent
06181ac479
commit
7b054bb571
3 changed files with 17 additions and 9 deletions
|
@ -4,6 +4,7 @@ from collections.abc import Iterable
|
|||
|
||||
import ldap.dn
|
||||
import ldap.filter
|
||||
from ldap.controls.readentry import PostReadControl
|
||||
|
||||
from canaille.backends.models import BackendModel
|
||||
|
||||
|
@ -136,6 +137,7 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
|
|||
|
||||
def __eq__(self, other):
|
||||
ldap_attributes = self.may() + self.must()
|
||||
|
||||
if not (
|
||||
isinstance(other, self.__class__)
|
||||
and self.may() == other.may()
|
||||
|
@ -414,6 +416,13 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
|
|||
|
||||
self.set_ldap_attribute("objectClass", self.ldap_object_class)
|
||||
|
||||
# PostReadControl allows to read the updated object attributes on creation/edition
|
||||
attributes = ["objectClass"] + [
|
||||
self.python_attribute_to_ldap(name) for name in self.attributes
|
||||
]
|
||||
attributes.remove("dn")
|
||||
read_post_control = PostReadControl(criticality=True, attrList=attributes)
|
||||
|
||||
# Object already exists in the LDAP database
|
||||
if self.exists:
|
||||
deletions = [
|
||||
|
@ -435,7 +444,9 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
|
|||
(ldap.MOD_REPLACE, name, values)
|
||||
for name, values in formatted_changes.items()
|
||||
]
|
||||
conn.modify_s(self.dn, modlist)
|
||||
_, _, _, [result] = conn.modify_ext_s(
|
||||
self.dn, modlist, serverctrls=[read_post_control]
|
||||
)
|
||||
|
||||
# Object does not exist yet in the LDAP database
|
||||
else:
|
||||
|
@ -445,11 +456,13 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
|
|||
if value and value[0]
|
||||
}
|
||||
formatted_changes = python_attrs_to_ldap(changes, null_allowed=False)
|
||||
attributes = [(name, values) for name, values in formatted_changes.items()]
|
||||
conn.add_s(self.dn, attributes)
|
||||
modlist = [(name, values) for name, values in formatted_changes.items()]
|
||||
_, _, _, [result] = conn.add_ext_s(
|
||||
self.dn, modlist, serverctrls=[read_post_control]
|
||||
)
|
||||
|
||||
self.exists = True
|
||||
self.state = {**self.state, **self.changes}
|
||||
self.state = {**result.entry, **self.changes}
|
||||
self.changes = {}
|
||||
|
||||
def delete(self):
|
||||
|
|
|
@ -226,7 +226,6 @@ def test_model_creation_edition_datetime(testclient, backend):
|
|||
formatted_name="foo",
|
||||
)
|
||||
user.save()
|
||||
user.reload()
|
||||
assert user.created == datetime.datetime(
|
||||
2020, 1, 1, 2, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
|
@ -237,7 +236,6 @@ def test_model_creation_edition_datetime(testclient, backend):
|
|||
with freezegun.freeze_time("2021-01-01 02:00:00"):
|
||||
user.family_name = "bar"
|
||||
user.save()
|
||||
user.reload()
|
||||
assert user.created == datetime.datetime(
|
||||
2020, 1, 1, 2, tzinfo=datetime.timezone.utc
|
||||
)
|
||||
|
|
|
@ -33,7 +33,6 @@ def test_revokation(testclient, client, consent, logged_user, token):
|
|||
def test_revokation_already_revoked(testclient, client, consent, logged_user):
|
||||
consent.revoke()
|
||||
|
||||
consent.reload()
|
||||
assert consent.revoked
|
||||
|
||||
res = testclient.get(f"/consent/revoke/{consent.consent_id}", status=302)
|
||||
|
@ -47,7 +46,6 @@ def test_revokation_already_revoked(testclient, client, consent, logged_user):
|
|||
def test_restoration(testclient, client, consent, logged_user, token):
|
||||
consent.revoke()
|
||||
|
||||
consent.reload()
|
||||
assert consent.revoked
|
||||
token.reload()
|
||||
assert token.revoked
|
||||
|
@ -101,7 +99,6 @@ def test_oidc_authorization_after_revokation(
|
|||
):
|
||||
consent.revoke()
|
||||
|
||||
consent.reload()
|
||||
assert consent.revoked
|
||||
|
||||
res = testclient.get(
|
||||
|
|
Loading…
Reference in a new issue