-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
188 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
### Implementing ActivityPub Inbox and Outbox in Rails | ||
|
||
#### 1. Database Setup: | ||
|
||
To store incoming and outgoing activities, you'll need to set up the appropriate database tables. | ||
|
||
```bash | ||
rails generate model Activity content:text actor:references type:string object:references target:references published:datetime | ||
``` | ||
|
||
Then run `rails db:migrate`. | ||
|
||
#### 2. Routes: | ||
|
||
Define routes for the inbox and outbox. | ||
|
||
```ruby | ||
# config/routes.rb | ||
resources :actors do | ||
member do | ||
post :inbox | ||
get :outbox | ||
end | ||
end | ||
``` | ||
|
||
#### 3. Controller: | ||
|
||
Set up your controller to handle the incoming and outgoing requests. | ||
|
||
```ruby | ||
# app/controllers/actors_controller.rb | ||
class ActorsController < ApplicationController | ||
def inbox | ||
# Parse the incoming ActivityPub request. | ||
activity = ActivityPub::Activity.from_h(params.require(:activity).permit!) | ||
|
||
# Process the incoming activity. | ||
case activity.type | ||
when "Create" | ||
# Handle the creation of a new activity. | ||
when "Follow" | ||
# Handle a new follow request. | ||
end | ||
|
||
# Respond to the request. | ||
head :created | ||
end | ||
|
||
def outbox | ||
# For the sake of simplicity, we're just displaying all activities related to an actor. | ||
@activities = Activity.where(actor: params[:id]) | ||
end | ||
end | ||
``` | ||
|
||
#### 4. Model: | ||
|
||
Your `Activity` model will hold the core logic for processing activities. | ||
|
||
```ruby | ||
# app/models/activity.rb | ||
class Activity < ApplicationRecord | ||
belongs_to :actor | ||
|
||
# You can add validation and methods to process specific activity types. | ||
|
||
validates :type, presence: true | ||
|
||
def process_incoming | ||
# Logic to process an incoming activity. | ||
end | ||
|
||
def send_outgoing | ||
# Logic to send an outgoing activity. | ||
end | ||
end | ||
``` | ||
|
||
#### 5. Views: | ||
|
||
You may or may not need views, as a lot of this is server-to-server communication. However, for the outbox, it's useful to have a visual representation. | ||
|
||
```erb | ||
<!-- app/views/actors/outbox.html.erb --> | ||
<% @activities.each do |activity| %> | ||
<div class="activity"> | ||
<strong>Type:</strong> <%= activity.type %><br> | ||
<strong>Content:</strong> <%= activity.content %><br> | ||
<!-- Add more fields as necessary --> | ||
</div> | ||
<% end %> | ||
``` | ||
|
||
#### 6. Processing Activities: | ||
|
||
When receiving an activity in the inbox, you'll want to process it according to its type. This could be acknowledging a follow request, storing a new note or message, updating your local state based on a delete activity, etc. | ||
|
||
When sending an activity from the outbox, you'll want to serialize your activity to the correct format, ensure you're addressing it to the correct recipients, handle any necessary authentication or HTTP signatures, and handle possible failures in delivery. | ||
|
||
#### 7. Integration with ActivityPub: | ||
|
||
Ensure that you integrate the ActivityPub-specific functionalities, like HTTP Signatures, JSON-LD parsing, etc. | ||
|
||
### Tips: | ||
|
||
- **Separation of Concerns:** Keep the ActivityPub logic separate from your core application logic. Consider using service objects or separate classes/modules to encapsulate ActivityPub-specific behaviors. | ||
|
||
- **Security:** Ensure you're verifying any incoming requests to ensure they're genuine. HTTP Signatures are a key component of this for ActivityPub. | ||
|
||
- **Testing:** Given the complexity of server-to-server interactions and the various ways an activity can be formatted, testing is crucial. Use Rails' testing capabilities along with libraries like `webmock` to mock external requests. | ||
|
||
- **Documentation:** The ActivityPub specification is thorough but can be dense. Regularly refer back to it, and consider looking at other implementations or communities for guidance. | ||
|
||
By following the above guidance and building upon the basic setup provided, you should be able to effectively implement and customize an ActivityPub inbox and outbox in a Rails app. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
### HTTP Signatures in ActivityPub with Rails: | ||
|
||
**HTTP Signatures** provide a standard way for servers to verify the authenticity and integrity of HTTP messages. They're crucial in a decentralized environment like ActivityPub. | ||
|
||
#### 1. Generating a key pair: | ||
|
||
Before you can sign anything, you need a public/private key pair. The private key will reside on the server doing the signing, and the public key will be shared with others to verify the signature. | ||
|
||
```bash | ||
openssl genpkey -algorithm RSA -out private.pem | ||
openssl pkey -in private.pem -pubout -out public.pem | ||
``` | ||
|
||
#### 2. Storing the keys: | ||
|
||
Store your private key securely on your server. You can serve the public key via your Actor's `publicKey` field in ActivityPub. | ||
|
||
#### 3. Signing the request: | ||
|
||
When sending an ActivityPub request from your server: | ||
|
||
- Create a signature string based on certain headers of your HTTP message. | ||
- Use your private key to sign this string. | ||
- Add the signature to the `Signature` header of your HTTP request. | ||
|
||
Ruby has several libraries that can help with this, e.g., `http-signature-ruby`. | ||
|
||
#### 4. Verifying incoming requests: | ||
|
||
For incoming ActivityPub messages: | ||
|
||
- Retrieve the public key from the Actor's profile that sent the request. | ||
- Use this key to verify the signature in the `Signature` header against the headers of the incoming message. | ||
|
||
This verifies both the authenticity (it's genuinely from who it claims to be from) and the integrity (the message wasn't tampered with in transit). | ||
|
||
### JSON-LD Parsing in ActivityPub with Rails: | ||
|
||
**JSON-LD** (JSON Linked Data) is a method of encoding Linked Data using JSON. ActivityPub uses it to provide a context for terms used in messages, ensuring consistent interpretation across different implementations. | ||
|
||
#### 1. Adding context: | ||
|
||
When sending an ActivityPub message, include a `@context` field, typically with the value "https://www.w3.org/ns/activitystreams". | ||
|
||
```json | ||
{ | ||
"@context": "https://www.w3.org/ns/activitystreams", | ||
"type": "Note", | ||
"content": "Hello World" | ||
} | ||
``` | ||
|
||
#### 2. Parsing incoming JSON-LD: | ||
|
||
When receiving a message, you'll want to interpret it in the context provided: | ||
|
||
- Libraries like `json-ld` can help expand messages to a full form, ensuring that shorthand terms are fully understood in their context. | ||
|
||
For Rails, you can parse JSON-LD as you would parse typical JSON but be mindful of the `@context` and terms used. The key is understanding that JSON-LD provides a way to disambiguate terms that might have different meanings in different contexts. | ||
|
||
### Tips: | ||
|
||
- **Security First**: Always validate incoming data. Never assume that just because a message has a valid signature, its content is safe or well-formed. | ||
|
||
- **Testing**: Implement thorough tests for your signing and verification logic. Ensure that you can correctly sign messages, and that you correctly reject invalid signatures or tampered messages. | ||
|
||
- **Standards are Your Friend**: When in doubt, refer to the [HTTP Signatures spec](https://tools.ietf.org/html/draft-cavage-http-signatures-12) and the [JSON-LD spec](https://www.w3.org/TR/json-ld/). ActivityPub has a well-defined spec, but it does intersect with other standards like these, so sometimes you'll need to look outside the main ActivityPub documentation for clarity. | ||
|
||
- **Libraries**: Take advantage of Ruby and Rails libraries. Many of these functionalities, especially HTTP Signatures, can be tricky to get right. Established libraries often have the benefit of community scrutiny and testing. | ||
|
||
Combining the above approaches will allow you to securely send and verify ActivityPub messages in a Rails context, while also ensuring that the semantics of those messages are correctly understood. |