Merge pull request #1620 from bookwyrm-social/email-reports

Email admins when a moderation report is created
This commit is contained in:
Mouse Reeve 2021-11-18 15:02:39 -08:00 committed by GitHub
commit f4ad1dbbdf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 71 additions and 21 deletions

View file

@ -10,14 +10,9 @@ from bookwyrm.settings import DOMAIN
def email_data(): def email_data():
"""fields every email needs""" """fields every email needs"""
site = models.SiteSettings.objects.get() site = models.SiteSettings.objects.get()
if site.logo_small:
logo_path = f"/images/{site.logo_small.url}"
else:
logo_path = "/static/images/logo-small.png"
return { return {
"site_name": site.name, "site_name": site.name,
"logo": logo_path, "logo": site.logo_small_url,
"domain": DOMAIN, "domain": DOMAIN,
"user": None, "user": None,
} }
@ -46,6 +41,18 @@ def password_reset_email(reset_code):
send_email.delay(reset_code.user.email, *format_email("password_reset", data)) send_email.delay(reset_code.user.email, *format_email("password_reset", data))
def moderation_report_email(report):
"""a report was created"""
data = email_data()
data["reporter"] = report.reporter.localname or report.reporter.username
data["reportee"] = report.user.localname or report.user.username
data["report_link"] = report.remote_id
for admin in models.User.objects.filter(groups__name="moderator"):
data["user"] = admin.display_name
send_email.delay(admin.email, *format_email("moderation_report", data))
def format_email(email_name, data): def format_email(email_name, data):
"""render the email templates""" """render the email templates"""
subject = get_template(f"email/{email_name}/subject.html").render(data).strip() subject = get_template(f"email/{email_name}/subject.html").render(data).strip()

View file

@ -1,5 +1,6 @@
""" the particulars for this instance of BookWyrm """ """ the particulars for this instance of BookWyrm """
import datetime import datetime
from urllib.parse import urljoin
from django.db import models, IntegrityError from django.db import models, IntegrityError
from django.dispatch import receiver from django.dispatch import receiver
@ -7,9 +8,10 @@ from django.utils import timezone
from model_utils import FieldTracker from model_utils import FieldTracker
from bookwyrm.preview_images import generate_site_preview_image_task from bookwyrm.preview_images import generate_site_preview_image_task
from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES, STATIC_FULL_URL
from .base_model import BookWyrmModel, new_access_code from .base_model import BookWyrmModel, new_access_code
from .user import User from .user import User
from .fields import get_absolute_url
class SiteSettings(models.Model): class SiteSettings(models.Model):
@ -66,6 +68,28 @@ class SiteSettings(models.Model):
default_settings.save() default_settings.save()
return default_settings return default_settings
@property
def logo_url(self):
"""helper to build the logo url"""
return self.get_url("logo", "images/logo.png")
@property
def logo_small_url(self):
"""helper to build the logo url"""
return self.get_url("logo_small", "images/logo-small.png")
@property
def favicon_url(self):
"""helper to build the logo url"""
return self.get_url("favicon", "images/favicon.png")
def get_url(self, field, default_path):
"""get a media url or a default static path"""
uploaded = getattr(self, field, None)
if uploaded:
return get_absolute_url(uploaded)
return urljoin(STATIC_FULL_URL, default_path)
class SiteInvite(models.Model): class SiteInvite(models.Model):
"""gives someone access to create an account on the instance""" """gives someone access to create an account on the instance"""

View file

@ -2,7 +2,7 @@
<div style="font-family: BlinkMacSystemFont,-apple-system,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Fira Sans','Droid Sans','Helvetica Neue',Helvetica,Arial,sans-serif; border-radius: 6px; background-color: #efefef; max-width: 632px;"> <div style="font-family: BlinkMacSystemFont,-apple-system,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Fira Sans','Droid Sans','Helvetica Neue',Helvetica,Arial,sans-serif; border-radius: 6px; background-color: #efefef; max-width: 632px;">
<div style="padding: 1rem; overflow: auto;"> <div style="padding: 1rem; overflow: auto;">
<div style="float: left; margin-right: 1rem;"> <div style="float: left; margin-right: 1rem;">
<a style="color: #3273dc;" href="https://{{ domain }}" style="text-decoration: none;"><img src="https://{{ domain }}/{{ logo }}" alt="logo"></a> <a style="color: #3273dc;" href="https://{{ domain }}" style="text-decoration: none;"><img src="{{ logo }}" alt="logo"></a>
</div> </div>
<div> <div>
<a style="color: black; text-decoration: none" href="https://{{ domain }}" style="text-decoration: none;"><strong>{{ site_name }}</strong><br> <a style="color: black; text-decoration: none" href="https://{{ domain }}" style="text-decoration: none;"><strong>{{ site_name }}</strong><br>

