Skip to content

Commit

Permalink
ATProto: reload DID doc along with profile when necessary
Browse files Browse the repository at this point in the history
for #1334
  • Loading branch information
snarfed committed Oct 4, 2024
1 parent 6aa30bf commit 2a13b83
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 4 deletions.
7 changes: 6 additions & 1 deletion atproto.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,11 @@ def handle_to_id(cls, handle):

return did.resolve_handle(handle, get_fn=util.requests_get)

def reload_profile(self):
"""Reloads this user's DID doc along with their profile object."""
super().reload_profile()
self.load(self.key.id(), did_doc=True, remote=True)

@classmethod
def bridged_web_url_for(cls, user, fallback=False):
"""Returns a bridged user's profile URL on bsky.app.
Expand Down Expand Up @@ -398,7 +403,7 @@ def create_for(cls, user):

# fetch and store profile
if not user.obj or not user.obj.as1:
user.obj = user.load(user.profile_id(), remote=True)
user.reload_profile()

initial_writes = []
if user.obj and user.obj.as1:
Expand Down
7 changes: 7 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,13 @@ def profile_id(self):
"""
return ids.profile_id(id=self.key.id(), proto=self)

def reload_profile(self):
"""Reloads this user's identity and profile from their native protocol.
Populates the reloaded profile :class:`Object` in ``self.obj``.
"""
self.obj = self.load(self.profile_id(), remote=True)

def user_page_path(self, rest=None):
"""Returns the user's Bridgy Fed user page path."""
path = f'/{self.ABBREV}/{self.handle_or_id()}'
Expand Down
2 changes: 1 addition & 1 deletion pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ def update_profile(protocol, id):
link = f'<a href="{user.web_url()}">{user.handle_or_id()}</a>'

try:
user.obj = user.load(user.profile_id(), remote=True)
user.reload_profile()
except (requests.RequestException, werkzeug.exceptions.HTTPException) as e:
_, msg = util.interpret_http_exception(e)
flash(f"Couldn't update profile for {link}: {msg}")
Expand Down
2 changes: 1 addition & 1 deletion protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@ def receive(from_cls, obj, authed_as=None, internal=False):
# follows of bot user; refresh user profile first
logger.info(f'Follow of bot user, reloading {actor}')
from_user = from_cls.get_or_create(id=actor, allow_opt_out=True)
from_user.obj = from_cls.load(from_user.profile_id(), remote=True)
from_user.reload_profile()
else:
# load actor user
from_user = from_cls.get_or_create(id=actor, allow_opt_out=internal)
Expand Down
14 changes: 14 additions & 0 deletions tests/test_atproto.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,20 @@ def test_handle_to_id_first_opted_out(self):
def test_handle_to_id_not_found(self, *_):
self.assertIsNone(ATProto.handle_to_id('ha.nl'))

@patch('requests.get', side_effect=[
requests_response({
'uri': 'at://did:plc:user/app.bsky.actor.profile/self',
'cid': 'bafyreigd',
'value': ACTOR_PROFILE_BSKY,
}),
requests_response(DID_DOC),
])
def test_reload_profile(self, mock_get):
user = ATProto(id='did:plc:user')
user.reload_profile()
self.assertEqual({**ACTOR_PROFILE_BSKY, 'cid': 'bafyreigd'}, user.obj.bsky)
self.assertEqual(DID_DOC, Object.get_by_id('did:plc:user').raw)

def test_bridged_web_url_for(self):
self.assertIsNone(ATProto.bridged_web_url_for(ATProto(id='did:plc:foo')))

Expand Down
5 changes: 4 additions & 1 deletion tests/test_integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -502,9 +502,9 @@ def test_activitypub_follow_bsky_bot_bad_username_error(self, mock_get):
# ...
}))
@patch('requests.get', side_effect=[
requests_response(DID_DOC), # alice DID
requests_response(PROFILE_GETRECORD), # alice profile
requests_response(PROFILE_GETRECORD), # ...
requests_response(DID_DOC), # alice DID
requests_response({ # getConvoForMembers
'convo': {
'id': 'convo123',
Expand All @@ -525,6 +525,9 @@ def test_atproto_follow_ap_bot_user_enables_protocol(self, mock_get, mock_post):
# only needed for atproto_firehose.load_dids
self.make_atproto_user('did:plc:eve')

# existing stale stored DID doc for alice, should be reloaded and overwritten
self.store_object(id='did:plc:alice', raw={'not': 'used'})

follow = {
'$type': 'app.bsky.graph.follow',
'subject': 'did:plc:ap',
Expand Down

0 comments on commit 2a13b83

Please sign in to comment.