Skip to content

Commit 807228e

Browse files
committed
fix: add validation guards for status expiration inputs
1 parent 24d4734 commit 807228e

4 files changed

Lines changed: 26 additions & 6 deletions

File tree

apps/meteor/app/api/server/v1/users.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ API.v1.addRoute(
649649
if (!canViewFullOtherUserInfo) {
650650
return API.v1.forbidden();
651651
}
652-
const escapedEmail = escapeRegExp(this.queryParams.email as string);
652+
const escapedEmail = escapeRegExp(this.queryParams.email);
653653
nonEmptyQuery['emails.address'] = {
654654
$regex: `^${escapedEmail}$`,
655655
$options: 'i',
@@ -2002,7 +2002,16 @@ API.v1
20022002
statusDefault: status,
20032003
statusSource: 'manual',
20042004
...(this.bodyParams.message != null && { statusText: this.bodyParams.message }),
2005-
...(this.bodyParams.expiresAt && { statusExpiresAt: new Date(this.bodyParams.expiresAt) }),
2005+
...(this.bodyParams.expiresAt &&
2006+
(() => {
2007+
const date = new Date(this.bodyParams.expiresAt);
2008+
if (isNaN(date.getTime())) {
2009+
throw new Meteor.Error('error-invalid-date', 'Invalid expiresAt date string', {
2010+
method: 'users.setStatus',
2011+
});
2012+
}
2013+
return { statusExpiresAt: date };
2014+
})()),
20062015
});
20072016
}
20082017

apps/meteor/client/components/UserStatusText/useExpirationText.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ export function parseExpiresAt(value?: unknown): Date | undefined {
1515
}
1616

1717
if (typeof value === 'object' && '$date' in (value as Record<string, unknown>)) {
18-
return new Date((value as { $date: number }).$date);
18+
const date = new Date((value as { $date: number }).$date);
19+
return Number.isNaN(date.getTime()) ? undefined : date;
1920
}
2021

2122
if (typeof value === 'string') {

apps/meteor/client/navbar/NavBarSettingsToolbar/UserMenu/EditStatusModal.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
9898
const [duration, setDuration] = useState('');
9999
const [customDate, setCustomDate] = useState(() => new Date().toLocaleDateString('en-CA'));
100100
const [customTime, setCustomTime] = useState(() => new Date().toTimeString().slice(0, 5));
101+
const minCustomDate = useMemo(() => new Date().toLocaleDateString('en-CA'), []);
101102

102103
const setUserStatus = useEndpoint('POST', '/v1/users.setStatus');
103104
const formatTime = useFormatTime();
@@ -123,9 +124,13 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
123124

124125
const computeExpiresAt = useCallback((): Date | undefined => {
125126
if (duration === 'custom') {
127+
if (!customDate || !customTime) {
128+
return undefined;
129+
}
126130
const [year, month, day] = customDate.split('-').map(Number);
127131
const [hours, mins] = customTime.split(':').map(Number);
128-
return new Date(year, month - 1, day, hours, mins, 0, 0);
132+
const parsedDate = new Date(year, month - 1, day, hours, mins, 0, 0);
133+
return Number.isNaN(parsedDate.getTime()) ? undefined : parsedDate;
129134
}
130135

131136
const option = DURATION_OPTIONS.find((o) => o.value === duration);
@@ -143,6 +148,10 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
143148
const handleSaveStatus = useCallback(async () => {
144149
try {
145150
const expiresAt = computeExpiresAt();
151+
if (duration === 'custom' && !expiresAt) {
152+
dispatchToastMessage({ type: 'error', message: t('Status_choose_date_and_time') });
153+
return;
154+
}
146155
await setUserStatus({
147156
message: statusText,
148157
status: statusType as UserStatusType,
@@ -155,7 +164,7 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
155164
}
156165

157166
onClose();
158-
}, [onClose, setUserStatus, statusText, statusType, computeExpiresAt, setCustomStatus, dispatchToastMessage, t]);
167+
}, [onClose, setUserStatus, statusText, statusType, computeExpiresAt, setCustomStatus, dispatchToastMessage, t, duration]);
159168

160169
return (
161170
<Modal
@@ -234,7 +243,7 @@ const EditStatusModal = ({ onClose, userStatus, userStatusText }: EditStatusModa
234243
flexGrow={1}
235244
value={customDate}
236245
onChange={(e: ChangeEvent<HTMLInputElement>) => setCustomDate(e.currentTarget.value)}
237-
min={customDate}
246+
min={minCustomDate}
238247
/>
239248
<InputBox
240249
aria-label='Expiration time'

apps/meteor/client/sidebar/RoomList/SidebarItemTemplateWithData.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ const keys: (keyof RoomListRowProps)[] = [
168168
't',
169169
'sidebarViewMode',
170170
'videoConfActions',
171+
'userId',
171172
];
172173

173174
export default memo(SidebarItemTemplateWithData, (prevProps, nextProps) => {

0 commit comments

Comments
 (0)