replace User.readable_id computed property with handle

pull/649/head
Ryan Barrett 2023-09-25 15:08:14 -07:00
rodzic c27404d681
commit a9fcc167f6
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
12 zmienionych plików z 40 dodań i 32 usunięć

Wyświetl plik

@ -8,6 +8,7 @@ from urllib.parse import quote_plus, urljoin
from flask import abort, g, request
from google.cloud import ndb
from google.cloud.ndb.query import OR
from granary import as1, as2
from httpsig import HeaderVerifier
from httpsig.requests_auth import HTTPSignatureAuth
@ -85,6 +86,7 @@ class ActivityPub(User, Protocol):
return self.ap_actor()
@ndb.ComputedProperty
def handle(self):
"""Returns this user's ActivityPub address, eg ``@user@foo.com``."""
if self.obj and self.obj.as1:
@ -94,7 +96,8 @@ class ActivityPub(User, Protocol):
return as2.address(self.key.id())
ap_address = handle
def ap_address(self):
return self.handle
def ap_actor(self, rest=None):
"""Returns this user's actor id URL, eg ``https://foo.com/@user``."""
@ -136,7 +139,9 @@ class ActivityPub(User, Protocol):
if not handle.startswith('@'):
handle = '@' + handle
user = ActivityPub.query(ActivityPub.readable_id == handle).get()
user = ActivityPub.query(OR(ActivityPub.handle == handle,
ActivityPub.readable_id == handle),
).get()
if user:
return user.key.id()

Wyświetl plik

@ -66,6 +66,7 @@ class ATProto(User, Protocol):
assert not self.atproto_did, \
f"{self.key} shouldn't have atproto_did {self.atproto_did}"
@ndb.ComputedProperty
def handle(self):
"""Returns handle if the DID document includes one, otherwise None."""
did_obj = ATProto.load(self.key.id(), remote=False)
@ -94,7 +95,7 @@ class ATProto(User, Protocol):
def handle_to_id(cls, handle):
assert cls.owns_handle(handle) is not False
user = ATProto.query(ATProto.readable_id == handle).get()
user = ATProto.query(ATProto.handle == handle).get()
if user:
return user.key.id()

Wyświetl plik

@ -105,7 +105,7 @@ How to add a new protocol
and
`User <https://github.com/snarfed/bridgy-fed/blob/main/models.py>`__.
Implement the ``send``, ``fetch``, ``serve``, and ``target_for``
methods from ``Protocol`` and ``readable_id``, ``web_url``,
methods from ``Protocol`` and ``handle``, ``web_url``,
``ap_address``, and ``ap_actor`` from ``User`` .
4. TODO: add a new usage section to the docs for the new protocol.
5. TODO: does the new protocol need any new UI or signup functionality?

Wyświetl plik

@ -286,20 +286,18 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
return self.obj.as_as2() if self.obj else {}
@ndb.ComputedProperty
def readable_id(self):
"""This user's human-readable unique id, eg ``@me@snarfed.org``.
TODO: rename to handle! And keep readable_id in queries for backcompat
"""
return self.handle()
def handle(self):
"""Returns this user's handle, eg ``@me@snarfed.org``.
"""This user's unique, human-chosen handle, eg ``@me@snarfed.org``.
To be implemented by subclasses.
"""
raise NotImplementedError()
@ndb.ComputedProperty
def readable_id(self):
"""DEPRECATED: replaced by handle. Kept for backward compatibility."""
return None
def handle_as(self, to_proto):
"""Returns this user's handle in a different protocol.
@ -312,7 +310,7 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
if isinstance(to_proto, str):
to_proto = PROTOCOLS[to_proto]
return ids.convert_handle(handle=self.handle(), from_proto=self.__class__,
return ids.convert_handle(handle=self.handle, from_proto=self.__class__,
to_proto=to_proto)
def id_as(self, to_proto):
@ -332,7 +330,7 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
def handle_or_id(self):
"""Returns handle if we know it, otherwise id."""
return self.handle() or self.key.id()
return self.handle or self.key.id()
def href(self):
return f'data:application/magic-public-key,RSA.{self.mod}.{self.public_exponent}'
@ -543,7 +541,7 @@ class Object(StringIdModel):
elif self.bsky:
owner, _, _ = arroba.util.parse_at_uri(self.key.id())
ATProto = PROTOCOLS['atproto']
handle = ATProto(id=owner).handle()
handle = ATProto(id=owner).handle
obj = bluesky.to_as1(self.bsky, repo_did=owner, repo_handle=handle,
pds=ATProto.target_for(self))

Wyświetl plik

@ -46,11 +46,13 @@ def load_user(protocol, id):
if protocol != 'web':
if not g.user:
g.user = cls.query(cls.readable_id == id).get()
g.user = cls.query(OR(cls.handle == id,
cls.readable_id == id),
).get()
if g.user and g.user.use_instead:
g.user = g.user.use_instead.get()
if g.user and id not in (g.user.key.id(), g.user.handle()):
if g.user and id not in (g.user.key.id(), g.user.handle):
error('', status=302, location=g.user.user_page_path())
elif g.user and id != g.user.key.id(): # use_instead redirect

Wyświetl plik

@ -1926,15 +1926,15 @@ class ActivityPubUtilsTest(TestCase):
'preferredUsername': 'me',
}))
self.assertEqual('@me@mas.to', user.ap_address())
self.assertEqual('@me@mas.to', user.readable_id)
self.assertEqual('@me@mas.to', user.handle)
user.obj.as2 = ACTOR
self.assertEqual('@swentel@mas.to', user.ap_address())
self.assertEqual('@swentel@mas.to', user.readable_id)
self.assertEqual('@swentel@mas.to', user.handle)
user = ActivityPub(id='https://mas.to/users/alice')
self.assertEqual('@alice@mas.to', user.ap_address())
self.assertEqual('@alice@mas.to', user.readable_id)
self.assertEqual('@alice@mas.to', user.handle)
def test_ap_actor(self):
user = self.make_user('http://foo/actor', cls=ActivityPub)
@ -1957,13 +1957,13 @@ class ActivityPubUtilsTest(TestCase):
user.obj.as2['url'] = ['http://my/url']
self.assertEqual('http://my/url', user.web_url())
def test_readable_id(self):
def test_handle(self):
user = self.make_user('http://foo', cls=ActivityPub)
self.assertIsNone(user.readable_id)
self.assertIsNone(user.handle)
self.assertEqual('http://foo', user.handle_or_id())
user.obj = Object(id='a', as2=ACTOR)
self.assertEqual('@swentel@mas.to', user.readable_id)
self.assertEqual('@swentel@mas.to', user.handle)
self.assertEqual('@swentel@mas.to', user.handle_or_id())
@skip

