diff --git a/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx
index 4a00780db53a5..90a1c353c4917 100644
--- a/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx
+++ b/apps/studio/components/interfaces/Auth/MfaAuthSettingsForm/MfaAuthSettingsForm.tsx
@@ -11,7 +11,7 @@ import NoPermission from 'components/ui/NoPermission'
import UpgradeToPro from 'components/ui/UpgradeToPro'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { IS_PLATFORM } from 'lib/constants'
import {
@@ -87,8 +87,14 @@ const MfaAuthSettingsForm = () => {
const [isUpdatingTotpForm, setIsUpdatingTotpForm] = useState(false)
const [isUpdatingPhoneForm, setIsUpdatingPhoneForm] = useState(false)
- const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue')
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
+ const { can: canReadConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.READ,
+ 'custom_config_gotrue'
+ )
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
const { data: organization } = useSelectedOrganizationQuery()
const isProPlanAndUp = organization?.plan?.id !== 'free'
diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx
index 259f5e7fd0198..57a9340330396 100644
--- a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx
+++ b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/PolicyDetailsV2.tsx
@@ -1,11 +1,11 @@
+import { PermissionAction } from '@supabase/shared-types/out/constants'
import { Check, ChevronsUpDown } from 'lucide-react'
import { useEffect, useState } from 'react'
import { UseFormReturn } from 'react-hook-form'
-import { PermissionAction } from '@supabase/shared-types/out/constants'
import { useDatabaseRolesQuery } from 'data/database-roles/database-roles-query'
import { useTablesQuery } from 'data/tables/tables-query'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import {
Button,
@@ -62,7 +62,10 @@ export const PolicyDetailsV2 = ({
}: PolicyDetailsV2Props) => {
const { data: project } = useSelectedProjectQuery()
const [open, setOpen] = useState(false)
- const canUpdatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables')
+ const { can: canUpdatePolicies } = useAsyncCheckProjectPermissions(
+ PermissionAction.TENANT_SQL_ADMIN_WRITE,
+ 'tables'
+ )
const { data: tables, isSuccess: isSuccessTables } = useTablesQuery({
projectRef: project?.ref,
diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx
index da7f29f264c94..ac3c2e99e3807 100644
--- a/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx
+++ b/apps/studio/components/interfaces/Auth/Policies/PolicyEditorPanel/index.tsx
@@ -15,7 +15,7 @@ import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { useDatabasePolicyUpdateMutation } from 'data/database-policies/database-policy-update-mutation'
import { databasePoliciesKeys } from 'data/database-policies/keys'
import { QueryResponseError, useExecuteSqlMutation } from 'data/sql/execute-sql-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import {
Button,
@@ -67,7 +67,10 @@ export const PolicyEditorPanel = memo(function ({
const queryClient = useQueryClient()
const { data: selectedProject } = useSelectedProjectQuery()
- const canUpdatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables')
+ const { can: canUpdatePolicies } = useAsyncCheckProjectPermissions(
+ PermissionAction.TENANT_SQL_ADMIN_WRITE,
+ 'tables'
+ )
// [Joshen] Hyrid form fields, just spit balling to get a decent POC out
const [using, setUsing] = useState('')
diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx
index 2bb0216f8004e..c58cc46fa172b 100644
--- a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx
+++ b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx
@@ -6,7 +6,7 @@ import { Edit, MoreVertical, Trash } from 'lucide-react'
import { DropdownMenuItemTooltip } from 'components/ui/DropdownMenuItemTooltip'
import Panel from 'components/ui/Panel'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
import {
@@ -38,7 +38,10 @@ const PolicyRow = ({
onSelectDeletePolicy = noop,
}: PolicyRowProps) => {
const aiSnap = useAiAssistantStateSnapshot()
- const canUpdatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'policies')
+ const { can: canUpdatePolicies } = useAsyncCheckProjectPermissions(
+ PermissionAction.TENANT_SQL_ADMIN_WRITE,
+ 'policies'
+ )
const { data: project } = useSelectedProjectQuery()
const { data: authConfig } = useAuthConfigQuery({ projectRef: project?.ref })
diff --git a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRowHeader.tsx b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRowHeader.tsx
index c668c505a3d33..6858191349ad2 100644
--- a/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRowHeader.tsx
+++ b/apps/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyTableRowHeader.tsx
@@ -5,7 +5,7 @@ import { Lock, Unlock } from 'lucide-react'
import { useParams } from 'common'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { EditorTablePageLink } from 'data/prefetchers/project.$ref.editor.$id'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
import { AiIconAnimation, Badge } from 'ui'
@@ -35,8 +35,14 @@ const PolicyTableRowHeader = ({
const { ref } = useParams()
const aiSnap = useAiAssistantStateSnapshot()
- const canCreatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'policies')
- const canToggleRLS = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables')
+ const { can: canCreatePolicies } = useAsyncCheckProjectPermissions(
+ PermissionAction.TENANT_SQL_ADMIN_WRITE,
+ 'policies'
+ )
+ const { can: canToggleRLS } = useAsyncCheckProjectPermissions(
+ PermissionAction.TENANT_SQL_ADMIN_WRITE,
+ 'tables'
+ )
const isRealtimeSchema = table.schema === 'realtime'
const isRealtimeMessagesTable = isRealtimeSchema && table.name === 'messages'
diff --git a/apps/studio/components/interfaces/Auth/ProtectionAuthSettingsForm/ProtectionAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/ProtectionAuthSettingsForm/ProtectionAuthSettingsForm.tsx
index 98370bad5384f..8f9dae46e2937 100644
--- a/apps/studio/components/interfaces/Auth/ProtectionAuthSettingsForm/ProtectionAuthSettingsForm.tsx
+++ b/apps/studio/components/interfaces/Auth/ProtectionAuthSettingsForm/ProtectionAuthSettingsForm.tsx
@@ -12,7 +12,7 @@ import { InlineLink } from 'components/ui/InlineLink'
import NoPermission from 'components/ui/NoPermission'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
@@ -69,18 +69,25 @@ const schema = object({
const ProtectionAuthSettingsForm = () => {
const { ref: projectRef } = useParams()
- const {
- data: authConfig,
- error: authConfigError,
- isLoading,
- isError,
- } = useAuthConfigQuery({ projectRef })
- const { mutate: updateAuthConfig, isLoading: isUpdatingConfig } = useAuthConfigUpdateMutation()
- const [isUpdatingProtection, setIsUpdatingProtection] = useState(false)
+ const { data: authConfig, error: authConfigError, isError } = useAuthConfigQuery({ projectRef })
+ const { mutate: updateAuthConfig, isLoading: isUpdatingConfig } = useAuthConfigUpdateMutation({
+ onError: (error) => {
+ toast.error(`Failed to update settings: ${error?.message}`)
+ },
+ onSuccess: () => {
+ toast.success('Successfully updated settings')
+ },
+ })
const [hidden, setHidden] = useState(true)
- const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue')
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
+ const { can: canReadConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.READ,
+ 'custom_config_gotrue'
+ )
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
const protectionForm = useForm({
resolver: yupResolver(schema),
@@ -102,7 +109,7 @@ const ProtectionAuthSettingsForm = () => {
})
useEffect(() => {
- if (authConfig && !isUpdatingProtection) {
+ if (authConfig && !isUpdatingConfig) {
protectionForm.reset({
DISABLE_SIGNUP: !authConfig.DISABLE_SIGNUP,
EXTERNAL_ANONYMOUS_USERS_ENABLED: authConfig.EXTERNAL_ANONYMOUS_USERS_ENABLED || false,
@@ -120,11 +127,9 @@ const ProtectionAuthSettingsForm = () => {
PASSWORD_HIBP_ENABLED: authConfig.PASSWORD_HIBP_ENABLED || false,
})
}
- }, [authConfig, isUpdatingProtection])
+ }, [authConfig, isUpdatingConfig])
const onSubmitProtection = (values: any) => {
- setIsUpdatingProtection(true)
-
const payload = { ...values }
payload.DISABLE_SIGNUP = !values.DISABLE_SIGNUP
// The backend uses empty string to represent no required characters in the password
@@ -132,19 +137,7 @@ const ProtectionAuthSettingsForm = () => {
payload.PASSWORD_REQUIRED_CHARACTERS = ''
}
- updateAuthConfig(
- { projectRef: projectRef!, config: payload },
- {
- onError: (error) => {
- toast.error(`Failed to update settings: ${error?.message}`)
- setIsUpdatingProtection(false)
- },
- onSuccess: () => {
- toast.success('Successfully updated settings')
- setIsUpdatingProtection(false)
- },
- }
- )
+ updateAuthConfig({ projectRef: projectRef!, config: payload })
}
if (isError) {
@@ -282,10 +275,8 @@ const ProtectionAuthSettingsForm = () => {
diff --git a/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx b/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx
index 30befae90b5f0..7b8ea69e7c1d3 100644
--- a/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx
+++ b/apps/studio/components/interfaces/Auth/RateLimits/RateLimits.tsx
@@ -13,7 +13,7 @@ import NoPermission from 'components/ui/NoPermission'
import { GenericSkeletonLoader } from 'components/ui/ShimmeringLoader'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import {
Button,
Card,
@@ -32,8 +32,14 @@ import { isSmtpEnabled } from '../SmtpForm/SmtpForm.utils'
const RateLimits = () => {
const { ref: projectRef } = useParams()
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
- const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue')
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
+ const { can: canReadConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.READ,
+ 'custom_config_gotrue'
+ )
const {
data: authConfig,
diff --git a/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrlList.tsx b/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrlList.tsx
index 304cac3af4def..fdcf729a56a9d 100644
--- a/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrlList.tsx
+++ b/apps/studio/components/interfaces/Auth/RedirectUrls/RedirectUrlList.tsx
@@ -3,7 +3,7 @@ import { Globe, Trash } from 'lucide-react'
import { ButtonTooltip } from 'components/ui/ButtonTooltip'
import { EmptyListState } from 'components/ui/States'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { Button, Checkbox_Shadcn_ } from 'ui'
import { ValueContainer } from './ValueContainer'
@@ -24,7 +24,10 @@ export const RedirectUrlList = ({
onSelectRemoveURLs,
onSelectClearSelection,
}: RedirectUrlListProps) => {
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
// [Joshen] One for next time: maybe shift this into a reusable logic since it
// seems like we can use this in multiple places for future
diff --git a/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx b/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx
index 5f9f9d892d621..dfb4b224731f5 100644
--- a/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx
+++ b/apps/studio/components/interfaces/Auth/SessionsAuthSettingsForm/SessionsAuthSettingsForm.tsx
@@ -11,7 +11,7 @@ import NoPermission from 'components/ui/NoPermission'
import UpgradeToPro from 'components/ui/UpgradeToPro'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { IS_PLATFORM } from 'lib/constants'
import {
@@ -68,8 +68,14 @@ const SessionsAuthSettingsForm = () => {
const [isUpdatingRefreshTokens, setIsUpdatingRefreshTokens] = useState(false)
const [isUpdatingUserSessions, setIsUpdatingUserSessions] = useState(false)
- const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue')
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
+ const { can: canReadConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.READ,
+ 'custom_config_gotrue'
+ )
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
const { data: organization } = useSelectedOrganizationQuery()
const isProPlanAndUp = organization?.plan?.id !== 'free'
diff --git a/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx b/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx
index e9e785b9c19e9..fd8a8a5b8d705 100644
--- a/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx
+++ b/apps/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx
@@ -1,16 +1,16 @@
+import { yupResolver } from '@hookform/resolvers/yup'
import { PermissionAction } from '@supabase/shared-types/out/constants'
+import { AlertCircle } from 'lucide-react'
import { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import { object, string } from 'yup'
-import { yupResolver } from '@hookform/resolvers/yup'
import { useParams } from 'common'
import { ScaffoldSection, ScaffoldSectionTitle } from 'components/layouts/Scaffold'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
-import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
@@ -24,7 +24,7 @@ import {
Form_Shadcn_,
Input_Shadcn_,
} from 'ui'
-import { AlertCircle } from 'lucide-react'
+import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
const schema = object({
SITE_URL: string().required('Must have a Site URL'),
@@ -36,7 +36,10 @@ const SiteUrl = () => {
const { mutate: updateAuthConfig } = useAuthConfigUpdateMutation()
const [isUpdatingSiteUrl, setIsUpdatingSiteUrl] = useState(false)
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
const siteUrlForm = useForm({
resolver: yupResolver(schema),
diff --git a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx
index e966cd43b4ec0..4acf7b5cd908c 100644
--- a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx
+++ b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx
@@ -1,18 +1,18 @@
import { yupResolver } from '@hookform/resolvers/yup'
import { PermissionAction } from '@supabase/shared-types/out/constants'
-import { useParams } from 'common'
+import { AlertTriangle, Eye, EyeOff } from 'lucide-react'
+import Link from 'next/link'
import { useEffect, useState } from 'react'
import { useForm } from 'react-hook-form'
import { toast } from 'sonner'
import * as yup from 'yup'
+import { useParams } from 'common'
import { ScaffoldContainer, ScaffoldSection } from 'components/layouts/Scaffold'
import NoPermission from 'components/ui/NoPermission'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
-import { AlertTriangle, Eye, EyeOff } from 'lucide-react'
-import Link from 'next/link'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import {
AlertDescription_Shadcn_,
AlertTitle_Shadcn_,
@@ -30,7 +30,7 @@ import {
WarningIcon,
} from 'ui'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
-import { urlRegex } from './../Auth.constants'
+import { urlRegex } from '../Auth.constants'
import { defaultDisabledSmtpFormValues } from './SmtpForm.constants'
import { generateFormValues, isSmtpEnabled } from './SmtpForm.utils'
@@ -53,8 +53,14 @@ const SmtpForm = () => {
const [enableSmtp, setEnableSmtp] = useState(false)
const [hidden, setHidden] = useState(true)
- const canReadConfig = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue')
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
+ const { can: canReadConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.READ,
+ 'custom_config_gotrue'
+ )
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
const smtpSchema = yup.object({
SMTP_ADMIN_EMAIL: yup.string().when('ENABLE_SMTP', {
diff --git a/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx b/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx
index fdf8cf905b67e..456bf706e53b7 100644
--- a/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx
+++ b/apps/studio/components/interfaces/Auth/ThirdPartyAuthForm/index.tsx
@@ -17,7 +17,7 @@ import {
ThirdPartyAuthIntegration,
useThirdPartyAuthIntegrationsQuery,
} from 'data/third-party-auth/integrations-query'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { cn } from 'ui'
import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { AddIntegrationDropdown } from './AddIntegrationDropdown'
@@ -49,7 +49,10 @@ export const ThirdPartyAuthForm = () => {
useState
()
const { mutateAsync: deleteIntegration } = useDeleteThirdPartyAuthIntegrationMutation()
- const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue')
+ const { can: canUpdateConfig } = useAsyncCheckProjectPermissions(
+ PermissionAction.UPDATE,
+ 'custom_config_gotrue'
+ )
if (isError) {
return (
diff --git a/apps/studio/components/interfaces/Auth/Users/AddUserDropdown.tsx b/apps/studio/components/interfaces/Auth/Users/AddUserDropdown.tsx
index d602f9fe963d2..4ef7f008d726e 100644
--- a/apps/studio/components/interfaces/Auth/Users/AddUserDropdown.tsx
+++ b/apps/studio/components/interfaces/Auth/Users/AddUserDropdown.tsx
@@ -2,7 +2,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
import { ChevronDown, Mail, UserPlus } from 'lucide-react'
import { useState } from 'react'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import {
Button,
DropdownMenu,
@@ -17,8 +17,14 @@ import CreateUserModal from './CreateUserModal'
import InviteUserModal from './InviteUserModal'
const AddUserDropdown = () => {
- const canInviteUsers = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'invite_user')
- const canCreateUsers = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'create_user')
+ const { can: canInviteUsers } = useAsyncCheckProjectPermissions(
+ PermissionAction.AUTH_EXECUTE,
+ 'invite_user'
+ )
+ const { can: canCreateUsers } = useAsyncCheckProjectPermissions(
+ PermissionAction.AUTH_EXECUTE,
+ 'create_user'
+ )
const [inviteVisible, setInviteVisible] = useState(false)
const [createVisible, setCreateVisible] = useState(false)
diff --git a/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx b/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx
index 63c4b904996e1..f2b630c369821 100644
--- a/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx
+++ b/apps/studio/components/interfaces/Auth/Users/CreateUserModal.tsx
@@ -7,7 +7,7 @@ import * as z from 'zod'
import { useParams } from 'common'
import { useUserCreateMutation } from 'data/auth/user-create-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import {
Button,
Checkbox_Shadcn_,
@@ -38,7 +38,10 @@ const CreateUserFormSchema = z.object({
const CreateUserModal = ({ visible, setVisible }: CreateUserModalProps) => {
const { ref: projectRef } = useParams()
- const canCreateUsers = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'create_user')
+ const { can: canCreateUsers } = useAsyncCheckProjectPermissions(
+ PermissionAction.AUTH_EXECUTE,
+ 'create_user'
+ )
const { mutate: createUser, isLoading: isCreatingUser } = useUserCreateMutation({
onSuccess(res) {
diff --git a/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx b/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx
index 59f7d064d3b17..d25657452053e 100644
--- a/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx
+++ b/apps/studio/components/interfaces/Auth/Users/InviteUserModal.tsx
@@ -4,7 +4,7 @@ import { toast } from 'sonner'
import { useParams } from 'common'
import { useUserInviteMutation } from 'data/auth/user-invite-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { Button, Form, Input, Modal } from 'ui'
export type InviteUserModalProps = {
@@ -22,7 +22,10 @@ const InviteUserModal = ({ visible, setVisible }: InviteUserModalProps) => {
setVisible(false)
},
})
- const canInviteUsers = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'invite_user')
+ const { can: canInviteUsers } = useAsyncCheckProjectPermissions(
+ PermissionAction.AUTH_EXECUTE,
+ 'invite_user'
+ )
const validate = (values: any) => {
const errors: any = {}
diff --git a/apps/studio/components/interfaces/Auth/Users/UserOverview.tsx b/apps/studio/components/interfaces/Auth/Users/UserOverview.tsx
index 0cb86332ff9eb..6a83f3c58fc1e 100644
--- a/apps/studio/components/interfaces/Auth/Users/UserOverview.tsx
+++ b/apps/studio/components/interfaces/Auth/Users/UserOverview.tsx
@@ -15,7 +15,7 @@ import { useUserSendMagicLinkMutation } from 'data/auth/user-send-magic-link-mut
import { useUserSendOTPMutation } from 'data/auth/user-send-otp-mutation'
import { useUserUpdateMutation } from 'data/auth/user-update-mutation'
import { User } from 'data/auth/users-infinite-query'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { BASE_PATH } from 'lib/constants'
import { timeout } from 'lib/helpers'
import { Button, cn, Separator } from 'ui'
@@ -59,12 +59,24 @@ export const UserOverview = ({ user, onDeleteSuccess }: UserOverviewProps) => {
}
)
- const canUpdateUser = useCheckPermissions(PermissionAction.AUTH_EXECUTE, '*')
- const canSendMagicLink = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'send_magic_link')
- const canSendRecovery = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'send_recovery')
- const canSendOtp = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'send_otp')
- const canRemoveUser = useCheckPermissions(PermissionAction.TENANT_SQL_DELETE, 'auth.users')
- const canRemoveMFAFactors = useCheckPermissions(
+ const { can: canUpdateUser } = useAsyncCheckProjectPermissions(PermissionAction.AUTH_EXECUTE, '*')
+ const { can: canSendMagicLink } = useAsyncCheckProjectPermissions(
+ PermissionAction.AUTH_EXECUTE,
+ 'send_magic_link'
+ )
+ const { can: canSendRecovery } = useAsyncCheckProjectPermissions(
+ PermissionAction.AUTH_EXECUTE,
+ 'send_recovery'
+ )
+ const { can: canSendOtp } = useAsyncCheckProjectPermissions(
+ PermissionAction.AUTH_EXECUTE,
+ 'send_otp'
+ )
+ const { can: canRemoveUser } = useAsyncCheckProjectPermissions(
+ PermissionAction.TENANT_SQL_DELETE,
+ 'auth.users'
+ )
+ const { can: canRemoveMFAFactors } = useAsyncCheckProjectPermissions(
PermissionAction.TENANT_SQL_DELETE,
'auth.mfa_factors'
)
diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx
index 5e693553554be..85d315f7ef780 100644
--- a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx
+++ b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx
@@ -5,7 +5,7 @@ import { toast } from 'sonner'
import { useParams } from 'common'
import Table from 'components/to-be-cleaned/Table'
import AlertError from 'components/ui/AlertError'
-import { useDeleteDestinationMutation } from 'data/replication/delete-destination-mutation'
+import { useDeleteDestinationPipelineMutation } from 'data/replication/delete-destination-pipeline-mutation'
import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query'
import { Pipeline } from 'data/replication/pipelines-query'
import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation'
@@ -69,7 +69,7 @@ export const DestinationRow = ({
: PipelineStatusRequestStatus.None
const { mutateAsync: stopPipeline } = useStopPipelineMutation()
- const { mutateAsync: deleteDestination } = useDeleteDestinationMutation({})
+ const { mutateAsync: deleteDestinationPipeline } = useDeleteDestinationPipelineMutation({})
const pipelineStatus = pipelineStatusData?.status
const statusName = getStatusName(pipelineStatus)
@@ -84,9 +84,11 @@ export const DestinationRow = ({
try {
await stopPipeline({ projectRef, pipelineId: pipeline.id })
- // deleting the destination also deletes the pipeline because of cascade delete
- // so we don't need to call deletePipeline explicitly
- await deleteDestination({ projectRef, destinationId: destinationId })
+ await deleteDestinationPipeline({
+ projectRef,
+ destinationId: destinationId,
+ pipelineId: pipeline.id,
+ })
} catch (error) {
toast.error(PIPELINE_ERROR_MESSAGES.DELETE_DESTINATION)
}
diff --git a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/create-key-dialog.tsx b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/create-key-dialog.tsx
index 639fbec988627..a3151640a4ce3 100644
--- a/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/create-key-dialog.tsx
+++ b/apps/studio/components/interfaces/JwtSecrets/jwt-secret-keys-table/create-key-dialog.tsx
@@ -1,5 +1,4 @@
import dayjs from 'dayjs'
-import relativeTime from 'dayjs/plugin/relativeTime'
import { useMemo, useState } from 'react'
import { toast } from 'sonner'
@@ -24,8 +23,6 @@ import {
Textarea,
} from 'ui'
-dayjs.extend(relativeTime)
-
const RSA_JWK_REQUIRED_PROPERTIES = ['kty', 'n', 'e', 'p', 'q', 'd', 'dq', 'dp', 'qi']
const EC_JWK_REQUIRED_PROPERTIES = ['kty', 'crv', 'x', 'y', 'd']
const ALLOWED_JWK_PROPERTIES = new Set([
diff --git a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx
index e9bd8a54ec0a2..f43ac43e38a85 100644
--- a/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx
+++ b/apps/studio/components/interfaces/TableGridEditor/GridHeaderActions.tsx
@@ -21,7 +21,7 @@ import {
} from 'data/table-editor/table-editor-types'
import { useTableUpdateMutation } from 'data/tables/table-update-mutation'
import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
-import { useCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
import { useIsFeatureEnabled } from 'hooks/misc/useIsFeatureEnabled'
import { useSelectedOrganizationQuery } from 'hooks/misc/useSelectedOrganization'
import { useSelectedProjectQuery } from 'hooks/misc/useSelectedProject'
@@ -107,9 +107,13 @@ const GridHeaderActions = ({ table }: GridHeaderActionsProps) => {
},
})
- const canSqlWriteTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables')
- const canSqlWriteColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns')
- const isReadOnly = !canSqlWriteTables && !canSqlWriteColumns
+ const { can: canSqlWriteTables, isLoading: isLoadingPermissions } =
+ useAsyncCheckProjectPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables')
+ const { can: canSqlWriteColumns } = useAsyncCheckProjectPermissions(
+ PermissionAction.TENANT_SQL_ADMIN_WRITE,
+ 'columns'
+ )
+ const isReadOnly = !isLoadingPermissions && !canSqlWriteTables && !canSqlWriteColumns
// This will change when we allow autogenerated API docs for schemas other than `public`
const doesHaveAutoGeneratedAPIDocs = table.schema === 'public'
diff --git a/apps/studio/components/layouts/Tabs/RecentItems.tsx b/apps/studio/components/layouts/Tabs/RecentItems.tsx
index bc684c59709ea..c7dd4276bc97b 100644
--- a/apps/studio/components/layouts/Tabs/RecentItems.tsx
+++ b/apps/studio/components/layouts/Tabs/RecentItems.tsx
@@ -1,5 +1,4 @@
import dayjs from 'dayjs'
-import relativeTime from 'dayjs/plugin/relativeTime'
import { AnimatePresence, motion } from 'framer-motion'
import Link from 'next/link'
@@ -9,8 +8,6 @@ import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants'
import { editorEntityTypes, useTabsStateSnapshot } from 'state/tabs'
import { useEditorType } from '../editors/EditorsLayout.hooks'
-dayjs.extend(relativeTime)
-
export function RecentItems() {
const { ref } = useParams()
const tabs = useTabsStateSnapshot()
diff --git a/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx b/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx
index 4072f6f2caab9..81cefd8d75a72 100644
--- a/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx
+++ b/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx
@@ -1,6 +1,7 @@
import { PermissionAction } from '@supabase/shared-types/out/constants'
import { JwtSecretUpdateStatus } from '@supabase/shared-types/out/events'
import { AlertCircle, Loader2 } from 'lucide-react'
+import Link from 'next/link'
import { useMemo } from 'react'
import { toast } from 'sonner'
@@ -9,8 +10,6 @@ import Panel from 'components/ui/Panel'
import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query'
import { useProjectSettingsV2Query } from 'data/config/project-settings-v2-query'
import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'
-import { useFlag } from 'hooks/ui/useFlag'
-import Link from 'next/link'
import { Input } from 'ui'
import { getLastUsedAPIKeys, useLastUsedAPIKeysLogQuery } from './DisplayApiSettings.utils'
import { ToggleLegacyApiKeysPanel } from './ToggleLegacyApiKeys'
@@ -26,8 +25,6 @@ export const DisplayApiSettings = ({
}) => {
const { ref: projectRef } = useParams()
- const newApiKeysInRollOut = useFlag('basicApiKeys')
-
const {
data: settings,
isError: isProjectSettingsError,
@@ -217,31 +214,20 @@ export const DisplayApiSettings = ({
))
)}
{showNotice ? (
- newApiKeysInRollOut ? (
-
- ) : (
-
- )
- ) : null}
+ href="https://github.com/orgs/supabase/discussions/29260"
+ buttonText="Read the announcement"
+ />
+ ) : (
+
+ )}
- {newApiKeysInRollOut && !showNotice && }
>
)
}
diff --git a/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.utils.ts b/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.utils.ts
index b8bd899e9bb4b..ae9fc2d3b8c96 100644
--- a/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.utils.ts
+++ b/apps/studio/components/ui/ProjectSettings/DisplayApiSettings.utils.ts
@@ -1,13 +1,8 @@
import dayjs from 'dayjs'
-import duration from 'dayjs/plugin/duration'
-import relativeTime from 'dayjs/plugin/relativeTime'
import { useRef } from 'react'
import useLogsQuery from 'hooks/analytics/useLogsQuery'
-dayjs.extend(duration)
-dayjs.extend(relativeTime)
-
export function useLastUsedAPIKeysLogQuery(projectRef: string) {
const now = useRef(new Date()).current
return useLogsQuery(projectRef, {
diff --git a/apps/studio/data/replication/delete-destination-mutation.ts b/apps/studio/data/replication/delete-destination-mutation.ts
deleted file mode 100644
index ce17893e5c47d..0000000000000
--- a/apps/studio/data/replication/delete-destination-mutation.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
-import { toast } from 'sonner'
-
-import type { ResponseError } from 'types'
-import { replicationKeys } from './keys'
-import { handleError, del } from 'data/fetchers'
-
-export type DeleteDestinationParams = {
- projectRef: string
- destinationId: number
-}
-
-async function deleteDestination(
- { projectRef, destinationId: destinationId }: DeleteDestinationParams,
- signal?: AbortSignal
-) {
- if (!projectRef) throw new Error('projectRef is required')
-
- const { data, error } = await del('/platform/replication/{ref}/destinations/{destination_id}', {
- params: { path: { ref: projectRef, destination_id: destinationId } },
- signal,
- })
- if (error) {
- handleError(error)
- }
-
- return data
-}
-
-type DeleteDestinationData = Awaited>
-
-export const useDeleteDestinationMutation = ({
- onSuccess,
- onError,
- ...options
-}: Omit<
- UseMutationOptions,
- 'mutationFn'
-> = {}) => {
- const queryClient = useQueryClient()
-
- return useMutation(
- (vars) => deleteDestination(vars),
- {
- async onSuccess(data, variables, context) {
- const { projectRef, destinationId } = variables
- await queryClient.invalidateQueries(replicationKeys.destinations(projectRef))
- await onSuccess?.(data, variables, context)
- },
- async onError(data, variables, context) {
- if (onError === undefined) {
- toast.error(`Failed to delete destination: ${data.message}`)
- } else {
- onError(data, variables, context)
- }
- },
- ...options,
- }
- )
-}
diff --git a/apps/studio/data/replication/delete-destination-pipeline-mutation.ts b/apps/studio/data/replication/delete-destination-pipeline-mutation.ts
new file mode 100644
index 0000000000000..2ccb247342311
--- /dev/null
+++ b/apps/studio/data/replication/delete-destination-pipeline-mutation.ts
@@ -0,0 +1,64 @@
+import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
+import { toast } from 'sonner'
+
+import type { ResponseError } from 'types'
+import { replicationKeys } from './keys'
+import { handleError, del } from 'data/fetchers'
+
+export type DeleteDestinationPipelineParams = {
+ projectRef: string
+ destinationId: number
+ pipelineId: number
+}
+
+async function deleteDestinationPipeline(
+ { projectRef, destinationId, pipelineId }: DeleteDestinationPipelineParams,
+ signal?: AbortSignal
+) {
+ if (!projectRef) throw new Error('projectRef is required')
+
+ const { data, error } = await del(
+ '/platform/replication/{ref}/destinations-pipelines/{destination_id}/{pipeline_id}',
+ {
+ params: { path: { ref: projectRef, destination_id: destinationId, pipeline_id: pipelineId } },
+ signal,
+ }
+ )
+ if (error) {
+ handleError(error)
+ }
+
+ return data
+}
+
+type DeleteDestinationPipelineData = Awaited>
+
+export const useDeleteDestinationPipelineMutation = ({
+ onSuccess,
+ onError,
+ ...options
+}: Omit<
+ UseMutationOptions,
+ 'mutationFn'
+> = {}) => {
+ const queryClient = useQueryClient()
+
+ return useMutation(
+ (vars) => deleteDestinationPipeline(vars),
+ {
+ async onSuccess(data, variables, context) {
+ const { projectRef } = variables
+ await queryClient.invalidateQueries(replicationKeys.destinations(projectRef))
+ await onSuccess?.(data, variables, context)
+ },
+ async onError(data, variables, context) {
+ if (onError === undefined) {
+ toast.error(`Failed to delete destination and pipeline: ${data.message}`)
+ } else {
+ onError(data, variables, context)
+ }
+ },
+ ...options,
+ }
+ )
+}
diff --git a/apps/studio/hooks/misc/useCheckPermissions.ts b/apps/studio/hooks/misc/useCheckPermissions.ts
index b77782fbda519..9ebf33696fb00 100644
--- a/apps/studio/hooks/misc/useCheckPermissions.ts
+++ b/apps/studio/hooks/misc/useCheckPermissions.ts
@@ -134,7 +134,10 @@ export function useGetProjectPermissions(
}
/**
- * @deprecated Use useAsyncCheckProjectPermissions instead
+ * @deprecated If checking for project permissions, use useAsyncCheckProjectPermissions instead so that we can always
+ * check for loading states to not prematurely show "no perms" UIs. We'll also need a separate async check for org perms too
+ *
+ * Use `import { useAsyncCheckProjectPermissions } from 'hooks/misc/useCheckPermissions'` instead
*/
export function useCheckPermissions(
action: string,
diff --git a/apps/studio/pages/_app.tsx b/apps/studio/pages/_app.tsx
index b062e6840535c..edeb124fc6f6a 100644
--- a/apps/studio/pages/_app.tsx
+++ b/apps/studio/pages/_app.tsx
@@ -24,6 +24,7 @@ import { Hydrate, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import dayjs from 'dayjs'
import customParseFormat from 'dayjs/plugin/customParseFormat'
+import duration from 'dayjs/plugin/duration'
import relativeTime from 'dayjs/plugin/relativeTime'
import timezone from 'dayjs/plugin/timezone'
import utc from 'dayjs/plugin/utc'
@@ -56,6 +57,7 @@ dayjs.extend(customParseFormat)
dayjs.extend(utc)
dayjs.extend(timezone)
dayjs.extend(relativeTime)
+dayjs.extend(duration)
loader.config({
// [Joshen] Attempt for offline support/bypass ISP issues is to store the assets required for monaco
diff --git a/apps/studio/pages/new/[slug].tsx b/apps/studio/pages/new/[slug].tsx
index 84301d2040aae..311c60f67c9ad 100644
--- a/apps/studio/pages/new/[slug].tsx
+++ b/apps/studio/pages/new/[slug].tsx
@@ -90,18 +90,7 @@ import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
import { InfoTooltip } from 'ui-patterns/info-tooltip'
-const sizes: DesiredInstanceSize[] = [
- 'micro',
- 'small',
- 'medium',
- 'large',
- 'xlarge',
- '2xlarge',
- '4xlarge',
- '8xlarge',
- '12xlarge',
- '16xlarge',
-]
+const sizes: DesiredInstanceSize[] = ['micro', 'small', 'medium']
const sizesWithNoCostConfirmationRequired: DesiredInstanceSize[] = ['micro', 'small']
@@ -783,7 +772,7 @@ const Wizard: NextPageWithLayout = () => {
CPU
${instanceSizeSpecs[option].priceHourly}/hour (~$
@@ -794,6 +783,15 @@ const Wizard: NextPageWithLayout = () => {
)
})}
+
+
+ Larger instance sizes available after creation
+
+
diff --git a/apps/studio/pages/project/[ref]/auth/providers.tsx b/apps/studio/pages/project/[ref]/auth/providers.tsx
index 57840283ae402..2bdc9ab95848b 100644
--- a/apps/studio/pages/project/[ref]/auth/providers.tsx
+++ b/apps/studio/pages/project/[ref]/auth/providers.tsx
@@ -1,21 +1,10 @@
-import { PermissionAction } from '@supabase/shared-types/out/constants'
-
import { AuthProvidersForm, BasicAuthSettingsForm } from 'components/interfaces/Auth'
import { AuthProvidersLayout } from 'components/layouts/AuthLayout/AuthProvidersLayout'
import DefaultLayout from 'components/layouts/DefaultLayout'
import { ScaffoldContainer } from 'components/layouts/Scaffold'
-import NoPermission from 'components/ui/NoPermission'
-import { useCheckPermissions, usePermissionsLoaded } from 'hooks/misc/useCheckPermissions'
import type { NextPageWithLayout } from 'types'
const ProvidersPage: NextPageWithLayout = () => {
- const canReadAuthSettings = useCheckPermissions(PermissionAction.READ, 'custom_config_gotrue')
- const isPermissionsLoaded = usePermissionsLoaded()
-
- if (isPermissionsLoaded && !canReadAuthSettings) {
- return
- }
-
return (
diff --git a/apps/studio/pages/project/[ref]/settings/api-keys/new.tsx b/apps/studio/pages/project/[ref]/settings/api-keys/new.tsx
index 9ceadc7cba2d4..99e475e2c9d52 100644
--- a/apps/studio/pages/project/[ref]/settings/api-keys/new.tsx
+++ b/apps/studio/pages/project/[ref]/settings/api-keys/new.tsx
@@ -1,5 +1,4 @@
import {
- ApiKeysComingSoonBanner,
ApiKeysCreateCallout,
ApiKeysFeedbackBanner,
} from 'components/interfaces/APIKeys/ApiKeysIllustrations'
@@ -14,11 +13,10 @@ import type { NextPageWithLayout } from 'types'
import { Separator } from 'ui'
const ApiKeysNewPage: NextPageWithLayout = () => {
- const { isInRollout, shouldDisableUI, canInitApiKeys } = useApiKeysVisibility()
+ const { shouldDisableUI, canInitApiKeys } = useApiKeysVisibility()
return (
<>
- {!isInRollout && }
{canInitApiKeys && }
diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts
index 0e606ba3d3233..b84082af171d7 100644
--- a/packages/api-types/types/platform.d.ts
+++ b/packages/api-types/types/platform.d.ts
@@ -3434,7 +3434,8 @@ export interface paths {
put?: never
/** Update a replication destination and pipeline. */
post: operations['ReplicationDestinationsPipelinesController_updateDestinationPipeline']
- delete?: never
+ /** Delete a replication destination and pipeline. */
+ delete: operations['ReplicationDestinationsPipelinesController_deleteDestinationPipeline']
options?: never
head?: never
patch?: never
@@ -4808,6 +4809,8 @@ export interface components {
}
| {
billing_email: string | null
+ /** @enum {string|null} */
+ billing_partner: 'fly' | 'aws' | 'vercel_marketplace' | null
id: number
is_owner: boolean
name: string
@@ -6582,6 +6585,8 @@ export interface components {
}
OrganizationResponse: {
billing_email: string | null
+ /** @enum {string|null} */
+ billing_partner: 'fly' | 'aws' | 'vercel_marketplace' | null
id: number
is_owner: boolean
name: string
@@ -6634,9 +6639,8 @@ export interface components {
}
OrganizationSlugResponse: {
billing_email: string | null
- billing_metadata: {
- [key: string]: unknown
- } | null
+ /** @enum {string|null} */
+ billing_partner: 'fly' | 'aws' | 'vercel_marketplace' | null
has_oriole_project: boolean
id: number
name: string
@@ -19126,6 +19130,44 @@ export interface operations {
}
}
}
+ ReplicationDestinationsPipelinesController_deleteDestinationPipeline: {
+ parameters: {
+ query?: never
+ header?: never
+ path: {
+ /** @description Destination id */
+ destination_id: number
+ /** @description Pipeline id */
+ pipeline_id: number
+ /** @description Project reference */
+ ref: string
+ }
+ cookie?: never
+ }
+ requestBody?: never
+ responses: {
+ /** @description Returned when the replication destination and pipeline are deleted. */
+ 201: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Returned when the API fails to delete the replication destination or pipeline. */
+ 500: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ }
+ }
ReplicationDestinationsController_getDestination: {
parameters: {
query?: never