Skip to content
8 changes: 8 additions & 0 deletions apps/docs/content/guides/platform/backups.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ If you enable PITR, Daily Backups will no longer be taken. PITR provides a finer

</Admonition>

When you disable PITR, all new backups will still be taken as physical backups only. Physical backups can still be used for restoration, but they are not available for direct download. If you need to download a backup after PITR is disabled, you’ll need to take a manual [logical backup using the Supabase CLI or pg_dump](https://supabase.com/docs/guides/platform/migrating-within-supabase/backup-restore#backup-database-using-the-cli).

<Admonition type="note">

If PITR has been disabled, logical backups remain available until they pass the backup retention period for your plan. After that window passes, only physical backups will be shown.

</Admonition>

### Backup process [#pitr-backup-process]

As discussed [here](https://supabase.com/blog/postgresql-physical-logical-backups), PITR is made possible by a combination of taking physical backups of a project, as well as archiving [Write Ahead Log (WAL)](https://www.postgresql.org/docs/current/wal-intro.html) files. Physical backups provide a snapshot of the underlying directory of the database, while WAL files contain records of every change made in the database.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export const RealtimeFilterPopover = ({ config, onChangeConfig }: RealtimeFilter
)}
</Button>
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_ className="p-0 w-[365px]" align="start">
<PopoverContent_Shadcn_ className="p-0 w-[365px]" align="start" portal={true}>
<div className="border-b border-overlay text-xs px-4 py-3 text-foreground">
Listen to event types
</div>
Expand Down
42 changes: 42 additions & 0 deletions apps/studio/components/interfaces/Realtime/RealtimeSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { PermissionAction } from '@supabase/shared-types/out/constants'
import Link from 'next/link'
import { useEffect } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import { toast } from 'sonner'
Expand All @@ -11,6 +12,7 @@ import { ScaffoldSection } from 'components/layouts/Scaffold'
import AlertError from 'components/ui/AlertError'
import { FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms/FormSection'
import { InlineLink } from 'components/ui/InlineLink'
import { useDatabasePoliciesQuery } from 'data/database-policies/database-policies-query'
import { useMaxConnectionsQuery } from 'data/database/max-connections-query'
import { useRealtimeConfigurationUpdateMutation } from 'data/realtime/realtime-config-mutation'
import {
Expand Down Expand Up @@ -50,8 +52,21 @@ export const RealtimeSettings = () => {
projectRef,
})

const { data: policies } = useDatabasePoliciesQuery({
projectRef,
connectionString: project?.connectionString,
schema: 'realtime',
})

const isUsageBillingEnabled = organization?.usage_billing_enabled

// Check if RLS policies exist for realtime.messages table
const realtimeMessagesPolicies = policies?.filter(
(policy) => policy.schema === 'realtime' && policy.table === 'messages'
)
const hasRealtimeMessagesPolicies =
realtimeMessagesPolicies && realtimeMessagesPolicies.length > 0

const { mutate: updateRealtimeConfig, isLoading: isUpdatingConfig } =
useRealtimeConfigurationUpdateMutation({
onSuccess: () => {
Expand Down Expand Up @@ -83,6 +98,9 @@ export const RealtimeSettings = () => {
},
})

const { allow_public } = form.watch()
const isSettingToPrivate = !data?.private_only && !allow_public

const onSubmit: SubmitHandler<z.infer<typeof FormSchema>> = (data) => {
if (!projectRef) return console.error('Project ref is required')
updateRealtimeConfig({
Expand Down Expand Up @@ -132,6 +150,30 @@ export const RealtimeSettings = () => {
/>
</FormControl_Shadcn_>
</FormItemLayout>

{!hasRealtimeMessagesPolicies && !allow_public && (
<Admonition
showIcon={false}
type="warning"
title="No Realtime RLS policies found"
description={
<>
<p className="prose max-w-full text-sm">
Private mode is {isSettingToPrivate ? 'being ' : ''}
enabled, but no RLS policies exists on the{' '}
<code className="text-xs">realtime.messages</code> table. No
messages will be received by users.
</p>

<Button asChild type="default" className="mt-2">
<Link href={`/project/${projectRef}/realtime/policies`}>
Create policy
</Link>
</Button>
</>
}
/>
)}
</FormSectionContent>
</FormSection>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const RoleImpersonationPopover = ({
</PopoverTrigger_Shadcn_>
<PopoverContent_Shadcn_
portal={portal}
className="p-0 w-full overflow-hidden"
className="p-0 w-[592px] overflow-hidden"
side="bottom"
align={align}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ const RoleImpersonationSelector = ({
{selectedOption === 'authenticated' && (
<>
<DropdownMenuSeparator />
<div className={cn('py-5', padded && 'px-5')}>
<UserImpersonationSelector />
</div>
<UserImpersonationSelector />
</>
)}
</>
Expand Down
Loading
Loading