View file

@ -0,0 +1,11 @@
{% extends 'email/html_layout.html' %}
{% load i18n %}
{% block content %}
<p>
{% blocktrans %}@{{ reporter }} has flagged behavior by @{{ reportee }} for moderation. {% endblocktrans %}
</p>
{% trans "View report" as text %}
{% include 'email/snippets/action.html' with path=report_link text=text %}
{% endblock %}

View file

@ -0,0 +1,2 @@
{% load i18n %}
{% blocktrans %}New report for {{ site_name }}{% endblocktrans %}

View file

@ -0,0 +1,9 @@
{% extends 'email/text_layout.html' %}
{% load i18n %}
{% block content %}
{% blocktrans %}@{{ reporter}} has flagged behavior by @{{ reportee }} for moderation. {% endblocktrans %}
{% trans "View report" %}
{{ report_link }}
{% endblock %}

View file

@ -1,4 +1,4 @@
<html lang="{% get_lang %}"> <html lang="en">
<body> <body>
<div> <div>
<strong>Subject:</strong> {% include subject_path %} <strong>Subject:</strong> {% include subject_path %}

View file

@ -7,7 +7,7 @@ from django.utils.decorators import method_decorator
from django.views import View from django.views import View
from django.views.decorators.http import require_POST from django.views.decorators.http import require_POST
from bookwyrm import forms, models from bookwyrm import emailing, forms, models
# pylint: disable=no-self-use # pylint: disable=no-self-use
@ -142,5 +142,6 @@ def make_report(request):
if not form.is_valid(): if not form.is_valid():
raise ValueError(form.errors) raise ValueError(form.errors)
form.save() report = form.save()
emailing.moderation_report_email(report)
return redirect(request.headers.get("Referer", "/")) return redirect(request.headers.get("Referer", "/"))

View file

@ -48,4 +48,7 @@ def email_preview(request):
data["invite_link"] = "https://example.com/link" data["invite_link"] = "https://example.com/link"
data["confirmation_link"] = "https://example.com/link" data["confirmation_link"] = "https://example.com/link"
data["confirmation_code"] = "AKJHKDGKJSDFG" data["confirmation_code"] = "AKJHKDGKJSDFG"
data["reporter"] = "ConcernedUser"
data["reportee"] = "UserName"
data["report_link"] = "https://example.com/link"
return TemplateResponse(request, "email/preview.html", data) return TemplateResponse(request, "email/preview.html", data)

View file

@ -9,7 +9,7 @@ from django.utils import timezone
from django.views.decorators.http import require_GET from django.views.decorators.http import require_GET
from bookwyrm import models from bookwyrm import models
from bookwyrm.settings import DOMAIN, VERSION, MEDIA_FULL_URL, STATIC_FULL_URL from bookwyrm.settings import DOMAIN, VERSION
@require_GET @require_GET
@ -93,7 +93,7 @@ def instance_info(_):
status_count = models.Status.objects.filter(user__local=True, deleted=False).count() status_count = models.Status.objects.filter(user__local=True, deleted=False).count()
site = models.SiteSettings.get() site = models.SiteSettings.get()
logo = get_image_url(site.logo, "logo.png") logo = site.logo_url
return JsonResponse( return JsonResponse(
{ {
"uri": DOMAIN, "uri": DOMAIN,
@ -134,14 +134,7 @@ def host_meta(request):
def opensearch(request): def opensearch(request):
"""Open Search xml spec""" """Open Search xml spec"""
site = models.SiteSettings.get() site = models.SiteSettings.get()
image = get_image_url(site.favicon, "favicon.png") image = site.favicon_url
return TemplateResponse( return TemplateResponse(
request, "opensearch.xml", {"image": image, "DOMAIN": DOMAIN} request, "opensearch.xml", {"image": image, "DOMAIN": DOMAIN}
) )
def get_image_url(obj, fallback):
"""helper for loading the full path to an image"""
if obj:
return f"{MEDIA_FULL_URL}{obj}"
return f"{STATIC_FULL_URL}images/{fallback}"