Files
supabase/apps/studio/data/jit-db-access/jit-db-access-grant-mutation.ts
85743d7215 feat: branching support for temporary access (#45411)
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.

YES

## What kind of change does this PR introduce?

feature


## Additional context

Needs API deployment, adds a toggle to allow roles to only be available
on branch projects


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a "Branches only" option for JIT database access grants;
included when grants are submitted.

* **UI**
* Configuration UI shows an informational notice and hides
temporary-access controls when preview branches are managed from the
main branch.
* Feature preview label changed to "Temporary access"; badge text now
reads "Preview".

* **Tests**
  * Unit test updated to cover branches-only serialization.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45411?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Danny White <3104761+dnywh@users.noreply.github.com>
Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-05-18 09:47:59 +02:00

69 lines
2.0 KiB
TypeScript

import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { jitDbAccessKeys } from './keys'
import { handleError, put } from '@/data/fetchers'
import type { ResponseError } from '@/types'
type JitDbAccessGrantVariables = {
projectRef: string
userId: string
roles: Array<{
role: string
branches_only?: boolean
expires_at?: number // Unix timestamp in seconds per role
allowed_networks?: {
allowed_cidrs?: Array<{ cidr: string }>
allowed_cidrs_v6?: Array<{ cidr: string }>
}
}>
}
async function grantJitDbAccess({ projectRef, userId, roles }: JitDbAccessGrantVariables) {
if (!projectRef) throw new Error('projectRef is required')
if (!userId) throw new Error('userId is required')
if (!roles || roles.length === 0) throw new Error('At least one role is required')
const { data, error } = await put(`/v1/projects/{ref}/database/jit`, {
params: { path: { ref: projectRef } },
body: {
user_id: userId,
roles,
},
})
if (error) handleError(error)
return data
}
type JitDbAccessGrantData = Awaited<ReturnType<typeof grantJitDbAccess>>
export const useJitDbAccessGrantMutation = ({
onSuccess,
onError,
...options
}: Omit<
UseMutationOptions<JitDbAccessGrantData, ResponseError, JitDbAccessGrantVariables>,
'mutationFn'
> = {}) => {
const queryClient = useQueryClient()
return useMutation<JitDbAccessGrantData, ResponseError, JitDbAccessGrantVariables>({
mutationFn: (vars) => grantJitDbAccess(vars),
async onSuccess(data, variables, context) {
const { projectRef } = variables
await queryClient.invalidateQueries({ queryKey: jitDbAccessKeys.members(projectRef) })
await onSuccess?.(data, variables, context)
},
async onError(data, variables, context) {
if (onError === undefined) {
toast.error(`Failed to grant temporary access: ${data.message}`)
} else {
onError(data, variables, context)
}
},
...options,
})
}