Store URIs of follows, follow requests and blocks for ActivityPub (#7160)

Same URI passed between follow request and follow, since they are
the same thing in ActivityPub. Local URIs are generated during
creation using UUIDs and are passed to serializers.
master
Eugen Rochko 7 years ago committed by GitHub
parent d1aef17f9a
commit 6793bec4c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/lib/activitypub/activity/block.rb
  2. 2
      app/lib/activitypub/activity/follow.rb
  3. 4
      app/lib/activitypub/tag_manager.rb
  4. 10
      app/models/block.rb
  5. 13
      app/models/concerns/account_interactions.rb
  6. 13
      app/models/follow.rb
  7. 16
      app/models/follow_request.rb
  8. 2
      app/serializers/activitypub/follow_serializer.rb
  9. 7
      db/migrate/20180416210259_add_uri_to_relationships.rb
  10. 6
      db/schema.rb
  11. 2
      spec/models/follow_request_spec.rb

@ -7,6 +7,6 @@ class ActivityPub::Activity::Block < ActivityPub::Activity
return if target_account.nil? || !target_account.local? || delete_arrived_first?(@json['id']) || @account.blocking?(target_account) return if target_account.nil? || !target_account.local? || delete_arrived_first?(@json['id']) || @account.blocking?(target_account)
UnfollowService.new.call(target_account, @account) if target_account.following?(@account) UnfollowService.new.call(target_account, @account) if target_account.following?(@account)
@account.block!(target_account) @account.block!(target_account, uri: @json['id'])
end end
end end

@ -12,7 +12,7 @@ class ActivityPub::Activity::Follow < ActivityPub::Activity
return return
end end
follow_request = FollowRequest.create!(account: @account, target_account: target_account) follow_request = FollowRequest.create!(account: @account, target_account: target_account, uri: @json['id'])
if target_account.locked? if target_account.locked?
NotifyService.new.call(target_account, follow_request) NotifyService.new.call(target_account, follow_request)

@ -38,6 +38,10 @@ class ActivityPub::TagManager
end end
end end
def generate_uri_for(_target)
URI.join(root_url, 'payloads', SecureRandom.uuid)
end
def activity_uri_for(target) def activity_uri_for(target)
raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local? raise ArgumentError, 'target must be a local activity' unless %i(note comment activity).include?(target.object_type) && target.local?

@ -8,6 +8,7 @@
# updated_at :datetime not null # updated_at :datetime not null
# account_id :bigint(8) not null # account_id :bigint(8) not null
# target_account_id :bigint(8) not null # target_account_id :bigint(8) not null
# uri :string
# #
class Block < ApplicationRecord class Block < ApplicationRecord
@ -19,7 +20,12 @@ class Block < ApplicationRecord
validates :account_id, uniqueness: { scope: :target_account_id } validates :account_id, uniqueness: { scope: :target_account_id }
def local?
false # Force uri_for to use uri attribute
end
after_commit :remove_blocking_cache after_commit :remove_blocking_cache
before_validation :set_uri, only: :create
private private
@ -27,4 +33,8 @@ class Block < ApplicationRecord
Rails.cache.delete("exclude_account_ids_for:#{account_id}") Rails.cache.delete("exclude_account_ids_for:#{account_id}")
Rails.cache.delete("exclude_account_ids_for:#{target_account_id}") Rails.cache.delete("exclude_account_ids_for:#{target_account_id}")
end end
def set_uri
self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil?
end
end end

@ -82,16 +82,19 @@ module AccountInteractions
has_many :domain_blocks, class_name: 'AccountDomainBlock', dependent: :destroy has_many :domain_blocks, class_name: 'AccountDomainBlock', dependent: :destroy
end end
def follow!(other_account, reblogs: nil) def follow!(other_account, reblogs: nil, uri: nil)
reblogs = true if reblogs.nil? reblogs = true if reblogs.nil?
rel = active_relationships.create_with(show_reblogs: reblogs).find_or_create_by!(target_account: other_account)
rel.update!(show_reblogs: reblogs)
rel = active_relationships.create_with(show_reblogs: reblogs, uri: uri)
.find_or_create_by!(target_account: other_account)
rel.update!(show_reblogs: reblogs)
rel rel
end end
def block!(other_account) def block!(other_account, uri: nil)
block_relationships.find_or_create_by!(target_account: other_account) block_relationships.create_with(uri: uri)
.find_or_create_by!(target_account: other_account)
end end
def mute!(other_account, notifications: nil) def mute!(other_account, notifications: nil)

@ -9,6 +9,7 @@
# account_id :bigint(8) not null # account_id :bigint(8) not null
# target_account_id :bigint(8) not null # target_account_id :bigint(8) not null
# show_reblogs :boolean default(TRUE), not null # show_reblogs :boolean default(TRUE), not null
# uri :string
# #
class Follow < ApplicationRecord class Follow < ApplicationRecord
@ -26,4 +27,16 @@ class Follow < ApplicationRecord
validates :account_id, uniqueness: { scope: :target_account_id } validates :account_id, uniqueness: { scope: :target_account_id }
scope :recent, -> { reorder(id: :desc) } scope :recent, -> { reorder(id: :desc) }
def local?
false # Force uri_for to use uri attribute
end
before_validation :set_uri, only: :create
private
def set_uri
self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil?
end
end end

@ -9,6 +9,7 @@
# account_id :bigint(8) not null # account_id :bigint(8) not null
# target_account_id :bigint(8) not null # target_account_id :bigint(8) not null
# show_reblogs :boolean default(TRUE), not null # show_reblogs :boolean default(TRUE), not null
# uri :string
# #
class FollowRequest < ApplicationRecord class FollowRequest < ApplicationRecord
@ -23,11 +24,22 @@ class FollowRequest < ApplicationRecord
validates :account_id, uniqueness: { scope: :target_account_id } validates :account_id, uniqueness: { scope: :target_account_id }
def authorize! def authorize!
account.follow!(target_account, reblogs: show_reblogs) account.follow!(target_account, reblogs: show_reblogs, uri: uri)
MergeWorker.perform_async(target_account.id, account.id) MergeWorker.perform_async(target_account.id, account.id)
destroy! destroy!
end end
alias reject! destroy! alias reject! destroy!
def local?
false # Force uri_for to use uri attribute
end
before_validation :set_uri, only: :create
private
def set_uri
self.uri = ActivityPub::TagManager.instance.generate_uri_for(self) if uri.nil?
end
end end

@ -5,7 +5,7 @@ class ActivityPub::FollowSerializer < ActiveModel::Serializer
attribute :virtual_object, key: :object attribute :virtual_object, key: :object
def id def id
[ActivityPub::TagManager.instance.uri_for(object.account), '#follows/', object.id].join ActivityPub::TagManager.instance.uri_for(object)
end end
def type def type

@ -0,0 +1,7 @@
class AddUriToRelationships < ActiveRecord::Migration[5.2]
def change
add_column :follows, :uri, :string
add_column :follow_requests, :uri, :string
add_column :blocks, :uri, :string
end
end

@ -10,10 +10,9 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_04_10_204633) do ActiveRecord::Schema.define(version: 2018_04_16_210259) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "plpgsql" enable_extension "plpgsql"
create_table "account_domain_blocks", force: :cascade do |t| create_table "account_domain_blocks", force: :cascade do |t|
@ -112,6 +111,7 @@ ActiveRecord::Schema.define(version: 2018_04_10_204633) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.bigint "target_account_id", null: false t.bigint "target_account_id", null: false
t.string "uri"
t.index ["account_id", "target_account_id"], name: "index_blocks_on_account_id_and_target_account_id", unique: true t.index ["account_id", "target_account_id"], name: "index_blocks_on_account_id_and_target_account_id", unique: true
end end
@ -176,6 +176,7 @@ ActiveRecord::Schema.define(version: 2018_04_10_204633) do
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.bigint "target_account_id", null: false t.bigint "target_account_id", null: false
t.boolean "show_reblogs", default: true, null: false t.boolean "show_reblogs", default: true, null: false
t.string "uri"
t.index ["account_id", "target_account_id"], name: "index_follow_requests_on_account_id_and_target_account_id", unique: true t.index ["account_id", "target_account_id"], name: "index_follow_requests_on_account_id_and_target_account_id", unique: true
end end
@ -185,6 +186,7 @@ ActiveRecord::Schema.define(version: 2018_04_10_204633) do
t.bigint "account_id", null: false t.bigint "account_id", null: false
t.bigint "target_account_id", null: false t.bigint "target_account_id", null: false
t.boolean "show_reblogs", default: true, null: false t.boolean "show_reblogs", default: true, null: false
t.string "uri"
t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true t.index ["account_id", "target_account_id"], name: "index_follows_on_account_id_and_target_account_id", unique: true
end end

@ -7,7 +7,7 @@ RSpec.describe FollowRequest, type: :model do
let(:target_account) { Fabricate(:account) } let(:target_account) { Fabricate(:account) }
it 'calls Account#follow!, MergeWorker.perform_async, and #destroy!' do it 'calls Account#follow!, MergeWorker.perform_async, and #destroy!' do
expect(account).to receive(:follow!).with(target_account, reblogs: true) expect(account).to receive(:follow!).with(target_account, reblogs: true, uri: follow_request.uri)
expect(MergeWorker).to receive(:perform_async).with(target_account.id, account.id) expect(MergeWorker).to receive(:perform_async).with(target_account.id, account.id)
expect(follow_request).to receive(:destroy!) expect(follow_request).to receive(:destroy!)
follow_request.authorize! follow_request.authorize!

Loading…
Cancel
Save