2023-09-21 20:37:17 +00:00
|
|
|
"""Unit tests for ids.py."""
|
2023-12-24 18:04:01 +00:00
|
|
|
from unittest.mock import patch
|
|
|
|
|
2023-09-21 20:37:17 +00:00
|
|
|
from activitypub import ActivityPub
|
|
|
|
from atproto import ATProto
|
2023-11-03 18:37:36 +00:00
|
|
|
from flask_app import app
|
2024-05-29 19:08:10 +00:00
|
|
|
import ids
|
2023-10-26 23:20:30 +00:00
|
|
|
from ids import translate_handle, translate_object_id, translate_user_id
|
2023-09-21 20:37:17 +00:00
|
|
|
from models import Target
|
|
|
|
from .testutil import Fake, TestCase
|
2023-11-15 22:23:08 +00:00
|
|
|
from web import Web
|
2023-09-21 20:37:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
class IdsTest(TestCase):
|
2024-04-25 21:29:48 +00:00
|
|
|
def setUp(self):
|
|
|
|
super().setUp()
|
|
|
|
Web(id='bsky.brid.gy', ap_subdomain='bsky', has_redirects=True).put()
|
|
|
|
Web(id='fed.brid.gy', ap_subdomain='fed', has_redirects=True).put()
|
|
|
|
|
2023-10-26 20:49:42 +00:00
|
|
|
def test_translate_user_id(self):
|
2023-11-16 03:08:06 +00:00
|
|
|
Web(id='user.com',
|
2023-09-21 20:37:17 +00:00
|
|
|
copies=[Target(uri='did:plc:123', protocol='atproto')]).put()
|
2023-11-16 03:08:06 +00:00
|
|
|
ActivityPub(id='https://inst/user',
|
2023-09-21 20:37:17 +00:00
|
|
|
copies=[Target(uri='did:plc:456', protocol='atproto')]).put()
|
2023-11-16 03:08:06 +00:00
|
|
|
Fake(id='fake:user',
|
2023-09-21 20:37:17 +00:00
|
|
|
copies=[Target(uri='did:plc:789', protocol='atproto')]).put()
|
|
|
|
|
2024-04-09 17:04:16 +00:00
|
|
|
# DID doc and ATProto, used to resolve handle in bsky.app URL
|
2024-04-09 16:48:16 +00:00
|
|
|
did = self.store_object(id='did:plc:123', raw={
|
|
|
|
'id': 'did:plc:123',
|
|
|
|
'alsoKnownAs': ['at://user.com'],
|
|
|
|
})
|
|
|
|
ATProto(id='did:plc:123', obj_key=did.key).put()
|
|
|
|
|
2023-09-21 20:37:17 +00:00
|
|
|
for from_, id, to, expected in [
|
2023-09-25 13:42:31 +00:00
|
|
|
(ActivityPub, 'https://inst/user', ActivityPub, 'https://inst/user'),
|
|
|
|
(ActivityPub, 'https://inst/user', ATProto, 'did:plc:456'),
|
2023-11-02 20:08:12 +00:00
|
|
|
(ActivityPub, 'https://inst/user', Fake, 'fake:u:https://inst/user'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(ActivityPub, 'https://inst/user', Web, 'https://inst/user'),
|
2024-04-09 16:48:16 +00:00
|
|
|
(ActivityPub, 'https://bsky.app/profile/user.com', ATProto, 'did:plc:123'),
|
|
|
|
(ActivityPub, 'https://bsky.app/profile/did:plc:123',
|
|
|
|
ATProto, 'did:plc:123'),
|
2024-04-25 21:29:48 +00:00
|
|
|
|
2023-11-07 04:17:23 +00:00
|
|
|
(ATProto, 'did:plc:456', ATProto, 'did:plc:456'),
|
|
|
|
# copies
|
2023-09-21 20:37:17 +00:00
|
|
|
(ATProto, 'did:plc:123', Web, 'user.com'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(ATProto, 'did:plc:456', ActivityPub, 'https://inst/user'),
|
2023-09-21 20:37:17 +00:00
|
|
|
(ATProto, 'did:plc:789', Fake, 'fake:user'),
|
2024-04-25 21:29:48 +00:00
|
|
|
|
2023-11-07 04:17:23 +00:00
|
|
|
# no copies
|
2024-04-16 18:52:50 +00:00
|
|
|
(ATProto, 'did:plc:x', Web, 'https://bsky.brid.gy/web/did:plc:x'),
|
|
|
|
(ATProto, 'did:plc:x', ActivityPub, 'https://bsky.brid.gy/ap/did:plc:x'),
|
2023-11-07 04:17:23 +00:00
|
|
|
(ATProto, 'did:plc:x', Fake, 'fake:u:did:plc:x'),
|
2024-04-09 16:48:16 +00:00
|
|
|
(ATProto, 'https://bsky.app/profile/user.com', ATProto, 'did:plc:123'),
|
|
|
|
(ATProto, 'https://bsky.app/profile/did:plc:123', ATProto, 'did:plc:123'),
|
2024-04-25 21:29:48 +00:00
|
|
|
|
2023-10-24 22:46:03 +00:00
|
|
|
(Fake, 'fake:user', ActivityPub, 'https://fa.brid.gy/ap/fake:user'),
|
2023-09-21 20:37:17 +00:00
|
|
|
(Fake, 'fake:user', ATProto, 'did:plc:789'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(Fake, 'fake:user', Fake, 'fake:user'),
|
2023-11-07 04:17:23 +00:00
|
|
|
(Fake, 'fake:user', Web, 'https://fa.brid.gy/web/fake:user'),
|
2024-04-25 21:29:48 +00:00
|
|
|
|
2023-11-03 18:37:36 +00:00
|
|
|
(Web, 'user.com', ActivityPub, 'http://localhost/user.com'),
|
|
|
|
(Web, 'https://user.com/', ActivityPub, 'http://localhost/user.com'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(Web, 'user.com', ATProto, 'did:plc:123'),
|
2023-11-03 18:00:34 +00:00
|
|
|
(Web, 'https://user.com', ATProto, 'did:plc:123'),
|
2024-04-09 16:48:16 +00:00
|
|
|
(Web, 'https://bsky.app/profile/user.com', ATProto, 'did:plc:123'),
|
|
|
|
(Web, 'https://bsky.app/profile/did:plc:123', ATProto, 'did:plc:123'),
|
2023-11-02 20:08:12 +00:00
|
|
|
(Web, 'user.com', Fake, 'fake:u:user.com'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(Web, 'user.com', Web, 'user.com'),
|
2023-11-03 18:00:34 +00:00
|
|
|
(Web, 'https://user.com/', Web, 'user.com'),
|
2024-04-25 21:29:48 +00:00
|
|
|
|
|
|
|
# instance actor / protocol bot users
|
|
|
|
(Web, 'fed.brid.gy', ActivityPub, 'https://fed.brid.gy/fed.brid.gy'),
|
|
|
|
(Web, 'bsky.brid.gy', ActivityPub, 'https://bsky.brid.gy/bsky.brid.gy'),
|
2023-09-21 20:37:17 +00:00
|
|
|
]:
|
2024-05-29 19:08:10 +00:00
|
|
|
with self.subTest(id=id, from_=from_.LABEL, to=to.LABEL):
|
2023-10-26 20:49:42 +00:00
|
|
|
self.assertEqual(expected, translate_user_id(
|
2024-04-21 04:03:06 +00:00
|
|
|
id=id, from_=from_, to=to))
|
2023-09-21 20:37:17 +00:00
|
|
|
|
2023-11-02 20:08:12 +00:00
|
|
|
def test_translate_user_id_no_copy_did_stored(self):
|
2023-09-22 18:41:30 +00:00
|
|
|
for proto, id in [
|
|
|
|
(Web, 'user.com'),
|
|
|
|
(ActivityPub, 'https://instance/user'),
|
|
|
|
(Fake, 'fake:user'),
|
|
|
|
]:
|
2024-05-29 19:08:10 +00:00
|
|
|
with self.subTest(proto=proto.LABEL, id=id):
|
2024-04-21 04:03:06 +00:00
|
|
|
self.assertIsNone(translate_user_id(id=id, from_=proto, to=ATProto))
|
2023-11-03 21:53:19 +00:00
|
|
|
|
|
|
|
def test_translate_user_id_use_instead(self):
|
|
|
|
did = Target(uri='did:plc:123', protocol='atproto')
|
|
|
|
user = self.make_user('user.com', cls=Web, copies=[did])
|
|
|
|
self.make_user('www.user.com', cls=Web, use_instead=user.key)
|
|
|
|
|
|
|
|
for proto, expected in [
|
|
|
|
(ATProto, 'did:plc:123'),
|
|
|
|
(ActivityPub, 'http://localhost/user.com'),
|
|
|
|
(Fake, 'fake:u:user.com'),
|
|
|
|
]:
|
|
|
|
with self.subTest(proto=proto.LABEL):
|
|
|
|
self.assertEqual(expected, translate_user_id(
|
2024-04-21 04:03:06 +00:00
|
|
|
id='www.user.com', from_=Web, to=proto))
|
2023-11-03 21:53:19 +00:00
|
|
|
self.assertEqual(expected, translate_user_id(
|
2024-04-21 04:03:06 +00:00
|
|
|
id='https://www.user.com/', from_=Web, to=proto))
|
2023-09-22 18:41:30 +00:00
|
|
|
|
2023-12-24 18:04:01 +00:00
|
|
|
def test_translate_user_id_web_ap_subdomain_fed(self):
|
2024-04-22 22:15:27 +00:00
|
|
|
self.make_user('on-fed.com', cls=Web, ap_subdomain='fed')
|
|
|
|
self.make_user('on-bsky.com', cls=Web, ap_subdomain='bsky')
|
|
|
|
|
2023-12-24 18:04:01 +00:00
|
|
|
for base_url in ['https://web.brid.gy/', 'https://fed.brid.gy/']:
|
|
|
|
with app.test_request_context('/', base_url=base_url):
|
|
|
|
self.assertEqual('https://web.brid.gy/on-web.com', translate_user_id(
|
2024-04-21 04:03:06 +00:00
|
|
|
id='on-web.com', from_=Web, to=ActivityPub))
|
2023-12-24 18:04:01 +00:00
|
|
|
self.assertEqual('https://fed.brid.gy/on-fed.com', translate_user_id(
|
2024-04-21 04:03:06 +00:00
|
|
|
id='on-fed.com', from_=Web, to=ActivityPub))
|
2024-04-22 18:12:03 +00:00
|
|
|
self.assertEqual('https://bsky.brid.gy/on-bsky.com', translate_user_id(
|
|
|
|
id='on-bsky.com', from_=Web, to=ActivityPub))
|
2023-12-24 18:04:01 +00:00
|
|
|
|
2024-05-29 19:08:10 +00:00
|
|
|
def test_normalize_user_id(self):
|
|
|
|
for proto, id, expected in [
|
|
|
|
(ActivityPub, 'https://inst/user', 'https://inst/user'),
|
|
|
|
(ATProto, 'did:plc:456', 'did:plc:456'),
|
|
|
|
(ATProto, 'https://bsky.app/profile/did:plc:123', 'did:plc:123'),
|
|
|
|
(Fake, 'fake:user', 'fake:user'),
|
|
|
|
(Web, 'user.com', 'user.com'),
|
|
|
|
(Web, 'https://user.com/', 'user.com'),
|
|
|
|
(Web, 'https://www.user.com/', 'user.com'),
|
|
|
|
(Web, 'm.user.com', 'user.com'),
|
|
|
|
]:
|
|
|
|
with self.subTest(id=id, proto=proto):
|
|
|
|
self.assertEqual(expected, ids.normalize_user_id(id=id, proto=proto))
|
|
|
|
|
2024-05-29 23:18:15 +00:00
|
|
|
def test_profile_id(self):
|
|
|
|
for proto, id, expected in [
|
|
|
|
(ActivityPub, 'https://inst/user', 'https://inst/user'),
|
|
|
|
(ATProto, 'did:plc:123', 'at://did:plc:123/app.bsky.actor.profile/self'),
|
|
|
|
(Fake, 'fake:user', 'fake:profile:user'),
|
|
|
|
(Web, 'user.com', 'https://user.com/'),
|
|
|
|
]:
|
|
|
|
with self.subTest(id=id, proto=proto):
|
|
|
|
self.assertEqual(expected, ids.profile_id(id=id, proto=proto))
|
|
|
|
|
2023-10-26 20:49:42 +00:00
|
|
|
def test_translate_handle(self):
|
2023-09-22 18:41:30 +00:00
|
|
|
for from_, handle, to, expected in [
|
|
|
|
# basic
|
|
|
|
(Web, 'user.com', ActivityPub, '@user.com@web.brid.gy'),
|
|
|
|
(Web, 'user.com', ATProto, 'user.com.web.brid.gy'),
|
2023-09-22 21:53:36 +00:00
|
|
|
(Web, 'user.com', Fake, 'fake:handle:user.com'),
|
2024-05-02 22:41:41 +00:00
|
|
|
(Web, 'u_se-r.com', Fake, 'fake:handle:u_se-r.com'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(Web, 'user.com', Web, 'user.com'),
|
2023-09-22 18:41:30 +00:00
|
|
|
|
2023-09-25 13:42:31 +00:00
|
|
|
(ActivityPub, '@user@instance', ActivityPub, '@user@instance'),
|
2023-09-22 18:41:30 +00:00
|
|
|
(ActivityPub, '@user@instance', ATProto, 'user.instance.ap.brid.gy'),
|
2024-05-02 22:41:41 +00:00
|
|
|
(ActivityPub, '@u_se~r@instance', ATProto, 'u-se-r.instance.ap.brid.gy'),
|
2023-09-22 21:53:36 +00:00
|
|
|
(ActivityPub, '@user@instance', Fake, 'fake:handle:@user@instance'),
|
2023-11-15 22:23:08 +00:00
|
|
|
(ActivityPub, '@user@instance', Web, 'https://instance/@user'),
|
2023-09-22 18:41:30 +00:00
|
|
|
|
2024-04-16 18:52:50 +00:00
|
|
|
(ATProto, 'user.com', ActivityPub, '@user.com@bsky.brid.gy'),
|
2024-05-02 22:41:41 +00:00
|
|
|
(ATProto, 'u-se-r.com', ActivityPub, '@u-se-r.com@bsky.brid.gy'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(ATProto, 'user.com', ATProto, 'user.com'),
|
2023-09-22 21:53:36 +00:00
|
|
|
(ATProto, 'user.com', Fake, 'fake:handle:user.com'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(ATProto, 'user.com', Web, 'user.com'),
|
2023-09-22 18:41:30 +00:00
|
|
|
|
2023-09-22 21:53:36 +00:00
|
|
|
(Fake, 'fake:handle:user', ActivityPub, '@fake:handle:user@fa.brid.gy'),
|
2024-05-03 21:51:26 +00:00
|
|
|
(Fake, 'fake:handle:user', ATProto, 'fake-handle-user.fa.brid.gy'),
|
2023-09-25 13:42:31 +00:00
|
|
|
(Fake, 'fake:handle:user', Fake, 'fake:handle:user'),
|
|
|
|
(Fake, 'fake:handle:user', Web, 'fake:handle:user'),
|
2024-04-23 22:01:29 +00:00
|
|
|
|
|
|
|
# instance actor, protocol bot users
|
|
|
|
(Web, 'fed.brid.gy', ActivityPub, '@fed.brid.gy@fed.brid.gy'),
|
|
|
|
(Web, 'bsky.brid.gy', ActivityPub, '@bsky.brid.gy@bsky.brid.gy'),
|
|
|
|
(Web, 'ap.brid.gy', ATProto, 'ap.brid.gy'),
|
2023-09-22 18:41:30 +00:00
|
|
|
]:
|
|
|
|
with self.subTest(from_=from_.LABEL, to=to.LABEL):
|
2023-10-26 20:49:42 +00:00
|
|
|
self.assertEqual(expected, translate_handle(
|
2024-04-21 04:03:06 +00:00
|
|
|
handle=handle, from_=from_, to=to, enhanced=False))
|
2023-11-30 00:31:33 +00:00
|
|
|
|
|
|
|
def test_translate_handle_enhanced(self):
|
|
|
|
for from_, handle, to, expected in [
|
|
|
|
(Web, 'user.com', ActivityPub, '@user.com@user.com'),
|
|
|
|
(Web, 'user.com', Fake, 'fake:handle:user.com'),
|
|
|
|
(ActivityPub, '@user@instance', Web, 'https://instance/@user'),
|
|
|
|
(ActivityPub, '@user@user', Web, 'https://user'),
|
|
|
|
(ActivityPub, '@user@instance', Fake, 'fake:handle:@user@instance'),
|
|
|
|
(ATProto, 'user.com', ActivityPub, '@user.com@user.com'),
|
2024-04-22 20:24:24 +00:00
|
|
|
|
|
|
|
# instance actor, protocol bot user
|
|
|
|
(Web, 'fed.brid.gy', ActivityPub, '@fed.brid.gy@fed.brid.gy'),
|
|
|
|
(Web, 'bsky.brid.gy', ActivityPub, '@bsky.brid.gy@bsky.brid.gy'),
|
2023-11-30 00:31:33 +00:00
|
|
|
]:
|
|
|
|
with self.subTest(from_=from_.LABEL, to=to.LABEL):
|
|
|
|
self.assertEqual(expected, translate_handle(
|
2024-04-21 04:03:06 +00:00
|
|
|
handle=handle, from_=from_, to=to, enhanced=True))
|
2023-10-26 23:20:30 +00:00
|
|
|
|
|
|
|
def test_translate_object_id(self):
|
2024-02-08 22:40:59 +00:00
|
|
|
self.store_object(id='http://po.st',
|
2023-10-26 23:20:30 +00:00
|
|
|
copies=[Target(uri='at://did/web/post', protocol='atproto')])
|
|
|
|
self.store_object(id='https://inst/post',
|
|
|
|
copies=[Target(uri='at://did/ap/post', protocol='atproto')])
|
|
|
|
self.store_object(id='fake:post',
|
|
|
|
copies=[Target(uri='at://did/fa/post', protocol='atproto')])
|
|
|
|
|
2024-04-09 17:04:16 +00:00
|
|
|
# DID doc and ATProto, used to resolve handle in bsky.app URL
|
|
|
|
did = self.store_object(id='did:plc:123', raw={
|
|
|
|
'id': 'did:plc:123',
|
|
|
|
'alsoKnownAs': ['at://user.com'],
|
|
|
|
})
|
|
|
|
ATProto(id='did:plc:123', obj_key=did.key).put()
|
|
|
|
|
2023-10-26 23:20:30 +00:00
|
|
|
for from_, id, to, expected in [
|
|
|
|
(ActivityPub, 'https://inst/post', ActivityPub, 'https://inst/post'),
|
|
|
|
(ActivityPub, 'https://inst/post', ATProto, 'at://did/ap/post'),
|
2023-11-02 20:08:12 +00:00
|
|
|
(ActivityPub, 'https://inst/post', Fake, 'fake:o:ap:https://inst/post'),
|
2023-10-26 23:20:30 +00:00
|
|
|
(ActivityPub, 'https://inst/post',
|
2023-11-07 04:17:23 +00:00
|
|
|
Web, 'https://ap.brid.gy/convert/web/https://inst/post'),
|
|
|
|
(ATProto, 'at://did/atp/post', ATProto, 'at://did/atp/post'),
|
|
|
|
# copies
|
2024-02-08 22:40:59 +00:00
|
|
|
(ATProto, 'at://did/web/post', Web, 'http://po.st'),
|
2023-10-26 23:20:30 +00:00
|
|
|
(ATProto, 'at://did/ap/post', ActivityPub, 'https://inst/post'),
|
|
|
|
(ATProto, 'at://did/fa/post', Fake, 'fake:post'),
|
2023-11-07 04:17:23 +00:00
|
|
|
# no copies
|
2024-04-16 18:52:50 +00:00
|
|
|
(ATProto, 'did:plc:x', Web, 'https://bsky.brid.gy/convert/web/did:plc:x'),
|
|
|
|
(ATProto, 'did:plc:x', ActivityPub, 'https://bsky.brid.gy/convert/ap/did:plc:x'),
|
|
|
|
(ATProto, 'did:plc:x', Fake, 'fake:o:bsky:did:plc:x'),
|
2024-04-09 17:04:16 +00:00
|
|
|
(ATProto, 'https://bsky.app/profile/user.com/post/456',
|
|
|
|
ATProto, 'at://did:plc:123/app.bsky.feed.post/456'),
|
|
|
|
(ATProto, 'https://bsky.app/profile/did:plc:123/post/456',
|
|
|
|
ATProto, 'at://did:plc:123/app.bsky.feed.post/456'),
|
2023-10-26 23:20:30 +00:00
|
|
|
(Fake, 'fake:post',
|
|
|
|
ActivityPub, 'https://fa.brid.gy/convert/ap/fake:post'),
|
|
|
|
(Fake, 'fake:post', ATProto, 'at://did/fa/post'),
|
|
|
|
(Fake, 'fake:post', Fake, 'fake:post'),
|
|
|
|
(Fake, 'fake:post', Web, 'https://fa.brid.gy/convert/web/fake:post'),
|
2024-02-08 22:40:59 +00:00
|
|
|
(Web, 'http://po.st', ActivityPub, 'http://localhost/r/http://po.st'),
|
|
|
|
(Web, 'http://po.st', ATProto, 'at://did/web/post'),
|
|
|
|
(Web, 'http://po.st', Fake, 'fake:o:web:http://po.st'),
|
|
|
|
(Web, 'http://po.st', Web, 'http://po.st'),
|
2023-10-26 23:20:30 +00:00
|
|
|
]:
|
|
|
|
with self.subTest(from_=from_.LABEL, to=to.LABEL):
|
|
|
|
self.assertEqual(expected, translate_object_id(
|
2024-04-21 04:03:06 +00:00
|
|
|
id=id, from_=from_, to=to))
|
2023-11-03 18:37:36 +00:00
|
|
|
|
2023-12-24 18:26:12 +00:00
|
|
|
def test_translate_object_id_web_ap_subdomain_fed(self):
|
2024-04-22 22:15:27 +00:00
|
|
|
self.make_user('on-fed.com', cls=Web, ap_subdomain='fed')
|
|
|
|
|
2023-12-24 18:20:04 +00:00
|
|
|
for base_url in ['https://web.brid.gy/', 'https://fed.brid.gy/']:
|
|
|
|
with app.test_request_context('/', base_url=base_url):
|
2024-04-21 04:03:06 +00:00
|
|
|
got = translate_object_id(id='http://on-fed.com/post', from_=Web,
|
|
|
|
to=ActivityPub)
|
2023-12-24 18:20:04 +00:00
|
|
|
self.assertEqual('https://fed.brid.gy/r/http://on-fed.com/post', got)
|
|
|
|
|
2024-04-21 04:03:06 +00:00
|
|
|
got = translate_object_id(id='http://on-web.com/post', from_=Web,
|
|
|
|
to=ActivityPub)
|
2023-12-24 18:20:04 +00:00
|
|
|
self.assertEqual('https://web.brid.gy/r/http://on-web.com/post', got)
|