Skip to content

Sending the user as the actor in our activities

Related to #236 and #254 . Currently our activities are being sent with a generic "BACKLINKS SERVICE" actor. This means that from the receiver's point of view, the Parisian user didn't join the Nanteais server, but the Parisian server did

For many reasons and most pressingly for key exchange, we want to specify the actor as the user, not the server. For example it means that I can check that the incoming user has the permission to do that on my server, rather than having to put superuser-level trust into every server in the federation

Why it's hard

The backlink is discovered during a post_save listener, where we check if the object being updated has links to external resources. The post-save is a safe way to know in Django that an object has been updated:

  • by a request to a view
  • in the admin panel
  • in a shell script
  • in a unit test
  • anywhere in else in code, e.g. within another post_save listener

Possible solutions

Saving the creator on djangoldp.models.Model

By saving the creator to the Model (in the viewset/serializer), we could access it during automated backlink detection (which has access to the instance triggering the backlink). The issue with this would be along the lines of extensibility for application developers - e.g. when saving an object in a custom View

Getting the user into the post_save event handler

  • Firing a custom event signal in LDPViewSet should be fairly straightforward for this because the user is simple, it's the request.user. Overriding the changes in the admin panel might be straightforward (I haven't researched). However it's insufficient for the bulk of the saves (those which are triggered in code) - something extremely common for DjangoLDP packages to do
  • Overriding Model.save to raise an exception if the user is not passed into it. A safe solution but awful - essentially moves the problem onto the application developer

Changing the way that the backlink is sent

... ?

Using ActivityPub client-to-server

To be accurate, we use ActivityStreams in our backlinks but we're not using ActivityPub. Very briefly, we use Activities for our backlinks, which we then use in a server-to-server federation (like ActivityPub), but we don't use the client-to-server protocol at all (we send linked data to pre-configured endpoints client-side (#377 ))

The ActivityPub spec describes the user sending an object/Activity to their outbox (client-to-server). In the outbox the server would have access to the user who sent the activity. Evidently this is a considerable shift, and since ActivityPub is based on Linked Data to implement decentralised social networking applications, the scope of DjangoLDP is probably wider. Needs discussion

Sometimes sending the backlink from the server itself

Sending the user as the "server user" when we don't know. Easier but means that the receiver has to trust totally the "server user" which is a big security problem

This is more or less the original suggestion on #236, and it might not resolve the server-to-server key exchange issues which we were discussing this morning

ping @balessan @decentral1se

Edited by Calum Mackervoy