Merge pull request #1998 from oragegu/question_invite_correct

Custom question option and field for spammed bookwyrm instances
This commit is contained in:
Mouse Reeve 2022-03-16 16:49:00 -07:00 committed by GitHub
commit 922cc61a5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 68 additions and 6 deletions

View file

@ -407,7 +407,7 @@ class InviteRequestForm(CustomForm):
class Meta: class Meta:
model = models.InviteRequest model = models.InviteRequest
fields = ["email"] fields = ["email", "answer"]
class CreateInviteForm(CustomForm): class CreateInviteForm(CustomForm):

View file

@ -0,0 +1,30 @@
# Generated by Django 3.2.12 on 2022-03-13 22:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("bookwyrm", "0144_alter_announcement_display_type"),
]
operations = [
migrations.AddField(
model_name="inviterequest",
name="answer",
field=models.TextField(blank=True, max_length=50, null=True),
),
migrations.AddField(
model_name="sitesettings",
name="invite_question_text",
field=models.CharField(
blank=True, default="What is your favourite book?", max_length=255
),
),
migrations.AddField(
model_name="sitesettings",
name="invite_request_question",
field=models.BooleanField(default=False),
),
]

View file

@ -48,8 +48,12 @@ class SiteSettings(models.Model):
# registration # registration
allow_registration = models.BooleanField(default=False) allow_registration = models.BooleanField(default=False)
allow_invite_requests = models.BooleanField(default=True) allow_invite_requests = models.BooleanField(default=True)
invite_request_question = models.BooleanField(default=False)
require_confirm_email = models.BooleanField(default=True) require_confirm_email = models.BooleanField(default=True)
invite_question_text = models.CharField(
max_length=255, blank=True, default="What is your favourite book?"
)
# images # images
logo = models.ImageField(upload_to="logos/", null=True, blank=True) logo = models.ImageField(upload_to="logos/", null=True, blank=True)
logo_small = models.ImageField(upload_to="logos/", null=True, blank=True) logo_small = models.ImageField(upload_to="logos/", null=True, blank=True)
@ -99,11 +103,13 @@ class SiteSettings(models.Model):
return urljoin(STATIC_FULL_URL, default_path) return urljoin(STATIC_FULL_URL, default_path)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
"""if require_confirm_email is disabled, make sure no users are pending""" """if require_confirm_email is disabled, make sure no users are pending, if enabled, make sure invite_question_text is not empty"""
if not self.require_confirm_email: if not self.require_confirm_email:
User.objects.filter(is_active=False, deactivation_reason="pending").update( User.objects.filter(is_active=False, deactivation_reason="pending").update(
is_active=True, deactivation_reason=None is_active=True, deactivation_reason=None
) )
if not self.invite_question_text:
self.invite_question_text = "What is your favourite book?"
super().save(*args, **kwargs) super().save(*args, **kwargs)
@ -149,6 +155,7 @@ class InviteRequest(BookWyrmModel):
invite = models.ForeignKey( invite = models.ForeignKey(
SiteInvite, on_delete=models.SET_NULL, null=True, blank=True SiteInvite, on_delete=models.SET_NULL, null=True, blank=True
) )
answer = models.TextField(max_length=50, unique=False, null=True, blank=True)
invite_sent = models.BooleanField(default=False) invite_sent = models.BooleanField(default=False)
ignored = models.BooleanField(default=False) ignored = models.BooleanField(default=False)

View file

@ -70,6 +70,14 @@
{% include 'snippets/form_errors.html' with errors_list=request_form.email.errors id="desc_request_email" %} {% include 'snippets/form_errors.html' with errors_list=request_form.email.errors id="desc_request_email" %}
</div> </div>
{% if site.invite_request_question %}
<div class="block">
<label for="id_answer_register" class="label">{{ site.invite_question_text }}</label>
<input type="answer" name="answer" maxlength="50" class="input" required="true" id="id_answer_register" aria-describedby="desc_answer_register">
{% include 'snippets/form_errors.html' with errors_list=request_form.answer.errors id="desc_answer_register" %}
</div>
{% endif %}
<button type="submit" class="button is-link">{% trans "Submit" %}</button> <button type="submit" class="button is-link">{% trans "Submit" %}</button>
</form> </form>
{% endif %} {% endif %}

View file

@ -40,6 +40,9 @@
{% include 'snippets/table-sort-header.html' with field="invite__invitees__created_date" sort=sort text=text %} {% include 'snippets/table-sort-header.html' with field="invite__invitees__created_date" sort=sort text=text %}
</th> </th>
<th>{% trans "Email" %}</th> <th>{% trans "Email" %}</th>
{% if site.invite_request_question %}
<th>{% trans "Answer" %}</th>
{% endif %}
<th> <th>
{% trans "Status" as text %} {% trans "Status" as text %}
{% include 'snippets/table-sort-header.html' with field="invite__times_used" sort=sort text=text %} {% include 'snippets/table-sort-header.html' with field="invite__times_used" sort=sort text=text %}
@ -54,6 +57,9 @@
<td>{{ req.created_date | naturaltime }}</td> <td>{{ req.created_date | naturaltime }}</td>
<td>{{ req.invite.invitees.first.created_date | naturaltime }}</td> <td>{{ req.invite.invitees.first.created_date | naturaltime }}</td>
<td>{{ req.email }}</td> <td>{{ req.email }}</td>
{% if site.invite_request_question %}
<td>{{ req.answer }}</td>
{% endif %}
<td> <td>
{% if req.invite.times_used %} {% if req.invite.times_used %}
{% trans "Accepted" %} {% trans "Accepted" %}

View file

@ -145,6 +145,18 @@
{% trans "Allow invite requests" %} {% trans "Allow invite requests" %}
</label> </label>
</div> </div>
<div class="field">
<label class="label" for="id_invite_requests_question">
{{ site_form.invite_request_question }}
{% trans "Set a question for invite requests" %}
</label>
</div>
<div class="field">
<label class="label" for="id_invite_question_text">
{% trans "Question:" %}
{{ site_form.invite_question_text }}
</label>
</div>
<div class="field"> <div class="field">
<label class="label mb-0" for="id_require_confirm_email"> <label class="label mb-0" for="id_require_confirm_email">
{{ site_form.require_confirm_email }} {{ site_form.require_confirm_email }}

View file

@ -96,6 +96,7 @@ class ManageInviteRequests(View):
"created_date", "created_date",
"invite__times_used", "invite__times_used",
"invite__invitees__created_date", "invite__invitees__created_date",
"answer",
] ]
# pylint: disable=consider-using-f-string # pylint: disable=consider-using-f-string
if not sort in sort_fields + ["-{:s}".format(f) for f in sort_fields]: if not sort in sort_fields + ["-{:s}".format(f) for f in sort_fields]:
@ -143,6 +144,7 @@ class ManageInviteRequests(View):
invite_request = get_object_or_404( invite_request = get_object_or_404(
models.InviteRequest, id=request.POST.get("invite-request") models.InviteRequest, id=request.POST.get("invite-request")
) )
# only create a new invite if one doesn't exist already (resending) # only create a new invite if one doesn't exist already (resending)
if not invite_request.invite: if not invite_request.invite:
invite_request.invite = models.SiteInvite.objects.create( invite_request.invite = models.SiteInvite.objects.create(
@ -170,10 +172,7 @@ class InviteRequest(View):
received = True received = True
form.save() form.save()
data = { data = {"request_form": form, "request_received": received}
"request_form": form,
"request_received": received,
}
return TemplateResponse(request, "landing/landing.html", data) return TemplateResponse(request, "landing/landing.html", data)