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.main
parent
d1aef17f9a
commit
6793bec4c6
|
@ -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…
Reference in New Issue