Skip to content

Commit

Permalink
Merge pull request #35385 from mkhutornyi/fix-32500
Browse files Browse the repository at this point in the history
  • Loading branch information
blimpich authored Feb 14, 2024
2 parents 821bc7b + 404dfb3 commit be5ee07
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 114 deletions.
9 changes: 9 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,15 @@ const CONST = {
];
},

// Emails that profile view is prohibited
get RESTRICTED_EMAILS(): readonly string[] {
return [this.EMAIL.NOTIFICATIONS];
},
// Account IDs that profile view is prohibited
get RESTRICTED_ACCOUNT_IDS() {
return [this.ACCOUNT_ID.NOTIFICATIONS];
},

// Auth limit is 60k for the column but we store edits and other metadata along the html so let's use a lower limit to accommodate for it.
MAX_COMMENT_LENGTH: 10000,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateA
subtitle = '';
}
}
if (CONST.RESTRICTED_ACCOUNT_IDS.includes(userAccountID) || CONST.RESTRICTED_EMAILS.includes(userLogin.trim())) {
subtitle = '';
}
const renderTooltipContent = useCallback(
() => (
<View style={[styles.alignItemsCenter, styles.ph2, styles.pv2]}>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/DetailsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ function DetailsPage({personalDetails, route, session}: DetailsPageProps) {

return (
<ScreenWrapper testID={DetailsPage.displayName}>
<FullPageNotFoundView shouldShow={!login}>
<FullPageNotFoundView shouldShow={!login || CONST.RESTRICTED_EMAILS.includes(login)}>
<HeaderWithBackButton title={translate('common.details')} />
<View style={[styles.containerWithSpaceBetween, styles.pointerEventsBoxNone]}>
{details ? (
Expand Down
223 changes: 113 additions & 110 deletions src/pages/ProfilePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import _ from 'underscore';
import AutoUpdateTime from '@components/AutoUpdateTime';
import Avatar from '@components/Avatar';
import BlockingView from '@components/BlockingViews/BlockingView';
import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView';
import CommunicationsLink from '@components/CommunicationsLink';
import FullScreenLoadingIndicator from '@components/FullscreenLoadingIndicator';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
Expand Down Expand Up @@ -144,122 +145,124 @@ function ProfilePage(props) {

return (
<ScreenWrapper testID={ProfilePage.displayName}>
<HeaderWithBackButton
title={props.translate('common.profile')}
onBackButtonPress={() => Navigation.goBack(navigateBackTo)}
/>
<View style={[styles.containerWithSpaceBetween, styles.pointerEventsBoxNone]}>
{hasMinimumDetails && (
<ScrollView>
<View style={styles.avatarSectionWrapper}>
<PressableWithoutFocus
style={[styles.noOutline]}
onPress={() => Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))}
accessibilityLabel={props.translate('common.profile')}
accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
>
<OfflineWithFeedback pendingAction={lodashGet(details, 'pendingFields.avatar', null)}>
<Avatar
containerStyles={[styles.avatarXLarge, styles.mb3]}
imageStyles={[styles.avatarXLarge]}
source={UserUtils.getAvatar(avatar, accountID)}
size={CONST.AVATAR_SIZE.XLARGE}
fallbackIcon={fallbackIcon}
/>
</OfflineWithFeedback>
</PressableWithoutFocus>
{Boolean(displayName) && (
<Text
style={[styles.textHeadline, styles.pre, styles.mb6, styles.w100, styles.textAlignCenter]}
numberOfLines={1}
<FullPageNotFoundView shouldShow={CONST.RESTRICTED_ACCOUNT_IDS.includes(accountID)}>
<HeaderWithBackButton
title={props.translate('common.profile')}
onBackButtonPress={() => Navigation.goBack(navigateBackTo)}
/>
<View style={[styles.containerWithSpaceBetween, styles.pointerEventsBoxNone]}>
{hasMinimumDetails && (
<ScrollView>
<View style={styles.avatarSectionWrapper}>
<PressableWithoutFocus
style={[styles.noOutline]}
onPress={() => Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))}
accessibilityLabel={props.translate('common.profile')}
accessibilityRole={CONST.ACCESSIBILITY_ROLE.IMAGEBUTTON}
>
{displayName}
</Text>
)}
{hasStatus && (
<View style={[styles.mb6, styles.detailsPageSectionContainer, styles.mw100]}>
<OfflineWithFeedback pendingAction={lodashGet(details, 'pendingFields.avatar', null)}>
<Avatar
containerStyles={[styles.avatarXLarge, styles.mb3]}
imageStyles={[styles.avatarXLarge]}
source={UserUtils.getAvatar(avatar, accountID)}
size={CONST.AVATAR_SIZE.XLARGE}
fallbackIcon={fallbackIcon}
/>
</OfflineWithFeedback>
</PressableWithoutFocus>
{Boolean(displayName) && (
<Text
style={[styles.textLabelSupporting, styles.mb1]}
style={[styles.textHeadline, styles.pre, styles.mb6, styles.w100, styles.textAlignCenter]}
numberOfLines={1}
>
{props.translate('statusPage.status')}
{displayName}
</Text>
<Text>{statusContent}</Text>
</View>
)}
)}
{hasStatus && (
<View style={[styles.mb6, styles.detailsPageSectionContainer, styles.mw100]}>
<Text
style={[styles.textLabelSupporting, styles.mb1]}
numberOfLines={1}
>
{props.translate('statusPage.status')}
</Text>
<Text>{statusContent}</Text>
</View>
)}

{login ? (
<View style={[styles.mb6, styles.detailsPageSectionContainer, styles.w100]}>
<Text
style={[styles.textLabelSupporting, styles.mb1]}
numberOfLines={1}
>
{props.translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')}
</Text>
<CommunicationsLink value={phoneOrEmail}>
<UserDetailsTooltip accountID={details.accountID}>
<Text numberOfLines={1}>{isSMSLogin ? props.formatPhoneNumber(phoneNumber) : login}</Text>
</UserDetailsTooltip>
</CommunicationsLink>
</View>
) : null}
{pronouns ? (
<View style={[styles.mb6, styles.detailsPageSectionContainer]}>
<Text
style={[styles.textLabelSupporting, styles.mb1]}
numberOfLines={1}
>
{props.translate('profilePage.preferredPronouns')}
</Text>
<Text numberOfLines={1}>{pronouns}</Text>
</View>
) : null}
{shouldShowLocalTime && <AutoUpdateTime timezone={timezone} />}
</View>
{shouldShowNotificationPreference && (
<MenuItemWithTopDescription
shouldShowRightIcon
title={notificationPreference}
description={props.translate('notificationPreferencesPage.label')}
onPress={() => Navigation.navigate(ROUTES.REPORT_SETTINGS_NOTIFICATION_PREFERENCES.getRoute(props.report.reportID))}
wrapperStyle={[styles.mtn6, styles.mb5]}
/>
)}
{!isCurrentUser && !Session.isAnonymousUser() && (
<MenuItem
title={`${props.translate('common.message')}${displayName}`}
titleStyle={styles.flex1}
icon={Expensicons.ChatBubble}
onPress={() => Report.navigateToAndOpenReportWithAccountIDs([accountID])}
wrapperStyle={styles.breakAll}
shouldShowRightIcon
/>
)}
{!_.isEmpty(props.report) && (
<MenuItem
title={`${props.translate('privateNotes.title')}`}
titleStyle={styles.flex1}
icon={Expensicons.Pencil}
onPress={() => ReportUtils.navigateToPrivateNotes(props.report, props.session)}
wrapperStyle={styles.breakAll}
shouldShowRightIcon
brickRoadIndicator={Report.hasErrorInPrivateNotes(props.report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''}
/>
)}
</ScrollView>
)}
{!hasMinimumDetails && isLoading && <FullScreenLoadingIndicator style={styles.flex1} />}
{shouldShowBlockingView && (
<BlockingView
icon={Illustrations.ToddBehindCloud}
iconWidth={variables.modalTopIconWidth}
iconHeight={variables.modalTopIconHeight}
title={props.translate('notFound.notHere')}
shouldShowLink
link={props.translate('notFound.goBackHome')}
/>
)}
</View>
{login ? (
<View style={[styles.mb6, styles.detailsPageSectionContainer, styles.w100]}>
<Text
style={[styles.textLabelSupporting, styles.mb1]}
numberOfLines={1}
>
{props.translate(isSMSLogin ? 'common.phoneNumber' : 'common.email')}
</Text>
<CommunicationsLink value={phoneOrEmail}>
<UserDetailsTooltip accountID={details.accountID}>
<Text numberOfLines={1}>{isSMSLogin ? props.formatPhoneNumber(phoneNumber) : login}</Text>
</UserDetailsTooltip>
</CommunicationsLink>
</View>
) : null}
{pronouns ? (
<View style={[styles.mb6, styles.detailsPageSectionContainer]}>
<Text
style={[styles.textLabelSupporting, styles.mb1]}
numberOfLines={1}
>
{props.translate('profilePage.preferredPronouns')}
</Text>
<Text numberOfLines={1}>{pronouns}</Text>
</View>
) : null}
{shouldShowLocalTime && <AutoUpdateTime timezone={timezone} />}
</View>
{shouldShowNotificationPreference && (
<MenuItemWithTopDescription
shouldShowRightIcon
title={notificationPreference}
description={props.translate('notificationPreferencesPage.label')}
onPress={() => Navigation.navigate(ROUTES.REPORT_SETTINGS_NOTIFICATION_PREFERENCES.getRoute(props.report.reportID))}
wrapperStyle={[styles.mtn6, styles.mb5]}
/>
)}
{!isCurrentUser && !Session.isAnonymousUser() && (
<MenuItem
title={`${props.translate('common.message')}${displayName}`}
titleStyle={styles.flex1}
icon={Expensicons.ChatBubble}
onPress={() => Report.navigateToAndOpenReportWithAccountIDs([accountID])}
wrapperStyle={styles.breakAll}
shouldShowRightIcon
/>
)}
{!_.isEmpty(props.report) && (
<MenuItem
title={`${props.translate('privateNotes.title')}`}
titleStyle={styles.flex1}
icon={Expensicons.Pencil}
onPress={() => ReportUtils.navigateToPrivateNotes(props.report, props.session)}
wrapperStyle={styles.breakAll}
shouldShowRightIcon
brickRoadIndicator={Report.hasErrorInPrivateNotes(props.report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : ''}
/>
)}
</ScrollView>
)}
{!hasMinimumDetails && isLoading && <FullScreenLoadingIndicator style={styles.flex1} />}
{shouldShowBlockingView && (
<BlockingView
icon={Illustrations.ToddBehindCloud}
iconWidth={variables.modalTopIconWidth}
iconHeight={variables.modalTopIconHeight}
title={props.translate('notFound.notHere')}
shouldShowLink
link={props.translate('notFound.goBackHome')}
/>
)}
</View>
</FullPageNotFoundView>
</ScreenWrapper>
);
}
Expand Down
5 changes: 3 additions & 2 deletions src/pages/ReportParticipantsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ const getAllParticipants = (
ReportUtils.getVisibleMemberIDs(report)
.map((accountID, index) => {
const userPersonalDetail = personalDetails?.[accountID];
const userLogin = LocalePhoneNumber.formatPhoneNumber(userPersonalDetail?.login ?? '') ?? translate('common.hidden');
const userLogin =
!!userPersonalDetail?.login && !CONST.RESTRICTED_ACCOUNT_IDS.includes(accountID) ? LocalePhoneNumber.formatPhoneNumber(userPersonalDetail.login) : translate('common.hidden');
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(userPersonalDetail);

return {
Expand Down Expand Up @@ -76,7 +77,7 @@ function ReportParticipantsPage({report, personalDetails}: ReportParticipantsPag

const participants = getAllParticipants(report, personalDetails, translate).map((participant) => ({
...participant,
isDisabled: participant?.accountID ? ReportUtils.isOptimisticPersonalDetail(participant.accountID) : false,
isDisabled: ReportUtils.isOptimisticPersonalDetail(participant.accountID ?? 0) || CONST.RESTRICTED_ACCOUNT_IDS.includes(participant.accountID ?? 0),
}));

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,10 @@ function SuggestionMention({
if (!detail.login || detail.isOptimisticPersonalDetail) {
return false;
}
// We don't want to mention system emails like notifications@expensify.com
if (CONST.RESTRICTED_EMAILS.includes(detail.login) || CONST.RESTRICTED_ACCOUNT_IDS.includes(detail.accountID)) {
return false;
}
const displayName = PersonalDetailsUtils.getDisplayNameOrDefault(detail);
const displayText = displayName === formatPhoneNumber(detail.login) ? displayName : `${displayName} ${detail.login}`;
if (searchValue && !displayText.toLowerCase().includes(searchValue.toLowerCase())) {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/home/report/ReportActionItemSingle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ function ReportActionItemSingle({

const shouldDisableDetailPage = useMemo(
() =>
actorAccountID === CONST.ACCOUNT_ID.NOTIFICATIONS ||
CONST.RESTRICTED_ACCOUNT_IDS.includes(actorAccountID ?? 0) ||
(!isWorkspaceActor && ReportUtils.isOptimisticPersonalDetail(action.delegateAccountID ? Number(action.delegateAccountID) : actorAccountID ?? -1)),
[action, isWorkspaceActor, actorAccountID],
);
Expand Down

0 comments on commit be5ee07

Please sign in to comment.