FEATURE: Promote polymorphic bookmarks to default and migrate (#16729)

This commit migrates all bookmarks to be polymorphic (using the
bookmarkable_id and bookmarkable_type) columns. It also deletes
all the old code guarded behind the use_polymorphic_bookmarks setting
and changes that setting to true for all sites and by default for
the sake of plugins.

No data is deleted in the migrations, the old post_id and for_topic
columns for bookmarks will be dropped later on.
This commit is contained in:
Martin Brennan
2022-05-23 10:07:15 +10:00
committed by GitHub
parent bf987af3ca
commit fcc2e7ebbf
63 changed files with 582 additions and 1833 deletions

View File

@ -13,22 +13,30 @@ RSpec.describe BookmarkQuery do
end
describe "#list_all" do
fab!(:bookmark1) { Fabricate(:bookmark, user: user) }
fab!(:bookmark2) { Fabricate(:bookmark, user: user) }
let!(:topic_user1) { Fabricate(:topic_user, topic: bookmark1.topic, user: user) }
let!(:topic_user2) { Fabricate(:topic_user, topic: bookmark2.topic, user: user) }
before do
Bookmark.reset_bookmarkables
register_test_bookmarkable
Fabricate(:topic_user, user: user, topic: post_bookmark.bookmarkable.topic)
Fabricate(:topic_user, user: user, topic: topic_bookmark.bookmarkable)
user_bookmark
end
let(:post_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:post)) }
let(:topic_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:topic)) }
let(:user_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:user, username: "bookmarkqueen")) }
after do
Bookmark.reset_bookmarkables
end
it "returns all the bookmarks for a user" do
expect(bookmark_query.list_all.count).to eq(2)
expect(bookmark_query.list_all.count).to eq(3)
end
it "does not return deleted posts" do
bookmark1.post.trash!
expect(bookmark_query.list_all.count).to eq(1)
end
it "does not return deleted topics" do
bookmark1.topic.trash!
it "does not return deleted bookmarkables" do
post_bookmark.bookmarkable.trash!
topic_bookmark.bookmarkable.trash!
expect(bookmark_query.list_all.count).to eq(1)
end
@ -41,149 +49,92 @@ RSpec.describe BookmarkQuery do
expect(preloaded_bookmarks.any?).to eq(true)
end
it "does not query topic_users for the bookmark topic that are not the current user" do
topic_user3 = Fabricate(:topic_user, topic: bookmark1.topic)
bookmark = bookmark_query.list_all.find do |b|
b.topic_id == bookmark1.topic_id
end
expect(bookmark.topic.topic_users.map(&:user_id)).to contain_exactly(user.id)
it "returns a mixture of post, topic, and custom bookmarkable type bookmarks" do
bookmarks = bookmark_query.list_all
expect(bookmarks.map(&:id)).to match_array([post_bookmark.id, topic_bookmark.id, user_bookmark.id])
end
context "for polymorphic bookmarks" do
before do
SiteSetting.use_polymorphic_bookmarks = true
Bookmark.reset_bookmarkables
register_test_bookmarkable
it "handles the user not having permission for all of the bookmarks of a certain bookmarkable" do
UserTestBookmarkable.expects(:list_query).returns(nil)
bookmarks = bookmark_query.list_all
expect(bookmarks.map(&:id)).to match_array([post_bookmark.id, topic_bookmark.id])
end
Fabricate(:topic_user, user: user, topic: post_bookmark.bookmarkable.topic)
Fabricate(:topic_user, user: user, topic: topic_bookmark.bookmarkable)
user_bookmark
end
let(:post_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:post)) }
let(:topic_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:topic)) }
let(:user_bookmark) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:user, username: "bookmarkqueen")) }
after do
Bookmark.reset_bookmarkables
end
it "returns a mixture of post, topic, and custom bookmarkable type bookmarks" do
bookmarks = bookmark_query.list_all
expect(bookmarks.map(&:id)).to match_array([post_bookmark.id, topic_bookmark.id, user_bookmark.id])
end
it "handles the user not having permission for all of the bookmarks of a certain bookmarkable" do
UserTestBookmarkable.expects(:list_query).returns(nil)
bookmarks = bookmark_query.list_all
expect(bookmarks.map(&:id)).to match_array([post_bookmark.id, topic_bookmark.id])
end
it "handles the user not having permission to see any of their bookmarks" do
topic_bookmark.bookmarkable.update(category: Fabricate(:private_category, group: Fabricate(:group)))
post_bookmark.bookmarkable.topic.update(category: topic_bookmark.bookmarkable.category)
UserTestBookmarkable.expects(:list_query).returns(nil)
bookmarks = bookmark_query.list_all
expect(bookmarks.map(&:id)).to eq([])
end
it "handles the user not having permission to see any of their bookmarks" do
topic_bookmark.bookmarkable.update(category: Fabricate(:private_category, group: Fabricate(:group)))
post_bookmark.bookmarkable.topic.update(category: topic_bookmark.bookmarkable.category)
UserTestBookmarkable.expects(:list_query).returns(nil)
bookmarks = bookmark_query.list_all
expect(bookmarks.map(&:id)).to eq([])
end
context "when q param is provided" do
let!(:post) { Fabricate(:post, raw: "Some post content here", topic: Fabricate(:topic, title: "Bugfix game for devs")) }
context "when not using polymorphic bookmarks" do
let(:bookmark3) { Fabricate(:bookmark, user: user, name: "Check up later") }
let(:bookmark4) { Fabricate(:bookmark, user: user, post: post) }
before do
Fabricate(:topic_user, user: user, topic: bookmark3.topic)
Fabricate(:topic_user, user: user, topic: bookmark4.topic)
end
it "can search by bookmark name" do
bookmarks = bookmark_query(params: { q: 'check' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark3.id])
end
it "can search by post content" do
bookmarks = bookmark_query(params: { q: 'content' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark4.id])
end
it "can search by topic title" do
bookmarks = bookmark_query(params: { q: 'bugfix' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark4.id])
end
before do
Bookmark.reset_bookmarkables
end
context "when using polymorphic bookmarks" do
after do
Bookmark.reset_bookmarkables
end
let(:bookmark3) { Fabricate(:bookmark, user: user, name: "Check up later", bookmarkable: Fabricate(:post)) }
let(:bookmark4) { Fabricate(:bookmark, user: user, bookmarkable: post) }
before do
Fabricate(:topic_user, user: user, topic: bookmark3.bookmarkable.topic)
Fabricate(:topic_user, user: user, topic: bookmark4.bookmarkable.topic)
end
it "can search by bookmark name" do
bookmarks = bookmark_query(params: { q: 'check' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark3.id])
end
it "can search by post content" do
bookmarks = bookmark_query(params: { q: 'content' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark4.id])
end
it "can search by topic title" do
bookmarks = bookmark_query(params: { q: 'bugfix' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark4.id])
end
context "with custom bookmarkable fitering" do
before do
SiteSetting.use_polymorphic_bookmarks = true
Bookmark.reset_bookmarkables
register_test_bookmarkable
end
after do
Bookmark.reset_bookmarkables
end
let!(:bookmark5) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:user, username: "bookmarkking")) }
let(:bookmark3) { Fabricate(:bookmark, user: user, name: "Check up later", bookmarkable: Fabricate(:post)) }
let(:bookmark4) { Fabricate(:bookmark, user: user, bookmarkable: post) }
before do
Fabricate(:topic_user, user: user, topic: bookmark3.bookmarkable.topic)
Fabricate(:topic_user, user: user, topic: bookmark4.bookmarkable.topic)
end
it "can search by bookmark name" do
bookmarks = bookmark_query(params: { q: 'check' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark3.id])
end
it "can search by post content" do
bookmarks = bookmark_query(params: { q: 'content' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark4.id])
end
it "can search by topic title" do
bookmarks = bookmark_query(params: { q: 'bugfix' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark4.id])
end
context "with custom bookmarkable fitering" do
before do
register_test_bookmarkable
end
let!(:bookmark5) { Fabricate(:bookmark, user: user, bookmarkable: Fabricate(:user, username: "bookmarkqueen")) }
it "allows searching bookmarkables by fields in other tables" do
bookmarks = bookmark_query(params: { q: 'bookmarkq' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark5.id])
end
it "allows searching bookmarkables by fields in other tables" do
bookmarks = bookmark_query(params: { q: 'bookmarkk' }).list_all
expect(bookmarks.map(&:id)).to eq([bookmark5.id])
end
end
end
context "for a whispered post" do
before do
bookmark1.post.update(post_type: Post.types[:whisper])
post_bookmark.bookmarkable.update(post_type: Post.types[:whisper])
end
context "when the user is moderator" do
it "does return the whispered post" do
user.update!(moderator: true)
expect(bookmark_query.list_all.count).to eq(2)
expect(bookmark_query.list_all.count).to eq(3)
end
end
context "when the user is admin" do
it "does return the whispered post" do
user.update!(admin: true)
expect(bookmark_query.list_all.count).to eq(2)
expect(bookmark_query.list_all.count).to eq(3)
end
end
context "when the user is not staff" do
it "does not return the whispered post" do
expect(bookmark_query.list_all.count).to eq(1)
expect(bookmark_query.list_all.count).to eq(2)
end
end
end
@ -191,7 +142,7 @@ RSpec.describe BookmarkQuery do
context "for a private message topic bookmark" do
let(:pm_topic) { Fabricate(:private_message_topic) }
before do
bookmark1.update(post: Fabricate(:post, topic: pm_topic))
post_bookmark.update(bookmarkable: Fabricate(:post, topic: pm_topic))
TopicUser.change(user.id, pm_topic.id, total_msecs_viewed: 1)
end
@ -200,7 +151,7 @@ RSpec.describe BookmarkQuery do
TopicAllowedUser.create(topic: pm_topic, user: user)
end
it "shows the user the bookmark in the PM" do
expect(bookmark_query.list_all.map(&:id).count).to eq(2)
expect(bookmark_query.list_all.map(&:id).count).to eq(3)
end
end
@ -211,19 +162,19 @@ RSpec.describe BookmarkQuery do
TopicAllowedGroup.create(topic: pm_topic, group: group)
end
it "shows the user the bookmark in the PM" do
expect(bookmark_query.list_all.map(&:id).count).to eq(2)
expect(bookmark_query.list_all.map(&:id).count).to eq(3)
end
end
context "when the user is not a topic_allowed_user" do
it "does not show the user a bookmarked post in a PM where they are not an allowed user" do
expect(bookmark_query.list_all.map(&:id).count).to eq(1)
expect(bookmark_query.list_all.map(&:id).count).to eq(2)
end
end
context "when the user is not in a topic_allowed_group" do
it "does not show the user a bookmarked post in a PM where they are not in an allowed group" do
expect(bookmark_query.list_all.map(&:id).count).to eq(1)
expect(bookmark_query.list_all.map(&:id).count).to eq(2)
end
end
end
@ -231,15 +182,15 @@ RSpec.describe BookmarkQuery do
context "when the topic category is private" do
let(:group) { Fabricate(:group) }
before do
bookmark1.topic.update(category: Fabricate(:private_category, group: group))
bookmark1.reload
post_bookmark.bookmarkable.topic.update(category: Fabricate(:private_category, group: group))
post_bookmark.reload
end
it "does not show the user a post/topic in a private category they cannot see" do
expect(bookmark_query.list_all.map(&:id)).not_to include(bookmark1.id)
expect(bookmark_query.list_all.map(&:id)).not_to include(post_bookmark.id)
end
it "does show the user a post/topic in a private category they can see" do
GroupUser.create(user: user, group: group)
expect(bookmark_query.list_all.map(&:id)).to include(bookmark1.id)
expect(bookmark_query.list_all.map(&:id)).to include(post_bookmark.id)
end
end
@ -260,7 +211,7 @@ RSpec.describe BookmarkQuery do
before do
[bookmark1, bookmark2, bookmark3, bookmark4, bookmark5].each do |bm|
Fabricate(:topic_user, topic: bm.topic, user: user)
Fabricate(:topic_user, topic: bm.bookmarkable.topic, user: user)
bm.reload
end
end