diff options
author | pdp8 <pdp8@pdp8.info> | 2023-06-09 13:15:21 +0200 |
---|---|---|
committer | pdp8 <pdp8@pdp8.info> | 2023-06-09 13:15:21 +0200 |
commit | f65f10f8c0c45b53013154da22217f8ec1646611 (patch) | |
tree | 3d421bfcc39e554951ae0265bfc00febaeedc8cf | |
parent | e13839321f5b1dd1106a00cd3f93259bdf1ca8c6 (diff) |
archive inbox
-rw-r--r-- | activitypub.rb | 166 | ||||
-rw-r--r-- | views/index.erb | 12 |
2 files changed, 101 insertions, 77 deletions
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 <head> <link rel='stylesheet' type='text/css' href='/style.css'> </head> - <body>" - @inbox.each do |item| - html += html(item) + <body> + <h1>#{dir}</h1> + " + threads.each do |item| + html << item_html(item,dir) end - html+=' </body> - </html>' - #erb :index + html << " + <form action='delete' method='post'> + <button>Delete all</button> + </form> + </body> + </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 = " <div style='margin-left:#{indent}em'> <b><a href='#{ item[:actor_url] }', target='_blank'>#{ item[:mention] }</a></b> @@ -229,9 +279,22 @@ def html item, indent=2 <button>#{ item[:follow].capitalize }</button> </form> - <form action='#{ File.join 'delete', item[:file] }' method='post'> - <button>Delete</button> - </form> + " + case dir + when "inbox" + html << " + <form action='#{ File.join 'archive', item[:file] }' method='post'> + <button>Archive</button> + </form> + " + when "archive" + html << " + <form action='#{ File.join 'delete', item[:file] }' method='post'> + <button>Delete</button> + </form> + " + end + html << " #{ item[:content].gsub('<br />','') }" if item[:attachment] item[:attachment].each do |att| @@ -252,7 +315,7 @@ def html item, indent=2 html << " </div>" 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 diff --git a/views/index.erb b/views/index.erb deleted file mode 100644 index 3a245a9..0000000 --- a/views/index.erb +++ /dev/null @@ -1,12 +0,0 @@ - <!DOCTYPE html> - <html lang='en'> - <head> - <link rel='stylesheet' type='text/css' href='/style.css'> - </head> - <body> - <% @inbox.each do |item| %> - <%= erb :item %> - <hr> - <% end %> - </body> - </html> |