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
@@ -1,10 +1,10 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Check } from 'lucide-react'
import { useTheme } from 'next-themes'
import { useQueryState } from 'nuqs'
import { useEffect, useState } from 'react'
import ReactMarkdown from 'react-markdown'
import { toast } from 'sonner'
import { useTheme } from 'next-themes'

import { useParams } from 'common'
import { Markdown } from 'components/interfaces/Markdown'
Expand Down Expand Up @@ -214,6 +214,10 @@ export const ProviderForm = ({ config, provider, isActive }: ProviderFormProps)
: description,
}
const isDisabledDueToPlan = properties.isPaid && isFreePlan
const shouldDisable =
properties.type === 'boolean'
? isDisabledDueToPlan && !values[x]
: isDisabledDueToPlan

return (
<FormField
Expand All @@ -222,9 +226,7 @@ export const ProviderForm = ({ config, provider, isActive }: ProviderFormProps)
setFieldValue={setFieldValue}
properties={properties}
formValues={values}
disabled={
shouldDisableField(x) || !canUpdateConfig || isDisabledDueToPlan
}
disabled={shouldDisableField(x) || !canUpdateConfig || shouldDisable}
/>
)
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ describe('Policies.utils - Policy Generation', () => {
expect(policy).toHaveProperty('schema', 'public')
expect(policy).toHaveProperty('action', 'PERMISSIVE')
expect(policy).toHaveProperty('roles')
expect(policy.roles).toContain('public')
expect(policy.roles).toContain('authenticated')
}
})

