summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client.rb29
-rw-r--r--create.rb6
-rw-r--r--helpers.rb9
-rw-r--r--server.rb81
-rwxr-xr-xwatch2
5 files changed, 51 insertions, 76 deletions
diff --git a/client.rb b/client.rb
index 8af00c9..7b93c83 100644
--- a/client.rb
+++ b/client.rb
@@ -9,7 +9,7 @@ end
post '/delete' do
protected!
params['id'].each do |id|
- file = find_file id
+ file, object = find_object id
halt 404 unless file and File.exist?(file)
FileUtils.rm(file)
end
@@ -53,20 +53,19 @@ post '/share' do # TODO
200
end
-# post '/undo' do # TODO: generalize for announce
-# protected!
-# activity_file = find_file(params['id'])
-# Dir[File.join('outbox', '*', '*.json')].each do |f|
-# activity = JSON.load_file(f)
-# next unless activity['id'] == params['id']
-#
-# object_file = find_file activity['object']['id']
-# create_activity 'Undo', params['id'], activity['to']
-# FileUtils.rm(object_file)
-# FileUtils.rm(f)
-# end
-# 200
-# end
+post '/undo' do # TODO: generalize for announce
+ protected!
+ Dir[File.join('outbox', '*', '*.json')].each do |activity_file|
+ activity = JSON.load_file(activity_file)
+ next unless activity['id'] == params['id']
+
+ object_file = find_file activity['object']['id']
+ create_activity 'Undo', params['id'], activity['to']
+ FileUtils.rm(activity_file)
+ FileUtils.rm(object_file)
+ end
+ 200
+end
post '/login' do
session['client'] = (OpenSSL::Digest::SHA256.base64digest(params['secret']) == File.read('.digest').chomp)
diff --git a/create.rb b/create.rb
index 0798ba1..dc1daab 100644
--- a/create.rb
+++ b/create.rb
@@ -37,15 +37,17 @@ post '/create' do
when REPLY_REGEXP
inReplyTo = line.sub(REPLY_REGEXP, '')
when ATTACH_REGEXP
- url = line.sub(ATTACH_REGEXP, '')
+ url, description = line.sub(ATTACH_REGEXP, '').split(/\s+/, 2)
attachment << {
'type' => 'Document',
'mediaType' => media_type(url),
- 'url' => url
+ 'url' => url,
+ 'name' => description
}
else # create links
# single quotes in html invalidate digest, reason unknown
line.split(/\s+/).each do |word|
+ word = word.gsub('<p>', '').gsub('</p>', '')
case word
when HASHTAG_REGEXP
tag_url = File.join('https://social.pdp8.info', 'tags', word.sub('#', ''))
diff --git a/helpers.rb b/helpers.rb
index 536a7c6..0a7f829 100644
--- a/helpers.rb
+++ b/helpers.rb
@@ -80,7 +80,6 @@ helpers do
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}\""
- p inbox
# Net::HTTP fails with OpenSSL error
curl(
"-X POST -H 'Host: #{uri.host}' -H 'Date: #{httpdate}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' --data-binary '@#{activity_path}'", inbox
@@ -204,8 +203,14 @@ helpers do
def find_file(id)
Dir[File.join('*', 'object', '*', '*.json')].find do |f|
- # Dir[File.join('*box', '**', '*.json')].find do |f|
JSON.load_file(f)['id'] == id
end
end
+
+ def find_object(id)
+ Dir[File.join('*', '**', '*.json')].each do |file|
+ object = JSON.load_file(file)
+ return [file, object] if object['id'] == id
+ end
+ end
end
diff --git a/server.rb b/server.rb
index 0807375..41663cb 100644
--- a/server.rb
+++ b/server.rb
@@ -82,11 +82,13 @@ helpers do
end
def follow
+ save_item @activity, File.join(INBOX[:dir], @activity['type'].downcase, activity_name)
update_collection FOLLOWERS, @activity['actor']
create_activity 'Accept', @activity, [@activity['actor']]
end
def accept
+ save_item @activity, File.join(INBOX[:dir], @activity['type'].downcase, activity_name)
if @activity['object']['type'] == 'Follow'
update_collection FOLLOWING, @activity['object']['object']
else
@@ -131,13 +133,15 @@ helpers do
if ACTIVITIES.include? type
send(type)
else
- p "Unknown activity #{type}:"
- jj @activity
+ unless %w[Add Remove].include? @activity['type']
+ p "Unknown activity #{type}:"
+ jj @activity
+ end
end
end
def activity_name
- @activity['published'] ? "#{@activity['published']}_#{mention(@activity['actor'])}.json" : "_#{Time.now.utc.iso8601}_#{mention(@activity['actor'])}.json"
+ @activity['published'] ? "#{@activity['published']}_#{mention(@activity['actor'])}.json" : "#{Time.now.utc.iso8601}_#{mention(@activity['actor'])}.json"
end
def save_inbox_object
@@ -155,15 +159,12 @@ helpers do
end
def public_outbox
- # files = Dir[File.join('outbox', 'create', '*.json')] + Dir[File.join('outbox', 'announce', '*.json')]
create = Dir[File.join('outbox', 'create', '*.json')].collect do |f|
JSON.load_file(f)
end.select { |a| a['to'].include?('https://www.w3.org/ns/activitystreams#Public') }.sort_by { |a| a['published'] }.reverse
announce = Dir[File.join('outbox', 'announce', '*.json')].collect do |f|
JSON.load_file(f)
end.select { |a| a['to'].include?('https://www.w3.org/ns/activitystreams#Public') }.sort_by { |a| a['published'] }.reverse
- # activities = files.collect { |f| JSON.load_file(f) }
- # activities.select { |a| a['to'].include?('https://www.w3.org/ns/activitystreams#Public') }.sort_by { |a| a['published'] }
create + announce
end
@@ -172,7 +173,11 @@ helpers do
# digest
sha256 = OpenSSL::Digest.new('SHA256')
digest = "SHA-256=#{sha256.base64digest(@body)}"
- halt 403 unless digest == request.env['HTTP_DIGEST']
+ unless digest == request.env['HTTP_DIGEST']
+ p 'invalid digest'
+ p @body
+ halt 403
+ end
# signature
signature_params = {}
@@ -186,7 +191,11 @@ helpers do
signature = Base64.decode64(signature_params['signature'])
actor = fetch key_id
- halt 403 unless actor
+ unless actor
+ p 'no actor'
+ jj @activity
+ halt 403
+ end
key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem'])
@@ -200,51 +209,13 @@ helpers do
end
end.join("\n")
- halt 403 unless key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
- end
-
- # def outbox(type, object, to) # https://github.com/mastodon/mastodon/blob/main/app/lib/request.rb
- # to = [to] if to.is_a?(String)
- # inboxes = []
- # to.uniq.each do |url|
- # next if [ACTOR, 'https://www.w3.org/ns/activitystreams#Public'].include? url
- #
- # if url == FOLLOWERS_URL
- # JSON.load_file(FOLLOWERS)['orderedItems'].each do |follower|
- # inboxes << actor_inbox(follower)
- # end
- # next
- # end
- # inboxes << actor_inbox(url)
- # end
- #
- # # add date and id, save
- # activity_path = save_activity({
- # '@context' => 'https://www.w3.org/ns/activitystreams',
- # 'type' => type,
- # 'actor' => ACTOR,
- # 'object' => object,
- # 'to' => to
- # }, OUTBOX)
- #
- # # p activity_path
- # body = File.read(activity_path)
- # sha256 = OpenSSL::Digest.new('SHA256')
- # digest = "SHA-256=#{sha256.base64digest(body)}"
- # keypair = OpenSSL::PKey::RSA.new(File.read('private.pem'))
- #
- # inboxes.compact.uniq.each do |inbox|
- # uri = URI(inbox)
- # httpdate = Time.now.utc.httpdate
- # string = "(request-target): post #{uri.request_uri}\nhost: #{uri.host}\ndate: #{httpdate}\ndigest: #{digest}\ncontent-type: #{CONTENT_TYPE}"
- # 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}\""
- #
- # # Net::HTTP fails with OpenSSL error
- # curl(
- # "-X POST -H 'Host: #{uri.host}' -H 'Date: #{httpdate}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' --data-binary '@#{activity_path}'", inbox
- # )
- # end
- # activity_path
- # end
+ return if key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison)
+
+ p 'verification failed'
+ p signature_params
+ p actor['publicKey']
+ p signature, comparison
+ jj @activity
+ # halt 403
+ end
end
diff --git a/watch b/watch
index 31ac8fd..bdaa77e 100755
--- a/watch
+++ b/watch
@@ -1,6 +1,4 @@
#!/bin/sh
while inotifywait -qq -r ./ -e create,delete,modify; do
./update
- #rsync -a --exclude='.git/' --exclude='watch' --exclude='generate-digest.rb' --exclude='.gitignore' --exclude='TODO' --filter=":- .gitignore" ./ /srv/social/
- sudo systemctl restart social.service
done