Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Automatic Merge
  • Loading branch information
mattermost-build authored Nov 28, 2024
1 parent 2042d5e commit 55bd7de
Show file tree
Hide file tree
Showing 10 changed files with 53 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {UserProfile} from '@mattermost/types/users';

import {Posts} from 'mattermost-redux/constants';
import type {MessageData} from 'mattermost-redux/utils/post_list';
import {secureGetFromRecord} from 'mattermost-redux/utils/post_utils';

import Markdown from 'components/markdown';

Expand Down Expand Up @@ -264,7 +265,8 @@ export class CombinedSystemMessage extends React.PureComponent<Props> {
return userId !== currentUserId && userId !== currentUsername;
}).
map((userId) => {
return allUsernames[userId] ? `@${allUsernames[userId]}` : someone;
const username = secureGetFromRecord(allUsernames, userId);
return username ? `@${username}` : someone;
}).
filter((username) => {
return username && username !== '';
Expand Down Expand Up @@ -299,11 +301,16 @@ export class CombinedSystemMessage extends React.PureComponent<Props> {
singleline: true,
};

const selectedPostTypeMessage = secureGetFromRecord(postTypeMessage, postType);
if (!selectedPostTypeMessage) {
return <></>;
}

if (numOthers > 1) {
return (
<LastUsers
actor={actor}
expandedLocale={postTypeMessage[postType].many_expanded}
expandedLocale={selectedPostTypeMessage.many_expanded}
formatOptions={options}
postType={postType}
usernames={usernames}
Expand All @@ -313,16 +320,16 @@ export class CombinedSystemMessage extends React.PureComponent<Props> {

let localeHolder: MessageDescriptor = {};
if (numOthers === 0) {
localeHolder = postTypeMessage[postType].one;
localeHolder = selectedPostTypeMessage.one;

if (
(userIds[0] === this.props.currentUserId || userIds[0] === this.props.currentUsername) &&
postTypeMessage[postType].one_you
selectedPostTypeMessage.one_you
) {
localeHolder = postTypeMessage[postType].one_you;
localeHolder = selectedPostTypeMessage.one_you;
}
} else if (numOthers === 1) {
localeHolder = postTypeMessage[postType].two;
localeHolder = selectedPostTypeMessage.two;
}

const formattedMessage = formatMessage(localeHolder, {firstUser, secondUser, actor});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {defineMessages, injectIntl} from 'react-intl';
import type {IntlShape, MessageDescriptor} from 'react-intl';

import {Posts} from 'mattermost-redux/constants';
import {secureGetFromRecord} from 'mattermost-redux/utils/post_utils';

import Markdown from 'components/markdown';

Expand Down Expand Up @@ -121,10 +122,12 @@ export class LastUsers extends React.PureComponent<Props, State> {
{numOthers: lastIndex},
);

const actorMessage = formatMessage(
{id: typeMessage[postType].id, defaultMessage: typeMessage[postType].defaultMessage},
const selectedTypeMessage = secureGetFromRecord(typeMessage, postType);

const actorMessage = selectedTypeMessage ? formatMessage(
{id: selectedTypeMessage.id, defaultMessage: selectedTypeMessage.defaultMessage},
{actor},
);
) : '';

return (
<span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import styled, {css} from 'styled-components';
import type {PostAction, PostActionOption} from '@mattermost/types/integration_actions';

import type {Theme} from 'mattermost-redux/selectors/entities/preferences';
import {secureGetFromRecord} from 'mattermost-redux/utils/post_utils';
import {changeOpacity} from 'mattermost-redux/utils/theme_utils';

import Markdown from 'components/markdown';
Expand Down Expand Up @@ -51,8 +52,8 @@ const ActionButton = ({
if (action.style) {
const STATUS_COLORS = getStatusColors(theme);
hexColor =
STATUS_COLORS[action.style] ||
theme[action.style] ||
secureGetFromRecord(STATUS_COLORS, action.style) ||
secureGetFromRecord(theme, action.style) ||
(action.style.match('^#(?:[0-9a-fA-F]{3}){1,2}$') && action.style);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type {ConnectedProps} from 'react-redux';

import type {PostAction} from '@mattermost/types/integration_actions';

import {secureGetFromRecord} from 'mattermost-redux/utils/post_utils';

import {autocompleteChannels} from 'actions/channel_actions';
import {autocompleteUsers} from 'actions/user_actions';
import {selectAttachmentMenuAction} from 'actions/views/posts';
Expand All @@ -22,7 +24,7 @@ export type OwnProps = {

function mapStateToProps(state: GlobalState, ownProps: OwnProps) {
const actions = state.views.posts.menuActions[ownProps.postId];
const selected = (ownProps.action && ownProps.action.id) ? actions && actions[ownProps.action && ownProps.action.id] : undefined;
const selected = (ownProps.action?.id) ? secureGetFromRecord(actions, ownProps.action.id) : undefined;

return {
selected,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
import type {PostImage} from '@mattermost/types/posts';

import type {ActionResult} from 'mattermost-redux/types/actions';
import {secureGetFromRecord} from 'mattermost-redux/utils/post_utils';

import {trackEvent} from 'actions/telemetry_actions';

Expand Down Expand Up @@ -101,7 +102,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>
if (!attachment.thumb_url) {
return;
}
if (!this.props.imagesMetadata || (this.props.imagesMetadata && !this.props.imagesMetadata[attachment.thumb_url])) {
if (!secureGetFromRecord(this.props.imagesMetadata, attachment.thumb_url)) {
this.handleHeightReceived(height);
}
};
Expand All @@ -111,7 +112,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>
if (!attachment.image_url) {
return;
}
if (!this.props.imagesMetadata || (this.props.imagesMetadata && !this.props.imagesMetadata[attachment.image_url])) {
if (!secureGetFromRecord(this.props.imagesMetadata, attachment.image_url)) {
this.handleHeightReceived(height);
}
};
Expand Down Expand Up @@ -369,7 +370,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>
<ExternalImage
key={'attachment__author-icon'}
src={attachment.author_icon}
imageMetadata={this.props.imagesMetadata && this.props.imagesMetadata[attachment.author_icon]}
imageMetadata={secureGetFromRecord(this.props.imagesMetadata, attachment.author_icon)}
>
{(iconUrl) => (
<img
Expand Down Expand Up @@ -459,7 +460,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>

let image;
if (attachment.image_url) {
const imageMetadata = this.props.imagesMetadata && this.props.imagesMetadata[attachment.image_url];
const imageMetadata = secureGetFromRecord(this.props.imagesMetadata, attachment.image_url);

image = (
<div className='attachment__image-container'>
Expand All @@ -485,7 +486,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>
if (attachment.footer) {
let footerIcon;
if (attachment.footer_icon) {
const footerIconMetadata = this.props.imagesMetadata && this.props.imagesMetadata[attachment.footer_icon];
const footerIconMetadata = secureGetFromRecord(this.props.imagesMetadata, attachment.footer_icon);

footerIcon = (
<ExternalImage
Expand Down Expand Up @@ -515,7 +516,7 @@ export default class MessageAttachment extends React.PureComponent<Props, State>

let thumb;
if (attachment.thumb_url) {
const thumbMetadata = this.props.imagesMetadata && this.props.imagesMetadata[attachment.thumb_url];
const thumbMetadata = secureGetFromRecord(this.props.imagesMetadata, attachment.thumb_url);

thumb = (
<div className='attachment__thumb-container'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,9 @@ export function getNeededAtMentionedUsernamesAndGroups(state: GlobalState, posts

if (attachment.fields) {
for (const field of attachment.fields) {
findNeededUsernamesAndGroups(field.value);
if (typeof field.value === 'string') {
findNeededUsernamesAndGroups(field.value);
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
} from 'mattermost-redux/selectors/entities/common';
import {getConfig, getLicense} from 'mattermost-redux/selectors/entities/general';
import {getDirectShowPreferences, getTeammateNameDisplaySetting} from 'mattermost-redux/selectors/entities/preferences';
import {secureGetFromRecord} from 'mattermost-redux/utils/post_utils';
import {
displayUsername,
filterProfilesStartingWithTerm,
Expand Down Expand Up @@ -687,7 +688,7 @@ export function makeGetProfilesByIdsAndUsernames(): (

if (allUserIds && allUserIds.length > 0) {
const profilesById = allUserIds.
filter((userId) => allProfilesById[userId]).
filter((userId) => secureGetFromRecord(allProfilesById, userId)).
map((userId) => allProfilesById[userId]);

if (profilesById && profilesById.length > 0) {
Expand All @@ -697,7 +698,7 @@ export function makeGetProfilesByIdsAndUsernames(): (

if (allUsernames && allUsernames.length > 0) {
const profilesByUsername = allUsernames.
filter((username) => allProfilesByUsername[username]).
filter((username) => secureGetFromRecord(allProfilesByUsername, username)).
map((username) => allProfilesByUsername[username]);

if (profilesByUsername && profilesByUsername.length > 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,3 +249,7 @@ export function ensureString(v: unknown) {
export function ensureNumber(v: unknown) {
return typeof v === 'number' ? v : 0;
}

export function secureGetFromRecord<T>(v: Record<string, T> | undefined, key: string) {
return typeof v === 'object' && v && Object.hasOwn(v, key) ? v[key] : undefined;
}
9 changes: 8 additions & 1 deletion webapp/channels/src/selectors/views/custom_status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@ import configureStore from 'store';
import {TestHelper} from 'utils/test_helper';
import {addTimeToTimestamp, TimeInformation} from 'utils/utils';

jest.mock('mattermost-redux/selectors/entities/users');
jest.mock('mattermost-redux/selectors/entities/users', () => {
const originalModule = jest.requireActual('mattermost-redux/selectors/entities/users');
return {
...originalModule,
getCurrentUser: jest.fn(),
getUser: jest.fn(),
};
});
jest.mock('mattermost-redux/selectors/entities/general');
jest.mock('mattermost-redux/selectors/entities/preferences');

Expand Down
5 changes: 3 additions & 2 deletions webapp/channels/src/selectors/views/marketplace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {MarketplaceApp, MarketplacePlugin} from '@mattermost/types/marketpl

import {createSelector} from 'mattermost-redux/selectors/create_selector';
import {isPlugin} from 'mattermost-redux/utils/marketplace';
import {secureGetFromRecord} from 'mattermost-redux/utils/post_utils';

import type {GlobalState} from 'types/store';

Expand Down Expand Up @@ -45,6 +46,6 @@ export const getApp = (state: GlobalState, id: string): MarketplaceApp | undefin

export const getFilter = (state: GlobalState): string => state.views.marketplace.filter;

export const getInstalling = (state: GlobalState, id: string): boolean => Boolean(state.views.marketplace.installing[id]);
export const getInstalling = (state: GlobalState, id: string): boolean => Boolean(secureGetFromRecord(state.views.marketplace.installing, id));

export const getError = (state: GlobalState, id: string): string => state.views.marketplace.errors[id];
export const getError = (state: GlobalState, id: string): string | undefined => secureGetFromRecord(state.views.marketplace.errors, id);

0 comments on commit 55bd7de

Please sign in to comment.