-
Notifications
You must be signed in to change notification settings - Fork 27
Expand file tree
/
Copy pathforms.py
More file actions
184 lines (149 loc) · 6.3 KB
/
Copy pathforms.py
File metadata and controls
184 lines (149 loc) · 6.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import os
from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import UploadedFile
from django import forms
from allauth.account.forms import ResetPasswordKeyForm
from allauth.account.forms import SignupForm
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 CustomSignUpForm(SignupForm):
accept_terms_of_use = forms.BooleanField(required=True)
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):
old_image = self.instance.profile_image
old_image_name = old_image.name if old_image else None
new_image_data = self.cleaned_data.get("profile_image")
has_new_upload = isinstance(new_image_data, UploadedFile)
# Save the new image
user = super().save(commit=False)
if not old_image:
# reset image on image delete checked
user.image_uploaded = False
elif has_new_upload and old_image_name:
# Delete the old file directly from storage (not via FieldFile.delete(),
# which closes file handles and interferes with the pending upload)
old_image.storage.delete(old_image_name)
if has_new_upload:
_, file_extension = os.path.splitext(new_image_data.name)
file_extension = file_extension.lstrip(".")
new_image_data.name = f"{user.profile_image_filename_root}.{file_extension}"
user.profile_image = new_image_data
user.image_uploaded = True
if commit:
user.save()
# Invalidate the cached thumbnail so ImageKit regenerates it
if has_new_upload:
user.delete_cached_thumbnail()
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