kopia lustrzana https://gitlab.com/jaywink/federation
fix tests
rodzic
63b591db46
commit
46a518f04a
|
@ -28,7 +28,13 @@ def get_outbound_entity(entity: BaseEntity, private_key):
|
|||
return entity
|
||||
outbound = None
|
||||
cls = entity.__class__
|
||||
if cls == Accept:
|
||||
if cls in [
|
||||
models.Accept, models.Follow, models.Person, models.Note,
|
||||
models.Delete, models.Tombstone, models.Announce,
|
||||
] and isinstance(entity, BaseEntity):
|
||||
# Already fine
|
||||
outbound = entity
|
||||
elif cls == Accept:
|
||||
outbound = models.Accept.from_base(entity)
|
||||
elif cls == Follow:
|
||||
outbound = models.Follow.from_base(entity)
|
||||
|
|
|
@ -206,7 +206,6 @@ class MixedField(fields.Nested):
|
|||
return super()._serialize(value, attr, obj, **kwargs)
|
||||
|
||||
def _deserialize(self, value, attr, data, **kwargs):
|
||||
print(attr, value, type(value))
|
||||
# this is just so the ACTIVITYPUB_POST_OBJECT_IMAGES test payload passes
|
||||
if len(value) == 0: return value
|
||||
|
||||
|
@ -293,7 +292,6 @@ class Object(BaseEntity, metaclass=JsonLDAnnotation):
|
|||
|
||||
def to_as2(self):
|
||||
obj = self.activity if isinstance(self.activity, Activity) else self
|
||||
print('to_as2', obj, getattr(obj, 'tag_objects', None))
|
||||
return jsonld.compact(obj.dump(), CONTEXT)
|
||||
|
||||
@classmethod
|
||||
|
@ -399,10 +397,8 @@ class Home(metaclass=JsonLDAnnotation):
|
|||
|
||||
class NormalizedList(fields.List):
|
||||
def _deserialize(self,value, attr, data, **kwargs):
|
||||
print('List', attr, value)
|
||||
value = normalize_value(value)
|
||||
ret = super()._deserialize(value,attr,data,**kwargs)
|
||||
print('List after', ret)
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -555,9 +551,9 @@ class Emoji(Object):
|
|||
class Person(Object, base.Profile):
|
||||
id = fields.Id()
|
||||
inbox = IRI(ldp.inbox)
|
||||
outbox = IRI(as2.outbox, dump_derived={'fmt': '{id}/outbox/', 'fields': ['id']})
|
||||
following = IRI(as2.following, dump_derived={'fmt': '{id}/following/', 'fields': ['id']})
|
||||
followers = IRI(as2.followers, dump_derived={'fmt': '{id}/followers/', 'fields': ['id']})
|
||||
outbox = IRI(as2.outbox)
|
||||
following = IRI(as2.following)
|
||||
followers = IRI(as2.followers)
|
||||
username = fields.String(as2.preferredUsername)
|
||||
endpoints = CompactedDict(as2.endpoints)
|
||||
shared_inbox = IRI(as2.sharedInbox) # misskey adds this
|
||||
|
@ -570,7 +566,7 @@ class Person(Object, base.Profile):
|
|||
devices = IRI(toot.devices)
|
||||
public_key_dict = CompactedDict(sec.publicKey)
|
||||
guid = fields.String(diaspora.guid)
|
||||
handle = fields.String(diaspora.handle)
|
||||
handle = fields.String(diaspora.handle, default="")
|
||||
raw_content = fields.String(as2.summary, default="") # None fails in extract_mentions
|
||||
has_address = MixedField(vcard.hasAddress, nested='HomeSchema')
|
||||
has_instant_message = fields.List(vcard.hasInstantMessage, cls_or_instance=fields.String)
|
||||
|
@ -580,6 +576,7 @@ class Person(Object, base.Profile):
|
|||
copied_to = IRI(toot.copiedTo)
|
||||
capabilities = CompactedDict(litepub.capabilities)
|
||||
suspended = fields.Boolean(toot.suspended)
|
||||
public = True
|
||||
_inboxes = None
|
||||
_public_key = None
|
||||
_image_urls = None
|
||||
|
@ -598,7 +595,21 @@ class Person(Object, base.Profile):
|
|||
self._allowed_children += (PropertyValue, IdentityProof)
|
||||
|
||||
def to_as2(self):
|
||||
self.id = self.id.rstrip('/') # TODO: sort out the trailing / business
|
||||
#self.id = self.id.rstrip('/') # TODO: sort out the trailing / business
|
||||
self.followers = f'{with_slash(self.id)}followers/'
|
||||
self.following = f'{with_slash(self.id)}following/'
|
||||
self.outbox = f'{with_slash(self.id)}outbox/'
|
||||
|
||||
if hasattr(self, 'times'):
|
||||
if self.times.get('updated',0) > self.times.get('created',0):
|
||||
self.updated = self.times.get('updated')
|
||||
if self.times.get('edited'):
|
||||
self.activity = Update(
|
||||
activity_id=f'{self.id}#profile-{uuid.uuid4()}',
|
||||
actor_id=self.id,
|
||||
created_at=self.times.get('updated'),
|
||||
object_=self,
|
||||
)
|
||||
return super().to_as2()
|
||||
|
||||
@property
|
||||
|
@ -617,10 +628,11 @@ class Person(Object, base.Profile):
|
|||
|
||||
@inboxes.setter
|
||||
def inboxes(self, value):
|
||||
self._inboxes = value
|
||||
if isinstance(value, dict):
|
||||
self.inbox = value.get('private', None)
|
||||
self.endpoints = {'sharedInbox': value.get('public', None)}
|
||||
if value != {'private':None, 'public':None}:
|
||||
self._inboxes = value
|
||||
if isinstance(value, dict):
|
||||
self.inbox = value.get('private', None)
|
||||
self.endpoints = {'sharedInbox': value.get('public', None)}
|
||||
|
||||
@property
|
||||
def public_key(self):
|
||||
|
@ -634,8 +646,9 @@ class Person(Object, base.Profile):
|
|||
@public_key.setter
|
||||
def public_key(self, value):
|
||||
self._public_key = value
|
||||
id_ = self.id.rstrip('/')
|
||||
self.public_key_dict = {'id': id_+'#main-key', 'owner': id_, 'publicKeyPem': value}
|
||||
#id_ = self.id.rstrip('/')
|
||||
#self.public_key_dict = {'id': id_+'#main-key', 'owner': id_, 'publicKeyPem': value}
|
||||
self.public_key_dict = {'id': self.id+'#main-key', 'owner': self.id, 'publicKeyPem': value}
|
||||
|
||||
@property
|
||||
def image_urls(self):
|
||||
|
@ -652,18 +665,15 @@ class Person(Object, base.Profile):
|
|||
|
||||
@image_urls.setter
|
||||
def image_urls(self, value):
|
||||
self._image_urls = value
|
||||
if value.get('large'):
|
||||
try:
|
||||
profile_icon = base.Image(url=value.get('large'))
|
||||
if profile_icon.media_type:
|
||||
self.icon = [Image.from_base(profile_icon)]
|
||||
except Exception as ex:
|
||||
logger.warning("models.Person - failed to set profile icon: %s", ex)
|
||||
|
||||
def to_base(self):
|
||||
set_public(self)
|
||||
return self
|
||||
if value != {'large':'', 'medium':'', 'small':''}:
|
||||
self._image_urls = value
|
||||
if value.get('large'):
|
||||
try:
|
||||
profile_icon = base.Image(url=value.get('large'))
|
||||
if profile_icon.media_type:
|
||||
self.icon = [Image.from_base(profile_icon)]
|
||||
except Exception as ex:
|
||||
logger.warning("models.Person - failed to set profile icon: %s", ex)
|
||||
|
||||
class Meta:
|
||||
rdf_type = as2.Person
|
||||
|
@ -988,11 +998,10 @@ class Follow(Activity, base.Follow):
|
|||
def to_as2(self):
|
||||
if not self.following:
|
||||
self.activity = Undo(
|
||||
activity_id = self.activity_id,
|
||||
activity_id = self.activity_id if self.activity_id else f"{self.actor_id}#follow-{uuid.uuid4()}",
|
||||
actor_id = self.actor_id,
|
||||
object_ = self
|
||||
)
|
||||
self.activity_id = f"{self.actor_id}#follow-{uuid.uuid4()}"
|
||||
|
||||
return super().to_as2()
|
||||
|
||||
|
@ -1067,10 +1076,8 @@ class Announce(Activity, base.Share):
|
|||
self.activity = self.activity(
|
||||
activity_id = self.activity_id if self.activity_id else f"{self.actor_id}#share-{uuid.uuid4()}",
|
||||
actor_id = self.actor_id,
|
||||
created_at = self.created_at,
|
||||
object_ = self
|
||||
)
|
||||
self.id = f"{self.target_id}"
|
||||
|
||||
return super().to_as2()
|
||||
|
||||
|
@ -1097,7 +1104,7 @@ class Tombstone(Object, base.Retraction):
|
|||
def to_as2(self):
|
||||
if not isinstance(self.activity, type): return None
|
||||
self.activity = self.activity(
|
||||
activity_id = self.activity_id,
|
||||
activity_id = self.activity_id if self.activity_id else f"{self.actor_id}#delete-{uuid.uuid4()}",
|
||||
actor_id = self.actor_id,
|
||||
created_at = self.created_at,
|
||||
object_ = self,
|
||||
|
@ -1200,9 +1207,9 @@ def extract_receivers(entity):
|
|||
"""
|
||||
receivers = []
|
||||
profile = None
|
||||
# don't care about receivers for payloads without an actor_id
|
||||
with rc.enabled(cache_name='fed_cache', backend=backend):
|
||||
if getattr(entity, 'actor_id'):
|
||||
# don't care about receivers for payloads without an actor_id
|
||||
if getattr(entity, 'actor_id'):
|
||||
with rc.enabled(cache_name='fed_cache', backend=backend):
|
||||
profile = retrieve_and_parse_profile(entity.actor_id)
|
||||
if not profile: return receivers
|
||||
|
||||
|
@ -1262,11 +1269,10 @@ def element_to_objects(element: Union[Dict, Object]) -> List:
|
|||
|
||||
# json-ld handling with calamus
|
||||
# Skips unimplemented payloads
|
||||
# TODO: remove unused code
|
||||
entity = model_to_objects(element) if not isinstance(element, Object) else element
|
||||
#if entity: entity = entity.to_base()
|
||||
if entity and hasattr(entity, 'to_base'):
|
||||
entity = entity.to_base()
|
||||
if isinstance(entity, BaseEntity):
|
||||
try:
|
||||
extract_and_validate(entity)
|
||||
except ValueError as ex:
|
||||
|
|
|
@ -358,6 +358,7 @@ def handle_send(
|
|||
# Do actual sending
|
||||
for payload in payloads:
|
||||
for url in payload["urls"]:
|
||||
# Comment this out for testing
|
||||
#try:
|
||||
# pprint(json.loads(payload["payload"]))
|
||||
#except:
|
||||
|
|
|
@ -15,7 +15,7 @@ def disable_network_calls(monkeypatch):
|
|||
"""Disable network calls."""
|
||||
monkeypatch.setattr("requests.post", Mock())
|
||||
|
||||
class MockResponse(str):
|
||||
class MockGetResponse(str):
|
||||
status_code = 200
|
||||
text = ""
|
||||
|
||||
|
@ -29,8 +29,17 @@ def disable_network_calls(monkeypatch):
|
|||
return saved_get(*args, **kwargs)
|
||||
return DEFAULT
|
||||
|
||||
monkeypatch.setattr("requests.get", Mock(return_value=MockResponse, side_effect=side_effect))
|
||||
monkeypatch.setattr("requests.get", Mock(return_value=MockGetResponse, side_effect=side_effect))
|
||||
|
||||
class MockHeadResponse(dict):
|
||||
status_code = 200
|
||||
headers = {'Content-Type':'image/jpeg'}
|
||||
|
||||
@staticmethod
|
||||
def raise_for_status():
|
||||
pass
|
||||
|
||||
monkeypatch.setattr("requests.head", Mock(return_value=MockHeadResponse))
|
||||
|
||||
@pytest.fixture
|
||||
def private_key():
|
||||
|
|
|
@ -376,10 +376,12 @@ class TestEntitiesConvertToAS2:
|
|||
'id': 'http://127.0.0.1:8000/post/123456/#delete',
|
||||
'actor': 'http://127.0.0.1:8000/profile/123456/',
|
||||
'object': {
|
||||
'actor': 'http://127.0.0.1:8000/profile/123456/',
|
||||
'id': 'http://127.0.0.1:8000/post/123456/activity',
|
||||
'object': 'http://127.0.0.1:8000/post/123456',
|
||||
'type': 'Announce',
|
||||
'published': '2019-04-27T00:00:00',
|
||||
},
|
||||
'published': '2019-04-27T00:00:00',
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from datetime import datetime
|
||||
from unittest.mock import patch, Mock
|
||||
from unittest.mock import patch, Mock, DEFAULT
|
||||
|
||||
import json
|
||||
import pytest
|
||||
|
||||
#from federation.entities.activitypub.entities import (
|
||||
|
@ -8,12 +9,13 @@ import pytest
|
|||
# models.Delete, models.Announce)
|
||||
import federation.entities.activitypub.models as models
|
||||
from federation.entities.activitypub.mappers import message_to_objects, get_outbound_entity
|
||||
from federation.entities.base import Accept, Follow, Profile, Post, Comment, Image, Share
|
||||
from federation.entities.base import Accept, Follow, Profile, Post, Comment, Image, Share, Retraction
|
||||
from federation.tests.fixtures.payloads import (
|
||||
ACTIVITYPUB_FOLLOW, ACTIVITYPUB_PROFILE, ACTIVITYPUB_PROFILE_INVALID, ACTIVITYPUB_UNDO_FOLLOW, ACTIVITYPUB_POST,
|
||||
ACTIVITYPUB_COMMENT, ACTIVITYPUB_RETRACTION, ACTIVITYPUB_SHARE, ACTIVITYPUB_RETRACTION_SHARE,
|
||||
ACTIVITYPUB_POST_IMAGES, ACTIVITYPUB_POST_WITH_SOURCE_MARKDOWN, ACTIVITYPUB_POST_WITH_TAGS,
|
||||
ACTIVITYPUB_POST_WITH_SOURCE_BBCODE, ACTIVITYPUB_POST_WITH_MENTIONS, ACTIVITYPUB_PROFILE_WITH_DIASPORA_GUID)
|
||||
ACTIVITYPUB_POST_WITH_SOURCE_BBCODE, ACTIVITYPUB_POST_WITH_MENTIONS, ACTIVITYPUB_PROFILE_WITH_DIASPORA_GUID,
|
||||
ACTIVITYPUB_REMOTE_PROFILE, ACTIVITYPUB_COLLECTION)
|
||||
from federation.types import UserType, ReceiverVariant
|
||||
|
||||
|
||||
|
@ -217,7 +219,20 @@ class TestActivitypubEntityMappersReceive:
|
|||
assert profile.id == "https://friendica.feneas.org/profile/feneas"
|
||||
assert profile.guid == "76158462365bd347844d248732383358"
|
||||
|
||||
def test_message_to_objects_receivers_are_saved(self):
|
||||
@patch('federation.utils.activitypub.fetch_document')
|
||||
def test_message_to_objects_receivers_are_saved(self, mock_fetch):
|
||||
def side_effect(*args, **kwargs):
|
||||
payloads = {'https://diaspodon.fr/users/jaywink': json.dumps(ACTIVITYPUB_PROFILE),
|
||||
'https://fosstodon.org/users/astdenis': json.dumps(ACTIVITYPUB_REMOTE_PROFILE),
|
||||
'https://diaspodon.fr/users/jaywink/followers': json.dumps(ACTIVITYPUB_COLLECTION),
|
||||
}
|
||||
if args[0] in payloads.keys():
|
||||
return payloads[args[0]], 200, None
|
||||
else:
|
||||
return DEFAULT
|
||||
|
||||
mock_fetch.side_effect = side_effect
|
||||
|
||||
# noinspection PyTypeChecker
|
||||
entities = message_to_objects(
|
||||
ACTIVITYPUB_POST,
|
||||
|
@ -230,7 +245,7 @@ class TestActivitypubEntityMappersReceive:
|
|||
id='https://diaspodon.fr/users/jaywink', receiver_variant=ReceiverVariant.FOLLOWERS,
|
||||
),
|
||||
UserType(
|
||||
id='https://dev.jasonrobinson.me/p/d4574854-a5d7-42be-bfac-f70c16fcaa97/',
|
||||
id='https://fosstodon.org/users/astdenis',
|
||||
receiver_variant=ReceiverVariant.ACTOR,
|
||||
)
|
||||
}
|
||||
|
@ -239,7 +254,7 @@ class TestActivitypubEntityMappersReceive:
|
|||
entities = message_to_objects(ACTIVITYPUB_RETRACTION, "https://friendica.feneas.org/profile/jaywink")
|
||||
assert len(entities) == 1
|
||||
entity = entities[0]
|
||||
assert isinstance(entity, models.Delete)
|
||||
assert isinstance(entity, Retraction)
|
||||
assert entity.actor_id == "https://friendica.feneas.org/profile/jaywink"
|
||||
assert entity.target_id == "https://friendica.feneas.org/objects/76158462-165d-3386-aa23-ba2090614385"
|
||||
assert entity.entity_type == "Object"
|
||||
|
@ -248,7 +263,7 @@ class TestActivitypubEntityMappersReceive:
|
|||
entities = message_to_objects(ACTIVITYPUB_RETRACTION_SHARE, "https://mastodon.social/users/jaywink")
|
||||
assert len(entities) == 1
|
||||
entity = entities[0]
|
||||
assert isinstance(entity, models.Announce)
|
||||
assert isinstance(entity, Retraction)
|
||||
assert entity.actor_id == "https://mastodon.social/users/jaywink"
|
||||
assert entity.target_id == "https://mastodon.social/users/jaywink/statuses/102571932479036987/activity"
|
||||
assert entity.entity_type == "Object"
|
||||
|
|
|
@ -19,7 +19,7 @@ class TestGetBaseAttributes:
|
|||
assert set(attrs) == {
|
||||
"created_at", "location", "provider_display_name", "public", "raw_content",
|
||||
"signature", "base_url", "actor_id", "id", "handle", "guid", "activity", "activity_id",
|
||||
"url", "mxid",
|
||||
"url", "mxid", "times",
|
||||
}
|
||||
entity = Profile()
|
||||
attrs = get_base_attributes(entity).keys()
|
||||
|
@ -27,7 +27,7 @@ class TestGetBaseAttributes:
|
|||
"created_at", "name", "email", "gender", "raw_content", "location", "public",
|
||||
"nsfw", "public_key", "image_urls", "tag_list", "signature", "url", "atom_url",
|
||||
"base_url", "id", "actor_id", "handle", "handle", "guid", "activity", "activity_id", "username",
|
||||
"inboxes", "mxid",
|
||||
"inboxes", "mxid", "times",
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ https://jasonrobinson.me/media/uploads/2019/07/16/daa24d89-cedf-4fc7-bad8-74a902
|
|||
def activitypubprofile(mock_fetch):
|
||||
with freeze_time("2022-09-06"):
|
||||
return models.Person(
|
||||
id="https://example.com/bob/", raw_content="foobar", name="Bob Bobertson", public=True,
|
||||
id="https://example.com/bob", raw_content="foobar", name="Bob Bobertson", public=True,
|
||||
tag_list=["socialfederation", "federation"], image_urls={
|
||||
"large": "urllarge", "medium": "urlmedium", "small": "urlsmall"
|
||||
}, inboxes={
|
||||
|
@ -195,7 +195,7 @@ def activitypubprofile(mock_fetch):
|
|||
def activitypubprofile_diaspora_guid(mock_fetch):
|
||||
with freeze_time("2022-09-06"):
|
||||
return models.Person(
|
||||
id="https://example.com/bob/", raw_content="foobar", name="Bob Bobertson", public=True,
|
||||
id="https://example.com/bob", raw_content="foobar", name="Bob Bobertson", public=True,
|
||||
tag_list=["socialfederation", "federation"], image_urls={
|
||||
"large": "urllarge", "medium": "urlmedium", "small": "urlsmall"
|
||||
}, inboxes={
|
||||
|
@ -222,7 +222,8 @@ def activitypubretraction():
|
|||
def activitypubretraction_announce():
|
||||
with freeze_time("2019-04-27"):
|
||||
obj = Retraction(
|
||||
target_id="http://127.0.0.1:8000/post/123456/activity",
|
||||
id="http://127.0.0.1:8000/post/123456/activity",
|
||||
target_id="http://127.0.0.1:8000/post/123456",
|
||||
activity_id="http://127.0.0.1:8000/post/123456/#delete",
|
||||
actor_id="http://127.0.0.1:8000/profile/123456/",
|
||||
entity_type="Share",
|
||||
|
|
|
@ -128,6 +128,85 @@ ACTIVITYPUB_PROFILE = {
|
|||
}
|
||||
}
|
||||
|
||||
ACTIVITYPUB_REMOTE_PROFILE = {
|
||||
"@context": ["https://www.w3.org/ns/activitystreams",
|
||||
"https://w3id.org/security/v1",
|
||||
{"Curve25519Key": "toot:Curve25519Key",
|
||||
"Device": "toot:Device",
|
||||
"Ed25519Key": "toot:Ed25519Key",
|
||||
"Ed25519Signature": "toot:Ed25519Signature",
|
||||
"EncryptedMessage": "toot:EncryptedMessage",
|
||||
"PropertyValue": "schema:PropertyValue",
|
||||
"alsoKnownAs": {"@id": "as:alsoKnownAs", "@type": "@id"},
|
||||
"cipherText": "toot:cipherText",
|
||||
"claim": {"@id": "toot:claim", "@type": "@id"},
|
||||
"deviceId": "toot:deviceId",
|
||||
"devices": {"@id": "toot:devices", "@type": "@id"},
|
||||
"discoverable": "toot:discoverable",
|
||||
"featured": {"@id": "toot:featured", "@type": "@id"},
|
||||
"featuredTags": {"@id": "toot:featuredTags", "@type": "@id"},
|
||||
"fingerprintKey": {"@id": "toot:fingerprintKey", "@type": "@id"},
|
||||
"focalPoint": {"@container": "@list", "@id": "toot:focalPoint"},
|
||||
"identityKey": {"@id": "toot:identityKey", "@type": "@id"},
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"messageFranking": "toot:messageFranking",
|
||||
"messageType": "toot:messageType",
|
||||
"movedTo": {"@id": "as:movedTo", "@type": "@id"},
|
||||
"publicKeyBase64": "toot:publicKeyBase64",
|
||||
"schema": "http://schema.org#",
|
||||
"suspended": "toot:suspended",
|
||||
"toot": "http://joinmastodon.org/ns#",
|
||||
"value": "schema:value"}],
|
||||
"attachment": [{"name": "OS", "type": "PropertyValue", "value": "Manjaro"},
|
||||
{"name": "Self Hosting",
|
||||
"type": "PropertyValue",
|
||||
"value": "Matrix HS, Nextcloud"}],
|
||||
"devices": "https://fosstodon.org/users/astdenis/collections/devices",
|
||||
"discoverable": True,
|
||||
"endpoints": {"sharedInbox": "https://fosstodon.org/inbox"},
|
||||
"featured": "https://fosstodon.org/users/astdenis/collections/featured",
|
||||
"featuredTags": "https://fosstodon.org/users/astdenis/collections/tags",
|
||||
"followers": "https://fosstodon.org/users/astdenis/followers",
|
||||
"following": "https://fosstodon.org/users/astdenis/following",
|
||||
"icon": {"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "https://cdn.fosstodon.org/accounts/avatars/000/252/976/original/09b7067cde009950.jpg"},
|
||||
"id": "https://fosstodon.org/users/astdenis",
|
||||
"image": {"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "https://cdn.fosstodon.org/accounts/headers/000/252/976/original/555a1ac1819e4e7f.jpg"},
|
||||
"inbox": "https://fosstodon.org/users/astdenis/inbox",
|
||||
"manuallyApprovesFollowers": False,
|
||||
"name": "Alain",
|
||||
"outbox": "https://fosstodon.org/users/astdenis/outbox",
|
||||
"preferredUsername": "astdenis",
|
||||
"publicKey": {"id": "https://fosstodon.org/users/astdenis#main-key",
|
||||
"owner": "https://fosstodon.org/users/astdenis",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\n"
|
||||
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuaoIq/b+aUNqGAJNYF76\n"
|
||||
"WY8tk49Vb1udyb7X+oseBXYtOwCDGfbZMalnFfqur1bAzogkKzuyjCeA3BfVs6R3\n"
|
||||
"Cll897kUveMNHVc24pslhOx5ZzwpNT8e4q97dNaeHWLSLH5H+4JJGbeoD23G5SaY\n"
|
||||
"9ZKt5iP+qRUlO/kSsUPwqsX9i2qSEqzwDiSvyRYhvvx4O588cUaaY9rAliLgtc/P\n"
|
||||
"4EID3v6Edexe2QosUaghwGbb8zZWsYq0O4Umn2QMN4LzmQ0FjP+lq1TFX8FkGDZH\n"
|
||||
"lnP+AMEQMyuac9Yb12t4RwvdsAIk4MXhAKvutMJm/X1GVQIyrsLEmvAO3rgk8dMr\n"
|
||||
"6QIDAQAB\n"
|
||||
"-----END PUBLIC KEY-----\n"},
|
||||
"published": "2020-07-25T00:00:00Z",
|
||||
"summary": "<p>Linux user and sysadmin since 1994, retired from the HPC field "
|
||||
"since 2019.</p><p>Utilisateur et sysadmin Linux depuis 1994, "
|
||||
"retraité du domaine du CHP depuis 2019.</p>",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
"url": "https://fosstodon.org/@astdenis"
|
||||
}
|
||||
|
||||
ACTIVITYPUB_COLLECTION = {
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"id": "https://diaspodon.fr/users/jaywink/followers",
|
||||
"totalItems": 231,
|
||||
"type": "OrderedCollection"
|
||||
}
|
||||
|
||||
ACTIVITYPUB_PROFILE_INVALID = {
|
||||
"@context": [
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
|
@ -313,7 +392,7 @@ ACTIVITYPUB_POST = {
|
|||
'published': '2019-06-29T21:08:45Z',
|
||||
'to': 'https://www.w3.org/ns/activitystreams#Public',
|
||||
'cc': ['https://diaspodon.fr/users/jaywink/followers',
|
||||
'https://dev.jasonrobinson.me/p/d4574854-a5d7-42be-bfac-f70c16fcaa97/'],
|
||||
'https://fosstodon.org/users/astdenis'],
|
||||
'object': {'id': 'https://diaspodon.fr/users/jaywink/statuses/102356911717767237',
|
||||
'type': 'Note',
|
||||
'summary': None,
|
||||
|
@ -323,7 +402,7 @@ ACTIVITYPUB_POST = {
|
|||
'attributedTo': 'https://diaspodon.fr/users/jaywink',
|
||||
'to': 'https://www.w3.org/ns/activitystreams#Public',
|
||||
'cc': ['https://diaspodon.fr/users/jaywink/followers',
|
||||
'https://dev.jasonrobinson.me/p/d4574854-a5d7-42be-bfac-f70c16fcaa97/'],
|
||||
'https://fosstodon.org/users/astdenis'],
|
||||
'sensitive': False,
|
||||
'atomUri': 'https://diaspodon.fr/users/jaywink/statuses/102356911717767237',
|
||||
'inReplyToAtomUri': None,
|
||||
|
|
|
@ -50,35 +50,39 @@ class TestRetrieveAndParseDocument:
|
|||
"https://example.com/foobar", extra_headers={'accept': 'application/activity+json'}, auth=auth,
|
||||
)
|
||||
|
||||
@patch("federation.entities.activitypub.models.extract_receivers", return_value=[])
|
||||
@patch("federation.utils.activitypub.fetch_document", autospec=True, return_value=(
|
||||
json.dumps(ACTIVITYPUB_FOLLOW), None, None),
|
||||
)
|
||||
@patch.object(Follow, "post_receive")
|
||||
def test_returns_entity_for_valid_document__follow(self, mock_post_receive, mock_fetch):
|
||||
def test_returns_entity_for_valid_document__follow(self, mock_post_receive, mock_fetch, mock_recv):
|
||||
entity = retrieve_and_parse_document("https://example.com/foobar")
|
||||
assert isinstance(entity, Follow)
|
||||
|
||||
@patch("federation.entities.activitypub.models.extract_receivers", return_value=[])
|
||||
@patch("federation.utils.activitypub.fetch_document", autospec=True, return_value=(
|
||||
json.dumps(ACTIVITYPUB_POST_OBJECT), None, None),
|
||||
)
|
||||
def test_returns_entity_for_valid_document__post__without_activity(self, mock_fetch):
|
||||
def test_returns_entity_for_valid_document__post__without_activity(self, mock_fetch, mock_recv):
|
||||
entity = retrieve_and_parse_document("https://example.com/foobar")
|
||||
assert isinstance(entity, Note)
|
||||
|
||||
@patch("federation.entities.activitypub.models.extract_receivers", return_value=[])
|
||||
@patch("federation.utils.activitypub.fetch_document", autospec=True, return_value=(
|
||||
json.dumps(ACTIVITYPUB_POST_OBJECT_IMAGES), None, None),
|
||||
)
|
||||
def test_returns_entity_for_valid_document__post__without_activity__with_images(self, mock_fetch):
|
||||
def test_returns_entity_for_valid_document__post__without_activity__with_images(self, mock_fetch, mock_recv):
|
||||
entity = retrieve_and_parse_document("https://example.com/foobar")
|
||||
assert isinstance(entity, Note)
|
||||
assert len(entity._children) == 1
|
||||
assert entity._children[0].url == "https://files.mastodon.social/media_attachments/files/017/792/237/original" \
|
||||
"/foobar.jpg"
|
||||
|
||||
@patch("federation.entities.activitypub.models.extract_receivers", return_value=[])
|
||||
@patch("federation.utils.activitypub.fetch_document", autospec=True, return_value=(
|
||||
json.dumps(ACTIVITYPUB_POST), None, None),
|
||||
)
|
||||
def test_returns_entity_for_valid_document__post__wrapped_in_activity(self, mock_fetch):
|
||||
def test_returns_entity_for_valid_document__post__wrapped_in_activity(self, mock_fetch, mock_recv):
|
||||
entity = retrieve_and_parse_document("https://example.com/foobar")
|
||||
assert isinstance(entity, Note)
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue