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:
2026-11-06 22:05:29 -05:00
co-authored by Claude Opus 5.5
parent d73f7d1b80
commit 86ce546a17
5 changed files with 69 additions and 3 deletions
+2 -2
View File
@@ -274,7 +274,7 @@ def logout(request):
def _profile_context(account, values):
return {"account": account, "profile_loaded": True, "form": ProfileForm(initial=profiles.initial(values)), "email_form": ProfileEmailForm(), "password_form": ProfilePasswordForm(), "email_values": values["mail"], "revision": profiles.revision(account, values)}
return {"account": account, "profile_loaded": True, "name_editable": profiles.name_editable(account.ldap_dn), "name_values": values["cn"], "form": ProfileForm(initial=profiles.initial(values)), "email_form": ProfileEmailForm(), "password_form": ProfilePasswordForm(), "email_values": values["mail"], "revision": profiles.revision(account, values)}
@sensitive_post_parameters()
@@ -298,7 +298,7 @@ def profile(request):
return HttpResponse("Please try again later.", status=429)
action = request.POST.get("action")
forms = {"profile": ("form", ProfileForm), "email": ("email_form", ProfileEmailForm), "password": ("password_form", ProfilePasswordForm)}
if action not in forms:
if action not in forms or (action == "profile" and not context["name_editable"]):
return HttpResponse(status=400)
form_key, form_class = forms[action]
form = form_class(request.POST)