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
6 changes: 6 additions & 0 deletions apps/docs/content/guides/platform/ssl-enforcement.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ Projects need to be at least on Postgres 13.3.0 to enable SSL enforcement. You c

SSL enforcement can be configured via the "Enforce SSL on incoming connections" setting under the SSL Configuration section in [Database Settings page](/dashboard/project/_/database/settings) of the dashboard.

<Admonition type="note">

Updating SSL enforcement requires a brief database reboot. This restarts only the database and involves a few minutes of downtime.

</Admonition>

## Manage SSL enforcement via the Management API

You can also manage SSL enforcement using the Management API:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,23 +245,29 @@ export const AccessTokenList = ({ searchString = '', onDeleteSuccess }: AccessTo
<TimestampInfo
utcTimestamp={x.last_used_at}
label={dayjs(x.last_used_at).fromNow()}
className="text-sm"
/>
) : (
'Never used'
<p className="text-foreground-light text-sm">Never used</p>
)}
</TableCell>
<TableCell className="min-w-28 text-foreground-light">
{x.expires_at ? (
dayjs(x.expires_at).isBefore(dayjs()) ? (
<TimestampInfo utcTimestamp={x.expires_at} label="Expired" />
<TimestampInfo
utcTimestamp={x.expires_at}
label="Expired"
className="text-sm"
/>
) : (
<TimestampInfo
utcTimestamp={x.expires_at}
label={dayjs(x.expires_at).format('DD MMM YYYY')}
className="text-sm"
/>
)
) : (
<p className="text-foreground-light">Never</p>
<p className="text-foreground-light text-sm">Never</p>
)}
</TableCell>
<TableCell>
Expand Down
50 changes: 0 additions & 50 deletions apps/studio/components/interfaces/App/AppBannerWrapperContext.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { BarChart2 } from 'lucide-react'
import { useMemo } from 'react'

import { REPORT_DATERANGE_HELPER_LABELS } from '@/components/interfaces/Reports/Reports.constants'
import { REPLICA_STATUS } from '@/components/interfaces/Settings/Infrastructure/InfrastructureConfiguration/InstanceConfiguration.constants'
import { ScaffoldContainer, ScaffoldSection } from '@/components/layouts/Scaffold'
import { useInfraMonitoringAttributesQuery } from '@/data/analytics/infra-monitoring-query'
import { useLoadBalancersQuery } from '@/data/read-replicas/load-balancers-query'
import { useReplicationLagQuery } from '@/data/read-replicas/replica-lag-query'
import { useReadReplicasQuery } from '@/data/read-replicas/replicas-query'
import { useReadReplicasStatusesQuery } from '@/data/read-replicas/replicas-status-query'
import { useReportDateRange } from '@/hooks/misc/useReportDateRange'
import { BASE_PATH } from '@/lib/constants'
import { useFlag, useParams } from 'common'
import { AWS_REGIONS } from 'shared-data'
import { Card, CardContent, CardHeader, CardTitle } from 'ui'
import {
Chart,
ChartCard,
ChartContent,
ChartEmptyState,
ChartHeader,
ChartLine,
ChartLoadingState,
ChartMetric,
GenericSkeletonLoader,
} from 'ui-patterns'
import { Input } from 'ui-patterns/DataInputs/Input'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'

