diff --git a/bugsink/urls.py b/bugsink/urls.py
index 86da762..100acd2 100644
--- a/bugsink/urls.py
+++ b/bugsink/urls.py
@@ -8,7 +8,7 @@ from alerts.views import debug_email as debug_alerts_email
from users.views import debug_email as debug_users_email
from teams.views import debug_email as debug_teams_email
from bugsink.app_settings import get_settings
-from users.views import signup, confirm_email, resend_confirmation, request_reset_password, reset_password
+from users.views import signup, confirm_email, resend_confirmation, request_reset_password, reset_password, preferences
from .views import home, trigger_error, favicon, settings_view
@@ -31,6 +31,8 @@ urlpatterns = [
path("accounts/login/", auth_views.LoginView.as_view(template_name="bugsink/login.html"), name="login"),
path("accounts/logout/", auth_views.LogoutView.as_view(template_name="users/logged_out.html"), name="logout"),
+ path("accounts/preferences/", preferences, name="preferences"),
+
path('api/', include('ingest.urls')),
path('projects/', include('projects.urls')),
diff --git a/theme/templates/base.html b/theme/templates/base.html
index 814bd05..1acc3ef 100644
--- a/theme/templates/base.html
+++ b/theme/templates/base.html
@@ -34,7 +34,7 @@
{% if logged_in_user.is_anonymous %}
Login
{# I don't think this is actually ever shown in practice, because you must always be logged in #}
{% else %}
- Profile
+ Preferences
{% endif %}
diff --git a/users/forms.py b/users/forms.py
index ee6442d..090d837 100644
--- a/users/forms.py
+++ b/users/forms.py
@@ -11,6 +11,12 @@ from django.forms import ModelForm
from django.utils.html import escape, mark_safe
+TRUE_FALSE_CHOICES = (
+ (True, 'Yes'),
+ (False, 'No')
+)
+
+
def _(x):
# dummy gettext
return x
@@ -101,3 +107,13 @@ class SetPasswordForm(BaseSetPasswordForm):
self.fields['new_password1'].help_text = "At least 8 characters"
self.fields['new_password2'].help_text = None # "Confirm password" is descriptive enough
+
+
+class PreferencesForm(ModelForm):
+ # I haven't gotten a decent display for checkboxes in forms yet; the quickest hack around this is a ChoiceField
+ send_email_alerts = forms.ChoiceField(
+ label=_("Send email alerts"), choices=TRUE_FALSE_CHOICES, required=False, widget=forms.Select())
+
+ class Meta:
+ model = UserModel
+ fields = ("send_email_alerts",)
diff --git a/users/templates/users/preferences.html b/users/templates/users/preferences.html
new file mode 100644
index 0000000..25374ba
--- /dev/null
+++ b/users/templates/users/preferences.html
@@ -0,0 +1,37 @@
+{% extends "base.html" %}
+{% load static %}
+{% load tailwind_forms %}
+
+{% block title %}User Preferences ยท {{ site_title }}{% endblock %}
+
+{% block content %}
+
+
+
+
+{% endblock %}
diff --git a/users/views.py b/users/views.py
index ed0dd6b..cbbd1f3 100644
--- a/users/views.py
+++ b/users/views.py
@@ -5,10 +5,13 @@ from django.shortcuts import render, redirect, reverse
from django.contrib.auth import get_user_model
from django.http import Http404
from django.utils import timezone
+from django.contrib import messages
+from django.contrib.auth.decorators import login_required
from bugsink.app_settings import get_settings, CB_ANYBODY
+from bugsink.decorators import atomic_for_request_method
-from .forms import UserCreationForm, ResendConfirmationForm, RequestPasswordResetForm, SetPasswordForm
+from .forms import UserCreationForm, ResendConfirmationForm, RequestPasswordResetForm, SetPasswordForm, PreferencesForm
from .models import EmailVerification
from .tasks import send_confirm_email, send_reset_email
@@ -150,6 +153,28 @@ def reset_password(request, token=None):
return render(request, "users/reset_password.html", {"form": form, "next": next})
+@atomic_for_request_method
+# in the general case this is done by Middleware but we're under /accounts/. not security-critical because we simply
+# get a failure on request.user if this wasn't there, but still the "right thing"
+@login_required
+def preferences(request):
+ user = request.user
+ if request.method == 'POST':
+ form = PreferencesForm(request.POST, instance=user)
+
+ if form.is_valid():
+ form.save()
+ messages.success(request, "Updated preferences")
+ return redirect('preferences')
+
+ else:
+ form = PreferencesForm(instance=user)
+
+ return render(request, 'users/preferences.html', {
+ 'form': form,
+ })
+
+
DEBUG_CONTEXTS = {
"confirm_email": {
"site_title": get_settings().SITE_TITLE,