Files
website-v2/users/forms.py

174 lines
5.8 KiB
Python

import os
from django.contrib.auth import get_user_model
from django import forms
from allauth.account.forms import ResetPasswordKeyForm
from .models import Preferences
from news.models import NEWS_MODELS
from news.acl import can_approve
User = get_user_model()
NEWS_ENTRY_CHOICES = [(m.news_type, m._meta.verbose_name.title()) for m in NEWS_MODELS]
class CustomResetPasswordFromKeyForm(ResetPasswordKeyForm):
def save(self, **kwargs):
"""Override default reset password form so we can mark unclaimed
users as claimed once they have reset their passwords."""
result = super().save(**kwargs)
self.user.claim()
return result
class PreferencesForm(forms.ModelForm):
allow_notification_own_news_approved = forms.MultipleChoiceField(
choices=NEWS_ENTRY_CHOICES,
widget=forms.widgets.CheckboxSelectMultiple,
label="Your own news is approved after moderation",
required=False,
)
allow_notification_others_news_posted = forms.MultipleChoiceField(
choices=NEWS_ENTRY_CHOICES,
widget=forms.widgets.CheckboxSelectMultiple,
label="Other users publish their news",
required=False,
)
allow_notification_others_news_needs_moderation = forms.MultipleChoiceField(
choices=NEWS_ENTRY_CHOICES,
widget=forms.widgets.CheckboxSelectMultiple,
label="There are new entries pending moderation",
required=False,
)
allow_notification_terms_changed = forms.BooleanField(
label="The site's Terms of Use or Privacy Policy are changed",
required=False,
)
def __init__(self, *args, instance=None, **kwargs):
if instance is not None:
is_moderator = can_approve(instance.user)
initial = kwargs.pop("initial", {})
for field in self.Meta.fields:
initial[field] = getattr(instance, field)
kwargs["initial"] = initial
else:
is_moderator = False
all_news = Preferences.ALL_NEWS_TYPES
kwargs["initial"] = {i: all_news for i in self.Meta.fields}
# Use default for terms changed field
kwargs["initial"][
"allow_notification_terms_changed"
] = Preferences().allow_notification_terms_changed
super().__init__(*args, instance=instance, **kwargs)
if not is_moderator:
self.fields.pop("allow_notification_others_news_needs_moderation")
self.initial.pop("allow_notification_others_news_needs_moderation")
def save(self, *args, **kwargs):
for field, value in self.cleaned_data.items():
setattr(self.instance, field, value)
return super().save(*args, **kwargs)
class Meta:
model = Preferences
fields = [
"allow_notification_own_news_approved",
"allow_notification_others_news_posted",
"allow_notification_others_news_needs_moderation",
"allow_notification_terms_changed",
]
class UserProfileForm(forms.ModelForm):
class Meta:
model = User
fields = [
"email",
"display_name",
"indicate_last_login_method",
"is_commit_author_name_overridden",
]
labels = {
"display_name": "Username",
"is_commit_author_name_overridden": "Override commit author name",
}
override_msg = (
"Globally replaces your git commit author name with Username "
"value set above."
)
help_texts = {
"display_name": "Your name as it will be displayed across the site.",
"is_commit_author_name_overridden": override_msg,
}
class CustomClearableFileInput(forms.ClearableFileInput):
"""
Overrides the template for clearable file input so that we can display
the widget without the filename/path displayed and change the checkbox
to clear the field.
"""
template_name = "users/clearable_file_input.html"
class UserProfilePhotoForm(forms.ModelForm):
profile_image = forms.FileField(widget=CustomClearableFileInput, required=False)
class Meta:
model = User
fields = ["profile_image"]
def clean(self):
"""Ensure a user can't update their photo if they
don't have permission."""
cleaned_data = super().clean()
if not self.instance.can_update_image:
raise forms.ValidationError(
"You do not have permission to update your profile photo."
)
return cleaned_data
def save(self, commit=True):
# Temporarily store the old image
old_image = self.instance.profile_image
# Save the new image
user = super().save(commit=False)
if not old_image:
# reset image on image delete checked
user.image_uploaded = False
elif self.cleaned_data["profile_image"] != old_image:
# Delete the old image file if there's a new image being uploaded
old_image.delete(save=False)
if new_image := self.cleaned_data.get("profile_image"):
_, file_extension = os.path.splitext(new_image.name)
# Strip the leading period from the file extension.
file_extension = file_extension.lstrip(".")
new_image.name = f"{user.profile_image_filename_root}.{file_extension}"
user.profile_image = new_image
user.image_uploaded = True
if commit:
user.save()
return user
class DeleteAccountForm(forms.Form):
verify = forms.CharField(help_text='To verify, type "delete my account" above.')
def clean_verify(self):
verify = self.cleaned_data["verify"]
if self.cleaned_data["verify"] != "delete my account":
raise forms.ValidationError('Please enter "delete my account"')
return verify