add new User.copies property

pull/642/head
Ryan Barrett 2023-09-19 16:07:11 -07:00
rodzic abde77e7eb
commit bb18b5ee0d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 6BE31FDF4776E9D4
3 zmienionych plików z 49 dodań i 36 usunięć

Wyświetl plik

@ -222,6 +222,7 @@ class ATProto(User, Protocol):
def update_user_create_repo():
Object.get_or_create(did_plc.did, raw=did_plc.doc)
user.atproto_did = did_plc.did
add(user.copies, Target(uri=did_plc.did, protocol=to_cls.LABEL))
user.put()
assert not storage.load_repo(user.atproto_did)

Wyświetl plik

@ -50,6 +50,42 @@ OBJECT_EXPIRE_AGE = timedelta(days=90)
logger = logging.getLogger(__name__)
class Target(ndb.Model):
"""Protocol + URI pairs for identifying objects.
These are currently used for:
* delivery destinations, eg ActivityPub inboxes, webmention targets, etc.
* copies of :class:`Object`s and :class:`User`s elsewhere, eg at:// URIs for
ATProto records, nevent etc bech32-encoded Nostr ids, ATProto user DIDs,
etc.
Used in StructuredPropertys inside :class:`Object` and :class:`User`; not
stored as top-level entities in the datastore.
ndb implements this by hoisting each property here into a corresponding
property on the parent entity, prefixed by the StructuredProperty name
below, eg `delivered.uri`, `delivered.protocol`, etc.
For repeated StructuredPropertys, the hoisted properties are all repeated on
the parent entity, and reconstructed into StructuredPropertys based on their
order.
https://googleapis.dev/python/python-ndb/latest/model.html#google.cloud.ndb.model.StructuredProperty
"""
uri = ndb.StringProperty(required=True)
# choices is populated in app via reset_protocol_properties, after all User
# subclasses are created, so that PROTOCOLS is fully populated
protocol = ndb.StringProperty(choices=[], required=True)
def __eq__(self, other):
"""Equality excludes Targets' :class:`Key`."""
return self.uri == other.uri and self.protocol == other.protocol
def __hash__(self):
"""Allow hashing so these can be dict keys."""
return hash((self.protocol, self.uri))
class ProtocolUserMeta(type(ndb.Model)):
""":class:`User` metaclass. Registers all subclasses in the PROTOCOLS global."""
def __new__(meta, name, bases, class_dict):
@ -110,6 +146,11 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
# OLD. some stored entities still have this; do not reuse.
# actor_as2 = JsonProperty()
# Proxy copies of this user elsewhere, eg DIDs for ATProto records, bech32
# npub Nostr ids, etc. Similar to rel-me links in microformats2, alsoKnownAs
# in DID docs (and now AS2), etc.
copies = ndb.StructuredProperty(Target, repeated=True)
def __init__(self, **kwargs):
"""Constructor.
@ -371,40 +412,6 @@ class User(StringIdModel, metaclass=ProtocolUserMeta):
return f'<a class="h-card u-author" href="{self.user_page_path()}"><img src="{img}" class="profile"> {self.name()}</a>'
class Target(ndb.Model):
"""Protocol + URI pairs for identifying objects.
These are currently used for:
* delivery destinations, eg ActivityPub inboxes, webmention targets, etc.
* copies of objects stored elsewhere, eg at:// URIs for ATProto records
Used in StructuredPropertys inside Object; not stored directly in the
datastore.
ndb implements this by hoisting each property here into a corresponding
property on the parent entity, prefixed by the StructuredProperty name
below, eg delivered.uri, delivered.protocol, etc.
For repeated StructuredPropertys, the hoisted properties are all repeated on
the parent entity, and reconstructed into StructuredPropertys based on their
order.
https://googleapis.dev/python/python-ndb/latest/model.html#google.cloud.ndb.model.StructuredProperty
"""
uri = ndb.StringProperty(required=True)
# choices is populated in app via reset_protocol_properties, after all User
# subclasses are created, so that PROTOCOLS is fully populated
protocol = ndb.StringProperty(choices=[], required=True)
def __eq__(self, other):
"""Equality excludes Targets' :class:`Key`."""
return self.uri == other.uri and self.protocol == other.protocol
def __hash__(self):
"""Allow hashing so these can be dict keys."""
return hash((self.protocol, self.uri))
class Object(StringIdModel):
"""An activity or other object, eg actor.
@ -453,7 +460,10 @@ class Object(StringIdModel):
undelivered = ndb.StructuredProperty(Target, repeated=True)
failed = ndb.StructuredProperty(Target, repeated=True)
# Copies of this object elsewhere, eg at:// URIs for ATProto records
# Copies of this object elsewhere, eg at:// URIs for ATProto records and
# nevent etc bech32-encoded Nostr ids, where this object is the original.
# Similar to u-syndication links in microformats2 and
# upstream/downstreamDuplicates in AS1.
copies = ndb.StructuredProperty(Target, repeated=True)
created = ndb.DateTimeProperty(auto_now_add=True)

Wyświetl plik

@ -48,7 +48,7 @@ DID_DOC = {
}],
}
KEY = arroba.util.new_key()
KEY = arroba.util.new_key(2349823483510) # deterministic seed
class ATProtoTest(TestCase):
@ -231,6 +231,8 @@ class ATProtoTest(TestCase):
# check DID doc
user = user.key.get()
assert user.atproto_did
self.assertEqual([Target(uri=user.atproto_did, protocol='atproto')],
user.copies)
did_obj = ATProto.load(user.atproto_did)
self.assertEqual('http://localhost/',
did_obj.raw['service'][0]['serviceEndpoint'])