diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap index cc70fb74ce..51d2f3a80f 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/__snapshots__/add_users_to_role_modal.test.tsx.snap @@ -1,6 +1,395 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`admin_console/add_users_to_role_modal should match snapshot 1`] = ` +exports[`admin_console/add_users_to_role_modal search should not include bot user 1`] = ` + + + + + + , + } + } + /> + + + + + + + } + optionRenderer={[Function]} + options={ + Array [ + Object { + "auth_service": "", + "bot_description": "", + "create_at": 0, + "delete_at": 0, + "email": "", + "first_name": "", + "id": "user_id", + "is_bot": false, + "label": "some-user", + "last_activity_at": 0, + "last_name": "", + "last_password_update": 0, + "last_picture_update": 0, + "locale": "", + "mfa_active": false, + "nickname": "", + "notify_props": Object { + "calls_desktop_sound": "true", + "channel": "false", + "comments": "never", + "desktop": "default", + "desktop_sound": "false", + "email": "false", + "first_name": "false", + "mark_unread": "mention", + "mention_keys": "", + "push": "none", + "push_status": "offline", + }, + "password": "", + "position": "", + "props": Object {}, + "roles": "", + "terms_of_service_create_at": 0, + "terms_of_service_id": "", + "update_at": 0, + "username": "some-user", + "value": "user_id", + }, + ] + } + perPage={50} + placeholderText="Search and add members" + saveButtonPosition="top" + saving={false} + savingEnabled={true} + valueRenderer={[Function]} + valueWithImage={false} + values={Array []} + /> + + +`; + +exports[`admin_console/add_users_to_role_modal should exclude user 1`] = ` + + + + + + , + } + } + /> + + + + + + + } + optionRenderer={[Function]} + options={Array []} + perPage={50} + placeholderText="Search and add members" + saveButtonPosition="top" + saving={false} + savingEnabled={true} + valueRenderer={[Function]} + valueWithImage={false} + values={Array []} + /> + + +`; + +exports[`admin_console/add_users_to_role_modal should have single passed value 1`] = ` + + + + + + , + } + } + /> + + + + + + + } + optionRenderer={[Function]} + options={ + Array [ + Object { + "auth_service": "", + "bot_description": "", + "create_at": 0, + "delete_at": 0, + "email": "", + "first_name": "", + "id": "user_id", + "is_bot": false, + "label": "some-user", + "last_activity_at": 0, + "last_name": "", + "last_password_update": 0, + "last_picture_update": 0, + "locale": "", + "mfa_active": false, + "nickname": "", + "notify_props": Object { + "calls_desktop_sound": "true", + "channel": "false", + "comments": "never", + "desktop": "default", + "desktop_sound": "false", + "email": "false", + "first_name": "false", + "mark_unread": "mention", + "mention_keys": "", + "push": "none", + "push_status": "offline", + }, + "password": "", + "position": "", + "props": Object {}, + "roles": "", + "terms_of_service_create_at": 0, + "terms_of_service_id": "", + "update_at": 0, + "username": "some-user", + "value": "user_id", + }, + ] + } + perPage={50} + placeholderText="Search and add members" + saveButtonPosition="top" + saving={false} + savingEnabled={true} + valueRenderer={[Function]} + valueWithImage={false} + values={Array []} + /> + + +`; + +exports[`admin_console/add_users_to_role_modal should include additional user 1`] = ` `; + +exports[`admin_console/add_users_to_role_modal should include additional user 2`] = ` + + + + + + , + } + } + /> + + + + + + + } + optionRenderer={[Function]} + options={ + Array [ + Object { + "auth_service": "", + "bot_description": "", + "create_at": 0, + "delete_at": 0, + "email": "", + "first_name": "", + "id": "user_id", + "is_bot": false, + "label": "some-user", + "last_activity_at": 0, + "last_name": "", + "last_password_update": 0, + "last_picture_update": 0, + "locale": "", + "mfa_active": false, + "nickname": "", + "notify_props": Object { + "calls_desktop_sound": "true", + "channel": "false", + "comments": "never", + "desktop": "default", + "desktop_sound": "false", + "email": "false", + "first_name": "false", + "mark_unread": "mention", + "mention_keys": "", + "push": "none", + "push_status": "offline", + }, + "password": "", + "position": "", + "props": Object {}, + "roles": "", + "terms_of_service_create_at": 0, + "terms_of_service_id": "", + "update_at": 0, + "username": "some-user", + "value": "user_id", + }, + Object { + "auth_service": "", + "bot_description": "", + "create_at": 0, + "delete_at": 0, + "email": "", + "first_name": "", + "id": "user_id", + "is_bot": false, + "label": "some-user", + "last_activity_at": 0, + "last_name": "", + "last_password_update": 0, + "last_picture_update": 0, + "locale": "", + "mfa_active": false, + "nickname": "", + "notify_props": Object { + "calls_desktop_sound": "true", + "channel": "false", + "comments": "never", + "desktop": "default", + "desktop_sound": "false", + "email": "false", + "first_name": "false", + "mark_unread": "mention", + "mention_keys": "", + "push": "none", + "push_status": "offline", + }, + "password": "", + "position": "", + "props": Object {}, + "roles": "", + "terms_of_service_create_at": 0, + "terms_of_service_id": "", + "update_at": 0, + "username": "some-user", + "value": "user_id", + }, + ] + } + perPage={50} + placeholderText="Search and add members" + saveButtonPosition="top" + saving={false} + savingEnabled={true} + valueRenderer={[Function]} + valueWithImage={false} + values={Array []} + /> + + +`; + +exports[`admin_console/add_users_to_role_modal should not include bot user 1`] = ` + + + + + + , + } + } + /> + + + + + + + } + optionRenderer={[Function]} + options={ + Array [ + Object { + "auth_service": "", + "bot_description": "", + "create_at": 0, + "delete_at": 0, + "email": "", + "first_name": "", + "id": "user_id", + "is_bot": false, + "label": "some-user", + "last_activity_at": 0, + "last_name": "", + "last_password_update": 0, + "last_picture_update": 0, + "locale": "", + "mfa_active": false, + "nickname": "", + "notify_props": Object { + "calls_desktop_sound": "true", + "channel": "false", + "comments": "never", + "desktop": "default", + "desktop_sound": "false", + "email": "false", + "first_name": "false", + "mark_unread": "mention", + "mention_keys": "", + "push": "none", + "push_status": "offline", + }, + "password": "", + "position": "", + "props": Object {}, + "roles": "", + "terms_of_service_create_at": 0, + "terms_of_service_id": "", + "update_at": 0, + "username": "some-user", + "value": "user_id", + }, + ] + } + perPage={50} + placeholderText="Search and add members" + saveButtonPosition="top" + saving={false} + savingEnabled={true} + valueRenderer={[Function]} + valueWithImage={false} + values={Array []} + /> + + +`; diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.test.tsx b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.test.tsx index bbccad71fc..57f0b0c997 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.test.tsx +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.test.tsx @@ -9,15 +9,11 @@ import {TestHelper} from 'utils/test_helper'; import AddUsersToRoleModal from './add_users_to_role_modal'; describe('admin_console/add_users_to_role_modal', () => { - const props = { + const baseProps = { role: TestHelper.getRoleMock(), users: [TestHelper.getUserMock()], - excludeUsers: { - asdf123: TestHelper.getUserMock(), - }, - includeUsers: { - asdf123: TestHelper.getUserMock(), - }, + excludeUsers: {}, + includeUsers: {}, onAddCallback: jest.fn(), onExited: jest.fn(), actions: { @@ -26,12 +22,76 @@ describe('admin_console/add_users_to_role_modal', () => { }, }; - test('should match snapshot', () => { + test('should have single passed value', () => { + const wrapper = shallow( + ); + expect(wrapper.find('MultiSelect').prop('options')).toHaveLength(1); + expect(wrapper).toMatchSnapshot(); + }); + + test('should exclude user', () => { + const props = {...baseProps, excludeUsers: {user_id: TestHelper.getUserMock()}}; const wrapper = shallow( ); + expect(wrapper.find('MultiSelect').prop('options')).toHaveLength(0); + expect(wrapper).toMatchSnapshot(); + }); + test('should include additional user', () => { + const props = {...baseProps, includeUsers: {user_id1: TestHelper.getUserMock()}}; + const wrapper = shallow( + ); + expect(wrapper.find('MultiSelect').prop('options')).toHaveLength(2); + expect(wrapper).toMatchSnapshot(); + }); + + test('should include additional user', () => { + const props = {...baseProps, includeUsers: {user_id1: TestHelper.getUserMock()}}; + const wrapper = shallow( + ); + expect(wrapper.find('MultiSelect').prop('options')).toHaveLength(2); + expect(wrapper).toMatchSnapshot(); + }); + + test('should not include bot user', () => { + const botUser = TestHelper.getUserMock(); + botUser.is_bot = true; + const props = {...baseProps, + actions: { + getProfiles: jest.fn().mockResolvedValue({data: [TestHelper.getUserMock(), botUser]}), + searchProfiles: jest.fn(), + }, + }; + const wrapper = shallow( + ); + expect(wrapper.find('MultiSelect').prop('options')).toHaveLength(1); + expect(wrapper).toMatchSnapshot(); + }); + + test('search should not include bot user', () => { + const botUser = TestHelper.getUserMock(); + botUser.is_bot = true; + const props = {...baseProps, + actions: { + searchProfiles: jest.fn().mockResolvedValue({data: [TestHelper.getUserMock(), botUser]}), + getProfiles: jest.fn(), + }, + }; + const wrapper = shallow( + ); + expect(wrapper.find('MultiSelect').prop('options')).toHaveLength(1); expect(wrapper).toMatchSnapshot(); }); }); diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx index b7bdcbd6a2..fe0c9b9162 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/add_users_to_role_modal.tsx @@ -82,11 +82,15 @@ export default class AddUsersToRoleModal extends React.PureComponent { this.setUsersLoadingState(true); - let searchResults: UserProfile[] = []; + const searchResults: UserProfile[] = []; const search = term !== ''; if (search) { const {data} = await this.props.actions.searchProfiles(term, {replace: true}); - searchResults = data; + data.forEach((user) => { + if (!user.is_bot) { + searchResults.push(user); + } + }); } else { await this.props.actions.getProfiles(0, USERS_PER_PAGE * 2); } diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/index.tsx b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/index.tsx index 85c9413025..9ad92d9c35 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/index.tsx +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/add_users_to_role_modal/index.tsx @@ -16,7 +16,7 @@ import AddUsersToRoleModal from './add_users_to_role_modal'; import type {Props} from './add_users_to_role_modal'; function mapStateToProps(state: GlobalState, props: Props) { - const filterOptions: {[key: string]: any} = {active: true, exclude_roles: [props.role.name]}; + const filterOptions: {[key: string]: any} = {active: true, exclude_roles: [props.role.name], exclude_bots: true}; const users: UserProfile[] = selectProfiles(state, filterOptions); return { diff --git a/webapp/channels/src/components/admin_console/system_roles/system_role/system_role.tsx b/webapp/channels/src/components/admin_console/system_roles/system_role/system_role.tsx index 5507be1244..4323f0fc33 100644 --- a/webapp/channels/src/components/admin_console/system_roles/system_role/system_role.tsx +++ b/webapp/channels/src/components/admin_console/system_roles/system_role/system_role.tsx @@ -156,7 +156,7 @@ export default class SystemRole extends React.PureComponent { } const userIdsToAdd = Object.keys(usersToAdd); - if (userIdsToAdd.length > 0 && serverError == null) { + if (userIdsToAdd.length > 0 && !serverError) { const addUserPromises: Array> = []; userIdsToAdd.forEach((userId) => { const user = usersToAdd[userId]; @@ -174,16 +174,16 @@ export default class SystemRole extends React.PureComponent { } let {saveKey} = this.state; - if (serverError === null) { + if (!serverError) { saveKey += 1; } - if (serverError === null) { + if (!serverError) { getHistory().push('/admin_console/user_management/system_roles'); } - setNavigationBlocked(serverError !== null); + setNavigationBlocked(Boolean(serverError)); this.setState({ - saveNeeded: (serverError !== null), + saveNeeded: Boolean(serverError), saving: false, serverError, usersToAdd: {}, diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts index faaf0d405b..c414396902 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.test.ts @@ -819,4 +819,70 @@ describe('Selectors.Users', () => { expect(Selectors.currentUserHasAnAdminRole(state)).toEqual(false); }); }); + + describe('filterProfiles', () => { + it('no filter, return all users', () => { + expect(Object.keys(Selectors.filterProfiles(profiles)).length).toEqual(7); + }); + + it('filter role', () => { + const filter = { + role: 'system_admin', + }; + expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(3); + }); + + it('filter roles', () => { + const filter = { + roles: ['system_admin'], + team_roles: ['team_admin'], + }; + + const membership = TestHelper.fakeTeamMember(user3.id, team1.id); + membership.scheme_admin = true; + const memberships = {[user3.id]: membership}; + + expect(Object.keys(Selectors.filterProfiles(profiles, filter, memberships)).length).toEqual(4); + }); + + it('exclude_roles', () => { + const filter = { + exclude_roles: ['system_admin'], + }; + expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(4); + }); + + it('exclude bots', () => { + const filter = { + exclude_bots: true, + }; + const botUser = { + ...user1, + id: 'test_bot_id', + username: 'botusername', + first_name: '', + last_name: '', + is_bot: true, + }; + const newProfiles = { + ...profiles, + [botUser.id]: botUser, + }; + expect(Object.keys(Selectors.filterProfiles(newProfiles, filter)).length).toEqual(7); + }); + + it('filter inactive', () => { + const filter = { + inactive: true, + }; + expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(2); + }); + + it('filter active', () => { + const filter = { + active: true, + }; + expect(Object.keys(Selectors.filterProfiles(profiles, filter)).length).toEqual(5); + }); + }); }); diff --git a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts index 9b292ae7e8..d94d592c74 100644 --- a/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts +++ b/webapp/channels/src/packages/mattermost-redux/src/selectors/entities/users.ts @@ -49,6 +49,7 @@ type Filters = { exclude_roles?: string[]; channel_roles?: string[]; team_roles?: string[]; + exclude_bots?: boolean; }; export function getUserIdsInChannels(state: GlobalState): RelationOneToManyUnique { @@ -304,6 +305,10 @@ export function filterProfiles(profiles: IDMappedObjects, filters?: }); } + if (filters.exclude_bots) { + users = users.filter((user) => !user.is_bot); + } + if (filters.inactive) { users = users.filter((user) => user.delete_at !== 0); } else if (filters.active) {