Files
Compass/backend/api/src/update-notif-setting.ts
MartinBraquet d69bc44dfd Improve SQL robustness and security across notification settings, private messages, and utilities
- Replaced raw SQL interpolation with parameterized queries to prevent injection risks.
- Refactored user notification preference validation using runtime synchronized enums for enhanced type safety.
- Updated private message and channel membership checks to respect the "left" status.
- Enhanced JSONB handling in update queries for correctness and maintainability.
2026-07-23 14:14:26 +02:00

33 lines
1.2 KiB
TypeScript

import {createSupabaseDirectClient} from 'shared/supabase/init'
import {updatePrivateUser} from 'shared/supabase/users'
import {broadcastUpdatedPrivateUser} from 'shared/websockets/helpers'
import {type APIHandler} from './helpers/endpoint'
export const updateNotifSettings: APIHandler<'update-notif-settings'> = async (
{type, medium, enabled},
auth,
) => {
const pg = createSupabaseDirectClient()
if (type === 'opt_out_all' && medium === 'mobile') {
await updatePrivateUser(pg, auth.uid, {
interestedInPushNotifications: !enabled,
})
} else {
// deep update array at data.notificationPreferences[type].
// `type` and `medium` are passed as bound parameters (never interpolated into the SQL
// text) and are additionally constrained by the Zod enums on the endpoint schema. The
// jsonb path is built with array[...] so the key is a value, not raw SQL.
await pg.none(
`update private_users
set data = jsonb_set(data, array['notificationPreferences', $1],
coalesce(data->'notificationPreferences'->$1, '[]'::jsonb)
${enabled ? `|| to_jsonb($2::text)` : `- $2`}
)
where id = $3`,
[type, medium, auth.uid],
)
broadcastUpdatedPrivateUser(auth.uid)
}
}