diff --git a/models.py b/models.py index d33a7e58..3e7a8098 100644 --- a/models.py +++ b/models.py @@ -486,6 +486,12 @@ class Object(StringIdModel): def _pre_put_hook(self): assert '^^' not in self.key.id() + if self.key.id().startswith('at://'): + repo, _, _ = arroba.util.parse_at_uri(self.key.id()) + if not repo.startswith('did:'): + raise ValueError( + f'at:// URI ids must have DID repos; got {self.key.id()}') + if self.as1 and self.as1.get('objectType') == 'activity': add(self.labels, 'activity') elif 'activity' in self.labels: diff --git a/tests/test_models.py b/tests/test_models.py index 1e2a5180..7c539a14 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -441,6 +441,15 @@ class ObjectTest(TestCase): self.assertIsNone(obj.mf2) self.assertIsNone(obj.bsky) + def test_validate_id(self): + # DID repo ids + Object(id='at://did:plc:123/app.bsky.feed.post/abc').put() + Object(id='at://did:plc:foo.com/app.bsky.actor.profile/self').put() + + with self.assertRaises(ValueError): + # non-DID (bare handle) repo id + Object(id='at://foo.com/app.bsky.feed.post/abc').put() + class FollowerTest(TestCase):