mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
chore: better ipv6 migration notices (#20817)
* chore: better ipv6 migration notices * adds multiple dismisses * add migration for ipv6_active_status rpc * fix sql syntax * use rpc * Fix NoticeBanner acknowledged logic * ci: Autofix updates from GitHub workflow * Remove console log * Lint * Fix logic * Update pgbouncer and vercel notices to be project specific --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com> Co-authored-by: github-tidy-bot <github-tidy-bot@supabase.com>
This commit is contained in:
4 files changed
+165
-20
No files matched your search
@@ -3,38 +3,75 @@ import { PropsWithChildren, createContext, useContext, useEffect, useState } fro
|
||||
|
||||
import { LOCAL_STORAGE_KEYS } from 'lib/constants'
|
||||
|
||||
const NOTICE_BANNER_KEY = LOCAL_STORAGE_KEYS.PGBOUNCER_DEPRECATION_WARNING
|
||||
const PGBOUNCER_BANNER_KEY = LOCAL_STORAGE_KEYS.PGBOUNCER_IPV6_DEPRECATION_WARNING
|
||||
const VERCEL_BANNER_KEY = LOCAL_STORAGE_KEYS.VERCEL_IPV6_DEPRECATION_WARNING
|
||||
const DEFAULT_NOTICE_BANNER_KEY = LOCAL_STORAGE_KEYS.PGBOUNCER_DEPRECATION_WARNING
|
||||
|
||||
// [Joshen] Update this as and when we need to use the NoticeBanner
|
||||
|
||||
type AppBannerContextType = {
|
||||
acknowledged: boolean
|
||||
onUpdateAcknowledged: (value: boolean) => void
|
||||
ipv6BannerAcknowledged: boolean
|
||||
pgbouncerBannerAcknowledged: string[]
|
||||
vercelBannerAcknowledged: string[]
|
||||
onUpdateAcknowledged: (key: 'ipv6' | 'pgbouncer' | 'vercel', value: boolean | string) => void
|
||||
}
|
||||
|
||||
const AppBannerContext = createContext<AppBannerContextType>({
|
||||
acknowledged: false,
|
||||
ipv6BannerAcknowledged: false,
|
||||
pgbouncerBannerAcknowledged: [],
|
||||
vercelBannerAcknowledged: [],
|
||||
onUpdateAcknowledged: noop,
|
||||
})
|
||||
|
||||
export const useAppBannerContext = () => useContext(AppBannerContext)
|
||||
|
||||
export const AppBannerContextProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
const [acknowledged, setAcknowledged] = useState(false)
|
||||
const [ipv6BannerAcknowledged, setIpv6BannerAcknowledged] = useState(false)
|
||||
|
||||
// [Joshen] These will take a list of refs instead since they are project specific
|
||||
// Comma separated strings, no spaces
|
||||
const [pgbouncerBannerAcknowledged, setPgbouncerBannerAcknowledged] = useState<string[]>([])
|
||||
const [vercelBannerAcknowledged, setVercelBannerAcknowledged] = useState<string[]>([])
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
setAcknowledged(localStorage.getItem(NOTICE_BANNER_KEY) === 'true')
|
||||
setIpv6BannerAcknowledged(localStorage.getItem(DEFAULT_NOTICE_BANNER_KEY) === 'true')
|
||||
|
||||
const acknowledgedPbBouncerRefs = localStorage.getItem(PGBOUNCER_BANNER_KEY)?.split(',') ?? []
|
||||
setPgbouncerBannerAcknowledged(acknowledgedPbBouncerRefs)
|
||||
|
||||
const acknowledgedVercelRefs = localStorage.getItem(VERCEL_BANNER_KEY)?.split(',') ?? []
|
||||
setVercelBannerAcknowledged(acknowledgedVercelRefs)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const value = {
|
||||
acknowledged,
|
||||
onUpdateAcknowledged: (value: boolean) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(NOTICE_BANNER_KEY, value.toString())
|
||||
ipv6BannerAcknowledged,
|
||||
pgbouncerBannerAcknowledged,
|
||||
vercelBannerAcknowledged,
|
||||
onUpdateAcknowledged: (key: 'ipv6' | 'pgbouncer' | 'vercel', value: boolean | string) => {
|
||||
if (key === 'ipv6' && typeof value === 'boolean') {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(DEFAULT_NOTICE_BANNER_KEY, value.toString())
|
||||
}
|
||||
setIpv6BannerAcknowledged(value)
|
||||
}
|
||||
|
||||
if (key === 'pgbouncer' && typeof value === 'string' && value.length > 0) {
|
||||
const updatedRefs = pgbouncerBannerAcknowledged.concat([value])
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(PGBOUNCER_BANNER_KEY, updatedRefs.join(','))
|
||||
}
|
||||
setPgbouncerBannerAcknowledged(updatedRefs)
|
||||
}
|
||||
|
||||
if (key === 'vercel' && typeof value === 'string' && value.length > 0) {
|
||||
const updatedRefs = pgbouncerBannerAcknowledged.concat([value])
|
||||
if (typeof window !== 'undefined') {
|
||||
window.localStorage.setItem(VERCEL_BANNER_KEY, updatedRefs.join(','))
|
||||
}
|
||||
setVercelBannerAcknowledged(updatedRefs)
|
||||
}
|
||||
setAcknowledged(value)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -42,6 +79,7 @@ export const AppBannerContextProvider = ({ children }: PropsWithChildren<{}>) =>
|
||||
}
|
||||
|
||||
export const useIsNoticeBannerShown = () => {
|
||||
const { acknowledged } = useAppBannerContext()
|
||||
return acknowledged
|
||||
const { ipv6BannerAcknowledged, pgbouncerBannerAcknowledged, vercelBannerAcknowledged } =
|
||||
useAppBannerContext()
|
||||
return ipv6BannerAcknowledged && pgbouncerBannerAcknowledged && vercelBannerAcknowledged
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
import { useSupabaseClient } from '@supabase/auth-helpers-react'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useParams } from 'common'
|
||||
|
||||
import { useAppBannerContext } from 'components/interfaces/App/AppBannerWrapperContext'
|
||||
import { useProfile } from 'lib/profile'
|
||||
import { useRouter } from 'next/router'
|
||||
import { Button, IconExternalLink } from 'ui'
|
||||
|
||||
// [Joshen] For this notice specifically, just FYI
|
||||
@@ -9,12 +13,74 @@ import { Button, IconExternalLink } from 'ui'
|
||||
|
||||
export const NoticeBanner = () => {
|
||||
const router = useRouter()
|
||||
const { isLoading } = useProfile()
|
||||
const { isLoading: isLoadingProfile } = useProfile()
|
||||
|
||||
const appBannerContext = useAppBannerContext()
|
||||
const { acknowledged, onUpdateAcknowledged } = appBannerContext
|
||||
const {
|
||||
ipv6BannerAcknowledged,
|
||||
pgbouncerBannerAcknowledged,
|
||||
vercelBannerAcknowledged,
|
||||
onUpdateAcknowledged,
|
||||
} = appBannerContext
|
||||
|
||||
if (isLoading || router.pathname.includes('sign-in') || acknowledged) return null
|
||||
const supabase = useSupabaseClient()
|
||||
const { ref: projectRef } = useParams()
|
||||
|
||||
// [Alaister]: using inline queries here since this is temporary
|
||||
const { data, isLoading: isLoadingIpv6Enabled } = useQuery(
|
||||
['projects', projectRef, 'pgbouncer-enabled'],
|
||||
async ({ signal }) => {
|
||||
let query = supabase.rpc('ipv6_active_status', { project_ref: projectRef }).returns<
|
||||
{
|
||||
pgbouncer_active: boolean
|
||||
vercel_active: boolean
|
||||
}[]
|
||||
>()
|
||||
|
||||
if (signal) {
|
||||
query = query.abortSignal(signal)
|
||||
}
|
||||
|
||||
const result = await query
|
||||
|
||||
if (result.data === null) {
|
||||
return {
|
||||
pgbouncer_active: false,
|
||||
vercel_active: false,
|
||||
}
|
||||
}
|
||||
|
||||
return result.data[0]
|
||||
},
|
||||
{ enabled: Boolean(projectRef) }
|
||||
)
|
||||
|
||||
const pgbouncerEnabled = data?.pgbouncer_active ?? false
|
||||
const vercelWithoutSupavisorEnabled = data?.vercel_active ?? false
|
||||
|
||||
// [Joshen] Pgbouncer list and vercel list are mutually exclusive
|
||||
const pgbouncerProjectAcknowledged = pgbouncerBannerAcknowledged.includes(projectRef ?? '')
|
||||
const vercelProjectAcknowledged = vercelBannerAcknowledged.includes(projectRef ?? '')
|
||||
const allAcknowledged =
|
||||
(!pgbouncerEnabled && !vercelWithoutSupavisorEnabled && ipv6BannerAcknowledged) ||
|
||||
(ipv6BannerAcknowledged && pgbouncerEnabled && pgbouncerProjectAcknowledged) ||
|
||||
(ipv6BannerAcknowledged && vercelWithoutSupavisorEnabled && vercelProjectAcknowledged)
|
||||
|
||||
if (
|
||||
isLoadingProfile ||
|
||||
isLoadingIpv6Enabled ||
|
||||
router.pathname.includes('sign-in') ||
|
||||
allAcknowledged
|
||||
) {
|
||||
return null
|
||||
}
|
||||
|
||||
const currentlyViewing =
|
||||
pgbouncerEnabled && !pgbouncerProjectAcknowledged
|
||||
? ('pgbouncer' as const)
|
||||
: vercelWithoutSupavisorEnabled && !vercelProjectAcknowledged
|
||||
? ('vercel' as const)
|
||||
: ('ipv6' as const)
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -22,19 +88,37 @@ export const NoticeBanner = () => {
|
||||
style={{ height: '44px' }}
|
||||
>
|
||||
<p className="text-sm">
|
||||
Prepare for the PgBouncer and IPv4 deprecations on 26th January 2024
|
||||
{currentlyViewing === 'pgbouncer' &&
|
||||
'Our logs on 26th Jan show that you have accessed PgBouncer. Please migrate now. You can ignore this warning if you have already migrated.'}
|
||||
{currentlyViewing === 'vercel' &&
|
||||
"To prepare for the IPv4 migration, please redeploy your Vercel application to detect the updated environment variables if it hasn't been deployed since 27th January."}
|
||||
{currentlyViewing === 'ipv6' &&
|
||||
'We are migrating our infrastructure from IPv4 to IPv6. Please migrate now. You can ignore this warning if you have already migrated.'}
|
||||
</p>
|
||||
<div className="flex items-center gap-x-1">
|
||||
<Button asChild type="link" iconRight={<IconExternalLink />}>
|
||||
<a
|
||||
href="https://github.com/orgs/supabase/discussions/17817"
|
||||
href={
|
||||
currentlyViewing === 'vercel'
|
||||
? 'https://supabase.com/partners/integrations/vercel'
|
||||
: 'https://github.com/orgs/supabase/discussions/17817'
|
||||
}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</Button>
|
||||
<Button type="text" className="opacity-75" onClick={() => onUpdateAcknowledged(true)}>
|
||||
<Button
|
||||
type="text"
|
||||
className="opacity-75"
|
||||
onClick={() =>
|
||||
onUpdateAcknowledged(
|
||||
currentlyViewing,
|
||||
currentlyViewing === 'ipv6' ? true : projectRef ?? ''
|
||||
)
|
||||
}
|
||||
>
|
||||
Dismiss
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -39,6 +39,8 @@ export const LOCAL_STORAGE_KEYS = {
|
||||
GRAPHIQL_RLS_BYPASS_WARNING: 'graphiql-rls-bypass-warning-dismissed',
|
||||
CLS_DIFF_WARNING: 'cls-diff-warning-dismissed',
|
||||
CLS_SELECT_STAR_WARNING: 'cls-select-star-warning-dismissed',
|
||||
PGBOUNCER_IPV6_DEPRECATION_WARNING: 'pgbouncer-ipv6-deprecation-warning-dismissed',
|
||||
VERCEL_IPV6_DEPRECATION_WARNING: 'vercel-ipv6-deprecation-warning-dismissed',
|
||||
PGBOUNCER_DEPRECATION_WARNING: 'pgbouncer-deprecation-warning-dismissed',
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
create
|
||||
or replace function ipv6_active_status (project_ref text) returns table (pgbouncer_active boolean, vercel_active boolean) as $$
|
||||
declare
|
||||
pgbouncer_active boolean;
|
||||
vercel_active boolean;
|
||||
begin
|
||||
select exists (
|
||||
select 1
|
||||
from active_pgbouncer_projects ap
|
||||
where ap.project_ref = $1
|
||||
) into pgbouncer_active;
|
||||
|
||||
select exists (
|
||||
select 1
|
||||
from vercel_project_connections_without_supavisor vp
|
||||
where vp.project_ref = $1
|
||||
) into vercel_active;
|
||||
|
||||
return query select pgbouncer_active, vercel_active;
|
||||
end;
|
||||
$$ language plpgsql security definer;
|
||||
Reference in new issue
Block a user