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

[FIX] UserCard sanitization #25089

Merged
merged 4 commits into from
Apr 13, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
11 changes: 0 additions & 11 deletions client/components/UserCard/Action.js

This file was deleted.

6 changes: 0 additions & 6 deletions client/components/UserCard/Info.js

This file was deleted.

10 changes: 0 additions & 10 deletions client/components/UserCard/Role.js

This file was deleted.

11 changes: 0 additions & 11 deletions client/components/UserCard/Roles.js

This file was deleted.

92 changes: 0 additions & 92 deletions client/components/UserCard/UserCard.js

This file was deleted.

15 changes: 13 additions & 2 deletions client/components/UserCard/UserCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,20 @@ export default {
args: {
name: 'guilherme.gazzo',
customStatus: '🛴 currently working on User Card',
roles: [<UserCard.Role>Admin</UserCard.Role>, <UserCard.Role>Rocket.Chat</UserCard.Role>, <UserCard.Role>Team</UserCard.Role>],
roles: (
<>
<UserCard.Role>Admin</UserCard.Role>
<UserCard.Role>Rocket.Chat</UserCard.Role>
<UserCard.Role>Team</UserCard.Role>
</>
),
bio: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla tempus, eros convallis vulputate cursus, nisi neque eleifend libero, eget lacinia justo purus nec est. In at sodales ipsum. Sed lacinia quis purus eget pulvinar. Aenean eu pretium nunc, at aliquam magna. Praesent dignissim, tortor sed volutpat mattis, mauris diam pulvinar leo, porta commodo risus est non purus. Mauris in justo vel lorem ullamcorper hendrerit. Nam est metus, viverra a pellentesque vitae, ornare eget odio. Morbi tempor feugiat mattis. Morbi non felis tempor, aliquam justo sed, sagittis nibh. Mauris consequat ex metus. Praesent sodales sit amet nibh a vulputate. Integer commodo, mi vel bibendum sollicitudin, urna lectus accumsan ante, eget faucibus augue ex id neque. Aenean consectetur, orci a pellentesque mattis, tortor tellus fringilla elit, non ullamcorper risus nunc feugiat risus. Fusce sit amet nisi dapibus turpis commodo placerat. In tortor ante, vehicula sit amet augue et, imperdiet porta sem.',
actions: [<UserCard.Action icon='message' />, <UserCard.Action icon='phone' />],
actions: (
<>
<UserCard.Action icon='message' />
<UserCard.Action icon='phone' />
</>
),
localTime: 'Local Time: 7:44 AM',
},
} as ComponentMeta<typeof UserCard>;
Expand Down
118 changes: 118 additions & 0 deletions client/components/UserCard/UserCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { css } from '@rocket.chat/css-in-js';
import { Box, ActionButton, Skeleton } from '@rocket.chat/fuselage';
import React, { forwardRef, ReactNode, ComponentProps } from 'react';

import { useTranslation } from '../../contexts/TranslationContext';
import MarkdownText from '../MarkdownText';
import * as Status from '../UserStatus';
import UserAvatar from '../avatar/UserAvatar';
import UserCardContainer from './UserCardContainer';
import UserCardInfo from './UserCardInfo';
import UserCardRoles from './UserCardRoles';
import UserCardUsername from './UserCardUsername';

const clampStyle = css`
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
word-break: break-all;
`;

type UserCardProps = {
className?: string;
style?: ComponentProps<typeof Box>['style'];
open?: () => void;
name?: string;
username?: string;
etag?: string;
customStatus?: ReactNode;
roles?: ReactNode;
bio?: ReactNode;
status?: ReactNode;
actions?: ReactNode;
localTime?: ReactNode;
onClose?: () => void;
nickname?: string;
};

