Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: Permissions missing on new Room Edit and Contact Edit form #21315

Merged
merged 30 commits into from
Apr 1, 2021
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5a24a7d
Allow editing rooms in chat room
murtaza98 Mar 26, 2021
813dd40
Allow editing contact in chat room
murtaza98 Mar 26, 2021
2e72762
Fix default value error
murtaza98 Mar 26, 2021
4148e5c
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Mar 27, 2021
0ec0172
Move chats and contacts file out of omnichannel directory
murtaza98 Mar 27, 2021
adb04eb
Merge with develop
murtaza98 Mar 27, 2021
d58e9fe
Merge branch 'develop' into omnichannel/March2021-regression-2
murtaza98 Mar 27, 2021
095caa7
Show edit option for room info only if the user has permission
murtaza98 Mar 28, 2021
60cc1d0
Refactor + display room tags within edit only if user has permission
murtaza98 Mar 28, 2021
9d2f736
Merge branch 'omnichannel/March2021-regression-2' of https://github.c…
murtaza98 Mar 28, 2021
145262e
Add permissions for editing omnichannel contact
murtaza98 Mar 29, 2021
2ddbee4
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Mar 30, 2021
3c43b84
Merge branch 'develop' into omnichannel/March2021-regression-2
murtaza98 Mar 30, 2021
4a29157
Merge branch 'omnichannel/March2021-regression-2' of https://github.c…
murtaza98 Mar 30, 2021
84dbd72
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Mar 30, 2021
2e4f364
Re-add permission
murtaza98 Mar 30, 2021
1245e29
Merge branch 'omnichannel/March2021-regression-2' of https://github.c…
murtaza98 Mar 30, 2021
1bb4a4d
Merge branch 'develop' into omnichannel/March2021-regression-2
murtaza98 Mar 31, 2021
eef4d0c
fix auto room-info panel routing issue
murtaza98 Mar 31, 2021
b58d191
Merge branch 'develop' into omnichannel/March2021-regression-2
rafaelblink Mar 31, 2021
58fdaa3
Merge branch 'develop' into omnichannel/March2021-regression-2
rafaelblink Mar 31, 2021
81ba860
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Mar 31, 2021
7831b52
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Mar 31, 2021
7fe895b
Fix Permissions.
renatobecker Apr 1, 2021
fb999c1
Fix indentation.
renatobecker Apr 1, 2021
4397453
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Apr 1, 2021
cab6aa1
Merge branch 'omnichannel/March2021-regression-2' of https://github.c…
renatobecker Apr 1, 2021
672122f
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Apr 1, 2021
14306b4
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Apr 1, 2021
d082592
Merge branch 'develop' into omnichannel/March2021-regression-2
renatobecker Apr 1, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/authorization/server/startup.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ Meteor.startup(function() {
{ _id: 'call-management', roles: ['admin', 'owner', 'moderator'] },
{ _id: 'create-invite-links', roles: ['admin', 'owner', 'moderator'] },
{ _id: 'view-l-room', roles: ['livechat-agent', 'livechat-manager', 'admin'] },
{ _id: 'view-livechat-manager', roles: ['livechat-manager', 'admin'] },
murtaza98 marked this conversation as resolved.
Show resolved Hide resolved
{ _id: 'view-livechat-manager', roles: ['livechat-manager', 'admin'] },
{ _id: 'edit-omnichannel-contact', roles: ['livechat-manager', 'admin', 'livechat-agent'] },
{ _id: 'view-livechat-rooms', roles: ['livechat-manager', 'admin'] },
{ _id: 'close-livechat-room', roles: ['livechat-agent', 'livechat-manager', 'admin'] },
{ _id: 'close-others-livechat-room', roles: ['livechat-manager', 'admin'] },
Expand Down
2 changes: 1 addition & 1 deletion app/livechat/client/tabBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ addAction('room-info', {
id: 'room-info',
title: 'Room_Info',
icon: 'info-circled',
template: lazy(() => import('../../../client/omnichannel/directory/chats/contextualBar')),
template: lazy(() => import('../../../client/omnichannel/chats/contextualBar')),
order: 0,
});

Expand Down
2 changes: 1 addition & 1 deletion app/ui/client/views/app/room.js
Original file line number Diff line number Diff line change
Expand Up @@ -890,7 +890,7 @@ Meteor.startup(() => {

let room = Rooms.findOne({ _id: rid }, { fields: { t: 1 } });

if (room?.t === 'l' && !FlowRouter.getParam('tab')) {
if (room?.t === 'l') {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@renatobecker I forgot to revert this change in the previous commit. So I'm doing it here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we don't have a Chat History button in contacts directory, this is no longer needed

room = Tracker.nonreactive(() => Rooms.findOne({ _id: rid }));
roomTypes.getConfig(room.t).openCustomProfileTab(this, room, room.v.username);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { Table, Tag, Box } from '@rocket.chat/fuselage';
import moment from 'moment';
import { Meteor } from 'meteor/meteor';

import { useTranslation } from '../../../contexts/TranslationContext';
import { useEndpointData } from '../../../hooks/useEndpointData';
import GenericTable from '../../../components/GenericTable';
import FilterByText from '../../../components/FilterByText';
import { usePermission } from '../../../contexts/AuthorizationContext';
import NotAuthorizedPage from '../../../components/NotAuthorizedPage';
import { useRoute } from '../../../contexts/RouterContext';
import { useTranslation } from '../../contexts/TranslationContext';
import { useEndpointData } from '../../hooks/useEndpointData';
import GenericTable from '../../components/GenericTable';
import FilterByText from '../../components/FilterByText';
import { usePermission } from '../../contexts/AuthorizationContext';
import NotAuthorizedPage from '../../components/NotAuthorizedPage';
import { useRoute } from '../../contexts/RouterContext';


const useQuery = ({ text, itemsPerPage, current }, [column, direction], userIdLoggedIn) => useMemo(() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@ import { Box, Margins, Tag, Avatar, Button, Icon, ButtonGroup } from '@rocket.ch
import { css } from '@rocket.chat/css-in-js';
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';

import VerticalBar from '../../../../components/VerticalBar';
import UserCard from '../../../../components/UserCard';
import { FormSkeleton } from '../../Skeleton';
import { useEndpointData } from '../../../../hooks/useEndpointData';
import { useTranslation } from '../../../../contexts/TranslationContext';
import { useFormatDateAndTime } from '../../../../hooks/useFormatDateAndTime';
import { useFormatDuration } from '../../../../hooks/useFormatDuration';
import { AsyncStatePhase } from '../../../../hooks/useAsyncState';
import UserAvatar from '../../../../components/avatar/UserAvatar';
import { UserStatus } from '../../../../components/UserStatus';
import { roomTypes } from '../../../../../app/utils/client';
import { useRoute } from '../../../../contexts/RouterContext';
import VerticalBar from '../../../components/VerticalBar';
import UserCard from '../../../components/UserCard';
import { FormSkeleton } from '../../directory/Skeleton';
import { useEndpointData } from '../../../hooks/useEndpointData';
import { useTranslation } from '../../../contexts/TranslationContext';
import { useFormatDateAndTime } from '../../../hooks/useFormatDateAndTime';
import { AsyncStatePhase } from '../../../hooks/useAsyncState';
import UserAvatar from '../../../components/avatar/UserAvatar';
import { UserStatus } from '../../../components/UserStatus';
import { roomTypes } from '../../../../app/utils/client';
import { useRoute } from '../../../contexts/RouterContext';
import { useFormatDuration } from '../../../hooks/useFormatDuration';


const wordBreak = css`
Expand Down Expand Up @@ -90,7 +90,7 @@ const AgentField = ({ agent }) => {
</>;
};

export function ChatInfo({ id, route }) {
export function ChatInfo({ id, route, hasEditAccess }) {
const t = useTranslation();

const formatDateAndTime = useFormatDateAndTime();
Expand All @@ -103,6 +103,7 @@ export function ChatInfo({ id, route }) {

const onEditClick = useMutableCallback(() => routePath.push(
route ? {
tab: 'room-info',
context: 'edit',
id,
} : {
Expand Down Expand Up @@ -170,10 +171,10 @@ export function ChatInfo({ id, route }) {
</>}
</Margins>
</VerticalBar.ScrollableContent>
<VerticalBar.Footer>
{hasEditAccess && <VerticalBar.Footer>
<ButtonGroup stretch>
<Button onClick={onEditClick}><Icon name='pencil' size='x20'/> {t('Edit')}</Button>
</ButtonGroup>
</VerticalBar.Footer>
</VerticalBar.Footer>}
</>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,33 @@ import { Field, TextInput, ButtonGroup, Button, Box } from '@rocket.chat/fuselag
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { useSubscription } from 'use-subscription';

import { useTranslation } from '../../../../contexts/TranslationContext';
import VerticalBar from '../../../../components/VerticalBar';
import { useForm } from '../../../../hooks/useForm';
import { useComponentDidUpdate } from '../../../../hooks/useComponentDidUpdate';
// import { useEndpointAction } from '../../../../hooks/useEndpointAction';
import { useToastMessageDispatch } from '../../../../contexts/ToastMessagesContext';
import { useEndpointData } from '../../../../hooks/useEndpointData';
import { FormSkeleton } from '../../Skeleton';
import { AsyncStatePhase } from '../../../../hooks/useAsyncState';
import { isEmail } from '../../../../../app/utils';
import { hasAtLeastOnePermission } from '../../../../../app/authorization';
import CustomFieldsForm from '../../../../components/CustomFieldsForm';
import { useMethod } from '../../../../contexts/ServerContext';
import { formsSubscription } from '../../../../views/omnichannel/additionalForms';
import { useTranslation } from '../../../contexts/TranslationContext';
import VerticalBar from '../../../components/VerticalBar';
import { useForm } from '../../../hooks/useForm';
import { useComponentDidUpdate } from '../../../hooks/useComponentDidUpdate';
import { useToastMessageDispatch } from '../../../contexts/ToastMessagesContext';
import { useEndpointData } from '../../../hooks/useEndpointData';
import { FormSkeleton } from '../../directory/Skeleton';
import { AsyncStatePhase } from '../../../hooks/useAsyncState';
import { isEmail } from '../../../../app/utils';
import { hasAtLeastOnePermission } from '../../../../app/authorization';
import CustomFieldsForm from '../../../components/CustomFieldsForm';
import { useMethod } from '../../../contexts/ServerContext';
import { formsSubscription } from '../../../views/omnichannel/additionalForms';
import { hasPermission } from '../../../../app/authorization/client';


const initialValuesUser = {
name: '',
email: '',
phone: '',
livechatData: '',
livechatData: {},
};

const initialValuesRoom = {
topic: '',
tags: '',
livechatData: '',
livechatData: {},
};


Expand All @@ -44,7 +44,7 @@ const getInitialValuesUser = (visitor) => {
name: (name || fname) ?? '',
email: visitorEmails ? visitorEmails[0].address : '',
phone: phone ? phone[0].phoneNumber : '',
livechatData: livechatData ?? '',
livechatData: livechatData ?? {},
};
};

Expand All @@ -61,8 +61,7 @@ const getInitialValuesRoom = (room) => {
};
};


export function RoomEditWithData({ id, reload, close }) {
export function RoomEditWithData({ id, reload, close, hasEditAccess }) {
const t = useTranslation();

const { value: roomData, phase: state, error } = useEndpointData(`rooms.info?roomId=${ id }`);
Expand All @@ -75,6 +74,9 @@ export function RoomEditWithData({ id, reload, close }) {
return <Box mbs='x16'>{t('Room_not_found')}</Box>;
}

if (!hasEditAccess) {
return <Box mbs='x16'>{t('Not_authorized')}</Box>;
}

return <VisitorData room={roomData} reload={reload} close={close} />;
}
Expand Down Expand Up @@ -107,6 +109,7 @@ export function RoomEdit({ room, visitor, reload, close }) {
const { values, handlers } = useForm(getInitialValuesUser(visitor));
const { values: valuesRoom, handlers: handlersRoom } = useForm(getInitialValuesRoom(room));
const canViewCustomFields = () => hasAtLeastOnePermission(['view-livechat-room-customfields', 'edit-livechat-room-customfields']);
const canViewTags = hasPermission('manage-livechat-tags');

const {
handleName,
Expand Down Expand Up @@ -218,7 +221,7 @@ export function RoomEdit({ room, visitor, reload, close }) {
try {
saveRoom(userData, roomData);
dispatchToastMessage({ type: 'success', message: t('Saved') });
reload();
reload && reload();
close();
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
Expand Down Expand Up @@ -270,12 +273,12 @@ export function RoomEdit({ room, visitor, reload, close }) {
<TextInput flexGrow={1} value={topic} onChange={handleTopic} />
</Field.Row>
</Field>
<Field>
{ canViewTags && <Field>
<Field.Label mb='x4'>{t('Tags')}</Field.Label>
<Field.Row>
<Tags value={Object.values(tags)} handler={handleTags} />
</Field.Row>
</Field>
</Field>}
</VerticalBar.ScrollableContent>
<VerticalBar.Footer>
<ButtonGroup stretch>
Expand Down
43 changes: 43 additions & 0 deletions client/omnichannel/chats/contextualBar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react';
import { Icon, Box } from '@rocket.chat/fuselage';

import { ChatInfo } from './ChatInfo';
import { RoomEditWithData } from './ChatRoomEdit';
import VerticalBar from '../../../components/VerticalBar';
import { useRoute, useRouteParameter } from '../../../contexts/RouterContext';
import { useTranslation } from '../../../contexts/TranslationContext';
import { useUserSubscription } from '../../../contexts/UserContext';
import { hasPermission } from '../../../../app/authorization/client';

const PATH = 'live';

const ChatsContextualBar = ({ id }) => {
const t = useTranslation();

const context = useRouteParameter('context');

const directoryRoute = useRoute(PATH);

const subscription = useUserSubscription(id);
const hasGlobalEditRoomPermission = hasPermission('save-others-livechat-room-info');

const hasEditAccess = !!subscription || hasGlobalEditRoomPermission;

const closeContextualBar = () => {
directoryRoute.push({ id });
};

const handleRoomEditBarCloseButtonClick = () => {
directoryRoute.push({ id, tab: 'room-info' });
};

return <>
<VerticalBar.Header>
<Box flexShrink={1} flexGrow={1} withTruncatedText mi='x8'><Icon name='info-circled' size='x20' /> {t('Room_Info')}</Box>
<VerticalBar.Close onClick={closeContextualBar} />
</VerticalBar.Header>
{context === 'edit' && hasEditAccess ? <RoomEditWithData id={id} close={handleRoomEditBarCloseButtonClick} hasEditAccess={hasEditAccess} /> : <ChatInfo route={PATH} id={id} hasEditAccess={hasEditAccess} />}
</>;
};

export default ({ rid }) => <ChatsContextualBar id={rid} />;
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import React, { useState, useMemo, useCallback, useEffect } from 'react';
import { useDebouncedValue, useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { Table } from '@rocket.chat/fuselage';

import { useTranslation } from '../../../contexts/TranslationContext';
import { useEndpointData } from '../../../hooks/useEndpointData';
import GenericTable from '../../../components/GenericTable';
import FilterByText from '../../../components/FilterByText';
import { useRoute } from '../../../contexts/RouterContext';
import { useFormatDate } from '../../../hooks/useFormatDate';
import { usePermission } from '../../../contexts/AuthorizationContext';
import { NotAuthorizedPage } from '../../../components/NotAuthorizedPage';
import { useTranslation } from '../../contexts/TranslationContext';
import { useEndpointData } from '../../hooks/useEndpointData';
import GenericTable from '../../components/GenericTable';
import FilterByText from '../../components/FilterByText';
import { useRoute } from '../../contexts/RouterContext';
import { useFormatDate } from '../../hooks/useFormatDate';
import { usePermission } from '../../contexts/AuthorizationContext';
import { NotAuthorizedPage } from '../../components/NotAuthorizedPage';


const useQuery = ({ text, itemsPerPage, current }, [column, direction]) => useMemo(() => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import { Field, TextInput, ButtonGroup, Button, Box } from '@rocket.chat/fuselag
import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
import { useSubscription } from 'use-subscription';

import { useTranslation } from '../../../../contexts/TranslationContext';
import VerticalBar from '../../../../components/VerticalBar';
import { useForm } from '../../../../hooks/useForm';
import { isEmail } from '../../../../../app/utils';
import { useComponentDidUpdate } from '../../../../hooks/useComponentDidUpdate';
import { useEndpointAction } from '../../../../hooks/useEndpointAction';
import { useToastMessageDispatch } from '../../../../contexts/ToastMessagesContext';
import { useEndpointData } from '../../../../hooks/useEndpointData';
import { FormSkeleton } from '../../Skeleton';
import CustomFieldsForm from '../../../../components/CustomFieldsForm';
import { hasAtLeastOnePermission } from '../../../../../app/authorization';
import { AsyncStatePhase } from '../../../../hooks/useAsyncState';
import { formsSubscription } from '../../../../views/omnichannel/additionalForms';
import { createToken } from '../../../../components/helpers';
import { useTranslation } from '../../../contexts/TranslationContext';
import VerticalBar from '../../../components/VerticalBar';
import { useForm } from '../../../hooks/useForm';
import { isEmail } from '../../../../app/utils';
import { useComponentDidUpdate } from '../../../hooks/useComponentDidUpdate';
import { useEndpointAction } from '../../../hooks/useEndpointAction';
import { useToastMessageDispatch } from '../../../contexts/ToastMessagesContext';
import { useEndpointData } from '../../../hooks/useEndpointData';
import { FormSkeleton } from '../../directory/Skeleton';
import CustomFieldsForm from '../../../components/CustomFieldsForm';
import { hasAtLeastOnePermission } from '../../../../app/authorization';
import { AsyncStatePhase } from '../../../hooks/useAsyncState';
import { formsSubscription } from '../../../views/omnichannel/additionalForms';
import { createToken } from '../../../components/helpers';

const initialValues = {
token: '',
Expand All @@ -38,12 +38,12 @@ const getInitialValues = (data) => {
name: name ?? '',
email: visitorEmails ? visitorEmails[0].address : '',
phone: phone ? phone[0].phoneNumber : '',
livechatData: livechatData ?? '',
livechatData: livechatData ?? {},
username: contactManager?.username ?? '',
};
};

export function ContactEditWithData({ id, reload, close }) {
export function ContactEditWithData({ id, reload, close, hasEditAccess }) {
const t = useTranslation();
const { value: data, phase: state, error } = useEndpointData(`omnichannel/contact?contactId=${ id }`);

Expand All @@ -55,6 +55,10 @@ export function ContactEditWithData({ id, reload, close }) {
return <Box mbs='x16'>{t('Contact_not_found')}</Box>;
}

if (!hasEditAccess) {
return <Box mbs='x16'>{t('Not_authorized')}</Box>;
}

return <ContactNewEdit id={id} data={data} reload={reload} close={close} />;
}

Expand Down Expand Up @@ -188,7 +192,7 @@ export function ContactNewEdit({ id, data, reload, close }) {
try {
await saveContact(payload);
dispatchToastMessage({ type: 'success', message: t('Saved') });
reload();
reload && reload();
close();
} catch (error) {
dispatchToastMessage({ type: 'error', message: error });
Expand Down
Loading