Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 6 additions & 0 deletions static/gsAdmin/components/createBroadcastModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ export function CreateBroadcastModal({
category: data.category || undefined,
mediaUrl: data.mediaUrl || undefined,
region: data.region || undefined,
organizations: data.organizations
? String(data.organizations)
.split(',')
.map(s => Number(s.trim()))
.filter(n => n > 0)
: undefined,
};

updateBroadcast(newData);
Expand Down
8 changes: 8 additions & 0 deletions static/gsAdmin/schemas/broadcasts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ export function getBroadcastSchema(): Field[] {
label: 'Link',
placeholder: 'e.g. https://blog.sentry.io/2021/01/01/shiny-new-feature',
},
{
name: 'organizations',
type: 'string',
required: false,
label: 'Organization IDs',
placeholder: 'e.g. 123, 456, 789 (leave empty to broadcast to all users)',
help: 'Comma-separated list of organization IDs to restrict this broadcast to. If left empty, the broadcast will be shown to all users.',
},
{
name: 'mediaUrl',
type: 'string',
Expand Down
4 changes: 4 additions & 0 deletions static/gsAdmin/views/broadcastDetails.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ describe('Broadcast Details', () => {
platform: ['bun', 'capacitor'],
product: ['errors', 'spans'],
createdBy: 'admin@sentry.io',
organizations: [123, 456],
earlyAdopter: true,
};

Expand Down Expand Up @@ -60,6 +61,9 @@ describe('Broadcast Details', () => {
expect(
screen.getByText(textWithMarkupMatcher('Created By:admin@sentry.io'))
).toBeInTheDocument();
expect(
screen.getByText(textWithMarkupMatcher('Organization IDs:123, 456'))
).toBeInTheDocument();
expect(
screen.getByText(textWithMarkupMatcher('Early Adopter:Yes'))
).toBeInTheDocument();
Expand Down
20 changes: 18 additions & 2 deletions static/gsAdmin/views/broadcastDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ export function BroadcastDetails() {
<DetailLabel title="Link">
<ExternalLink href={data.link}>{data.link}</ExternalLink>
</DetailLabel>
<DetailLabel title="Organization IDs">
{data.organizations?.length ? data.organizations.join(', ') : '-'}
</DetailLabel>
<DetailLabel title="Media URL">{data.mediaUrl ?? '-'}</DetailLabel>
<DetailLabel title="Category">
{formatData(data.category, CATEGORYCHOICES)}
Expand Down Expand Up @@ -166,6 +169,12 @@ export function BroadcastDetails() {
}
payload[key] = value;
}
if (typeof formData.organizations === 'string') {
payload.organizations = formData.organizations
.split(',')
.map((s: string) => Number(s.trim()))
.filter((n: number) => n > 0);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty org field sends array

High Severity

On broadcast edit save, an empty organizations text field is always converted to an empty array in the PUT payload. Create treats a blank field as undefined (all users), and the field help says empty means everyone. Saving any unrestricted broadcast—or clearing org IDs—can persist organizations: [] instead of removing targeting.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 26e2194. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine. We want to pass empty organizations list if the field is empty.

return payload;
}}
onSubmitSuccess={() => {
Expand Down Expand Up @@ -194,8 +203,9 @@ export function BroadcastDetails() {
roles: data.roles ?? [],
plans: data.plans ?? [],
trialStatus: data.trialStatus ?? undefined,
organizations: data.organizations?.length ? data.organizations.join(', ') : '',
earlyAdopter: Boolean(data.earlyAdopter),
region: data.region ?? [],
region: data.region ?? undefined,
platform: data.platform ?? [],
product: data.product ?? [],
}}
Expand Down Expand Up @@ -226,6 +236,13 @@ export function BroadcastDetails() {
maxLength={256}
/>
<TextField {...fieldProps} name="link" label="Link" required />
<TextField
{...fieldProps}
name="organizations"
label="Organization IDs"
help="Comma-separated list of organization IDs to restrict this broadcast to. If left empty, the broadcast will be shown to all users."
placeholder="e.g. 123, 456, 789 (leave empty to broadcast to all users)"
/>
<TextField
{...fieldProps}
name="mediaUrl"
Expand Down Expand Up @@ -266,7 +283,6 @@ export function BroadcastDetails() {
{...fieldProps}
name="region"
label="Region"
multiple
options={toOptions(REGIONCHOICES)}
/>
<SelectField
Expand Down
Loading