+
+ {% if site.user_exports_enabled %}
+
+
+
+ {% trans "Disable starting new user exports" %}
+
+
+
+
+
@@ -108,7 +135,7 @@
{% trans "Set the value to 0 to not enforce any limit." %}
-
+
{% csrf_token %}
@@ -120,6 +147,28 @@
+ {% else %}
+
+ {% endif %}
{% trans "Book Imports" %}
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py
index 76e60245b..1a577c84b 100644
--- a/bookwyrm/urls.py
+++ b/bookwyrm/urls.py
@@ -338,6 +338,16 @@ urlpatterns = [
views.disable_imports,
name="settings-imports-disable",
),
+ re_path(
+ r"^settings/user-exports/enable/?$",
+ views.enable_user_exports,
+ name="settings-user-exports-enable",
+ ),
+ re_path(
+ r"^settings/user-exports/disable/?$",
+ views.disable_user_exports,
+ name="settings-user-exports-disable",
+ ),
re_path(
r"^settings/imports/enable/?$",
views.enable_imports,
diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py
index 3be813208..f11c11dd6 100644
--- a/bookwyrm/views/__init__.py
+++ b/bookwyrm/views/__init__.py
@@ -18,6 +18,8 @@ from .admin.imports import (
set_import_size_limit,
set_user_import_completed,
set_user_import_limit,
+ enable_user_exports,
+ disable_user_exports,
)
from .admin.ip_blocklist import IPBlocklist
from .admin.invite import ManageInvites, Invite, InviteRequest
diff --git a/bookwyrm/views/admin/imports.py b/bookwyrm/views/admin/imports.py
index a85d6c79e..0924536bf 100644
--- a/bookwyrm/views/admin/imports.py
+++ b/bookwyrm/views/admin/imports.py
@@ -9,7 +9,7 @@ from django.views.decorators.http import require_POST
from bookwyrm import models
from bookwyrm.views.helpers import redirect_to_referer
-from bookwyrm.settings import PAGE_LENGTH
+from bookwyrm.settings import PAGE_LENGTH, USE_S3
# pylint: disable=no-self-use
@@ -59,6 +59,7 @@ class ImportList(View):
"import_size_limit": site_settings.import_size_limit,
"import_limit_reset": site_settings.import_limit_reset,
"user_import_time_limit": site_settings.user_import_time_limit,
+ "use_s3": USE_S3,
}
return TemplateResponse(request, "settings/imports/imports.html", data)
@@ -126,3 +127,25 @@ def set_user_import_limit(request):
site.user_import_time_limit = int(request.POST.get("limit"))
site.save(update_fields=["user_import_time_limit"])
return redirect("settings-imports")
+
+
+@require_POST
+@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
+# pylint: disable=unused-argument
+def enable_user_exports(request):
+ """Allow users to export account data"""
+ site = models.SiteSettings.objects.get()
+ site.user_exports_enabled = True
+ site.save(update_fields=["user_exports_enabled"])
+ return redirect("settings-imports")
+
+
+@require_POST
+@permission_required("bookwyrm.edit_instance_settings", raise_exception=True)
+# pylint: disable=unused-argument
+def disable_user_exports(request):
+ """Don't allow users to export account data"""
+ site = models.SiteSettings.objects.get()
+ site.user_exports_enabled = False
+ site.save(update_fields=["user_exports_enabled"])
+ return redirect("settings-imports")
diff --git a/nginx/development b/nginx/development
index 841db0124..ac663053c 100644
--- a/nginx/development
+++ b/nginx/development
@@ -64,13 +64,18 @@ server {
# directly serve images and static files from the
# bookwyrm filesystem using sendfile.
# make the logs quieter by not reporting these requests
- location ~ ^/(images|static)/ {
+ location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp)$ {
root /app;
try_files $uri =404;
add_header X-Cache-Status STATIC;
access_log off;
}
+ # block access to any non-image files from images or static
+ location ~ ^/(images|static)/ {
+ return 403;
+ }
+
# monitor the celery queues with flower, no caching enabled
location /flower/ {
proxy_pass http://flower:8888;
diff --git a/nginx/production b/nginx/production
index 9018ab9de..4e40f32a0 100644
--- a/nginx/production
+++ b/nginx/production
@@ -96,12 +96,17 @@ server {
# # directly serve images and static files from the
# # bookwyrm filesystem using sendfile.
# # make the logs quieter by not reporting these requests
-# location ~ ^/(images|static)/ {
+# location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp)$ {
# root /app;
# try_files $uri =404;
# add_header X-Cache-Status STATIC;
# access_log off;
# }
+
+# # block access to any non-image files from images or static
+# location ~ ^/(images|static)/ {
+# return 403;
+# }
#
# # monitor the celery queues with flower, no caching enabled
# location /flower/ {
From ea7f3c297e6f92ca82c06b6fb3ace0d37ebdd53f Mon Sep 17 00:00:00 2001
From: Hugh Rundle
Date: Wed, 17 Jan 2024 20:12:06 +1100
Subject: [PATCH 36/56] allow js and css
---
nginx/development | 4 ++--
nginx/production | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/nginx/development b/nginx/development
index ac663053c..64cd1b911 100644
--- a/nginx/development
+++ b/nginx/development
@@ -64,7 +64,7 @@ server {
# directly serve images and static files from the
# bookwyrm filesystem using sendfile.
# make the logs quieter by not reporting these requests
- location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp)$ {
+ location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp|css|js)$ {
root /app;
try_files $uri =404;
add_header X-Cache-Status STATIC;
@@ -72,7 +72,7 @@ server {
}
# block access to any non-image files from images or static
- location ~ ^/(images|static)/ {
+ location ~ ^/images/ {
return 403;
}
diff --git a/nginx/production b/nginx/production
index 4e40f32a0..76ed19449 100644
--- a/nginx/production
+++ b/nginx/production
@@ -96,7 +96,7 @@ server {
# # directly serve images and static files from the
# # bookwyrm filesystem using sendfile.
# # make the logs quieter by not reporting these requests
-# location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp)$ {
+# location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp|css|js)$ {
# root /app;
# try_files $uri =404;
# add_header X-Cache-Status STATIC;
@@ -104,7 +104,7 @@ server {
# }
# # block access to any non-image files from images or static
-# location ~ ^/(images|static)/ {
+# location ~ ^/images/ {
# return 403;
# }
#
From b990d9ccd8f2bff4990b79f7dc7cd494190d0536 Mon Sep 17 00:00:00 2001
From: Hugh Rundle
Date: Wed, 17 Jan 2024 21:06:04 +1100
Subject: [PATCH 37/56] Pass correct user id in Move notification
We were passing the *requesting* user's moved_to value to the Move notification template, instead of the id of the user that they are being notified about.
Additionally, the id_to_username template tag had no fallback for if the user_id is None.
This resolves both problems and removes an unnecessary space in a template for when the logged in user made the move.
Fixes #3196
---
bookwyrm/templates/moved.html | 2 +-
bookwyrm/templates/notifications/items/move_user.html | 2 +-
bookwyrm/templatetags/utilities.py | 3 ++-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/bookwyrm/templates/moved.html b/bookwyrm/templates/moved.html
index 545fc3d87..382b752be 100644
--- a/bookwyrm/templates/moved.html
+++ b/bookwyrm/templates/moved.html
@@ -23,7 +23,7 @@
- {% id_to_username request.user.moved_to as username %}
+ {% id_to_username request.user.moved_to as username %}
{% blocktrans trimmed with moved_to=user.moved_to %}
You have moved your account to {{ username }}
{% endblocktrans %}
diff --git a/bookwyrm/templates/notifications/items/move_user.html b/bookwyrm/templates/notifications/items/move_user.html
index b94d96dc4..3121d3f45 100644
--- a/bookwyrm/templates/notifications/items/move_user.html
+++ b/bookwyrm/templates/notifications/items/move_user.html
@@ -14,7 +14,7 @@
{% block description %}
{% if related_user_moved_to %}
- {% id_to_username request.user.moved_to as username %}
+ {% id_to_username related_user_moved_to as username %}
{% blocktrans trimmed %}
{{ related_user }} has moved to {{ username }}
{% endblocktrans %}
diff --git a/bookwyrm/templatetags/utilities.py b/bookwyrm/templatetags/utilities.py
index fca66688a..230db366e 100644
--- a/bookwyrm/templatetags/utilities.py
+++ b/bookwyrm/templatetags/utilities.py
@@ -125,7 +125,8 @@ def id_to_username(user_id):
name = parts[-1]
value = f"{name}@{domain}"
- return value
+ return value
+ return "a new user account"
@register.filter(name="get_file_size")
From 8e2649ba3b26bc03ff90d8a5790f7b19301ebd34 Mon Sep 17 00:00:00 2001
From: Rohan Sureshkumar
Date: Thu, 18 Jan 2024 21:23:25 +0530
Subject: [PATCH 38/56] Issue-3187: change variable name and code formatting
---
bookwyrm/templates/feed/feed.html | 2 +-
bookwyrm/views/feed.py | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/bookwyrm/templates/feed/feed.html b/bookwyrm/templates/feed/feed.html
index 56c380202..1b6cf29ff 100644
--- a/bookwyrm/templates/feed/feed.html
+++ b/bookwyrm/templates/feed/feed.html
@@ -41,7 +41,7 @@
{% endif %}
- {% if annual_summary_year and tab.key == 'home' and has_read_throughs %}
+ {% if annual_summary_year and tab.key == 'home' and has_summary_read_throughs %}
{% include 'feed/summary_card.html' with year=annual_summary_year %}
diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py
index 45ff00d02..79e2f24d2 100644
--- a/bookwyrm/views/feed.py
+++ b/bookwyrm/views/feed.py
@@ -54,8 +54,7 @@ class Feed(View):
suggestions = suggested_users.get_suggestions(request.user)
cutoff = date(get_annual_summary_year(), 12, 31)
readthroughs = models.ReadThrough.objects.filter(
- user=request.user,
- finish_date__lte=cutoff
+ user=request.user, finish_date__lte=cutoff
)
data = {
@@ -72,7 +71,7 @@ class Feed(View):
"path": f"/{tab['key']}",
"annual_summary_year": get_annual_summary_year(),
"has_tour": True,
- "has_read_throughs": len(readthroughs) > 0,
+ "has_summary_read_throughs": len(readthroughs),
},
}
return TemplateResponse(request, "feed/feed.html", data)
From a59dcfc89002828331ee8eee6fda2d02af4897a5 Mon Sep 17 00:00:00 2001
From: Milan
Date: Thu, 18 Jan 2024 17:03:02 +0100
Subject: [PATCH 39/56] nginx: fix missing ttf static files
---
nginx/development | 2 +-
nginx/production | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/nginx/development b/nginx/development
index 64cd1b911..0054c8c26 100644
--- a/nginx/development
+++ b/nginx/development
@@ -64,7 +64,7 @@ server {
# directly serve images and static files from the
# bookwyrm filesystem using sendfile.
# make the logs quieter by not reporting these requests
- location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp|css|js)$ {
+ location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|ttf|webp|css|js)$ {
root /app;
try_files $uri =404;
add_header X-Cache-Status STATIC;
diff --git a/nginx/production b/nginx/production
index 76ed19449..7cc0bad22 100644
--- a/nginx/production
+++ b/nginx/production
@@ -96,7 +96,7 @@ server {
# # directly serve images and static files from the
# # bookwyrm filesystem using sendfile.
# # make the logs quieter by not reporting these requests
-# location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|webp|css|js)$ {
+# location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|ttf|webp|css|js)$ {
# root /app;
# try_files $uri =404;
# add_header X-Cache-Status STATIC;
From dd5c314bd5e0808ecaedbf31447fd4edc4a3ea06 Mon Sep 17 00:00:00 2001
From: Milan
Date: Thu, 18 Jan 2024 22:29:43 +0100
Subject: [PATCH 40/56] nginx: also serve svg static files
---
nginx/development | 2 +-
nginx/production | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/nginx/development b/nginx/development
index 0054c8c26..fdfd14e1d 100644
--- a/nginx/development
+++ b/nginx/development
@@ -64,7 +64,7 @@ server {
# directly serve images and static files from the
# bookwyrm filesystem using sendfile.
# make the logs quieter by not reporting these requests
- location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|ttf|webp|css|js)$ {
+ location ~ \.(bmp|ico|jpg|jpeg|png|svg|tif|tiff|ttf|webp|css|js)$ {
root /app;
try_files $uri =404;
add_header X-Cache-Status STATIC;
diff --git a/nginx/production b/nginx/production
index 7cc0bad22..296ede70c 100644
--- a/nginx/production
+++ b/nginx/production
@@ -96,7 +96,7 @@ server {
# # directly serve images and static files from the
# # bookwyrm filesystem using sendfile.
# # make the logs quieter by not reporting these requests
-# location ~ \.(bmp|ico|jpg|jpeg|png|tif|tiff|ttf|webp|css|js)$ {
+# location ~ \.(bmp|ico|jpg|jpeg|png|svg|tif|tiff|ttf|webp|css|js)$ {
# root /app;
# try_files $uri =404;
# add_header X-Cache-Status STATIC;
From 6cb3b97144dc20abdbcb7f2c54cd9c5bcb4da3f8 Mon Sep 17 00:00:00 2001
From: Bart Schuurmans
Date: Sat, 20 Jan 2024 16:15:14 +0100
Subject: [PATCH 41/56] Replace python-requests with BookWyrm in user agent
Fixes #3108
---
bookwyrm/settings.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py
index cc941da84..adc9bd0ef 100644
--- a/bookwyrm/settings.py
+++ b/bookwyrm/settings.py
@@ -347,8 +347,7 @@ USE_L10N = True
USE_TZ = True
-agent = requests.utils.default_user_agent()
-USER_AGENT = f"{agent} (BookWyrm/{VERSION}; +https://{DOMAIN}/)"
+USER_AGENT = f"BookWyrm (BookWyrm/{VERSION}; +https://{DOMAIN}/)"
# Imagekit generated thumbnails
ENABLE_THUMBNAIL_GENERATION = env.bool("ENABLE_THUMBNAIL_GENERATION", False)
From f7b4d9ea50ca4593bdfe24518ead29da5093679b Mon Sep 17 00:00:00 2001
From: Bart Schuurmans
Date: Fri, 19 Jan 2024 21:35:12 +0100
Subject: [PATCH 42/56] Give individual status page a title and OpenGraph
description
---
bookwyrm/models/status.py | 45 +++++++++++++++++++++++++++++
bookwyrm/templates/feed/status.html | 12 ++++----
bookwyrm/views/feed.py | 2 ++
3 files changed, 52 insertions(+), 7 deletions(-)
diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py
index cc44fe2bf..04fb8daa3 100644
--- a/bookwyrm/models/status.py
+++ b/bookwyrm/models/status.py
@@ -12,6 +12,8 @@ from django.db.models import Q
from django.dispatch import receiver
from django.template.loader import get_template
from django.utils import timezone
+from django.utils.translation import gettext_lazy as _
+from django.utils.translation import ngettext_lazy
from model_utils import FieldTracker
from model_utils.managers import InheritanceManager
@@ -178,6 +180,16 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
"""you can't boost dms"""
return self.privacy in ["unlisted", "public"]
+ @property
+ def page_title(self):
+ """title of the page when only this status is shown"""
+ return _("%(display_name)s's status") % {"display_name": self.user.display_name}
+
+ @property
+ def page_description(self):
+ """description of the page in meta tags when only this status is shown"""
+ return None
+
def to_replies(self, **kwargs):
"""helper function for loading AP serialized replies to a status"""
return self.to_ordered_collection(
@@ -332,6 +344,13 @@ class Comment(BookStatus):
activity_serializer = activitypub.Comment
+ @property
+ def page_title(self):
+ return _("%(display_name)s's comment on %(book_title)s") % {
+ "display_name": self.user.display_name,
+ "book_title": self.book.title,
+ }
+
class Quotation(BookStatus):
"""like a review but without a rating and transient"""
@@ -374,6 +393,13 @@ class Quotation(BookStatus):
activity_serializer = activitypub.Quotation
+ @property
+ def page_title(self):
+ return _("%(display_name)s's quote from %(book_title)s") % {
+ "display_name": self.user.display_name,
+ "book_title": self.book.title,
+ }
+
class Review(BookStatus):
"""a book review"""
@@ -403,6 +429,13 @@ class Review(BookStatus):
"""indicate the book in question for mastodon (or w/e) users"""
return self.content
+ @property
+ def page_title(self):
+ return _("%(display_name)s's review of %(book_title)s") % {
+ "display_name": self.user.display_name,
+ "book_title": self.book.title,
+ }
+
activity_serializer = activitypub.Review
pure_type = "Article"
@@ -426,6 +459,18 @@ class ReviewRating(Review):
template = get_template("snippets/generated_status/rating.html")
return template.render({"book": self.book, "rating": self.rating}).strip()
+ @property
+ def page_description(self):
+ return ngettext_lazy(
+ "%(display_name)s rated %(book_title)s: %(display_rating).1f star",
+ "%(display_name)s rated %(book_title)s: %(display_rating).1f stars",
+ "display_rating",
+ ) % {
+ "display_name": self.user.display_name,
+ "book_title": self.book.title,
+ "display_rating": self.rating,
+ }
+
activity_serializer = activitypub.Rating
pure_type = "Note"
diff --git a/bookwyrm/templates/feed/status.html b/bookwyrm/templates/feed/status.html
index c05d2ba46..b381c3714 100644
--- a/bookwyrm/templates/feed/status.html
+++ b/bookwyrm/templates/feed/status.html
@@ -2,13 +2,11 @@
{% load feed_page_tags %}
{% load i18n %}
+{% block title %}{{ title }}{% endblock %}
+
+
{% block opengraph %}
- {% firstof status.book status.mention_books.first as book %}
- {% if book %}
- {% include 'snippets/opengraph.html' with image=preview %}
- {% else %}
- {% include 'snippets/opengraph.html' %}
- {% endif %}
+ {% include 'snippets/opengraph.html' with image=preview %}
{% endblock %}
@@ -41,4 +39,4 @@
-{% endblock %}
+{% endblock %}
\ No newline at end of file
diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py
index 17218b93e..2d91990d0 100644
--- a/bookwyrm/views/feed.py
+++ b/bookwyrm/views/feed.py
@@ -197,6 +197,8 @@ class Status(View):
"status": status,
"children": children,
"ancestors": ancestors,
+ "title": status.page_title,
+ "description": status.page_description,
"preview": preview,
},
}
From ad56024ffe8adac7a8cab916b160b2f18edd2f1d Mon Sep 17 00:00:00 2001
From: Bart Schuurmans
Date: Sat, 20 Jan 2024 17:18:50 +0100
Subject: [PATCH 43/56] Add Status.page_image property
---
bookwyrm/models/status.py | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py
index 04fb8daa3..236826a2b 100644
--- a/bookwyrm/models/status.py
+++ b/bookwyrm/models/status.py
@@ -190,6 +190,15 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
"""description of the page in meta tags when only this status is shown"""
return None
+ @property
+ def page_image(self):
+ """image to use as preview in meta tags when only this status is shown"""
+ if self.mention_books.exists():
+ book = self.mention_books.first()
+ return book.preview_image
+ else:
+ return self.user.preview_image
+
def to_replies(self, **kwargs):
"""helper function for loading AP serialized replies to a status"""
return self.to_ordered_collection(
@@ -313,6 +322,10 @@ class BookStatus(Status):
abstract = True
+ @property
+ def page_image(self):
+ return self.book.preview_image or super().page_image
+
class Comment(BookStatus):
"""like a review but without a rating and transient"""
From 290ee997b3c935297811f033d8da0a564ba48f52 Mon Sep 17 00:00:00 2001
From: Bart Schuurmans
Date: Sat, 20 Jan 2024 17:24:20 +0100
Subject: [PATCH 44/56] Refactor OpenGraph tags logic
---
bookwyrm/templates/snippets/opengraph.html | 29 +++++++++++-----------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/bookwyrm/templates/snippets/opengraph.html b/bookwyrm/templates/snippets/opengraph.html
index 1e87a464f..78a6b1b3f 100644
--- a/bookwyrm/templates/snippets/opengraph.html
+++ b/bookwyrm/templates/snippets/opengraph.html
@@ -1,24 +1,25 @@
{% load static %}
-{% if preview_images_enabled is True %}
+{% firstof image site.preview_image as page_image %}
+{% if page_image %}
- {% if image %}
-
-
- {% else %}
-
-
- {% endif %}
+
+
+{% elif site.logo %}
+
+
+
+
{% else %}
-
-
+
+
+
{% endif %}
-
-
-
-
+{% firstof description site.instance_tagline as description %}
+
+
From ea9d3f8ba1ac3db3a050b0355bd3de3d20cd061e Mon Sep 17 00:00:00 2001
From: Bart Schuurmans
Date: Sat, 20 Jan 2024 17:25:20 +0100
Subject: [PATCH 45/56] Use Status.page_image for OpenGraph tags
---
bookwyrm/templates/feed/status.html | 4 ++--
bookwyrm/views/feed.py | 8 +-------
2 files changed, 3 insertions(+), 9 deletions(-)
diff --git a/bookwyrm/templates/feed/status.html b/bookwyrm/templates/feed/status.html
index b381c3714..64e992a01 100644
--- a/bookwyrm/templates/feed/status.html
+++ b/bookwyrm/templates/feed/status.html
@@ -6,7 +6,7 @@
{% block opengraph %}
- {% include 'snippets/opengraph.html' with image=preview %}
+ {% include 'snippets/opengraph.html' with image=page_image %}
{% endblock %}
@@ -39,4 +39,4 @@
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py
index 2d91990d0..d1feb278e 100644
--- a/bookwyrm/views/feed.py
+++ b/bookwyrm/views/feed.py
@@ -185,12 +185,6 @@ class Status(View):
params=[status.id, visible_thread, visible_thread],
)
- preview = None
- if hasattr(status, "book"):
- preview = status.book.preview_image
- elif status.mention_books.exists():
- preview = status.mention_books.first().preview_image
-
data = {
**feed_page_data(request.user),
**{
@@ -199,7 +193,7 @@ class Status(View):
"ancestors": ancestors,
"title": status.page_title,
"description": status.page_description,
- "preview": preview,
+ "page_image": status.page_image,
},
}
return TemplateResponse(request, "feed/status.html", data)
From 646b27b7a7e1099e81d5c3fa4c2b0008f54c889e Mon Sep 17 00:00:00 2001
From: Bart Schuurmans
Date: Sat, 20 Jan 2024 17:28:51 +0100
Subject: [PATCH 46/56] OpenGraph: fall back on book cover when preview images
are disabled
---
bookwyrm/models/status.py | 4 ++--
bookwyrm/templates/book/book.html | 3 ++-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py
index 236826a2b..94893d6ae 100644
--- a/bookwyrm/models/status.py
+++ b/bookwyrm/models/status.py
@@ -195,7 +195,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
"""image to use as preview in meta tags when only this status is shown"""
if self.mention_books.exists():
book = self.mention_books.first()
- return book.preview_image
+ return book.preview_image or book.cover
else:
return self.user.preview_image
@@ -324,7 +324,7 @@ class BookStatus(Status):
@property
def page_image(self):
- return self.book.preview_image or super().page_image
+ return self.book.preview_image or self.book.cover or super().page_image
class Comment(BookStatus):
diff --git a/bookwyrm/templates/book/book.html b/bookwyrm/templates/book/book.html
index 8e76fb014..4c345832e 100644
--- a/bookwyrm/templates/book/book.html
+++ b/bookwyrm/templates/book/book.html
@@ -9,7 +9,8 @@
{% block title %}{{ book|book_title }}{% endblock %}
{% block opengraph %}
- {% include 'snippets/opengraph.html' with title=book.title description=book|book_description image=book.preview_image %}
+ {% firstof book.preview_image book.cover as book_image %}
+ {% include 'snippets/opengraph.html' with title=book.title description=book|book_description image=book_image %}
{% endblock %}
{% block content %}
From eb6bea013fd1634f178da689e4843adcd05a6296 Mon Sep 17 00:00:00 2001
From: Bart Schuurmans
Date: Sun, 21 Jan 2024 11:04:08 +0100
Subject: [PATCH 47/56] Fix pylint warning
---
bookwyrm/models/status.py | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py
index 94893d6ae..0c9b18cc9 100644
--- a/bookwyrm/models/status.py
+++ b/bookwyrm/models/status.py
@@ -196,8 +196,7 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
if self.mention_books.exists():
book = self.mention_books.first()
return book.preview_image or book.cover
- else:
- return self.user.preview_image
+ return self.user.preview_image
def to_replies(self, **kwargs):
"""helper function for loading AP serialized replies to a status"""
From 30ba8d37dc130ac547c59a5b7c2b7fae3d529214 Mon Sep 17 00:00:00 2001
From: Wesley Aptekar-Cassels
Date: Tue, 23 Jan 2024 18:19:31 -0500
Subject: [PATCH 48/56] Add redis automatic rewrite configuration.
This should hopefully prevent the AOF file from growing too large.
---
redis.conf | 3 +++
1 file changed, 3 insertions(+)
diff --git a/redis.conf b/redis.conf
index 2a417579f..79d6804f5 100644
--- a/redis.conf
+++ b/redis.conf
@@ -2,6 +2,9 @@ bind 127.0.0.1 ::1
protected-mode yes
port 6379
+auto-aof-rewrite-percentage 50
+auto-aof-rewrite-min-size 128mb
+
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG ""
From c4596544a341a5030fe02fe7b1df704f343a35ee Mon Sep 17 00:00:00 2001
From: Rohan Sureshkumar
Date: Wed, 24 Jan 2024 19:18:46 +0530
Subject: [PATCH 49/56] Issue-3187: fix failing tests
---
bookwyrm/views/feed.py | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/bookwyrm/views/feed.py b/bookwyrm/views/feed.py
index 79e2f24d2..6e8f820e4 100644
--- a/bookwyrm/views/feed.py
+++ b/bookwyrm/views/feed.py
@@ -52,9 +52,18 @@ class Feed(View):
paginated = Paginator(filtered_activities, PAGE_LENGTH)
suggestions = suggested_users.get_suggestions(request.user)
- cutoff = date(get_annual_summary_year(), 12, 31)
- readthroughs = models.ReadThrough.objects.filter(
- user=request.user, finish_date__lte=cutoff
+
+ cutoff = (
+ date(get_annual_summary_year(), 12, 31)
+ if get_annual_summary_year()
+ else None
+ )
+ readthroughs = (
+ models.ReadThrough.objects.filter(
+ user=request.user, finish_date__lte=cutoff
+ )
+ if get_annual_summary_year()
+ else []
)
data = {
From 2d4b11aaeedd9530ad4ddcfcea6f8aeb2b55dda9 Mon Sep 17 00:00:00 2001
From: Alexey Skobkin
Date: Thu, 25 Jan 2024 01:50:10 +0300
Subject: [PATCH 50/56] Adding FictionBook format ("FB2", "FB3") to
autocomplete options in "Get a copy" block.
---
bookwyrm/static/js/autocomplete.js | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/bookwyrm/static/js/autocomplete.js b/bookwyrm/static/js/autocomplete.js
index a98cd9634..6836d356d 100644
--- a/bookwyrm/static/js/autocomplete.js
+++ b/bookwyrm/static/js/autocomplete.js
@@ -111,6 +111,10 @@ const tries = {
},
},
f: {
+ b: {
+ 2: "FB2",
+ 3: "FB3",
+ },
l: {
a: {
c: "FLAC",
From 82f9aa9da4ae68c2e042bbb981c89d8089cd39dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adeodato=20Sim=C3=B3?=
Date: Wed, 24 Jan 2024 19:30:45 +0100
Subject: [PATCH 51/56] Set SESSION_COOKIE_AGE from environment, default to one
month
While we do wish for a longer maximum age (up to one year, see #3082),
we only want to do that after termination of active sessions is
implemented (see #2278).
In the meantime, by reading and setting the variable from settings,
we allow site admins to alter the default.
---
bookwyrm/settings.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py
index 16241f9df..4af7afb14 100644
--- a/bookwyrm/settings.py
+++ b/bookwyrm/settings.py
@@ -30,6 +30,9 @@ RELEASE_API = env(
PAGE_LENGTH = env.int("PAGE_LENGTH", 15)
DEFAULT_LANGUAGE = env("DEFAULT_LANGUAGE", "English")
+# TODO: extend maximum age to 1 year once termination of active sessions
+# is implemented (see bookwyrm-social#2278, bookwyrm-social#3082).
+SESSION_COOKIE_AGE = env.int("SESSION_COOKIE_AGE", 3600 * 24 * 30) # 1 month
JS_CACHE = "ac315a3b"
From 80ad36e75b20213939852470506f12593353216c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adeodato=20Sim=C3=B3?=
Date: Wed, 24 Jan 2024 19:54:55 +0100
Subject: [PATCH 52/56] Include SESSION_COOKIE_AGE in .env.example
Suggested-by: Alexey Skobkin
---
.env.example | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/.env.example b/.env.example
index 20ce8240b..d0971660e 100644
--- a/.env.example
+++ b/.env.example
@@ -137,6 +137,10 @@ TWO_FACTOR_LOGIN_MAX_SECONDS=60
# and AWS_S3_CUSTOM_DOMAIN (if used) are added by default.
# Value should be a comma-separated list of host names.
CSP_ADDITIONAL_HOSTS=
+
# The last number here means "megabytes"
# Increase if users are having trouble uploading BookWyrm export files.
-DATA_UPLOAD_MAX_MEMORY_SIZE = (1024**2 * 100)
\ No newline at end of file
+DATA_UPLOAD_MAX_MEMORY_SIZE = (1024**2 * 100)
+
+# Time before being logged out (in seconds)
+# SESSION_COOKIE_AGE=2592000 # current default: 30 days
From 31babdfa510d88f89d08cbfb56de94cd8c0ac028 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adeodato=20Sim=C3=B3?=
Date: Fri, 26 Jan 2024 06:01:34 -0300
Subject: [PATCH 53/56] Always prefer shared inboxes when computing receipent
lists
This avoids duplicate submissions to remote instances when mentioning
followers (i.e., `POST /user/foo/inbox` followed by `POST /inbox`, which
results in two separate `add_status` tasks, and might generate duplicates
in the target instance).
---
bookwyrm/models/activitypub_mixin.py | 2 +-
bookwyrm/tests/models/test_activitypub_mixin.py | 12 ++++++++----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py
index d0a941f43..41772a162 100644
--- a/bookwyrm/models/activitypub_mixin.py
+++ b/bookwyrm/models/activitypub_mixin.py
@@ -153,7 +153,7 @@ class ActivitypubMixin:
mentions = self.recipients if hasattr(self, "recipients") else []
# we always send activities to explicitly mentioned users' inboxes
- recipients = [u.inbox for u in mentions or [] if not u.local]
+ recipients = [u.shared_inbox or u.inbox for u in mentions if not u.local]
# unless it's a dm, all the followers should receive the activity
if privacy != "direct":
diff --git a/bookwyrm/tests/models/test_activitypub_mixin.py b/bookwyrm/tests/models/test_activitypub_mixin.py
index cad970412..2f6fad76d 100644
--- a/bookwyrm/tests/models/test_activitypub_mixin.py
+++ b/bookwyrm/tests/models/test_activitypub_mixin.py
@@ -227,14 +227,18 @@ class ActivitypubMixins(TestCase):
shared_inbox="http://example.com/inbox",
outbox="https://example.com/users/nutria/outbox",
)
- MockSelf = namedtuple("Self", ("privacy", "user"))
- mock_self = MockSelf("public", self.local_user)
+ MockSelf = namedtuple("Self", ("privacy", "user", "recipients"))
self.local_user.followers.add(self.remote_user)
self.local_user.followers.add(another_remote_user)
+ mock_self = MockSelf("public", self.local_user, [])
recipients = ActivitypubMixin.get_recipients(mock_self)
- self.assertEqual(len(recipients), 1)
- self.assertEqual(recipients[0], "http://example.com/inbox")
+ self.assertCountEqual(recipients, ["http://example.com/inbox"])
+
+ # should also work with recipient that is a follower
+ mock_self.recipients.append(another_remote_user)
+ recipients = ActivitypubMixin.get_recipients(mock_self)
+ self.assertCountEqual(recipients, ["http://example.com/inbox"])
def test_get_recipients_software(self, *_):
"""should differentiate between bookwyrm and other remote users"""
From 8ac873419fe66de65cdddf6a25560ed24c4e4a63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adeodato=20Sim=C3=B3?=
Date: Fri, 26 Jan 2024 06:29:59 -0300
Subject: [PATCH 54/56] refactor: eagerly use a set in recipients,
get_recipients
---
bookwyrm/models/activitypub_mixin.py | 25 +++++++++++++------------
bookwyrm/models/status.py | 6 +++---
2 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/bookwyrm/models/activitypub_mixin.py b/bookwyrm/models/activitypub_mixin.py
index 41772a162..db737b8bc 100644
--- a/bookwyrm/models/activitypub_mixin.py
+++ b/bookwyrm/models/activitypub_mixin.py
@@ -152,8 +152,9 @@ class ActivitypubMixin:
# find anyone who's tagged in a status, for example
mentions = self.recipients if hasattr(self, "recipients") else []
- # we always send activities to explicitly mentioned users' inboxes
- recipients = [u.shared_inbox or u.inbox for u in mentions if not u.local]
+ # we always send activities to explicitly mentioned users (using shared inboxes
+ # where available to avoid duplicate submissions to a given instance)
+ recipients = {u.shared_inbox or u.inbox for u in mentions if not u.local}
# unless it's a dm, all the followers should receive the activity
if privacy != "direct":
@@ -173,18 +174,18 @@ class ActivitypubMixin:
if user:
queryset = queryset.filter(following=user)
- # ideally, we will send to shared inboxes for efficiency
- shared_inboxes = (
- queryset.filter(shared_inbox__isnull=False)
- .values_list("shared_inbox", flat=True)
- .distinct()
+ # as above, we prefer shared inboxes if available
+ recipients.update(
+ queryset.filter(shared_inbox__isnull=False).values_list(
+ "shared_inbox", flat=True
+ )
)
- # but not everyone has a shared inbox
- inboxes = queryset.filter(shared_inbox__isnull=True).values_list(
- "inbox", flat=True
+ recipients.update(
+ queryset.filter(shared_inbox__isnull=True).values_list(
+ "inbox", flat=True
+ )
)
- recipients += list(shared_inboxes) + list(inboxes)
- return list(set(recipients))
+ return list(recipients)
def to_activity_dataclass(self):
"""convert from a model to an activity"""
diff --git a/bookwyrm/models/status.py b/bookwyrm/models/status.py
index cc44fe2bf..0d1d0d839 100644
--- a/bookwyrm/models/status.py
+++ b/bookwyrm/models/status.py
@@ -107,14 +107,14 @@ class Status(OrderedCollectionPageMixin, BookWyrmModel):
@property
def recipients(self):
"""tagged users who definitely need to get this status in broadcast"""
- mentions = [u for u in self.mention_users.all() if not u.local]
+ mentions = {u for u in self.mention_users.all() if not u.local}
if (
hasattr(self, "reply_parent")
and self.reply_parent
and not self.reply_parent.user.local
):
- mentions.append(self.reply_parent.user)
- return list(set(mentions))
+ mentions.add(self.reply_parent.user)
+ return list(mentions)
@classmethod
def ignore_activity(
From 940274b1c22e08fc870e92cc95e5ae6a95f5297e Mon Sep 17 00:00:00 2001
From: Braden Solt
Date: Fri, 26 Jan 2024 15:47:55 -0700
Subject: [PATCH 55/56] classes that fix widths
---
bookwyrm/templates/confirm_email/confirm_email.html | 4 ++--
bookwyrm/templates/landing/invite.html | 4 ++--
bookwyrm/templates/landing/login.html | 12 +++++++-----
bookwyrm/templates/landing/password_reset.html | 4 ++--
bookwyrm/templates/landing/reactivate.html | 12 +++++++-----
5 files changed, 20 insertions(+), 16 deletions(-)
diff --git a/bookwyrm/templates/confirm_email/confirm_email.html b/bookwyrm/templates/confirm_email/confirm_email.html
index abdd3a734..49a1ebd2d 100644
--- a/bookwyrm/templates/confirm_email/confirm_email.html
+++ b/bookwyrm/templates/confirm_email/confirm_email.html
@@ -6,8 +6,8 @@
{% block content %}
{% trans "Confirm your email address" %}
-
-
+
+
{% trans "A confirmation code has been sent to the email address you used to register your account." %}
{% include 'snippets/form_errors.html' with errors_list=login_form.password.errors id="desc_password" %}
@@ -58,10 +60,10 @@
{% include 'snippets/about.html' %}
{% include 'snippets/form_errors.html' with errors_list=login_form.password.errors id="desc_password" %}
@@ -51,10 +53,10 @@
{% include 'snippets/about.html' %}