From 516c4a9790f1142d2baa4ef641f5a0fc680de07b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 2 Jul 2022 21:02:44 -0700 Subject: [PATCH 1/2] Add warning to dashboard if email sender looks misconfigured This can be a really obscure error, hopefully this warning will catch potential issues. --- bookwyrm/templates/settings/dashboard/dashboard.html | 11 +++++++++++ bookwyrm/views/admin/dashboard.py | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/bookwyrm/templates/settings/dashboard/dashboard.html b/bookwyrm/templates/settings/dashboard/dashboard.html index cec3e89ac..46d552fb1 100644 --- a/bookwyrm/templates/settings/dashboard/dashboard.html +++ b/bookwyrm/templates/settings/dashboard/dashboard.html @@ -37,6 +37,17 @@
+ {% if email_config_error %} +
+ + {% blocktrans trimmed %} + Your outgoing email address, {{ email_sender }}, may be misconfigured. + {% endblocktrans %} + {% trans "Check the EMAIL_SENDER_NAME and EMAIL_SENDER_DOMAIN in your .env." %} + +
+ {% endif %} + {% if reports %}
diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py index b06b6ba00..8b9017bb4 100644 --- a/bookwyrm/views/admin/dashboard.py +++ b/bookwyrm/views/admin/dashboard.py @@ -1,5 +1,7 @@ """ instance overview """ from datetime import timedelta +import re + from dateutil.parser import parse from packaging import version @@ -13,6 +15,7 @@ from django.views import View from bookwyrm import models, settings from bookwyrm.connectors.abstract_connector import get_data from bookwyrm.connectors.connector_manager import ConnectorException +from bookwyrm.utils import regex # pylint: disable= no-self-use @@ -88,6 +91,10 @@ class Dashboard(View): }, ) + email_config_error = re.findall( + r"[\s\@]", settings.EMAIL_SENDER_DOMAIN + ) or not re.match(regex.DOMAIN, settings.EMAIL_SENDER_DOMAIN) + data = { "start": start.strftime("%Y-%m-%d"), "end": end.strftime("%Y-%m-%d"), @@ -109,6 +116,8 @@ class Dashboard(View): "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), + "email_config_error": email_config_error, + "email_sender": f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}", } # check version From 89165fd909ba4f4033f706569d77b2fd5348c8e8 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sun, 3 Jul 2022 08:28:24 -0700 Subject: [PATCH 2/2] Creates helper function for creating charts --- bookwyrm/views/admin/dashboard.py | 177 ++++++++++++++++-------------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/bookwyrm/views/admin/dashboard.py b/bookwyrm/views/admin/dashboard.py index 8b9017bb4..df34fe5bf 100644 --- a/bookwyrm/views/admin/dashboard.py +++ b/bookwyrm/views/admin/dashboard.py @@ -29,96 +29,18 @@ class Dashboard(View): def get(self, request): """list of users""" - 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() - }, - ) + data = get_charts_and_stats(request) + # Make sure email looks properly configured email_config_error = re.findall( r"[\s\@]", settings.EMAIL_SENDER_DOMAIN ) or not re.match(regex.DOMAIN, settings.EMAIL_SENDER_DOMAIN) - 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), - "email_config_error": email_config_error, - "email_sender": f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}", - } + data["email_config_error"] = email_config_error + # pylint: disable=line-too-long + data[ + "email_sender" + ] = f"{settings.EMAIL_SENDER_NAME}@{settings.EMAIL_SENDER_DOMAIN}" # check version try: @@ -135,6 +57,91 @@ class Dashboard(View): 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: """Data for a chart"""