diff --git a/.rubocop.yml b/.rubocop.yml
index 01f4f98..f005830 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -8,3 +8,15 @@ Style/StringLiteralsInInterpolation:
Layout/LineLength:
Max: 190
+
+Metrics/BlockLength:
+ Max: 60
+
+Metrics/ParameterLists:
+ Max: 8
+
+Metrics/MethodLength:
+ Max: 13
+
+Metrics/BlockLength:
+ Max: 80
diff --git a/Gemfile b/Gemfile
index baeb205..3eec88f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -9,8 +9,8 @@ gem "pry"
gem "webmock"
-gem "sinatra"
gem "puma"
+gem "sinatra"
gem "rake", "~> 13.0"
diff --git a/activitypub.gemspec b/activitypub.gemspec
index 71123cc..7aa5d55 100644
--- a/activitypub.gemspec
+++ b/activitypub.gemspec
@@ -10,10 +10,10 @@ Gem::Specification.new do |spec|
spec.summary = "A Ruby library for the ActivityPub protocol."
spec.description = "A comprehensive library for building and parsing ActivityPub content in Ruby."
- spec.homepage = "https://github.com/rauversion/activitypub_ruby"
+ spec.homepage = "https://github.com/rauversion/activitypub"
spec.license = "MIT"
- spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0")
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4")
# spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
diff --git a/app.rb b/app.rb
index 4a3fbfa..eeca2c4 100644
--- a/app.rb
+++ b/app.rb
@@ -1,4 +1,6 @@
-require 'sinatra'
+# frozen_string_literal: true
+
+require "sinatra"
require_relative "lib/activitypub"
# For simplicity, we'll hardcode actor_id and generate a keypair on startup
@@ -6,7 +8,7 @@
keypair = ActivityPub::Signature.generate_keypair
outbox = ActivityPub::Outbox.new(actor_id: actor_id, private_key: keypair[:private])
-post '/actors/1/outbox' do
+post "/actors/1/outbox" do
target_inbox_url = params[:inbox_url] # expect the client to provide target inbox URL
activity_data = params[:activity_data] # and the activity data
@@ -14,9 +16,9 @@
[response.code.to_i, response.body]
end
-post '/actors/1/inbox' do
+post "/actors/1/inbox" do
# This is where other actors would send activities to our actor
- incoming_activity = JSON.parse(params['incoming_activity']) # JSON.parse(request.body.read)
+ incoming_activity = JSON.parse(params["incoming_activity"]) # JSON.parse(request.body.read)
# For demonstration purposes, we'll just print the activity to the console
puts "Received activity: #{incoming_activity}"
@@ -25,7 +27,7 @@
[200, "Activity received"]
end
-get '/' do
+get "/" do
%(
"ActivityPub Sinatra Example"
Send an Activity to Outbox
diff --git a/lib/activitypub.rb b/lib/activitypub.rb
index e2ffa96..7ec03f0 100644
--- a/lib/activitypub.rb
+++ b/lib/activitypub.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
require "json"
-require 'time'
-require 'base64'
+require "time"
+require "base64"
require_relative "activitypub/version"
require_relative "activitypub/activity"
require_relative "activitypub/object"
diff --git a/lib/activitypub/activity.rb b/lib/activitypub/activity.rb
index 0adfa75..518e743 100644
--- a/lib/activitypub/activity.rb
+++ b/lib/activitypub/activity.rb
@@ -1,4 +1,10 @@
+# frozen_string_literal: true
+
module ActivityPub
+ # The Activity class represents a specific action or event in the ActivityPub protocol.
+ # It encapsulates details of the action being taken and any associated metadata.
+ # This class provides methods for creating, validating, and processing activities
+ # in accordance with the ActivityPub standard.
class Activity
# The type of the activity, e.g., 'Create', 'Like', 'Follow', etc.
attr_accessor :type
@@ -26,7 +32,7 @@ def initialize(type:, actor:, object:, **other_attributes)
# Convert the activity into a hash representation.
def to_h
{
- '@context': 'https://www.w3.org/ns/activitystreams',
+ '@context': "https://www.w3.org/ns/activitystreams",
type: @type,
actor: @actor,
object: @object
@@ -43,9 +49,9 @@ def to_json(*args)
# Load an activity from a hash.
def self.from_h(hash)
new(
- type: hash['type'],
- actor: hash['actor'],
- object: hash['object']
+ type: hash["type"],
+ actor: hash["actor"],
+ object: hash["object"]
# Handle any other attributes as needed.
# ...
)
diff --git a/lib/activitypub/actor.rb b/lib/activitypub/actor.rb
index 16df718..bb2d5f6 100644
--- a/lib/activitypub/actor.rb
+++ b/lib/activitypub/actor.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# The ActivityPub::Actor represents individual and
# collective entities which perform activities.
# Commonly used actor types include Person, Organization,
@@ -7,10 +9,15 @@
# Here's a basic representation for the ActivityPub::Actor:
module ActivityPub
+ # The Actor class represents participants in the ActivityPub network.
+ # An Actor can be an individual user, a group, a service, or any other entity
+ # that performs actions on the network. This class handles details related to
+ # actor identity, public keys, endpoints, and other metadata essential for
+ # secure and accurate communication within the ActivityPub protocol.
class Actor
attr_accessor :id, :type, :name, :preferred_username, :inbox, :outbox, :followers, :following
- def initialize(id:, type: 'Person', name:, preferred_username:, inbox:, outbox:, followers: nil, following: nil)
+ def initialize(id:, type: "Person", name:, preferred_username:, inbox:, outbox:, followers: nil, following: nil)
@id = id
@type = type
@name = name
@@ -23,7 +30,7 @@ def initialize(id:, type: 'Person', name:, preferred_username:, inbox:, outbox:,
def to_h
{
- '@context': 'https://www.w3.org/ns/activitystreams',
+ '@context': "https://www.w3.org/ns/activitystreams",
id: @id,
type: @type,
name: @name,
@@ -41,14 +48,14 @@ def to_json(*args)
def self.from_h(hash)
new(
- id: hash['id'],
- type: hash['type'] || 'Person',
- name: hash['name'],
- preferred_username: hash['preferredUsername'],
- inbox: hash['inbox'],
- outbox: hash['outbox'],
- followers: hash['followers'],
- following: hash['following']
+ id: hash["id"],
+ type: hash["type"] || "Person",
+ name: hash["name"],
+ preferred_username: hash["preferredUsername"],
+ inbox: hash["inbox"],
+ outbox: hash["outbox"],
+ followers: hash["followers"],
+ following: hash["following"]
)
end
end
diff --git a/lib/activitypub/inbox.rb b/lib/activitypub/inbox.rb
index a8a13a7..36bc6a2 100644
--- a/lib/activitypub/inbox.rb
+++ b/lib/activitypub/inbox.rb
@@ -1,7 +1,12 @@
-require 'net/http'
-require 'json'
+# frozen_string_literal: true
+
+require "net/http"
+require "json"
module ActivityPub
+ # The Inbox class manages the reception of activities from other actors.
+ # It is responsible for validating incoming activities, verifying signatures,
+ # and processing or storing them as needed in the context of the ActivityPub protocol.
class Inbox
attr_reader :actor_id
@@ -17,9 +22,7 @@ def accept_activity(activity_data, headers)
signature = headers["Signature"]
# Verify the activity's signature
- unless ActivityPub::Signature.verify?(activity_data, signature, public_key)
- raise "Invalid signature"
- end
+ raise "Invalid signature" unless ActivityPub::Signature.verify?(activity_data, signature, public_key)
# Process activity
process_activity(activity_data)
@@ -35,7 +38,7 @@ def fetch_actor_public_key(actor_id)
# This assumes the public key is stored under a 'publicKey' key in the actor's profile.
# This structure may vary based on the implementation details of the server hosting the actor's profile.
- profile['publicKey']['publicKeyPem']
+ profile["publicKey"]["publicKeyPem"]
end
def process_activity(activity_data)
diff --git a/lib/activitypub/object.rb b/lib/activitypub/object.rb
index 41a93f7..41e96fe 100644
--- a/lib/activitypub/object.rb
+++ b/lib/activitypub/object.rb
@@ -1,8 +1,13 @@
+# frozen_string_literal: true
+
module ActivityPub
+ # The Object class represents the primary data structure of the ActivityPub protocol.
+ # It provides a foundational element from which specific ActivityPub types (like "Note" or "Event") derive.
+ # This class facilitates the creation, validation, and manipulation of ActivityPub objects.
class Object
attr_accessor :id, :type, :published, :updated, :content, :attributed_to
- def initialize(id:, type: 'Object', published: nil, updated: nil, content: nil, attributed_to: nil)
+ def initialize(id:, type: "Object", published: nil, updated: nil, content: nil, attributed_to: nil)
@id = id
@type = type
@published = published || Time.now.utc.iso8601
@@ -13,7 +18,7 @@ def initialize(id:, type: 'Object', published: nil, updated: nil, content: nil,
def to_h
{
- '@context': 'https://www.w3.org/ns/activitystreams',
+ '@context': "https://www.w3.org/ns/activitystreams",
id: @id,
type: @type,
published: @published,
@@ -29,22 +34,20 @@ def to_json(*args)
def self.from_h(hash)
new(
- id: hash['id'],
- type: hash['type'] || 'Object',
- published: hash['published'],
- updated: hash['updated'],
- content: hash['content'],
- attributed_to: hash['attributedTo']
+ id: hash["id"],
+ type: hash["type"] || "Object",
+ published: hash["published"],
+ updated: hash["updated"],
+ content: hash["content"],
+ attributed_to: hash["attributedTo"]
)
end
end
end
-=begin
- obj = ActivityPub::Object.new(id: 'https://example.com/objects/1', content: 'Hello world!')
-puts obj.to_json
-
-loaded_obj = ActivityPub::Object.from_h(JSON.parse(obj.to_json))
-puts loaded_obj.content # => "Hello world!"
-
-=end
+# obj = ActivityPub::Object.new(id: 'https://example.com/objects/1', content: 'Hello world!')
+# puts obj.to_json
+#
+# loaded_obj = ActivityPub::Object.from_h(JSON.parse(obj.to_json))
+# puts loaded_obj.content # => "Hello world!"
+#
diff --git a/lib/activitypub/outbox.rb b/lib/activitypub/outbox.rb
index 7486c56..b629ada 100644
--- a/lib/activitypub/outbox.rb
+++ b/lib/activitypub/outbox.rb
@@ -1,6 +1,12 @@
-require 'net/http'
+# frozen_string_literal: true
+
+require "net/http"
module ActivityPub
+ # The Outbox class is responsible for sending activities to other actors.
+ # It wraps the process of preparing an activity, signing it, and then delivering it to
+ # the recipient's inbox. This ensures that messages sent via ActivityPub are
+ # authenticated and securely delivered.
class Outbox
attr_reader :actor_id, :private_key
@@ -28,7 +34,7 @@ def send_activity(target_inbox_url, activity_data)
def post_activity(inbox_url, activity_data, signature)
uri = URI(inbox_url)
http = Net::HTTP.new(uri.host, uri.port)
- request = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/ld+json', 'Signature' => signature })
+ request = Net::HTTP::Post.new(uri.path, { "Content-Type" => "application/ld+json", "Signature" => signature })
request.body = activity_data
http.request(request)
end
diff --git a/lib/activitypub/signature.rb b/lib/activitypub/signature.rb
index b05bfee..3625205 100644
--- a/lib/activitypub/signature.rb
+++ b/lib/activitypub/signature.rb
@@ -1,4 +1,6 @@
-require 'openssl'
+# frozen_string_literal: true
+
+require "openssl"
# Digital signatures are essential in federated networks
# like ActivityPub to ensure data integrity and authenticity.
@@ -6,6 +8,9 @@
# in the ActivityPub community is the RSA-SHA256 algorithm.
module ActivityPub
+ # This class handles the generation and verification of ActivityPub signatures.
+ # It ensures that outgoing messages are authenticated and incoming messages
+ # are verified against a known public key.
class Signature
# Generates a new RSA private and public key pair
def self.generate_keypair
@@ -17,7 +22,7 @@ def self.generate_keypair
def self.sign(data, private_key_pem)
private_key = OpenSSL::PKey::RSA.new(private_key_pem)
signature = private_key.sign(OpenSSL::Digest::SHA256.new, data)
- Base64.encode64(signature).gsub("\n", '')
+ Base64.encode64(signature).gsub("\n", "")
end
# Verifies the signature with the provided public key
diff --git a/spec/activity_spec.rb b/spec/activity_spec.rb
index 1ec5d4d..7aa5e40 100644
--- a/spec/activity_spec.rb
+++ b/spec/activity_spec.rb
@@ -1,36 +1,38 @@
+# frozen_string_literal: true
+
RSpec.describe ActivityPub::Activity do
- describe '#initialize' do
- subject { described_class.new(type: 'Like', actor: 'https://example.com/users/alice', object: 'https://example.com/posts/1') }
+ describe "#initialize" do
+ subject { described_class.new(type: "Like", actor: "https://example.com/users/alice", object: "https://example.com/posts/1") }
- it 'initializes with given attributes' do
- expect(subject.type).to eq('Like')
- expect(subject.actor).to eq('https://example.com/users/alice')
- expect(subject.object).to eq('https://example.com/posts/1')
+ it "initializes with given attributes" do
+ expect(subject.type).to eq("Like")
+ expect(subject.actor).to eq("https://example.com/users/alice")
+ expect(subject.object).to eq("https://example.com/posts/1")
end
end
- describe '#to_json' do
- subject { described_class.new(type: 'Like', actor: 'https://example.com/users/alice', object: 'https://example.com/posts/1') }
+ describe "#to_json" do
+ subject { described_class.new(type: "Like", actor: "https://example.com/users/alice", object: "https://example.com/posts/1") }
- it 'converts the activity to a JSON representation' do
+ it "converts the activity to a JSON representation" do
json_output = subject.to_json
parsed_output = JSON.parse(json_output)
- expect(parsed_output['type']).to eq('Like')
- expect(parsed_output['actor']).to eq('https://example.com/users/alice')
- expect(parsed_output['object']).to eq('https://example.com/posts/1')
+ expect(parsed_output["type"]).to eq("Like")
+ expect(parsed_output["actor"]).to eq("https://example.com/users/alice")
+ expect(parsed_output["object"]).to eq("https://example.com/posts/1")
end
end
- describe '.from_h' do
- let(:activity_hash) { { 'type' => 'Like', 'actor' => 'https://example.com/users/alice', 'object' => 'https://example.com/posts/1' } }
+ describe ".from_h" do
+ let(:activity_hash) { { "type" => "Like", "actor" => "https://example.com/users/alice", "object" => "https://example.com/posts/1" } }
- it 'loads an activity from a hash' do
+ it "loads an activity from a hash" do
activity = described_class.from_h(activity_hash)
- expect(activity.type).to eq('Like')
- expect(activity.actor).to eq('https://example.com/users/alice')
- expect(activity.object).to eq('https://example.com/posts/1')
+ expect(activity.type).to eq("Like")
+ expect(activity.actor).to eq("https://example.com/users/alice")
+ expect(activity.object).to eq("https://example.com/posts/1")
end
end
end
diff --git a/spec/actor_spec.rb b/spec/actor_spec.rb
index 4e0cd5d..9e0ddc6 100644
--- a/spec/actor_spec.rb
+++ b/spec/actor_spec.rb
@@ -1,70 +1,72 @@
+# frozen_string_literal: true
+
RSpec.describe ActivityPub::Actor do
- describe '#initialize' do
+ describe "#initialize" do
subject do
described_class.new(
- id: 'https://example.com/users/alice',
- name: 'Alice',
- preferred_username: 'alice',
- inbox: 'https://example.com/users/alice/inbox',
- outbox: 'https://example.com/users/alice/outbox'
+ id: "https://example.com/users/alice",
+ name: "Alice",
+ preferred_username: "alice",
+ inbox: "https://example.com/users/alice/inbox",
+ outbox: "https://example.com/users/alice/outbox"
)
end
- it 'initializes with given attributes' do
- expect(subject.id).to eq('https://example.com/users/alice')
- expect(subject.type).to eq('Person')
- expect(subject.name).to eq('Alice')
- expect(subject.preferred_username).to eq('alice')
- expect(subject.inbox).to eq('https://example.com/users/alice/inbox')
- expect(subject.outbox).to eq('https://example.com/users/alice/outbox')
+ it "initializes with given attributes" do
+ expect(subject.id).to eq("https://example.com/users/alice")
+ expect(subject.type).to eq("Person")
+ expect(subject.name).to eq("Alice")
+ expect(subject.preferred_username).to eq("alice")
+ expect(subject.inbox).to eq("https://example.com/users/alice/inbox")
+ expect(subject.outbox).to eq("https://example.com/users/alice/outbox")
end
end
- describe '#to_json' do
+ describe "#to_json" do
subject do
described_class.new(
- id: 'https://example.com/users/alice',
- name: 'Alice',
- preferred_username: 'alice',
- inbox: 'https://example.com/users/alice/inbox',
- outbox: 'https://example.com/users/alice/outbox'
+ id: "https://example.com/users/alice",
+ name: "Alice",
+ preferred_username: "alice",
+ inbox: "https://example.com/users/alice/inbox",
+ outbox: "https://example.com/users/alice/outbox"
)
end
- it 'converts the actor to a JSON representation' do
+ it "converts the actor to a JSON representation" do
json_output = subject.to_json
parsed_output = JSON.parse(json_output)
- expect(parsed_output['id']).to eq('https://example.com/users/alice')
- expect(parsed_output['type']).to eq('Person')
- expect(parsed_output['name']).to eq('Alice')
- expect(parsed_output['preferredUsername']).to eq('alice')
- expect(parsed_output['inbox']).to eq('https://example.com/users/alice/inbox')
- expect(parsed_output['outbox']).to eq('https://example.com/users/alice/outbox')
+ expect(parsed_output["id"]).to eq("https://example.com/users/alice")
+ expect(parsed_output["type"]).to eq("Person")
+ expect(parsed_output["name"]).to eq("Alice")
+ expect(parsed_output["preferredUsername"]).to eq("alice")
+ expect(parsed_output["inbox"]).to eq("https://example.com/users/alice/inbox")
+ expect(parsed_output["outbox"]).to eq("https://example.com/users/alice/outbox")
end
end
- describe '.from_h' do
+ describe ".from_h" do
let(:actor_hash) do
{
- 'id' => 'https://example.com/users/alice',
- 'type' => 'Person',
- 'name' => 'Alice',
- 'preferredUsername' => 'alice',
- 'inbox' => 'https://example.com/users/alice/inbox',
- 'outbox' => 'https://example.com/users/alice/outbox'
+ "id" => "https://example.com/users/alice",
+ "type" => "Person",
+ "name" => "Alice",
+ "preferredUsername" => "alice",
+ "inbox" => "https://example.com/users/alice/inbox",
+ "outbox" => "https://example.com/users/alice/outbox"
}
end
- it 'loads an actor from a hash' do
+ it "loads an actor from a hash" do
actor = described_class.from_h(actor_hash)
- expect(actor.id).to eq('https://example.com/users/alice')
- expect(actor.type).to eq('Person')
- expect(actor.name).to eq('Alice')
- expect(actor.preferred_username).to eq('alice')
- expect(actor.inbox).to eq('https://example.com/users/alice/inbox')
- expect(actor.outbox).to eq('https://example.com/users/alice/outbox')
+ expect(actor.id).to eq("https://example.com/users/alice")
+ expect(actor.type).to eq("Person")
+ expect(actor.name).to eq("Alice")
+ expect(actor.preferred_username).to eq("alice")
+ expect(actor.inbox).to eq("https://example.com/users/alice/inbox")
+ expect(actor.outbox).to eq("https://example.com/users/alice/outbox")
end
end
end
diff --git a/spec/inbox_spec.rb b/spec/inbox_spec.rb
index 6c64374..d74bd9a 100644
--- a/spec/inbox_spec.rb
+++ b/spec/inbox_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# spec/activitypub/inbox_spec.rb
RSpec.describe ActivityPub::Inbox do
@@ -22,12 +24,12 @@
allow(Net::HTTP).to receive(:get).with(URI(actor_id)).and_return(public_key_response)
end
- describe '#accept_activity' do
- it 'accepts and processes a valid activity' do
+ describe "#accept_activity" do
+ it "accepts and processes a valid activity" do
expect { subject.accept_activity(activity_data, headers) }.not_to raise_error
end
- it 'raises an error for an activity with an invalid signature' do
+ it "raises an error for an activity with an invalid signature" do
tampered_headers = headers.merge("Signature" => "INVALID_SIGNATURE")
expect { subject.accept_activity(activity_data, tampered_headers) }.to raise_error("Invalid signature")
diff --git a/spec/object_spec.rb b/spec/object_spec.rb
index 58d8abb..8f59281 100644
--- a/spec/object_spec.rb
+++ b/spec/object_spec.rb
@@ -1,44 +1,46 @@
+# frozen_string_literal: true
+
# spec/activitypub/object_spec.rb
RSpec.describe ActivityPub::Object do
let(:current_time) { Time.now.utc.iso8601 }
- describe '#initialize' do
- subject { described_class.new(id: 'https://example.com/objects/1', content: 'Hello world!') }
+ describe "#initialize" do
+ subject { described_class.new(id: "https://example.com/objects/1", content: "Hello world!") }
- it 'initializes with given attributes' do
- expect(subject.id).to eq('https://example.com/objects/1')
- expect(subject.type).to eq('Object')
- expect(subject.content).to eq('Hello world!')
+ it "initializes with given attributes" do
+ expect(subject.id).to eq("https://example.com/objects/1")
+ expect(subject.type).to eq("Object")
+ expect(subject.content).to eq("Hello world!")
expect(subject.published).to be_a(String) # Checking if it's a formatted string for simplicity. In a real-world scenario, you might want to parse and validate.
expect(subject.updated).to be_a(String)
end
end
- describe '#to_json' do
- subject { described_class.new(id: 'https://example.com/objects/1', content: 'Hello world!', published: current_time, updated: current_time) }
+ describe "#to_json" do
+ subject { described_class.new(id: "https://example.com/objects/1", content: "Hello world!", published: current_time, updated: current_time) }
- it 'converts the object to a JSON representation' do
+ it "converts the object to a JSON representation" do
json_output = subject.to_json
parsed_output = JSON.parse(json_output)
- expect(parsed_output['id']).to eq('https://example.com/objects/1')
- expect(parsed_output['type']).to eq('Object')
- expect(parsed_output['content']).to eq('Hello world!')
- expect(parsed_output['published']).to eq(current_time)
- expect(parsed_output['updated']).to eq(current_time)
+ expect(parsed_output["id"]).to eq("https://example.com/objects/1")
+ expect(parsed_output["type"]).to eq("Object")
+ expect(parsed_output["content"]).to eq("Hello world!")
+ expect(parsed_output["published"]).to eq(current_time)
+ expect(parsed_output["updated"]).to eq(current_time)
end
end
- describe '.from_h' do
- let(:object_hash) { { 'id' => 'https://example.com/objects/1', 'type' => 'Object', 'content' => 'Hello world!', 'published' => current_time, 'updated' => current_time } }
+ describe ".from_h" do
+ let(:object_hash) { { "id" => "https://example.com/objects/1", "type" => "Object", "content" => "Hello world!", "published" => current_time, "updated" => current_time } }
- it 'loads an object from a hash' do
+ it "loads an object from a hash" do
obj = described_class.from_h(object_hash)
- expect(obj.id).to eq('https://example.com/objects/1')
- expect(obj.type).to eq('Object')
- expect(obj.content).to eq('Hello world!')
+ expect(obj.id).to eq("https://example.com/objects/1")
+ expect(obj.type).to eq("Object")
+ expect(obj.content).to eq("Hello world!")
expect(obj.published).to eq(current_time)
expect(obj.updated).to eq(current_time)
end
diff --git a/spec/outbox_spec.rb b/spec/outbox_spec.rb
index 80c29f1..a983062 100644
--- a/spec/outbox_spec.rb
+++ b/spec/outbox_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# spec/activitypub/outbox_spec.rb
RSpec.describe ActivityPub::Outbox do
@@ -14,18 +16,18 @@
.with(
body: activity_data,
headers: {
- 'Accept' => '*/*',
- 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
- 'Content-Type' => 'application/ld+json',
- 'User-Agent' => 'Ruby',
- 'Signature' => ActivityPub::Signature.sign(activity_data, keypair[:private])
+ "Accept" => "*/*",
+ "Accept-Encoding" => "gzip;q=1.0,deflate;q=0.6,identity;q=0.3",
+ "Content-Type" => "application/ld+json",
+ "User-Agent" => "Ruby",
+ "Signature" => ActivityPub::Signature.sign(activity_data, keypair[:private])
}
)
.to_return(status: 200, body: "", headers: {})
end
- describe '#send_activity' do
- it 'sends the activity to the target inbox' do
+ describe "#send_activity" do
+ it "sends the activity to the target inbox" do
response = subject.send_activity(inbox_url, activity_data)
expect(response.code).to eq("200")
end
diff --git a/spec/signature_spec.rb b/spec/signature_spec.rb
index bfdcb4b..2978722 100644
--- a/spec/signature_spec.rb
+++ b/spec/signature_spec.rb
@@ -1,34 +1,36 @@
+# frozen_string_literal: true
+
# spec/activitypub/signature_spec.rb
RSpec.describe ActivityPub::Signature do
let(:keypair) { described_class.generate_keypair }
let(:data) { "Important data that needs to be signed" }
- describe '.generate_keypair' do
- it 'generates a valid RSA key pair' do
+ describe ".generate_keypair" do
+ it "generates a valid RSA key pair" do
expect(keypair[:private]).to be_a(String)
expect(keypair[:public]).to be_a(String)
end
end
- describe '.sign' do
+ describe ".sign" do
let(:signature) { described_class.sign(data, keypair[:private]) }
- it 'signs data using a private key' do
+ it "signs data using a private key" do
expect(signature).to be_a(String)
# Note: In a real-world scenario, you'd have more comprehensive checks
# or perhaps try verifying the signature as a test.
end
end
- describe '.verify?' do
+ describe ".verify?" do
let(:signature) { described_class.sign(data, keypair[:private]) }
- it 'verifies the signed data with the correct public key' do
+ it "verifies the signed data with the correct public key" do
expect(described_class.verify?(data, signature, keypair[:public])).to be_truthy
end
- it 'returns false for incorrect data' do
+ it "returns false for incorrect data" do
expect(described_class.verify?("Tampered data", signature, keypair[:public])).to be_falsey
end
end