diff --git a/studio/__mocks__/hooks.js b/studio/__mocks__/hooks.js index 0b0c07a3e57..e5fbfee3462 100644 --- a/studio/__mocks__/hooks.js +++ b/studio/__mocks__/hooks.js @@ -1,5 +1,4 @@ export const useFlag = jest.fn().mockReturnValue(true) -export const checkPermissions = jest.fn().mockReturnValue(true) export const useCheckPermissions = jest.fn().mockReturnValue(true) const { useStore: _useStore, StoreProvider: _StoreProvider } = jest.requireActual('hooks') diff --git a/studio/components/grid/components/header/Header.tsx b/studio/components/grid/components/header/Header.tsx index 86aad589319..db30a9924d1 100644 --- a/studio/components/grid/components/header/Header.tsx +++ b/studio/components/grid/components/header/Header.tsx @@ -13,7 +13,7 @@ import { } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore, useUrlState } from 'hooks' +import { useCheckPermissions, useStore, useUrlState } from 'hooks' import FilterDropdown from './filter' import SortPopover from './sort' import RefreshButton from './RefreshButton' @@ -106,7 +106,7 @@ const DefaultHeader = ({ const canAddNew = onAddRow !== undefined || onAddColumn !== undefined // [Joshen] Using this logic to block both column and row creation/update/delete - const canCreateColumns = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') + const canCreateColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') const [{ filter: filters, sort: sorts }, setParams] = useUrlState({ arrayKeys: ['sort', 'filter'], diff --git a/studio/components/interfaces/App/CommandMenuWrapper.tsx b/studio/components/interfaces/App/CommandMenuWrapper.tsx index c144d66e646..e94fe6797d1 100644 --- a/studio/components/interfaces/App/CommandMenuWrapper.tsx +++ b/studio/components/interfaces/App/CommandMenuWrapper.tsx @@ -8,7 +8,7 @@ import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectConte import { useProjectApiQuery } from 'data/config/project-api-query' import { SqlSnippet } from 'data/content/sql-snippets-query' import { useEntityDefinitionsQuery } from 'data/database/entity-definitions-query' -import { checkPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' import { uuidv4 } from 'lib/helpers' import { useProfile } from 'lib/profile' import { useSqlEditorStateSnapshot } from 'state/sql-editor' @@ -27,7 +27,7 @@ const CommandMenuWrapper = ({ children }: PropsWithChildren<{}>) => { const { profile } = useProfile() const { data: settings } = useProjectApiQuery({ projectRef: ref }) - const canCreateSQLSnippet = checkPermissions(PermissionAction.CREATE, 'user_content', { + const canCreateSQLSnippet = useCheckPermissions(PermissionAction.CREATE, 'user_content', { resource: { type: 'sql', owner_id: profile?.id }, subject: { id: profile?.id }, }) diff --git a/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx b/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx index cab31f81782..0851c3e397f 100644 --- a/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx +++ b/studio/components/interfaces/Auth/AuthProvidersForm/ProviderForm.tsx @@ -7,7 +7,7 @@ import { Alert, Button, Collapsible, Form, IconCheck, IconChevronUp, Input } fro import { useParams } from 'common' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import { useCustomDomainsQuery } from 'data/custom-domains/custom-domains-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { BASE_PATH } from 'lib/constants' import { ProviderCollapsibleClasses } from './AuthProvidersForm.constants' import { Provider } from './AuthProvidersForm.types' @@ -23,7 +23,7 @@ const ProviderForm = ({ provider }: ProviderFormProps) => { const { project: selectedProject } = useProjectContext() const { ref } = useParams() const doubleNegativeKeys = ['MAILER_AUTOCONFIRM', 'SMS_AUTOCONFIRM'] - const canUpdateConfig = checkPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') + const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') const { data: customDomainData } = useCustomDomainsQuery({ projectRef: ref }) diff --git a/studio/components/interfaces/Auth/AutoSchemaForm.tsx b/studio/components/interfaces/Auth/AutoSchemaForm.tsx index 614fe8ba38e..72722a74e46 100644 --- a/studio/components/interfaces/Auth/AutoSchemaForm.tsx +++ b/studio/components/interfaces/Auth/AutoSchemaForm.tsx @@ -4,7 +4,7 @@ import { boolean, number, object, string } from 'yup' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Button, Form, Input, IconEye, IconEyeOff, InputNumber, Toggle, Radio } from 'ui' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { FormActions, FormHeader, @@ -20,7 +20,7 @@ const AutoSchemaForm = observer(() => { const formId = 'auth-config-general-form' const [hidden, setHidden] = useState(true) - const canUpdateConfig = checkPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') + const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') const INITIAL_VALUES = { DISABLE_SIGNUP: !authConfig.config.DISABLE_SIGNUP, diff --git a/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx b/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx index 1dd3ab709bf..d1e9e700792 100644 --- a/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx +++ b/studio/components/interfaces/Auth/EmailTemplates/TemplateEditor.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react-lite' import { Input, Form } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { FormSchema } from 'types' import { FormActions, FormSection, FormSectionContent, FormSectionLabel } from 'components/ui/Forms' import CodeEditor from 'components/ui/CodeEditor' @@ -23,7 +23,7 @@ const TemplateEditor: FC = ({ template }) => { const formId = `auth-config-email-templates-${id}` const INITIAL_VALUES: { [x: string]: string } = {} - const canUpdateConfig = checkPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') + const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') useEffect(() => { if (isLoaded) { diff --git a/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx b/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx index 41518f2742e..aa9dcb9cc88 100644 --- a/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx +++ b/studio/components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow.tsx @@ -4,7 +4,7 @@ import { Button, Dropdown, IconEdit, IconTrash, IconMoreVertical } from 'ui' import type { PostgresPolicy } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import Panel from 'components/ui/Panel' interface Props { @@ -18,7 +18,7 @@ const PolicyRow: FC = ({ onSelectEditPolicy = () => {}, onSelectDeletePolicy = () => {}, }) => { - const canUpdatePolicies = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'policies') + const canUpdatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'policies') return ( = ({ }) => { const router = useRouter() const { ref } = router.query - const canToggleRLS = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') - const canCreatePolicies = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'policies') + const canToggleRLS = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const canCreatePolicies = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'policies') return (
diff --git a/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx b/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx index 178ad63bd38..19ed2369767 100644 --- a/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx +++ b/studio/components/interfaces/Auth/RedirectUrls/RedirectUrls.tsx @@ -5,7 +5,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, Form, Input, Modal } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { FormHeader } from 'components/ui/Forms' import { urlRegex } from '../Auth.constants' import RedirectUrlList from './RedirectUrlList' @@ -21,7 +21,7 @@ const RedirectUrls = () => { const [isDeleting, setIsDeleting] = useState(false) const [selectedUrlToDelete, setSelectedUrlToDelete] = useState() - const canUpdateConfig = checkPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') + const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') const newUrlSchema = object({ url: string().matches(urlRegex, 'URL is not valid').required(), diff --git a/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx b/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx index 1ad738c80be..da893178403 100644 --- a/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx +++ b/studio/components/interfaces/Auth/SiteUrl/SiteUrl.tsx @@ -12,7 +12,7 @@ import { FormSectionContent, FormSectionLabel, } from 'components/ui/Forms' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' const SiteUrl = observer(() => { const { authConfig, ui } = useStore() @@ -21,7 +21,7 @@ const SiteUrl = observer(() => { const formId = 'auth-config-general-form' const [hidden, setHidden] = useState(true) - const canUpdateConfig = checkPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') + const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') const INITIAL_VALUES = { DISABLE_SIGNUP: !authConfig.config.DISABLE_SIGNUP, diff --git a/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx b/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx index 8d658333d9b..26cba0e4739 100644 --- a/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx +++ b/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx @@ -12,7 +12,7 @@ import { FormSectionContent, FormSectionLabel, } from 'components/ui/Forms' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { urlRegex } from './../Auth.constants' import { defaultDisabledSmtpFormValues } from './SmtpForm.constants' import { generateFormValues, isSmtpEnabled } from './SmtpForm.utils' @@ -26,7 +26,7 @@ const SmtpForm = () => { const formId = 'auth-config-smtp-form' const initialValues = generateFormValues(authConfig.config) - const canUpdateConfig = checkPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') + const canUpdateConfig = useCheckPermissions(PermissionAction.UPDATE, 'custom_config_gotrue') useEffect(() => { if (isLoaded && isSmtpEnabled(config)) { diff --git a/studio/components/interfaces/Auth/Users/CreateUserModal.tsx b/studio/components/interfaces/Auth/Users/CreateUserModal.tsx index 94698aca740..527b09d4f16 100644 --- a/studio/components/interfaces/Auth/Users/CreateUserModal.tsx +++ b/studio/components/interfaces/Auth/Users/CreateUserModal.tsx @@ -5,7 +5,7 @@ import { Button, Checkbox, Form, IconLock, IconMail, Input, Loading, Modal } fro import { useUserCreateMutation } from 'data/auth/user-create-mutation' import { useProjectApiQuery } from 'data/config/project-api-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { PageContext } from 'pages/project/[ref]/auth/users' export type CreateUserModalProps = { @@ -21,7 +21,7 @@ const CreateUserModal = ({ visible, setVisible }: CreateUserModalProps) => { const { data, isLoading, isSuccess } = useProjectApiQuery({ projectRef }, { enabled: visible }) const handleToggle = () => setVisible(!visible) - const canCreateUsers = checkPermissions(PermissionAction.AUTH_EXECUTE, 'create_user') + const canCreateUsers = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'create_user') const validate = (values: any) => { const errors: any = {} diff --git a/studio/components/interfaces/Auth/Users/InviteUserModal.tsx b/studio/components/interfaces/Auth/Users/InviteUserModal.tsx index 2ec628eb448..f64c1723ccb 100644 --- a/studio/components/interfaces/Auth/Users/InviteUserModal.tsx +++ b/studio/components/interfaces/Auth/Users/InviteUserModal.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react-lite' import { useContext } from 'react' import { Button, Form, IconMail, Input, Modal } from 'ui' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { PageContext } from 'pages/project/[ref]/auth/users' @@ -18,7 +18,7 @@ const InviteUserModal = ({ visible, setVisible }: InviteUserModalProps) => { const PageState: any = useContext(PageContext) const handleToggle = () => setVisible(!visible) - const canInviteUsers = checkPermissions(PermissionAction.AUTH_EXECUTE, 'invite_user') + const canInviteUsers = useCheckPermissions(PermissionAction.AUTH_EXECUTE, 'invite_user') const validate = (values: any) => { const errors: any = {} diff --git a/studio/components/interfaces/Auth/Users/UsersList.tsx b/studio/components/interfaces/Auth/Users/UsersList.tsx index cd583dd76c3..652858cb5f1 100644 --- a/studio/components/interfaces/Auth/Users/UsersList.tsx +++ b/studio/components/interfaces/Auth/Users/UsersList.tsx @@ -6,15 +6,15 @@ import { PageContext } from 'pages/project/[ref]/auth/users' import Table from 'components/to-be-cleaned/Table' import UserListItem from './UsersListItem' import UsersPagination from './UsersPagination' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { PermissionAction } from '@supabase/shared-types/out/constants' const UsersList = ({}) => { const PageState: any = useContext(PageContext) // Check once on the top level, rather than checking for every row - const canRemoveUser = checkPermissions(PermissionAction.TENANT_SQL_DELETE, 'auth.users') - const canRemoveMFAFactors = checkPermissions( + const canRemoveUser = useCheckPermissions(PermissionAction.TENANT_SQL_DELETE, 'auth.users') + const canRemoveMFAFactors = useCheckPermissions( PermissionAction.TENANT_SQL_DELETE, 'auth.mfa_factors' ) diff --git a/studio/components/interfaces/BillingV2/Subscription/AddOns/ComputeInstanceSidePanel.tsx b/studio/components/interfaces/BillingV2/Subscription/AddOns/ComputeInstanceSidePanel.tsx index 955d6a82d8b..f6bdf2517a6 100644 --- a/studio/components/interfaces/BillingV2/Subscription/AddOns/ComputeInstanceSidePanel.tsx +++ b/studio/components/interfaces/BillingV2/Subscription/AddOns/ComputeInstanceSidePanel.tsx @@ -12,7 +12,7 @@ import { useProjectAddonRemoveMutation } from 'data/subscriptions/project-addon- import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon-update-mutation' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { BASE_PATH, PROJECT_STATUS } from 'lib/constants' import Telemetry from 'lib/telemetry' import { useSubscriptionPageStateSnapshot } from 'state/subscription-page' @@ -51,7 +51,10 @@ const ComputeInstanceSidePanel = () => { const [selectedCategory, setSelectedCategory] = useState<'micro' | 'optimized'>('micro') const [selectedOption, setSelectedOption] = useState('ci_micro') - const canUpdateCompute = checkPermissions(PermissionAction.BILLING_WRITE, 'stripe.subscriptions') + const canUpdateCompute = useCheckPermissions( + PermissionAction.BILLING_WRITE, + 'stripe.subscriptions' + ) const snap = useSubscriptionPageStateSnapshot() const visible = snap.panelKey === 'computeInstance' diff --git a/studio/components/interfaces/BillingV2/Subscription/AddOns/CustomDomainSidePanel.tsx b/studio/components/interfaces/BillingV2/Subscription/AddOns/CustomDomainSidePanel.tsx index 46c5be4a06f..3dc20f0aa3b 100644 --- a/studio/components/interfaces/BillingV2/Subscription/AddOns/CustomDomainSidePanel.tsx +++ b/studio/components/interfaces/BillingV2/Subscription/AddOns/CustomDomainSidePanel.tsx @@ -5,7 +5,7 @@ import { useProjectAddonRemoveMutation } from 'data/subscriptions/project-addon- import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon-update-mutation' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import Link from 'next/link' import { useEffect, useState } from 'react' import { useSubscriptionPageStateSnapshot } from 'state/subscription-page' @@ -21,7 +21,7 @@ const CustomDomainSidePanel = () => { const [isSubmitting, setIsSubmitting] = useState(false) const [selectedOption, setSelectedOption] = useState('cd_none') - const canUpdateCustomDomain = checkPermissions( + const canUpdateCustomDomain = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.subscriptions' ) diff --git a/studio/components/interfaces/BillingV2/Subscription/AddOns/PITRSidePanel.tsx b/studio/components/interfaces/BillingV2/Subscription/AddOns/PITRSidePanel.tsx index b944e79cd6b..3fe86f26c81 100644 --- a/studio/components/interfaces/BillingV2/Subscription/AddOns/PITRSidePanel.tsx +++ b/studio/components/interfaces/BillingV2/Subscription/AddOns/PITRSidePanel.tsx @@ -5,7 +5,7 @@ import { useProjectAddonRemoveMutation } from 'data/subscriptions/project-addon- import { useProjectAddonUpdateMutation } from 'data/subscriptions/project-addon-update-mutation' import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { BASE_PATH } from 'lib/constants' import Link from 'next/link' import { useEffect, useState } from 'react' @@ -44,7 +44,7 @@ const PITRSidePanel = () => { const [selectedCategory, setSelectedCategory] = useState<'on' | 'off'>('off') const [selectedOption, setSelectedOption] = useState('pitr_0') - const canUpdatePitr = checkPermissions(PermissionAction.BILLING_WRITE, 'stripe.subscriptions') + const canUpdatePitr = useCheckPermissions(PermissionAction.BILLING_WRITE, 'stripe.subscriptions') const snap = useSubscriptionPageStateSnapshot() const visible = snap.panelKey === 'pitr' diff --git a/studio/components/interfaces/BillingV2/Subscription/CostControl/SpendCapSidePanel.tsx b/studio/components/interfaces/BillingV2/Subscription/CostControl/SpendCapSidePanel.tsx index 3a8bb65b1e2..8e150368483 100644 --- a/studio/components/interfaces/BillingV2/Subscription/CostControl/SpendCapSidePanel.tsx +++ b/studio/components/interfaces/BillingV2/Subscription/CostControl/SpendCapSidePanel.tsx @@ -3,7 +3,7 @@ import { useParams, useTheme } from 'common' import Table from 'components/to-be-cleaned/Table' import { useProjectSubscriptionUpdateMutation } from 'data/subscriptions/project-subscription-update-mutation' import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { BASE_PATH, PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import Link from 'next/link' import { useEffect, useState } from 'react' @@ -44,7 +44,10 @@ const SpendCapSidePanel = () => { const [isSubmitting, setIsSubmitting] = useState(false) const [selectedOption, setSelectedOption] = useState<'on' | 'off'>() - const canUpdateSpendCap = checkPermissions(PermissionAction.BILLING_WRITE, 'stripe.subscriptions') + const canUpdateSpendCap = useCheckPermissions( + PermissionAction.BILLING_WRITE, + 'stripe.subscriptions' + ) const snap = useSubscriptionPageStateSnapshot() const visible = snap.panelKey === 'costControl' diff --git a/studio/components/interfaces/BillingV2/Subscription/Tier/PaymentMethodSelection.tsx b/studio/components/interfaces/BillingV2/Subscription/Tier/PaymentMethodSelection.tsx index f0716fe15f5..877d1cc9f94 100644 --- a/studio/components/interfaces/BillingV2/Subscription/Tier/PaymentMethodSelection.tsx +++ b/studio/components/interfaces/BillingV2/Subscription/Tier/PaymentMethodSelection.tsx @@ -5,7 +5,7 @@ import { useEffect, useMemo, useState } from 'react' import { useParams } from 'common' import { useOrganizationCustomerProfileQuery } from 'data/organizations/organization-customer-profile-query' import { useOrganizationPaymentMethodsQuery } from 'data/organizations/organization-payment-methods-query' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { BASE_PATH } from 'lib/constants' import { getURL } from 'lib/helpers' import { Button, IconAlertCircle, IconCreditCard, IconLoader, IconPlus, Listbox } from 'ui' @@ -37,7 +37,7 @@ const PaymentMethodSelection = ({ const { data: customerProfile, isSuccess: loadedCustomerProfile } = useOrganizationCustomerProfileQuery({ slug }) - const canUpdatePaymentMethods = checkPermissions( + const canUpdatePaymentMethods = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.payment_methods' ) diff --git a/studio/components/interfaces/BillingV2/Subscription/Tier/SubscriptionPaymentMethod.tsx b/studio/components/interfaces/BillingV2/Subscription/Tier/SubscriptionPaymentMethod.tsx index 5d976888e09..ae705f20c2a 100644 --- a/studio/components/interfaces/BillingV2/Subscription/Tier/SubscriptionPaymentMethod.tsx +++ b/studio/components/interfaces/BillingV2/Subscription/Tier/SubscriptionPaymentMethod.tsx @@ -9,7 +9,7 @@ import { updateSubscriptionTier, } from 'data/subscriptions/project-subscription-update-mutation' import { ProjectSubscriptionResponse } from 'data/subscriptions/project-subscription-v2-query' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { BASE_PATH } from 'lib/constants' import Link from 'next/link' import { Button, IconCreditCard, Modal } from 'ui' @@ -30,7 +30,7 @@ const SubscriptionPaymentMethod = ({ const selectedOrganization = useSelectedOrganization() const currentOrgSlug = selectedOrganization?.slug - const canUpdatePaymentMethod = checkPermissions( + const canUpdatePaymentMethod = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.subscriptions' ) diff --git a/studio/components/interfaces/BillingV2/Subscription/Tier/TierUpdateSidePanel.tsx b/studio/components/interfaces/BillingV2/Subscription/Tier/TierUpdateSidePanel.tsx index 4e70127394f..5c6d5675bec 100644 --- a/studio/components/interfaces/BillingV2/Subscription/Tier/TierUpdateSidePanel.tsx +++ b/studio/components/interfaces/BillingV2/Subscription/Tier/TierUpdateSidePanel.tsx @@ -11,7 +11,7 @@ import { useProjectAddonsQuery } from 'data/subscriptions/project-addons-query' import { useProjectPlansQuery } from 'data/subscriptions/project-plans-query' import { useProjectSubscriptionUpdateMutation } from 'data/subscriptions/project-subscription-update-mutation' import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import Telemetry from 'lib/telemetry' import { useRouter } from 'next/router' @@ -36,7 +36,7 @@ const TierUpdateSidePanel = () => { const [showDowngradeError, setShowDowngradeError] = useState(false) const [selectedTier, setSelectedTier] = useState<'tier_free' | 'tier_pro' | 'tier_team'>() - const canUpdateSubscription = checkPermissions( + const canUpdateSubscription = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.subscriptions' ) diff --git a/studio/components/interfaces/Database/Backups/BackupItem.tsx b/studio/components/interfaces/Database/Backups/BackupItem.tsx index 79ab41f9275..473f4b837cb 100644 --- a/studio/components/interfaces/Database/Backups/BackupItem.tsx +++ b/studio/components/interfaces/Database/Backups/BackupItem.tsx @@ -6,7 +6,7 @@ import { FC, useState } from 'react' import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal' import { setProjectStatus } from 'data/projects/projects-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { post } from 'lib/common/fetch' import { API_URL, PROJECT_STATUS } from 'lib/constants' import { Badge, Button, IconDownload } from 'ui' @@ -25,7 +25,7 @@ const BackupItem: FC = ({ projectRef, backup, index }) => { const [isDownloading, setDownloading] = useState(false) const [isRestoring, setRestoring] = useState(false) - const canTriggerScheduledBackups = checkPermissions( + const canTriggerScheduledBackups = useCheckPermissions( PermissionAction.INFRA_EXECUTE, 'queue_job.restore.prepare' ) diff --git a/studio/components/interfaces/Database/Backups/BackupsList.tsx b/studio/components/interfaces/Database/Backups/BackupsList.tsx index 8b402c75b84..fd379d00293 100644 --- a/studio/components/interfaces/Database/Backups/BackupsList.tsx +++ b/studio/components/interfaces/Database/Backups/BackupsList.tsx @@ -6,7 +6,7 @@ import InformationBox from 'components/ui/InformationBox' import Loading from 'components/ui/Loading' import Panel from 'components/ui/Panel' import UpgradeToPro from 'components/ui/UpgradeToPro' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { IconAlertCircle, IconClock } from 'ui' import BackupItem from './BackupItem' import BackupsEmpty from './BackupsEmpty' @@ -16,7 +16,7 @@ const BackupsList = () => { const { project: selectedProject } = useProjectContext() const { backups } = useStore() const projectRef = selectedProject?.ref || 'default' - const canTriggerScheduledBackups = checkPermissions( + const canTriggerScheduledBackups = useCheckPermissions( PermissionAction.INFRA_EXECUTE, 'queue_job.restore.prepare' ) diff --git a/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx b/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx index 88e43844ae3..9a1e23206e7 100644 --- a/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx +++ b/studio/components/interfaces/Database/Backups/PITR/PITRNotice.tsx @@ -2,7 +2,7 @@ import Link from 'next/link' import { Button, IconCalendar } from 'ui' import { FormPanel } from 'components/ui/Forms' import * as Tooltip from '@radix-ui/react-tooltip' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import { getPITRRetentionDuration } from './PITR.utils' import { PermissionAction } from '@supabase/shared-types/out/constants' @@ -13,7 +13,7 @@ const PITRNotice = ({}) => { const { data: addonsResponse } = useProjectAddonsQuery({ projectRef }) const retentionPeriod = getPITRRetentionDuration(addonsResponse?.selected_addons ?? []) - const canUpdateSubscription = checkPermissions( + const canUpdateSubscription = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.subscriptions' ) @@ -28,7 +28,10 @@ const PITRNotice = ({}) => { - + diff --git a/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx b/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx index 86983a22ba6..93fd29b5a17 100644 --- a/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx +++ b/studio/components/interfaces/Database/Backups/PITR/PITRStatus.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react-lite' import { Button, IconAlertCircle } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { Timezone } from './PITR.types' import { FormPanel } from 'components/ui/Forms' import TimezoneSelection from './TimezoneSelection' @@ -31,7 +31,7 @@ const PITRStatus: FC = ({ selectedTimezone, onUpdateTimezone, onSetConfig .tz(selectedTimezone?.utc[0]) .format('DD MMM YYYY, HH:mm:ss') - const canTriggerPhysicalBackup = checkPermissions( + const canTriggerPhysicalBackup = useCheckPermissions( PermissionAction.INFRA_EXECUTE, 'queue_job.walg.prepare_restore' ) diff --git a/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx b/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx index f7f3337f962..4115bd71ec5 100644 --- a/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx +++ b/studio/components/interfaces/Database/Extensions/ExtensionCard.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react-lite' import { Badge, IconLoader, Toggle } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal' import EnableExtensionModal from './EnableExtensionModal' @@ -18,7 +18,7 @@ const ExtensionCard: FC = ({ extension }) => { const [loading, setLoading] = useState(false) const [showConfirmEnableModal, setShowConfirmEnableModal] = useState(false) - const canUpdateExtensions = checkPermissions( + const canUpdateExtensions = useCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions' ) diff --git a/studio/components/interfaces/Database/Extensions/Extensions.tsx b/studio/components/interfaces/Database/Extensions/Extensions.tsx index 48164cf331f..c6d771b111d 100644 --- a/studio/components/interfaces/Database/Extensions/Extensions.tsx +++ b/studio/components/interfaces/Database/Extensions/Extensions.tsx @@ -4,7 +4,7 @@ import { partition, isNull } from 'lodash' import { Input, IconSearch, IconAlertCircle, Button, IconBookOpen } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import ExtensionCard from './ExtensionCard' import { HIDDEN_EXTENSIONS } from './Extensions.constants' @@ -31,7 +31,7 @@ const Extensions: FC = ({}) => { (ext: any) => !isNull(ext.installed_version) ) - const canUpdateExtensions = checkPermissions( + const canUpdateExtensions = useCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions' ) diff --git a/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx b/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx index 025e271ef86..84da9135f79 100644 --- a/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx +++ b/studio/components/interfaces/Database/Functions/FunctionsList/FunctionList.tsx @@ -7,7 +7,7 @@ import { FC } from 'react' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { Button, Dropdown, IconEdit3, IconFileText, IconMoreVertical, IconTrash } from 'ui' interface Props { @@ -34,7 +34,10 @@ const FunctionList: FC = ({ const isApiDocumentAvailable = schema == 'public' const projectRef = selectedProject?.ref - const canUpdateFunctions = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'functions') + const canUpdateFunctions = useCheckPermissions( + PermissionAction.TENANT_SQL_ADMIN_WRITE, + 'functions' + ) function onEdit(func: any) { editFunction(func) diff --git a/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx b/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx index b5571b31790..14432ade492 100644 --- a/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx +++ b/studio/components/interfaces/Database/Functions/FunctionsList/FunctionsList.tsx @@ -6,7 +6,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PostgresFunction } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import AlphaPreview from 'components/to-be-cleaned/AlphaPreview' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' import SchemaTable from './SchemaTable' @@ -32,7 +32,10 @@ const FunctionsList: FC = ({ includes(x.name?.toLowerCase(), filterString.toLowerCase()) ) const filteredFunctionSchemas = lodashMap(uniqBy(filteredFunctions, 'schema'), 'schema') - const canCreateFunctions = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'functions') + const canCreateFunctions = useCheckPermissions( + PermissionAction.TENANT_SQL_ADMIN_WRITE, + 'functions' + ) if (meta.functions.isLoading) { return ( diff --git a/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx b/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx index df502f33d71..b023527e7a0 100644 --- a/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx +++ b/studio/components/interfaces/Database/Hooks/HooksList/HookList.tsx @@ -7,7 +7,7 @@ import { useParams } from 'common/hooks' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import Table from 'components/to-be-cleaned/Table' import { useDatabaseHooks } from 'data/database-triggers/database-triggers-query' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { BASE_PATH } from 'lib/constants' import { Badge, Button, Dropdown, IconEdit3, IconMoreVertical, IconTrash } from 'ui' @@ -35,7 +35,7 @@ const HookList = ({ schema, filterString, editHook = noop, deleteHook = noop }: x.schema === schema && x.function_args.length >= 2 ) - const canUpdateWebhook = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') + const canUpdateWebhook = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') return ( <> diff --git a/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx b/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx index e7330f12d3e..ec66dbfa62c 100644 --- a/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx +++ b/studio/components/interfaces/Database/Hooks/HooksList/HooksList.tsx @@ -6,7 +6,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, Input, IconSearch, IconExternalLink } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import SchemaTable from './SchemaTable' import AlphaPreview from 'components/to-be-cleaned/AlphaPreview' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' @@ -44,7 +44,7 @@ const HooksList = ({ includes(x.name.toLowerCase(), filterString.toLowerCase()) ) const filteredHookSchemas = lodashMap(uniqBy(filteredHooks, 'schema'), 'schema') - const canCreateWebhooks = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') + const canCreateWebhooks = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') return ( <> diff --git a/studio/components/interfaces/Database/Publications/PublicationsList.tsx b/studio/components/interfaces/Database/Publications/PublicationsList.tsx index ce030e980f3..385235c3f96 100644 --- a/studio/components/interfaces/Database/Publications/PublicationsList.tsx +++ b/studio/components/interfaces/Database/Publications/PublicationsList.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react-lite' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Button, Input, Toggle, IconSearch, IconAlertCircle } from 'ui' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { confirmAlert } from 'components/to-be-cleaned/ModalsDeprecated/ConfirmModal' import Table from 'components/to-be-cleaned/Table' import NoSearchResults from 'components/ui/NoSearchResults' @@ -17,7 +17,7 @@ const PublicationsList: FC = ({ onSelectPublication = () => {} }) => { const { ui, meta } = useStore() const [filterString, setFilterString] = useState('') - const canUpdatePublications = checkPermissions( + const canUpdatePublications = useCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, 'publications' ) diff --git a/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx b/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx index 5c30d1f31cc..1a0c0ef867c 100644 --- a/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx +++ b/studio/components/interfaces/Database/Publications/PublicationsTableItem.tsx @@ -4,7 +4,7 @@ import { Badge, Toggle } from 'ui' import type { PostgresPublication, PostgresTable } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import Table from 'components/to-be-cleaned/Table' interface Props { @@ -21,7 +21,7 @@ const PublicationsTableItem: FC = ({ table, selectedPublication }) => { selectedPublication.tables?.find((x: any) => x.id == table.id) != undefined ) - const canUpdatePublications = checkPermissions( + const canUpdatePublications = useCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, 'publications' ) diff --git a/studio/components/interfaces/Database/Publications/PublicationsTables.tsx b/studio/components/interfaces/Database/Publications/PublicationsTables.tsx index 73d2f67bbd5..a24f038b8a9 100644 --- a/studio/components/interfaces/Database/Publications/PublicationsTables.tsx +++ b/studio/components/interfaces/Database/Publications/PublicationsTables.tsx @@ -4,7 +4,7 @@ import { Button, Input, IconChevronLeft, IconSearch, IconAlertCircle } from 'ui' import type { PostgresPublication } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import PublicationsTableItem from './PublicationsTableItem' import Table from 'components/to-be-cleaned/Table' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' @@ -19,7 +19,7 @@ const PublicationsTables: FC = ({ selectedPublication, onSelectBack }) => const { meta } = useStore() const [filterString, setFilterString] = useState('') - const canUpdatePublications = checkPermissions( + const canUpdatePublications = useCheckPermissions( PermissionAction.TENANT_SQL_ADMIN_WRITE, 'publications' ) diff --git a/studio/components/interfaces/Database/Roles/RolesList.tsx b/studio/components/interfaces/Database/Roles/RolesList.tsx index 09b4d1d24d2..85c2cd4ec62 100644 --- a/studio/components/interfaces/Database/Roles/RolesList.tsx +++ b/studio/components/interfaces/Database/Roles/RolesList.tsx @@ -6,7 +6,7 @@ import { PostgresRole } from '@supabase/postgres-meta' import { Button, Input, IconPlus, IconSearch, IconX, Badge } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import SparkBar from 'components/ui/SparkBar' import { FormHeader } from 'components/ui/Forms' import RoleRow from './RoleRow' @@ -24,7 +24,7 @@ const RolesList = ({}) => { const [isCreatingRole, setIsCreatingRole] = useState(false) const [selectedRoleToDelete, setSelectedRoleToDelete] = useState() - const canUpdateRoles = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'roles') + const canUpdateRoles = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'roles') useEffect(() => { const getMaxConnectionLimit = async () => { diff --git a/studio/components/interfaces/Database/Tables/ColumnList.tsx b/studio/components/interfaces/Database/Tables/ColumnList.tsx index 447e4a82750..03b9a1ff1c4 100644 --- a/studio/components/interfaces/Database/Tables/ColumnList.tsx +++ b/studio/components/interfaces/Database/Tables/ColumnList.tsx @@ -5,7 +5,7 @@ import { Input, Button, IconSearch, IconPlus, IconChevronLeft, IconEdit3, IconTr import type { PostgresTable } from '@supabase/postgres-meta' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import Table from 'components/to-be-cleaned/Table' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' @@ -32,7 +32,7 @@ const ColumnList: FC = ({ : selectedTable.columns?.filter((column: any) => column.name.includes(filterString))) ?? [] const isLocked = meta.excludedSchemas.includes(selectedTable.schema ?? '') - const canUpdateColumns = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') + const canUpdateColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') return ( <> diff --git a/studio/components/interfaces/Database/Tables/TableList.tsx b/studio/components/interfaces/Database/Tables/TableList.tsx index ecf88deec88..075c2873ecd 100644 --- a/studio/components/interfaces/Database/Tables/TableList.tsx +++ b/studio/components/interfaces/Database/Tables/TableList.tsx @@ -16,7 +16,7 @@ import { partition } from 'lodash' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import Table from 'components/to-be-cleaned/Table' import NoSearchResults from 'components/to-be-cleaned/NoSearchResults' import type { PostgresTable, PostgresSchema } from '@supabase/postgres-meta' @@ -42,7 +42,7 @@ const TableList: FC = ({ const { meta } = useStore() const { isLoading } = meta.tables const [filterString, setFilterString] = useState('') - const canUpdateTables = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const canUpdateTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const schemas: PostgresSchema[] = meta.schemas.list() const [protectedSchemas, openSchemas] = partition(schemas, (schema) => diff --git a/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx b/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx index 659ff35ba08..51212f9b822 100644 --- a/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx +++ b/studio/components/interfaces/Database/Triggers/TriggersList/TriggerList.tsx @@ -5,7 +5,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Badge, Button, Dropdown, IconMoreVertical, IconTrash, IconEdit3 } from 'ui' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import Table from 'components/to-be-cleaned/Table' interface Props { @@ -23,7 +23,7 @@ const TriggerList: FC = ({ filterString, schema, editTrigger, deleteTrigg ) const _triggers = filteredTriggers.filter((x: any) => x.schema == schema) - const canUpdateTriggers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') + const canUpdateTriggers = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') function onEdit(trigger: any) { editTrigger(trigger) diff --git a/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx b/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx index 75fa2be96dc..1f39f35c974 100644 --- a/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx +++ b/studio/components/interfaces/Database/Triggers/TriggersList/TriggersList.tsx @@ -5,7 +5,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, Input, IconSearch, IconLoader } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import SchemaTable from './SchemaTable' import AlphaPreview from 'components/to-be-cleaned/AlphaPreview' import ProductEmptyState from 'components/to-be-cleaned/ProductEmptyState' @@ -23,7 +23,7 @@ const TriggersList: FC = ({ includes(x.name.toLowerCase(), filterString.toLowerCase()) ) const filteredTriggerSchemas = lodashMap(uniqBy(filteredTriggers, 'schema'), 'schema') - const canCreateTriggers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') + const canCreateTriggers = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'triggers') if (meta.triggers.isLoading) { return ( diff --git a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx index b2693a6ee2b..84e100f16e9 100644 --- a/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/CreateWrapper.tsx @@ -6,7 +6,7 @@ import { observer } from 'mobx-react-lite' import { Button, Form, Input, IconArrowLeft, IconExternalLink, IconEdit, IconTrash } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { FormPanel, @@ -37,7 +37,7 @@ const CreateWrapper = () => { const [selectedTableToEdit, setSelectedTableToEdit] = useState() const [formErrors, setFormErrors] = useState<{ [k: string]: string }>({}) - const canCreateWrapper = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') + const canCreateWrapper = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') const wrapperMeta = WRAPPERS.find((wrapper) => wrapper.name === type) const initialValues = diff --git a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx index bb82a567cdf..8c26b54fe79 100644 --- a/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx +++ b/studio/components/interfaces/Database/Wrappers/EditWrapper.tsx @@ -16,7 +16,7 @@ import { import { PermissionAction } from '@supabase/shared-types/out/constants' import { VaultSecret } from 'types' -import { checkPermissions, useImmutableValue, useStore } from 'hooks' +import { useCheckPermissions, useImmutableValue, useStore } from 'hooks' import { useParams } from 'common/hooks' import { useFDWsQuery } from 'data/fdw/fdws-query' import { useFDWUpdateMutation } from 'data/fdw/fdw-update-mutation' @@ -65,7 +65,7 @@ const EditWrapper = () => { const [selectedTableToEdit, setSelectedTableToEdit] = useState() const [formErrors, setFormErrors] = useState<{ [k: string]: string }>({}) - const canUpdateWrapper = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') + const canUpdateWrapper = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') const initialValues = wrapperMeta !== undefined diff --git a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx index d22d91b727f..411c23e0ac3 100644 --- a/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrapperRow.tsx @@ -6,7 +6,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { Collapsible, IconChevronUp, Button, IconExternalLink, IconTrash, IconEdit } from 'ui' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import { WrapperMeta } from './Wrappers.types' import { FDW } from 'data/fdw/fdws-query' @@ -27,7 +27,7 @@ const WrapperRow: FC = ({ wrappers = [], wrapperMeta, isOpen, onOpen }) = const { project } = useProjectContext() const { mutateAsync: deleteFDW } = useFDWDeleteMutation() - const canManageWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') + const canManageWrappers = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') const onDeleteWrapper = (wrapper: any) => { confirmAlert({ diff --git a/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx b/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx index f21bf7bbe6b..7a74cdb78ec 100644 --- a/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrappersDisabledState.tsx @@ -5,7 +5,7 @@ import { observer } from 'mobx-react-lite' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { BASE_PATH } from 'lib/constants' import { useTheme } from 'common' @@ -19,7 +19,10 @@ const WrappersDisabledState = () => { const isNotAvailable = wrappersExtension === undefined || vaultExtension === undefined const [isEnabling, setIsEnabling] = useState(false) - const canToggleWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions') + const canToggleWrappers = useCheckPermissions( + PermissionAction.TENANT_SQL_ADMIN_WRITE, + 'extensions' + ) const onEnableWrappers = async () => { if (wrappersExtension === undefined || vaultExtension === undefined) return diff --git a/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx b/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx index 33b5cd693ed..5fdab17e076 100644 --- a/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx +++ b/studio/components/interfaces/Database/Wrappers/WrappersDropdown.tsx @@ -6,7 +6,7 @@ import { Button, Dropdown, IconPlus } from 'ui' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import { WRAPPERS } from './Wrappers.constants' @@ -17,7 +17,7 @@ interface Props { const WrapperDropdown: FC = ({ buttonText = 'Add wrapper', align = 'end' }) => { const { ref } = useParams() - const canManageWrappers = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') + const canManageWrappers = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'wrappers') if (!canManageWrappers) { return ( diff --git a/studio/components/interfaces/Docs/LangSelector.tsx b/studio/components/interfaces/Docs/LangSelector.tsx index a0e05272874..e9bf2158ef0 100644 --- a/studio/components/interfaces/Docs/LangSelector.tsx +++ b/studio/components/interfaces/Docs/LangSelector.tsx @@ -1,6 +1,6 @@ import { FC } from 'react' import { Button, Dropdown, IconKey } from 'ui' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { PermissionAction } from '@supabase/shared-types/out/constants' import { showApiKey } from 'components/interfaces/Docs/Docs.types' @@ -24,7 +24,7 @@ const LangSelector: FC = ({ apiKey, autoApiService, }) => { - const canReadServiceKey = checkPermissions( + const canReadServiceKey = useCheckPermissions( PermissionAction.READ, 'service_api_keys.service_role_key' ) diff --git a/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx b/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx index a3d970c4fa1..60a433db257 100644 --- a/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx +++ b/studio/components/interfaces/Functions/EdgeFunctionDetails/EdgeFunctionDetails.tsx @@ -17,7 +17,7 @@ import { IconExternalLink, } from 'ui' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import Panel from 'components/ui/Panel' import CommandRender from '../CommandRender' @@ -51,7 +51,7 @@ const EdgeFunctionDetails: FC = () => { const { mutateAsync: deleteEdgeFunction, isLoading: isDeleting } = useEdgeFunctionDeleteMutation() const formId = 'edge-function-update-form' - const canUpdateEdgeFunction = checkPermissions(PermissionAction.FUNCTIONS_WRITE, '*') + const canUpdateEdgeFunction = useCheckPermissions(PermissionAction.FUNCTIONS_WRITE, '*') // Get the API service const apiService = settings?.autoApiService diff --git a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx index 42b39dbac4b..815ac8cec05 100644 --- a/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx +++ b/studio/components/interfaces/Home/NewProjectPanel/APIKeys.tsx @@ -6,7 +6,7 @@ import { IconAlertCircle, IconLoader, Input } from 'ui' import { useProjectApiQuery } from 'data/config/project-api-query' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import Snippets from 'components/to-be-cleaned/Docs/Snippets' import Panel from 'components/ui/Panel' @@ -36,7 +36,7 @@ const APIKeys = () => { } = useJwtSecretUpdatingStatusQuery({ projectRef }) const jwtSecretUpdateStatus = data?.jwtSecretUpdateStatus - const canReadAPIKeys = checkPermissions(PermissionAction.READ, 'service_api_keys') + const canReadAPIKeys = useCheckPermissions(PermissionAction.READ, 'service_api_keys') // Get the API service const apiService = settings?.autoApiService diff --git a/studio/components/interfaces/Organization/BillingSettings/BillingAddress/BillingAddress.tsx b/studio/components/interfaces/Organization/BillingSettings/BillingAddress/BillingAddress.tsx index 9a95fc2ee29..510117e4e2c 100644 --- a/studio/components/interfaces/Organization/BillingSettings/BillingAddress/BillingAddress.tsx +++ b/studio/components/interfaces/Organization/BillingSettings/BillingAddress/BillingAddress.tsx @@ -5,7 +5,7 @@ import { Button, Form, Input, Listbox } from 'ui' import NoPermission from 'components/ui/NoPermission' import Panel from 'components/ui/Panel' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { COUNTRIES } from './BillingAddress.constants' @@ -22,8 +22,11 @@ const BillingAddress = ({ loading, address, onAddressUpdated }: BillingAddressPr const orgSlug = selectedOrganization?.slug ?? '' const { city, country, line1, line2, postal_code, state } = address - const canReadBillingAddress = checkPermissions(PermissionAction.BILLING_READ, 'stripe.customer') - const canUpdateBillingAddress = checkPermissions( + const canReadBillingAddress = useCheckPermissions( + PermissionAction.BILLING_READ, + 'stripe.customer' + ) + const canUpdateBillingAddress = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.customer' ) diff --git a/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx b/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx index 7fa6c9c14b0..42ecf17386e 100644 --- a/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx +++ b/studio/components/interfaces/Organization/BillingSettings/BillingEmail.tsx @@ -5,7 +5,7 @@ import { useEffect } from 'react' import { useParams } from 'common/hooks' import { FormActions, FormPanel, FormSection, FormSectionContent } from 'components/ui/Forms' import { invalidateOrganizationsQuery } from 'data/organizations/organizations-query' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { Form, Input } from 'ui' @@ -22,8 +22,8 @@ const BillingEmail = () => { billing_email: billing_email ?? '', } - const canUpdateOrganization = checkPermissions(PermissionAction.UPDATE, 'organizations') - const canReadBillingEmail = checkPermissions(PermissionAction.READ, 'organizations') + const canUpdateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') + const canReadBillingEmail = useCheckPermissions(PermissionAction.READ, 'organizations') const onUpdateOrganization = async (values: any, { setSubmitting, resetForm }: any) => { if (!canUpdateOrganization) { diff --git a/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx b/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx index ca01db97c3f..fb96137ff51 100644 --- a/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx +++ b/studio/components/interfaces/Organization/BillingSettings/BillingSettings.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from 'react' import { useParams } from 'common/hooks' import { useProjectsQuery } from 'data/projects/projects-query' -import { checkPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' import { PermissionAction } from '@supabase/shared-types/out/constants' import { get } from 'lib/common/fetch' import { API_URL } from 'lib/constants' @@ -42,7 +42,7 @@ const BillingSettings = () => { : customerBalance const orgBillingMigrationEnabled = useFlag('orgBillingMigration') - const canMigrateOrganization = checkPermissions(PermissionAction.UPDATE, 'organizations') + const canMigrateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') const selectedOrganization = useSelectedOrganization() const { subscription_id } = selectedOrganization ?? {} diff --git a/studio/components/interfaces/Organization/BillingSettings/PaymentMethods.tsx b/studio/components/interfaces/Organization/BillingSettings/PaymentMethods.tsx index d74754969c9..d0aeeeb3416 100644 --- a/studio/components/interfaces/Organization/BillingSettings/PaymentMethods.tsx +++ b/studio/components/interfaces/Organization/BillingSettings/PaymentMethods.tsx @@ -17,7 +17,7 @@ import { import { AddNewPaymentMethodModal } from 'components/interfaces/Billing' import NoPermission from 'components/ui/NoPermission' import Panel from 'components/ui/Panel' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { delete_, patch } from 'lib/common/fetch' import { API_URL, BASE_PATH } from 'lib/constants' import { getURL } from 'lib/helpers' @@ -48,11 +48,11 @@ const PaymentMethods = ({ const [showAddPaymentMethodModal, setShowAddPaymentMethodModal] = useState(false) const [isUpdatingPaymentMethod, setIsUpdatingPaymentMethod] = useState(false) - const canReadPaymentMethods = checkPermissions( + const canReadPaymentMethods = useCheckPermissions( PermissionAction.BILLING_READ, 'stripe.payment_methods' ) - const canUpdatePaymentMethods = checkPermissions( + const canUpdatePaymentMethods = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.payment_methods' ) diff --git a/studio/components/interfaces/Organization/BillingSettings/TaxID/TaxID.tsx b/studio/components/interfaces/Organization/BillingSettings/TaxID/TaxID.tsx index 0a7dc257ebd..3566af3da31 100644 --- a/studio/components/interfaces/Organization/BillingSettings/TaxID/TaxID.tsx +++ b/studio/components/interfaces/Organization/BillingSettings/TaxID/TaxID.tsx @@ -5,7 +5,7 @@ import { Button, IconPlus, IconX, Input, Listbox } from 'ui' import NoPermission from 'components/ui/NoPermission' import Panel from 'components/ui/Panel' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { delete_, post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { uuidv4 } from 'lib/helpers' @@ -51,8 +51,8 @@ const TaxID = ({ loading, taxIds, onTaxIdsUpdated }: TaxIDProps) => { }, [taxIds]) const hasChanges = !isEqual(taxIdValues, formattedTaxIds) - const canReadTaxIds = checkPermissions(PermissionAction.BILLING_READ, 'stripe.tax_ids') - const canUpdateTaxIds = checkPermissions(PermissionAction.BILLING_WRITE, 'stripe.tax_ids') + const canReadTaxIds = useCheckPermissions(PermissionAction.BILLING_READ, 'stripe.tax_ids') + const canUpdateTaxIds = useCheckPermissions(PermissionAction.BILLING_WRITE, 'stripe.tax_ids') const onUpdateTaxId = (id: string, key: string, value: string) => { const updatedTaxIds = taxIdValues.map((taxId: any) => { diff --git a/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx b/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx index 0f101f4871f..55f3c6ed20f 100644 --- a/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx +++ b/studio/components/interfaces/Organization/GeneralSettings/DeleteOrganizationButton.tsx @@ -5,7 +5,7 @@ import { useState } from 'react' import { Button, Form, Input, Modal } from 'ui' import { invalidateOrganizationsQuery } from 'data/organizations/organizations-query' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { delete_ } from 'lib/common/fetch' import { API_URL } from 'lib/constants' @@ -20,7 +20,7 @@ const DeleteOrganizationButton = () => { const [isOpen, setIsOpen] = useState(false) const [value, setValue] = useState('') - const canDeleteOrganization = checkPermissions(PermissionAction.UPDATE, 'organizations') + const canDeleteOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') const onValidate = (values: any) => { const errors: any = {} diff --git a/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx b/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx index 6cc42c37052..67c39a663b8 100644 --- a/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx +++ b/studio/components/interfaces/Organization/GeneralSettings/GeneralSettings.tsx @@ -15,7 +15,7 @@ import { FormSectionLabel, } from 'components/ui/Forms' import { invalidateOrganizationsQuery } from 'data/organizations/organizations-query' -import { checkPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import OrganizationDeletePanel from './OrganizationDeletePanel' @@ -35,8 +35,8 @@ const GeneralSettings = () => { const showCMDK = useFlag('dashboardCmdk') const allowCMDKDataOptIn = useFlag('dashboardCmdkDataOptIn') - const canUpdateOrganization = checkPermissions(PermissionAction.UPDATE, 'organizations') - const canDeleteOrganization = checkPermissions(PermissionAction.UPDATE, 'organizations') + const canUpdateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') + const canDeleteOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') const onUpdateOrganization = async (values: any, { setSubmitting, resetForm }: any) => { if (!canUpdateOrganization) { return ui.setNotification({ diff --git a/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx b/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx index 49024811da5..f54d883d63b 100644 --- a/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx +++ b/studio/components/interfaces/Organization/GeneralSettings/MigrateOrganizationBillingButton.tsx @@ -3,7 +3,7 @@ import { observer } from 'mobx-react-lite' import { Button, Form, Modal, Listbox, Loading, Alert, IconHelpCircle, Toggle } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions, useSelectedOrganization } from 'hooks' +import { useStore, useCheckPermissions, useSelectedOrganization } from 'hooks' import { PRICING_TIER_LABELS_ORG } from 'lib/constants' import { useOrganizationBillingMigrationMutation } from 'data/organizations/organization-migrate-billing-mutation' import { useOrganizationBillingMigrationPreview } from 'data/organizations/organization-migrate-billing-preview-query' @@ -62,7 +62,7 @@ const MigrateOrganizationBillingButton = observer(() => { } }, [isOpen]) - const canMigrateOrganization = checkPermissions(PermissionAction.UPDATE, 'organizations') + const canMigrateOrganization = useCheckPermissions(PermissionAction.UPDATE, 'organizations') const toggle = () => { setIsOpen(!isOpen) diff --git a/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx b/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx index 80d8403c1be..79c58e9a894 100644 --- a/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx +++ b/studio/components/interfaces/Organization/InvoicesSettings/InvoicesSettings.tsx @@ -6,7 +6,7 @@ import InvoiceStatusBadge from 'components/interfaces/Billing/InvoiceStatusBadge import { Invoice, InvoiceStatus } from 'components/interfaces/Billing/Invoices.types' import Table from 'components/to-be-cleaned/Table' import NoPermission from 'components/ui/NoPermission' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { get, head } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { Button, IconChevronLeft, IconChevronRight, IconDownload, IconFileText, Loading } from 'ui' @@ -27,7 +27,7 @@ const InvoicesSettings = () => { const { stripe_customer_id, slug } = selectedOrganization ?? {} const offset = (page - 1) * PAGE_LIMIT - const canReadInvoices = checkPermissions(PermissionAction.READ, 'invoices') + const canReadInvoices = useCheckPermissions(PermissionAction.READ, 'invoices') useEffect(() => { if (!canReadInvoices || !stripe_customer_id || !slug) return diff --git a/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx b/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx index 4ac9ce6acbe..d9bf01381cc 100644 --- a/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx @@ -1,14 +1,14 @@ +import * as Tooltip from '@radix-ui/react-tooltip' import { isNil } from 'lodash' import { useEffect, useState } from 'react' import { object, string } from 'yup' -import * as Tooltip from '@radix-ui/react-tooltip' -import { Button, Form, IconMail, Input, Listbox, Modal } from 'ui' -import { Member, Role } from 'types' -import { checkPermissions, useStore } from 'hooks' -import { useParams } from 'common/hooks' import { PermissionAction } from '@supabase/shared-types/out/constants' +import { useParams } from 'common/hooks' import { useOrganizationMemberInviteCreateMutation } from 'data/organizations/organization-member-invite-create-mutation' +import { doPermissionsCheck, useGetPermissions, useStore } from 'hooks' +import { Member, Role } from 'types' +import { Button, Form, IconMail, Input, Listbox, Modal } from 'ui' export interface InviteMemberButtonProps { userId: number @@ -28,8 +28,12 @@ const InviteMemberButton = ({ const [isOpen, setIsOpen] = useState(false) + const { permissions: allPermissions } = useGetPermissions() + const canInviteMembers = roles.some(({ id: role_id }) => - checkPermissions(PermissionAction.CREATE, 'user_invites', { resource: { role_id } }) + doPermissionsCheck(allPermissions, PermissionAction.CREATE, 'user_invites', { + resource: { role_id }, + }) ) const initialValues = { email: '', role: '' } diff --git a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx index 0038fdf50ea..d49a715f289 100644 --- a/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx +++ b/studio/components/interfaces/Organization/TeamSettings/MemberActions.tsx @@ -9,7 +9,7 @@ import { useOrganizationMemberDeleteMutation } from 'data/organizations/organiza import { useOrganizationMemberInviteCreateMutation } from 'data/organizations/organization-member-invite-create-mutation' import { useOrganizationMemberInviteDeleteMutation } from 'data/organizations/organization-member-invite-delete-mutation' import { usePermissionsQuery } from 'data/permissions/permissions-query' -import { checkPermissions, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useSelectedOrganization, useStore } from 'hooks' import { Member, Role } from 'types' import { Button, Dropdown, IconMoreHorizontal, IconTrash } from 'ui' import { isInviteExpired } from '../Organization.utils' @@ -36,10 +36,10 @@ const MemberActions: FC = ({ member, roles }) => { const roleId = member.role_ids?.[0] ?? -1 const canRemoveMember = rolesRemovable.includes((member?.role_ids ?? [-1])[0]) - const canResendInvite = checkPermissions(PermissionAction.CREATE, 'user_invites', { + const canResendInvite = useCheckPermissions(PermissionAction.CREATE, 'user_invites', { resource: { role_id: roleId }, }) - const canRevokeInvite = checkPermissions(PermissionAction.DELETE, 'user_invites', { + const canRevokeInvite = useCheckPermissions(PermissionAction.DELETE, 'user_invites', { resource: { role_id: roleId }, }) diff --git a/studio/components/interfaces/Settings/API/JWTSettings.tsx b/studio/components/interfaces/Settings/API/JWTSettings.tsx index d9853359b33..e93d4e12f74 100644 --- a/studio/components/interfaces/Settings/API/JWTSettings.tsx +++ b/studio/components/interfaces/Settings/API/JWTSettings.tsx @@ -23,7 +23,7 @@ import { import { PermissionAction } from '@supabase/shared-types/out/constants' import { uuidv4 } from 'lib/helpers' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' import { useJwtSecretUpdateMutation } from 'data/config/jwt-secret-update-mutation' @@ -48,8 +48,8 @@ const JWTSettings: FC = ({}) => { const [isSubmittingJwtSecretUpdateRequest, setIsSubmittingJwtSecretUpdateRequest] = useState(false) - const canReadJWTSecret = checkPermissions(PermissionAction.READ, 'field.jwt_secret') - const canGenerateNewJWTSecret = checkPermissions( + const canReadJWTSecret = useCheckPermissions(PermissionAction.READ, 'field.jwt_secret') + const canGenerateNewJWTSecret = useCheckPermissions( PermissionAction.INFRA_EXECUTE, 'queue_job.projects.update_jwt' ) diff --git a/studio/components/interfaces/Settings/API/PostgrestConfig.tsx b/studio/components/interfaces/Settings/API/PostgrestConfig.tsx index f52a9da6473..1328b337b0f 100644 --- a/studio/components/interfaces/Settings/API/PostgrestConfig.tsx +++ b/studio/components/interfaces/Settings/API/PostgrestConfig.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react-lite' import { Input, Form, IconAlertCircle, InputNumber } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { useProjectPostgrestConfigQuery } from 'data/config/project-postgrest-config-query' import { useProjectPostgrestConfigUpdateMutation } from 'data/config/project-postgrest-config-update-mutation' @@ -37,7 +37,7 @@ const PostgrestConfig: FC = ({}) => { db_extra_search_path: '', } - const canUpdatePostgrestConfig = checkPermissions( + const canUpdatePostgrestConfig = useCheckPermissions( PermissionAction.UPDATE, 'custom_config_postgrest' ) diff --git a/studio/components/interfaces/Settings/Database/ConnectionPooling.tsx b/studio/components/interfaces/Settings/Database/ConnectionPooling.tsx index 13385ecd934..95c8ba477a4 100644 --- a/studio/components/interfaces/Settings/Database/ConnectionPooling.tsx +++ b/studio/components/interfaces/Settings/Database/ConnectionPooling.tsx @@ -7,7 +7,7 @@ import SchemaFormPanel from 'components/to-be-cleaned/forms/SchemaFormPanel' import Divider from 'components/ui/Divider' import Panel from 'components/ui/Panel' import ShimmeringLoader from 'components/ui/ShimmeringLoader' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { pluckObjectFields } from 'lib/helpers' @@ -123,7 +123,7 @@ interface ConfigProps { export const PgbouncerConfig: FC = ({ projectRef, bouncerInfo, connectionInfo }) => { const { ui } = useStore() - const canUpdateConnectionPoolingConfiguration = checkPermissions( + const canUpdateConnectionPoolingConfiguration = useCheckPermissions( PermissionAction.UPDATE, 'projects' ) diff --git a/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx b/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx index 098c514f2f7..73b3de9eec1 100644 --- a/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx +++ b/studio/components/interfaces/Settings/Database/DatabaseSettings/ResetDbPassword.tsx @@ -5,7 +5,7 @@ import generator from 'generate-password' import { Input, Button, Modal } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { patch } from 'lib/common/fetch' import { passwordStrength } from 'lib/helpers' @@ -19,7 +19,7 @@ const ResetDbPassword: FC = ({ disabled = false }) => { const { ui, app, meta } = useStore() const { ref } = useParams() - const canResetDbPassword = checkPermissions(PermissionAction.UPDATE, 'projects') + const canResetDbPassword = useCheckPermissions(PermissionAction.UPDATE, 'projects') const [showResetDbPass, setShowResetDbPass] = useState(false) const [isUpdatingPassword, setIsUpdatingPassword] = useState(false) diff --git a/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx b/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx index e99285afbc8..b7c73169bd3 100644 --- a/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx +++ b/studio/components/interfaces/Settings/Database/DiskSizeConfiguration.tsx @@ -6,7 +6,7 @@ import Panel from 'components/ui/Panel' import { useProjectDiskResizeMutation } from 'data/config/project-disk-resize-mutation' import { useProjectSubscriptionV2Query } from 'data/subscriptions/project-subscription-v2-query' import { useProjectUsageQuery } from 'data/usage/project-usage-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import Link from 'next/link' import { useEffect, useState } from 'react' import { Alert, Button, Form, InputNumber, Modal } from 'ui' @@ -20,7 +20,7 @@ const DiskSizeConfiguration = ({ disabled = false }: DiskSizeConfigurationProps) const { ui } = useStore() const { ref: projectRef } = useParams() - const canUpdateDiskSizeConfig = checkPermissions(PermissionAction.UPDATE, 'projects') + const canUpdateDiskSizeConfig = useCheckPermissions(PermissionAction.UPDATE, 'projects') const [showResetDbPass, setShowResetDbPass] = useState(false) const [isUpdatingDiskSize, setIsUpdatingDiskSize] = useState(false) diff --git a/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx b/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx index b0391bea62f..16f5414552e 100644 --- a/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx +++ b/studio/components/interfaces/Settings/Database/NetworkRestrictions/NetworkRestrictions.tsx @@ -4,7 +4,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconAlertCircle, IconExternalLink, IconGlobe, IconLock } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import Panel from 'components/ui/Panel' import { FormPanel, FormHeader } from 'components/ui/Forms' @@ -84,7 +84,7 @@ const NetworkRestrictions = ({}) => { const [selectedRestrictionToRemove, setSelectedRestrictionToRemove] = useState() const { data, isLoading } = useNetworkRestrictionsQuery({ projectRef: ref }) - const canUpdateNetworkRestrictions = checkPermissions(PermissionAction.UPDATE, 'projects') + const canUpdateNetworkRestrictions = useCheckPermissions(PermissionAction.UPDATE, 'projects') const hasAccessToRestrictions = data?.entitlement === 'allowed' const restrictedIps = data?.config?.dbAllowedCidrs ?? [] diff --git a/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx b/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx index 1970db56306..d6dfc2bd7b5 100644 --- a/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx +++ b/studio/components/interfaces/Settings/Database/SSLConfiguration.tsx @@ -4,7 +4,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconDownload, Toggle, IconLoader, Alert, IconExternalLink } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore, useFlag } from 'hooks' +import { useCheckPermissions, useStore, useFlag } from 'hooks' import { useParams } from 'common/hooks' import { FormHeader, @@ -34,7 +34,7 @@ const SSLConfiguration = () => { }) const { mutateAsync: updateSSLEnforcement } = useSSLEnforcementUpdateMutation() - const canUpdateSSLEnforcement = checkPermissions(PermissionAction.UPDATE, 'projects') + const canUpdateSSLEnforcement = useCheckPermissions(PermissionAction.UPDATE, 'projects') const hasAccessToSSLEnforcement = !sslEnforcementConfiguration?.isNotAllowed const env = process.env.NEXT_PUBLIC_ENVIRONMENT === 'prod' ? 'prod' : 'staging' diff --git a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx index 4a3349638cc..75c54228551 100644 --- a/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx +++ b/studio/components/interfaces/Settings/General/CustomDomainConfig/CustomDomainsConfigureHostname.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react-lite' import { Button, Form, IconExternalLink, Input } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { FormActions, @@ -28,7 +28,7 @@ const CustomDomainsConfigureHostname = () => { const FORM_ID = 'custom-domains-form' const endpoint = settings?.autoApiService.endpoint - const canConfigureCustomDomain = checkPermissions(PermissionAction.UPDATE, 'projects') + const canConfigureCustomDomain = useCheckPermissions(PermissionAction.UPDATE, 'projects') const verifyCNAME = async (domain: string): Promise => { const res = await fetch(`https://1.1.1.1/dns-query?name=${domain}`, { diff --git a/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx b/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx index b630039ef37..915c12b0dc5 100644 --- a/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx +++ b/studio/components/interfaces/Settings/General/DeleteProjectPanel/DeleteProjectButton.tsx @@ -9,7 +9,7 @@ import { CANCELLATION_REASONS } from 'components/interfaces/BillingV2/Billing.co import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import TextConfirmModal from 'components/ui/Modals/TextConfirmModal' import { invalidateProjectsQuery } from 'data/projects/projects-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { delete_, post } from 'lib/common/fetch' import { API_URL, PRICING_TIER_PRODUCT_IDS } from 'lib/constants' @@ -39,7 +39,7 @@ const DeleteProjectButton = ({ type = 'danger' }: DeleteProjectButtonProps) => { } }, [isOpen]) - const canDeleteProject = checkPermissions(PermissionAction.UPDATE, 'projects') + const canDeleteProject = useCheckPermissions(PermissionAction.UPDATE, 'projects') const toggle = () => { if (loading) return diff --git a/studio/components/interfaces/Settings/General/General.tsx b/studio/components/interfaces/Settings/General/General.tsx index a1630be4b42..9fcbdac5795 100644 --- a/studio/components/interfaces/Settings/General/General.tsx +++ b/studio/components/interfaces/Settings/General/General.tsx @@ -12,7 +12,7 @@ import { FormSectionLabel, } from 'components/ui/Forms' import { invalidateProjectsQuery } from 'data/projects/projects-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { patch } from 'lib/common/fetch' import { API_URL } from 'lib/constants' @@ -23,7 +23,7 @@ const General = () => { const formId = 'project-general-settings' const initialValues = { name: project?.name ?? '', ref: project?.ref ?? '' } - const canUpdateProject = checkPermissions(PermissionAction.UPDATE, 'projects') + const canUpdateProject = useCheckPermissions(PermissionAction.UPDATE, 'projects') const onSubmit = async (values: any, { resetForm }: any) => { const response = await patch(`${API_URL}/projects/${project?.ref}`, { diff --git a/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx b/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx index 55f1736fccd..fdd25f07510 100644 --- a/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx +++ b/studio/components/interfaces/Settings/General/Infrastructure/PauseProjectButton.tsx @@ -8,7 +8,7 @@ import { FC, useState } from 'react' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' import ConfirmModal from 'components/ui/Dialogs/ConfirmDialog' import { setProjectStatus } from 'data/projects/projects-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { post } from 'lib/common/fetch' import { API_URL, PROJECT_STATUS } from 'lib/constants' import { Button, IconPause } from 'ui' @@ -30,7 +30,7 @@ const PauseProjectButton: FC = observer(({ projectRef, projectId }) => { const closeModal = () => setIsModalOpen(false) const isPaused = project?.status === PROJECT_STATUS.INACTIVE - const canPauseProject = checkPermissions( + const canPauseProject = useCheckPermissions( PermissionAction.INFRA_EXECUTE, 'queue_jobs.projects.pause' ) diff --git a/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx b/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx index c11859ad691..2435d800eea 100644 --- a/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx +++ b/studio/components/interfaces/Settings/General/Infrastructure/RestartServerButton.tsx @@ -8,7 +8,7 @@ import { Button, Dropdown, IconChevronDown } from 'ui' import ConfirmModal from 'components/ui/Dialogs/ConfirmDialog' import { setProjectPostgrestStatus } from 'data/projects/projects-query' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { post } from 'lib/common/fetch' import { API_URL } from 'lib/constants' import { Project } from 'types' @@ -27,7 +27,7 @@ const RestartServerButton = ({ project }: RestartServerButtonProps) => { const projectRef = project.ref const projectRegion = project.region - const canRestartProject = checkPermissions(PermissionAction.INFRA_EXECUTE, 'reboot') + const canRestartProject = useCheckPermissions(PermissionAction.INFRA_EXECUTE, 'reboot') const requestProjectRestart = async () => { if (!canRestartProject) { diff --git a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx index 01e4a6d527f..1d743178e1c 100644 --- a/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Keys/EncryptionKeysManagement.tsx @@ -18,7 +18,7 @@ import { IconExternalLink, } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import Divider from 'components/ui/Divider' @@ -36,7 +36,7 @@ const EncryptionKeysManagement: FC = ({}) => { const [selectedKeyToRemove, setSelectedKeyToRemove] = useState() const [isDeletingKey, setIsDeletingKey] = useState(false) - const canManageKeys = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const canManageKeys = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') useEffect(() => { if (id !== undefined) setSearchValue(id) diff --git a/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx b/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx index a4b2cf56e7b..c0a9419c7e8 100644 --- a/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx +++ b/studio/components/interfaces/Settings/Vault/Secrets/SecretRow.tsx @@ -16,7 +16,7 @@ import { import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' import { VaultSecret } from 'types' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' interface Props { @@ -33,7 +33,7 @@ const SecretRow: FC = ({ secret, onSelectEdit, onSelectRemove }) => { const [revealedValue, setRevealedValue] = useState() const name = secret?.name ?? 'No name provided' - const canManageSecrets = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const canManageSecrets = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const revealSecret = async () => { setIsLoading(true) diff --git a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx index e5dfe455fe0..88954ad8984 100644 --- a/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx +++ b/studio/components/interfaces/Settings/Vault/Secrets/SecretsManagement.tsx @@ -5,7 +5,7 @@ import { FC, Fragment, useState, useEffect } from 'react' import { IconSearch, Input, Button, Listbox, IconLoader, IconExternalLink, IconX } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import { useParams } from 'common/hooks' import SecretRow from './SecretRow' import EditSecretModal from './EditSecretModal' @@ -25,7 +25,7 @@ const SecretsManagement: FC = ({}) => { const [selectedSecretToEdit, setSelectedSecretToEdit] = useState() const [selectedSecretToRemove, setSelectedSecretToRemove] = useState() - const canManageSecrets = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const canManageSecrets = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') useEffect(() => { if (search !== undefined) setSearchValue(search) diff --git a/studio/components/interfaces/Settings/Vault/VaultToggle.tsx b/studio/components/interfaces/Settings/Vault/VaultToggle.tsx index f8a187ecc90..e96511cf63c 100644 --- a/studio/components/interfaces/Settings/Vault/VaultToggle.tsx +++ b/studio/components/interfaces/Settings/Vault/VaultToggle.tsx @@ -5,7 +5,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { Button, IconExternalLink } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { useParams } from 'common/hooks' import { BASE_PATH } from 'lib/constants' import { useTheme } from 'common' @@ -17,7 +17,7 @@ const VaultToggle: FC = () => { const { ref } = useParams() const { isDarkMode } = useTheme() const [isEnabling, setIsEnabling] = useState(false) - const canToggleVault = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions') + const canToggleVault = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'extensions') const vaultExtension = meta.extensions.byId('supabase_vault') const isNotAvailable = vaultExtension === undefined diff --git a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx index 56a81b2c554..61fb02e7fd4 100644 --- a/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx +++ b/studio/components/interfaces/TableGridEditor/TableGridEditor.tsx @@ -7,7 +7,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import { QueryKey, useQueryClient } from '@tanstack/react-query' import { SchemaView } from 'types' -import { checkPermissions, useFlag, useStore, useUrlState } from 'hooks' +import { useCheckPermissions, useFlag, useStore, useUrlState } from 'hooks' import useEntityType from 'hooks/misc/useEntityType' import { useParams } from 'common/hooks' import GridHeaderActions from './GridHeaderActions' @@ -116,9 +116,10 @@ const TableGridEditor = ({ } } - const isReadOnly = - !checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') && - !checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') + const canEditTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const canEditColumns = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'columns') + + const isReadOnly = !canEditTables && !canEditColumns const getEncryptedColumns = async (table: any) => { const columns = await vault.listEncryptedColumns(table.schema, table.name) @@ -214,7 +215,6 @@ const TableGridEditor = ({ const isTableSelected = entityType?.type === ENTITY_TYPE.TABLE const isForeignTableSelected = entityType?.type === ENTITY_TYPE.FOREIGN_TABLE const isLocked = meta.excludedSchemas.includes(entityType?.schema ?? '') - const canUpdateTables = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const canEditViaTableEditor = isTableSelected && !isLocked // [Joshen] We can tweak below to eventually support composite keys as the data @@ -351,7 +351,7 @@ const TableGridEditor = ({ theme={theme} gridProps={{ height: '100%' }} storageRef={projectRef} - editable={!isReadOnly && canUpdateTables && canEditViaTableEditor} + editable={!isReadOnly && canEditTables && canEditViaTableEditor} schema={selectedTable.schema} table={gridTable} refreshDocs={refreshDocs} diff --git a/studio/components/layouts/FunctionsLayout.tsx b/studio/components/layouts/FunctionsLayout.tsx index 8c5c69d1d2e..815aff90c2f 100644 --- a/studio/components/layouts/FunctionsLayout.tsx +++ b/studio/components/layouts/FunctionsLayout.tsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react-lite' import { Button, IconExternalLink, IconCode, Modal, IconTerminal } from 'ui' import ProjectLayout from './' -import { checkPermissions, withAuth } from 'hooks' +import { useCheckPermissions, withAuth } from 'hooks' import { useParams } from 'common/hooks' import FunctionsNav from '../interfaces/Functions/FunctionsNav' import NoPermission from 'components/ui/NoPermission' @@ -24,7 +24,7 @@ const FunctionsLayout: FC = ({ title, children }) => { const { data: functions, isLoading } = useEdgeFunctionsQuery({ projectRef: ref }) const { data: selectedFunction } = useEdgeFunctionQuery({ projectRef: ref, slug: functionSlug }) - const canReadFunctions = checkPermissions(PermissionAction.FUNCTIONS_READ, '*') + const canReadFunctions = useCheckPermissions(PermissionAction.FUNCTIONS_READ, '*') if (!canReadFunctions) { return ( diff --git a/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx b/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx index b4f140347ca..adadffcaae4 100644 --- a/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx +++ b/studio/components/layouts/ProjectLayout/ProjectPausedState.tsx @@ -8,7 +8,7 @@ import { useParams } from 'common' import ConfirmModal from 'components/ui/Dialogs/ConfirmDialog' import { useFreeProjectLimitCheckQuery } from 'data/organizations/free-project-limit-check-query' import { setProjectStatus } from 'data/projects/projects-query' -import { checkPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' +import { useCheckPermissions, useFlag, useSelectedOrganization, useStore } from 'hooks' import { post } from 'lib/common/fetch' import { API_URL, PROJECT_STATUS } from 'lib/constants' import { Button, IconPauseCircle, Modal } from 'ui' @@ -33,7 +33,7 @@ const ProjectPausedState = ({ product }: ProjectPausedStateProps) => { const [showConfirmRestore, setShowConfirmRestore] = useState(false) const [showFreeProjectLimitWarning, setShowFreeProjectLimitWarning] = useState(false) - const canResumeProject = checkPermissions( + const canResumeProject = useCheckPermissions( PermissionAction.INFRA_EXECUTE, 'queue_jobs.projects.initialize_or_resume' ) diff --git a/studio/components/layouts/StorageLayout/BucketRow.tsx b/studio/components/layouts/StorageLayout/BucketRow.tsx index 6afb956a349..dc79e48b408 100644 --- a/studio/components/layouts/StorageLayout/BucketRow.tsx +++ b/studio/components/layouts/StorageLayout/BucketRow.tsx @@ -5,7 +5,7 @@ import Link from 'next/link' import { Badge, Button, Dropdown, IconChevronDown, IconEdit2, IconLoader, IconTrash } from 'ui' import { Bucket } from 'data/storage/buckets-query' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' export interface BucketRowProps { bucket: Bucket @@ -22,7 +22,7 @@ const BucketRow = ({ onSelectDeleteBucket = noop, onSelectEditBucket = noop, }: BucketRowProps) => { - const canUpdateBuckets = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canUpdateBuckets = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') return (
{ const { ref, bucketId } = useParams() const [showCreateBucketModal, setShowCreateBucketModal] = useState(false) const [selectedBucketToEdit, setSelectedBucketToEdit] = useState() - const canCreateBuckets = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canCreateBuckets = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') const page = router.pathname.split('/')[4] as | undefined diff --git a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx index 4479159c2c0..2cf50e4643f 100644 --- a/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx +++ b/studio/components/layouts/TableEditorLayout/TableEditorLayout.tsx @@ -9,7 +9,7 @@ import Connecting from 'components/ui/Loading/Loading' import NoPermission from 'components/ui/NoPermission' import { ENTITY_TYPE } from 'data/entity-types/entity-type-constants' import { Entity } from 'data/entity-types/entity-type-query' -import { checkPermissions, useSelectedProject, useStore } from 'hooks' +import { useCheckPermissions, useSelectedProject, useStore } from 'hooks' import useEntityType from 'hooks/misc/useEntityType' import useLatest from 'hooks/misc/useLatest' import { useIsTableLoaded, useTableEditorStateSnapshot } from 'state/table-editor' @@ -44,7 +44,7 @@ const TableEditorLayout = ({ const id = _id ? Number(_id) : undefined const snap = useTableEditorStateSnapshot() - const canReadTables = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'tables') + const canReadTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_READ, 'tables') const vaultExtension = meta.extensions.byId('supabase_vault') const isVaultEnabled = vaultExtension !== undefined && vaultExtension.installed_version !== null diff --git a/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx b/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx index 4c6e3d1c8b2..1e8f7e114e6 100644 --- a/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx +++ b/studio/components/layouts/TableEditorLayout/TableEditorMenu.tsx @@ -20,7 +20,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants' import type { PostgresSchema } from '@supabase/postgres-meta' import { useParams } from 'common/hooks' -import { checkPermissions, useStore, useLocalStorage } from 'hooks' +import { useCheckPermissions, useStore, useLocalStorage } from 'hooks' import { useEntityTypesQuery } from 'data/entity-types/entity-types-infinite-query' import { Entity } from 'data/entity-types/entity-type-query' import { useProjectContext } from '../ProjectLayout/ProjectContext' @@ -85,7 +85,7 @@ const TableEditorMenu = ({ const schemas: PostgresSchema[] = meta.schemas.list() const schema = schemas.find((schema) => schema.name === selectedSchema) - const canCreateTables = checkPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') + const canCreateTables = useCheckPermissions(PermissionAction.TENANT_SQL_ADMIN_WRITE, 'tables') const isLoadingTableMetadata = id ? !meta.tables.byId(id) : true diff --git a/studio/components/to-be-cleaned/Docs/Description.js b/studio/components/to-be-cleaned/Docs/Description.js index ec37ba6e9b1..fc942ac6c50 100644 --- a/studio/components/to-be-cleaned/Docs/Description.js +++ b/studio/components/to-be-cleaned/Docs/Description.js @@ -2,7 +2,7 @@ import { useState } from 'react' import { Button, IconLoader } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { useStore, checkPermissions } from 'hooks' +import { useStore, useCheckPermissions } from 'hooks' import AutoTextArea from 'components/to-be-cleaned/forms/AutoTextArea' import { timeout } from 'lib/helpers' @@ -32,7 +32,7 @@ export default function Description({ content, metadata, onChange = () => {} }) const hasChanged = value != contentText const animateCss = `transition duration-150` - const canUpdateDescription = checkPermissions(PermissionAction.TENANT_SQL_QUERY, '*') + const canUpdateDescription = useCheckPermissions(PermissionAction.TENANT_SQL_QUERY, '*') const updateDescription = async () => { if (isUpdating || !canUpdateDescription) return false diff --git a/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx b/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx index 9e121416c62..bfd8d6a21c4 100644 --- a/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerHeader.tsx @@ -21,7 +21,7 @@ import { import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' import { STORAGE_VIEWS, STORAGE_SORT_BY, STORAGE_SORT_BY_ORDER } from '../Storage.constants' @@ -141,7 +141,7 @@ const FileExplorerHeader: FC = ({ const breadcrumbs = columns.map((column: any) => column.name) const backDisabled = columns.length <= 1 - const canUpdateStorage = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canUpdateStorage = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') useEffect(() => { if (itemSearchString) setSearchString(itemSearchString) diff --git a/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx b/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx index 19567f7484b..ab905d4f326 100644 --- a/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageExplorer/FileExplorerRow.tsx @@ -21,7 +21,7 @@ import * as Tooltip from '@radix-ui/react-tooltip' import { useContextMenu } from 'react-contexify' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { STORAGE_VIEWS, STORAGE_ROW_TYPES, @@ -119,7 +119,7 @@ const FileExplorerRow = ({ const isOpened = openedFolders.length > columnIndex ? isEqual(openedFolders[columnIndex], item) : false const isPreviewed = !isEmpty(selectedFilePreview) && isEqual(selectedFilePreview.id, item.id) - const canUpdateFiles = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canUpdateFiles = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') const { show } = useContextMenu() diff --git a/studio/components/to-be-cleaned/Storage/StorageExplorer/FolderContextMenu.tsx b/studio/components/to-be-cleaned/Storage/StorageExplorer/FolderContextMenu.tsx index 5dea1dd1b93..541d3437f0c 100644 --- a/studio/components/to-be-cleaned/Storage/StorageExplorer/FolderContextMenu.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageExplorer/FolderContextMenu.tsx @@ -4,7 +4,7 @@ import 'react-contexify/dist/ReactContexify.css' import { IconEdit, IconDownload, IconTrash2 } from 'ui' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' interface Props { @@ -14,7 +14,7 @@ interface Props { const FolderContextMenu: FC = ({ id = '' }) => { const storageExplorerStore = useStorageStore() const { downloadFolder, setSelectedItemToRename, setSelectedItemsToDelete } = storageExplorerStore - const canUpdateFiles = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canUpdateFiles = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') return ( diff --git a/studio/components/to-be-cleaned/Storage/StorageExplorer/ItemContextMenu.tsx b/studio/components/to-be-cleaned/Storage/StorageExplorer/ItemContextMenu.tsx index e04d39f146c..beede269ab7 100644 --- a/studio/components/to-be-cleaned/Storage/StorageExplorer/ItemContextMenu.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageExplorer/ItemContextMenu.tsx @@ -4,7 +4,7 @@ import 'react-contexify/dist/ReactContexify.css' import { PermissionAction } from '@supabase/shared-types/out/constants' import { IconClipboard, IconEdit, IconMove, IconDownload, IconTrash2, IconChevronRight } from 'ui' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { URL_EXPIRY_DURATION } from '../Storage.constants' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' import { noop } from 'lodash' @@ -26,7 +26,7 @@ const ItemContextMenu = ({ id = '', onCopyUrl = noop }: ItemContextMenuProps) => setSelectedFileCustomExpiry, } = storageExplorerStore const isPublic = selectedBucket.public - const canUpdateFiles = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canUpdateFiles = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') const onHandleClick = async (event: any, item: any, expiresIn?: number) => { if (item.isCorrupted) return diff --git a/studio/components/to-be-cleaned/Storage/StorageExplorer/PreviewPane.tsx b/studio/components/to-be-cleaned/Storage/StorageExplorer/PreviewPane.tsx index cb4deb1bea3..a50d04e58f6 100644 --- a/studio/components/to-be-cleaned/Storage/StorageExplorer/PreviewPane.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageExplorer/PreviewPane.tsx @@ -17,7 +17,7 @@ import { Transition } from '@headlessui/react' import * as Tooltip from '@radix-ui/react-tooltip' import { PermissionAction } from '@supabase/shared-types/out/constants' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { URL_EXPIRY_DURATION } from '../Storage.constants' import { useStorageStore } from 'localStores/storageExplorer/StorageExplorerStore' @@ -116,7 +116,7 @@ const PreviewPane = ({ onCopyUrl }: PreviewPaneProps) => { const mimeType = file.metadata ? file.metadata.mimetype : null const createdAt = file.created_at ? new Date(file.created_at).toLocaleString() : 'Unknown' const updatedAt = file.updated_at ? new Date(file.updated_at).toLocaleString() : 'Unknown' - const canUpdateFiles = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canUpdateFiles = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') return ( <> diff --git a/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx b/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx index 2da515fa150..6fe14d00574 100644 --- a/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx +++ b/studio/components/to-be-cleaned/Storage/StorageSettings/StorageSettings.tsx @@ -1,7 +1,7 @@ import { useState } from 'react' import { Button, Form, IconClock, Input, Listbox } from 'ui' -import { checkPermissions, useStore } from 'hooks' +import { useCheckPermissions, useStore } from 'hooks' import { IS_PLATFORM } from 'lib/constants' import { useProjectStorageConfigQuery } from 'data/config/project-storage-config-query' import { useProjectStorageConfigUpdateUpdateMutation } from 'data/config/project-storage-config-update-mutation' @@ -44,7 +44,7 @@ const StorageConfig = ({ config, projectRef }: any) => { const [selectedUnit, setSelectedUnit] = useState(unit) let initialValues = { fileSizeLimit: value, unformattedFileSizeLimit: fileSizeLimit } - const canUpdateStorageSettings = checkPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') + const canUpdateStorageSettings = useCheckPermissions(PermissionAction.STORAGE_ADMIN_WRITE, '*') const formattedMaxSizeBytes = `${new Intl.NumberFormat('en-US').format( STORAGE_FILE_SIZE_LIMIT_MAX_BYTES diff --git a/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx b/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx index fce70a3dc2b..a19d5f34d48 100644 --- a/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx +++ b/studio/components/ui/ProjectSettings/DisplayApiSettings.tsx @@ -6,7 +6,7 @@ import { useParams } from 'common/hooks' import Panel from 'components/ui/Panel' import { useJwtSecretUpdatingStatusQuery } from 'data/config/jwt-secret-updating-status-query' import { useProjectSettingsQuery } from 'data/config/project-settings-query' -import { checkPermissions } from 'hooks' +import { useCheckPermissions } from 'hooks' import { DEFAULT_PROJECT_API_SERVICE_ID } from 'lib/constants' const DisplayApiSettings = () => { @@ -24,7 +24,7 @@ const DisplayApiSettings = () => { } = useJwtSecretUpdatingStatusQuery({ projectRef }) const jwtSecretUpdateStatus = data?.jwtSecretUpdateStatus - const canReadAPIKeys = checkPermissions(PermissionAction.READ, 'service_api_keys') + const canReadAPIKeys = useCheckPermissions(PermissionAction.READ, 'service_api_keys') const isNotUpdatingJwtSecret = jwtSecretUpdateStatus === undefined || jwtSecretUpdateStatus === JwtSecretUpdateStatus.Updated diff --git a/studio/components/ui/UpgradeToPro.tsx b/studio/components/ui/UpgradeToPro.tsx index fe0a055afa9..2c6e6031b12 100644 --- a/studio/components/ui/UpgradeToPro.tsx +++ b/studio/components/ui/UpgradeToPro.tsx @@ -5,7 +5,7 @@ import { FC, ReactNode } from 'react' import { useParams } from 'common/hooks' import { useProjectContext } from 'components/layouts/ProjectLayout/ProjectContext' -import { checkPermissions, useFlag } from 'hooks' +import { useCheckPermissions, useFlag } from 'hooks' import { PRICING_TIER_PRODUCT_IDS } from 'lib/constants' import { Button } from 'ui' @@ -21,7 +21,7 @@ const UpgradeToPro: FC = ({ icon, primaryText, projectRef, secondaryText const { project } = useProjectContext() const tier = project?.subscription_tier - const canUpdateSubscription = checkPermissions( + const canUpdateSubscription = useCheckPermissions( PermissionAction.BILLING_WRITE, 'stripe.subscriptions' ) @@ -47,7 +47,11 @@ const UpgradeToPro: FC = ({ icon, primaryText, projectRef, secondaryText