From f65f10f8c0c45b53013154da22217f8ec1646611 Mon Sep 17 00:00:00 2001 From: pdp8 Date: Fri, 9 Jun 2023 13:15:21 +0200 Subject: archive inbox --- activitypub.rb | 166 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 101 insertions(+), 65 deletions(-) (limited to 'activitypub.rb') diff --git a/activitypub.rb b/activitypub.rb index a340291..ba763e3 100644 --- a/activitypub.rb +++ b/activitypub.rb @@ -1,8 +1,7 @@ # TODO -# delete all/thread -# anchors (return after delete) +# follow request confirmation +# anchors (return after archive) # boost -# archive # federation # client post media # test with pleroma etc @@ -26,13 +25,8 @@ set :session_secret, File.read(".secret").chomp set :default_content_type, 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"' set :port, 9292 -before "/" do - if request.request_method == "POST" - halt 400 unless verify_signature(request.env) - end -end - post "/inbox" do # server-server + verify! request.body.rewind # in case someone already read it body = request.body.read action = JSON.parse body @@ -67,8 +61,9 @@ post "/inbox" do # server-server end end - #else - #p body + else + p "Unknown action: #{action['type']}" + p body end end @@ -116,12 +111,24 @@ post "/outbox" do # client-server recipients.each { |r| send_signed create, r } end +post "/archive/*" do + protected! + FileUtils.mv params['splat'][0], "archive/" + redirect to("/") +end + post "/delete/*" do protected! FileUtils.rm params['splat'][0] redirect to("/") end +post "/delete" do + protected! + FileUtils.rm Dir["inbox/*.json"] + redirect to("/") +end + post "/follow/*" do protected! mention = params['splat'][0] @@ -167,9 +174,60 @@ get "/.well-known/webfinger" do end end +get "/archive", :provides => 'html' do + protected! + dir_html "archive" +end + get "/", :provides => 'html' do protected! - items = Dir['./inbox/*.json'].sort.collect do |file| + dir_html "inbox" +end + +["/outbox","/following","/followers"].each do |path| + get path do + ordered_collection(path).to_json + end +end + +helpers do + + def protected! + redirect("/login.html") unless session['client'] + end + + def verify! + # https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb + # TODO verify digest + signature_params = {} + request.env["HTTP_SIGNATURE"].split(',').each do |pair| + k, v = pair.split('=') + signature_params[k] = v.gsub('"', '') + end + + key_id = signature_params['keyId'] + headers = signature_params['headers'] + signature = Base64.decode64(signature_params['signature']) + + actor = fetch key_id + key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem']) + + comparison = headers.split(' ').map do |signed_params_name| + if signed_params_name == '(request-target)' + '(request-target): post /inbox' + elsif signed_params_name == 'content-type' + "#{signed_params_name}: #{request.env["CONTENT_TYPE"]}" + else + "#{signed_params_name}: #{request.env["HTTP_" + signed_params_name.upcase]}" + end + end.join("\n") + + halt 400 unless key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison) + end +end + +def dir_html dir + items = Dir[File.join(dir, '*.json')].sort.collect do |file| item = JSON.parse(File.read(file)) mention = mention(item['attributedTo']) following_path = File.join('public', 'following', mention + '.json') @@ -185,12 +243,11 @@ get "/", :provides => 'html' do :replies => [] } end.compact - @inbox = [] + threads = [] items.each do |i| if i[:parent].nil? or items.select{|it| it[:id] == i[:parent] }.empty? - @inbox << i + threads << i else - #p i items.select{|it| it[:id] == i[:parent] }.each{|it| it[:replies] << i} end end @@ -199,29 +256,22 @@ get "/", :provides => 'html' do - " - @inbox.each do |item| - html += html(item) + +

#{dir}

+ " + threads.each do |item| + html << item_html(item,dir) end - html+=' - ' - #erb :index + html << " +
+ +
+ + " if dir == "inbox" html end -["/outbox","/following","/followers"].each do |path| - get path do - ordered_collection(path).to_json - end -end - -helpers do - def protected! - redirect("/login.html") unless session['client'] - end -end - -def html item, indent=2 +def item_html item, dir, indent=2 html = "
#{ item[:mention] }  @@ -229,9 +279,22 @@ def html item, indent=2   -
- -
+ " + case dir + when "inbox" + html << " +
+ +
+ " + when "archive" + html << " +
+ +
+ " + end + html << " #{ item[:content].gsub('
','') }" if item[:attachment] item[:attachment].each do |att| @@ -252,7 +315,7 @@ def html item, indent=2 html << "
" item[:replies].each do |r| - html << html(r,indent+4) + html << item_html(r,dir,indent+4) end html @@ -363,33 +426,6 @@ def inbox uri end def verify_signature env - # https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb - # TODO verify digest - #begin - signature_params = {} - env["HTTP_SIGNATURE"].split(',').each do |pair| - k, v = pair.split('=') - signature_params[k] = v.gsub('"', '') - end - - key_id = signature_params['keyId'] - headers = signature_params['headers'] - signature = Base64.decode64(signature_params['signature']) - - actor = fetch key_id - key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem']) - - comparison = headers.split(' ').map do |signed_params_name| - if signed_params_name == '(request-target)' - '(request-target): post /inbox' - elsif signed_params_name == 'content-type' - "#{signed_params_name}: #{env["CONTENT_TYPE"]}" - else - "#{signed_params_name}: #{env["HTTP_" + signed_params_name.upcase]}" - end - end.join("\n") - - key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison) #rescue #false #end -- cgit v1.2.3