Compare commits
3 commits
dependabot
...
activitypu
Author | SHA1 | Date | |
---|---|---|---|
|
a54c0993c1 | ||
|
fa829953a9 | ||
|
a19c462245 |
7 changed files with 104 additions and 20 deletions
2
Gemfile
2
Gemfile
|
@ -98,7 +98,7 @@ gem 'webauthn', '~> 2.5'
|
|||
|
||||
gem 'json-ld'
|
||||
gem 'json-ld-preloaded', '~> 3.2'
|
||||
gem 'rdf-normalize', '~> 0.6'
|
||||
gem 'rdf-normalize', '~> 0.5'
|
||||
|
||||
group :development, :test do
|
||||
gem 'fabrication', '~> 2.30'
|
||||
|
|
|
@ -550,9 +550,9 @@ GEM
|
|||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
random_name_generator (2.0.1)
|
||||
rdf (3.2.11)
|
||||
rdf (3.2.9)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
rdf-normalize (0.6.1)
|
||||
rdf-normalize (0.5.1)
|
||||
rdf (~> 3.2)
|
||||
redcarpet (3.6.0)
|
||||
redis (4.5.1)
|
||||
|
@ -851,7 +851,7 @@ DEPENDENCIES
|
|||
rails-i18n (~> 6.0)
|
||||
rails-settings-cached (~> 0.6)
|
||||
random_name_generator
|
||||
rdf-normalize (~> 0.6)
|
||||
rdf-normalize (~> 0.5)
|
||||
redcarpet (~> 3.6)
|
||||
redis (~> 4.5)
|
||||
redis-namespace (~> 1.10)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "faraday"
|
||||
require "uri"
|
||||
|
||||
class Api::V1::JsonLdController < Api::BaseController
|
||||
include ActionController::Live
|
||||
|
@ -9,6 +10,40 @@ class Api::V1::JsonLdController < Api::BaseController
|
|||
render json: { error: e.to_s }, status: 422
|
||||
end
|
||||
|
||||
before_action :require_user!
|
||||
|
||||
REQUEST_TARGET = '(request-target)'
|
||||
|
||||
def signature(headers)
|
||||
account = Account.representative
|
||||
|
||||
key_id = ActivityPub::TagManager.instance.key_uri_for(account)
|
||||
algorithm = 'rsa-sha256'
|
||||
signed_string = headers.map { |key, value| "#{key.downcase}: #{value}" }.join("\n")
|
||||
signature = Base64.strict_encode64(account.keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string))
|
||||
|
||||
"keyId=\"#{key_id}\",algorithm=\"#{algorithm}\",headers=\"#{headers.keys.join(' ').downcase}\",signature=\"#{signature}\""
|
||||
end
|
||||
|
||||
def signed_headers(url_string)
|
||||
if url_string.include?(".well-known")
|
||||
return {'Accept': 'application/jrd+json'}
|
||||
end
|
||||
|
||||
url = URI.parse(url_string)
|
||||
tmp_headers = {
|
||||
'Date': Time.now.utc.httpdate,
|
||||
'Host': url.host,
|
||||
'Accept': 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
|
||||
}
|
||||
tmp_headers[REQUEST_TARGET] = "get #{url_string.delete_prefix("#{url.scheme}://#{url.host}")}"
|
||||
additional_headers = {
|
||||
'Signature': signature(tmp_headers),
|
||||
'User-Agent': Mastodon::Version.user_agent,
|
||||
}
|
||||
tmp_headers.merge(additional_headers).except(REQUEST_TARGET)
|
||||
end
|
||||
|
||||
def show
|
||||
url = params[:url]
|
||||
|
||||
|
@ -17,13 +52,12 @@ class Api::V1::JsonLdController < Api::BaseController
|
|||
Thread.new {
|
||||
begin
|
||||
conn = Faraday::Connection.new
|
||||
conn.options.timeout = 5
|
||||
|
||||
api_response = conn.get(url, nil, {'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'})
|
||||
api_response = conn.get(url, nil, signed_headers(url))
|
||||
|
||||
max_redirects = 5
|
||||
while api_response.status == 301 || api_response.status == 302 and max_redirects > 0 do
|
||||
api_response = conn.get(api_response.headers['Location'], nil, {'Accept' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"'})
|
||||
api_response = conn.get(api_response.headers['Location'], nil, signed_headers(api_response.headers['Location']))
|
||||
max_redirects -= 1
|
||||
end
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
- thumbnail = @instance_presenter.thumbnail
|
||||
- description ||= @instance_presenter.description.presence || strip_tags(t('about.about_mastodon_html'))
|
||||
- description = 'Learn ActivityPub interactively, by seeing protocol interactions visualized in real time'
|
||||
|
||||
%meta{ name: 'description', content: description }/
|
||||
|
||||
= opengraph 'og:site_name', t('about.hosted_on', domain: site_hostname)
|
||||
= opengraph 'og:site_name', 'ActivityPub Academy - A learning resource for ActivityPub'
|
||||
= opengraph 'og:url', url_for(only_path: false)
|
||||
= opengraph 'og:type', 'website'
|
||||
= opengraph 'og:title', @instance_presenter.title
|
||||
= opengraph 'og:title', 'ActivityPub Academy'
|
||||
= opengraph 'og:description', description
|
||||
= opengraph 'og:image', full_asset_url(thumbnail&.file&.url(:'@1x') || asset_pack_path('media/images/preview.png', protocol: :request))
|
||||
= opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '1200'
|
||||
= opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '630'
|
||||
= opengraph 'og:image', full_asset_url(thumbnail&.file&.url(:'@1x') || asset_pack_path('media/images/academy-mascot.webp', protocol: :request))
|
||||
= opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '500'
|
||||
= opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '573'
|
||||
= opengraph 'twitter:card', 'summary_large_image'
|
||||
|
|
|
@ -28,17 +28,13 @@ class Scheduler::OldAccountCleanupScheduler
|
|||
.where("domain IS NULL")
|
||||
# id -99 is the instance actor
|
||||
.where("id <> -99")
|
||||
# don't delete admin
|
||||
.where("username <> 'admin'")
|
||||
# don't delete crepels
|
||||
.where("username <> 'crepels'")
|
||||
# don't delete alice
|
||||
.where("username <> 'alice'")
|
||||
# only delete accounts whose username contains underscores (those are auto-generated)
|
||||
.where("username LIKE '%\\_%'")
|
||||
.where("created_at < ?", 1.day.ago)
|
||||
.order(created_at: :asc)
|
||||
.limit(MAX_DELETIONS_PER_JOB)
|
||||
.each do |account|
|
||||
AccountDeletionWorker.perform_async(account.id, { :reserve_username => false })
|
||||
AccountDeletionWorker.perform_async(account.id, { 'reserve_username' => false })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
21
dist/nginx.conf
vendored
21
dist/nginx.conf
vendored
|
@ -114,6 +114,27 @@ server {
|
|||
tcp_nodelay on;
|
||||
}
|
||||
|
||||
location ^~ /api/v1/json_ld {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto https;
|
||||
proxy_set_header Proxy "";
|
||||
proxy_pass_header Server;
|
||||
|
||||
proxy_pass http://backend;
|
||||
proxy_redirect off;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection '';
|
||||
|
||||
proxy_cache off;
|
||||
proxy_buffering off;
|
||||
chunked_transfer_encoding off;
|
||||
|
||||
tcp_nodelay on;
|
||||
}
|
||||
|
||||
location ^~ /api/v1/activity_log {
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
|
33
spec/workers/scheduler/old_account_cleanup_scheduler_spec.rb
Normal file
33
spec/workers/scheduler/old_account_cleanup_scheduler_spec.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
require 'json'
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Scheduler::OldAccountCleanupScheduler do
|
||||
subject { described_class.new }
|
||||
let!(:generated_user) { Fabricate(:account, username: 'containing_underscore', created_at: 25.hours.ago) }
|
||||
let!(:alice) { Fabricate(:account, username: 'alice', created_at: 25.hours.ago) }
|
||||
let!(:generated_user_other_instance) { Fabricate(:account, username: 'containing_underscore', domain: 'example.com', created_at: 25.hours.ago) }
|
||||
let!(:instance_actor) { Fabricate(:account, id: 99, created_at: 25.hours.ago) }
|
||||
|
||||
describe '#perform' do
|
||||
it 'removes auto-generated user-accounts that are older than one day' do
|
||||
expect { subject.perform }.to change { Account.exists?(generated_user.id) }.from(true).to(false)
|
||||
end
|
||||
|
||||
it 'does not remove auto-generated user-accounts that are younger than one day' do
|
||||
generated_user.update!(created_at: 23.hours.ago)
|
||||
expect { subject.perform }.not_to change { Account.exists?(generated_user.id) }.from(true)
|
||||
end
|
||||
|
||||
it 'does not remove accounts with underscores from other instances' do
|
||||
expect { subject.perform }.not_to change { Account.exists?(generated_user_other_instance.id) }.from(true)
|
||||
end
|
||||
|
||||
it 'does not remove accounts without underscores' do
|
||||
expect { subject.perform }.not_to change { Account.exists?(alice.id) }.from(true)
|
||||
end
|
||||
|
||||
it 'does not remove instance actor' do
|
||||
expect { subject.perform }.not_to change { Account.exists?(instance_actor.id) }.from(true)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue