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>
113 lines
8.2 KiB
HTML
Executable File
113 lines
8.2 KiB
HTML
Executable File
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="robots" content="noindex">
|
|
<title>Your profile · eom.dev</title>
|
|
<link rel="stylesheet" href="/static/home.css">
|
|
<link rel="stylesheet" href="/static/membership.css">
|
|
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
|
|
</head>
|
|
<body>
|
|
<header class="member-nav">
|
|
<a class="brand" href="/">eom.dev</a>
|
|
<nav aria-label="Membership navigation"><a href="#main-content">Skip to content</a><a href="{% url 'members:home' %}">Membership</a></nav>
|
|
</header>
|
|
<main id="main-content" class="member-main profile-main">
|
|
<header class="profile-heading">
|
|
<p class="eyebrow">One account. Your own identity.</p>
|
|
<h1>Your profile</h1>
|
|
<p>Your eom.dev account is shared across every service you sign in to. Services see your username, name and email address.</p>
|
|
{% if account %}<p class="member-small">Signed in as <strong>{{ account.uid }}</strong>. Your username cannot be changed here.</p>{% endif %}
|
|
</header>
|
|
{% if saved %}<p class="member-notice" role="status">Your changes have been saved.</p>{% endif %}
|
|
{% if email_sent %}<p class="member-notice" role="status">Check your new email inbox for a verification link. Your stored email addresses stay unchanged until you confirm.</p>{% endif %}
|
|
{% if confirm_email %}
|
|
<section class="member-panel profile-section" aria-labelledby="confirm-heading">
|
|
<h2 id="confirm-heading">Confirm your new email</h2>
|
|
<p>{% if confirmation_email %}Confirm <strong>{{ confirmation_email }}</strong> as your email address. {% endif %}After verification, this replaces all currently stored email addresses with the new address.</p>
|
|
<p>Enter your current password to finish. Opening this link alone does not change your account.</p>
|
|
<form method="post">
|
|
{% csrf_token %}
|
|
{% if confirmation_form.non_field_errors %}<div class="profile-errors" role="alert">{{ confirmation_form.non_field_errors }}</div>{% endif %}
|
|
{% include "profile_fields.html" with fields=confirmation_form only %}
|
|
<button class="button button-primary" type="submit">Confirm email change</button>
|
|
</form>
|
|
</section>
|
|
{% elif not profile_loaded %}
|
|
<section class="member-panel profile-section" aria-labelledby="unavailable-heading">
|
|
<h2 id="unavailable-heading">Your profile is temporarily unavailable</h2>
|
|
<p>We could not load your stored profile. Editing is unavailable so that missing data cannot overwrite your details. Please try again later.</p>
|
|
<a class="button button-secondary" href="{% url 'members:profile' %}">Try loading again</a>
|
|
</section>
|
|
{% else %}
|
|
<nav class="profile-jump-links" aria-label="Profile sections">
|
|
<a href="#identity">Name</a><a href="#email">Email</a>{% if newsletter_status %}<a href="#newsletter">Newsletter</a>{% endif %}<a href="#password">Password</a>
|
|
</nav>
|
|
{% if name_editable %}
|
|
<form id="identity" action="{% url 'members:profile' %}" method="post" class="member-panel profile-section profile-edit-form" aria-labelledby="identity-heading">
|
|
{% csrf_token %}
|
|
<input type="hidden" name="action" value="profile">
|
|
<input type="hidden" name="revision" value="{{ revision }}">
|
|
<h2 id="identity-heading">Name</h2>
|
|
{% if form.errors %}<div class="profile-errors" role="alert"><p>Your name has not been saved. Correct the fields marked below and enter your current password again.</p>{{ form.non_field_errors }}</div>{% endif %}
|
|
{% include "profile_fields.html" with fields=form.identity_fields only %}
|
|
{% include "profile_fields.html" with fields=form.authorization_fields only %}
|
|
<button class="button button-primary" type="submit">Save name</button>
|
|
</form>
|
|
{% else %}
|
|
<section id="identity" class="member-panel profile-section" aria-labelledby="identity-heading">
|
|
<h2 id="identity-heading">Name</h2>
|
|
<p class="profile-readonly-name"><strong>{{ name_values|first|default:account.uid }}</strong></p>
|
|
<p class="member-small">Your name is part of how your account is stored, so it can't be changed here. Contact eric@eom.dev if it needs updating.</p>
|
|
</section>
|
|
{% endif %}
|
|
<section id="email" class="member-panel profile-section" aria-labelledby="email-heading">
|
|
<h2 id="email-heading">Email address</h2>
|
|
<p>Current email address:</p>
|
|
<ul class="profile-email-values">{% for email in email_values %}<li>{{ email }}</li>{% empty %}<li>No email address stored.</li>{% endfor %}</ul>
|
|
<p>A verified change replaces <strong>all</strong> currently stored email addresses with the new address. We will email a verification link to the new address; nothing changes until you confirm it with your current password.</p>
|
|
<form action="{% url 'members:profile' %}" method="post">
|
|
{% csrf_token %}<input type="hidden" name="action" value="email">
|
|
{% if email_form.non_field_errors %}<div class="profile-errors" role="alert">{{ email_form.non_field_errors }}</div>{% endif %}
|
|
{% include "profile_fields.html" with fields=email_form only %}
|
|
<button class="button button-primary" type="submit">Send verification email</button>
|
|
</form>
|
|
</section>
|
|
{% if newsletter_status %}
|
|
<section id="newsletter" class="member-panel profile-section" aria-labelledby="newsletter-heading">
|
|
<h2 id="newsletter-heading">Newsletter</h2>
|
|
{% if request.GET.newsletter == "saved" %}<p class="member-notice" role="status">Your newsletter preference has been saved.</p>{% elif request.GET.newsletter == "error" %}<p class="profile-errors" role="alert">Your newsletter preference couldn't be changed just now. Please try again later.</p>{% endif %}
|
|
<p>One short email per premiere (about twice a month), plus the monthly essay. Sent to {{ account.email }}.</p>
|
|
{% if newsletter_status == "subscribed" %}
|
|
<p>You're subscribed.</p>
|
|
<form action="{% url 'members:newsletter' %}" method="post">{% csrf_token %}<input type="hidden" name="action" value="unsubscribe"><button class="button button-secondary" type="submit">Unsubscribe</button></form>
|
|
{% elif newsletter_status == "unsubscribed" %}
|
|
<p>You're not subscribed.</p>
|
|
<form action="{% url 'members:newsletter' %}" method="post">{% csrf_token %}<input type="hidden" name="action" value="subscribe"><button class="button button-primary" type="submit">Subscribe</button></form>
|
|
{% elif newsletter_status == "blocked" %}
|
|
<p>This address has opted out of all eom.dev email. Contact eric@eom.dev to opt back in.</p>
|
|
{% else %}
|
|
<p>Newsletter settings are temporarily unavailable.</p>
|
|
{% endif %}
|
|
</section>
|
|
{% endif %}
|
|
<section id="password" class="member-panel profile-section" aria-labelledby="password-heading">
|
|
<h2 id="password-heading">Password</h2>
|
|
<p>Choose a strong, unique password for your shared eom.dev account. Your current password is needed to authorize the change. Spaces in passwords are preserved.</p>
|
|
<p class="member-small">Password hashing policy is controlled by the server. Legacy MD5Crypt is insecure; changing a password here does not guarantee that the server upgrades its hashing policy.</p>
|
|
<form action="{% url 'members:profile' %}" method="post">
|
|
{% csrf_token %}<input type="hidden" name="action" value="password">
|
|
{% if password_form.non_field_errors %}<div class="profile-errors" role="alert">{{ password_form.non_field_errors }}</div>{% endif %}
|
|
{% include "profile_fields.html" with fields=password_form only %}
|
|
<button class="button button-primary" type="submit">Change password</button>
|
|
</form>
|
|
</section>
|
|
{% endif %}
|
|
<p class="profile-back"><a href="{% url 'members:home' %}">Back to membership</a></p>
|
|
</main>
|
|
<footer class="member-footer">Your account. Across the community. <a href="{% url 'members:home' %}">Membership</a></footer>
|
|
</body>
|
|
</html>
|