Skip to content

Detect and distinguish user ids vs object ids better #2281

@snarfed

Description

@snarfed

We don't really know right now whether a given id is user id or an object id. We just infer it from context. This mostly works, but sometimes doesn't, eg the object of a block can be either a user or an object (eg a blocklist). This breaks us subtly sometimes, eg Protocol.translate_ids always assumes a block's id is an object, since block is in as1.VERBS_WITH_ACTOR_OBJECT.

bridgy-fed/protocol.py

Lines 1015 to 1018 in 88bf048

obj_is_actor = o.get('verb') in as1.VERBS_WITH_ACTOR_OBJECT
translate(o, 'object', (ids.translate_user_id if obj_is_actor
else ids.translate_object_id))

Same with Object.normalize_ids:

bridgy-fed/models.py

Lines 1828 to 1831 in 88bf048

translate_fn = ids.translate_object_id
if (as1.object_type(inner_obj) in as1.ACTOR_TYPES
or as1.object_type(outer_obj) in as1.VERBS_WITH_ACTOR_OBJECT):
translate_fn = ids.translate_user_id

Object.resolve_ids at least handles it:

bridgy-fed/models.py

Lines 1747 to 1750 in 88bf048

# object field could be either object (eg repost) or actor (eg follow)
outer_obj['object'] = replace(inner_obj, get_original_object_key)
if not replaced:
outer_obj['object'] = replace(inner_obj, get_original_user_key)

...but the root problem here continues to bite us, eg this crash, which we band-aided with 4c96ea5678dab859bdf1d3d28227b54d9b0cadb8.

Ideally we'd add something like a Protocol.is_user_id method, a top-level ids.translate_id function that uses it, and then switch to ids.translate_id most places. That would let us drastically clean up translate/resolve/normalize_ids too.

Example tests for Protocol.translate_ids below. These are in the stash towards is_user_id etc, #2281.

    def test_translate_ids_block_actor(self):  # fails!
        self.assert_equals({
            'objectType': 'activity',
            'verb': 'block',
            'actor': 'other:u:fake:alice',
            'object': 'other:u:fa:fake:bob',
        }, OtherFake.translate_ids({
            'objectType': 'activity',
            'verb': 'block',
            'actor': 'fake:alice',
            'object': 'fake:bob',
        }))

    def test_translate_ids_block_object(self):  # passes
        self.assert_equals({
            'objectType': 'activity',
            'verb': 'block',
            'actor': 'other:u:fake:alice',
            'object': 'other:o:fa:fake:list',
        }, OtherFake.translate_ids({
            'objectType': 'activity',
            'verb': 'block',
            'actor': 'fake:alice',
            'object': 'fake:list',
        }))

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions