PLT-6139 (WebApp): Manage Private Channel Members (#5947)
Honour the policy setting for add/remove members from private channels in the WebApp UI.
Этот коммит содержится в:
коммит произвёл
Harrison Healey
родитель
6bf080393d
Коммит
6bb65ef420
@@ -34,6 +34,7 @@ export default class PolicySettings extends AdminSettings {
|
|||||||
config.TeamSettings.RestrictPrivateChannelManagement = this.state.restrictPrivateChannelManagement;
|
config.TeamSettings.RestrictPrivateChannelManagement = this.state.restrictPrivateChannelManagement;
|
||||||
config.TeamSettings.RestrictPublicChannelDeletion = this.state.restrictPublicChannelDeletion;
|
config.TeamSettings.RestrictPublicChannelDeletion = this.state.restrictPublicChannelDeletion;
|
||||||
config.TeamSettings.RestrictPrivateChannelDeletion = this.state.restrictPrivateChannelDeletion;
|
config.TeamSettings.RestrictPrivateChannelDeletion = this.state.restrictPrivateChannelDeletion;
|
||||||
|
config.TeamSettings.RestrictPrivateChannelManageMembers = this.state.restrictPrivateChannelManageMembers;
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@@ -49,7 +50,8 @@ export default class PolicySettings extends AdminSettings {
|
|||||||
restrictPublicChannelManagement: config.TeamSettings.RestrictPublicChannelManagement,
|
restrictPublicChannelManagement: config.TeamSettings.RestrictPublicChannelManagement,
|
||||||
restrictPrivateChannelManagement: config.TeamSettings.RestrictPrivateChannelManagement,
|
restrictPrivateChannelManagement: config.TeamSettings.RestrictPrivateChannelManagement,
|
||||||
restrictPublicChannelDeletion: config.TeamSettings.RestrictPublicChannelDeletion,
|
restrictPublicChannelDeletion: config.TeamSettings.RestrictPublicChannelDeletion,
|
||||||
restrictPrivateChannelDeletion: config.TeamSettings.RestrictPrivateChannelDeletion
|
restrictPrivateChannelDeletion: config.TeamSettings.RestrictPrivateChannelDeletion,
|
||||||
|
restrictPrivateChannelManageMembers: config.TeamSettings.RestrictPrivateChannelManageMembers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +216,29 @@ export default class PolicySettings extends AdminSettings {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<DropdownSetting
|
||||||
|
id='restrictPrivateChannelManageMembers'
|
||||||
|
values={[
|
||||||
|
{value: Constants.PERMISSIONS_ALL, text: Utils.localizeMessage('admin.general.policy.permissionsAllChannel', 'All channel members')},
|
||||||
|
{value: Constants.PERMISSIONS_CHANNEL_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsChannelAdmin', 'Channel, Team and System Admins')},
|
||||||
|
{value: Constants.PERMISSIONS_TEAM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsAdmin', 'Team and System Admins')},
|
||||||
|
{value: Constants.PERMISSIONS_SYSTEM_ADMIN, text: Utils.localizeMessage('admin.general.policy.permissionsSystemAdmin', 'System Admins')}
|
||||||
|
]}
|
||||||
|
label={
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.general.policy.restrictPrivateChannelManageMembersTitle'
|
||||||
|
defaultMessage='Enable managing of private group members for:'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
value={this.state.restrictPrivateChannelManageMembers}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
helpText={
|
||||||
|
<FormattedMessage
|
||||||
|
id='admin.general.policy.restrictPrivateChannelManageMembersDescription'
|
||||||
|
defaultMessage='Set policy on who can add and remove members from private groups.'
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<DropdownSetting
|
<DropdownSetting
|
||||||
id='restrictPrivateChannelDeletion'
|
id='restrictPrivateChannelDeletion'
|
||||||
values={[
|
values={[
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ export default class ChannelHeader extends React.Component {
|
|||||||
);
|
);
|
||||||
let channelTitle = channel.display_name;
|
let channelTitle = channel.display_name;
|
||||||
const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
|
const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
|
||||||
|
const isTeamAdmin = TeamStore.isTeamAdminForCurrentTeam();
|
||||||
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
|
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
|
||||||
const isChannelAdmin = ChannelStore.isChannelAdminForCurrentChannel();
|
const isChannelAdmin = ChannelStore.isChannelAdminForCurrentChannel();
|
||||||
const isDirect = (this.state.channel.type === Constants.DM_CHANNEL);
|
const isDirect = (this.state.channel.type === Constants.DM_CHANNEL);
|
||||||
@@ -492,44 +493,65 @@ export default class ChannelHeader extends React.Component {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
dropdownContents.push(
|
if (ChannelUtils.canManageMembers(channel, isSystemAdmin, isTeamAdmin, isChannelAdmin)) {
|
||||||
<li
|
dropdownContents.push(
|
||||||
id='channelAddMembers'
|
<li
|
||||||
key='add_members'
|
id='channelAddMembers'
|
||||||
role='presentation'
|
key='add_members'
|
||||||
>
|
role='presentation'
|
||||||
<ToggleModalButton
|
|
||||||
ref='channelInviteModalButton'
|
|
||||||
role='menuitem'
|
|
||||||
dialogType={ChannelInviteModal}
|
|
||||||
dialogProps={{channel, currentUser: this.state.currentUser}}
|
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<ToggleModalButton
|
||||||
id='channel_header.addMembers'
|
ref='channelInviteModalButton'
|
||||||
defaultMessage='Add Members'
|
role='menuitem'
|
||||||
/>
|
dialogType={ChannelInviteModal}
|
||||||
</ToggleModalButton>
|
dialogProps={{channel, currentUser: this.state.currentUser}}
|
||||||
</li>
|
>
|
||||||
);
|
<FormattedMessage
|
||||||
|
id='channel_header.addMembers'
|
||||||
|
defaultMessage='Add Members'
|
||||||
|
/>
|
||||||
|
</ToggleModalButton>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
|
||||||
dropdownContents.push(
|
dropdownContents.push(
|
||||||
<li
|
<li
|
||||||
id='channelManageMembers'
|
id='channelManageMembers'
|
||||||
key='manage_members'
|
key='manage_members'
|
||||||
role='presentation'
|
role='presentation'
|
||||||
>
|
|
||||||
<a
|
|
||||||
role='menuitem'
|
|
||||||
href='#'
|
|
||||||
onClick={() => this.setState({showMembersModal: true})}
|
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
<a
|
||||||
id='channel_header.manageMembers'
|
role='menuitem'
|
||||||
defaultMessage='Manage Members'
|
href='#'
|
||||||
/>
|
onClick={() => this.setState({showMembersModal: true})}
|
||||||
</a>
|
>
|
||||||
</li>
|
<FormattedMessage
|
||||||
);
|
id='channel_header.manageMembers'
|
||||||
|
defaultMessage='Manage Members'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
dropdownContents.push(
|
||||||
|
<li
|
||||||
|
id='channelViewMembers'
|
||||||
|
key='view_members'
|
||||||
|
role='presentation'
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
role='menuitem'
|
||||||
|
href='#'
|
||||||
|
onClick={() => this.setState({showMembersModal: true})}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_header.viewMembers'
|
||||||
|
defaultMessage='View Members'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteOption = (
|
const deleteOption = (
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {removeUserFromChannel, makeUserChannelAdmin, makeUserChannelMember} from
|
|||||||
|
|
||||||
import * as AsyncClient from 'utils/async_client.jsx';
|
import * as AsyncClient from 'utils/async_client.jsx';
|
||||||
import * as Utils from 'utils/utils.jsx';
|
import * as Utils from 'utils/utils.jsx';
|
||||||
|
import {canManageMembers} from 'utils/channel_utils.jsx';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
@@ -91,8 +92,7 @@ export default class ChannelMembersDropdown extends React.Component {
|
|||||||
|
|
||||||
// Checks if the current user has the power to remove this member from the channel.
|
// Checks if the current user has the power to remove this member from the channel.
|
||||||
canRemoveMember() {
|
canRemoveMember() {
|
||||||
// TODO: This will be implemented as part of PLT-5047.
|
return canManageMembers(this.props.channel, UserStore.isSystemAdminForCurrentUser(), TeamStore.isTeamAdminForCurrentTeam(), ChannelStore.isChannelAdminForCurrentChannel());
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|||||||
@@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
import MemberListChannel from './member_list_channel.jsx';
|
import MemberListChannel from './member_list_channel.jsx';
|
||||||
|
|
||||||
|
import TeamStore from 'stores/team_store.jsx';
|
||||||
|
import UserStore from 'stores/user_store.jsx';
|
||||||
|
import ChannelStore from 'stores/channel_store.jsx';
|
||||||
|
|
||||||
|
import {canManageMembers} from 'utils/channel_utils.jsx';
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Modal} from 'react-bootstrap';
|
import {Modal} from 'react-bootstrap';
|
||||||
import {FormattedMessage} from 'react-intl';
|
import {FormattedMessage} from 'react-intl';
|
||||||
@@ -24,6 +30,30 @@ export default class ChannelMembersModal extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
|
||||||
|
const isTeamAdmin = TeamStore.isTeamAdminForCurrentTeam();
|
||||||
|
const isChannelAdmin = ChannelStore.isChannelAdminForCurrentChannel();
|
||||||
|
|
||||||
|
let addMembersButton = null;
|
||||||
|
if (canManageMembers(this.state.channel, isSystemAdmin, isTeamAdmin, isChannelAdmin)) {
|
||||||
|
addMembersButton = (
|
||||||
|
<a
|
||||||
|
id='showInviteModal'
|
||||||
|
className='btn btn-md btn-primary'
|
||||||
|
href='#'
|
||||||
|
onClick={() => {
|
||||||
|
this.props.showInviteModal();
|
||||||
|
this.onHide();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id='channel_members_modal.addNew'
|
||||||
|
defaultMessage=' Add New Members'
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Modal
|
<Modal
|
||||||
@@ -40,20 +70,7 @@ export default class ChannelMembersModal extends React.Component {
|
|||||||
defaultMessage=' Members'
|
defaultMessage=' Members'
|
||||||
/>
|
/>
|
||||||
</Modal.Title>
|
</Modal.Title>
|
||||||
<a
|
{addMembersButton}
|
||||||
id='showInviteModal'
|
|
||||||
className='btn btn-md btn-primary'
|
|
||||||
href='#'
|
|
||||||
onClick={() => {
|
|
||||||
this.props.showInviteModal();
|
|
||||||
this.onHide();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id='channel_members_modal.addNew'
|
|
||||||
defaultMessage=' Add New Members'
|
|
||||||
/>
|
|
||||||
</a>
|
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body
|
<Modal.Body
|
||||||
ref='modalBody'
|
ref='modalBody'
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import * as AsyncClient from 'utils/async_client.jsx';
|
|||||||
import Client from 'client/web_client.jsx';
|
import Client from 'client/web_client.jsx';
|
||||||
import * as Utils from 'utils/utils.jsx';
|
import * as Utils from 'utils/utils.jsx';
|
||||||
import Constants from 'utils/constants.jsx';
|
import Constants from 'utils/constants.jsx';
|
||||||
|
import {canManageMembers} from 'utils/channel_utils.jsx';
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
@@ -86,10 +87,11 @@ export default class PopoverListMembers extends React.Component {
|
|||||||
const popoverHtml = [];
|
const popoverHtml = [];
|
||||||
const members = this.props.members;
|
const members = this.props.members;
|
||||||
const teamMembers = UserStore.getProfilesUsernameMap();
|
const teamMembers = UserStore.getProfilesUsernameMap();
|
||||||
let isAdmin = false;
|
|
||||||
const currentUserId = UserStore.getCurrentId();
|
const currentUserId = UserStore.getCurrentId();
|
||||||
|
|
||||||
isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser();
|
const isSystemAdmin = UserStore.isSystemAdminForCurrentUser();
|
||||||
|
const isTeamAdmin = TeamStore.isTeamAdminForCurrentTeam();
|
||||||
|
const isChannelAdmin = ChannelStore.isChannelAdminForCurrentChannel();
|
||||||
|
|
||||||
if (members && teamMembers) {
|
if (members && teamMembers) {
|
||||||
members.sort((a, b) => {
|
members.sort((a, b) => {
|
||||||
@@ -156,7 +158,7 @@ export default class PopoverListMembers extends React.Component {
|
|||||||
defaultMessage='Manage Members'
|
defaultMessage='Manage Members'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
if (!isAdmin && ChannelStore.isDefault(this.props.channel)) {
|
if (!canManageMembers(this.props.channel, isSystemAdmin, isTeamAdmin, isChannelAdmin) && !ChannelStore.isDefault(this.props.channel)) {
|
||||||
membersName = (
|
membersName = (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='members_popover.viewMembers'
|
id='members_popover.viewMembers'
|
||||||
@@ -217,7 +219,7 @@ export default class PopoverListMembers extends React.Component {
|
|||||||
teamMembersModal = (
|
teamMembersModal = (
|
||||||
<TeamMembersModal
|
<TeamMembersModal
|
||||||
onHide={() => this.setState({showTeamMembersModal: false})}
|
onHide={() => this.setState({showTeamMembersModal: false})}
|
||||||
isAdmin={isAdmin}
|
isAdmin={isTeamAdmin || isSystemAdmin}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -331,10 +331,12 @@
|
|||||||
"admin.general.policy.restrictPrivateChannelCreationDescription": "Set policy on who can create private groups.",
|
"admin.general.policy.restrictPrivateChannelCreationDescription": "Set policy on who can create private groups.",
|
||||||
"admin.general.policy.restrictPrivateChannelCreationTitle": "Enable private group creation for:",
|
"admin.general.policy.restrictPrivateChannelCreationTitle": "Enable private group creation for:",
|
||||||
"admin.general.policy.restrictPrivateChannelDeletionCommandLineToolLink": "command line tool",
|
"admin.general.policy.restrictPrivateChannelDeletionCommandLineToolLink": "command line tool",
|
||||||
"admin.general.policy.restrictPrivateChannelDeletionDescription": "Set policy on who can delete private groups. Deleted groups can be recovered from the database using a {commandLineToolLink}.",
|
"admin.general.policy.restrictPrivateChannelDeletionDescription": "Set policy on who can delete private channels. Deleted channels can be recovered from the database using a {commandLineToolLink}.",
|
||||||
"admin.general.policy.restrictPrivateChannelDeletionTitle": "Enable private group deletion for:",
|
"admin.general.policy.restrictPrivateChannelDeletionTitle": "Enable private channel deletion for:",
|
||||||
"admin.general.policy.restrictPrivateChannelManagementDescription": "Set policy on who can rename and set the header or purpose for private groups.",
|
"admin.general.policy.restrictPrivateChannelManagementDescription": "Set policy on who can rename and set the header or purpose for private channels.",
|
||||||
"admin.general.policy.restrictPrivateChannelManagementTitle": "Enable private group renaming for:",
|
"admin.general.policy.restrictPrivateChannelManagementTitle": "Enable private channel renaming for:",
|
||||||
|
"admin.general.policy.restrictPrivateChannelManageMembersDescription": "Set policy on who can add and remove members from private channels.",
|
||||||
|
"admin.general.policy.restrictPrivateChannelManageMembersTitle": "Enable managing of private channel members for:",
|
||||||
"admin.general.policy.restrictPublicChannelCreationDescription": "Set policy on who can create public channels.",
|
"admin.general.policy.restrictPublicChannelCreationDescription": "Set policy on who can create public channels.",
|
||||||
"admin.general.policy.restrictPublicChannelCreationTitle": "Enable public channel creation for:",
|
"admin.general.policy.restrictPublicChannelCreationTitle": "Enable public channel creation for:",
|
||||||
"admin.general.policy.restrictPublicChannelDeletionCommandLineToolLink": "command line tool",
|
"admin.general.policy.restrictPublicChannelDeletionCommandLineToolLink": "command line tool",
|
||||||
|
|||||||
@@ -208,6 +208,26 @@ export function showDeleteOption(channel, isAdmin, isSystemAdmin, isChannelAdmin
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function canManageMembers(channel, isSystemAdmin, isTeamAdmin, isChannelAdmin) {
|
||||||
|
if (global.window.mm_license.IsLicensed !== 'true') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel.type === Constants.PRIVATE_CHANNEL) {
|
||||||
|
if (global.window.mm_config.RestrictPrivateChannelManageMembers === Constants.PERMISSIONS_SYSTEM_ADMIN && !isSystemAdmin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (global.window.mm_config.RestrictPrivateChannelManageMembers === Constants.PERMISSIONS_TEAM_ADMIN && !isTeamAdmin && !isSystemAdmin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (global.window.mm_config.RestrictPrivateChannelManageMembers === Constants.PERMISSIONS_CHANNEL_ADMIN && !isChannelAdmin && !isTeamAdmin && !isSystemAdmin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
export function buildGroupChannelName(channelId) {
|
export function buildGroupChannelName(channelId) {
|
||||||
const profiles = UserStore.getProfileListInChannel(channelId, true);
|
const profiles = UserStore.getProfileListInChannel(channelId, true);
|
||||||
let displayName = '';
|
let displayName = '';
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user