Add the user settings page too

This commit is contained in:
Andrew Godwin 2022-11-17 19:36:25 -07:00
parent 6adfdbabe0
commit adf2449d37
11 changed files with 116 additions and 15 deletions

View file

@ -69,16 +69,16 @@ the less sure I am about it.
- [x] Settings subsystem - [x] Settings subsystem
- [x] Server management page - [x] Server management page
- [x] Domain management page - [x] Domain management page
- [ ] Email subsystem - [x] Email subsystem
- [ ] Signup flow - [x] Signup flow
- [ ] Password change flow - [x] Password reset flow
- [ ] Password reset flow
### Beta ### Beta
- [ ] Attach images to posts - [ ] Attach images to posts
- [ ] Edit posts - [ ] Edit posts
- [ ] Delete posts - [ ] Delete posts
- [ ] Password change flow
- [ ] Fetch remote post images locally and thumbnail - [ ] Fetch remote post images locally and thumbnail
- [ ] Show follow pending states - [ ] Show follow pending states
- [ ] Manual approval of followers - [ ] Manual approval of followers

View file

@ -9,7 +9,7 @@ class Search(FormView):
template_name = "activities/search.html" template_name = "activities/search.html"
class form_class(forms.Form): class form_class(forms.Form):
query = forms.CharField() query = forms.CharField(help_text="Search for a user by @username@domain")
def form_valid(self, form): def form_valid(self, form):
query = form.cleaned_data["query"].lstrip("@").lower() query = form.cleaned_data["query"].lstrip("@").lower()

View file

@ -21,6 +21,11 @@ urlpatterns = [
settings.SettingsRoot.as_view(), settings.SettingsRoot.as_view(),
name="settings", name="settings",
), ),
path(
"settings/security/",
settings.SecurityPage.as_view(),
name="settings_security",
),
path( path(
"settings/profile/", "settings/profile/",
settings.ProfilePage.as_view(), settings.ProfilePage.as_view(),
@ -85,7 +90,8 @@ urlpatterns = [
path("auth/login/", auth.Login.as_view(), name="login"), path("auth/login/", auth.Login.as_view(), name="login"),
path("auth/logout/", auth.Logout.as_view(), name="logout"), path("auth/logout/", auth.Logout.as_view(), name="logout"),
path("auth/signup/", auth.Signup.as_view(), name="signup"), path("auth/signup/", auth.Signup.as_view(), name="signup"),
path("auth/reset/<token>/", auth.Reset.as_view(), name="password_reset"), path("auth/reset/", auth.TriggerReset.as_view(), name="trigger_reset"),
path("auth/reset/<token>/", auth.PerformReset.as_view(), name="password_reset"),
# Identity selection # Identity selection
path("@<handle>/activate/", identity.ActivateIdentity.as_view()), path("@<handle>/activate/", identity.ActivateIdentity.as_view()),
path("identity/select/", identity.SelectIdentity.as_view()), path("identity/select/", identity.SelectIdentity.as_view()),

View file

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block title %}Reset Password{% endblock %}
{% block content %}
<form action="." method="POST">
{% csrf_token %}
<fieldset>
<legend>Reset Password</legend>
{% for field in form %}
{% include "forms/_field.html" %}
{% endfor %}
</fieldset>
<div class="buttons">
<button>Send Email</button>
</div>
</form>
{% endblock %}

View file

@ -0,0 +1,14 @@
{% extends "base.html" %}
{% block title %}Password Reset Sent{% endblock %}
{% block content %}
<form>
<fieldset>
<legend>Password Reset Sent</legend>
<p>
Please check your email at <tt>{{ email }}</tt> for the reset link.
</p>
</fieldset>
</form>
{% endblock %}

View file

@ -8,7 +8,7 @@
</a> </a>
{% if request.user.admin %} {% if request.user.admin %}
<h3>Account</h3> <h3>Account</h3>
<a href="#" {% if section == "login" %}class="selected"{% endif %}> <a href="{% url "settings_security" %}" {% if section == "security" %}class="selected"{% endif %}>
<i class="fa-solid fa-key"></i> Login &amp; Security <i class="fa-solid fa-key"></i> Login &amp; Security
</a> </a>
<a href="/auth/logout/"> <a href="/auth/logout/">

View file

@ -0,0 +1,17 @@
{% extends "settings/base.html" %}
{% block subtitle %}Login &amp; Security{% endblock %}
{% block content %}
<form action="." method="POST">
{% csrf_token %}
<fieldset>
<legend>Login</legend>
{% include "forms/_field.html" with field=form.email %}
</fieldset>
<fieldset>
<legend>Password</legend>
<p>To change your password, please trigger a <a href="{% url "trigger_reset" %}">password reset</a>.
</fieldset>
</form>
{% endblock %}

View file

@ -44,9 +44,38 @@ class Signup(FormView):
) )
class Reset(FormView): class TriggerReset(FormView):
template_name = "auth/reset.html" template_name = "auth/trigger_reset.html"
class form_class(forms.Form):
email = forms.EmailField(
help_text="We will send a reset link to this email",
)
def clean_email(self):
email = self.cleaned_data.get("email").lower()
if not email:
return
if not User.objects.filter(email=email).exists():
raise forms.ValidationError("This email does not have an account")
return email
def form_valid(self, form):
PasswordReset.create_for_user(
User.objects.get(email=form.cleaned_data["email"])
)
return render(
self.request,
"auth/trigger_reset_success.html",
{"email": form.cleaned_data["email"]},
)
class PerformReset(FormView):
template_name = "auth/perform_reset.html"
class form_class(forms.Form): class form_class(forms.Form):
@ -81,7 +110,7 @@ class Reset(FormView):
self.reset.delete() self.reset.delete()
return render( return render(
self.request, self.request,
"auth/reset_success.html", "auth/perform_reset_success.html",
{"email": self.reset.user.email}, {"email": self.reset.user.email},
) )

View file

@ -126,6 +126,7 @@ class ProfilePage(FormView):
""" """
template_name = "settings/profile.html" template_name = "settings/profile.html"
extra_context = {"section": "profile"}
class form_class(forms.Form): class form_class(forms.Form):
name = forms.CharField(max_length=500) name = forms.CharField(max_length=500)
@ -150,11 +151,6 @@ class ProfilePage(FormView):
"image": self.request.identity.image.url, "image": self.request.identity.image.url,
} }
def get_context_data(self):
context = super().get_context_data()
context["section"] = "profile"
return context
def form_valid(self, form): def form_valid(self, form):
# Update identity name and summary # Update identity name and summary
self.request.identity.name = form.cleaned_data["name"] self.request.identity.name = form.cleaned_data["name"]
@ -174,3 +170,24 @@ class ProfilePage(FormView):
self.request.identity.image = image self.request.identity.image = image
self.request.identity.save() self.request.identity.save()
return redirect(".") return redirect(".")
@method_decorator(identity_required, name="dispatch")
class SecurityPage(FormView):
"""
Lets the identity's profile be edited
"""
template_name = "settings/login_security.html"
extra_context = {"section": "security"}
class form_class(forms.Form):
email = forms.EmailField(
disabled=True,
help_text="Your email address cannot be changed yet.",
)
def get_initial(self):
return {"email": self.request.user.email}
template_name = "settings/login_security.html"