Wyświetl plik

@ -228,11 +228,11 @@ class ATProtoTest(TestCase):
@patch('requests.get', return_value=requests_response('', status=404))
def test_handle_or_id(self, mock_get):
user = self.make_user('did:plc:foo', cls=ATProto)
self.assertIsNone(user.handle())
self.assertIsNone(user.handle)
self.assertEqual('did:plc:foo', user.handle_or_id())
self.store_object(id='did:plc:foo', raw=DID_DOC)
self.assertEqual('han.dull', user.handle())
self.assertEqual('han.dull', user.handle)
self.assertEqual('han.dull', user.handle_or_id())
def test_ap_address(self):

Wyświetl plik

@ -113,8 +113,8 @@ class UserTest(TestCase):
g.user.obj = Object(id='a', as2={'name': 'alice'})
self.assertEqual('alice', g.user.name())
def test_readable_id(self):
self.assertEqual('y.z', g.user.readable_id)
def test_handle(self):
self.assertEqual('y.z', g.user.handle)
def test_as2(self):
self.assertEqual({}, g.user.as2())

Wyświetl plik

@ -40,7 +40,7 @@ class PagesTest(TestCase):
got = self.client.get('/fa/foo.com')
self.assert_equals(200, got.status_code)
def test_user_readable_id_activitypub_address(self):
def test_user_page_handle(self):
user = self.make_user('http://foo', cls=ActivityPub,
obj_as2=ACTOR_WITH_PREFERRED_USERNAME)
self.assertEqual('@me@plus.google.com', user.ap_address())

Wyświetl plik

@ -1892,7 +1892,7 @@ class WebUtilTest(TestCase):
self.assertIsNone(Web.key_for(bad))
def test_handle(self, *_):
self.assertEqual('user.com', g.user.handle())
self.assertEqual('user.com', g.user.handle)
def test_owns_id(self, *_):
self.assertIsNone(Web.owns_id('http://foo.com'))

Wyświetl plik

@ -70,6 +70,7 @@ class Fake(User, protocol.Protocol):
# in-order list of ids
fetched = []
@ndb.ComputedProperty
def handle(self):
return self.key.id().replace('fake:', 'fake:handle:')
@ -435,8 +436,8 @@ class TestCase(unittest.TestCase, testutil.Asserts):
self.assert_equals(obj_as2, got.as2())
# generated, computed, etc
ignore = ['created', 'mod', 'obj_key', 'private_exponent',
'public_exponent', 'readable_id', 'updated']
ignore = ['created', 'mod', 'handle', 'obj_key', 'private_exponent',
'public_exponent', 'updated']
for prop in ignore:
assert prop not in props

3
web.py
Wyświetl plik

@ -81,7 +81,7 @@ class Web(User, Protocol):
"""Validate domain id, don't allow upper case or invalid characters."""
super()._pre_put_hook()
id = self.key.id()
assert is_valid_domain(id)
assert is_valid_domain(id), id
assert id.lower() == id, f'upper case is not allowed in Web key id: {id}'
@classmethod
@ -93,6 +93,7 @@ class Web(User, Protocol):
"""
return super().get_or_create(id.lower().strip('.'), **kwargs)
@ndb.ComputedProperty
def handle(self):
"""Returns this user's chosen username or domain, eg ``user.com``."""
# prettify if domain, noop if username