From 9804d4cf514585b66d286cc8d1d55a6b13f1eb3b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 10:19:38 -0700 Subject: [PATCH 01/53] Adds more book view tests --- bookwyrm/tests/views/test_book.py | 78 +++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/bookwyrm/tests/views/test_book.py b/bookwyrm/tests/views/test_book.py index 3b6748523..6280f54ff 100644 --- a/bookwyrm/tests/views/test_book.py +++ b/bookwyrm/tests/views/test_book.py @@ -12,6 +12,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory +from django.utils import timezone from bookwyrm import forms, models, views from bookwyrm.activitypub import ActivitypubResponse @@ -52,6 +53,11 @@ class BookViews(TestCase): def test_book_page(self): """there are so many views, this just makes sure it LOADS""" view = views.Book.as_view() + models.ReadThrough.objects.create( + user=self.local_user, + book=self.book, + start_date=timezone.now(), + ) request = self.factory.get("") request.user = self.local_user with patch("bookwyrm.views.books.is_api_request") as is_api: @@ -67,6 +73,78 @@ class BookViews(TestCase): self.assertIsInstance(result, ActivitypubResponse) self.assertEqual(result.status_code, 200) + @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") + def test_book_page_statuses(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Book.as_view() + + review = models.Review.objects.create( + user=self.local_user, + book=self.book, + content="hi", + ) + + comment = models.Comment.objects.create( + user=self.local_user, + book=self.book, + content="hi", + ) + + quote = models.Quotation.objects.create( + user=self.local_user, + book=self.book, + content="hi", + quote="wow", + ) + + request = self.factory.get("") + request.user = self.local_user + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.book.id, user_statuses="review") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["statuses"].object_list[0], review) + + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.book.id, user_statuses="comment") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["statuses"].object_list[0], comment) + + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.book.id, user_statuses="quotation") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["statuses"].object_list[0], quote) + + def test_book_page_invalid_id(self): + """there are so many views, this just makes sure it LOADS""" + view = views.Book.as_view() + request = self.factory.get("") + request.user = self.local_user + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, 0) + self.assertEqual(result.status_code, 404) + + def test_book_page_work_id(self): + """there are so many views, this just makes sure it LOADS""" + view = views.Book.as_view() + request = self.factory.get("") + request.user = self.local_user + with patch("bookwyrm.views.books.is_api_request") as is_api: + is_api.return_value = False + result = view(request, self.work.id) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual(result.context_data["book"], self.book) + def test_edit_book_page(self): """there are so many views, this just makes sure it LOADS""" view = views.EditBook.as_view() From 3abceb8563e3229e8d1ef5d34f89b8667ed917dc Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 10:33:14 -0700 Subject: [PATCH 02/53] Templatetag test --- bookwyrm/tests/test_templatetags.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bookwyrm/tests/test_templatetags.py b/bookwyrm/tests/test_templatetags.py index 3c5d8b258..d75d368c1 100644 --- a/bookwyrm/tests/test_templatetags.py +++ b/bookwyrm/tests/test_templatetags.py @@ -175,3 +175,10 @@ class TemplateTags(TestCase): result = bookwyrm_tags.related_status(notification) self.assertIsInstance(result, models.Status) + + def test_get_next_shelf(self, *_): + """self progress helper""" + self.assertEqual(bookwyrm_tags.get_next_shelf("to-read"), "reading") + self.assertEqual(bookwyrm_tags.get_next_shelf("reading"), "read") + self.assertEqual(bookwyrm_tags.get_next_shelf("read"), "read") + self.assertEqual(bookwyrm_tags.get_next_shelf("blooooga"), "to-read") From 0d2622e4ffbb0436d94dbc81adf22bd6e4cb8d5a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 11:23:38 -0700 Subject: [PATCH 03/53] Tests login view --- bookwyrm/tests/views/test_authentication.py | 64 ++++++++++++++++++++- bookwyrm/views/authentication.py | 3 +- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index 10531f517..e2d67fbe1 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -8,7 +8,7 @@ from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory -from bookwyrm import models, views +from bookwyrm import forms, models, views from bookwyrm.settings import DOMAIN @@ -22,7 +22,7 @@ class AuthenticationViews(TestCase): self.factory = RequestFactory() with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"): self.local_user = models.User.objects.create_user( - "mouse@local.com", + "mouse@your.domain.here", "mouse@mouse.com", "password", local=True, @@ -49,6 +49,66 @@ class AuthenticationViews(TestCase): self.assertEqual(result.url, "/") self.assertEqual(result.status_code, 302) + def test_login_post_localname(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse@mouse.com" + form.data["password"] = "password" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_login_post_username(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse@your.domain.here" + form.data["password"] = "password" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_login_post_email(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse" + form.data["password"] = "password" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_login_post_invalid_credentials(self, _): + """there are so many views, this just makes sure it LOADS""" + view = views.Login.as_view() + form = forms.LoginForm() + form.data["localname"] = "mouse" + form.data["password"] = "passsword1" + request = self.factory.post("", form.data) + request.user = self.anonymous_user + + with patch("bookwyrm.views.authentication.login"): + result = view(request) + result.render() + self.assertEqual(result.status_code, 200) + self.assertEqual( + result.context_data["login_form"].non_field_errors, + "Username or password are incorrect", + ) + def test_register(self, _): """create a user""" view = views.Register.as_view() diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index 003e94b09..6598aef2a 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404, redirect from django.template.response import TemplateResponse from django.utils import timezone from django.utils.decorators import method_decorator +from django.utils.translation import gettext_lazy as _ from django.views.decorators.csrf import csrf_exempt from django.views import View @@ -54,7 +55,7 @@ class Login(View): return redirect(request.GET.get("next", "/")) # login errors - login_form.non_field_errors = "Username or password are incorrect" + login_form.non_field_errors = _("Username or password are incorrect") register_form = forms.RegisterForm() data = {"login_form": login_form, "register_form": register_form} return TemplateResponse(request, "login.html", data) From 568e30230a58d5d1263af36633b304c9dcf5a72b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 11:43:55 -0700 Subject: [PATCH 04/53] Adds start import view test --- bookwyrm/tests/views/test_import.py | 26 ++++++++++++++++++++++++-- locale/de_DE/LC_MESSAGES/django.po | 6 +++++- locale/en_US/LC_MESSAGES/django.po | 6 +++++- locale/es/LC_MESSAGES/django.po | 6 +++++- locale/fr_FR/LC_MESSAGES/django.po | 6 +++++- locale/zh_Hans/LC_MESSAGES/django.po | 6 +++++- locale/zh_Hant/LC_MESSAGES/django.po | 6 +++++- 7 files changed, 54 insertions(+), 8 deletions(-) diff --git a/bookwyrm/tests/views/test_import.py b/bookwyrm/tests/views/test_import.py index 13c0ef5d2..d9d67d568 100644 --- a/bookwyrm/tests/views/test_import.py +++ b/bookwyrm/tests/views/test_import.py @@ -1,11 +1,12 @@ """ test for app action functionality """ +import pathlib from unittest.mock import patch +from django.core.files.uploadedfile import SimpleUploadedFile from django.template.response import TemplateResponse from django.test import TestCase from django.test.client import RequestFactory -from bookwyrm import models -from bookwyrm import views +from bookwyrm import forms, models, views class ImportViews(TestCase): @@ -47,6 +48,27 @@ class ImportViews(TestCase): result.render() self.assertEqual(result.status_code, 200) + def test_start_import(self): + """retry failed items""" + view = views.Import.as_view() + form = forms.ImportForm() + form.data["source"] = "LibraryThing" + form.data["privacy"] = "public" + form.data["include_reviews"] = False + csv_file = pathlib.Path(__file__).parent.joinpath("../data/goodreads.csv") + form.data["csv_file"] = SimpleUploadedFile( + csv_file, open(csv_file, "rb").read(), content_type="text/csv" + ) + + request = self.factory.post("", form.data) + request.user = self.local_user + + with patch("bookwyrm.importers.Importer.start_import"): + view(request) + job = models.ImportJob.objects.get() + self.assertFalse(job.include_reviews) + self.assertEqual(job.privacy, "public") + def test_retry_import(self): """retry failed items""" view = views.ImportStatus.as_view() diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index b047f0310..140f91dcc 100644 --- a/locale/de_DE/LC_MESSAGES/django.po +++ b/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-03-02 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -3295,6 +3295,10 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 #, fuzzy #| msgid "Email address:" diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index 153d8b9a1..ab56046ee 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -2991,6 +2991,10 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "" diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index 5bae4d7e2..dbf7540c7 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -3036,6 +3036,10 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "No un archivo csv válido" diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index 399e40563..b4405df5a 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-04-05 12:44+0100\n" "Last-Translator: Fabien Basmaison \n" "Language-Team: Mouse Reeve \n" @@ -3015,6 +3015,10 @@ msgstr "Ce fichier dépasse la taille limite : 10 Mo" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s (%(subtitle)s)" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "Fichier CSV non valide" diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index d9921655e..471de85d0 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-03-20 00:56+0000\n" "Last-Translator: Kana \n" "Language-Team: Mouse Reeve \n" @@ -2992,6 +2992,10 @@ msgstr "文件超过了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s:%(subtitle)s" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "不是有效的 csv 文件" diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index 5ce42251b..40b12995b 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-05 01:33+0000\n" +"POT-Creation-Date: 2021-08-06 18:34+0000\n" "PO-Revision-Date: 2021-06-30 10:36+0000\n" "Last-Translator: Grace Cheng \n" "Language-Team: LANGUAGE \n" @@ -3011,6 +3011,10 @@ msgstr "檔案超過了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "" +#: bookwyrm/views/authentication.py:58 +msgid "Username or password are incorrect" +msgstr "" + #: bookwyrm/views/import_data.py:67 msgid "Not a valid csv file" msgstr "不是有效的 csv 檔案" From 3082c4ce5c7d7dafa5016cef1a463e1e94412aaa Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 11:55:20 -0700 Subject: [PATCH 05/53] Tests invite create view --- bookwyrm/tests/views/test_invite.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/bookwyrm/tests/views/test_invite.py b/bookwyrm/tests/views/test_invite.py index 1eaf57c03..6ad464208 100644 --- a/bookwyrm/tests/views/test_invite.py +++ b/bookwyrm/tests/views/test_invite.py @@ -52,6 +52,26 @@ class InviteViews(TestCase): result.render() self.assertEqual(result.status_code, 200) + def test_manage_invites_post(self): + """there are so many views, this just makes sure it LOADS""" + view = views.ManageInvites.as_view() + form = forms.CreateInviteForm() + form.data["use_limit"] = 3 + form.data["expiry"] = "" + request = self.factory.post("", form.data) + request.user = self.local_user + request.user.is_superuser = True + + result = view(request) + + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + + invite = models.SiteInvite.objects.get() + self.assertEqual(invite.use_limit, 3) + self.assertIsNone(invite.expiry) + def test_invite_request(self): """request to join a server""" form = forms.InviteRequestForm() From 3e2f1806e9a3d490599665afb442a10ebd8acc5d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 14:42:18 -0700 Subject: [PATCH 06/53] Adds email confirmation code field --- .../migrations/0082_auto_20210806_2141.py | 51 +++++++++++++++++++ bookwyrm/models/base_model.py | 8 +++ bookwyrm/models/site.py | 9 +--- bookwyrm/models/user.py | 3 +- 4 files changed, 62 insertions(+), 9 deletions(-) create mode 100644 bookwyrm/migrations/0082_auto_20210806_2141.py diff --git a/bookwyrm/migrations/0082_auto_20210806_2141.py b/bookwyrm/migrations/0082_auto_20210806_2141.py new file mode 100644 index 000000000..76c8c9628 --- /dev/null +++ b/bookwyrm/migrations/0082_auto_20210806_2141.py @@ -0,0 +1,51 @@ +# Generated by Django 3.2.4 on 2021-08-06 21:41 + +import bookwyrm.models.base_model +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("bookwyrm", "0081_alter_user_last_active_date"), + ] + + operations = [ + migrations.AddField( + model_name="user", + name="confirmation_code", + field=models.CharField( + default=bookwyrm.models.base_model.new_access_code, max_length=32 + ), + ), + migrations.AlterField( + model_name="connector", + name="deactivation_reason", + field=models.CharField( + blank=True, + choices=[ + ("pending", "Pending"), + ("self_deletion", "Self Deletion"), + ("moderator_deletion", "Moderator Deletion"), + ("domain_block", "Domain Block"), + ], + max_length=255, + null=True, + ), + ), + migrations.AlterField( + model_name="user", + name="deactivation_reason", + field=models.CharField( + blank=True, + choices=[ + ("pending", "Pending"), + ("self_deletion", "Self Deletion"), + ("moderator_deletion", "Moderator Deletion"), + ("domain_block", "Domain Block"), + ], + max_length=255, + null=True, + ), + ), + ] diff --git a/bookwyrm/models/base_model.py b/bookwyrm/models/base_model.py index 2cb7c0365..5b55ea50f 100644 --- a/bookwyrm/models/base_model.py +++ b/bookwyrm/models/base_model.py @@ -1,4 +1,6 @@ """ base model with default fields """ +import base64 +from Crypto import Random from django.db import models from django.dispatch import receiver @@ -9,6 +11,7 @@ from .fields import RemoteIdField DeactivationReason = models.TextChoices( "DeactivationReason", [ + "pending", "self_deletion", "moderator_deletion", "domain_block", @@ -16,6 +19,11 @@ DeactivationReason = models.TextChoices( ) +def new_access_code(): + """the identifier for a user invite""" + return base64.b32encode(Random.get_random_bytes(5)).decode("ascii") + + class BookWyrmModel(models.Model): """shared fields""" diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py index 872f6b454..fdc068664 100644 --- a/bookwyrm/models/site.py +++ b/bookwyrm/models/site.py @@ -1,8 +1,6 @@ """ the particulars for this instance of BookWyrm """ -import base64 import datetime -from Crypto import Random from django.db import models, IntegrityError from django.dispatch import receiver from django.utils import timezone @@ -10,7 +8,7 @@ from model_utils import FieldTracker from bookwyrm.preview_images import generate_site_preview_image_task from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES -from .base_model import BookWyrmModel +from .base_model import BookWyrmModel, new_access_code from .user import User @@ -61,11 +59,6 @@ class SiteSettings(models.Model): return default_settings -def new_access_code(): - """the identifier for a user invite""" - return base64.b32encode(Random.get_random_bytes(5)).decode("ascii") - - class SiteInvite(models.Model): """gives someone access to create an account on the instance""" diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index cb6941c9b..08bd87b3c 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -22,7 +22,7 @@ from bookwyrm.signatures import create_key_pair from bookwyrm.tasks import app from bookwyrm.utils import regex from .activitypub_mixin import OrderedCollectionPageMixin, ActivitypubMixin -from .base_model import BookWyrmModel, DeactivationReason +from .base_model import BookWyrmModel, DeactivationReason, new_access_code from .federated_server import FederatedServer from . import fields, Review @@ -123,6 +123,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): deactivation_reason = models.CharField( max_length=255, choices=DeactivationReason.choices, null=True, blank=True ) + confirmation_code = models.CharField(max_length=32, default=new_access_code) name_field = "username" property_fields = [("following_link", "following")] From 247a7f74896e91ba09c6ae3e9467bb332fa8eee9 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 15:38:37 -0700 Subject: [PATCH 07/53] Email confirmation email --- .env.dev.example | 3 +++ .env.prod.example | 3 +++ bookwyrm/emailing.py | 7 +++++++ bookwyrm/models/user.py | 16 +++++++++++++--- bookwyrm/settings.py | 3 +++ .../templates/email/confirm/html_content.html | 14 ++++++++++++++ bookwyrm/templates/email/confirm/subject.html | 4 ++++ .../templates/email/confirm/text_content.html | 11 +++++++++++ bookwyrm/views/authentication.py | 15 ++++++++++++--- bookwyrm/views/site.py | 2 ++ 10 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 bookwyrm/templates/email/confirm/html_content.html create mode 100644 bookwyrm/templates/email/confirm/subject.html create mode 100644 bookwyrm/templates/email/confirm/text_content.html diff --git a/.env.dev.example b/.env.dev.example index f42aaaaec..a74e7bb36 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -36,6 +36,9 @@ FLOWER_PORT=8888 #FLOWER_USER=mouse #FLOWER_PASSWORD=changeme +# make users confirm their email addresses after registration +CONFIRM_EMAIL=false + EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/.env.prod.example b/.env.prod.example index 5115469ca..c5edb55ec 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -36,6 +36,9 @@ FLOWER_PORT=8888 FLOWER_USER=mouse FLOWER_PASSWORD=changeme +# make users confirm their email addresses after registration +CONFIRM_EMAIL=true + EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py index 657310b05..516d64c93 100644 --- a/bookwyrm/emailing.py +++ b/bookwyrm/emailing.py @@ -23,6 +23,13 @@ def email_data(): } +def email_confirmation_email(user): + """newly registered users confirm email address""" + data = email_data() + data["confirmation_code"] = user.confirmation_code + data["confirmation_link"] = user.confirmation_link + send_email.delay(user.email, *format_email("confirm_email", data)) + def invite_email(invite_request): """send out an invite code""" data = email_data() diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index 08bd87b3c..94b7b41e1 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -17,7 +17,7 @@ from bookwyrm.connectors import get_data, ConnectorException from bookwyrm.models.shelf import Shelf from bookwyrm.models.status import Status, Review from bookwyrm.preview_images import generate_user_preview_image_task -from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES +from bookwyrm.settings import DOMAIN, ENABLE_PREVIEW_IMAGES, USE_HTTPS from bookwyrm.signatures import create_key_pair from bookwyrm.tasks import app from bookwyrm.utils import regex @@ -26,6 +26,10 @@ from .base_model import BookWyrmModel, DeactivationReason, new_access_code from .federated_server import FederatedServer from . import fields, Review +def site_link(): + """helper for generating links to the site""" + protocol = "https" if USE_HTTPS else "http" + return f"{protocol}://{DOMAIN}" class User(OrderedCollectionPageMixin, AbstractUser): """a user who wants to read books""" @@ -129,6 +133,12 @@ class User(OrderedCollectionPageMixin, AbstractUser): property_fields = [("following_link", "following")] field_tracker = FieldTracker(fields=["name", "avatar"]) + @property + def confirmation_link(self): + """helper for generating confirmation links""" + link = site_link() + return f"{link}/confirm-email/{self.confirmation_code}" + @property def following_link(self): """just how to find out the following info""" @@ -260,9 +270,9 @@ class User(OrderedCollectionPageMixin, AbstractUser): return # populate fields for local users - self.remote_id = "https://%s/user/%s" % (DOMAIN, self.localname) + self.remote_id = "%s/user/%s" % (site_link(), self.localname) self.inbox = "%s/inbox" % self.remote_id - self.shared_inbox = "https://%s/inbox" % DOMAIN + self.shared_inbox = "%s/inbox" % site_link() self.outbox = "%s/outbox" % self.remote_id # an id needs to be set before we can proceed with related models diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 180191d98..130889ac2 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -24,6 +24,9 @@ CELERY_ACCEPT_CONTENT = ["application/json"] CELERY_TASK_SERIALIZER = "json" CELERY_RESULT_SERIALIZER = "json" +# make users confirm their email addresses after registration +CONFIRM_EMAIL = env("CONFIRM_EMAIL", True) + # email EMAIL_BACKEND = env("EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend") EMAIL_HOST = env("EMAIL_HOST") diff --git a/bookwyrm/templates/email/confirm/html_content.html b/bookwyrm/templates/email/confirm/html_content.html new file mode 100644 index 000000000..b47642af7 --- /dev/null +++ b/bookwyrm/templates/email/confirm/html_content.html @@ -0,0 +1,14 @@ +{% extends 'email/html_layout.html' %} +{% load i18n %} + +{% block content %} +

+{% blocktrans trimmed %} +One last step before you join {{ site_name }}! Please confirm your email address by clicking the link below: +{% endblocktrans %} +

+ +{% trans "Confirm Email" as text %} +{% include 'email/snippets/action.html' with path=confirmation_link text=text %} + +{% endblock %} diff --git a/bookwyrm/templates/email/confirm/subject.html b/bookwyrm/templates/email/confirm/subject.html new file mode 100644 index 000000000..b81a5a83f --- /dev/null +++ b/bookwyrm/templates/email/confirm/subject.html @@ -0,0 +1,4 @@ +{% load i18n %} +{% blocktrans trimmed %} +Please confirm your email +{% endblocktrans %} diff --git a/bookwyrm/templates/email/confirm/text_content.html b/bookwyrm/templates/email/confirm/text_content.html new file mode 100644 index 000000000..e3d739383 --- /dev/null +++ b/bookwyrm/templates/email/confirm/text_content.html @@ -0,0 +1,11 @@ +{% extends 'email/text_layout.html' %} +{% load i18n %} +{% block content %} +{% blocktrans trimmed %} +One last step before you join {{ site_name }}! Please confirm your email address by clicking the link below: +{% endblocktrans %} + +{{ confirmation_link }} + + +{% endblock %} diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index 003e94b09..43b4bb373 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -9,8 +9,8 @@ from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from django.views import View -from bookwyrm import forms, models -from bookwyrm.settings import DOMAIN +from bookwyrm import emailing, forms, models +from bookwyrm.settings import DOMAIN, CONFIRM_EMAIL # pylint: disable= no-self-use @@ -104,13 +104,22 @@ class Register(View): username = "%s@%s" % (localname, DOMAIN) user = models.User.objects.create_user( - username, email, password, localname=localname, local=True + username, + email, + password, + localname=localname, + local=True, + is_active=not CONFIRM_EMAIL, ) if invite: invite.times_used += 1 invite.invitees.add(user) invite.save() + if CONFIRM_EMAIL: + emailing.email_confirmation_email(user) + return redirect("confirm-email") + login(request, user) return redirect("get-started-profile") diff --git a/bookwyrm/views/site.py b/bookwyrm/views/site.py index 46bdf7226..42e8a6dd5 100644 --- a/bookwyrm/views/site.py +++ b/bookwyrm/views/site.py @@ -46,4 +46,6 @@ def email_preview(request): data["text_content_path"] = "email/{}/text_content.html".format(template) data["reset_link"] = "https://example.com/link" data["invite_link"] = "https://example.com/link" + data["confirmation_link"] = "https://example.com/link" + data["confirmation_code"] = "AKJHKDGKJSDFG" return TemplateResponse(request, "email/preview.html", data) From 5926224d7e5784be753da402822ff8e5a9a879f0 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 16:24:57 -0700 Subject: [PATCH 08/53] Confirm email views --- .env.dev.example | 3 - .env.prod.example | 3 - bookwyrm/emailing.py | 1 + ...806_2141.py => 0082_auto_20210806_2324.py} | 7 +- bookwyrm/models/site.py | 1 + bookwyrm/models/user.py | 6 +- bookwyrm/settings.py | 3 - bookwyrm/templates/confirm_email.html | 1 + bookwyrm/urls.py | 7 ++ bookwyrm/views/__init__.py | 1 + bookwyrm/views/authentication.py | 73 +++++++++++++++---- 11 files changed, 78 insertions(+), 28 deletions(-) rename bookwyrm/migrations/{0082_auto_20210806_2141.py => 0082_auto_20210806_2324.py} (87%) create mode 100644 bookwyrm/templates/confirm_email.html diff --git a/.env.dev.example b/.env.dev.example index a74e7bb36..f42aaaaec 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -36,9 +36,6 @@ FLOWER_PORT=8888 #FLOWER_USER=mouse #FLOWER_PASSWORD=changeme -# make users confirm their email addresses after registration -CONFIRM_EMAIL=false - EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/.env.prod.example b/.env.prod.example index c5edb55ec..5115469ca 100644 --- a/.env.prod.example +++ b/.env.prod.example @@ -36,9 +36,6 @@ FLOWER_PORT=8888 FLOWER_USER=mouse FLOWER_PASSWORD=changeme -# make users confirm their email addresses after registration -CONFIRM_EMAIL=true - EMAIL_HOST="smtp.mailgun.org" EMAIL_PORT=587 EMAIL_HOST_USER=mail@your.domain.here diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py index 516d64c93..cf46baf33 100644 --- a/bookwyrm/emailing.py +++ b/bookwyrm/emailing.py @@ -30,6 +30,7 @@ def email_confirmation_email(user): data["confirmation_link"] = user.confirmation_link send_email.delay(user.email, *format_email("confirm_email", data)) + def invite_email(invite_request): """send out an invite code""" data = email_data() diff --git a/bookwyrm/migrations/0082_auto_20210806_2141.py b/bookwyrm/migrations/0082_auto_20210806_2324.py similarity index 87% rename from bookwyrm/migrations/0082_auto_20210806_2141.py rename to bookwyrm/migrations/0082_auto_20210806_2324.py index 76c8c9628..ab0aa158b 100644 --- a/bookwyrm/migrations/0082_auto_20210806_2141.py +++ b/bookwyrm/migrations/0082_auto_20210806_2324.py @@ -1,4 +1,4 @@ -# Generated by Django 3.2.4 on 2021-08-06 21:41 +# Generated by Django 3.2.4 on 2021-08-06 23:24 import bookwyrm.models.base_model from django.db import migrations, models @@ -11,6 +11,11 @@ class Migration(migrations.Migration): ] operations = [ + migrations.AddField( + model_name="sitesettings", + name="require_confirm_email", + field=models.BooleanField(default=True), + ), migrations.AddField( model_name="user", name="confirmation_code", diff --git a/bookwyrm/models/site.py b/bookwyrm/models/site.py index fdc068664..ef3f7c3ca 100644 --- a/bookwyrm/models/site.py +++ b/bookwyrm/models/site.py @@ -31,6 +31,7 @@ class SiteSettings(models.Model): # registration allow_registration = models.BooleanField(default=True) allow_invite_requests = models.BooleanField(default=True) + require_confirm_email = models.BooleanField(default=True) # images logo = models.ImageField(upload_to="logos/", null=True, blank=True) diff --git a/bookwyrm/models/user.py b/bookwyrm/models/user.py index 94b7b41e1..e10bcd293 100644 --- a/bookwyrm/models/user.py +++ b/bookwyrm/models/user.py @@ -26,11 +26,13 @@ from .base_model import BookWyrmModel, DeactivationReason, new_access_code from .federated_server import FederatedServer from . import fields, Review + def site_link(): """helper for generating links to the site""" protocol = "https" if USE_HTTPS else "http" return f"{protocol}://{DOMAIN}" + class User(OrderedCollectionPageMixin, AbstractUser): """a user who wants to read books""" @@ -218,7 +220,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): self.following.order_by("-updated_date").all(), remote_id=remote_id, id_only=True, - **kwargs + **kwargs, ) def to_followers_activity(self, **kwargs): @@ -228,7 +230,7 @@ class User(OrderedCollectionPageMixin, AbstractUser): self.followers.order_by("-updated_date").all(), remote_id=remote_id, id_only=True, - **kwargs + **kwargs, ) def to_activity(self, **kwargs): diff --git a/bookwyrm/settings.py b/bookwyrm/settings.py index 130889ac2..180191d98 100644 --- a/bookwyrm/settings.py +++ b/bookwyrm/settings.py @@ -24,9 +24,6 @@ CELERY_ACCEPT_CONTENT = ["application/json"] CELERY_TASK_SERIALIZER = "json" CELERY_RESULT_SERIALIZER = "json" -# make users confirm their email addresses after registration -CONFIRM_EMAIL = env("CONFIRM_EMAIL", True) - # email EMAIL_BACKEND = env("EMAIL_BACKEND", "django.core.mail.backends.smtp.EmailBackend") EMAIL_HOST = env("EMAIL_HOST") diff --git a/bookwyrm/templates/confirm_email.html b/bookwyrm/templates/confirm_email.html new file mode 100644 index 000000000..ac5b92825 --- /dev/null +++ b/bookwyrm/templates/confirm_email.html @@ -0,0 +1 @@ +{% extends "layout.html" %} diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index d3e2dad1a..e7036feb9 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -46,7 +46,14 @@ urlpatterns = [ re_path("^api/updates/stream/(?P[a-z]+)/?$", views.get_unread_status_count), # authentication re_path(r"^login/?$", views.Login.as_view(), name="login"), + re_path(r"^login/(?Pconfirmed)?$", views.Login.as_view(), name="login"), re_path(r"^register/?$", views.Register.as_view()), + re_path(r"confirm-email/?$", views.ConfirmEmail.as_view(), name="confirm-email"), + re_path( + r"confirm-email/(?P[A-Za-z0-9]+)/?$", + views.ConfirmEmailCode.as_view(), + name="confirm-email-code", + ), re_path(r"^logout/?$", views.Logout.as_view(), name="logout"), re_path( r"^password-reset/?$", diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 41bb64e54..112271a76 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -1,6 +1,7 @@ """ make sure all our nice views are available """ from .announcements import Announcements, Announcement, delete_announcement from .authentication import Login, Register, Logout +from .authentication import ConfirmEmail, ConfirmEmailCode from .author import Author, EditAuthor from .block import Block, unblock from .books import Book, EditBook, ConfirmEditBook, Editions diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index 43b4bb373..edf960cc1 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -10,20 +10,21 @@ from django.views.decorators.csrf import csrf_exempt from django.views import View from bookwyrm import emailing, forms, models -from bookwyrm.settings import DOMAIN, CONFIRM_EMAIL +from bookwyrm.settings import DOMAIN -# pylint: disable= no-self-use +# pylint: disable=no-self-use @method_decorator(csrf_exempt, name="dispatch") class Login(View): """authenticate an existing user""" - def get(self, request): + def get(self, request, confirmed=None): """login page""" if request.user.is_authenticated: return redirect("/") - # sene user to the login page + # send user to the login page data = { + "show_confirmed_email": confirmed, "login_form": forms.LoginForm(), "register_form": forms.RegisterForm(), } @@ -37,14 +38,15 @@ class Login(View): localname = login_form.data["localname"] if "@" in localname: # looks like an email address to me - email = localname try: - username = models.User.objects.get(email=email) + username = models.User.objects.get(email=localname).username except models.User.DoesNotExist: # maybe it's a full username? username = localname else: username = "%s@%s" % (localname, DOMAIN) password = login_form.data["password"] + + # perform authentication user = authenticate(request, username=username, password=password) if user is not None: # successful login @@ -53,6 +55,12 @@ class Login(View): user.save(broadcast=False, update_fields=["last_active_date"]) return redirect(request.GET.get("next", "/")) + # maybe the user is pending email confirmation + if models.User.objects.filter( + username=username, is_active=False, deactivation_reason="pending" + ).exists(): + return redirect("confirm-email") + # login errors login_form.non_field_errors = "Username or password are incorrect" register_form = forms.RegisterForm() @@ -60,12 +68,23 @@ class Login(View): return TemplateResponse(request, "login.html", data) +@method_decorator(login_required, name="dispatch") +class Logout(View): + """log out""" + + def get(self, request): + """done with this place! outa here!""" + logout(request) + return redirect("/") + + class Register(View): """register a user""" def post(self, request): """join the server""" - if not models.SiteSettings.get().allow_registration: + settings = models.SiteSettings.get() + if not settings.allow_registration: invite_code = request.POST.get("invite_code") if not invite_code: @@ -109,14 +128,15 @@ class Register(View): password, localname=localname, local=True, - is_active=not CONFIRM_EMAIL, + deactivation_reason="pending" if settings.require_confirm_email else None, + is_active=not settings.require_confirm_email, ) if invite: invite.times_used += 1 invite.invitees.add(user) invite.save() - if CONFIRM_EMAIL: + if settings.require_confirm_email: emailing.email_confirmation_email(user) return redirect("confirm-email") @@ -124,11 +144,32 @@ class Register(View): return redirect("get-started-profile") -@method_decorator(login_required, name="dispatch") -class Logout(View): - """log out""" +class ConfirmEmail(View): + """enter code to confirm email address""" - def get(self, request): - """done with this place! outa here!""" - logout(request) - return redirect("/") + def get(self, request): # pylint: disable=unused-argument + """you need a code! keep looking""" + settings = models.SiteSettings.get() + if request.user.is_authenticated or not settings.require_confirm_email: + return redirect("/") + + return TemplateResponse(request, "confirm_email.html") + + +class ConfirmEmailCode(View): + """confirm email address""" + + def get(self, request, code): # pylint: disable=unused-argument + """you got the code! good work""" + settings = models.SiteSettings.get() + if request.user.is_authenticated or not settings.require_confirm_email: + return redirect("/") + + # look up the user associated with this code + user = get_object_or_404(models.User, confirmation_code=code) + # update the user + user.is_active = True + user.deactivation_reason = None + user.save(broadcast=False, update_fields=["is_active", "deactivation_reason"]) + # direct the user to log in + return redirect("login", confirmed="confirmed") From 1ad057d89d5e99fc4eff546cb1abe93289f53b9a Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 17:23:44 -0700 Subject: [PATCH 09/53] Confirmation templates --- bookwyrm/emailing.py | 2 +- bookwyrm/templates/confirm_email.html | 1 - .../confirm_email/confirm_email.html | 44 +++++++++++++++++++ .../templates/confirm_email/resend_form.html | 19 ++++++++ bookwyrm/templates/settings/site.html | 7 +++ bookwyrm/views/authentication.py | 34 ++++++++------ 6 files changed, 92 insertions(+), 15 deletions(-) delete mode 100644 bookwyrm/templates/confirm_email.html create mode 100644 bookwyrm/templates/confirm_email/confirm_email.html create mode 100644 bookwyrm/templates/confirm_email/resend_form.html diff --git a/bookwyrm/emailing.py b/bookwyrm/emailing.py index cf46baf33..fff3985ef 100644 --- a/bookwyrm/emailing.py +++ b/bookwyrm/emailing.py @@ -28,7 +28,7 @@ def email_confirmation_email(user): data = email_data() data["confirmation_code"] = user.confirmation_code data["confirmation_link"] = user.confirmation_link - send_email.delay(user.email, *format_email("confirm_email", data)) + send_email.delay(user.email, *format_email("confirm", data)) def invite_email(invite_request): diff --git a/bookwyrm/templates/confirm_email.html b/bookwyrm/templates/confirm_email.html deleted file mode 100644 index ac5b92825..000000000 --- a/bookwyrm/templates/confirm_email.html +++ /dev/null @@ -1 +0,0 @@ -{% extends "layout.html" %} diff --git a/bookwyrm/templates/confirm_email/confirm_email.html b/bookwyrm/templates/confirm_email/confirm_email.html new file mode 100644 index 000000000..85ca2bb1b --- /dev/null +++ b/bookwyrm/templates/confirm_email/confirm_email.html @@ -0,0 +1,44 @@ +{% extends "layout.html" %} +{% load i18n %} + +{% block title %}{% trans "Confirm email" %}{% endblock %} + +{% block content %} +

{% trans "Confirm your email address" %}

+ +
+
+
+
+

{% trans "A confirmation code has been sent to the email address you used to register your account." %}

+ {% if not valid %} +

{% trans "Sorry! We couldn't find that code." %}

+ {% endif %} +
+ {% csrf_token %} + +
+
+ +
+
+ +
+
+
+
+ +
+ {% trans "Can't find your code?" as button_text %} + {% include "snippets/toggle/open_button.html" with text=button_text controls_text="resend-form" focus="resend-form-header" %} + {% include "confirm_email/resend_form.html" with controls_text="resend-form" %} +
+
+
+
+
+ {% include 'snippets/about.html' %} +
+
+
+{% endblock %} diff --git a/bookwyrm/templates/confirm_email/resend_form.html b/bookwyrm/templates/confirm_email/resend_form.html new file mode 100644 index 000000000..00a89403f --- /dev/null +++ b/bookwyrm/templates/confirm_email/resend_form.html @@ -0,0 +1,19 @@ +{% extends "components/inline_form.html" %} +{% load i18n %} +{% block header %} +{% trans "Resend confirmation link" %} +{% endblock %} + +{% block form %} +
+
+ +
+ +
+
+
+ +
+
+{% endblock %} diff --git a/bookwyrm/templates/settings/site.html b/bookwyrm/templates/settings/site.html index d36371a41..f64b529ad 100644 --- a/bookwyrm/templates/settings/site.html +++ b/bookwyrm/templates/settings/site.html @@ -91,6 +91,13 @@ {% trans "Allow invite requests" %} +
+ +

{% trans "(Recommended if registration is open)" %}

+
{{ site_form.registration_closed_text }} diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index edf960cc1..dedcf408a 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -144,18 +144,6 @@ class Register(View): return redirect("get-started-profile") -class ConfirmEmail(View): - """enter code to confirm email address""" - - def get(self, request): # pylint: disable=unused-argument - """you need a code! keep looking""" - settings = models.SiteSettings.get() - if request.user.is_authenticated or not settings.require_confirm_email: - return redirect("/") - - return TemplateResponse(request, "confirm_email.html") - - class ConfirmEmailCode(View): """confirm email address""" @@ -166,10 +154,30 @@ class ConfirmEmailCode(View): return redirect("/") # look up the user associated with this code - user = get_object_or_404(models.User, confirmation_code=code) + try: + user = models.User.objects.get(confirmation_code=code) + except models.User.DoesNotExist: + return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": False}) # update the user user.is_active = True user.deactivation_reason = None user.save(broadcast=False, update_fields=["is_active", "deactivation_reason"]) # direct the user to log in return redirect("login", confirmed="confirmed") + + +class ConfirmEmail(View): + """enter code to confirm email address""" + + def get(self, request): # pylint: disable=unused-argument + """you need a code! keep looking""" + settings = models.SiteSettings.get() + if request.user.is_authenticated or not settings.require_confirm_email: + return redirect("/") + + return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": True}) + + def post(self, request): + """same as clicking the link""" + code = request.POST.get("code") + return ConfirmEmailCode().get(request, code) From 9077516fa14c9d64c06d1a81e0c2185d63d74229 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 17:39:22 -0700 Subject: [PATCH 10/53] Resend links --- .../confirm_email/confirm_email.html | 2 +- .../templates/confirm_email/resend_form.html | 5 +++-- bookwyrm/templates/login.html | 5 +++++ bookwyrm/urls.py | 1 + bookwyrm/views/__init__.py | 2 +- bookwyrm/views/authentication.py | 22 +++++++++++++++++-- 6 files changed, 31 insertions(+), 6 deletions(-) diff --git a/bookwyrm/templates/confirm_email/confirm_email.html b/bookwyrm/templates/confirm_email/confirm_email.html index 85ca2bb1b..6c9eda5ee 100644 --- a/bookwyrm/templates/confirm_email/confirm_email.html +++ b/bookwyrm/templates/confirm_email/confirm_email.html @@ -19,7 +19,7 @@
- +
diff --git a/bookwyrm/templates/confirm_email/resend_form.html b/bookwyrm/templates/confirm_email/resend_form.html index 00a89403f..7c0c10980 100644 --- a/bookwyrm/templates/confirm_email/resend_form.html +++ b/bookwyrm/templates/confirm_email/resend_form.html @@ -5,11 +5,12 @@ {% endblock %} {% block form %} -
+ + {% csrf_token %}
- +
diff --git a/bookwyrm/templates/login.html b/bookwyrm/templates/login.html index e3d0133cf..19c103eac 100644 --- a/bookwyrm/templates/login.html +++ b/bookwyrm/templates/login.html @@ -11,8 +11,13 @@ {% if login_form.non_field_errors %}

{{ login_form.non_field_errors }}

{% endif %} + + {% if show_confirmed_email %} +

{% trans "Success! Email address confirmed." %}

+ {% endif %} {% csrf_token %} + {% if show_confirmed_email %}{% endif %}
diff --git a/bookwyrm/urls.py b/bookwyrm/urls.py index e7036feb9..eb8491a94 100644 --- a/bookwyrm/urls.py +++ b/bookwyrm/urls.py @@ -54,6 +54,7 @@ urlpatterns = [ views.ConfirmEmailCode.as_view(), name="confirm-email-code", ), + re_path(r"resend-link", views.resend_link, name="resend-link"), re_path(r"^logout/?$", views.Logout.as_view(), name="logout"), re_path( r"^password-reset/?$", diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index 112271a76..eccb7f5e5 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -1,7 +1,7 @@ """ make sure all our nice views are available """ from .announcements import Announcements, Announcement, delete_announcement from .authentication import Login, Register, Logout -from .authentication import ConfirmEmail, ConfirmEmailCode +from .authentication import ConfirmEmail, ConfirmEmailCode, resend_link from .author import Author, EditAuthor from .block import Block, unblock from .books import Book, EditBook, ConfirmEditBook, Editions diff --git a/bookwyrm/views/authentication.py b/bookwyrm/views/authentication.py index dedcf408a..f81be8d15 100644 --- a/bookwyrm/views/authentication.py +++ b/bookwyrm/views/authentication.py @@ -7,6 +7,7 @@ from django.template.response import TemplateResponse from django.utils import timezone from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt +from django.views.decorators.http import require_POST from django.views import View from bookwyrm import emailing, forms, models @@ -53,6 +54,8 @@ class Login(View): login(request, user) user.last_active_date = timezone.now() user.save(broadcast=False, update_fields=["last_active_date"]) + if request.POST.get("first_login"): + return redirect("get-started-profile") return redirect(request.GET.get("next", "/")) # maybe the user is pending email confirmation @@ -157,7 +160,9 @@ class ConfirmEmailCode(View): try: user = models.User.objects.get(confirmation_code=code) except models.User.DoesNotExist: - return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": False}) + return TemplateResponse( + request, "confirm_email/confirm_email.html", {"valid": False} + ) # update the user user.is_active = True user.deactivation_reason = None @@ -175,9 +180,22 @@ class ConfirmEmail(View): if request.user.is_authenticated or not settings.require_confirm_email: return redirect("/") - return TemplateResponse(request, "confirm_email/confirm_email.html", {"valid": True}) + return TemplateResponse( + request, "confirm_email/confirm_email.html", {"valid": True} + ) def post(self, request): """same as clicking the link""" code = request.POST.get("code") return ConfirmEmailCode().get(request, code) + + +@require_POST +def resend_link(request): + """resend confirmation link""" + email = request.POST.get("email") + user = get_object_or_404(models.User, email=email) + emailing.email_confirmation_email(user) + return TemplateResponse( + request, "confirm_email/confirm_email.html", {"valid": True} + ) From cec69430692ee29075fab8d45ced4ae9e497abc4 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 17:43:50 -0700 Subject: [PATCH 11/53] Adds missing mock --- bookwyrm/tests/views/test_book.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_book.py b/bookwyrm/tests/views/test_book.py index 6280f54ff..c5d86a12d 100644 --- a/bookwyrm/tests/views/test_book.py +++ b/bookwyrm/tests/views/test_book.py @@ -74,7 +74,8 @@ class BookViews(TestCase): self.assertEqual(result.status_code, 200) @patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay") - def test_book_page_statuses(self, _): + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_book_page_statuses(self, *_): """there are so many views, this just makes sure it LOADS""" view = views.Book.as_view() From 98a98f8e691f533edaef220877e145207a7661b2 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 18:13:51 -0700 Subject: [PATCH 12/53] Updates test env --- .github/workflows/django-tests.yml | 1 + bookwyrm/tests/views/test_authentication.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/django-tests.yml b/.github/workflows/django-tests.yml index 03147744a..038751935 100644 --- a/.github/workflows/django-tests.yml +++ b/.github/workflows/django-tests.yml @@ -36,6 +36,7 @@ jobs: env: SECRET_KEY: beepbeep DEBUG: false + USE_HTTPS: true DOMAIN: your.domain.here BOOKWYRM_DATABASE_BACKEND: postgres MEDIA_ROOT: images/ diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index e2d67fbe1..bbafe7bd5 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -31,7 +31,9 @@ class AuthenticationViews(TestCase): self.anonymous_user = AnonymousUser self.anonymous_user.is_authenticated = False - self.settings = models.SiteSettings.objects.create(id=1) + self.settings = models.SiteSettings.objects.create( + id=1, require_email_confirmation=False + ) def test_login_get(self, _): """there are so many views, this just makes sure it LOADS""" From a3d5a0347770e6eb6621aed5a362a5d6abd0fe28 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 18:47:25 -0700 Subject: [PATCH 13/53] Updates locales --- locale/de_DE/LC_MESSAGES/django.po | 121 +++++++++++++++++++------- locale/en_US/LC_MESSAGES/django.po | 108 +++++++++++++++++------ locale/es/LC_MESSAGES/django.po | 121 ++++++++++++++++++++------ locale/fr_FR/LC_MESSAGES/django.po | 123 ++++++++++++++++++++------- locale/zh_Hans/LC_MESSAGES/django.po | 118 +++++++++++++++++++------ locale/zh_Hant/LC_MESSAGES/django.po | 118 +++++++++++++++++++------ 6 files changed, 552 insertions(+), 157 deletions(-) diff --git a/locale/de_DE/LC_MESSAGES/django.po b/locale/de_DE/LC_MESSAGES/django.po index 140f91dcc..4906082a5 100644 --- a/locale/de_DE/LC_MESSAGES/django.po +++ b/locale/de_DE/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-03-02 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -306,7 +306,7 @@ msgstr "" #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 -#: bookwyrm/templates/settings/site.html:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -739,6 +739,58 @@ msgstr "Schließen" msgid "Compose status" msgstr "Status teilen" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "Bestätigen" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "E-Mail Adresse" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "Passwort bestätigen:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "Absenden" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "E-Mail Adresse" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +msgid "Resend link" +msgstr "" + #: bookwyrm/templates/directory/community_filter.html:5 #, fuzzy #| msgid "Comment" @@ -882,7 +934,7 @@ msgid "Join %(name)s" msgstr "Tritt %(name)s bei" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "Diese Instanz ist geschlossen" @@ -894,22 +946,26 @@ msgstr "" msgid "Request an Invitation" msgstr "" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "E-Mail Adresse" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "Absenden" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "Dein Account" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "Bestätigen" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1342,7 +1398,7 @@ msgid "Imported" msgstr "Importiert" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "Erstelle einen Account" @@ -1412,7 +1468,7 @@ msgid "Notifications" msgstr "Benachrichtigungen" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "" @@ -1421,12 +1477,12 @@ msgstr "" msgid "password" msgstr "Passwort" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "Passwort vergessen?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "Anmelden" @@ -1619,16 +1675,20 @@ msgstr "Deine Listen" msgid "Login" msgstr "" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "Passwort:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "Kontaktiere für eine Einladung eine*n Admin" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "Mehr über diese Seite" @@ -2554,7 +2614,15 @@ msgstr "Registrierungen erlauben" msgid "Allow invite requests" msgstr "Folgeanfragen" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "Registrierungen geschlossen text" @@ -3295,7 +3363,7 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" @@ -3375,11 +3443,6 @@ msgstr "" #~ msgid "Enter a valid integer." #~ msgstr "E-Mail Adresse" -#, fuzzy -#~| msgid "Email address:" -#~ msgid "Enter a valid email address." -#~ msgstr "E-Mail Adresse" - #, fuzzy #~| msgid "Email address:" #~ msgid "Enter a valid IPv4 address." diff --git a/locale/en_US/LC_MESSAGES/django.po b/locale/en_US/LC_MESSAGES/django.po index ab56046ee..e8e3b0b31 100644 --- a/locale/en_US/LC_MESSAGES/django.po +++ b/locale/en_US/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-02-28 17:19-0800\n" "Last-Translator: Mouse Reeve \n" "Language-Team: English \n" @@ -282,7 +282,7 @@ msgstr "" #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 -#: bookwyrm/templates/settings/site.html:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -680,6 +680,52 @@ msgstr "" msgid "Compose status" msgstr "" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +msgid "Confirm email" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +msgid "Confirm your email address" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +msgid "Confirmation code:" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +msgid "Resend link" +msgstr "" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "" @@ -806,7 +852,7 @@ msgid "Join %(name)s" msgstr "" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "" @@ -818,22 +864,24 @@ msgstr "" msgid "Request an Invitation" msgstr "" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +msgid "Confirm Email" +msgstr "" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1235,7 +1283,7 @@ msgid "Imported" msgstr "" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "" @@ -1303,7 +1351,7 @@ msgid "Notifications" msgstr "" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "" @@ -1312,12 +1360,12 @@ msgstr "" msgid "password" msgstr "" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "" @@ -1493,16 +1541,20 @@ msgstr "" msgid "Login" msgstr "" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "" @@ -2315,7 +2367,15 @@ msgstr "" msgid "Allow invite requests" msgstr "" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "" @@ -2991,7 +3051,7 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" diff --git a/locale/es/LC_MESSAGES/django.po b/locale/es/LC_MESSAGES/django.po index dbf7540c7..9fc28535e 100644 --- a/locale/es/LC_MESSAGES/django.po +++ b/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-03-19 11:49+0800\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -288,7 +288,7 @@ msgstr "Clave Goodreads:" #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 -#: bookwyrm/templates/settings/site.html:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -688,6 +688,60 @@ msgstr "Cerrar" msgid "Compose status" msgstr "Componer status" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "Confirmar" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Enter a valid email address." +msgid "Confirm your email address" +msgstr "Ingrese una dirección de correo electrónico válida." + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "Confirmar contraseña:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "Enviar" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "Dirección de correo electrónico:" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "Re-enviar invitación" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "Comunidad" @@ -816,7 +870,7 @@ msgid "Join %(name)s" msgstr "Unirse con %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "Esta instancia está cerrada." @@ -828,22 +882,26 @@ msgstr "¡Gracias! Tu solicitud ha sido recibido." msgid "Request an Invitation" msgstr "Solicitar una invitación" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "Dirección de correo electrónico:" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "Enviar" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "Tu cuenta" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "Confirmar" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1250,7 +1308,7 @@ msgid "Imported" msgstr "Importado" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "Crear una cuenta" @@ -1318,7 +1376,7 @@ msgid "Notifications" msgstr "Notificaciones" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nombre de usuario:" @@ -1327,12 +1385,12 @@ msgstr "Nombre de usuario:" msgid "password" msgstr "contraseña" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "¿Olvidaste tu contraseña?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "Iniciar sesión" @@ -1510,16 +1568,20 @@ msgstr "Tus listas" msgid "Login" msgstr "Iniciar sesión" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "Contraseña:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "Contactar a unx administradorx para recibir una invitación" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "Más sobre este sitio" @@ -2351,7 +2413,15 @@ msgstr "Permitir registración:" msgid "Allow invite requests" msgstr "Permitir solicitudes de invitación:" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "Texto de registración cerrada:" @@ -3036,7 +3106,7 @@ msgstr "" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" @@ -3117,9 +3187,6 @@ msgstr "Un enlace para reestablecer tu contraseña se enviará a %s" #~ msgid "Enter a valid integer." #~ msgstr "Ingrese un entero válido." -#~ msgid "Enter a valid email address." -#~ msgstr "Ingrese una dirección de correo electrónico válida." - #~ msgid "Enter a valid “slug” consisting of letters, numbers, underscores or hyphens." #~ msgstr "Ingrese un “slug” válido que consiste de letras, numeros, guiones bajos, o guiones" diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index b4405df5a..f0a559f97 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-04-05 12:44+0100\n" "Last-Translator: Fabien Basmaison \n" "Language-Team: Mouse Reeve \n" @@ -286,7 +286,7 @@ msgstr "Clé Goodreads :" #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 -#: bookwyrm/templates/settings/site.html:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -684,6 +684,60 @@ msgstr "Fermer" msgid "Compose status" msgstr "Rédiger un statut" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "Confirmer" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "Adresse email :" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "Confirmez le mot de passe :" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "Valider" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "Adresse email :" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "Envoyer l’invitation de nouveau" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "Communauté" @@ -812,7 +866,7 @@ msgid "Join %(name)s" msgstr "Rejoignez %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "Cette instance est fermée" @@ -824,22 +878,26 @@ msgstr "Merci ! Votre demande a bien été reçue." msgid "Request an Invitation" msgstr "Demander une invitation" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "Adresse email :" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "Valider" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "Votre compte" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "Confirmer" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1246,7 +1304,7 @@ msgid "Imported" msgstr "Importé" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "Créer un compte" @@ -1314,7 +1372,7 @@ msgid "Notifications" msgstr "Notifications" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "Nom du compte :" @@ -1323,12 +1381,12 @@ msgstr "Nom du compte :" msgid "password" msgstr "Mot de passe" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "Mot de passe oublié ?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "Se connecter" @@ -1504,16 +1562,20 @@ msgstr "Vos listes" msgid "Login" msgstr "Connexion" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "Mot de passe :" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "Contacter un administrateur pour obtenir une invitation" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "En savoir plus sur ce site" @@ -2333,7 +2395,15 @@ msgstr "Autoriser les inscriptions" msgid "Allow invite requests" msgstr "Autoriser les demandes d’invitation" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "Texte affiché lorsque les inscriptions sont closes :" @@ -3015,7 +3085,7 @@ msgstr "Ce fichier dépasse la taille limite : 10 Mo" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s (%(subtitle)s)" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" @@ -3066,11 +3136,6 @@ msgstr "Un lien de réinitialisation a été envoyé à %s." #~ msgid "Enter a valid integer." #~ msgstr "Adresse email :" -#, fuzzy -#~| msgid "Email address:" -#~ msgid "Enter a valid email address." -#~ msgstr "Adresse email :" - #, fuzzy #~| msgid "Email address:" #~ msgid "Enter a valid IPv4 address." diff --git a/locale/zh_Hans/LC_MESSAGES/django.po b/locale/zh_Hans/LC_MESSAGES/django.po index 471de85d0..adb0d36c6 100644 --- a/locale/zh_Hans/LC_MESSAGES/django.po +++ b/locale/zh_Hans/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-03-20 00:56+0000\n" "Last-Translator: Kana \n" "Language-Team: Mouse Reeve \n" @@ -284,7 +284,7 @@ msgstr "Goodreads key:" #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 -#: bookwyrm/templates/settings/site.html:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -681,6 +681,60 @@ msgstr "关闭" msgid "Compose status" msgstr "撰写状态" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "确认" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "邮箱地址:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "确认密码:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "提交" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "邮箱地址:" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "重新发送请求" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "社区" @@ -807,7 +861,7 @@ msgid "Join %(name)s" msgstr "加入 %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "本实例不开放。" @@ -819,22 +873,26 @@ msgstr "谢谢你!我们已经收到了你的请求。" msgid "Request an Invitation" msgstr "请求邀请" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "邮箱地址:" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "提交" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "你的帐号" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "确认" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1237,7 +1295,7 @@ msgid "Imported" msgstr "已导入" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "创建帐号" @@ -1305,7 +1363,7 @@ msgid "Notifications" msgstr "通知" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "用户名:" @@ -1314,12 +1372,12 @@ msgstr "用户名:" msgid "password" msgstr "密码" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "忘记了密码?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "登录" @@ -1495,16 +1553,20 @@ msgstr "你的列表" msgid "Login" msgstr "登录" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "密码:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "联系管理员以取得邀请" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "更多关于本站点的信息" @@ -2319,7 +2381,15 @@ msgstr "允许注册" msgid "Allow invite requests" msgstr "允许请求邀请" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "注册关闭文字:" @@ -2992,7 +3062,7 @@ msgstr "文件超过了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "%(title)s:%(subtitle)s" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" diff --git a/locale/zh_Hant/LC_MESSAGES/django.po b/locale/zh_Hant/LC_MESSAGES/django.po index 40b12995b..c496bb924 100644 --- a/locale/zh_Hant/LC_MESSAGES/django.po +++ b/locale/zh_Hant/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2021-08-06 18:34+0000\n" +"POT-Creation-Date: 2021-08-07 01:35+0000\n" "PO-Revision-Date: 2021-06-30 10:36+0000\n" "Last-Translator: Grace Cheng \n" "Language-Team: LANGUAGE \n" @@ -288,7 +288,7 @@ msgstr "Goodreads key:" #: bookwyrm/templates/settings/announcement_form.html:69 #: bookwyrm/templates/settings/edit_server.html:68 #: bookwyrm/templates/settings/federated_server.html:98 -#: bookwyrm/templates/settings/site.html:101 +#: bookwyrm/templates/settings/site.html:108 #: bookwyrm/templates/snippets/shelve_button/finish_reading_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/progress_update_modal.html:42 #: bookwyrm/templates/snippets/shelve_button/start_reading_modal.html:36 @@ -687,6 +687,60 @@ msgstr "關閉" msgid "Compose status" msgstr "撰寫狀態" +#: bookwyrm/templates/confirm_email/confirm_email.html:4 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm email" +msgstr "確認" + +#: bookwyrm/templates/confirm_email/confirm_email.html:7 +#, fuzzy +#| msgid "Email address:" +msgid "Confirm your email address" +msgstr "郵箱地址:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:13 +msgid "A confirmation code has been sent to the email address you used to register your account." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:15 +msgid "Sorry! We couldn't find that code." +msgstr "" + +#: bookwyrm/templates/confirm_email/confirm_email.html:19 +#, fuzzy +#| msgid "Confirm password:" +msgid "Confirmation code:" +msgstr "確認密碼:" + +#: bookwyrm/templates/confirm_email/confirm_email.html:25 +#: bookwyrm/templates/discover/landing_layout.html:70 +#: bookwyrm/templates/moderation/report_modal.html:33 +msgid "Submit" +msgstr "提交" + +#: bookwyrm/templates/confirm_email/confirm_email.html:32 +msgid "Can't find your code?" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:4 +msgid "Resend confirmation link" +msgstr "" + +#: bookwyrm/templates/confirm_email/resend_form.html:11 +#: bookwyrm/templates/discover/landing_layout.html:64 +#: bookwyrm/templates/password_reset_request.html:18 +#: bookwyrm/templates/preferences/edit_user.html:38 +#: bookwyrm/templates/snippets/register_form.html:13 +msgid "Email address:" +msgstr "郵箱地址:" + +#: bookwyrm/templates/confirm_email/resend_form.html:17 +#, fuzzy +#| msgid "Re-send invite" +msgid "Resend link" +msgstr "重新發送請求" + #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" msgstr "社群" @@ -813,7 +867,7 @@ msgid "Join %(name)s" msgstr "加入 %(name)s" #: bookwyrm/templates/discover/landing_layout.html:51 -#: bookwyrm/templates/login.html:51 +#: bookwyrm/templates/login.html:56 msgid "This instance is closed" msgstr "本實例不開放。" @@ -825,22 +879,26 @@ msgstr "謝謝你!我們已經受到了你的請求。" msgid "Request an Invitation" msgstr "請求邀請" -#: bookwyrm/templates/discover/landing_layout.html:64 -#: bookwyrm/templates/password_reset_request.html:18 -#: bookwyrm/templates/preferences/edit_user.html:38 -#: bookwyrm/templates/snippets/register_form.html:13 -msgid "Email address:" -msgstr "郵箱地址:" - -#: bookwyrm/templates/discover/landing_layout.html:70 -#: bookwyrm/templates/moderation/report_modal.html:33 -msgid "Submit" -msgstr "提交" - #: bookwyrm/templates/discover/landing_layout.html:79 msgid "Your Account" msgstr "你的帳號" +#: bookwyrm/templates/email/confirm/html_content.html:6 +#: bookwyrm/templates/email/confirm/text_content.html:4 +#, python-format +msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" +msgstr "" + +#: bookwyrm/templates/email/confirm/html_content.html:11 +#, fuzzy +#| msgid "Confirm" +msgid "Confirm Email" +msgstr "確認" + +#: bookwyrm/templates/email/confirm/subject.html:2 +msgid "Please confirm your email" +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -1247,7 +1305,7 @@ msgid "Imported" msgstr "已匯入" #: bookwyrm/templates/invite.html:4 bookwyrm/templates/invite.html:12 -#: bookwyrm/templates/login.html:46 +#: bookwyrm/templates/login.html:51 msgid "Create an Account" msgstr "建立帳號" @@ -1315,7 +1373,7 @@ msgid "Notifications" msgstr "通知" #: bookwyrm/templates/layout.html:158 bookwyrm/templates/layout.html:162 -#: bookwyrm/templates/login.html:17 +#: bookwyrm/templates/login.html:22 #: bookwyrm/templates/snippets/register_form.html:4 msgid "Username:" msgstr "使用者名稱:" @@ -1324,12 +1382,12 @@ msgstr "使用者名稱:" msgid "password" msgstr "密碼" -#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:36 +#: bookwyrm/templates/layout.html:164 bookwyrm/templates/login.html:41 msgid "Forgot your password?" msgstr "忘記了密碼?" #: bookwyrm/templates/layout.html:167 bookwyrm/templates/login.html:10 -#: bookwyrm/templates/login.html:33 +#: bookwyrm/templates/login.html:38 msgid "Log in" msgstr "登入" @@ -1505,16 +1563,20 @@ msgstr "你的列表" msgid "Login" msgstr "登入" -#: bookwyrm/templates/login.html:23 bookwyrm/templates/password_reset.html:17 +#: bookwyrm/templates/login.html:16 +msgid "Success! Email address confirmed." +msgstr "" + +#: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 msgid "Password:" msgstr "密碼:" -#: bookwyrm/templates/login.html:52 +#: bookwyrm/templates/login.html:57 msgid "Contact an administrator to get an invite" msgstr "聯絡管理員以取得邀請" -#: bookwyrm/templates/login.html:63 +#: bookwyrm/templates/login.html:68 msgid "More about this site" msgstr "關於本網站的更多" @@ -2338,7 +2400,15 @@ msgstr "允許註冊:" msgid "Allow invite requests" msgstr "允許請求邀請:" -#: bookwyrm/templates/settings/site.html:95 +#: bookwyrm/templates/settings/site.html:97 +msgid "Require users to confirm email address" +msgstr "" + +#: bookwyrm/templates/settings/site.html:99 +msgid "(Recommended if registration is open)" +msgstr "" + +#: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" msgstr "註冊關閉文字:" @@ -3011,7 +3081,7 @@ msgstr "檔案超過了最大大小: 10MB" msgid "%(title)s: %(subtitle)s" msgstr "" -#: bookwyrm/views/authentication.py:58 +#: bookwyrm/views/authentication.py:69 msgid "Username or password are incorrect" msgstr "" From e198e663d1b821a596a56b12986a00441c86b815 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 18:48:16 -0700 Subject: [PATCH 14/53] Fixes names of site settings field in tests --- bookwyrm/tests/views/test_authentication.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index bbafe7bd5..bd4b3b029 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -32,7 +32,7 @@ class AuthenticationViews(TestCase): self.anonymous_user.is_authenticated = False self.settings = models.SiteSettings.objects.create( - id=1, require_email_confirmation=False + id=1, require_confirm_email=False ) def test_login_get(self, _): From aad5de3b618b20d2c24cfe456f1f7a2e0324243d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 19:03:15 -0700 Subject: [PATCH 15/53] Improves cross-edition display for lists --- bookwyrm/templatetags/bookwyrm_tags.py | 2 +- bookwyrm/views/books.py | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/bookwyrm/templatetags/bookwyrm_tags.py b/bookwyrm/templatetags/bookwyrm_tags.py index 5cba5455f..4811f4fd5 100644 --- a/bookwyrm/templatetags/bookwyrm_tags.py +++ b/bookwyrm/templatetags/bookwyrm_tags.py @@ -12,7 +12,7 @@ register = template.Library() def get_rating(book, user): """get the overall rating of a book""" queryset = views.helpers.privacy_filter( - user, models.Review.objects.filter(book=book) + user, models.Review.objects.filter(book__in=book.parent_work.editions.all()) ) return queryset.aggregate(Avg("rating"))["rating__avg"] diff --git a/bookwyrm/views/books.py b/bookwyrm/views/books.py index d56e2f22c..6cd0427c1 100644 --- a/bookwyrm/views/books.py +++ b/bookwyrm/views/books.py @@ -65,6 +65,13 @@ class Book(View): queryset = queryset.select_related("user") paginated = Paginator(queryset, PAGE_LENGTH) + lists = privacy_filter( + request.user, + models.List.objects.filter( + listitem__approved=True, + listitem__book__in=book.parent_work.editions.all(), + ), + ) data = { "book": book, "statuses": paginated.get_page(request.GET.get("page")), @@ -75,9 +82,7 @@ class Book(View): if not user_statuses else None, "rating": reviews.aggregate(Avg("rating"))["rating__avg"], - "lists": privacy_filter( - request.user, book.list_set.filter(listitem__approved=True) - ), + "lists": lists, } if request.user.is_authenticated: From 0fa9fd7331e71dd981b8effa6faeb4aba61fada6 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:28:24 -0700 Subject: [PATCH 16/53] Registration with confirm email tests --- bookwyrm/tests/views/test_authentication.py | 97 +++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index bd4b3b029..dc9f5dd53 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -132,6 +132,32 @@ class AuthenticationViews(TestCase): self.assertEqual(nutria.localname, "nutria-user.user_nutria") self.assertEqual(nutria.local, True) + def test_register_email_confirm(self, _): + """create a user""" + self.settings.require_confirm_email = True + self.settings.save() + + view = views.Register.as_view() + self.assertEqual(models.User.objects.count(), 1) + request = self.factory.post( + "register/", + { + "localname": "nutria", + "password": "mouseword", + "email": "aa@bb.cccc", + }, + ) + with patch("bookwyrm.views.authentication.login"): + response = view(request) + self.assertEqual(response.status_code, 302) + nutria = models.User.objects.get(localname="nutria") + self.assertEqual(nutria.username, "nutria@%s" % DOMAIN) + self.assertEqual(nutria.local, True) + + self.assertFalse(nutria.is_active) + self.assertEqual(nutria.deactivation_reason, "pending") + self.assertIsNotNone(nutria.confirmation_code) + def test_register_trailing_space(self, _): """django handles this so weirdly""" view = views.Register.as_view() @@ -251,3 +277,74 @@ class AuthenticationViews(TestCase): with self.assertRaises(Http404): response = view(request) self.assertEqual(models.User.objects.count(), 2) + + def test_confirm_email_code_get(self, _): + """there are so many views, this just makes sure it LOADS""" + self.settings.require_confirm_email = True + self.settings.save() + + self.local_user.is_active = False + self.local_user.deactivation_reason = "pending" + self.local_user.confirmation_code = "12345" + self.local_user.save( + broadcast=False, + update_fields=["is_active", "deactivation_reason", "confirmation_code"], + ) + view = views.ConfirmEmailCode.as_view() + request = self.factory.get("") + request.user = self.anonymous_user + + result = view(request, "12345") + self.assertEqual(result.url, "/login/confirmed") + self.assertEqual(result.status_code, 302) + + self.local_user.refresh_from_db() + self.assertTrue(self.local_user.is_active) + self.assertIsNone(self.local_user.deactivation_reason) + + request.user = self.local_user + result = view(request, "12345") + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) + + def test_confirm_email_code_get_invalid_code(self, _): + """there are so many views, this just makes sure it LOADS""" + self.settings.require_confirm_email = True + self.settings.save() + + self.local_user.is_active = False + self.local_user.deactivation_reason = "pending" + self.local_user.confirmation_code = "12345" + self.local_user.save( + broadcast=False, + update_fields=["is_active", "deactivation_reason", "confirmation_code"], + ) + view = views.ConfirmEmailCode.as_view() + request = self.factory.get("") + request.user = self.anonymous_user + + result = view(request, "abcde") + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + self.assertFalse(self.local_user.is_active) + self.assertEqual(self.local_user.deactivation_reason, "pending") + + def test_confirm_email_get(self, _): + """there are so many views, this just makes sure it LOADS""" + self.settings.require_confirm_email = True + self.settings.save() + + login = views.ConfirmEmail.as_view() + request = self.factory.get("") + request.user = self.anonymous_user + + result = login(request) + self.assertIsInstance(result, TemplateResponse) + result.render() + self.assertEqual(result.status_code, 200) + + request.user = self.local_user + result = login(request) + self.assertEqual(result.url, "/") + self.assertEqual(result.status_code, 302) From 226c325099e1bd5ff723dd2c0df6549999067dc6 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:37:18 -0700 Subject: [PATCH 17/53] Adds plaintext code to emails --- bookwyrm/templates/email/confirm/html_content.html | 6 ++++++ bookwyrm/templates/email/confirm/text_content.html | 3 +++ 2 files changed, 9 insertions(+) diff --git a/bookwyrm/templates/email/confirm/html_content.html b/bookwyrm/templates/email/confirm/html_content.html index b47642af7..231b0388e 100644 --- a/bookwyrm/templates/email/confirm/html_content.html +++ b/bookwyrm/templates/email/confirm/html_content.html @@ -11,4 +11,10 @@ One last step before you join {{ site_name }}! Please confirm your email address {% trans "Confirm Email" as text %} {% include 'email/snippets/action.html' with path=confirmation_link text=text %} +

+{% blocktrans trimmed %} +Or enter the code "{{ confirmation_code }}" at login. +{% endblocktrans %} +

+ {% endblock %} diff --git a/bookwyrm/templates/email/confirm/text_content.html b/bookwyrm/templates/email/confirm/text_content.html index e3d739383..847009e55 100644 --- a/bookwyrm/templates/email/confirm/text_content.html +++ b/bookwyrm/templates/email/confirm/text_content.html @@ -7,5 +7,8 @@ One last step before you join {{ site_name }}! Please confirm your email address {{ confirmation_link }} +{% blocktrans trimmed %} +Or enter the code "{{ confirmation_code }}" at login. +{% endblocktrans %} {% endblock %} From 68e4462486d03573b278ef5da42b73ce5fd7bf5d Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:43:30 -0700 Subject: [PATCH 18/53] Make email a required html field in register form --- bookwyrm/templates/snippets/register_form.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/register_form.html b/bookwyrm/templates/snippets/register_form.html index cd7ea8063..9e610bd13 100644 --- a/bookwyrm/templates/snippets/register_form.html +++ b/bookwyrm/templates/snippets/register_form.html @@ -12,7 +12,7 @@
- + {% for error in register_form.email.errors %}

{{ error | escape }}

{% endfor %} From 38f614a526209e78b469e477261a8efef5d0ebda Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 07:56:30 -0700 Subject: [PATCH 19/53] Include generated notes in books stream --- bookwyrm/activitystreams.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index bad7c59f8..66dcad84e 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -358,25 +358,39 @@ def add_statuses_on_shelve(sender, instance, *args, **kwargs): """update books stream when user shelves a book""" if not instance.user.local: return - # check if the book is already on the user's shelves - if models.ShelfBook.objects.filter( - user=instance.user, book__in=instance.book.parent_work.editions.all() - ).exists(): + book = None + if hasattr(instance, "book"): + book = instance.book + elif instance.mention_books.exists(): + book = instance.mention_books.first() + if not book: return - BooksStream().add_book_statuses(instance.user, instance.book) + # check if the book is already on the user's shelves + editions = book.parent_work.editions.all() + if models.ShelfBook.objects.filter(user=instance.user, book__in=editions).exists(): + return + + BooksStream().add_book_statuses(instance.user, book) @receiver(signals.post_delete, sender=models.ShelfBook) # pylint: disable=unused-argument -def remove_statuses_on_shelve(sender, instance, *args, **kwargs): +def remove_statuses_on_unshelve(sender, instance, *args, **kwargs): """update books stream when user unshelves a book""" if not instance.user.local: return + + book = None + if hasattr(instance, "book"): + book = instance.book + elif instance.mention_books.exists(): + book = instance.mention_books.first() + if not book: + return # check if the book is actually unshelved, not just moved - if models.ShelfBook.objects.filter( - user=instance.user, book__in=instance.book.parent_work.editions.all() - ).exists(): + editions = book.parent_work.editions.all() + if models.ShelfBook.objects.filter(user=instance.user, book__in=editions).exists(): return BooksStream().remove_book_statuses(instance.user, instance.book) From 026c6ac025f2725f0e2805da4e7040e212a4d4a5 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 08:01:14 -0700 Subject: [PATCH 20/53] Mocks emailer in registration test --- bookwyrm/tests/views/test_authentication.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/test_authentication.py b/bookwyrm/tests/views/test_authentication.py index dc9f5dd53..22008e100 100644 --- a/bookwyrm/tests/views/test_authentication.py +++ b/bookwyrm/tests/views/test_authentication.py @@ -132,7 +132,8 @@ class AuthenticationViews(TestCase): self.assertEqual(nutria.localname, "nutria-user.user_nutria") self.assertEqual(nutria.local, True) - def test_register_email_confirm(self, _): + @patch("bookwyrm.emailing.send_email.delay") + def test_register_email_confirm(self, *_): """create a user""" self.settings.require_confirm_email = True self.settings.save() From 468f1f135c42b819f6f2f884dbe39fbf9101dd04 Mon Sep 17 00:00:00 2001 From: reese Date: Sat, 7 Aug 2021 11:35:07 -0500 Subject: [PATCH 21/53] update spanish translations --- locale/es/LC_MESSAGES/django.mo | Bin 42719 -> 44832 bytes locale/es/LC_MESSAGES/django.po | 135 ++++++++++---------------------- 2 files changed, 41 insertions(+), 94 deletions(-) diff --git a/locale/es/LC_MESSAGES/django.mo b/locale/es/LC_MESSAGES/django.mo index 23869cf45428ccb9c4d7e0d8a06dc96b209e7775..c73db384d7792b0008f0fef891c4d286b5a253f7 100644 GIT binary patch delta 15136 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\n" "Language-Team: LANGUAGE \n" @@ -100,10 +100,8 @@ msgid "Home" msgstr "Hogar" #: bookwyrm/settings.py:124 -#, fuzzy -#| msgid "Book Title" msgid "Books Timeline" -msgstr "Título" +msgstr "Línea temporal de libros" #: bookwyrm/settings.py:124 bookwyrm/templates/search/layout.html:21 #: bookwyrm/templates/search/layout.html:42 @@ -132,10 +130,8 @@ msgid "Simplified Chinese" msgstr "Chino simplificado" #: bookwyrm/settings.py:175 -#, fuzzy -#| msgid "Additional info:" msgid "Traditional Chinese" -msgstr "Más informacion:" +msgstr "Chino tradicional" #: bookwyrm/templates/404.html:4 bookwyrm/templates/404.html:8 msgid "Not Found" @@ -190,10 +186,8 @@ msgid "View on Inventaire" msgstr "Ver en Inventaire" #: bookwyrm/templates/author/author.html:85 -#, fuzzy -#| msgid "View on OpenLibrary" msgid "View on LibraryThing" -msgstr "Ver en OpenLibrary" +msgstr "Ver en LibraryThing" #: bookwyrm/templates/author/author.html:93 msgid "View on Goodreads" @@ -534,16 +528,12 @@ msgid "Authors" msgstr "Autores" #: bookwyrm/templates/book/edit_book.html:202 -#, fuzzy, python-format -#| msgid "Remove from %(name)s" msgid "Remove %(name)s" -msgstr "Quitar de %(name)s" +msgstr "Quitar %(name)s" #: bookwyrm/templates/book/edit_book.html:205 -#, fuzzy, python-format -#| msgid "Remove from %(name)s" msgid "Author page for %(name)s" -msgstr "Quitar de %(name)s" +msgstr "Página de autor por %(name)s" #: bookwyrm/templates/book/edit_book.html:212 msgid "Add Authors:" @@ -689,16 +679,12 @@ msgid "Compose status" msgstr "Componer status" #: bookwyrm/templates/confirm_email/confirm_email.html:4 -#, fuzzy -#| msgid "Confirm" msgid "Confirm email" -msgstr "Confirmar" +msgstr "Confirmar correo electrónico" #: bookwyrm/templates/confirm_email/confirm_email.html:7 -#, fuzzy -#| msgid "Enter a valid email address." msgid "Confirm your email address" -msgstr "Ingrese una dirección de correo electrónico válida." +msgstr "Confirmar tu dirección de correo electrónico" #: bookwyrm/templates/confirm_email/confirm_email.html:13 msgid "A confirmation code has been sent to the email address you used to register your account." @@ -709,10 +695,8 @@ msgid "Sorry! We couldn't find that code." msgstr "" #: bookwyrm/templates/confirm_email/confirm_email.html:19 -#, fuzzy -#| msgid "Confirm password:" msgid "Confirmation code:" -msgstr "Confirmar contraseña:" +msgstr "Código de confirmación:" #: bookwyrm/templates/confirm_email/confirm_email.html:25 #: bookwyrm/templates/discover/landing_layout.html:70 @@ -737,10 +721,8 @@ msgid "Email address:" msgstr "Dirección de correo electrónico:" #: bookwyrm/templates/confirm_email/resend_form.html:17 -#, fuzzy -#| msgid "Re-send invite" msgid "Resend link" -msgstr "Re-enviar invitación" +msgstr "Re-enviar enlace" #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" @@ -791,10 +773,8 @@ msgstr "Activ@ recientemente" #: bookwyrm/templates/directory/user_card.html:18 #: bookwyrm/templates/user/user_preview.html:16 #: bookwyrm/templates/user/user_preview.html:17 -#, fuzzy -#| msgid "Your Account" msgid "Locked account" -msgstr "Tu cuenta" +msgstr "Cuenta bloqueada" #: bookwyrm/templates/directory/user_card.html:40 msgid "follower you follow" @@ -893,15 +873,23 @@ msgid "One last step before you join %(site_name)s! Please confirm your email ad msgstr "" #: bookwyrm/templates/email/confirm/html_content.html:11 -#, fuzzy -#| msgid "Confirm" msgid "Confirm Email" -msgstr "Confirmar" +msgstr "Confirmar correo electrónico" + +#: bookwyrm/templates/email/confirm/html_content.html:15 +#, python-format +msgid "Or enter the code \"%(confirmation_code)s\" at login." +msgstr "" #: bookwyrm/templates/email/confirm/subject.html:2 msgid "Please confirm your email" msgstr "" +#: bookwyrm/templates/email/confirm/text_content.html:10 +#, python-format +msgid "Or enter the code \"%(confirmation_code)s\" at login." +msgstr "" + #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 msgid "Hi there," @@ -983,10 +971,8 @@ msgid "You have no messages right now." msgstr "No tienes ningún mensaje en este momento." #: bookwyrm/templates/feed/feed.html:22 -#, fuzzy, python-format -#| msgid "load 0 unread status(es)" msgid "load 0 unread status(es)" -msgstr "cargar 0 status(es) no leídos" +msgstr "cargar 0 status(es) no leído(s)" #: bookwyrm/templates/feed/feed.html:38 msgid "There aren't any activities right now! Try following a user to get started" @@ -1229,10 +1215,8 @@ msgid "Import Status" msgstr "Status de importación" #: bookwyrm/templates/import_status.html:11 -#, fuzzy -#| msgid "Back to reports" msgid "Back to imports" -msgstr "Volver a los informes" +msgstr "Volver a las importaciones" #: bookwyrm/templates/import_status.html:15 msgid "Import started:" @@ -1281,10 +1265,8 @@ msgid "Successfully imported" msgstr "Importado exitosamente" #: bookwyrm/templates/import_status.html:114 -#, fuzzy -#| msgid "Import still in progress." msgid "Import Progress" -msgstr "Importación todavia en progreso" +msgstr "Progreso de importación" #: bookwyrm/templates/import_status.html:119 msgid "Book" @@ -1399,10 +1381,8 @@ msgid "Join" msgstr "Unirse" #: bookwyrm/templates/layout.html:213 -#, fuzzy -#| msgid "About this server" msgid "About this instance" -msgstr "Sobre este servidor" +msgstr "Sobre esta instancia" #: bookwyrm/templates/layout.html:217 msgid "Contact site admin" @@ -1836,10 +1816,8 @@ msgstr "Nueva contraseña:" #: bookwyrm/templates/preferences/delete_user.html:7 #: bookwyrm/templates/preferences/delete_user.html:26 #: bookwyrm/templates/preferences/layout.html:23 -#, fuzzy -#| msgid "Create an Account" msgid "Delete Account" -msgstr "Crear una cuenta" +msgstr "Quitar cuenta" #: bookwyrm/templates/preferences/delete_user.html:12 msgid "Permanently delete account" @@ -1859,10 +1837,8 @@ msgid "Show set reading goal prompt in feed:" msgstr "Mostrar meta de lectura en el feed:" #: bookwyrm/templates/preferences/edit_user.html:58 -#, fuzzy -#| msgid "Post privacy" msgid "Default post privacy:" -msgstr "Privacidad de publicación" +msgstr "Privacidad de publicación por defecto:" #: bookwyrm/templates/preferences/edit_user.html:70 #, python-format @@ -1886,22 +1862,16 @@ msgid "Relationships" msgstr "Relaciones" #: bookwyrm/templates/reading_progress/finish.html:5 -#, fuzzy, python-format -#| msgid "Finish \"%(book_title)s\"" msgid "Finish \"%(book_title)s\"" -msgstr "Terminar \"%(book_title)s\"" +msgstr "Terminar \"%(book_title)s\"" #: bookwyrm/templates/reading_progress/start.html:5 -#, fuzzy, python-format -#| msgid "Edit \"%(book_title)s\"" msgid "Start \"%(book_title)s\"" -msgstr "Editar \"%(book_title)s\"" +msgstr "Empezar \"%(book_title)s\"" #: bookwyrm/templates/reading_progress/want.html:5 -#, fuzzy, python-format -#| msgid "Want to Read \"%(book_title)s\"" msgid "Want to Read \"%(book_title)s\"" -msgstr "Quiero leer \"%(book_title)s\"" +msgstr "Quiero leer \"%(book_title)s\"" #: bookwyrm/templates/rss/title.html:5 #: bookwyrm/templates/snippets/status/status_header.html:36 @@ -1967,10 +1937,8 @@ msgstr "Administrar usuarios" #: bookwyrm/templates/settings/admin_layout.html:39 #: bookwyrm/templates/settings/federation.html:3 #: bookwyrm/templates/settings/federation.html:5 -#, fuzzy -#| msgid "Federated Servers" msgid "Federated Instances" -msgstr "Servidores federalizados" +msgstr "Instancias federalizadas" #: bookwyrm/templates/settings/admin_layout.html:44 msgid "Instance Settings" @@ -2097,17 +2065,13 @@ msgstr "inactivo" #: bookwyrm/templates/settings/federation.html:10 #: bookwyrm/templates/settings/server_blocklist.html:3 #: bookwyrm/templates/settings/server_blocklist.html:20 -#, fuzzy -#| msgid "View instance" msgid "Add instance" -msgstr "Ver instancia" +msgstr "Agregar instancia" #: bookwyrm/templates/settings/edit_server.html:7 #: bookwyrm/templates/settings/server_blocklist.html:7 -#, fuzzy -#| msgid "Back to server list" msgid "Back to instance list" -msgstr "Volver a la lista de servidores" +msgstr "Volver a la lista de instancias" #: bookwyrm/templates/settings/edit_server.html:16 #: bookwyrm/templates/settings/server_blocklist.html:16 @@ -2217,10 +2181,8 @@ msgstr "Todos los usuarios en esta instancia serán re-activados." #: bookwyrm/templates/settings/federation.html:19 #: bookwyrm/templates/user_admin/server_filter.html:5 -#, fuzzy -#| msgid "Instance Name:" msgid "Instance name" -msgstr "Nombre de instancia:" +msgstr "Nombre de instancia" #: bookwyrm/templates/settings/federation.html:23 msgid "Date federated" @@ -2402,16 +2364,12 @@ msgid "Additional info:" msgstr "Más informacion:" #: bookwyrm/templates/settings/site.html:85 -#, fuzzy -#| msgid "Allow registration:" msgid "Allow registration" -msgstr "Permitir registración:" +msgstr "Permitir registración" #: bookwyrm/templates/settings/site.html:91 -#, fuzzy -#| msgid "Allow invite requests:" msgid "Allow invite requests" -msgstr "Permitir solicitudes de invitación:" +msgstr "Permitir solicitudes de invitación" #: bookwyrm/templates/settings/site.html:97 msgid "Require users to confirm email address" @@ -2442,10 +2400,8 @@ msgid "No cover" msgstr "Sin portada" #: bookwyrm/templates/snippets/book_titleby.html:6 -#, fuzzy, python-format -#| msgid "%(title)s by " msgid "%(title)s by" -msgstr "%(title)s por " +msgstr "%(title)s por" #: bookwyrm/templates/snippets/boost_button.html:20 #: bookwyrm/templates/snippets/boost_button.html:21 @@ -2673,8 +2629,6 @@ msgid "page %(page)s of %(total_pages)s" msgstr "página %(page)s de %(total_pages)s" #: bookwyrm/templates/snippets/page_text.html:6 -#, fuzzy, python-format -#| msgid "page %(page)s" msgid "page %(page)s" msgstr "página %(pages)s" @@ -2862,10 +2816,8 @@ msgstr[1] "%(shared_books)s libros en tus estantes" #: bookwyrm/templates/snippets/suggested_users.html:31 #: bookwyrm/templates/user/user_preview.html:36 -#, fuzzy -#| msgid "followed you" msgid "Follows you" -msgstr "te siguió" +msgstr "Te sigue" #: bookwyrm/templates/snippets/switch_edition_button.html:5 msgid "Switch to this edition" @@ -3018,11 +2970,8 @@ msgstr[0] "%(mutuals_display)s seguidor que sigues" msgstr[1] "%(mutuals_display)s seguidores que sigues" #: bookwyrm/templates/user/user_preview.html:38 -#, fuzzy -#| msgid "follower you follow" -#| msgid_plural "followers you follow" msgid "No followers you follow" -msgstr "seguidor que tu sigues" +msgstr "Ningún seguidor que tu sigues" #: bookwyrm/templates/user_admin/user.html:9 msgid "Back to users" @@ -3047,10 +2996,8 @@ msgid "Last Active" msgstr "Actividad reciente" #: bookwyrm/templates/user_admin/user_admin.html:38 -#, fuzzy -#| msgid "View instance" msgid "Remote instance" -msgstr "Ver instancia" +msgstr "Instancia remota" #: bookwyrm/templates/user_admin/user_admin.html:47 msgid "Active" From a0d2f3897016dbeb37cf214102d2cc56f5c81ee4 Mon Sep 17 00:00:00 2001 From: Fabien Basmaison Date: Sat, 7 Aug 2021 19:35:43 +0200 Subject: [PATCH 22/53] [french] Translate strings about email confirmation. --- locale/fr_FR/LC_MESSAGES/django.po | 38 +++++++++++------------------- 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/locale/fr_FR/LC_MESSAGES/django.po b/locale/fr_FR/LC_MESSAGES/django.po index f0a559f97..badfcdcaf 100644 --- a/locale/fr_FR/LC_MESSAGES/django.po +++ b/locale/fr_FR/LC_MESSAGES/django.po @@ -685,30 +685,24 @@ msgid "Compose status" msgstr "Rédiger un statut" #: bookwyrm/templates/confirm_email/confirm_email.html:4 -#, fuzzy -#| msgid "Confirm" msgid "Confirm email" -msgstr "Confirmer" +msgstr "Confirmation de l’email" #: bookwyrm/templates/confirm_email/confirm_email.html:7 -#, fuzzy -#| msgid "Email address:" msgid "Confirm your email address" -msgstr "Adresse email :" +msgstr "Veuillez confirmer votre adresse email" #: bookwyrm/templates/confirm_email/confirm_email.html:13 msgid "A confirmation code has been sent to the email address you used to register your account." -msgstr "" +msgstr "Un code de confirmation a été envoyé à l’adresse email rattachée à votre compte." #: bookwyrm/templates/confirm_email/confirm_email.html:15 msgid "Sorry! We couldn't find that code." -msgstr "" +msgstr "Pardon ! Nous ne reconnaissons pas ce code." #: bookwyrm/templates/confirm_email/confirm_email.html:19 -#, fuzzy -#| msgid "Confirm password:" msgid "Confirmation code:" -msgstr "Confirmez le mot de passe :" +msgstr "Code de confirmation :" #: bookwyrm/templates/confirm_email/confirm_email.html:25 #: bookwyrm/templates/discover/landing_layout.html:70 @@ -718,11 +712,11 @@ msgstr "Valider" #: bookwyrm/templates/confirm_email/confirm_email.html:32 msgid "Can't find your code?" -msgstr "" +msgstr "Vous ne trouvez pas votre code ?" #: bookwyrm/templates/confirm_email/resend_form.html:4 msgid "Resend confirmation link" -msgstr "" +msgstr "Envoyer le lien de confirmation de nouveau" #: bookwyrm/templates/confirm_email/resend_form.html:11 #: bookwyrm/templates/discover/landing_layout.html:64 @@ -733,10 +727,8 @@ msgid "Email address:" msgstr "Adresse email :" #: bookwyrm/templates/confirm_email/resend_form.html:17 -#, fuzzy -#| msgid "Re-send invite" msgid "Resend link" -msgstr "Envoyer l’invitation de nouveau" +msgstr "Envoyer le lien de nouveau" #: bookwyrm/templates/directory/community_filter.html:5 msgid "Community" @@ -886,17 +878,15 @@ msgstr "Votre compte" #: bookwyrm/templates/email/confirm/text_content.html:4 #, python-format msgid "One last step before you join %(site_name)s! Please confirm your email address by clicking the link below:" -msgstr "" +msgstr "Une dernière petite étape avant de rejoindre %(site_name)s ! Veuillez confirmer votre adresse email en cliquant le lien ci‑dessous :" #: bookwyrm/templates/email/confirm/html_content.html:11 -#, fuzzy -#| msgid "Confirm" msgid "Confirm Email" -msgstr "Confirmer" +msgstr "Confirmation de l’email" #: bookwyrm/templates/email/confirm/subject.html:2 msgid "Please confirm your email" -msgstr "" +msgstr "Veuillez confirmer votre adresse email" #: bookwyrm/templates/email/html_layout.html:15 #: bookwyrm/templates/email/text_layout.html:2 @@ -1564,7 +1554,7 @@ msgstr "Connexion" #: bookwyrm/templates/login.html:16 msgid "Success! Email address confirmed." -msgstr "" +msgstr "Bravo ! L’adresse email a été confirmée." #: bookwyrm/templates/login.html:28 bookwyrm/templates/password_reset.html:17 #: bookwyrm/templates/snippets/register_form.html:22 @@ -2397,11 +2387,11 @@ msgstr "Autoriser les demandes d’invitation" #: bookwyrm/templates/settings/site.html:97 msgid "Require users to confirm email address" -msgstr "" +msgstr "Demander aux utilisateurs et utilisatrices de confirmer leur adresse email" #: bookwyrm/templates/settings/site.html:99 msgid "(Recommended if registration is open)" -msgstr "" +msgstr "(Recommandé si les inscriptions sont ouvertes)" #: bookwyrm/templates/settings/site.html:102 msgid "Registration closed text:" From cce7d9a6484af4c203105e4c49fafe9de5ba0591 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 10:59:55 -0700 Subject: [PATCH 23/53] Don't skip updates statuses when adding to streams Generated note books are added post-initial save --- bookwyrm/activitystreams.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/bookwyrm/activitystreams.py b/bookwyrm/activitystreams.py index 66dcad84e..754b4b159 100644 --- a/bookwyrm/activitystreams.py +++ b/bookwyrm/activitystreams.py @@ -260,9 +260,6 @@ def add_status_on_create(sender, instance, created, *args, **kwargs): stream.remove_object_from_related_stores(instance) return - if not created: - return - for stream in streams.values(): stream.add_status(instance) From 040758c833ea4670aa955f676091ae5564a396da Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 11:15:02 -0700 Subject: [PATCH 24/53] Renames "discover" --- .../{discover => landing}/about.html | 2 +- .../discover.html => landing/landing.html} | 14 +++++------ .../{discover => landing}/landing_layout.html | 0 .../{discover => landing}/large-book.html | 0 .../{discover => landing}/small-book.html | 1 - bookwyrm/tests/views/test_landing.py | 4 ++-- bookwyrm/views/__init__.py | 3 ++- bookwyrm/views/discover.py | 23 +++++++++++++++++++ bookwyrm/views/helpers.py | 4 ++-- bookwyrm/views/landing.py | 14 +++++------ 10 files changed, 44 insertions(+), 21 deletions(-) rename bookwyrm/templates/{discover => landing}/about.html (95%) rename bookwyrm/templates/{discover/discover.html => landing/landing.html} (72%) rename bookwyrm/templates/{discover => landing}/landing_layout.html (100%) rename bookwyrm/templates/{discover => landing}/large-book.html (100%) rename bookwyrm/templates/{discover => landing}/small-book.html (99%) create mode 100644 bookwyrm/views/discover.py diff --git a/bookwyrm/templates/discover/about.html b/bookwyrm/templates/landing/about.html similarity index 95% rename from bookwyrm/templates/discover/about.html rename to bookwyrm/templates/landing/about.html index a6f3a026a..dd7036c4f 100644 --- a/bookwyrm/templates/discover/about.html +++ b/bookwyrm/templates/landing/about.html @@ -1,4 +1,4 @@ -{% extends 'discover/landing_layout.html' %} +{% extends 'landing/landing_layout.html' %} {% load i18n %} {% block panel %} diff --git a/bookwyrm/templates/discover/discover.html b/bookwyrm/templates/landing/landing.html similarity index 72% rename from bookwyrm/templates/discover/discover.html rename to bookwyrm/templates/landing/landing.html index d553c3680..38180c3bf 100644 --- a/bookwyrm/templates/discover/discover.html +++ b/bookwyrm/templates/landing/landing.html @@ -1,4 +1,4 @@ -{% extends 'discover/landing_layout.html' %} +{% extends 'landing/landing_layout.html' %} {% load i18n %} {% block panel %} @@ -10,18 +10,18 @@
- {% include 'discover/large-book.html' with book=books.0 %} + {% include 'landing/large-book.html' with book=books.0 %}
- {% include 'discover/small-book.html' with book=books.1 %} + {% include 'landing/small-book.html' with book=books.1 %}
- {% include 'discover/small-book.html' with book=books.2 %} + {% include 'landing/small-book.html' with book=books.2 %}
@@ -30,18 +30,18 @@
- {% include 'discover/small-book.html' with book=books.3 %} + {% include 'landing/small-book.html' with book=books.3 %}
- {% include 'discover/small-book.html' with book=books.4 %} + {% include 'landing/small-book.html' with book=books.4 %}
- {% include 'discover/large-book.html' with book=books.5 %} + {% include 'landing/large-book.html' with book=books.5 %}
diff --git a/bookwyrm/templates/discover/landing_layout.html b/bookwyrm/templates/landing/landing_layout.html similarity index 100% rename from bookwyrm/templates/discover/landing_layout.html rename to bookwyrm/templates/landing/landing_layout.html diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/landing/large-book.html similarity index 100% rename from bookwyrm/templates/discover/large-book.html rename to bookwyrm/templates/landing/large-book.html diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/landing/small-book.html similarity index 99% rename from bookwyrm/templates/discover/small-book.html rename to bookwyrm/templates/landing/small-book.html index 73133de45..3f7cbecc3 100644 --- a/bookwyrm/templates/discover/small-book.html +++ b/bookwyrm/templates/landing/small-book.html @@ -1,4 +1,3 @@ - {% load bookwyrm_tags %} {% load i18n %} diff --git a/bookwyrm/tests/views/test_landing.py b/bookwyrm/tests/views/test_landing.py index 4d1531e45..476da74b1 100644 --- a/bookwyrm/tests/views/test_landing.py +++ b/bookwyrm/tests/views/test_landing.py @@ -54,9 +54,9 @@ class LandingViews(TestCase): result.render() self.assertEqual(result.status_code, 200) - def test_discover(self): + def test_landing(self): """there are so many views, this just makes sure it LOADS""" - view = views.Discover.as_view() + view = views.Landing.as_view() request = self.factory.get("") result = view(request) self.assertIsInstance(result, TemplateResponse) diff --git a/bookwyrm/views/__init__.py b/bookwyrm/views/__init__.py index eccb7f5e5..15b55accb 100644 --- a/bookwyrm/views/__init__.py +++ b/bookwyrm/views/__init__.py @@ -7,6 +7,7 @@ from .block import Block, unblock from .books import Book, EditBook, ConfirmEditBook, Editions from .books import upload_cover, add_description, switch_edition, resolve_book from .directory import Directory +from .discover import Discover from .edit_user import EditUser, DeleteUser from .federation import Federation, FederatedServer from .federation import AddFederatedServer, ImportServerBlocklist @@ -22,7 +23,7 @@ from .interaction import Favorite, Unfavorite, Boost, Unboost from .invite import ManageInvites, Invite, InviteRequest from .invite import ManageInviteRequests, ignore_invite_request from .isbn import Isbn -from .landing import About, Home, Discover +from .landing import About, Home, Landing from .list import Lists, List, Curate, UserLists from .notifications import Notifications from .outbox import Outbox diff --git a/bookwyrm/views/discover.py b/bookwyrm/views/discover.py new file mode 100644 index 000000000..9bef6974d --- /dev/null +++ b/bookwyrm/views/discover.py @@ -0,0 +1,23 @@ +""" What's up locally """ +from django.contrib.auth.decorators import login_required +from django.template.response import TemplateResponse +from django.utils.decorators import method_decorator +from django.views import View + +from bookwyrm import forms +from . import helpers + + +# pylint: disable= no-self-use +@method_decorator(login_required, name="dispatch") +class Discover(View): + """preview of recently reviewed books""" + + def get(self, request): + """tiled book activity page""" + data = { + "register_form": forms.RegisterForm(), + "request_form": forms.InviteRequestForm(), + "books": helpers.get_landing_books(), + } + return TemplateResponse(request, "landing/landing.html", data) diff --git a/bookwyrm/views/helpers.py b/bookwyrm/views/helpers.py index 42aa48f0e..f757cec95 100644 --- a/bookwyrm/views/helpers.py +++ b/bookwyrm/views/helpers.py @@ -162,8 +162,8 @@ def is_blocked(viewer, user): return False -def get_discover_books(): - """list of books for the discover page""" +def get_landing_books(): + """list of books for the landing page""" return list( set( models.Edition.objects.filter( diff --git a/bookwyrm/views/landing.py b/bookwyrm/views/landing.py index 1361935ee..6f480b70f 100644 --- a/bookwyrm/views/landing.py +++ b/bookwyrm/views/landing.py @@ -13,22 +13,22 @@ class About(View): def get(self, request): """more information about the instance""" - return TemplateResponse(request, "discover/about.html") + return TemplateResponse(request, "landing/about.html") class Home(View): - """discover page or home feed depending on auth""" + """landing page or home feed depending on auth""" def get(self, request): """this is the same as the feed on the home tab""" if request.user.is_authenticated: feed_view = Feed.as_view() return feed_view(request, "home") - discover_view = Discover.as_view() - return discover_view(request) + landing_view = Landing.as_view() + return landing_view(request) -class Discover(View): +class Landing(View): """preview of recently reviewed books""" def get(self, request): @@ -36,6 +36,6 @@ class Discover(View): data = { "register_form": forms.RegisterForm(), "request_form": forms.InviteRequestForm(), - "books": helpers.get_discover_books(), + "books": helpers.get_landing_books(), } - return TemplateResponse(request, "discover/discover.html", data) + return TemplateResponse(request, "landing/landing.html", data) From b5153f3df12a96010fc35c852a47a0a6f0956876 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 12:33:45 -0700 Subject: [PATCH 25/53] WIP --- bookwyrm/templates/discover/discover.html | 54 +++++++++++++++++++++ bookwyrm/templates/discover/large-book.html | 38 +++++++++++++++ bookwyrm/templates/discover/small-book.html | 41 ++++++++++++++++ bookwyrm/templates/landing/large-book.html | 2 +- bookwyrm/templates/landing/small-book.html | 2 +- bookwyrm/views/discover.py | 25 +++++++--- 6 files changed, 154 insertions(+), 8 deletions(-) create mode 100644 bookwyrm/templates/discover/discover.html create mode 100644 bookwyrm/templates/discover/large-book.html create mode 100644 bookwyrm/templates/discover/small-book.html diff --git a/bookwyrm/templates/discover/discover.html b/bookwyrm/templates/discover/discover.html new file mode 100644 index 000000000..0a419e51b --- /dev/null +++ b/bookwyrm/templates/discover/discover.html @@ -0,0 +1,54 @@ +{% extends "layout.html" %} +{% load i18n %} + +{% block title %}{% trans "Discover" %}{% endblock %} + +{% block content %} + +
+

