ActivityPub
We want to create a new module to implement ActivityPub.
Here is the idea :
- Server A can "follow" the server B. When adding a new "source" the server A send a follow activity to the server B source inbox (aka https://api.test-paris.happy-dev.fr/job-offers/inbox ) (see : https://www.w3.org/TR/activitypub/#follow-activity-inbox)
- At follow request the server B add server A to its "followers" for 'job-offers' and send a Accept activity (https://www.w3.org/TR/activitypub/#accept-activity-inbox). An admin could authorize this follower.
- when receiving the accept activity, server A must add server B to its followings and GET the outbox of server B to get all old activities.
- Each time a job-offer is create on server B, server B will send a create activity to the server A inbox. Also this activity can be fetch using e GET on server B outbox
- The activity is stored on the server A.
- An agent can react to the activity creation to do anything, for instance sending email to users with some job-offers skills.
-
Make a proof of concept implementing basic ActivityPub feature :
- Create djangoldp-activitypub project (https://git.happy-dev.fr/startinblox/djangoldp-packages/djangoldp-activitypub)
- Allow webfinger extension on djangoldp modules and extend it on activity-pub module
- Implements Actor endpoints
-
Implements Follow Request
- Receive
- Send (Optional)
-
Implements Accept Request
- Receive (Optional)
- Send
-
Implements Undo Request (Useful for unfollow)
- Receive
- Send (Optinnal)
- Implements /inbox endpoints
- Implements /outbox endpoints
-
Implements Like request (Optional)
- Receive
- Send (Optional)
- Make a activitypub bridge on job-offers module
- Test with mastodon and prepare a demo
-
Security
- Verifiy signature (Optional)
- Sign Request
Implemenation help :
- https://django-activity-stream.readthedocs.io/en/latest/
- https://blog.joinmastodon.org/2018/06/how-to-implement-a-basic-activitypub-server/
- https://github.com/tOkeshu/activitypub-example/
- https://dev.funkwhale.audio/funkwhale/funkwhale
To discover the endpoint of each actor, we do a GET on the source
url :
GET https://api.test-paris.happy-dev.r/job-offers/
Accept: application/activity+json
returns :
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
],
"id": "https://api.test-paris.happy-dev.fr/job-offers/",
"type": "Service",
"following": "https://api.test-paris.happy-dev.r/job-offers/following",
"followers": "https://api.test-paris.happy-dev.fr/job-offers/followers",
"inbox": "https://api.test-paris.happy-dev.fr/inbox",
"outbox": "https://api.test-paris.happy-dev.fr/outbox",
"featured": "https://api.test-paris.happy-dev.fr/job-offers/featured",
"preferredUsername": "job-offers",
"name": "Paris Job Offers",
"summary": "Paris Job Offers",
"url": "https://test-paris.happy-dev.fr/job-offers/",
"publicKey": {
"id": "https://api.test-paris.happy-dev.fr/job-offers/#main-key",
"owner": "https://api.test-paris.happy-dev.fr/job-offers/",
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8WTFWrnNQ3lMFXMxxuRw\nghuEyAqJKIYnQL+QJkAnsRiPIC5susT9AwUrahrJ0sMu5wyF1Kt/B4cHzHL5/MXQ\nEN+4PgzCvbZCTjp0q6JSQuqN3BDq0q6fmusQdJ1WDko5xLgY3g8fD5wgJFtAcuoz\n0KPagz3NrjcOjSduwj0chF0tbIYFP0NoyveKJ3rWWn2ekMqke7x51pVmhjqdGtB5\nlqusXvUBFloC/sOlOUVHD/pR0lTyDSd/d7w7/GRCdbaV3hvEiHg//qaPCSnnU0nK\nH32o5t7Ab9yBkHUB6dLMMwyuZ0v19Wv9TenGpOxD2itrSSjnrFj4Id5A6o+rtGgB\nzQIDAQAB\n-----END PUBLIC KEY-----\n"
},
"tag": [],
"endpoints": {
"sharedInbox": "https://api.test-paris.happy-dev.fr/inbox"
},
"icon": {
"type": "Image",
"mediaType": "image/png",
"url": "https://test-paris.happy-dev.fr/images/logo.png"
}
}