summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client.rb45
-rw-r--r--helpers.rb77
-rw-r--r--server.rb73
-rw-r--r--views/item.erb15
4 files changed, 118 insertions, 92 deletions
diff --git a/client.rb b/client.rb
index 512c1d3..759fdec 100644
--- a/client.rb
+++ b/client.rb
@@ -2,11 +2,19 @@
post "/outbox" do
protected!
request.body.rewind # in case someone already read it
- body = request.body.read
+ #body = request.body.read
date = Time.now.strftime("%Y-%m-%dT%H:%M:%S")
# TODO hashtags, replys
outbox_path = File.join("public/outbox", date + ".json")
object_path = File.join("public/objects", date + ".json")
+
+ #recipients = ["https://www.w3.org/ns/activitystreams#Public", params[:to]]
+ recipients = [params[:to]]
+ #recipients += Dir[File.join("public/followers", "*.json")].collect { |f| JSON.parse(File.read(f))["actor"] }
+ recipients.delete ACTOR
+ recipients.uniq!
+
+ p params
create = {
"@context" => "https://www.w3.org/ns/activitystreams",
"id" => File.join(SOCIAL_URL, outbox_path),
@@ -16,31 +24,34 @@ post "/outbox" do
"id" => File.join(SOCIAL_URL, object_path),
"type" => "Note",
"attributedTo" => ACTOR,
+ "inReplyTo" => params[:inReplyTo],
"published" => date,
- "content" => "",
- "to" => ["https://www.w3.org/ns/activitystreams#Public"]
+ "content" => params[:content],
+ "to" => recipients
},
"published" => date,
- "to" => ["https://www.w3.org/ns/activitystreams#Public"]
+ "to" => recipients
}
- recipients = []
+=begin
if /^@/.match body
mentions, body = body.split("\n", 2)
mentions.split(/, */).each do |m|
recipients << actor(m.chomp)
end
end
- create["object"]["content"] = body.lines.select { |l| !l.empty? }.join("<br>")
- recipients += Dir[File.join("public/followers", "*.json")].collect { |f| JSON.parse(File.read(f))["actor"] }
- recipients.delete ACTOR
- recipients.uniq!
- create["object"]["to"] += recipients
- create["to"] += recipients
+=end
+ #create["object"]["content"] = body#.lines.select { |l| !l.empty? }.join("<br>")
+ #create["object"]["to"] += recipients
+ #create["to"] += recipients
+ #p params["to"]
+ p create
File.open(outbox_path, "w+") { |f| f.puts create.to_json }
File.open(object_path, "w+") { |f| f.puts create["object"].to_json }
- recipients.each { |r| send_signed create, r }
+ #p recipients
+ create["to"].each { |r| send_signed create, r }
+ redirect to(params['redirect'])
end
post "/archive" do
@@ -65,8 +76,6 @@ post "/follow/*" do
protected!
mention = params['splat'][0]
actor = actor(mention)
- p mention
- p actor
follow = { "@context" => "https://www.w3.org/ns/activitystreams",
"id" => File.join(SOCIAL_URL, "following", mention + ".json"),
"type" => "Follow",
@@ -115,3 +124,11 @@ end
erb :index
end
end
+
+helpers do
+
+ def protected!
+ redirect("/login.html") unless session['client']
+ end
+
+end
diff --git a/helpers.rb b/helpers.rb
index 8774f74..50a2b24 100644
--- a/helpers.rb
+++ b/helpers.rb
@@ -1,43 +1,5 @@
helpers do
- def protected!
- redirect("/login.html") unless session['client']
- end
-
- # https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb
- def verify!
- # TODO verify digest
- begin
- 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)
- rescue => e
- p request.env["HTTP_SIGNATURE"], e
- halt 400
- end
- end
-
def items
nr = 0
@items = Dir[File.join(@dir, '*.json')].sort.collect do |file|
@@ -82,30 +44,6 @@ helpers do
erb :item
end
- def delete object
- Dir["inbox/*.json"].each do |doc|
- FileUtils.rm doc if JSON.parse(File.read(doc))["id"] == object["id"]
- end
- end
-
- def create object
- unless object['type'] == 'Person'
- doc = File.join("inbox", "#{Time.now.strftime('%Y-%m-%dT%H:%M:%S.%N')}.json")
- File.open(doc, "w+") { |f| f.puts object.to_json }
- if object['inReplyTo']
- @dir = 'inbox'
- items
- if @items.select{|it| it[:id] == object['inReplyTo'] }.empty?
- download object['inReplyTo']
- end
- end
- end
- end
-
- def download object_url
- create fetch(object_url)
- end
-
def people
File.read('cache/people.tsv').split("\n").collect {|l| l.chomp.split("\t")}
end
@@ -144,17 +82,6 @@ helpers do
JSON.parse(response)
end
- def ordered_collection dir
- posts = Dir[File.join("public",dir, "*.json")].collect { |f| JSON.parse(File.read f) }.sort_by { |o| o["published"] }
- {
- "@context" => "https://www.w3.org/ns/activitystreams",
- "summary" => "#{USER} #{dir}",
- "type" => "OrderedCollection",
- "totalItems" => posts.size,
- "orderedItems" => posts,
- }
- end
-
# https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb
def send_signed object, url
@@ -171,7 +98,9 @@ helpers do
signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string))
signed_header = 'keyId="' + ACTOR + '#main-key",algorithm="rsa-sha256",headers="(request-target) host date digest content-type",signature="' + signature + '"'
- puts `/run/current-system/sw/bin/curl --fail-with-body -sSL -X POST -H 'Content-Type: application/activity+json' -H 'Host: #{host}' -H 'Date: #{date}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}' #{inbox}`
+ p url
+ #puts `/run/current-system/sw/bin/curl --fail-with-body -sSL -X POST -H 'Content-Type: application/activity+json' -H 'Host: #{host}' -H 'Date: #{date}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}' #{inbox}`
+ puts `/run/current-system/sw/bin/curl -iL -X POST -H 'Content-Type: application/activity+json' -H 'Host: #{host}' -H 'Date: #{date}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}' #{inbox}`
end
end
diff --git a/server.rb b/server.rb
index 13153b8..b5076f3 100644
--- a/server.rb
+++ b/server.rb
@@ -74,3 +74,76 @@ end
ordered_collection(path).to_json
end
end
+
+helpers do
+
+ # https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb
+ def verify!
+ # TODO verify digest
+ begin
+ 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)
+ rescue => e
+ p request.env["HTTP_SIGNATURE"], e
+ halt 400
+ end
+ end
+
+ def create object
+ unless object['type'] == 'Person'
+ doc = File.join("inbox", "#{Time.now.strftime('%Y-%m-%dT%H:%M:%S.%N')}.json")
+ File.open(doc, "w+") { |f| f.puts object.to_json }
+ if object['inReplyTo']
+ @dir = 'inbox'
+ items
+ if @items.select{|it| it[:id] == object['inReplyTo'] }.empty?
+ download object['inReplyTo']
+ end
+ end
+ end
+ end
+
+ def download object_url
+ create fetch(object_url)
+ end
+
+ def delete object
+ Dir["inbox/*.json"].each do |doc|
+ FileUtils.rm doc if JSON.parse(File.read(doc))["id"] == object["id"]
+ end
+ end
+
+ def ordered_collection dir
+ posts = Dir[File.join("public",dir, "*.json")].collect { |f| JSON.parse(File.read f) }.sort_by { |o| o["published"] }
+ {
+ "@context" => "https://www.w3.org/ns/activitystreams",
+ "summary" => "#{USER} #{dir}",
+ "type" => "OrderedCollection",
+ "totalItems" => posts.size,
+ "orderedItems" => posts,
+ }
+ end
+
+end
diff --git a/views/item.erb b/views/item.erb
index aafc4cc..933fe71 100644
--- a/views/item.erb
+++ b/views/item.erb
@@ -5,15 +5,15 @@
</form>
&nbsp;
<form action='/delete' method='post'>
- <input type='hidden' name='file' id='file' value='<%= @item[:file] %>' />
- <input type='hidden' name='redirect' id='redirect' value='/<%= @dir.sub('inbox','') %>#<%= @item[:nr] %>' />
+ <input type='hidden' name='file' value='<%= @item[:file] %>' />
+ <input type='hidden' name='redirect' value='/<%= @dir.sub('inbox','') %>#<%= @item[:nr] %>' />
<button>Delete</button>
</form>
<% if @dir == 'inbox' %>
&nbsp;
<form action='/archive' method='post'>
- <input type='hidden' name='file' id='file' value='<%= @item[:file] %>' />
- <input type='hidden' name='redirect' id='redirect' value='/<%= @dir.sub('inbox','') %>#<%= @item[:nr] %>' />
+ <input type='hidden' name='file' value='<%= @item[:file] %>' />
+ <input type='hidden' name='redirect' value='/<%= @dir.sub('inbox','') %>#<%= @item[:nr] %>' />
<button>Archive</button>
</form>
<% end %>
@@ -33,6 +33,13 @@
<% end %>
<% end %>
<% end %>
+ <form action='/outbox' method='post'>
+ <input type='hidden' name='to' value='<%= @item[:actor_url] %>' />
+ <input type='hidden' name='inReplyTo' value='<%= @item[:id] %>' />
+ <input type='hidden' name='redirect' value='/<%= @dir.sub('inbox','') %>#<%= @item[:nr] %>' />
+ <textarea name="content"></textarea>
+ <input type="submit" value="Reply">
+ </form>
</div>
<% @item[:replies].each do |reply| %>
<%= html reply %>