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
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ message = "connect ECONNREFUSED 1.2.3.4:5432"
message = "psql: error: connection to server at \"db.xxxxxxxxxxxxxxxxxxxx.supabase.co\" (1.2.3.4), port 5432 failed: Connection refused Is the server running on that host and accepting TCP/IP connections?"
---

If you're not able to connect to the Supabase database and see the error `connect ECONNREFUSED 1.2.3.4:5432` or `psql: error: connection to server at "db.xxxxxxxxxxxxxxxxxxxx.supabase.co" (1.2.3.4), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?`, this could be because there are banned IPs on your project caused by Fail2ban as it kicks in when attempting 2 wrong passwords in a row.
If you're not able to connect to the Supabase database and see one of the errors below, this could be because there are banned IPs on your project caused by Fail2ban as it kicks in when attempting 2 wrong passwords in a row.

- `connect ECONNREFUSED 1.2.3.4:5432`
- `psql: error: connection to server at "db.xxxxxxxxxxxxxxxxxxxx.supabase.co" (1.2.3.4), port 5432 failed: Connection refused
Is the server running on that host and accepting TCP/IP connections?`
- `Circuit breaker open: Unable to establish connection to upstream database`

These bans will clear after 30mins but you can unban the IPs using the Supabase CLI https://supabase.com/docs/guides/cli following the commands below.

