From 711bf7f86daddd0209244f9640d8a3f27d958e3a Mon Sep 17 00:00:00 2001 From: pdp8 Date: Fri, 21 Jul 2023 00:52:49 +0200 Subject: inbox and outbox unified --- server.rb | 86 ++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 29 deletions(-) (limited to 'server.rb') 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 -- cgit v1.2.3