From 9804d4cf514585b66d286cc8d1d55a6b13f1eb3b Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Fri, 6 Aug 2021 10:19:38 -0700 Subject: [PATCH 01/19] 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 3b674852..6280f54f 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/19] 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 3c5d8b25..d75d368c 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/19] 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 10531f51..e2d67fbe 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 003e94b0..6598aef2 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/19] 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 13c0ef5d..d9d67d56 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 b047f031..140f91dc 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 153d8b9a..ab56046e 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 5bae4d7e..dbf7540c 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 399e4056..b4405df5 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 d9921655..471de85d 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 5ce42251..40b12995 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/19] 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 1eaf57c0..6ad46420 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/19] 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 00000000..76c8c962 --- /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 2cb7c036..5b55ea50 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 872f6b45..fdc06866 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 cb6941c9..08bd87b3 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/19] 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 f42aaaae..a74e7bb3 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 5115469c..c5edb55e 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 657310b0..516d64c9 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 08bd87b3..94b7b41e 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 180191d9..130889ac 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 00000000..b47642af --- /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 00000000..b81a5a83 --- /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 00000000..e3d73938 --- /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 003e94b0..43b4bb37 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 46bdf722..42e8a6dd 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/19] 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 a74e7bb3..f42aaaae 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 c5edb55e..5115469c 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 516d64c9..cf46baf3 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 76c8c962..ab0aa158 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 fdc06866..ef3f7c3c 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 94b7b41e..e10bcd29 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 130889ac..180191d9 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 00000000..ac5b9282 --- /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 d3e2dad1..e7036feb 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 41bb64e5..112271a7 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 43b4bb37..edf960cc 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/19] 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 cf46baf3..fff3985e 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 ac5b9282..00000000 --- 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 00000000..85ca2bb1 --- /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 00000000..00a89403 --- /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 d36371a4..f64b529a 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 edf960cc..dedcf408 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/19] 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 85ca2bb1..6c9eda5e 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 00a89403..7c0c1098 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 e3d0133c..19c103ea 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 e7036feb..eb8491a9 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 112271a7..eccb7f5e 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 dedcf408..f81be8d1 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/19] 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 6280f54f..c5d86a12 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/19] 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 03147744..03875193 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 e2d67fbe..bbafe7bd 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/19] 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 140f91dc..4906082a 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 ab56046e..e8e3b0b3 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 dbf7540c..9fc28535 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 b4405df5..f0a559f9 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 471de85d..adb0d36c 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 40b12995..c496bb92 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/19] 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 bbafe7bd..bd4b3b02 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/19] 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 5cba5455..4811f4fd 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 d56e2f22..6cd0427c 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/19] 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 bd4b3b02..dc9f5dd5 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/19] 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 b47642af..231b0388 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 e3d73938..847009e5 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/19] 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 cd7ea806..9e610bd1 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 026c6ac025f2725f0e2805da4e7040e212a4d4a5 Mon Sep 17 00:00:00 2001 From: Mouse Reeve Date: Sat, 7 Aug 2021 08:01:14 -0700 Subject: [PATCH 19/19] 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 dc9f5dd5..22008e10 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()