Expand Down Expand Up @@ -214,7 +214,7 @@ describe('Policies.utils - Policy Generation', () => {
expect(selectPolicy?.sql).toContain('CREATE POLICY')
expect(selectPolicy?.sql).toContain('public.posts')
expect(selectPolicy?.sql).toContain('AS PERMISSIVE FOR SELECT')
expect(selectPolicy?.sql).toContain('TO public')
expect(selectPolicy?.sql).toContain('TO authenticated')
expect(selectPolicy?.sql).toContain('USING')
expect(selectPolicy?.sql).toContain('auth.uid()')
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ const buildPoliciesForPath = (

return (['SELECT', 'INSERT', 'UPDATE', 'DELETE'] as const).map((command) => {
const name = `Enable ${command.toLowerCase()} access for users based on ${ident(targetCol)}`
const base = `CREATE POLICY "${name}" ON ${ident(table.schema)}.${ident(table.name)} AS PERMISSIVE FOR ${command} TO public`
const base = `CREATE POLICY "${name}" ON ${ident(table.schema)}.${ident(table.name)} AS PERMISSIVE FOR ${command} TO authenticated`

const sql =
command === 'INSERT'
Expand All @@ -338,7 +338,7 @@ const buildPoliciesForPath = (
definition,
check,
action: 'PERMISSIVE' as const,
roles: ['public'],
roles: ['authenticated'],
}
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,10 @@ export const ApiAccessToggle = ({
<p className="text-sm text-foreground flex items-center gap-1.5">
Data API Access
<InfoTooltip side="top" className="max-w-80">
This controls which operations the <code className="text-xs">anon</code> and{' '}
<code className="text-xs">authenticated</code> roles can perform on this table via
the Data API. Unselected privileges are revoked from these roles.
This controls which operations the <code className="text-code-inline">anon</code>{' '}
and <code className="text-code-inline whitespace-nowrap">authenticated</code> roles
can perform on this table via the Data API. Unselected privileges are revoked from
these roles.
</InfoTooltip>
</p>
<p className="text-sm text-foreground-lighter">
Expand Down
23 changes: 20 additions & 3 deletions apps/www/data/solutions/convex.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {
Code2,
Check,
InfoIcon,
TrendingUp,
Puzzle,
DollarSign,
} from 'lucide-react'
import RealtimeLogs from 'components/Products/Functions/RealtimeLogs'

Expand Down Expand Up @@ -90,9 +93,23 @@ const data = {
{
id: 'postgres-first',
icon: Database,
heading: 'A proven Postgres foundation',
heading: "It's just Postgres",
subheading:
"Real Postgres means real scale. Start small and grow to millions of users on the same database that powers the world's most demanding applications. Use any SQL client, ORM, or database tool. Connect with pgAdmin, Postico, DBeaver, or your favorite tool. Tap into the most popular Postgres extensions, including: PostGIS for geospatial, pgvector for AI, and more. No proprietary query language. No artificial limits. Just standard SQL that works everywhere.",
"Familiar SQL, familiar model, proven platform. No proprietary query language. No artificial limits. Just standard SQL that works everywhere. Postgres powers the world's most demanding applications, and you get the same battle-tested database.",
},
{
id: 'scale-to-millions',
icon: TrendingUp,
heading: 'Scale to millions',
subheading:
'Real Postgres means real scale. Start small and grow to millions of users on the same database. Postgres handles everything from startups to enterprise workloads with proven scalability. Your database grows with you, no migrations needed.',
},
{
id: 'powerful-ecosystem',
icon: Puzzle,
heading: 'A powerful ecosystem',
subheading:
'Connect with pgAdmin, Postico, DBeaver, or your favorite tool. Use any SQL client, ORM, or database tool. Tap into the most popular Postgres extensions, including: PostGIS for geospatial, pgvector for AI, and more. The entire Postgres ecosystem is at your fingertips.',
},
{
id: 'complete-stack',
Expand Down Expand Up @@ -124,7 +141,7 @@ const data = {
},
{
id: 'predictable-pricing',
icon: Lock,
icon: DollarSign,
heading: 'Fair, predictable pricing',
subheading:
"Supabase charges for what you use, not how your data syncs. No surprise bandwidth bills from real-time subscriptions. No per-function-call pricing that explodes with traffic. Postgres connection pooling means efficient resource usage at any scale. Know what you'll pay before you ship.",
Expand Down
5 changes: 4 additions & 1 deletion packages/ui-patterns/src/FilterBar/FilterBarContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ export type FilterBarContextValue = {
handleLogicalOperatorChange: (path: number[]) => void

// Options cache
propertyOptionsCache: Record<string, { options: (string | FilterOptionObject)[]; searchValue: string }>
propertyOptionsCache: Record<
string,
{ options: (string | FilterOptionObject)[]; searchValue: string }
>
loadingOptions: Record<string, boolean>
loadPropertyOptions: (property: FilterProperty, search: string) => void
optionsError: string | null
Expand Down
7 changes: 6 additions & 1 deletion packages/ui-patterns/src/FilterBar/menuItems.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { ActiveInput } from './hooks'
import { FilterBarAction, FilterGroup, FilterProperty } from './types'
import { findConditionByPath, isCustomOptionObject, isFilterOptionObject, isFilterOperatorObject } from './utils'
import {
findConditionByPath,
isCustomOptionObject,
isFilterOptionObject,
isFilterOperatorObject,
} from './utils'

export type MenuItem = {
value: string
Expand Down
5 changes: 4 additions & 1 deletion packages/ui-patterns/src/FilterBar/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ export type FilterBarAction = {
) => void | Promise<void>
}

export type SerializableFilterProperty = Pick<FilterProperty, 'label' | 'name' | 'type' | 'operators'> & {
export type SerializableFilterProperty = Pick<
FilterProperty,
'label' | 'name' | 'type' | 'operators'
> & {
options?: string[]
}

Expand Down
8 changes: 7 additions & 1 deletion packages/ui-patterns/src/FilterBar/useKeyboardNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,13 @@ export function useKeyboardNavigation({
}
}
},
[activeInput, activeFilters, findFirstConditionInGroup, findNextConditionFromGroup, setActiveInput]
[
activeInput,
activeFilters,
findFirstConditionInGroup,
findNextConditionFromGroup,
setActiveInput,
]
)

const handleKeyDown = useCallback(
Expand Down
8 changes: 6 additions & 2 deletions packages/ui-patterns/src/FilterBar/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ export function isFilterOptionObject(option: any): option is FilterOptionObject
}

export function isFilterOperatorObject(operator: any): operator is FilterOperatorObject {
return typeof operator === 'object' && operator !== null && 'value' in operator && 'label' in operator
return (
typeof operator === 'object' && operator !== null && 'value' in operator && 'label' in operator
)
}

export function isAsyncOptionsFunction(
Expand Down Expand Up @@ -132,7 +134,9 @@ export function addFilterToGroup(
): FilterGroup {
if (path.length === 0) {
const firstOperator = property.operators?.[0] || '='
const operatorValue = isFilterOperatorObject(firstOperator) ? firstOperator.value : firstOperator
const operatorValue = isFilterOperatorObject(firstOperator)
? firstOperator.value
: firstOperator

return {
...group,
Expand Down
Loading