Skip to content

Commit

Permalink
fix: visual issues & user already in role validation
Browse files Browse the repository at this point in the history
  • Loading branch information
dougfabris committed Jul 20, 2021
1 parent 318d7f6 commit 23ea82d
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 32 deletions.
9 changes: 8 additions & 1 deletion app/api/server/v1/roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,16 @@ API.v1.addRoute('roles.addUserToRole', { authRequired: true }, {
});

const user = this.getUserFromParams();
const { roleName, roomId } = this.bodyParams;

const users = getUsersInRole(roleName, roomId, { fields: { username: 1 } }).fetch().map(({ username }) => username);

if (users.indexOf(user.username) > -1) {
throw new Meteor.Error('error-user-already-in-role', 'User already in role');
}

Meteor.runAsUser(this.userId, () => {
Meteor.call('authorization:addUserToRole', this.bodyParams.roleName, user.username, this.bodyParams.roomId);
Meteor.call('authorization:addUserToRole', roleName, user.username, roomId);
});

return API.v1.success({
Expand Down
27 changes: 20 additions & 7 deletions client/components/UserAutoComplete/UserAutoComplete.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AutoComplete, Option } from '@rocket.chat/fuselage';
import { AutoComplete, Option, Box, Chip } from '@rocket.chat/fuselage';
import { useDebouncedValue } from '@rocket.chat/fuselage-hooks';
import React, { memo, useMemo, useState } from 'react';

import { useEndpointData } from '../../hooks/useEndpointData';
Expand All @@ -10,25 +11,37 @@ const query = (term = '', conditions = {}) => ({ selector: JSON.stringify({ term
const UserAutoComplete = (props) => {
const { conditions = {} } = props;
const [filter, setFilter] = useState('');
const debouncedFilter = useDebouncedValue(filter, 1000);
const { value: data } = useEndpointData(
'users.autocomplete',
// eslint-disable-next-line react-hooks/exhaustive-deps
useMemo(() => query(filter, conditions), [filter]),
useMemo(() => query(debouncedFilter, conditions), [filter]),
);

const options = useMemo(
() => (data && data.items.map((user) => ({ value: user.username, label: user.name }))) || [],
[data],
);

return (
<AutoComplete
{...props}
filter={filter}
setFilter={setFilter}
renderSelected={({ value, label }) => (
<>
<UserAvatar size='x20' username={value} /> {label}
</>
)}
renderSelected={({ value, label }) => {
if (!value) {
return '';
}

return (
<Chip height='x20' value={value} onClick={() => props.onChange()} mie='x4'>
<UserAvatar size='x20' username={value} />
<Box verticalAlign='middle' is='span' margin='none' mi='x4'>
{label}
</Box>
</Chip>
);
}}
renderItem={({ value, ...props }) => (
<Option key={value} {...props} avatar={<Avatar value={value} />} />
)}
Expand Down
59 changes: 38 additions & 21 deletions client/views/admin/permissions/UsersInRolePage.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Box, Field, Margins, ButtonGroup, Button, Callout, Flex } from '@rocket.chat/fuselage';
import { Box, Field, Margins, ButtonGroup, Button, Callout } from '@rocket.chat/fuselage';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import React, { useState, useRef } from 'react';

Expand All @@ -17,8 +17,9 @@ const UsersInRolePage = ({ data }) => {

const reload = useRef();

const [user, setUser] = useState();
const [user, setUser] = useState('');
const [rid, setRid] = useState();
const [userError, setUserError] = useState();

const { _id, name, description } = data;

Expand All @@ -34,6 +35,10 @@ const UsersInRolePage = ({ data }) => {
});

const handleAdd = useMutableCallback(async () => {
if (!user) {
return setUserError(t('User_cant_be_empty'));
}

try {
await addUser({ roleName: _id, username: user, roomId: rid });
dispatchToastMessage({ type: 'success', message: t('User_added') });
Expand All @@ -44,6 +49,14 @@ const UsersInRolePage = ({ data }) => {
}
});

const handleUserChange = useMutableCallback((user) => {
if (user !== '') {
setUserError();
}

return setUser(user);
});

return (
<Page>
<Page.Header title={`${t('Users_in_role')} "${description || name}"`}>
Expand All @@ -52,29 +65,33 @@ const UsersInRolePage = ({ data }) => {
</ButtonGroup>
</Page.Header>
<Page.Content>
<Box display='flex' flexDirection='row' w='full' mi='neg-x4'>
<Box display='flex' flexDirection='column' w='full' mi='neg-x4'>
<Margins inline='x4'>
<Flex.Item shrink={1}>
{data.scope !== 'Users' && (
<Field>
<Field.Label>{t('Choose_a_room')}</Field.Label>
<Field.Row>
<RoomAutoComplete value={rid} onChange={setRid} placeholder={t('User')} />
</Field.Row>
</Field>
)}
<Field>
<Field.Label>{t('Add_user')}</Field.Label>
{data.scope !== 'Users' && (
<Field mbe='x4'>
<Field.Label>{t('Choose_a_room')}</Field.Label>
<Field.Row>
<UserAutoComplete value={user} onChange={setUser} placeholder={t('User')} />
<RoomAutoComplete value={rid} onChange={setRid} placeholder={t('User')} />
</Field.Row>
</Field>
<Box display='flex' flexGrow={1} flexDirection='column' justifyContent='flex-end'>
<Button primary onClick={handleAdd}>
{t('Add')}
</Button>
</Box>
</Flex.Item>
)}
<Field>
<Field.Label>{t('Add_user')}</Field.Label>
<Field.Row>
<UserAutoComplete
value={user}
onChange={handleUserChange}
placeholder={t('User')}
/>

<ButtonGroup mis='x8' align='end'>
<Button primary onClick={handleAdd}>
{t('Add')}
</Button>
</ButtonGroup>
</Field.Row>
<Field.Error>{userError}</Field.Error>
</Field>
</Margins>
</Box>
<Margins blockStart='x8'>
Expand Down
3 changes: 1 addition & 2 deletions client/views/admin/permissions/UsersInRoleTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ function UsersInRoleTable({
const dispatchToastMessage = useToastMessageDispatch();

const setModal = useSetModal();
const closeModal = () => setModal();

const removeUser = useEndpoint('POST', 'roles.removeUserFromRole');

const closeModal = () => setModal();

const onRemove = useMutableCallback((username) => {
const remove = async () => {
try {
Expand Down
1 change: 1 addition & 0 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -4251,6 +4251,7 @@
"User_added_by": "User <em>__user_added__</em> added by <em>__user_by__</em>.",
"User_added_successfully": "User added successfully",
"User_and_group_mentions_only": "User and group mentions only",
"User_cant_be_empty": "User cannot be empty",
"User_created_successfully!": "User create successfully!",
"User_default": "User default",
"User_doesnt_exist": "No user exists by the name of `@%s`.",
Expand Down
2 changes: 1 addition & 1 deletion tests/end-to-end/api/13-roles.js
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ describe('[Roles]', function() {
request.post(api('roles.removeUserFromRole'))
.set(credentials)
.send({
roleName: usersScopedRole.name,
roleId: usersScopedRole._id,
username: login.user,
})
.expect('Content-Type', 'application/json')
Expand Down

0 comments on commit 23ea82d

Please sign in to comment.