Fixed #616: Do followers-only properly

pull/618/head
Andrew Godwin 2023-07-22 10:38:22 -06:00
rodzic 1dd076ff7d
commit 759d5ac052
4 zmienionych plików z 77 dodań i 8 usunięć

Wyświetl plik

@ -623,6 +623,7 @@ class Post(StatorModel):
"""
Returns the AP JSON for this object
"""
self.author.ensure_uris()
value = {
"to": [],
"cc": [],
@ -655,11 +656,14 @@ class Post(StatorModel):
if self.edited:
value["updated"] = format_ld_date(self.edited)
# Targeting
# TODO: Add followers object
if self.visibility == self.Visibilities.public:
value["to"].append("as:Public")
elif self.visibility == self.Visibilities.unlisted:
value["cc"].append("as:Public")
elif (
self.visibility == self.Visibilities.followers and self.author.followers_uri
):
value["to"].append(self.author.followers_uri)
# Mentions
for mention in self.mentions.all():
value["tag"].append(mention.to_ap_tag())
@ -922,6 +926,8 @@ class Post(StatorModel):
post.visibility = Post.Visibilities.public
elif "public" in cc or "as:public" in cc:
post.visibility = Post.Visibilities.unlisted
elif post.author.followers_uri in to:
post.visibility = Post.Visibilities.followers
# Attachments
# These have no IDs, so we have to wipe them each time
post.attachments.all().delete()

Wyświetl plik

@ -1,5 +1,5 @@
0.9
===
0.10
====
*Released: Not Yet Released*
@ -15,6 +15,11 @@ This release's major changes:
* TBC
Minor changes also include:
* Followers-only mode now works correctly inbound and outbound (though outbound
may need the other server to refresh the profile first).
If you'd like to help with code, design, or other areas, see
:doc:`/contributing` to see how to get in touch.

Wyświetl plik

@ -499,3 +499,45 @@ def test_post_hashtag_to_ap(identity: Identity, config_system):
]
assert "#world" in ap["object"]["content"]
assert 'rel="tag"' in ap["object"]["content"]
@pytest.mark.django_db
@pytest.mark.parametrize(
"visibility",
[
Post.Visibilities.public,
Post.Visibilities.unlisted,
Post.Visibilities.followers,
Post.Visibilities.mentioned,
],
)
def test_post_targets_to_ap(
identity: Identity, other_identity: Identity, visibility: Post.Visibilities
):
"""
Ensures that posts have the right targets in AP form.
"""
# Make a post
post = Post.objects.create(
content="<p>Hello @other</p>",
author=identity,
local=True,
visibility=visibility,
)
post.mentions.add(other_identity)
# Check its AP targets
ap_dict = post.to_ap()
if visibility == Post.Visibilities.public:
assert ap_dict["to"] == ["as:Public"]
assert ap_dict["cc"] == [other_identity.actor_uri]
elif visibility == Post.Visibilities.unlisted:
assert "to" not in ap_dict
assert ap_dict["cc"] == ["as:Public", other_identity.actor_uri]
elif visibility == Post.Visibilities.followers:
assert ap_dict["to"] == [identity.followers_uri]
assert ap_dict["cc"] == [other_identity.actor_uri]
elif visibility == Post.Visibilities.mentioned:
assert "to" not in ap_dict
assert ap_dict["cc"] == [other_identity.actor_uri]

Wyświetl plik

@ -317,6 +317,19 @@ class Identity(StatorModel):
for data in self.metadata
]
def ensure_uris(self):
"""
Ensures that local identities have all the URIs populated on their fields
(this lets us add new ones easily)
"""
if self.local:
self.inbox_uri = self.actor_uri + "inbox/"
self.outbox_uri = self.actor_uri + "outbox/"
self.featured_collection_uri = self.actor_uri + "collections/featured/"
self.followers_uri = self.actor_uri + "followers/"
self.following_uri = self.actor_uri + "following/"
self.shared_inbox_uri = f"https://{self.domain.uri_domain}/inbox/"
### Alternate constructors/fetchers ###
@classmethod
@ -482,12 +495,15 @@ class Identity(StatorModel):
def to_ap(self):
from activities.models import Emoji
self.ensure_uris()
response = {
"id": self.actor_uri,
"type": self.actor_type.title(),
"inbox": self.actor_uri + "inbox/",
"outbox": self.actor_uri + "outbox/",
"featured": self.actor_uri + "collections/featured/",
"inbox": self.inbox_uri,
"outbox": self.outbox_uri,
"featured": self.featured_collection_uri,
"followers": self.followers_uri,
"following": self.following_uri,
"preferredUsername": self.username,
"publicKey": {
"id": self.public_key_id,
@ -514,9 +530,9 @@ class Identity(StatorModel):
"mediaType": media_type_from_filename(self.image.name),
"url": self.image.url,
}
if self.local:
if self.shared_inbox_uri:
response["endpoints"] = {
"sharedInbox": f"https://{self.domain.uri_domain}/inbox/",
"sharedInbox": self.shared_inbox_uri,
}
if self.metadata:
response["attachment"] = [