2018-09-04 21:58:27 +00:00
|
|
|
django-kepi
|
|
|
|
===========
|
|
|
|
|
2018-09-06 16:09:31 +00:00
|
|
|
This is a Django library for ActivityPub. It's still at an
|
2018-09-04 21:58:27 +00:00
|
|
|
early stage, and you shouldn't particularly expect anything
|
|
|
|
to work properly. Its primary purpose is as part of the
|
|
|
|
un_chapeau Mastodon server.
|
|
|
|
|
2018-09-05 17:03:11 +00:00
|
|
|
At present we aren't supporting local clients posting to a
|
|
|
|
user's outbox, though we should eventually.
|
|
|
|
|
2018-09-04 21:58:27 +00:00
|
|
|
Not everything described herein has actually been implemented.
|
|
|
|
|
2018-09-05 17:03:11 +00:00
|
|
|
django_kepi.responses.ActivityObjectResponse
|
|
|
|
--------------------------------------------
|
2018-09-04 21:58:27 +00:00
|
|
|
This renders a Django object into ActivityStreams form.
|
2018-09-06 16:09:31 +00:00
|
|
|
It reads the object's activity property in order to
|
|
|
|
serialise it. If that property throws TombstoneException,
|
2018-09-04 21:58:27 +00:00
|
|
|
a Tombstone will be generated instead, and the HTTP
|
|
|
|
result code will be set to 410 (Gone).
|
|
|
|
|
2018-09-05 17:03:11 +00:00
|
|
|
Some of these objects, such as Likes, will belong to django_kepi.
|
|
|
|
Other kinds, such as Persons and Articles, will belong to other apps.
|
|
|
|
|
|
|
|
django_kepi.responses.CollectionResponse
|
|
|
|
----------------------------------------
|
2018-09-04 21:58:27 +00:00
|
|
|
These are based on ordinary Django ordered querysets.
|
|
|
|
|
|
|
|
Each subclass must reimplement get_queryset() to return
|
|
|
|
the relevant queryset. It may also reimplement serialize_object(),
|
|
|
|
which will serialize objects found in the queryset. If
|
2018-09-06 16:09:31 +00:00
|
|
|
you don't reimplement serialize_object(), the object's activity property
|
|
|
|
will be used as usual.
|
2018-09-04 21:58:27 +00:00
|
|
|
|
|
|
|
Objects which throw TombstoneException will be represented
|
|
|
|
with Tombstones, but this won't affect the HTTP result code.
|
|
|
|
|
2018-09-05 16:01:43 +00:00
|
|
|
django_kepi.TombstoneException
|
|
|
|
------------------------------
|
2018-09-06 16:09:31 +00:00
|
|
|
If ActivityObjectResponse reads an object's activity property,
|
|
|
|
and that property throws TombstoneException,
|
2018-09-05 16:01:43 +00:00
|
|
|
ActivityObjectResponse will produce an HTTP status of 410 (Gone)
|
|
|
|
and return a Tombstone object (as specified in ActivityPub).
|
|
|
|
|
2018-09-06 16:09:31 +00:00
|
|
|
If an activity property is read while producing a Collection,
|
|
|
|
and it throws TombstoneException, the object will be represented
|
2018-09-05 16:01:43 +00:00
|
|
|
by a Tombstone object, but the HTTP status code will be unaffected.
|
|
|
|
|
2018-09-05 17:03:11 +00:00
|
|
|
Throwing TombstoneException doesn't remove the object's record from
|
|
|
|
NamedObjects, because we'll still need to find the Tombstone when
|
|
|
|
someone asks for it.
|
|
|
|
|
2018-09-04 21:58:27 +00:00
|
|
|
django_kepi.models.resolve()
|
|
|
|
----------------------------
|
2018-09-05 16:01:43 +00:00
|
|
|
Takes a URL identifier, and returns the object it refers to,
|
|
|
|
in this way:
|
|
|
|
|
|
|
|
First, we check django_kepi.models.NamedObject. If the URL is
|
|
|
|
listed there, we return the object referred to.
|
|
|
|
|
|
|
|
Secondly, if the hostname is one of the names of the current site,
|
|
|
|
we run the path through django.urls.resolve() to find the view function.
|
|
|
|
|
|
|
|
(XXX This won't work. NamedObject finds us an object, and
|
|
|
|
d.u.resolve() gets us a view function. They need to be the same.)
|
|
|
|
|
2018-09-05 17:03:11 +00:00
|
|
|
XXX Fallback function to handle fetching, etc, per Activity type
|
2018-09-04 21:58:27 +00:00
|
|
|
|
2018-09-05 16:20:10 +00:00
|
|
|
XXX explain about how remote objects will have local proxy objects
|
|
|
|
XXX explain how these proxy objects should never be served
|
|
|
|
|
2018-09-05 17:03:11 +00:00
|
|
|
XXX There's actually four things we might want to do to an object:
|
|
|
|
XXX Create: ID + fields -> new object (serialised)
|
|
|
|
XXX Get: ID -> existing object (deserialised)
|
|
|
|
XXX Update: ID + fields -> existing object (partially serialised)
|
|
|
|
XXX Delete: ID -> no object (or Tombstone)
|
|
|
|
|
2018-09-04 21:58:27 +00:00
|
|
|
django_kepi.models.QuarantinedMessage
|
|
|
|
-------------------------------------
|
2018-09-05 16:01:43 +00:00
|
|
|
An activity message we've received from another server, but
|
|
|
|
haven't had a chance to verify.
|
2018-09-04 21:58:27 +00:00
|
|
|
|
2018-09-05 16:01:43 +00:00
|
|
|
Kepi will dump all incoming messages here. Verification is
|
|
|
|
never done while processing a request.
|
|
|
|
|
|
|
|
XXX explain how we do this in batch mode
|
|
|
|
|
|
|
|
Both the body of the message and the HTTP headers must be signed,
|
|
|
|
otherwise the message is discarded.
|
|
|
|
|
|
|
|
XXX Do both signatures have to use the same key?
|
|
|
|
|
|
|
|
To verify a message, we need to know the details of:
|
|
|
|
- the Actor who sent it, who must have nominated that key as
|
|
|
|
their public key
|
|
|
|
- the public key, which must name the Actor as its owner.
|
|
|
|
|
|
|
|
If a message fails verification, it gets logged and discarded.
|
|
|
|
If it passes verification, it gets created as a new
|
|
|
|
django_kepi.models.Activity.
|
|
|
|
|
|
|
|
django_kepi.models.NamedObject
|
|
|
|
------------------------------
|
2018-09-05 16:20:10 +00:00
|
|
|
This table maps URL identifiers to Django objects,
|
|
|
|
using the contenttypes mechanism.
|
|
|
|
It also keeps track of the object's ActivityObject type.
|
2018-09-05 17:03:11 +00:00
|
|
|
It keeps a timestamp, so the record can fade from the cache
|
|
|
|
(but we don't actually do that at present).
|
2018-09-05 16:20:10 +00:00
|
|
|
|
|
|
|
Any object we know about on a remote server must be listed in
|
|
|
|
this table. Objects on this server *may* be listed
|
|
|
|
in this table; if they're not django_kepi.models.resolve()
|
|
|
|
can also find them through following the URL path.
|
2018-09-05 16:01:43 +00:00
|
|
|
|
|
|
|
django_kepi.models.Activity
|
|
|
|
---------------------------
|
2018-09-05 16:20:10 +00:00
|
|
|
All our own Activities, and all the remote Activities we know about,
|
|
|
|
are listed here. Each is identified by a UUID.
|
|
|
|
|
|
|
|
Saving an Activity to this table may have side-effects, based
|
|
|
|
on the Activity type. For example, saving a Follow activity
|
|
|
|
constitutes a Follow request.
|
2018-09-04 21:58:27 +00:00
|
|
|
|
2018-09-05 16:21:41 +00:00
|
|
|
Activities have a "valid" flag, because they can be undone
|
|
|
|
by subsequent Activities of type Undo.
|
2018-09-05 17:03:11 +00:00
|
|
|
|
|
|
|
django_kepi.views.ActivityView
|
|
|
|
------------------------------
|
|
|
|
A class view which displays a django_kepi.models.Activity,
|
|
|
|
given its UUID. Only our own Activities will be displayed.
|
|
|
|
|
|
|
|
django_kepi.views.CollectionView
|
|
|
|
--------------------------------
|
|
|
|
A view of a queryset, based on django_kepi.responses.CollectionResponse.
|
|
|
|
|
|
|
|
Outgoing Activities
|
|
|
|
-------------------
|
|
|
|
....
|