refactor: ldapbackend explicitly uses the DN attribute for LDAP operations

This commit is contained in:
Éloi Rivard 2024-04-03 09:40:10 +02:00
parent 9876d44ab6
commit ab17137cd6
No known key found for this signature in database
GPG key ID: 7EDA204EA57DD184
2 changed files with 11 additions and 7 deletions

View file

@ -219,6 +219,10 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
value = self.get_ldap_attribute(self.rdn_attribute) value = self.get_ldap_attribute(self.rdn_attribute)
return (value[0] if isinstance(value, list) else value).strip() return (value[0] if isinstance(value, list) else value).strip()
@property
def dn(self):
return self.dn_for(self.rdn_value)
@classmethod @classmethod
def dn_for(cls, rdn): def dn_for(cls, rdn):
return f"{cls.rdn_attribute}={ldap.dn.escape_dn_chars(rdn)},{cls.base},{cls.root_dn}" return f"{cls.rdn_attribute}={ldap.dn.escape_dn_chars(rdn)},{cls.base},{cls.root_dn}"
@ -401,7 +405,7 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
def reload(self): def reload(self):
conn = Backend.get().connection conn = Backend.get().connection
result = conn.search_s(self.id, ldap.SCOPE_SUBTREE, None, ["+", "*"]) result = conn.search_s(self.dn, ldap.SCOPE_SUBTREE, None, ["+", "*"])
self.changes = {} self.changes = {}
self.state = result[0][1] self.state = result[0][1]
@ -431,7 +435,7 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
(ldap.MOD_REPLACE, name, values) (ldap.MOD_REPLACE, name, values)
for name, values in formatted_changes.items() for name, values in formatted_changes.items()
] ]
conn.modify_s(self.id, modlist) conn.modify_s(self.dn, modlist)
# Object does not exist yet in the LDAP database # Object does not exist yet in the LDAP database
else: else:
@ -442,7 +446,7 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
} }
formatted_changes = python_attrs_to_ldap(changes, null_allowed=False) formatted_changes = python_attrs_to_ldap(changes, null_allowed=False)
attributes = [(name, values) for name, values in formatted_changes.items()] attributes = [(name, values) for name, values in formatted_changes.items()]
conn.add_s(self.id, attributes) conn.add_s(self.dn, attributes)
self.exists = True self.exists = True
self.state = {**self.state, **self.changes} self.state = {**self.state, **self.changes}
@ -450,4 +454,4 @@ class LDAPObject(BackendModel, metaclass=LDAPObjectMetaclass):
def delete(self): def delete(self):
conn = Backend.get().connection conn = Backend.get().connection
conn.delete_s(self.id) conn.delete_s(self.dn)

View file

@ -102,7 +102,7 @@ class User(canaille.core.models.User, LDAPObject):
message = None message = None
try: try:
res = conn.simple_bind_s( res = conn.simple_bind_s(
self.id, password, serverctrls=[PasswordPolicyControl()] self.dn, password, serverctrls=[PasswordPolicyControl()]
) )
controls = res[3] controls = res[3]
result = True result = True
@ -133,7 +133,7 @@ class User(canaille.core.models.User, LDAPObject):
def set_password(self, password): def set_password(self, password):
conn = Backend.get().connection conn = Backend.get().connection
conn.passwd_s( conn.passwd_s(
self.id, self.dn,
None, None,
password.encode("utf-8"), password.encode("utf-8"),
) )
@ -177,7 +177,7 @@ class User(canaille.core.models.User, LDAPObject):
for details in current_app.config["CANAILLE"]["ACL"].values(): for details in current_app.config["CANAILLE"]["ACL"].values():
filter_ = self.acl_filter_to_ldap_filter(details["FILTER"]) filter_ = self.acl_filter_to_ldap_filter(details["FILTER"])
if not filter_ or ( if not filter_ or (
self.id and conn.search_s(self.id, ldap.SCOPE_SUBTREE, filter_) self.dn and conn.search_s(self.dn, ldap.SCOPE_SUBTREE, filter_)
): ):
self._permissions |= set(details["PERMISSIONS"]) self._permissions |= set(details["PERMISSIONS"])
self._readable_fields |= set(details["READ"]) self._readable_fields |= set(details["READ"])