summaryrefslogtreecommitdiff
path: root/server.rb
diff options
context:
space:
mode:
Diffstat (limited to 'server.rb')
-rw-r--r--server.rb86
1 files changed, 57 insertions, 29 deletions
diff --git a/server.rb b/server.rb
index 49204a3..f7e9b82 100644
--- a/server.rb
+++ b/server.rb
@@ -11,14 +11,11 @@ post '/inbox' do
p @body
halt 400
end
+ halt 501 if @activity['actor'] and @activity['type'] == 'Delete' # deleted actors return 403 => verification error
+ verify! # unless type == :accept # pixelfed sends unsigned accept activities???
+ complete_and_save(@activity)
type = @activity['type'].downcase.to_sym
- p type
- halt 501 unless respond_to?(type)
- @object = @activity['object']
- @object = fetch(@object) if @object.is_a?(String) && @object.match(/^http/)
- halt 400 unless @object
- verify! unless type == :accept # pixelfed sends unsigned accept activities???
- send(type)
+ send(type) if %i[follow accept undo].include? type
halt 200
end
@@ -28,43 +25,30 @@ get '/.well-known/webfinger' do
send_file(WEBFINGER, type: 'application/jrd+json')
end
-['/pdp8', '/following', '/followers', '/outbox', '/shared'].each do |path|
+get '/pdp8' do
+ send_file(File.join(PUBLIC_DIR, 'pdp8.json'), type: CONTENT_TYPE)
+end
+
+['/following', '/followers'].each do |path|
get path do
send_file(File.join(PUBLIC_DIR, path) + '.json', type: CONTENT_TYPE)
end
end
helpers do
- def create
- return unless @object
-
- # return if File.readlines(VISITED).collect { |l| l.chomp }.include? @object['id']
-
- # File.open(VISITED, 'a+') { |f| f.puts @object['id'] }
- update_collection INBOX, @object
- return unless @object['inReplyTo']
-
- @object = fetch @object['inReplyTo']
- create if @object
- end
-
- def announce
- create
- end
-
def follow
update_collection FOLLOWERS, @activity['actor']
outbox 'Accept', @activity, [@activity['actor']]
end
def accept
- halt 501 unless @object['type'] == 'Follow'
- update_collection FOLLOWING, @object['object']
+ halt 501 unless @activity['object']['type'] == 'Follow'
+ update_collection FOLLOWING, @activity['object']['object']
end
def undo
- halt 501 unless @object['type'] == 'Follow'
- update_collection FOLLOWERS, @object['actor'], true
+ halt 501 unless @activity['object']['type'] == 'Follow'
+ update_collection FOLLOWERS, @activity['object']['actor'], true
end
# https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb
@@ -102,4 +86,48 @@ helpers do
halt 403 unless key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
end
+
+ def outbox(type, object, recipients)
+ # add date and id, save
+ activity = complete_and_save({
+ '@context' => 'https://www.w3.org/ns/activitystreams',
+ 'type' => type,
+ 'actor' => ACTOR,
+ 'object' => object,
+ 'to' => recipients
+ })
+
+ # send
+ # https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb
+ keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'))
+ body = activity.to_json
+ sha256 = OpenSSL::Digest.new('SHA256')
+ digest = "SHA-256=#{sha256.base64digest(body)}"
+
+ inboxes = []
+ recipients.uniq.each do |url|
+ next if [ACTOR, 'https://www.w3.org/ns/activitystreams#Public'].include? url
+
+ actor = fetch url
+ next unless actor
+
+ if actor['endpoints'] and actor['endpoints']['sharedInbox']
+ inboxes << actor['endpoints']['sharedInbox']
+ elsif actor['inbox']
+ inboxes << actor['inbox']
+ end
+ end
+
+ inboxes.compact.uniq.each do |inbox|
+ uri = URI(inbox)
+ string = "(request-target): post #{uri.request_uri}\nhost: #{uri.host}\ndate: #{httpdate}\ndigest: #{digest}\ncontent-type: application/activity+json"
+ signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), string))
+ signed_header = "keyId=\"#{ACTOR}#main-key\",algorithm=\"rsa-sha256\",headers=\"(request-target) host date digest content-type\",signature=\"#{signature}\""
+
+ curl(
+ "-X POST -H 'Content-Type: application/activity+json' -H 'Host: #{uri.host}' -H 'Date: #{httpdate}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}'", inbox
+ )
+ end
+ activity
+ end
end