const UserCard = forwardRef(function UserCard(
{
className,
style,
open,
name,
username,
etag,
customStatus = <Skeleton width='100%' />,
roles = (
<>
<Skeleton width='32%' mi='x2' />
<Skeleton width='32%' mi='x2' />
<Skeleton width='32%' mi='x2' />
</>
),
bio = (
<>
<Skeleton width='100%' />
<Skeleton width='100%' />
<Skeleton width='100%' />
</>
),
status = <Status.Offline />,
actions,
localTime = <Skeleton width='100%' />,
onClose,
nickname,
}: UserCardProps,
ref,
) {
const t = useTranslation();

return (
<UserCardContainer className={className} ref={ref} style={style}>
<Box>
{!username ? <Skeleton width='x124' height='x124' variant='rect' /> : <UserAvatar username={username} etag={etag} size='x124' />}
{actions && (
<Box flexGrow={0} display='flex' mb='x12' alignItems='center' justifyContent='center'>
{actions}
</Box>
)}
</Box>
<Box display='flex' flexDirection='column' flexGrow={1} flexShrink={1} mis='x24' width='1px'>
<Box mbe='x4' withTruncatedText display='flex'>
{!name ? <Skeleton width='100%' /> : <UserCardUsername status={status} name={name} />}
{nickname && (
<Box flexGrow={1} flexShrink={1} flexBasis={0} title={t('Nickname')} color='hint' mis='x4' fontScale='p2' withTruncatedText>
({nickname})
</Box>
)}
</Box>
{customStatus && (
<UserCardInfo>
{typeof customStatus === 'string' ? (
<MarkdownText withTruncatedText variant='inlineWithoutBreaks' content={customStatus} parseEmoji={true} />
) : (
customStatus
)}
</UserCardInfo>
)}
<UserCardRoles>{roles}</UserCardRoles>
<UserCardInfo>{localTime}</UserCardInfo>
{bio && (
<UserCardInfo withTruncatedText={false} className={clampStyle} height='x60'>
{typeof bio === 'string' ? <MarkdownText variant='inline' content={bio} /> : bio}
</UserCardInfo>
)}
{open && <a onClick={open}>{t('See_full_profile')}</a>}
</Box>
{onClose && (
<Box>
<ActionButton small ghost title={t('Close')} icon='cross' onClick={onClose} />
</Box>
)}
</UserCardContainer>
);
});

export default UserCard;
13 changes: 13 additions & 0 deletions client/components/UserCard/UserCardAction.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { ActionButton, Icon } from '@rocket.chat/fuselage';
import React, { ReactElement, ComponentProps } from 'react';

type UserCardActionProps = {
label?: string;
icon: ComponentProps<typeof Icon>['name'];
};

const UserCardAction = ({ label, icon, ...props }: UserCardActionProps): ReactElement => (
<ActionButton icon={icon} small title={label} {...props} mi='x2' />
);

export default UserCardAction;
8 changes: 0 additions & 8 deletions client/components/UserCard/UserCardContainer.js

This file was deleted.

8 changes: 8 additions & 0 deletions client/components/UserCard/UserCardContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Box } from '@rocket.chat/fuselage';
import React, { forwardRef, ComponentProps } from 'react';

const UserCardContainer = forwardRef(function UserCardContainer(props: ComponentProps<typeof Box>, ref) {
return <Box ref={ref} rcx-user-card bg='surface' elevation='2' p='x24' display='flex' borderRadius='x2' width='439px' {...props} />;
});

export default UserCardContainer;
8 changes: 8 additions & 0 deletions client/components/UserCard/UserCardInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Box } from '@rocket.chat/fuselage';
import React, { ReactElement, ComponentProps } from 'react';

const UserCardInfo = (props: ComponentProps<typeof Box>): ReactElement => (
<Box mbe='x8' is='span' fontScale='p2' color='hint' withTruncatedText {...props} />
);

export default UserCardInfo;
10 changes: 10 additions & 0 deletions client/components/UserCard/UserCardRole.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Box, Tag } from '@rocket.chat/fuselage';
import React, { ReactNode, ReactElement } from 'react';

const UserCardRole = ({ children }: { children: ReactNode }): ReactElement => (
<Box m='x2' fontScale='c2'>
<Tag disabled children={children} />
</Box>
);

export default UserCardRole;
14 changes: 14 additions & 0 deletions client/components/UserCard/UserCardRoles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Box } from '@rocket.chat/fuselage';
import React, { ReactNode, ReactElement } from 'react';

import UserCardInfo from './UserCardInfo';

const UserCardRoles = ({ children }: { children: ReactNode }): ReactElement => (
<Box m='neg-x2'>
<UserCardInfo flexWrap='wrap' display='flex' flexShrink={0}>
{children}
</UserCardInfo>
</Box>
);

export default UserCardRoles;
31 changes: 31 additions & 0 deletions client/components/UserCard/UserCardUsername.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Box } from '@rocket.chat/fuselage';
import React, { ReactElement, ReactNode, ComponentProps } from 'react';

import * as UserStatus from '../UserStatus';

type UserCardUsernameProps = ComponentProps<typeof Box> & {
name: ReactNode;
status: ReactNode;
};

const UserCardUsername = ({ name, status = <UserStatus.Offline />, ...props }: UserCardUsernameProps): ReactElement => (
<Box
display='flex'
title={name}
flexGrow={2}
flexShrink={1}
flexBasis={0}
alignItems='center'
fontScale='h4'
color='default'
withTruncatedText
{...props}
>
{status}{' '}
<Box mis='x8' flexGrow={1} withTruncatedText>
{name}
</Box>
</Box>
);

export default UserCardUsername;
15 changes: 0 additions & 15 deletions client/components/UserCard/Username.js

This file was deleted.

Loading