export const ReadReplicaDetails = () => {
const { ref: projectRef, replicaId } = useParams()
const reportGranularityV2 = useFlag('reportGranularityV2')

const { data = [], isPending: isLoadingDatabases } = useReadReplicasQuery({ projectRef })
const replica = data.find((x) => x.identifier === replicaId)
const { identifier, connectionString, status: baseStatus, restUrl, region, size } = replica ?? {}
const regionLabel = Object.values(AWS_REGIONS).find((x) => x.code === region)?.displayName

const { data: statuses = [] } = useReadReplicasStatusesQuery({ projectRef })
const replicaStatus = statuses.find((x) => x.identifier === identifier)
const status = replicaStatus?.status ?? baseStatus

const { data: loadBalancers = [] } = useLoadBalancersQuery({ projectRef })
const loadBalancer = loadBalancers.find((x) =>
x.databases.some((x) => x.identifier === identifier)
)

const { data: lagDuration, isPending: isLoadingLag } = useReplicationLagQuery(
{
id: identifier ?? '',
projectRef,
connectionString,
},
{ enabled: status === REPLICA_STATUS.ACTIVE_HEALTHY }
)

const { selectedDateRange } = useReportDateRange(
REPORT_DATERANGE_HELPER_LABELS.LAST_60_MINUTES,
reportGranularityV2
)
// [Joshen] This is unused but intentional to scaffold the usage for now, refer to comment below
const { data: infraMonitoringData, isPending: isFetchingInfraMonitoring } =
useInfraMonitoringAttributesQuery(
{
projectRef,
attributes: ['physical_replication_lag_physical_replica_lag_seconds'],
databaseIdentifier: identifier,
startDate: selectedDateRange.period_start.date,
endDate: selectedDateRange.period_end.date,
interval: selectedDateRange.interval,
},
{ enabled: !!replica }
)

// [Joshen] Temporarily hardcoding the data as the query to retrieve replication lag doesn't seem to be working
// https://linear.app/supabase/issue/INDATA-325/investigate-infra-monitoring-for-physical-replication-lag-physical
const chartData = useMemo(() => {
return Array.from({ length: 46 }, (_, i) => {
const date = new Date()
date.setMinutes(date.getMinutes() - i * 5) // Each point 5 minutes apart

return {
timestamp: date.toISOString(),
replication_lag: Math.floor(Math.random() * 100),
}
}).reverse()
}, [])

return (
<>
<Chart className="mt-6" isLoading={isLoadingLag || isFetchingInfraMonitoring}>
<ChartCard className="rounded-none border-x-0">
<ChartHeader className="px-10">
<ChartMetric label="Replication lag" value={!!lagDuration ? `${lagDuration}s` : '-'} />
</ChartHeader>
<ChartContent
isEmpty={chartData.length === 0}
emptyState={
<ChartEmptyState
icon={<BarChart2 size={16} />}
title="No data to show"
description="It may take up to 24 hours for data to refresh"
/>
}
loadingState={<ChartLoadingState />}
>
<div className="h-56 px-5">
<ChartLine
data={chartData}
dataKey="replication_lag"
showGrid={true}
showYAxis={true}
YAxisProps={{
tickFormatter: (value) => `${value}s`,
width: 80,
}}
isFullHeight={true}
/>
</div>
</ChartContent>
</ChartCard>
</Chart>
<ScaffoldContainer>
<ScaffoldSection isFullWidth>
<Card>
<CardHeader>
<CardTitle>Replica Information</CardTitle>
</CardHeader>
{isLoadingDatabases ? (
<CardContent>
<GenericSkeletonLoader />
</CardContent>
) : (
<>
<CardContent>
<FormItemLayout
isReactForm={false}
layout="horizontal"
label="Load Balancer URL"
description="RESTful endpoint for querying and managing your databases through your load balancer"
>
<Input readOnly copy className="input-mono" value={loadBalancer?.endpoint} />
</FormItemLayout>
</CardContent>
<CardContent className="flex flex-col gap-y-4">
<FormItemLayout isReactForm={false} layout="horizontal" label="Replica URL">
<Input readOnly copy className="input-mono" value={restUrl} />
</FormItemLayout>
<FormItemLayout isReactForm={false} layout="horizontal" label="Region">
<Input
readOnly
className="input-mono"
value={regionLabel}
icon={
<img
alt="region icon"
className="w-5 rounded-sm"
src={`${BASE_PATH}/img/regions/${region ?? ''}.svg`}
/>
}
/>
</FormItemLayout>
<FormItemLayout
isReactForm={false}
layout="horizontal"
label="Compute Size"
description="Size of replica will be identical to the primary database"
>
<Input readOnly className="input-mono" value={size} />
</FormItemLayout>
</CardContent>
</>
)}
</Card>
</ScaffoldSection>
</ScaffoldContainer>
</>
)
}
Loading
Loading