mirror of
https://github.com/discourse/discourse.git
synced 2024-12-24 11:53:51 +08:00
54e7dee6d7
Some checks are pending
Licenses / run (push) Waiting to run
Linting / run (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (annotations, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (backend, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (backend, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (frontend, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (frontend, themes) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, chat) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, core) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, plugins) (push) Waiting to run
Tests / ${{ matrix.target }} ${{ matrix.build_type }} (system, themes) (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Chrome) (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Firefox ESR) (push) Waiting to run
Tests / core frontend (${{ matrix.browser }}) (Firefox Evergreen) (push) Waiting to run
In the case where: * Secure uploads were enabled * Allow unsecure chat uploads was enabled * For a site with login required enabled When a chat upload was created, it was being marked as secure. Since there is no provision for secure uploads in chat, this would lead to broken uploads/images shown in the channel. We can use the "public types" functionality of secure uploads to make sure we never mark chat uploads as secure, and we can revisit this whenever we get around to allowing secure uploads in chat.
457 lines
15 KiB
Ruby
457 lines
15 KiB
Ruby
# frozen_string_literal: true
|
||
|
||
describe Chat do
|
||
before do
|
||
SiteSetting.clean_up_uploads = true
|
||
SiteSetting.clean_orphan_uploads_grace_period_hours = 1
|
||
Jobs::CleanUpUploads.new.reset_last_cleanup!
|
||
SiteSetting.chat_enabled = true
|
||
end
|
||
|
||
describe "register_upload_unused" do
|
||
fab!(:chat_channel) { Fabricate(:chat_channel, chatable: Fabricate(:category)) }
|
||
fab!(:user)
|
||
fab!(:upload) { Fabricate(:upload, user: user, created_at: 1.month.ago) }
|
||
fab!(:unused_upload) { Fabricate(:upload, user: user, created_at: 1.month.ago) }
|
||
|
||
let!(:chat_message) do
|
||
Fabricate(
|
||
:chat_message,
|
||
chat_channel: chat_channel,
|
||
user: user,
|
||
message: "Hello world!",
|
||
uploads: [upload],
|
||
)
|
||
end
|
||
|
||
it "marks uploads with reference to ChatMessage via UploadReference in use" do
|
||
unused_upload
|
||
|
||
expect { Jobs::CleanUpUploads.new.execute({}) }.to change { Upload.count }.by(-1)
|
||
expect(Upload.exists?(id: upload.id)).to eq(true)
|
||
expect(Upload.exists?(id: unused_upload.id)).to eq(false)
|
||
end
|
||
end
|
||
|
||
describe "register_upload_in_use" do
|
||
fab!(:chat_channel) { Fabricate(:chat_channel, chatable: Fabricate(:category)) }
|
||
fab!(:user)
|
||
fab!(:message_upload) { Fabricate(:upload, user: user, created_at: 1.month.ago) }
|
||
fab!(:draft_upload) { Fabricate(:upload, user: user, created_at: 1.month.ago) }
|
||
fab!(:unused_upload) { Fabricate(:upload, user: user, created_at: 1.month.ago) }
|
||
|
||
let!(:chat_message) do
|
||
Fabricate(
|
||
:chat_message,
|
||
chat_channel: chat_channel,
|
||
user: user,
|
||
message: "Hello world! #{message_upload.sha1}",
|
||
)
|
||
end
|
||
let!(:draft_message) do
|
||
Chat::Draft.create!(
|
||
user: user,
|
||
chat_channel: chat_channel,
|
||
data:
|
||
"{\"value\":\"hello world \",\"uploads\":[\"#{draft_upload.sha1}\"],\"replyToMsg\":null}",
|
||
)
|
||
end
|
||
|
||
it "marks uploads with reference to ChatMessage via UploadReference in use" do
|
||
draft_upload
|
||
unused_upload
|
||
|
||
expect { Jobs::CleanUpUploads.new.execute({}) }.to change { Upload.count }.by(-1)
|
||
expect(Upload.exists?(id: message_upload.id)).to eq(true)
|
||
expect(Upload.exists?(id: draft_upload.id)).to eq(true)
|
||
expect(Upload.exists?(id: unused_upload.id)).to eq(false)
|
||
end
|
||
end
|
||
|
||
describe "user card serializer extension #can_chat_user" do
|
||
fab!(:target_user) { Fabricate(:user) }
|
||
let!(:user) { Fabricate(:user) }
|
||
let!(:guardian) { Guardian.new(user) }
|
||
let(:serializer) { UserCardSerializer.new(target_user, scope: guardian) }
|
||
fab!(:group)
|
||
|
||
context "when chat enabled" do
|
||
before { SiteSetting.chat_enabled = true }
|
||
|
||
it "returns true if the target user and the guardian user is in the Chat.allowed_group_ids" do
|
||
SiteSetting.chat_allowed_groups = group.id
|
||
SiteSetting.direct_message_enabled_groups = group.id
|
||
GroupUser.create(user: target_user, group: group)
|
||
GroupUser.create(user: user, group: group)
|
||
expect(serializer.can_chat_user).to eq(true)
|
||
end
|
||
|
||
it "returns false if the target user but not the guardian user is in the Chat.allowed_group_ids" do
|
||
SiteSetting.chat_allowed_groups = group.id
|
||
GroupUser.create(user: target_user, group: group)
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
|
||
it "returns false if the guardian user but not the target user is in the Chat.allowed_group_ids" do
|
||
SiteSetting.chat_allowed_groups = group.id
|
||
GroupUser.create(user: user, group: group)
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
|
||
context "when guardian user is same as target user" do
|
||
let!(:guardian) { Guardian.new(target_user) }
|
||
|
||
it "returns false" do
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
end
|
||
|
||
context "when guardian user is anon" do
|
||
let!(:guardian) { Guardian.new }
|
||
|
||
it "returns false" do
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
end
|
||
|
||
context "when both users are in Chat.allowed_group_ids" do
|
||
before do
|
||
SiteSetting.chat_allowed_groups = group.id
|
||
SiteSetting.direct_message_enabled_groups = group.id
|
||
GroupUser.create(user: target_user, group: group)
|
||
GroupUser.create(user: user, group: group)
|
||
end
|
||
|
||
it "returns true when both users are valid" do
|
||
expect(serializer.can_chat_user).to eq(true)
|
||
end
|
||
|
||
it "returns false if current user has chat disabled" do
|
||
user.user_option.update!(chat_enabled: false)
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
|
||
it "returns false if target user has chat disabled" do
|
||
target_user.user_option.update!(chat_enabled: false)
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
|
||
it "returns false if user is not in dm allowed group" do
|
||
SiteSetting.direct_message_enabled_groups = 3
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
end
|
||
end
|
||
|
||
context "when chat not enabled" do
|
||
before { SiteSetting.chat_enabled = false }
|
||
|
||
it "returns false" do
|
||
expect(serializer.can_chat_user).to eq(false)
|
||
end
|
||
end
|
||
end
|
||
|
||
describe "chat oneboxes" do
|
||
fab!(:chat_channel) { Fabricate(:category_channel) }
|
||
fab!(:user)
|
||
|
||
fab!(:chat_message) do
|
||
Fabricate(:chat_message, chat_channel: chat_channel, user: user, message: "Hello world!")
|
||
end
|
||
|
||
let(:chat_url) { "#{Discourse.base_url}/chat/c/-/#{chat_channel.id}" }
|
||
|
||
context "when inline" do
|
||
it "renders channel" do
|
||
results = InlineOneboxer.new([chat_url], skip_cache: true).process
|
||
expect(results).to be_present
|
||
expect(results[0][:url]).to eq(chat_url)
|
||
expect(results[0][:title]).to eq("Chat ##{chat_channel.name}")
|
||
end
|
||
|
||
it "renders messages" do
|
||
results = InlineOneboxer.new(["#{chat_url}/#{chat_message.id}"], skip_cache: true).process
|
||
expect(results).to be_present
|
||
expect(results[0][:url]).to eq("#{chat_url}/#{chat_message.id}")
|
||
expect(results[0][:title]).to eq(
|
||
"Message ##{chat_message.id} by #{chat_message.user.username} – ##{chat_channel.name}",
|
||
)
|
||
end
|
||
end
|
||
end
|
||
|
||
describe "auto-joining users to a channel" do
|
||
fab!(:chatters_group) { Fabricate(:group) }
|
||
fab!(:user) { Fabricate(:user, last_seen_at: 15.minutes.ago) }
|
||
let!(:channel) { Fabricate(:category_channel, auto_join_users: true, chatable: category) }
|
||
|
||
before { Jobs.run_immediately! }
|
||
|
||
def assert_user_following_state(user, channel, following:)
|
||
membership = Chat::UserChatChannelMembership.find_by(user: user, chat_channel: channel)
|
||
|
||
following ? (expect(membership.following).to eq(true)) : (expect(membership).to be_nil)
|
||
end
|
||
|
||
describe "when a user is added to a group with access to a channel through a category" do
|
||
let!(:category) { Fabricate(:private_category, group: chatters_group) }
|
||
|
||
it "joins the user to the channel if auto-join is enabled" do
|
||
chatters_group.add(user)
|
||
|
||
assert_user_following_state(user, channel, following: true)
|
||
end
|
||
|
||
it "does nothing if auto-join is disabled" do
|
||
channel.update!(auto_join_users: false)
|
||
|
||
assert_user_following_state(user, channel, following: false)
|
||
end
|
||
end
|
||
|
||
describe "when a user is created" do
|
||
fab!(:category)
|
||
let(:user) { Fabricate(:user, last_seen_at: nil, first_seen_at: nil) }
|
||
|
||
it "queues a job to auto-join the user the first time they log in" do
|
||
user.update_last_seen!
|
||
|
||
assert_user_following_state(user, channel, following: true)
|
||
end
|
||
|
||
it "does nothing if it's not the first time we see the user" do
|
||
user.update!(first_seen_at: 2.minute.ago)
|
||
user.update_last_seen!
|
||
|
||
assert_user_following_state(user, channel, following: false)
|
||
end
|
||
|
||
it "does nothing if auto-join is disabled" do
|
||
channel.update!(auto_join_users: false)
|
||
|
||
user.update_last_seen!
|
||
|
||
assert_user_following_state(user, channel, following: false)
|
||
end
|
||
end
|
||
|
||
describe "when category permissions change" do
|
||
fab!(:category)
|
||
|
||
let(:chatters_group_permission) do
|
||
{ chatters_group.name => CategoryGroup.permission_types[:full] }
|
||
end
|
||
|
||
describe "given permissions to a new group" do
|
||
it "adds the user to the channel" do
|
||
chatters_group.add(user)
|
||
|
||
category.update!(permissions: chatters_group_permission)
|
||
|
||
assert_user_following_state(user, channel, following: true)
|
||
end
|
||
|
||
it "does nothing if there is no channel for the category" do
|
||
another_category = Fabricate(:category)
|
||
|
||
another_category.update!(permissions: chatters_group_permission)
|
||
|
||
assert_user_following_state(user, channel, following: false)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
describe "secure uploads compatibility" do
|
||
fab!(:user)
|
||
|
||
it "disables chat uploads if secure uploads changes from disabled to enabled" do
|
||
enable_secure_uploads
|
||
expect(SiteSetting.chat_allow_uploads).to eq(false)
|
||
last_history = UserHistory.last
|
||
expect(last_history.action).to eq(UserHistory.actions[:change_site_setting])
|
||
expect(last_history.previous_value).to eq("true")
|
||
expect(last_history.new_value).to eq("false")
|
||
expect(last_history.subject).to eq("chat_allow_uploads")
|
||
expect(last_history.context).to eq("Disabled because secure_uploads is enabled")
|
||
end
|
||
|
||
context "when the global setting allow_unsecure_chat_uploads is true" do
|
||
fab!(:filename) { "small.pdf" }
|
||
fab!(:file) { file_from_fixtures(filename, "pdf") }
|
||
|
||
before { global_setting :allow_unsecure_chat_uploads, true }
|
||
|
||
it "does not disable chat uploads" do
|
||
expect { enable_secure_uploads }.not_to change { UserHistory.count }
|
||
expect(SiteSetting.chat_allow_uploads).to eq(true)
|
||
end
|
||
|
||
it "does not mark chat uploads as secure" do
|
||
filename = "small.pdf"
|
||
file = file_from_fixtures(filename, "pdf")
|
||
|
||
enable_secure_uploads
|
||
upload = UploadCreator.new(file, filename, type: "chat-composer").create_for(user.id)
|
||
expect(upload.secure).to eq(false)
|
||
end
|
||
|
||
context "when login_required is true" do
|
||
before { SiteSetting.login_required = true }
|
||
|
||
it "does not mark chat uploads as secure" do
|
||
enable_secure_uploads
|
||
upload = UploadCreator.new(file, filename, type: "chat-composer").create_for(user.id)
|
||
expect(upload.secure).to eq(false)
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
describe "current_user_serializer#has_joinable_public_channels" do
|
||
before do
|
||
SiteSetting.chat_enabled = true
|
||
SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:everyone]
|
||
end
|
||
|
||
fab!(:user)
|
||
let(:serializer) { CurrentUserSerializer.new(user, scope: Guardian.new(user)) }
|
||
|
||
context "when no channels exist" do
|
||
it "returns false" do
|
||
expect(serializer.has_joinable_public_channels).to eq(false)
|
||
end
|
||
end
|
||
|
||
context "when no joinable channel exist" do
|
||
fab!(:channel) { Fabricate(:chat_channel) }
|
||
|
||
before do
|
||
Fabricate(:user_chat_channel_membership, user: user, chat_channel: channel, following: true)
|
||
end
|
||
|
||
it "returns false" do
|
||
expect(serializer.has_joinable_public_channels).to eq(false)
|
||
end
|
||
end
|
||
|
||
context "when no public channel exist" do
|
||
fab!(:private_category) { Fabricate(:private_category, group: Fabricate(:group)) }
|
||
fab!(:private_channel) { Fabricate(:chat_channel, chatable: private_category) }
|
||
|
||
it "returns false" do
|
||
expect(serializer.has_joinable_public_channels).to eq(false)
|
||
end
|
||
end
|
||
|
||
context "when a joinable channel exists" do
|
||
fab!(:channel) { Fabricate(:chat_channel) }
|
||
|
||
it "returns true" do
|
||
expect(serializer.has_joinable_public_channels).to eq(true)
|
||
end
|
||
end
|
||
end
|
||
|
||
describe "Deleting posts while deleting a user" do
|
||
fab!(:user)
|
||
|
||
it "queues a job to also delete chat messages" do
|
||
deletion_opts = { delete_posts: true }
|
||
|
||
expect { UserDestroyer.new(Discourse.system_user).destroy(user, deletion_opts) }.to change(
|
||
Jobs::Chat::DeleteUserMessages.jobs,
|
||
:size,
|
||
).by(1)
|
||
end
|
||
end
|
||
|
||
describe "when using topic tags changed trigger automation" do
|
||
describe "with the send message script" do
|
||
fab!(:automation_1) do
|
||
Fabricate(
|
||
:automation,
|
||
trigger: DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED,
|
||
script: :send_chat_message,
|
||
)
|
||
end
|
||
fab!(:tag_1) { Fabricate(:tag) }
|
||
fab!(:user_1) { Fabricate(:admin) }
|
||
fab!(:topic_1) { Fabricate(:topic) }
|
||
fab!(:channel_1) { Fabricate(:chat_channel) }
|
||
|
||
before do
|
||
SiteSetting.discourse_automation_enabled = true
|
||
SiteSetting.tagging_enabled = true
|
||
|
||
automation_1.upsert_field!(
|
||
"watching_tags",
|
||
"tags",
|
||
{ value: [tag_1.name] },
|
||
target: "trigger",
|
||
)
|
||
automation_1.upsert_field!(
|
||
"chat_channel_id",
|
||
"text",
|
||
{ value: channel_1.id },
|
||
target: "script",
|
||
)
|
||
automation_1.upsert_field!(
|
||
"message",
|
||
"message",
|
||
{ value: "[{{topic_title}}]({{topic_url}})" },
|
||
target: "script",
|
||
)
|
||
end
|
||
|
||
it "sends the message" do
|
||
DiscourseTagging.tag_topic_by_names(topic_1, Guardian.new(user_1), [tag_1.name])
|
||
|
||
expect(channel_1.chat_messages.last.message).to eq(
|
||
"[#{topic_1.title}](#{topic_1.relative_url})",
|
||
)
|
||
end
|
||
end
|
||
end
|
||
|
||
describe "when using post_edited_created trigger automation" do
|
||
describe "with the send message script" do
|
||
fab!(:automation_1) do
|
||
Fabricate(
|
||
:automation,
|
||
trigger: DiscourseAutomation::Triggers::POST_CREATED_EDITED,
|
||
script: :send_chat_message,
|
||
)
|
||
end
|
||
fab!(:user_1) { Fabricate(:admin) }
|
||
fab!(:channel_1) { Fabricate(:chat_channel) }
|
||
|
||
before do
|
||
SiteSetting.discourse_automation_enabled = true
|
||
|
||
automation_1.upsert_field!(
|
||
"chat_channel_id",
|
||
"text",
|
||
{ value: channel_1.id },
|
||
target: "script",
|
||
)
|
||
automation_1.upsert_field!(
|
||
"message",
|
||
"message",
|
||
{ value: "[{{topic_title}}]({{topic_url}})\n{{post_quote}}" },
|
||
target: "script",
|
||
)
|
||
end
|
||
|
||
it "sends the message" do
|
||
post = PostCreator.create(user_1, { title: "hello world topic", raw: "my name is fred" })
|
||
|
||
expect(channel_1.chat_messages.last.message).to eq(
|
||
"[#{post.topic.title}](#{post.topic.relative_url})\n[quote=#{post.username}, post:#{post.post_number}, topic:#{post.topic_id}]\nmy name is fred\n[/quote]",
|
||
)
|
||
end
|
||
end
|
||
end
|
||
end
|