{% trans "Discover" %}

+
+ +
+
+
+
+ {% include 'discover/large-book.html' with status=large.0 %} +
+
+
+
+
+ {% include 'discover/small-book.html' with status=small.0 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small.1 %} +
+
+
+
+
+
+
+
+ {% include 'discover/small-book.html' with status=small.2 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small.3 %} +
+
+
+
+
+ {% include 'discover/large-book.html' with status=large.1 %} +
+
+
+
+ + +{% endblock %} diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html new file mode 100644 index 000000000..b273d4318 --- /dev/null +++ b/bookwyrm/templates/discover/large-book.html @@ -0,0 +1,38 @@ +{% load bookwyrm_tags %} +{% load markdown %} +{% load i18n %} + +{% if book %} + {% with book=book %} +
+
+ {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' %} + + {% include 'snippets/stars.html' with rating=book|rating:request.user %} +
+ + +
+

+ {{ book.title }} +

+ + {% if book.authors %} +

+ {% trans "by" %} + {% include 'snippets/authors.html' with limit=3 %} +

+ {% endif %} + + {% if book|book_description %} +
+ {{ book|book_description|to_markdown|safe|truncatewords_html:50 }} +
+ {% endif %} +
+
+ {% endwith %} +{% endif %} diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/discover/small-book.html new file mode 100644 index 000000000..052a540cf --- /dev/null +++ b/bookwyrm/templates/discover/small-book.html @@ -0,0 +1,41 @@ +{% load bookwyrm_tags %} +{% load utilities %} +{% load i18n %} + +{% if status %} + {% with book=status.book %} + + {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-h-l-tablet is-w-auto align to-b to-l' %} + + + {% include 'snippets/stars.html' with rating=book|rating:request.user %} + +

+ {{ book.title }} +

+ + {% if book.authors %} +

+ {% trans "by" %} + {% include 'snippets/authors.html' with limit=3 %} +

+ {% endif %} + + + + {% endwith %} +{% endif %} diff --git a/bookwyrm/templates/landing/large-book.html b/bookwyrm/templates/landing/large-book.html index 93026991e..b273d4318 100644 --- a/bookwyrm/templates/landing/large-book.html +++ b/bookwyrm/templates/landing/large-book.html @@ -23,7 +23,7 @@ {% if book.authors %}

{% trans "by" %} - {% include 'snippets/authors.html' %} + {% include 'snippets/authors.html' with limit=3 %}

{% endif %} diff --git a/bookwyrm/templates/landing/small-book.html b/bookwyrm/templates/landing/small-book.html index 3f7cbecc3..2ca505d94 100644 --- a/bookwyrm/templates/landing/small-book.html +++ b/bookwyrm/templates/landing/small-book.html @@ -16,7 +16,7 @@ {% if book.authors %}

{% trans "by" %} - {% include 'snippets/authors.html' %} + {% include 'snippets/authors.html' with limit=3 %}

{% endif %} {% endwith %} diff --git a/bookwyrm/views/discover.py b/bookwyrm/views/discover.py index 9bef6974d..685a4ded7 100644 --- a/bookwyrm/views/discover.py +++ b/bookwyrm/views/discover.py @@ -1,11 +1,14 @@ """ What's up locally """ from django.contrib.auth.decorators import login_required +from django.core.paginator import Paginator +from django.db.models import Q from django.template.response import TemplateResponse from django.utils.decorators import method_decorator from django.views import View -from bookwyrm import forms -from . import helpers +from bookwyrm import models +from bookwyrm.settings import PAGE_LENGTH +from .helpers import privacy_filter # pylint: disable= no-self-use @@ -15,9 +18,19 @@ class Discover(View): def get(self, request): """tiled book activity page""" + activities = privacy_filter( + request.user, + models.Status.objects.select_subclasses().filter( + Q(comment__isnull=False) + | Q(review__isnull=False) + | Q(quotation__isnull=False), + user__local=True + ), + #privacy_levels=["public"] + ) + #paginated = Paginator(activities, PAGE_LENGTH) data = { - "register_form": forms.RegisterForm(), - "request_form": forms.InviteRequestForm(), - "books": helpers.get_landing_books(), + "large": activities.filter(~Q(review__isnull=True, review__content=None))[:2], + "small": activities.filter(~Q(content=None))[:4], } - return TemplateResponse(request, "landing/landing.html", data) + return TemplateResponse(request, "discover/discover.html", data) From 06c5ae06a6aec5422d830a43dd85db0e1734ec52 Mon Sep 17 00:00:00 2001 From: Fabien Basmaison Date: Sat, 7 Aug 2021 21:47:30 +0200 Subject: [PATCH 26/53] [french] Compile French locale. --- locale/fr_FR/LC_MESSAGES/django.mo | Bin 45471 -> 46960 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/locale/fr_FR/LC_MESSAGES/django.mo b/locale/fr_FR/LC_MESSAGES/django.mo index f8ade2a391ba574da54afa6f45e1bf1ad55f9372..98bc29095737fda2d84bcd909167dd90097fb8e7 100644 GIT binary patch delta 14975 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 Wyz)FY_Ai{bY+FB%yh=M#{QnP}G=i!C From e3cbf306847b55cdc04875b335f11271f6857143 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 14:38:19 -0700 Subject: [PATCH 27/53] Local discovery view --- bookwyrm/templates/discover/discover.html | 87 +++++++++++++------ bookwyrm/templates/discover/large-book.html | 66 ++++++++++---- bookwyrm/templates/discover/small-book.html | 43 +++++---- .../templates/snippets/follow_button.html | 20 ++++- bookwyrm/views/discover.py | 18 ++-- 5 files changed, 166 insertions(+), 68 deletions(-) diff --git a/bookwyrm/templates/discover/discover.html b/bookwyrm/templates/discover/discover.html index 0a419e51b..01ef21869 100644 --- a/bookwyrm/templates/discover/discover.html +++ b/bookwyrm/templates/discover/discover.html @@ -5,50 +5,85 @@ {% block content %} -
-

{% trans "Discover" %}

-
+
+
+

{% trans "Discover" %}

+

+ {% blocktrans trimmed with site_name=site.name %} + See what's new in the local {{ site_name }} community + {% endblocktrans %} +

+
-
-
-
+
+
- {% include 'discover/large-book.html' with status=large.0 %} + {% include 'discover/large-book.html' with status=large_activities.0 %}
-
-
+
+
+ {% include 'discover/large-book.html' with status=large_activities.1 %} +
+
+
+ +
+
+
- {% include 'discover/small-book.html' with status=small.0 %} + {% include 'discover/large-book.html' with status=large_activities.2 %}
-
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.0 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.1 %} +
+
+
+
+
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.2 %} +
+
+
+
+ {% include 'discover/small-book.html' with status=small_activities.3 %} +
+
+
+
- {% include 'discover/small-book.html' with status=small.1 %} + {% include 'discover/large-book.html' with status=large_activities.3 %}
-
-
-
-
- {% include 'discover/small-book.html' with status=small.2 %} -
-
-
-
- {% include 'discover/small-book.html' with status=small.3 %} -
+ +
+
+
+ {% include 'discover/large-book.html' with status=large_activities.4 %}
-
+
- {% include 'discover/large-book.html' with status=large.1 %} + {% include 'discover/large-book.html' with status=large_activities.5 %}
- +
+ {% include 'snippets/pagination.html' with page=large_activities %} +
{% endblock %} diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html index b273d4318..81620be1c 100644 --- a/bookwyrm/templates/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -1,37 +1,67 @@ {% load bookwyrm_tags %} -{% load markdown %} {% load i18n %} -{% if book %} - {% with book=book %} +{% if status %} + {% with book=status.book %}
-
+
{% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto-tablet' %} {% include 'snippets/stars.html' with rating=book|rating:request.user %} -
- - -
-

+

{{ book.title }}

{% if book.authors %} -

- {% trans "by" %} - {% include 'snippets/authors.html' with limit=3 %} -

+

+ {% trans "by" %} + {% include 'snippets/authors.html' with limit=3 %} +

{% endif %} - {% if book|book_description %} -
- {{ book|book_description|to_markdown|safe|truncatewords_html:50 }} -
- {% endif %} + {% include 'snippets/shelve_button/shelve_button.html' %} +
+ +
+
+ +
+

+ + {{ status.user.display_name }} + + + {% if status.status_type == 'GeneratedNote' %} + {{ status.content|safe }} + {% elif status.status_type == 'Rating' %} + {% trans "rated" %} + {% elif status.status_type == 'Review' %} + {% trans "reviewed" %} + {% elif status.status_type == 'Comment' %} + {% trans "commented on" %} + {% elif status.status_type == 'Quotation' %} + {% trans "quoted" %} + {% endif %} + + {{ book.title }} +

+
+
+ +
+ {% include 'snippets/follow_button.html' with user=status.user show_username=True minimal=True %} +
+ +
+ {% include "snippets/status/content_status.html" with hide_book=True %} +
{% endwith %} diff --git a/bookwyrm/templates/discover/small-book.html b/bookwyrm/templates/discover/small-book.html index 052a540cf..1318c8bdc 100644 --- a/bookwyrm/templates/discover/small-book.html +++ b/bookwyrm/templates/discover/small-book.html @@ -5,23 +5,14 @@ {% if status %} {% with book=status.book %} - {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-h-l-tablet is-w-auto align to-b to-l' %} + {% include 'snippets/book_cover.html' with cover_class='is-w-l-mobile is-w-auto align to-b to-l' %} - {% include 'snippets/stars.html' with rating=book|rating:request.user %} +
+ {% include 'snippets/shelve_button/shelve_button.html' %} +
-

- {{ book.title }} -

- - {% if book.authors %} -

- {% trans "by" %} - {% include 'snippets/authors.html' with limit=3 %} -

- {% endif %} - -
+
-

+

{{ status.user.display_name }} + + {% if status.status_type == 'GeneratedNote' %} + {{ status.content|safe }} + {% elif status.status_type == 'Rating' %} + {% trans "rated" %} + {% elif status.status_type == 'Review' %} + {% trans "reviewed" %} + {% elif status.status_type == 'Comment' %} + {% trans "commented on" %} + {% elif status.status_type == 'Quotation' %} + {% trans "quoted" %} + {% endif %} + + {{ book.title }}

+ {% if status.rating %} +

+ {% include 'snippets/stars.html' with rating=status.rating %} +

+ {% endif %}
+
+ {% include 'snippets/follow_button.html' with user=status.user show_username=True minimal=True %} +
{% endwith %} {% endif %} diff --git a/bookwyrm/templates/snippets/follow_button.html b/bookwyrm/templates/snippets/follow_button.html index 0cbe6b8cd..8cafad7f9 100644 --- a/bookwyrm/templates/snippets/follow_button.html +++ b/bookwyrm/templates/snippets/follow_button.html @@ -9,15 +9,29 @@ {% csrf_token %} - +
diff --git a/bookwyrm/views/discover.py b/bookwyrm/views/discover.py index 685a4ded7..0b1fae2b5 100644 --- a/bookwyrm/views/discover.py +++ b/bookwyrm/views/discover.py @@ -7,7 +7,6 @@ from django.utils.decorators import method_decorator from django.views import View from bookwyrm import models -from bookwyrm.settings import PAGE_LENGTH from .helpers import privacy_filter @@ -24,13 +23,20 @@ class Discover(View): Q(comment__isnull=False) | Q(review__isnull=False) | Q(quotation__isnull=False), - user__local=True + user__local=True, ), - #privacy_levels=["public"] + privacy_levels=["public"], ) - #paginated = Paginator(activities, PAGE_LENGTH) + large_activities = Paginator( + activities.filter(~Q(content=None), ~Q(content="")), 6 + ) + small_activities = Paginator( + activities.filter(Q(content=None) | Q(content="")), 4 + ) + + page = request.GET.get("page") data = { - "large": activities.filter(~Q(review__isnull=True, review__content=None))[:2], - "small": activities.filter(~Q(content=None))[:4], + "large_activities": large_activities.get_page(page), + "small_activities": small_activities.get_page(page), } return TemplateResponse(request, "discover/discover.html", data) From 2eb37663b6a032aac0b2bf227c4e3f8230cf71f6 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 14:46:33 -0700 Subject: [PATCH 28/53] Adds mock to inbox test --- bookwyrm/tests/views/inbox/test_inbox_create.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bookwyrm/tests/views/inbox/test_inbox_create.py b/bookwyrm/tests/views/inbox/test_inbox_create.py index f93354bfb..6e8917238 100644 --- a/bookwyrm/tests/views/inbox/test_inbox_create.py +++ b/bookwyrm/tests/views/inbox/test_inbox_create.py @@ -47,7 +47,8 @@ class InboxCreate(TestCase): } models.SiteSettings.objects.create() - def test_create_status(self, _): + @patch("bookwyrm.activitystreams.ActivityStream.add_status") + def test_create_status(self, *_): """the "it justs works" mode""" datafile = pathlib.Path(__file__).parent.joinpath( "../../data/ap_quotation.json" From 760bd5a63fb51671f945bcb2f614eca41240d574 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 15:10:09 -0700 Subject: [PATCH 29/53] Fixes reference to landing page books --- bookwyrm/management/commands/populate_streams.py | 2 +- bookwyrm/views/invite.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bookwyrm/management/commands/populate_streams.py b/bookwyrm/management/commands/populate_streams.py index f8aa21a52..37559f082 100644 --- a/bookwyrm/management/commands/populate_streams.py +++ b/bookwyrm/management/commands/populate_streams.py @@ -8,7 +8,7 @@ def populate_streams(): users = models.User.objects.filter( local=True, is_active=True, - ) + ).order_by("last_active_date") for user in users: for stream in activitystreams.streams.values(): stream.populate_streams(user) diff --git a/bookwyrm/views/invite.py b/bookwyrm/views/invite.py index 3b9fd17c5..005d57cf8 100644 --- a/bookwyrm/views/invite.py +++ b/bookwyrm/views/invite.py @@ -170,9 +170,9 @@ class InviteRequest(View): data = { "request_form": form, "request_received": received, - "books": helpers.get_discover_books(), + "books": helpers.get_landing_books(), } - return TemplateResponse(request, "discover/discover.html", data) + return TemplateResponse(request, "landing/landing.html", data) @require_POST From 1006096cd06cc861c1ad5e0283f699f75f9869df Mon Sep 17 00:00:00 2001 From: Justin Abrahms Date: Sat, 7 Aug 2021 15:40:50 -0700 Subject: [PATCH 30/53] Close the span tag for an author. --- bookwyrm/templates/snippets/authors.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bookwyrm/templates/snippets/authors.html b/bookwyrm/templates/snippets/authors.html index 5584417d9..81aaa138b 100644 --- a/bookwyrm/templates/snippets/authors.html +++ b/bookwyrm/templates/snippets/authors.html @@ -19,7 +19,7 @@ itemtype="https://schema.org/Thing" >{{ author.name }}{% if not forloop.last %}, {% elif remainder_count > 0 %}, {% blocktrans trimmed count counter=remainder_count %} + >{{ author.name }}{% if not forloop.last %}, {% elif remainder_count > 0 %}, {% blocktrans trimmed count counter=remainder_count %} and {{ remainder_count_display }} other {% plural %} and {{ remainder_count_display }} others From 650a6037a29abb2c47e0084fc91c29594fe61f7b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 15:51:53 -0700 Subject: [PATCH 31/53] Trims status text --- bookwyrm/templates/discover/large-book.html | 9 +++++++-- bookwyrm/templates/snippets/trimmed_text.html | 7 ++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/bookwyrm/templates/discover/large-book.html b/bookwyrm/templates/discover/large-book.html index 81620be1c..fdea582d8 100644 --- a/bookwyrm/templates/discover/large-book.html +++ b/bookwyrm/templates/discover/large-book.html @@ -1,5 +1,6 @@ {% load bookwyrm_tags %} {% load i18n %} +{% load status_display %} {% if status %} {% with book=status.book %} @@ -59,9 +60,13 @@ {% include 'snippets/follow_button.html' with user=status.user show_username=True minimal=True %}
-
- {% include "snippets/status/content_status.html" with hide_book=True %} +
+ {% include "snippets/status/content_status.html" with hide_book=True trim_length=100 hide_more=True %}
+ + {% trans "View status" %} + +
{% endwith %} diff --git a/bookwyrm/templates/snippets/trimmed_text.html b/bookwyrm/templates/snippets/trimmed_text.html index cfffe0551..f6174a192 100644 --- a/bookwyrm/templates/snippets/trimmed_text.html +++ b/bookwyrm/templates/snippets/trimmed_text.html @@ -3,20 +3,24 @@ {% load i18n %} {% with 0|uuid as uuid %} +{% firstof trim_length 150 as trim_length %} {% if full %} {% with full|to_markdown|safe as full %} - {% with full|to_markdown|safe|truncatewords_html:150 as trimmed %} + {% with full|to_markdown|safe|truncatewords_html:trim_length as trimmed %} {% if not no_trim and trimmed != full %}
{{ trimmed }}
+ {% if not hide_more %} {% trans "Show more" as button_text %} {% include 'snippets/toggle/open_button.html' with text=button_text controls_text="full" controls_uid=uuid class="is-small" %} + {% endif %}
+ {% if not hide_more %}