From 5135d609b774b177d3d3894b176a822d86b73d3c Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sun, 30 Apr 2017 07:27:31 +0900 Subject: [PATCH] Use PostgreSQL inheritance for blocks and mutes (#2520) --- app/models/account.rb | 4 ++-- .../20180428000000_create_block_mutes.rb | 19 +++++++++++++++++++ db/schema.rb | 14 +++++++++++++- spec/lib/atom_serializer_spec.rb | 4 ++-- spec/models/account_spec.rb | 6 +++--- spec/models/status_spec.rb | 6 +++--- streaming/index.js | 2 +- 7 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 db/migrate/20180428000000_create_block_mutes.rb diff --git a/app/models/account.rb b/app/models/account.rb index 19f8ca365..89710b66c 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -87,11 +87,11 @@ class Account < ApplicationRecord end def block!(other_account) - block_relationships.where(target_account: other_account).first_or_create!(target_account: other_account) + block_relationships.where(target_account: other_account).first_or_create!(target_account: other_account, block: true) end def mute!(other_account) - mute_relationships.where(target_account: other_account).first_or_create!(target_account: other_account) + mute_relationships.where(target_account: other_account).first_or_create!(target_account: other_account, block: false) end def unfollow!(other_account) diff --git a/db/migrate/20180428000000_create_block_mutes.rb b/db/migrate/20180428000000_create_block_mutes.rb new file mode 100644 index 000000000..149c91a4d --- /dev/null +++ b/db/migrate/20180428000000_create_block_mutes.rb @@ -0,0 +1,19 @@ +class CreateBlockMutes < ActiveRecord::Migration[5.0] + def change + create_table "block_mutes", force: :casecade do |t| + t.integer "account_id", null: false + t.integer "target_account_id", null: false + t.boolean "block", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_column :blocks, :block, :boolean, null: false + execute "ALTER TABLE blocks ADD CONSTRAINT check_mutes_on_block CHECK(block = TRUE), INHERIT block_mutes" + Block.update_all block: true + + add_column :mutes, :block, :boolean, null: false + execute "ALTER TABLE mutes ADD CONSTRAINT check_mutes_on_block CHECK(block = FALSE), INHERIT block_mutes" + Mute.update_all block: false + end +end diff --git a/db/schema.rb b/db/schema.rb index 66326f2e2..ea948c429 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20170425202925) do +ActiveRecord::Schema.define(version: 20180428000000) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -54,13 +54,23 @@ ActiveRecord::Schema.define(version: 20170425202925) do t.index ["username", "domain"], name: "index_accounts_on_username_and_domain", unique: true, using: :btree end + create_table "block_mutes", force: :cascade, id: false do |t| + t.integer "account_id", null: false + t.integer "target_account_id", null: false + t.boolean "block", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "blocks", force: :cascade do |t| t.integer "account_id", null: false t.integer "target_account_id", null: false + t.boolean "block", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "target_account_id"], name: "index_blocks_on_account_id_and_target_account_id", unique: true, using: :btree end + execute "ALTER TABLE blocks ADD CONSTRAINT check_blocks_on_block CHECK(block = TRUE), INHERIT block_mutes" create_table "domain_blocks", force: :cascade do |t| t.string "domain", default: "", null: false @@ -137,10 +147,12 @@ ActiveRecord::Schema.define(version: 20170425202925) do create_table "mutes", force: :cascade do |t| t.integer "account_id", null: false t.integer "target_account_id", null: false + t.boolean "block", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["account_id", "target_account_id"], name: "index_mutes_on_account_id_and_target_account_id", unique: true, using: :btree end + execute "ALTER TABLE mutes ADD CONSTRAINT check_mutes_on_block CHECK(block = FALSE), INHERIT block_mutes" create_table "notifications", force: :cascade do |t| t.integer "account_id" diff --git a/spec/lib/atom_serializer_spec.rb b/spec/lib/atom_serializer_spec.rb index cfca82a28..345285a7a 100644 --- a/spec/lib/atom_serializer_spec.rb +++ b/spec/lib/atom_serializer_spec.rb @@ -152,7 +152,7 @@ RSpec.describe AtomSerializer do describe '#block_salmon' do let(:xml) do - block = Fabricate(:block, account: author, target_account: receiver) + block = Fabricate(:block, account: author, target_account: receiver, block: true) xml = AtomSerializer.render(AtomSerializer.new.block_salmon(block)) block.destroy xml @@ -171,7 +171,7 @@ RSpec.describe AtomSerializer do describe '#unblock_salmon' do let(:xml) do - block = Fabricate(:block, account: author, target_account: receiver) + block = Fabricate(:block, account: author, target_account: receiver, block: true) block.destroy xml = AtomSerializer.render(AtomSerializer.new.unblock_salmon(block)) author.block!(receiver) diff --git a/spec/models/account_spec.rb b/spec/models/account_spec.rb index 157db633a..b4481aaed 100644 --- a/spec/models/account_spec.rb +++ b/spec/models/account_spec.rb @@ -193,9 +193,9 @@ RSpec.describe Account, type: :model do describe '#excluded_from_timeline_account_ids' do it 'includes account ids of blockings, blocked_bys and mutes' do account = Fabricate(:account) - block = Fabricate(:block, account: account) - mute = Fabricate(:mute, account: account) - block_by = Fabricate(:block, target_account: account) + block = Fabricate(:block, account: account, block: true) + mute = Fabricate(:mute, account: account, block: false) + block_by = Fabricate(:block, target_account: account, block: true) results = account.excluded_from_timeline_account_ids expect(results.size).to eq 3 diff --git a/spec/models/status_spec.rb b/spec/models/status_spec.rb index c553b052e..956b9b882 100644 --- a/spec/models/status_spec.rb +++ b/spec/models/status_spec.rb @@ -226,7 +226,7 @@ RSpec.describe Status, type: :model do it 'excludes statuses from accounts blocked by the account' do blocked = Fabricate(:account) - Fabricate(:block, account: @account, target_account: blocked) + Fabricate(:block, account: @account, target_account: blocked, block: true) blocked_status = Fabricate(:status, account: blocked) results = Status.as_public_timeline(@account) @@ -235,7 +235,7 @@ RSpec.describe Status, type: :model do it 'excludes statuses from accounts who have blocked the account' do blocked = Fabricate(:account) - Fabricate(:block, account: blocked, target_account: @account) + Fabricate(:block, account: blocked, target_account: @account, block: true) blocked_status = Fabricate(:status, account: blocked) results = Status.as_public_timeline(@account) @@ -244,7 +244,7 @@ RSpec.describe Status, type: :model do it 'excludes statuses from accounts muted by the account' do muted = Fabricate(:account) - Fabricate(:mute, account: @account, target_account: muted) + Fabricate(:mute, account: @account, target_account: muted, block: false) muted_status = Fabricate(:status, account: muted) results = Status.as_public_timeline(@account) diff --git a/streaming/index.js b/streaming/index.js index 3be844037..da8066ff3 100644 --- a/streaming/index.js +++ b/streaming/index.js @@ -188,7 +188,7 @@ if (cluster.isMaster) { const unpackedPayload = JSON.parse(payload) const targetAccountIds = [unpackedPayload.account.id].concat(unpackedPayload.mentions.map(item => item.id)).concat(unpackedPayload.reblog ? [unpackedPayload.reblog.account.id] : []) - client.query(`SELECT target_account_id FROM blocks WHERE account_id = $1 AND target_account_id IN (${placeholders(targetAccountIds, 1)}) UNION SELECT target_account_id FROM mutes WHERE account_id = $1 AND target_account_id IN (${placeholders(targetAccountIds, 1)})`, [req.accountId].concat(targetAccountIds), (err, result) => { + client.query(`SELECT target_account_id FROM block_mutes WHERE account_id = $1 AND target_account_id IN (${placeholders(targetAccountIds, 1)})`, [req.accountId].concat(targetAccountIds), (err, result) => { done() if (err) {