Expand Down
1 change: 1 addition & 0 deletions apps/docs/public/humans.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Brendan Stephens
Brent Newson
Carel de Waal
Cameron Blackwood
Cameron Michie
Cemal Kılıç
Chandana Anumula
Charis Lam
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,9 @@ export const useIsColumnLevelPrivilegesEnabled = () => {

export const useUnifiedLogsPreview = () => {
const { flags, onUpdateFlag } = useFeaturePreviewContext()
const unifiedLogsEnabled = useFlag('unifiedLogs')

const isEnabled = flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS]
const isEnabled = unifiedLogsEnabled && flags[LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS]

const enable = () => onUpdateFlag(LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS, true)
const disable = () => onUpdateFlag(LOCAL_STORAGE_KEYS.UI_PREVIEW_UNIFIED_LOGS, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,17 @@ export const FeaturePreviewModal = () => {
)

const { flags, onUpdateFlag } = featurePreviewContext
const selectedFeature =
featurePreviews.find((preview) => preview.key === selectedFeatureKey) ?? featurePreviews[0]
const isSelectedFeatureEnabled = flags[selectedFeatureKey]
const allFeaturePreviews = (
IS_PLATFORM ? featurePreviews : featurePreviews.filter((x) => !x.isPlatformOnly)
).filter((x) => x.enabled)

const allFeaturePreviews = IS_PLATFORM
? featurePreviews
: featurePreviews.filter((x) => !x.isPlatformOnly)
const selectedFeature =
allFeaturePreviews.find((preview) => preview.key === selectedFeatureKey) ??
allFeaturePreviews[0]
const isSelectedFeatureEnabled = flags[selectedFeature?.key]

const toggleFeature = () => {
if (!selectedFeature) return
onUpdateFlag(selectedFeature.key, !isSelectedFeatureEnabled)
sendEvent({
action: isSelectedFeatureEnabled ? 'feature_preview_disabled' : 'feature_preview_enabled',
Expand All @@ -100,7 +102,7 @@ export const FeaturePreviewModal = () => {
<DialogSectionSeparator />

<DialogSection className="!p-0">
{featurePreviews.length > 0 ? (
{allFeaturePreviews.length > 0 ? (
<div className="flex">
<div>
<ScrollArea className="h-[550px] w-[280px] border-r">
Expand All @@ -113,7 +115,7 @@ export const FeaturePreviewModal = () => {
onClick={() => selectFeaturePreview(feature.key)}
className={cn(
'flex items-center justify-between p-4 border-b cursor-pointer bg transition',
selectedFeature.key === feature.key ? 'bg-surface-300' : 'bg-surface-100'
selectedFeature?.key === feature.key ? 'bg-surface-300' : 'bg-surface-100'
)}
>
<div className="flex items-center gap-x-3">
Expand Down Expand Up @@ -152,7 +154,7 @@ export const FeaturePreviewModal = () => {
</Button>
</div>
</div>
{FEATURE_PREVIEW_KEY_TO_CONTENT[selectedFeature.key]}
{FEATURE_PREVIEW_KEY_TO_CONTENT[selectedFeature?.key ?? '']}
</div>
</div>
) : (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { FeatureKey } from 'data/entitlements/entitlements-query'

export interface Enum {
label: string
value: string
Expand All @@ -22,7 +24,7 @@ export interface Provider {
descriptionOptional?: string
units?: string
isSecret?: boolean
isPaid?: boolean
entitlementKey?: FeatureKey
link?: string
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ResourceItem } from 'components/ui/Resource/ResourceItem'
import type { components } from 'data/api'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
import { useHasEntitlementAccess } from 'hooks/misc/useCheckEntitlements'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { BASE_PATH } from 'lib/constants'
import { Check } from 'lucide-react'
Expand Down Expand Up @@ -67,7 +68,7 @@ export const ProviderForm = ({ config, provider, isActive }: ProviderFormProps)
)
}

const isFreePlan = organization?.plan.id === 'free'
const hasEntitlementAccess = useHasEntitlementAccess()

const INITIAL_VALUES = (() => {
const initialValues: { [x: string]: string | boolean } = {}
Expand Down Expand Up @@ -201,18 +202,17 @@ export const ProviderForm = ({ config, provider, isActive }: ProviderFormProps)
)
}

const { entitlementKey } = provider.properties[x]
const hasAccess =
entitlementKey == null || hasEntitlementAccess(entitlementKey)
const properties = {
...provider.properties[x],
description:
provider.properties[x].isPaid && isFreePlan
? `${description} Only available on [Pro plan](/org/${organization.slug}/billing?panel=subscriptionPlan) and above.`
: description,
description: hasAccess
? description
: `${description} Only available on [Pro plan](/org/${organization?.slug}/billing?panel=subscriptionPlan) and above.`,
}
const isDisabledDueToPlan = properties.isPaid && isFreePlan
const shouldDisable =
properties.type === 'boolean'
? isDisabledDueToPlan && !values[x]
: isDisabledDueToPlan
properties.type === 'boolean' ? !hasAccess && !values[x] : !hasAccess

return (
<FormField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const PROVIDER_EMAIL = {
'Rejects the use of known or easy to guess passwords on sign up or password change. Powered by the HaveIBeenPwned.org Pwned Passwords API.',
type: 'boolean',
link: `${DOCS_URL}/guides/auth/password-security#password-strength-and-leaked-password-protection`,
isPaid: true,
entitlementKey: 'auth.password_hibp',
},
PASSWORD_MIN_LENGTH: {
title: 'Minimum password length',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { buildTableEditorUrl } from 'components/grid/SupabaseGrid.utils'
import { DiamondIcon, ExternalLink, Fingerprint, Hash, Key, Table2 } from 'lucide-react'
import { DiamondIcon, ExternalLink, Fingerprint, Hash, InfoIcon, Key, Table2 } from 'lucide-react'
import Link from 'next/link'
import { Handle, NodeProps } from 'reactflow'

import { Button, cn } from 'ui'
import { Button, cn, Tooltip, TooltipContent, TooltipTrigger } from 'ui'

// ReactFlow is scaling everything by the factor of 2
export const TABLE_NODE_WIDTH = 320
Expand All @@ -15,6 +14,7 @@ export type TableNodeData = {
name: string
ref?: string
isForeign: boolean
description: string
columns: {
id: string
isPrimary: boolean
Expand Down Expand Up @@ -67,19 +67,30 @@ export const TableNode = ({
<Table2 strokeWidth={1} size={12} className="text-light" />
{data.name}
</div>
{!placeholder && (
<Button asChild type="text" className="px-0 w-[16px] h-[16px] rounded">
<Link
href={buildTableEditorUrl({
projectRef: data.ref,
tableId: data.id,
schema: data.schema,
})}
>
<ExternalLink size={10} className="text-foreground-light" />
</Link>
</Button>
)}
<div className="flex items-center gap-2">
{data.description && (
<Tooltip>
<TooltipTrigger asChild className="cursor-default ">
<InfoIcon size={10} className="text-light" />
</TooltipTrigger>
<TooltipContent side="top">{data.description}</TooltipContent>
</Tooltip>
)}

{!placeholder && (
<Button asChild type="text" className="px-0 w-[16px] h-[16px] rounded">
<Link
href={buildTableEditorUrl({
projectRef: data.ref,
tableId: data.id,
schema: data.schema,
})}
>
<ExternalLink size={10} className="text-foreground-light" />
</Link>
</Button>
)}
</div>
</header>

{data.columns.map((column) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import dagre from '@dagrejs/dagre'
import type { PostgresSchema, PostgresTable } from '@supabase/postgres-meta'
import { uniqBy } from 'lodash'
import { Edge, Node, Position } from 'reactflow'

import 'reactflow/dist/style.css'

import { LOCAL_STORAGE_KEYS } from 'common'
import { tryParseJson } from 'lib/helpers'

import { TABLE_NODE_ROW_HEIGHT, TABLE_NODE_WIDTH, TableNodeData } from './SchemaTableNode'

const NODE_SEP = 25
Expand Down Expand Up @@ -41,6 +43,7 @@ export async function getGraphDataFromTables(
ref,
id: table.id,
name: table.name,
description: table.comment ?? '',
schema: table.schema,
isForeign: false,
columns,
Expand Down Expand Up @@ -78,6 +81,7 @@ export async function getGraphDataFromTables(
ref: ref!,
schema: rel.target_table_schema,
name: targetId,
description: '',
isForeign: true,
columns: [],
}
Expand Down
19 changes: 5 additions & 14 deletions apps/studio/components/interfaces/Home/ProjectList/EmptyStates.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { BoxPlus } from 'icons'
import { Plus } from 'lucide-react'
import Link from 'next/link'

import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { BASE_PATH } from 'lib/constants'
import {
Button,
Card,
Expand All @@ -16,21 +14,14 @@ import {
TableRow,
} from 'ui'
import { EmptyStatePresentational } from 'ui-patterns'

import { ShimmeringCard } from './ShimmeringCard'
import { HomeIcon } from '@/components/layouts/ProjectLayout/LayoutHeader/HomeIcon'

export const Header = () => {
return (
<div className="border-default border-b p-3">
<div className="flex items-center space-x-2">
<Link href="/projects">
<img
src={`${BASE_PATH}/img/supabase-logo.svg`}
alt="Supabase"
className="border-default rounded border p-1 hover:border-white"
style={{ height: 24 }}
/>
</Link>
</div>
<div className="flex items-center border-default border-b px-4 py-3.5">
<HomeIcon />
</div>
)
}
Expand Down
16 changes: 10 additions & 6 deletions apps/studio/components/interfaces/Home/ProjectUsage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ import {
} from 'data/analytics/project-log-stats-query'
import dayjs from 'dayjs'
import { useFillTimeseriesSorted } from 'hooks/analytics/useFillTimeseriesSorted'
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
import { useCheckEntitlements } from 'hooks/misc/useCheckEntitlements'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { Auth, Database, Realtime, Storage } from 'icons'
import sumBy from 'lodash/sumBy'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useState } from 'react'
import { useEffect, useState } from 'react'
import { Loading } from 'ui'

type ChartIntervalKey = ProjectLogStatsVariables['interval']
Expand All @@ -32,12 +32,18 @@ const ProjectUsage = () => {
'project_storage:all',
])

const { plan } = useCurrentOrgPlan()
const { getEntitlementMax } = useCheckEntitlements('log.retention_days')
const retentionDays = getEntitlementMax()

const DEFAULT_INTERVAL: ChartIntervalKey = plan?.id === 'free' ? '1hr' : '1day'
const DEFAULT_INTERVAL: ChartIntervalKey =
retentionDays !== undefined && retentionDays < 7 ? '1hr' : '1day'

const [interval, setInterval] = useState<ChartIntervalKey>(DEFAULT_INTERVAL)

useEffect(() => {
setInterval(retentionDays !== undefined && retentionDays < 7 ? '1hr' : '1day')
}, [retentionDays])

const { data, isPending: isLoading } = useProjectLogStatsQuery({ projectRef, interval })

const selectedInterval = CHART_INTERVALS.find((i) => i.key === interval) || CHART_INTERVALS[1]
Expand Down Expand Up @@ -94,8 +100,6 @@ const ProjectUsage = () => {
<ChartIntervalDropdown
value={interval || '1day'}
onChange={(interval) => setInterval(interval as ProjectLogStatsVariables['interval'])}
planId={plan?.id}
planName={plan?.name}
organizationSlug={organization?.slug}
dropdownAlign="start"
tooltipSide="right"
Expand Down
16 changes: 10 additions & 6 deletions apps/studio/components/interfaces/HomeNew/ProjectUsageSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import {
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
import dayjs from 'dayjs'
import { useFillTimeseriesSorted } from 'hooks/analytics/useFillTimeseriesSorted'
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
import { useCheckEntitlements } from 'hooks/misc/useCheckEntitlements'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useMemo, useState } from 'react'
import { useEffect, useMemo, useState } from 'react'
import { Card, CardContent, CardHeader, CardTitle, Loading } from 'ui'
import { Row } from 'ui-patterns'
import { LogsBarChart } from 'ui-patterns/LogsBarChart'
Expand Down Expand Up @@ -55,11 +55,17 @@ export const ProjectUsageSection = () => {
'project_auth:all',
'project_storage:all',
])
const { plan } = useCurrentOrgPlan()
const { getEntitlementMax } = useCheckEntitlements('log.retention_days')
const retentionDays = getEntitlementMax()

const DEFAULT_INTERVAL: ChartIntervalKey = plan?.id === 'free' ? '1hr' : '1day'
const DEFAULT_INTERVAL: ChartIntervalKey =
retentionDays !== undefined && retentionDays < 7 ? '1hr' : '1day'
const [interval, setInterval] = useState<ChartIntervalKey>(DEFAULT_INTERVAL)

useEffect(() => {
setInterval(retentionDays !== undefined && retentionDays < 7 ? '1hr' : '1day')
}, [retentionDays])

const selectedInterval = CHART_INTERVALS.find((i) => i.key === interval) || CHART_INTERVALS[1]

const { datetimeFormat } = useMemo(() => {
Expand Down Expand Up @@ -208,8 +214,6 @@ export const ProjectUsageSection = () => {
<ChartIntervalDropdown
value={interval}
onChange={(interval) => setInterval(interval as ChartIntervalKey)}
planId={plan?.id}
planName={plan?.name}
organizationSlug={organization?.slug}
dropdownAlign="end"
tooltipSide="left"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import ReportPadding from 'components/interfaces/Reports/ReportPadding'
import { ChartIntervalDropdown } from 'components/ui/Logs/ChartIntervalDropdown'
import { CHART_INTERVALS } from 'components/ui/Logs/logs.utils'
import dayjs from 'dayjs'
import { useCurrentOrgPlan } from 'hooks/misc/useCurrentOrgPlan'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { RefreshCw } from 'lucide-react'
Expand All @@ -25,7 +24,6 @@ export const ObservabilityOverview = () => {
const router = useRouter()
const { ref: projectRef } = useParams()
const { data: organization } = useSelectedOrganizationQuery()
const { plan } = useCurrentOrgPlan()
const queryClient = useQueryClient()

const { projectStorageAll: storageSupported } = useIsFeatureEnabled(['project_storage:all'])
Expand Down Expand Up @@ -156,8 +154,6 @@ export const ObservabilityOverview = () => {
<ChartIntervalDropdown
value={interval}
onChange={(interval) => setInterval(interval as ChartIntervalKey)}
planId={plan?.id}
planName={plan?.name}
organizationSlug={organization?.slug}
dropdownAlign="end"
tooltipSide="left"
Expand Down
Loading
Loading