From 05ec6cbe742ea5893016e1d74b0988ecd031924c Mon Sep 17 00:00:00 2001 From: Osma Ahvenlampi Date: Thu, 16 Nov 2023 16:07:28 +0200 Subject: [PATCH 1/2] add support for enabling Mastodon 4.2 search indexing --- api/schemas.py | 1 + core/ld.py | 1 + templates/identity/create.html | 1 + templates/settings/profile.html | 1 + tests/users/models/test_identity.py | 2 ++ users/migrations/0023_identity_indexable.py | 18 ++++++++++++++++++ users/models/identity.py | 4 ++++ users/services/identity.py | 2 ++ users/views/identity.py | 9 +++++++++ users/views/settings/profile.py | 9 +++++++++ 10 files changed, 48 insertions(+) create mode 100644 users/migrations/0023_identity_indexable.py diff --git a/api/schemas.py b/api/schemas.py index 0f0441c9c..1bcffeca8 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -71,6 +71,7 @@ class Account(Schema): bot: bool group: bool discoverable: bool + indexable: bool moved: Union[None, bool, "Account"] suspended: bool = False limited: bool = False diff --git a/core/ld.py b/core/ld.py index 9a5f7f913..0b7513cc2 100644 --- a/core/ld.py +++ b/core/ld.py @@ -557,6 +557,7 @@ "@context": { "toot": "http://joinmastodon.org/ns#", "discoverable": "toot:discoverable", + "indexable": "toot:indexable", "devices": "toot:devices", "featured": "toot:featured", "featuredTags": "toot:featuredTags", diff --git a/templates/identity/create.html b/templates/identity/create.html index 8d353d206..770a055f4 100644 --- a/templates/identity/create.html +++ b/templates/identity/create.html @@ -31,6 +31,7 @@

Create New Identity

{% include "forms/_field.html" with field=form.domain %} {% include "forms/_field.html" with field=form.name %} {% include "forms/_field.html" with field=form.discoverable %} + {% include "forms/_field.html" with field=form.indexable %}
diff --git a/templates/settings/profile.html b/templates/settings/profile.html index 1ceabea38..1260de78d 100644 --- a/templates/settings/profile.html +++ b/templates/settings/profile.html @@ -24,6 +24,7 @@
Privacy {% include "forms/_field.html" with field=form.discoverable %} + {% include "forms/_field.html" with field=form.indexable %} {% include "forms/_field.html" with field=form.visible_follows %} {% include "forms/_field.html" with field=form.search_enabled %}
diff --git a/tests/users/models/test_identity.py b/tests/users/models/test_identity.py index 3b8ac356f..5c7a9a853 100644 --- a/tests/users/models/test_identity.py +++ b/tests/users/models/test_identity.py @@ -204,6 +204,8 @@ def test_fetch_actor(httpx_mock, config_system): assert identity.image_uri == "https://example.com/image.jpg" assert identity.summary == "

A test user

" assert "ts-a-faaaake" in identity.public_key + # convention is that indexability should be opt-in + assert not identity.indexable @pytest.mark.django_db diff --git a/users/migrations/0023_identity_indexable.py b/users/migrations/0023_identity_indexable.py new file mode 100644 index 000000000..baced4bdc --- /dev/null +++ b/users/migrations/0023_identity_indexable.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.3 on 2023-11-16 13:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("users", "0022_follow_request"), + ] + + operations = [ + migrations.AddField( + model_name="identity", + name="indexable", + field=models.BooleanField(default=False), + ), + ] diff --git a/users/models/identity.py b/users/models/identity.py index 8912b33a9..0c98db83b 100644 --- a/users/models/identity.py +++ b/users/models/identity.py @@ -195,6 +195,7 @@ class Restriction(models.IntegerChoices): summary = models.TextField(blank=True, null=True) manually_approves_followers = models.BooleanField(blank=True, null=True) discoverable = models.BooleanField(default=True) + indexable = models.BooleanField(default=False) profile_uri = models.CharField(max_length=500, blank=True, null=True) inbox_uri = models.CharField(max_length=500, blank=True, null=True) @@ -557,6 +558,7 @@ def to_ap(self): "published": self.created.strftime("%Y-%m-%dT%H:%M:%SZ"), "url": self.absolute_profile_uri(), "toot:discoverable": self.discoverable, + "toot:indexable": self.indexable, } if self.name: response["name"] = self.name @@ -914,6 +916,7 @@ def fetch_actor(self) -> bool: self.icon_uri = get_first_image_url(document.get("icon", None)) self.image_uri = get_first_image_url(document.get("image", None)) self.discoverable = document.get("toot:discoverable", True) + self.indexable = document.get("toot:indexable", False) # Profile links/metadata self.metadata = [] for attachment in get_list(document, "attachment"): @@ -1051,6 +1054,7 @@ def to_mastodon_json(self, source=False, include_counts=True): "bot": self.actor_type.lower() in ["service", "application"], "group": self.actor_type.lower() == "group", "discoverable": self.discoverable, + "indexable": self.indexable, "suspended": False, "limited": False, "created_at": format_ld_date( diff --git a/users/services/identity.py b/users/services/identity.py index 20b9984d3..89aec64d6 100644 --- a/users/services/identity.py +++ b/users/services/identity.py @@ -36,6 +36,7 @@ def create( domain: Domain, name: str, discoverable: bool = True, + indexable: bool = False, ) -> Identity: identity = Identity.objects.create( actor_uri=f"https://{domain.uri_domain}/@{username}@{domain.domain}/", @@ -44,6 +45,7 @@ def create( name=name, local=True, discoverable=discoverable, + indexable=indexable, ) identity.users.add(user) identity.generate_keypair() diff --git a/users/views/identity.py b/users/views/identity.py index 028e49a95..737239791 100644 --- a/users/views/identity.py +++ b/users/views/identity.py @@ -313,6 +313,14 @@ class form_class(forms.Form): ), required=False, ) + indexable = forms.BooleanField( + help_text="Should this user's activities be indexable on other servers.", + initial=False, + widget=forms.Select( + choices=[(True, "Indexable"), (False, "Not Indexable")] + ), + required=False, + ) def __init__(self, user, *args, **kwargs): super().__init__(*args, **kwargs) @@ -385,6 +393,7 @@ def form_valid(self, form): domain=domain_instance, name=form.cleaned_data["name"], discoverable=form.cleaned_data["discoverable"], + indexable=form.cleaned_data["indexable"], ) self.request.session["identity_id"] = identity.id return redirect(identity.urls.view) diff --git a/users/views/settings/profile.py b/users/views/settings/profile.py index 2573d3cb8..2a5a16d39 100644 --- a/users/views/settings/profile.py +++ b/users/views/settings/profile.py @@ -43,6 +43,13 @@ class form_class(forms.Form): ), required=False, ) + indexable = forms.BooleanField( + help_text="Opt-in to be indexed for search on other servers.\n(Disabling this does not guarantee third-party servers won't index your posts without permission)", + widget=forms.Select( + choices=[(True, "Indexable"), (False, "Not Indexable")] + ), + required=False, + ) visible_follows = forms.BooleanField( help_text="Whether or not to show your following and follower counts in your profile", widget=forms.Select(choices=[(True, "Visible"), (False, "Hidden")]), @@ -93,6 +100,7 @@ def get_initial(self): "icon": self.identity.icon and self.identity.icon.url, "image": self.identity.image and self.identity.image.url, "discoverable": self.identity.discoverable, + "indexable": self.identity.indexable, "visible_follows": self.identity.config_identity.visible_follows, "metadata": self.identity.metadata or [], "search_enabled": self.identity.config_identity.search_enabled, @@ -104,6 +112,7 @@ def form_valid(self, form): service = IdentityService(self.identity) self.identity.name = form.cleaned_data["name"] self.identity.discoverable = form.cleaned_data["discoverable"] + self.identity.indexable = form.cleaned_data["indexable"] service.set_summary(form.cleaned_data["summary"]) # Resize images icon = form.cleaned_data.get("icon") From 85ee2692f1224e3677f8fba6b6f16028514cbf6b Mon Sep 17 00:00:00 2001 From: Osma Ahvenlampi Date: Thu, 16 Nov 2023 17:45:25 +0200 Subject: [PATCH 2/2] change in migrations formatting --- users/migrations/0023_identity_indexable.py | 1 - 1 file changed, 1 deletion(-) diff --git a/users/migrations/0023_identity_indexable.py b/users/migrations/0023_identity_indexable.py index baced4bdc..bd2d420b1 100644 --- a/users/migrations/0023_identity_indexable.py +++ b/users/migrations/0023_identity_indexable.py @@ -4,7 +4,6 @@ class Migration(migrations.Migration): - dependencies = [ ("users", "0022_follow_request"), ]