kopia lustrzana https://github.com/snarfed/bridgy-fed
User.ap_address() => handle_as(ActivityPub)
rodzic
a5f9daa46f
commit
520b2fd3b0
|
@ -98,9 +98,6 @@ class ActivityPub(User, Protocol):
|
||||||
|
|
||||||
return as2.address(self.key.id())
|
return as2.address(self.key.id())
|
||||||
|
|
||||||
def ap_address(self):
|
|
||||||
return self.handle
|
|
||||||
|
|
||||||
def ap_actor(self, rest=None):
|
def ap_actor(self, rest=None):
|
||||||
"""Returns this user's actor id URL, eg ``https://foo.com/@user``."""
|
"""Returns this user's actor id URL, eg ``https://foo.com/@user``."""
|
||||||
url = self.key.id()
|
url = self.key.id()
|
||||||
|
|
|
@ -46,7 +46,7 @@ def remote_follow():
|
||||||
if link.get('rel') == webfinger.SUBSCRIBE_LINK_REL:
|
if link.get('rel') == webfinger.SUBSCRIBE_LINK_REL:
|
||||||
template = link.get('template')
|
template = link.get('template')
|
||||||
if template and '{uri}' in template:
|
if template and '{uri}' in template:
|
||||||
return redirect(template.replace('{uri}', user.ap_address()))
|
return redirect(template.replace('{uri}', user.handle_as(ActivityPub)))
|
||||||
|
|
||||||
flash(f"Couldn't find remote follow link for {addr}")
|
flash(f"Couldn't find remote follow link for {addr}")
|
||||||
return redirect(user.user_page_path())
|
return redirect(user.user_page_path())
|
||||||
|
|
10
models.py
10
models.py
|
@ -337,6 +337,7 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
|
||||||
to_proto = PROTOCOLS[to_proto]
|
to_proto = PROTOCOLS[to_proto]
|
||||||
|
|
||||||
# override web users to always use domain instead of custom username
|
# override web users to always use domain instead of custom username
|
||||||
|
# TODO: fall back to id if handle is unset?
|
||||||
handle = self.key.id() if self.LABEL == 'web' else self.handle
|
handle = self.key.id() if self.LABEL == 'web' else self.handle
|
||||||
if not handle:
|
if not handle:
|
||||||
return None
|
return None
|
||||||
|
@ -428,15 +429,6 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
|
||||||
return (url == this or url == parsed_this.netloc or
|
return (url == this or url == parsed_this.netloc or
|
||||||
parsed_url[1:] == parsed_this[1:]) # ignore http vs https
|
parsed_url[1:] == parsed_this[1:]) # ignore http vs https
|
||||||
|
|
||||||
def ap_address(self):
|
|
||||||
"""Returns this user's ActivityPub address, eg ``@me@foo.com``.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
str:
|
|
||||||
"""
|
|
||||||
# TODO: use self.handle_as? need it to fall back to id?
|
|
||||||
return f'@{self.handle_or_id()}@{self.ABBREV}{common.SUPERDOMAIN}'
|
|
||||||
|
|
||||||
def ap_actor(self, rest=None):
|
def ap_actor(self, rest=None):
|
||||||
"""Returns this user's ActivityPub/AS2 actor id.
|
"""Returns this user's ActivityPub/AS2 actor id.
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
and proto.LABEL not in ('atproto', 'ui') %}
|
and proto.LABEL not in ('atproto', 'ui') %}
|
||||||
<nobr title="{{ proto.__name__ }} (bridged)">
|
<nobr title="{{ proto.__name__ }} (bridged)">
|
||||||
<span class="logo">{{ proto.LOGO_HTML|safe }}</span>
|
<span class="logo">{{ proto.LOGO_HTML|safe }}</span>
|
||||||
{{ user.ap_address() }}
|
{{ user.handle_as('activitypub') }}
|
||||||
</nobr>
|
</nobr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -2071,33 +2071,32 @@ class ActivityPubUtilsTest(TestCase):
|
||||||
postprocess_as2(postprocess_as2(obj)),
|
postprocess_as2(postprocess_as2(obj)),
|
||||||
ignore=['to'])
|
ignore=['to'])
|
||||||
|
|
||||||
def test_ap_address(self):
|
def test_handle_as(self):
|
||||||
user = ActivityPub(obj=Object(id='a', as2={
|
user = ActivityPub(obj=Object(id='a', as2={
|
||||||
**ACTOR,
|
**ACTOR,
|
||||||
'preferredUsername': 'me',
|
'preferredUsername': 'me',
|
||||||
}))
|
}))
|
||||||
self.assertEqual('@me@mas.to', user.ap_address())
|
self.assertEqual('@me@mas.to', user.handle_as(ActivityPub))
|
||||||
self.assertEqual('@me@mas.to', user.handle)
|
self.assertEqual('@me@mas.to', user.handle)
|
||||||
|
|
||||||
user.obj.as2 = ACTOR
|
user.obj.as2 = ACTOR
|
||||||
self.assertEqual('@swentel@mas.to', user.ap_address())
|
self.assertEqual('@swentel@mas.to', user.handle_as(ActivityPub))
|
||||||
self.assertEqual('@swentel@mas.to', user.handle)
|
self.assertEqual('@swentel@mas.to', user.handle)
|
||||||
|
|
||||||
user = ActivityPub(id='https://mas.to/users/alice')
|
user = ActivityPub(id='https://mas.to/users/alice')
|
||||||
self.assertEqual('@alice@mas.to', user.ap_address())
|
self.assertEqual('@alice@mas.to', user.handle_as(ActivityPub))
|
||||||
self.assertEqual('@alice@mas.to', user.handle)
|
self.assertEqual('@alice@mas.to', user.handle)
|
||||||
|
|
||||||
def test_ap_actor(self):
|
|
||||||
user = self.make_user('http://foo/actor', cls=ActivityPub)
|
|
||||||
self.assertEqual('http://foo/actor', user.ap_actor())
|
|
||||||
|
|
||||||
def test_handle_as(self):
|
|
||||||
user = self.make_user('http://a', cls=ActivityPub, obj_as2={
|
user = self.make_user('http://a', cls=ActivityPub, obj_as2={
|
||||||
'id': 'https://mas.to/users/foo',
|
'id': 'https://mas.to/users/foo',
|
||||||
'preferredUsername': 'me',
|
'preferredUsername': 'me',
|
||||||
})
|
})
|
||||||
self.assertEqual('me.mas.to.ap.brid.gy', user.handle_as('atproto'))
|
self.assertEqual('me.mas.to.ap.brid.gy', user.handle_as('atproto'))
|
||||||
|
|
||||||
|
def test_ap_actor(self):
|
||||||
|
user = self.make_user('http://foo/actor', cls=ActivityPub)
|
||||||
|
self.assertEqual('http://foo/actor', user.ap_actor())
|
||||||
|
|
||||||
def test_web_url(self):
|
def test_web_url(self):
|
||||||
user = self.make_user('http://foo/actor', cls=ActivityPub)
|
user = self.make_user('http://foo/actor', cls=ActivityPub)
|
||||||
self.assertEqual('http://foo/actor', user.web_url())
|
self.assertEqual('http://foo/actor', user.web_url())
|
||||||
|
|
|
@ -382,12 +382,15 @@ class ATProtoTest(TestCase):
|
||||||
self.assertEqual('han.dull', user.handle_or_id())
|
self.assertEqual('han.dull', user.handle_or_id())
|
||||||
|
|
||||||
@patch('requests.get', return_value=requests_response('', status=404))
|
@patch('requests.get', return_value=requests_response('', status=404))
|
||||||
def test_ap_address(self, mock_get):
|
def test_handle_as(self, mock_get):
|
||||||
user = self.make_user('did:plc:user', cls=ATProto)
|
user = self.make_user('did:plc:user', cls=ATProto)
|
||||||
self.assertEqual('@did:plc:user@atproto.brid.gy', user.ap_address())
|
|
||||||
|
# TODO? or remove?
|
||||||
|
# self.assertEqual('@did:plc:user@atproto.brid.gy',
|
||||||
|
# user.handle_as('activitypub'))
|
||||||
|
|
||||||
self.store_object(id='did:plc:user', raw=DID_DOC)
|
self.store_object(id='did:plc:user', raw=DID_DOC)
|
||||||
self.assertEqual('@han.dull@atproto.brid.gy', user.ap_address())
|
self.assertEqual('@han.dull@atproto.brid.gy', user.handle_as('activitypub'))
|
||||||
|
|
||||||
@patch('requests.get', return_value=requests_response(DID_DOC))
|
@patch('requests.get', return_value=requests_response(DID_DOC))
|
||||||
def test_profile_id(self, mock_get):
|
def test_profile_id(self, mock_get):
|
||||||
|
|
|
@ -62,7 +62,7 @@ class RemoteFollowTest(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.make_user('user.com', cls=Web)
|
self.make_user('user.com', cls=Web, has_redirects=True)
|
||||||
|
|
||||||
def test_no_domain(self, _):
|
def test_no_domain(self, _):
|
||||||
got = self.client.post('/remote-follow?address=@foo@bar&protocol=web')
|
got = self.client.post('/remote-follow?address=@foo@bar&protocol=web')
|
||||||
|
|
|
@ -44,7 +44,7 @@ class PagesTest(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.user = self.make_user('user.com', cls=Web)
|
self.user = self.make_user('user.com', cls=Web, has_redirects=True)
|
||||||
|
|
||||||
def test_user(self):
|
def test_user(self):
|
||||||
got = self.client.get('/web/user.com', base_url='https://fed.brid.gy/')
|
got = self.client.get('/web/user.com', base_url='https://fed.brid.gy/')
|
||||||
|
@ -58,7 +58,7 @@ class PagesTest(TestCase):
|
||||||
def test_user_page_handle(self):
|
def test_user_page_handle(self):
|
||||||
user = self.make_user('http://foo', cls=ActivityPub,
|
user = self.make_user('http://foo', cls=ActivityPub,
|
||||||
obj_as2=ACTOR_WITH_PREFERRED_USERNAME)
|
obj_as2=ACTOR_WITH_PREFERRED_USERNAME)
|
||||||
self.assertEqual('@me@plus.google.com', user.ap_address())
|
self.assertEqual('@me@plus.google.com', user.handle_as(ActivityPub))
|
||||||
|
|
||||||
got = self.client.get('/ap/@me@plus.google.com')
|
got = self.client.get('/ap/@me@plus.google.com')
|
||||||
self.assert_equals(200, got.status_code)
|
self.assert_equals(200, got.status_code)
|
||||||
|
|
|
@ -21,7 +21,7 @@ from common import CONTENT_TYPE_HTML
|
||||||
from models import Follower, Object
|
from models import Follower, Object
|
||||||
from web import TASKS_LOCATION, Web
|
from web import TASKS_LOCATION, Web
|
||||||
from . import test_activitypub
|
from . import test_activitypub
|
||||||
from .testutil import TestCase
|
from .testutil import Fake, TestCase
|
||||||
|
|
||||||
|
|
||||||
FULL_REDIR = requests_response(
|
FULL_REDIR = requests_response(
|
||||||
|
@ -1915,24 +1915,27 @@ http://this/404s
|
||||||
self.assertTrue(self.user.is_web_url('https://www.user.com/'))
|
self.assertTrue(self.user.is_web_url('https://www.user.com/'))
|
||||||
self.assertFalse(self.user.is_web_url('https://other.com/'))
|
self.assertFalse(self.user.is_web_url('https://other.com/'))
|
||||||
|
|
||||||
def test_ap_address(self, *_):
|
def test_handle_as(self, *_):
|
||||||
self.assertEqual('@user.com@user.com', self.user.ap_address())
|
self.assertEqual('@user.com@user.com', self.user.handle_as(ActivityPub))
|
||||||
|
|
||||||
self.user.obj = Object(id='a', as2={'type': 'Person'})
|
self.user.obj = Object(id='a', as2={'type': 'Person'})
|
||||||
self.assertEqual('@user.com@user.com', self.user.ap_address())
|
self.assertEqual('@user.com@user.com', self.user.handle_as(ActivityPub))
|
||||||
|
|
||||||
self.user.obj.as2 = {'url': 'http://foo'}
|
self.user.obj.as2 = {'url': 'http://foo'}
|
||||||
self.assertEqual('@user.com@user.com', self.user.ap_address())
|
self.assertEqual('@user.com@user.com', self.user.handle_as(ActivityPub))
|
||||||
|
|
||||||
self.user.has_redirects = False
|
self.user.has_redirects = False
|
||||||
self.assertEqual('@user.com@web.brid.gy', self.user.ap_address())
|
self.assertEqual('@user.com@web.brid.gy', self.user.handle_as(ActivityPub))
|
||||||
|
|
||||||
self.user.obj.as2 = {'url': ['http://foo', 'acct:bar@foo', 'acct:baz@user.com']}
|
self.user.obj.as2 = {'url': ['http://foo', 'acct:bar@foo', 'acct:baz@user.com']}
|
||||||
self.user.has_redirects = True
|
self.user.has_redirects = True
|
||||||
self.assertEqual('@baz@user.com', self.user.ap_address())
|
self.assertEqual('@baz@user.com', self.user.handle_as(ActivityPub))
|
||||||
|
|
||||||
self.user.has_redirects = False
|
self.user.has_redirects = False
|
||||||
self.assertEqual('@user.com@web.brid.gy', self.user.ap_address())
|
self.assertEqual('@user.com@web.brid.gy', self.user.handle_as(ActivityPub))
|
||||||
|
|
||||||
|
self.assertEqual('fake:handle:user.com', self.user.handle_as(Fake))
|
||||||
|
self.assertEqual('user.com.web.brid.gy', self.user.handle_as('atproto'))
|
||||||
|
|
||||||
def test_ap_actor(self, *_):
|
def test_ap_actor(self, *_):
|
||||||
self.assertEqual('http://localhost/user.com', self.user.ap_actor())
|
self.assertEqual('http://localhost/user.com', self.user.ap_actor())
|
||||||
|
@ -1941,9 +1944,6 @@ http://this/404s
|
||||||
self.assertEqual('http://localhost/user.com', self.user.ap_actor())
|
self.assertEqual('http://localhost/user.com', self.user.ap_actor())
|
||||||
self.assertEqual('http://localhost/user.com/inbox', self.user.ap_actor('inbox'))
|
self.assertEqual('http://localhost/user.com/inbox', self.user.ap_actor('inbox'))
|
||||||
|
|
||||||
def test_handle_as(self, *_):
|
|
||||||
self.assertEqual('user.com.web.brid.gy', self.user.handle_as('atproto'))
|
|
||||||
|
|
||||||
def test_check_web_site(self, mock_get, _):
|
def test_check_web_site(self, mock_get, _):
|
||||||
redir = 'http://localhost/.well-known/webfinger?resource=acct:user.com@user.com'
|
redir = 'http://localhost/.well-known/webfinger?resource=acct:user.com@user.com'
|
||||||
mock_get.side_effect = (
|
mock_get.side_effect = (
|
||||||
|
|
|
@ -141,7 +141,8 @@ class WebfingerTest(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
self.user = self.make_user('user.com', cls=Web, has_hcard=True, obj_as2={
|
self.user = self.make_user('user.com', cls=Web, has_hcard=True,
|
||||||
|
has_redirects=True, obj_as2={
|
||||||
'@context': 'https://www.w3.org/ns/activitystreams',
|
'@context': 'https://www.w3.org/ns/activitystreams',
|
||||||
'type': 'Person',
|
'type': 'Person',
|
||||||
'url': 'https://user.com/about-me',
|
'url': 'https://user.com/about-me',
|
||||||
|
|
17
web.py
17
web.py
|
@ -110,6 +110,14 @@ class Web(User, Protocol):
|
||||||
return util.domain_from_link(username, minimize=False)
|
return util.domain_from_link(username, minimize=False)
|
||||||
return username
|
return username
|
||||||
|
|
||||||
|
def handle_as(self, to_proto):
|
||||||
|
"""Special case ActivityPub to use custom username."""
|
||||||
|
if to_proto in ('activitypub', 'ap', PROTOCOLS['ap']):
|
||||||
|
return (f'@{self.username()}@{self.key.id()}' if self.has_redirects
|
||||||
|
else f'@{self.key.id()}@{self.ABBREV}{SUPERDOMAIN}')
|
||||||
|
|
||||||
|
return super().handle_as(to_proto)
|
||||||
|
|
||||||
def web_url(self):
|
def web_url(self):
|
||||||
"""Returns this user's web URL aka web_url, eg ``https://foo.com/``."""
|
"""Returns this user's web URL aka web_url, eg ``https://foo.com/``."""
|
||||||
return f'https://{self.key.id()}/'
|
return f'https://{self.key.id()}/'
|
||||||
|
@ -119,15 +127,6 @@ class Web(User, Protocol):
|
||||||
def is_web_url(self, url):
|
def is_web_url(self, url):
|
||||||
return super().is_web_url(url, ignore_www=True)
|
return super().is_web_url(url, ignore_www=True)
|
||||||
|
|
||||||
def ap_address(self):
|
|
||||||
"""Returns this user's ActivityPub address, eg ``@foo.com@foo.com``.
|
|
||||||
|
|
||||||
Uses the user's domain if they have the ``.well-known`` redirects,
|
|
||||||
otherwise ``web.brid.gy``.
|
|
||||||
"""
|
|
||||||
return (f'@{self.username()}@{self.key.id()}' if self.has_redirects
|
|
||||||
else f'@{self.key.id()}@{self.ABBREV}{SUPERDOMAIN}')
|
|
||||||
|
|
||||||
def ap_actor(self, rest=None):
|
def ap_actor(self, rest=None):
|
||||||
"""Returns this user's ActivityPub/AS2 actor id.
|
"""Returns this user's ActivityPub/AS2 actor id.
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ from oauth_dropins.webutil import flask_util, util
|
||||||
from oauth_dropins.webutil.flask_util import error, flash
|
from oauth_dropins.webutil.flask_util import error, flash
|
||||||
from oauth_dropins.webutil.util import json_dumps, json_loads
|
from oauth_dropins.webutil.util import json_dumps, json_loads
|
||||||
|
|
||||||
|
import activitypub
|
||||||
import common
|
import common
|
||||||
from flask_app import app, cache
|
from flask_app import app, cache
|
||||||
from protocol import Protocol
|
from protocol import Protocol
|
||||||
|
@ -99,7 +100,7 @@ class Webfinger(flask_util.XrdOrJrd):
|
||||||
|
|
||||||
# generate webfinger content
|
# generate webfinger content
|
||||||
data = util.trim_nulls({
|
data = util.trim_nulls({
|
||||||
'subject': 'acct:' + user.ap_address().lstrip('@'),
|
'subject': 'acct:' + user.handle_as('activitypub').lstrip('@'),
|
||||||
'aliases': urls,
|
'aliases': urls,
|
||||||
'links':
|
'links':
|
||||||
[{
|
[{
|
||||||
|
|
Ładowanie…
Reference in New Issue