Add feature user can change mail address

This commit is contained in:
2026-09-01 08:39:30 +03:00
parent f2ff00894e
commit 2dc4dedb2b
4 changed files with 42 additions and 2 deletions
+2 -1
View File
@@ -12,6 +12,7 @@
- [x] Add validated post image uploads with an in-article preview and click-to-expand view. - [x] Add validated post image uploads with an in-article preview and click-to-expand view.
- [x] Add ordered inline step images with captions for long-form repair and engineering posts. - [x] Add ordered inline step images with captions for long-form repair and engineering posts.
- [ ] Add code snippets to long-form stories. - [ ] Add code snippets to long-form stories.
- [ ] Allow users to change their email addresses. - [x] Allow users to change their email addresses.
- [ ] Add user email verification for registration and email-address changes. - [ ] Add user email verification for registration and email-address changes.
- [ ] Add user real names and use them as the published-by name. - [ ] Add user real names and use them as the published-by name.
- [ ] Add ability to hide posts from unregistered users.
+24
View File
@@ -406,6 +406,30 @@ def change_password():
return render_template("password_form.html", mode="change") return render_template("password_form.html", mode="change")
@app.route("/account/email", methods=("GET", "POST"))
@login_required
def change_email():
user = get_db().execute("SELECT email, password_hash FROM users WHERE id = ?", (session["user_id"],)).fetchone()
if request.method == "POST":
email = request.form.get("email", "").strip().lower()
current_password = request.form.get("current_password", "")
if not check_password_hash(user["password_hash"], current_password):
flash("Your current password is incorrect.", "error")
elif not valid_email(email):
flash("Enter a valid email address.", "error")
elif email == user["email"]:
flash("That is already your email address.", "notice")
else:
try:
get_db().execute("UPDATE users SET email = ? WHERE id = ?", (email, session["user_id"]))
get_db().commit()
flash("Email address updated.", "success")
return redirect(url_for("index"))
except sqlite3.IntegrityError:
flash("That email address is already in use.", "error")
return render_template("email_form.html", email=user["email"])
@app.post("/logout") @app.post("/logout")
def logout(): def logout():
session.clear() session.clear()
+1
View File
@@ -21,6 +21,7 @@
{% if current_user %} {% if current_user %}
<a href="{{ url_for('write') }}">Write</a> <a href="{{ url_for('write') }}">Write</a>
{% if current_user.role == 'admin' %}<a href="{{ url_for('admin_users') }}">Accounts</a>{% endif %} {% if current_user.role == 'admin' %}<a href="{{ url_for('admin_users') }}">Accounts</a>{% endif %}
<a href="{{ url_for('change_email') }}">Email</a>
<a href="{{ url_for('change_password') }}">Password</a> <a href="{{ url_for('change_password') }}">Password</a>
<span class="user-chip">{{ current_user.username }}</span> <span class="user-chip">{{ current_user.username }}</span>
<form action="{{ url_for('logout') }}" method="post"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><button class="text-button" type="submit">Log out</button></form> <form action="{{ url_for('logout') }}" method="post"><input type="hidden" name="csrf_token" value="{{ csrf_token() }}"><button class="text-button" type="submit">Log out</button></form>
+14
View File
@@ -0,0 +1,14 @@
{% extends 'base.html' %}
{% block title %}Email address | Eternity Project{% endblock %}
{% block content %}
<section class="auth-layout">
<div class="auth-copy"><span class="signal-label">ACCOUNT DETAILS</span><h1>Update your<br>address.</h1><p>Use an email address you control. Confirm your current password before saving the change.</p></div>
<form class="auth-form" method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<label>Current email<input type="email" value="{{ email or '' }}" readonly></label>
<label>New email<input name="email" type="email" autocomplete="email" required placeholder="you@example.com"></label>
<label>Current password<input name="current_password" type="password" autocomplete="current-password" required></label>
<button class="button" type="submit">Save email <span aria-hidden="true">→</span></button>
</form>
</section>
{% endblock %}