* Fix join private channel not showing on all needed scenarios

* Fix for other two instances of the logic

* Fix test

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Daniel Espino García
2025-06-13 17:42:21 +02:00
коммит произвёл GitHub
родитель c46ed6c681
Коммит c1a0710ab5
5 изменённых файлов: 64 добавлений и 96 удалений

Просмотреть файл

@@ -179,9 +179,7 @@ describe('Actions', () => {
...initialState.entities.users, ...initialState.entities.users,
profiles: { profiles: {
...initialState.entities.users.profiles, ...initialState.entities.users.profiles,
current_user_id: { current_user_id: {},
roles: 'system_admin',
},
}, },
}, },
}, },
@@ -205,9 +203,7 @@ describe('Actions', () => {
...initialState.entities.users, ...initialState.entities.users,
profiles: { profiles: {
...initialState.entities.users.profiles, ...initialState.entities.users.profiles,
current_user_id: { current_user_id: {},
roles: 'system_user',
},
}, },
}, },
channels: { channels: {

Просмотреть файл

@@ -10,9 +10,8 @@ import {joinChannel, getChannelByNameAndTeamName, getChannelMember, markGroupCha
import {getUser, getUserByUsername, getUserByEmail} from 'mattermost-redux/actions/users'; import {getUser, getUserByUsername, getUserByEmail} from 'mattermost-redux/actions/users';
import {Client4} from 'mattermost-redux/client'; import {Client4} from 'mattermost-redux/client';
import {getChannelByName, getOtherChannels, getChannel, getChannelsNameMapInTeam, getRedirectChannelNameForTeam} from 'mattermost-redux/selectors/entities/channels'; import {getChannelByName, getOtherChannels, getChannel, getChannelsNameMapInTeam, getRedirectChannelNameForTeam} from 'mattermost-redux/selectors/entities/channels';
import {getTeamByName, getMyTeamMember} from 'mattermost-redux/selectors/entities/teams'; import {getTeamByName} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser, getCurrentUserId, getUserByUsername as selectUserByUsername, getUser as selectUser, getUserByEmail as selectUserByEmail} from 'mattermost-redux/selectors/entities/users'; import {getCurrentUserId, getUserByUsername as selectUserByUsername, getUser as selectUser, getUserByEmail as selectUserByEmail} from 'mattermost-redux/selectors/entities/users';
import * as UserUtils from 'mattermost-redux/utils/user_utils';
import {openDirectChannelToUserId} from 'actions/channel_actions'; import {openDirectChannelToUserId} from 'actions/channel_actions';
import * as GlobalActions from 'actions/global_actions'; import * as GlobalActions from 'actions/global_actions';
@@ -187,21 +186,11 @@ export function goToChannelByChannelName(match: Match, history: History): Action
if (!channel || !member) { if (!channel || !member) {
if (channel?.type === Constants.PRIVATE_CHANNEL) { if (channel?.type === Constants.PRIVATE_CHANNEL) {
// Prompt system admins and team admins before joining the private channel // If we are here, we have permissions to join the channel
const user = getCurrentUser(getState()); // and the channel is private. Therefore prompt always.
const isSystemAdmin = UserUtils.isSystemAdmin(user?.roles); const joinPromptResult = await dispatch(joinPrivateChannelPrompt(teamObj, channel.display_name));
let prompt = false; if ('data' in joinPromptResult && !joinPromptResult.data!.join) {
if (isSystemAdmin) { return {data: undefined};
prompt = true;
} else {
const teamMember = getMyTeamMember(state, teamObj.id);
prompt = Boolean(teamMember && teamMember.scheme_admin);
}
if (prompt) {
const joinPromptResult = await dispatch(joinPrivateChannelPrompt(teamObj, channel.display_name));
if ('data' in joinPromptResult && !joinPromptResult.data!.join) {
return {data: undefined};
}
} }
} }

Просмотреть файл

@@ -10,10 +10,8 @@ import {getMissingProfilesByIds} from 'mattermost-redux/actions/users';
import {Client4} from 'mattermost-redux/client'; import {Client4} from 'mattermost-redux/client';
import {getCurrentChannel, getChannel as getChannelFromRedux} from 'mattermost-redux/selectors/entities/channels'; import {getCurrentChannel, getChannel as getChannelFromRedux} from 'mattermost-redux/selectors/entities/channels';
import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences'; import {isCollapsedThreadsEnabled} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeam, getTeam, getMyTeamMember} from 'mattermost-redux/selectors/entities/teams'; import {getCurrentTeam, getTeam} from 'mattermost-redux/selectors/entities/teams';
import {getCurrentUser} from 'mattermost-redux/selectors/entities/users';
import {getUserIdFromChannelName} from 'mattermost-redux/utils/channel_utils'; import {getUserIdFromChannelName} from 'mattermost-redux/utils/channel_utils';
import {isSystemAdmin} from 'mattermost-redux/utils/user_utils';
import {loadChannelsForCurrentUser} from 'actions/channel_actions'; import {loadChannelsForCurrentUser} from 'actions/channel_actions';
import {loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions'; import {loadNewDMIfNeeded, loadNewGMIfNeeded} from 'actions/user_actions';
@@ -109,18 +107,10 @@ export function focusPost(postId: string, returnTo = '', currentUserId: string,
} }
if (!postInfo.has_joined_channel) { if (!postInfo.has_joined_channel) {
// Prompt system admins and team admins before joining the private channel
const user = getCurrentUser(state);
let prompt = false;
if (postInfo.channel_type === Constants.PRIVATE_CHANNEL) { if (postInfo.channel_type === Constants.PRIVATE_CHANNEL) {
if (isSystemAdmin(user.roles)) { // Prompt system admins and team admins before joining the private channel.
prompt = true; // There is no need for permission check because if we received the info of
} else { // the post means that we can join the channel.
const teamMember = getMyTeamMember(state, currentTeam.id);
prompt = Boolean(teamMember && teamMember.scheme_admin);
}
}
if (prompt) {
privateChannelJoinPromptVisible = true; privateChannelJoinPromptVisible = true;
const joinPromptResult = await dispatch(joinPrivateChannelPrompt(currentTeam, postInfo.channel_display_name)); const joinPromptResult = await dispatch(joinPrivateChannelPrompt(currentTeam, postInfo.channel_display_name));
privateChannelJoinPromptVisible = false; privateChannelJoinPromptVisible = false;

Просмотреть файл

@@ -23,6 +23,7 @@ import TestHelper from 'packages/mattermost-redux/test/test_helper';
import {mountWithIntl} from 'tests/helpers/intl-test-helper'; import {mountWithIntl} from 'tests/helpers/intl-test-helper';
import mockStore from 'tests/test_store'; import mockStore from 'tests/test_store';
import {getHistory} from 'utils/browser_history'; import {getHistory} from 'utils/browser_history';
import {joinPrivateChannelPrompt} from 'utils/channel_utils';
import {ErrorPageTypes} from 'utils/constants'; import {ErrorPageTypes} from 'utils/constants';
jest.mock('actions/channel_actions', () => ({ jest.mock('actions/channel_actions', () => ({
@@ -543,13 +544,7 @@ describe('components/PermalinkView', () => {
}, },
}; };
jest.mock('utils/channel_utils', () => ({ jest.mocked(joinPrivateChannelPrompt).mockReturnValueOnce(async () => ({data: {join: true}}));
joinPrivateChannelPrompt: jest.fn(() => {
return async () => {
return {data: {join: true}};
};
}),
}));
const postId = 'privatepostid1'; const postId = 'privatepostid1';
nockInfoForPrivatePost(postId); nockInfoForPrivatePost(postId);

Просмотреть файл

@@ -1297,65 +1297,63 @@ export async function handleFormattedTextClick(e: React.MouseEvent, currentRelat
let isReply = false; let isReply = false;
if (isSystemAdmin(user.roles)) { if (match) {
if (match) { // Get team by name
// Get team by name const {teamName} = match;
const {teamName} = match; let team = getTeamByName(state, teamName);
let team = getTeamByName(state, teamName); if (!team) {
if (!team) { const {data: teamData} = await store.dispatch(getTeamByNameAction(teamName));
const {data: teamData} = await store.dispatch(getTeamByNameAction(teamName)); team = teamData;
team = teamData; }
} if (team && team.delete_at === 0) {
if (team && team.delete_at === 0) { let channel;
let channel;
// Handle channel url - Get channel data from channel name // Handle channel url - Get channel data from channel name
if (match.type === 'channel') { if (match.type === 'channel') {
const {channelName} = match; const {channelName} = match;
channel = getChannelsNameMapInTeam(state, team.id)[channelName as string]; channel = getChannelsNameMapInTeam(state, team.id)[channelName as string];
if (!channel) {
const {data: channelData} = await store.dispatch(getChannelByNameAndTeamName(teamName, channelName!, true));
channel = channelData;
}
} else { // Handle permalink - Get channel data from post
const {postId} = match;
let post = getPost(state, postId!);
if (!post) {
const {data: postData} = await store.dispatch(getPostAction(match.postId!));
post = postData!;
}
if (post) {
isReply = Boolean(post.root_id);
channel = getChannel(state, post.channel_id);
if (!channel) { if (!channel) {
const {data: channelData} = await store.dispatch(getChannelByNameAndTeamName(teamName, channelName!, true)); const {data: channelData} = await store.dispatch(getChannelAction(post.channel_id));
channel = channelData; channel = channelData;
} }
} else { // Handle permalink - Get channel data from post }
const {postId} = match; }
let post = getPost(state, postId!); if (channel && channel.type === Constants.PRIVATE_CHANNEL) {
if (!post) { let member = getMyChannelMemberships(state)[channel.id];
const {data: postData} = await store.dispatch(getPostAction(match.postId!)); if (!member) {
post = postData!; const membership = await store.dispatch(getChannelMember(channel.id, getCurrentUserId(state)));
} if ('data' in membership) {
if (post) { member = membership.data!;
isReply = Boolean(post.root_id);
channel = getChannel(state, post.channel_id);
if (!channel) {
const {data: channelData} = await store.dispatch(getChannelAction(post.channel_id));
channel = channelData;
}
} }
} }
if (channel && channel.type === Constants.PRIVATE_CHANNEL) { if (!member) {
let member = getMyChannelMemberships(state)[channel.id]; const {data} = await store.dispatch(joinPrivateChannelPrompt(team, channel.display_name, false));
if (!member) { if (data!.join) {
const membership = await store.dispatch(getChannelMember(channel.id, getCurrentUserId(state))); let error = false;
if ('data' in membership) { if (!getTeamMemberships(state)[team.id]) {
member = membership.data!; const joinTeamResult = await store.dispatch(addUserToTeam(team.id, user.id));
error = joinTeamResult.error;
} }
} if (!error) {
if (!member) { await store.dispatch(joinChannel(user.id, team.id, channel.id, channel.name));
const {data} = await store.dispatch(joinPrivateChannelPrompt(team, channel.display_name, false));
if (data!.join) {
let error = false;
if (!getTeamMemberships(state)[team.id]) {
const joinTeamResult = await store.dispatch(addUserToTeam(team.id, user.id));
error = joinTeamResult.error;
}
if (!error) {
await store.dispatch(joinChannel(user.id, team.id, channel.id, channel.name));
}
} else {
return;
} }
} else {
return;
} }
} }
} }