Merge pull request #2166 from bookwyrm-social/email-config-warning

Add warning to dashboard if email sender looks misconfigured
This commit is contained in:
Mouse Reeve 2022-07-03 10:49:14 -07:00 committed by GitHub
commit 0b900dc1ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 109 additions and 82 deletions

View file

@ -37,6 +37,17 @@
</div> </div>
<div class="columns block is-multiline"> <div class="columns block is-multiline">
{% if email_config_error %}
<div class="column is-flex">
<span class="notification is-warning is-block is-flex-grow-1">
{% blocktrans trimmed %}
Your outgoing email address, <code>{{ email_sender }}</code>, may be misconfigured.
{% endblocktrans %}
{% trans "Check the <code>EMAIL_SENDER_NAME</code> and <code>EMAIL_SENDER_DOMAIN</code> in your <code>.env</code>." %}
</span>
</div>
{% endif %}
{% if reports %} {% if reports %}
<div class="column is-flex"> <div class="column is-flex">
<a href="{% url 'settings-reports' %}" class="notification is-warning is-block is-flex-grow-1"> <a href="{% url 'settings-reports' %}" class="notification is-warning is-block is-flex-grow-1">

View file

@ -1,5 +1,7 @@
""" instance overview """ """ instance overview """
from datetime import timedelta from datetime import timedelta
import re
from dateutil.parser import parse from dateutil.parser import parse
from packaging import version from packaging import version
@ -13,6 +15,7 @@ from django.views import View
from bookwyrm import models, settings from bookwyrm import models, settings
from bookwyrm.connectors.abstract_connector import get_data from bookwyrm.connectors.abstract_connector import get_data
from bookwyrm.connectors.connector_manager import ConnectorException from bookwyrm.connectors.connector_manager import ConnectorException
from bookwyrm.utils import regex
# pylint: disable= no-self-use # pylint: disable= no-self-use
@ -26,90 +29,18 @@ class Dashboard(View):
def get(self, request): def get(self, request):
"""list of users""" """list of users"""
interval = int(request.GET.get("days", 1)) data = get_charts_and_stats(request)
now = timezone.now()
start = request.GET.get("start")
if start:
start = timezone.make_aware(parse(start))
else:
start = now - timedelta(days=6 * interval)
end = request.GET.get("end") # Make sure email looks properly configured
end = timezone.make_aware(parse(end)) if end else now email_config_error = re.findall(
start = start.replace(hour=0, minute=0, second=0) r"[\s\@]", settings.EMAIL_SENDER_DOMAIN
) or not re.match(regex.DOMAIN, settings.EMAIL_SENDER_DOMAIN)
user_queryset = models.User.objects.filter(local=True) data["email_config_error"] = email_config_error
user_chart = Chart( # pylint: disable=line-too-long
queryset=user_queryset, data[
queries={ "email_sender"
"total": lambda q, s, e: q.filter( ] = f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}"
Q(is_active=True) | Q(deactivation_date__gt=e),
created_date__lte=e,
).count(),
"active": lambda q, s, e: q.filter(
Q(is_active=True) | Q(deactivation_date__gt=e),
created_date__lte=e,
)
.filter(
last_active_date__gt=e - timedelta(days=31),
)
.count(),
},
)
status_queryset = models.Status.objects.filter(user__local=True, deleted=False)
status_chart = Chart(
queryset=status_queryset,
queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
},
)
register_chart = Chart(
queryset=user_queryset,
queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
},
)
works_chart = Chart(
queryset=models.Work.objects,
queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
},
)
data = {
"start": start.strftime("%Y-%m-%d"),
"end": end.strftime("%Y-%m-%d"),
"interval": interval,
"users": user_queryset.filter(is_active=True).count(),
"active_users": user_queryset.filter(
is_active=True, last_active_date__gte=now - timedelta(days=31)
).count(),
"statuses": status_queryset.count(),
"works": models.Work.objects.count(),
"reports": models.Report.objects.filter(resolved=False).count(),
"pending_domains": models.LinkDomain.objects.filter(
status="pending"
).count(),
"invite_requests": models.InviteRequest.objects.filter(
ignored=False, invite__isnull=True
).count(),
"user_stats": user_chart.get_chart(start, end, interval),
"status_stats": status_chart.get_chart(start, end, interval),
"register_stats": register_chart.get_chart(start, end, interval),
"works_stats": works_chart.get_chart(start, end, interval),
}
# check version # check version
try: try:
@ -126,6 +57,91 @@ class Dashboard(View):
return TemplateResponse(request, "settings/dashboard/dashboard.html", data) return TemplateResponse(request, "settings/dashboard/dashboard.html", data)
def get_charts_and_stats(request):
"""Defines the dashbaord charts"""
interval = int(request.GET.get("days", 1))
now = timezone.now()
start = request.GET.get("start")
if start:
start = timezone.make_aware(parse(start))
else:
start = now - timedelta(days=6 * interval)
end = request.GET.get("end")
end = timezone.make_aware(parse(end)) if end else now
start = start.replace(hour=0, minute=0, second=0)
user_queryset = models.User.objects.filter(local=True)
user_chart = Chart(
queryset=user_queryset,
queries={
"total": lambda q, s, e: q.filter(
Q(is_active=True) | Q(deactivation_date__gt=e),
created_date__lte=e,
).count(),
"active": lambda q, s, e: q.filter(
Q(is_active=True) | Q(deactivation_date__gt=e),
created_date__lte=e,
)
.filter(
last_active_date__gt=e - timedelta(days=31),
)
.count(),
},
)
status_queryset = models.Status.objects.filter(user__local=True, deleted=False)
status_chart = Chart(
queryset=status_queryset,
queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
},
)
register_chart = Chart(
queryset=user_queryset,
queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
},
)
works_chart = Chart(
queryset=models.Work.objects,
queries={
"total": lambda q, s, e: q.filter(
created_date__gt=s,
created_date__lte=e,
).count()
},
)
return {
"start": start.strftime("%Y-%m-%d"),
"end": end.strftime("%Y-%m-%d"),
"interval": interval,
"users": user_queryset.filter(is_active=True).count(),
"active_users": user_queryset.filter(
is_active=True, last_active_date__gte=now - timedelta(days=31)
).count(),
"statuses": status_queryset.count(),
"works": models.Work.objects.count(),
"reports": models.Report.objects.filter(resolved=False).count(),
"pending_domains": models.LinkDomain.objects.filter(status="pending").count(),
"invite_requests": models.InviteRequest.objects.filter(
ignored=False, invite__isnull=True
).count(),
"user_stats": user_chart.get_chart(start, end, interval),
"status_stats": status_chart.get_chart(start, end, interval),
"register_stats": register_chart.get_chart(start, end, interval),
"works_stats": works_chart.get_chart(start, end, interval),
}
class Chart: class Chart:
"""Data for a chart""" """Data for a chart"""