summary refs log tree commit diff
diff options
context:
space:
mode:
authorpdp8 <pdp8@pdp8.info>2023-06-09 13:15:21 +0200
committerpdp8 <pdp8@pdp8.info>2023-06-09 13:15:21 +0200
commitf65f10f8c0c45b53013154da22217f8ec1646611 (patch)
tree3d421bfcc39e554951ae0265bfc00febaeedc8cf
parente13839321f5b1dd1106a00cd3f93259bdf1ca8c6 (diff)
archive inbox
-rw-r--r--activitypub.rb166
-rw-r--r--views/index.erb12
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>&nbsp;
@@ -229,9 +279,22 @@ def html item, indent=2
     <button>#{ item[:follow].capitalize }</button>
   </form>
   &nbsp;
-  <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>