Profile: read-only name for cn-named directory entries
slapd refuses to remove an RDN value, and every legacy account is cn=<name>,ou=People, so a name edit there always failed. Those accounts now see their name read-only (the view rejects the profile action and update_profile refuses as a backstop); uid-named accounts from website registration can still edit it. README documents the cn/mail self-write ACL and mail uniqueness overlay now applied in production. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ from ldap3.core.exceptions import LDAPException
|
||||
from ldap3.operation.search import compile_filter, parse_filter
|
||||
from ldap3.protocol.controls import build_control
|
||||
from ldap3.utils.conv import escape_filter_chars
|
||||
from ldap3.utils.dn import parse_dn
|
||||
|
||||
from . import directory
|
||||
from .models import Account
|
||||
@@ -83,6 +84,24 @@ def read_profile(account):
|
||||
return values
|
||||
|
||||
|
||||
def name_editable(dn):
|
||||
"""False when cn names the entry: slapd refuses to remove an RDN value.
|
||||
|
||||
Legacy accounts are cn=<name>,ou=People; renaming them would change DNs
|
||||
that other services store, so their name is shown read-only instead.
|
||||
"""
|
||||
try:
|
||||
components = parse_dn(dn)
|
||||
except Exception:
|
||||
return False
|
||||
for attribute, _value, separator in components:
|
||||
if attribute.casefold() in {"cn", "2.5.4.3"}:
|
||||
return False
|
||||
if separator != "+":
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def revision(account, values):
|
||||
return signing.dumps({"account": str(account.pk), "uuid": account.ldap_uuid, "digest": _digest(values)}, salt="ldap-profile")
|
||||
|
||||
@@ -118,6 +137,8 @@ def update_profile(account, cleaned, expected_revision):
|
||||
with _authorized(account, cleaned["current_password"]) as (conn, values):
|
||||
if proof != {"account": str(account.pk), "uuid": account.ldap_uuid, "digest": _digest(values)}:
|
||||
raise ValueError("Your profile changed. Reload it before saving.")
|
||||
if not name_editable(account.ldap_dn):
|
||||
raise ValueError("This account's name is part of its directory entry name.")
|
||||
changes = {}
|
||||
for name in TEXT_ATTRIBUTES:
|
||||
new_values = cleaned[name]
|
||||
|
||||
Reference in New Issue
Block a user