FEATURE: introduces group channels (#24288)

Group channels will allow users to create channels with a name and invite people. It's possible to add people even after creation of the channel. Removing users is not yet possible but will be added in the near future.

Technically a group channel is `direct_message_channel` with a group attribute set to true on its direct message (chatable). This model might evolve in the future but offers much flexibility for now without having to rely on a complex migration.

The commit essentially consists of:
- a migration to set existing direct message channels with more than 2 users to a group
- a new message creator which allows to search, add members, and create groups
- a new `AddUsersToChannel` service
- a modified `SearchChatable` service
This commit is contained in:
Joffrey JAFFEUX
2023-11-10 11:29:28 +01:00
committed by GitHub
parent a8d6dc4d3a
commit ab832cc865
121 changed files with 2969 additions and 2332 deletions

View File

@ -0,0 +1,55 @@
# frozen_string_literal: true
RSpec.describe Chat::Api::ChannelsMembershipsController do
fab!(:current_user) { Fabricate(:user) }
fab!(:channel_1) do
Fabricate(:direct_message_channel, group: true, users: [current_user, Fabricate(:user)])
end
before do
SiteSetting.chat_enabled = true
SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:everyone]
channel_1.add(current_user)
sign_in(current_user)
end
describe "#create" do
describe "success" do
it "works" do
add_users_to_channel(current_user, channel_1)
post "/chat/api/channels/#{channel_1.id}/memberships",
params: {
usernames: [Fabricate(:user).username],
}
expect(response.status).to eq(200)
end
end
context "when users can't be added" do
before { channel_1.chatable.update(group: false) }
it "returns a 422" do
post "/chat/api/channels/#{channel_1.id}/memberships",
params: {
usernames: [Fabricate(:user).username],
}
expect(response.status).to eq(422)
expect(response.parsed_body["errors"].first).to eq(
I18n.t("chat.errors.users_cant_be_added_to_channel"),
)
end
end
context "when channel is not found" do
before { channel_1.chatable.update!(group: false) }
it "returns a 404" do
get "/chat/api/channels/-999/messages", params: { usernames: [Fabricate(:user).username] }
expect(response.status).to eq(404)
end
end
end
end

View File

@ -14,13 +14,16 @@ RSpec.describe Chat::Api::ChatablesController do
describe "without chat permissions" do
it "errors errors for anon" do
get "/chat/api/chatables"
expect(response.status).to eq(403)
end
it "errors when user cannot chat" do
SiteSetting.chat_allowed_groups = Group::AUTO_GROUPS[:staff]
sign_in(current_user)
get "/chat/api/chatables"
expect(response.status).to eq(403)
end
end
@ -28,9 +31,11 @@ RSpec.describe Chat::Api::ChatablesController do
describe "with chat permissions" do
fab!(:channel_1) { Fabricate(:chat_channel) }
before { sign_in(current_user) }
before { channel_1.add(current_user) }
it "returns results" do
sign_in(current_user)
get "/chat/api/chatables", params: { term: channel_1.name }
expect(response.status).to eq(200)

View File

@ -23,7 +23,10 @@ RSpec.describe Chat::Api::DirectMessagesController do
describe "#create" do
before { Group.refresh_automatic_groups! }
shared_examples "creating dms" do
describe "dm with one other user" do
let(:usernames) { user1.username }
let(:direct_message_user_ids) { [current_user.id, user1.id] }
it "creates a new dm channel with username(s) provided" do
expect {
post "/chat/api/direct-message-channels.json", params: { target_usernames: [usernames] }
@ -35,31 +38,55 @@ RSpec.describe Chat::Api::DirectMessagesController do
it "returns existing dm channel if one exists for username(s)" do
create_dm_channel(direct_message_user_ids)
expect {
post "/chat/api/direct-message-channels.json", params: { target_usernames: [usernames] }
}.not_to change { Chat::DirectMessage.count }
end
end
describe "dm with one other user" do
let(:usernames) { user1.username }
let(:direct_message_user_ids) { [current_user.id, user1.id] }
include_examples "creating dms"
end
describe "dm with myself" do
let(:usernames) { [current_user.username] }
let(:direct_message_user_ids) { [current_user.id] }
include_examples "creating dms"
it "creates a new dm channel with username(s) provided" do
expect {
post "/chat/api/direct-message-channels.json", params: { target_usernames: [usernames] }
}.to change { Chat::DirectMessage.count }.by(1)
expect(Chat::DirectMessage.last.direct_message_users.map(&:user_id)).to match_array(
direct_message_user_ids,
)
end
it "returns existing dm channel if one exists for username(s)" do
create_dm_channel(direct_message_user_ids)
expect {
post "/chat/api/direct-message-channels.json", params: { target_usernames: [usernames] }
}.not_to change { Chat::DirectMessage.count }
end
end
describe "dm with two other users" do
let(:usernames) { [user1, user2, user3].map(&:username) }
let(:direct_message_user_ids) { [current_user.id, user1.id, user2.id, user3.id] }
include_examples "creating dms"
it "creates a new dm channel with username(s) provided" do
expect {
post "/chat/api/direct-message-channels.json", params: { target_usernames: [usernames] }
}.to change { Chat::DirectMessage.count }.by(1)
expect(Chat::DirectMessage.last.direct_message_users.map(&:user_id)).to match_array(
direct_message_user_ids,
)
end
it "createsa new dm channel" do
create_dm_channel(direct_message_user_ids)
expect {
post "/chat/api/direct-message-channels.json", params: { target_usernames: [usernames] }
}.to change { Chat::DirectMessage.count }.by(1)
end
end
it "creates Chat::UserChatChannelMembership records" do

View File

@ -611,6 +611,7 @@ RSpec.describe Chat::ChatController do
expect(response.status).to eq(403)
Chat::DirectMessageUser.create(user: user, direct_message: dm_channel.chatable)
expect {
post "/chat/drafts.json", params: { chat_channel_id: dm_channel.id, data: "{}" }
}.to change { Chat::Draft.count }.by(1)