Skip to content

Commit

Permalink
fix(issues): Remove falsy values from user (#80154)
Browse files Browse the repository at this point in the history
  • Loading branch information
scttcper authored Nov 1, 2024
1 parent 526ec6f commit c91243c
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 22 deletions.
19 changes: 11 additions & 8 deletions static/app/components/events/contexts/contextCard.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styled from '@emotion/styled';
import startCase from 'lodash/startCase';

import ErrorBoundary from 'sentry/components/errorBoundary';
import type {ContextValue} from 'sentry/components/events/contexts';
import {
getContextIcon,
Expand Down Expand Up @@ -111,14 +112,16 @@ export default function ContextCard({
<Title>
<div>{getContextTitle({alias, type, value})}</div>
<div>
{getContextIcon({
alias,
type,
value,
contextIconProps: {
size: 'sm',
},
})}
<ErrorBoundary customComponent={null}>
{getContextIcon({
alias,
type,
value,
contextIconProps: {
size: 'sm',
},
})}
</ErrorBoundary>
</div>
</Title>
}
Expand Down
4 changes: 2 additions & 2 deletions static/app/components/events/contexts/user/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import UserAvatar from 'sentry/components/avatar/userAvatar';
import ErrorBoundary from 'sentry/components/errorBoundary';
import ContextBlock from 'sentry/components/events/contexts/contextBlock';
import KeyValueList from 'sentry/components/events/interfaces/keyValueList';
import {removeFilterMaskedEntries} from 'sentry/components/events/interfaces/utils';
import {userContextToActor} from 'sentry/components/events/interfaces/utils';
import type {Event} from 'sentry/types/event';
import type {AvatarUser} from 'sentry/types/user';
import {defined} from 'sentry/utils';
Expand Down Expand Up @@ -76,7 +76,7 @@ export function UserEventContext({data, event, meta: propsMeta}: Props) {
return (
<div className="user-widget">
<div className="pull-left">
<UserAvatar user={removeFilterMaskedEntries(data)} size={48} gravatar={false} />
<UserAvatar user={userContextToActor(data)} size={48} gravatar={false} />
</div>
<ContextBlock data={knownStructuredData} />
<ContextBlock data={unknownData} />
Expand Down
4 changes: 2 additions & 2 deletions static/app/components/events/contexts/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
type ContextIconProps,
getLogoImage,
} from 'sentry/components/events/contexts/contextIcon';
import {removeFilterMaskedEntries} from 'sentry/components/events/interfaces/utils';
import {userContextToActor} from 'sentry/components/events/interfaces/utils';
import StructuredEventData from 'sentry/components/structuredEventData';
import {t} from 'sentry/locale';
import plugins from 'sentry/plugins';
Expand Down Expand Up @@ -417,7 +417,7 @@ export function getContextIcon({
iconName = generateIconName(value?.name, value?.version);
break;
case 'user':
const user = removeFilterMaskedEntries(value);
const user = userContextToActor(value);
const iconSize = commonTheme.iconNumberSizes[contextIconProps?.size ?? 'xl'];
return <UserAvatar user={user as AvatarUser} size={iconSize} gravatar={false} />;
case 'gpu':
Expand Down
15 changes: 12 additions & 3 deletions static/app/components/events/interfaces/utils.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {
getCurrentThread,
getThreadById,
objectToSortedTupleArray,
removeFilterMaskedEntries,
stringifyQueryList,
userContextToActor,
} from 'sentry/components/events/interfaces/utils';
import {MetaProxy, withMeta} from 'sentry/components/events/meta/metaProxy';
import {FILTER_MASK} from 'sentry/constants';
Expand Down Expand Up @@ -268,12 +268,21 @@ describe('components/interfaces/utils', function () {
email: FILTER_MASK,
};
it('should remove filtered values', function () {
const result = removeFilterMaskedEntries(rawData);
const result = userContextToActor(rawData);
expect(result).not.toHaveProperty('name');
expect(result).not.toHaveProperty('email');
});
it('should remove boolean values', function () {
const result = userContextToActor({
...rawData,
name: true,
email: false,
});
expect(result).not.toHaveProperty('name');
expect(result).not.toHaveProperty('email');
});
it('should preserve unfiltered values', function () {
const result = removeFilterMaskedEntries(rawData);
const result = userContextToActor(rawData);
expect(result).toHaveProperty('id');
expect(result.id).toEqual('26');
expect(result).toHaveProperty('username');
Expand Down
25 changes: 18 additions & 7 deletions static/app/components/events/interfaces/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type {EntryRequest, EntryThreads, Event, Frame, Thread} from 'sentry/type
import {EntryType} from 'sentry/types/event';
import type {PlatformKey} from 'sentry/types/project';
import type {StacktraceType} from 'sentry/types/stacktrace';
import type {AvatarUser} from 'sentry/types/user';
import {defined} from 'sentry/utils';
import {fileExtensionToPlatform, getFileExtension} from 'sentry/utils/fileExtension';

Expand Down Expand Up @@ -239,15 +240,25 @@ export function objectToSortedTupleArray(obj: Record<string, string | string[]>)
});
}

// for context summaries and avatars
export function removeFilterMaskedEntries<T extends Record<string, any>>(rawData: T): T {
const cleanedData: Record<string, any> = {};
for (const key of Object.getOwnPropertyNames(rawData)) {
if (rawData[key] !== FILTER_MASK) {
cleanedData[key] = rawData[key];
function isValidContextValue(value: unknown): value is string {
return typeof value === 'string' && value !== FILTER_MASK;
}

const userAvatarKeys = ['id', 'ip', 'username', 'ip_address', 'name', 'email'] as const;

/**
* Convert a user context object to an actor object for avatar display
*/
export function userContextToActor(rawData: Record<string, unknown>): AvatarUser {
const result: Partial<AvatarUser> = {};

for (const key of userAvatarKeys) {
if (isValidContextValue(rawData[key])) {
result[key] = rawData[key];
}
}
return cleanedData as T;

return result as AvatarUser;
}

export function formatAddress(address: number, imageAddressLength: number | undefined) {
Expand Down

0 comments on commit c91243c

Please sign in to comment.