mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 11:55:05 +03:00
Merge branch 'master' into issue-16994
This commit is contained in:
15 files changed
+81
-45
No files matched your search
@@ -50,7 +50,11 @@ const NavigationMenuHome = () => {
|
||||
>
|
||||
{link?.icon && <HomeMenuIconPicker icon={link.icon} />}
|
||||
{link.label}
|
||||
{link.community && <Badge size="small">Community</Badge>}
|
||||
{link.community && (
|
||||
<Badge size="small" color="scale">
|
||||
Community
|
||||
</Badge>
|
||||
)}
|
||||
</li>
|
||||
</a>
|
||||
</Link>
|
||||
|
||||
@@ -170,6 +170,8 @@ services:
|
||||
PGRST_DB_ANON_ROLE: anon
|
||||
PGRST_JWT_SECRET: ${JWT_SECRET}
|
||||
PGRST_DB_USE_LEGACY_GUCS: "false"
|
||||
PGRST_APP_SETTINGS_JWT_SECRET: ${JWT_SECRET}
|
||||
PGRST_APP_SETTINGS_JWT_EXP: ${JWT_EXPIRY}
|
||||
|
||||
realtime:
|
||||
container_name: realtime-dev.supabase-realtime
|
||||
|
||||
@@ -216,8 +216,7 @@ export default {
|
||||
},
|
||||
dot: '-ml-0.5 mr-1.5 h-2 w-2 rounded-full',
|
||||
color: {
|
||||
brand: 'bg-brand bg-opacity-100 text-background border border-brand-400',
|
||||
alt: 'bg-brand-500 text-brand-600 border border-brand-400',
|
||||
brand: 'bg-brand-500 text-brand-600 border border-brand-400',
|
||||
scale: 'bg-scale-200 text-scale-1100 border border-scale-700',
|
||||
tomato: `bg-tomato-200 text-tomato-1100 border border-tomato-700`,
|
||||
red: `bg-red-200 text-red-1100 border border-red-700`,
|
||||
|
||||
@@ -2,11 +2,10 @@ import { observer } from 'mobx-react-lite'
|
||||
import { useRouter } from 'next/router'
|
||||
import { PropsWithChildren, useEffect } from 'react'
|
||||
|
||||
import { useParams } from 'common'
|
||||
import { useIsLoggedIn, useParams } from 'common'
|
||||
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
|
||||
import { useProjectsQuery } from 'data/projects/projects-query'
|
||||
import { useFlag, useStore } from 'hooks'
|
||||
import useLatest from 'hooks/misc/useLatest'
|
||||
import { useFlag, useStore, useLatest } from 'hooks'
|
||||
import { DEFAULT_HOME, IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
|
||||
|
||||
// Ideally these could all be within a _middleware when we use Next 12
|
||||
@@ -16,6 +15,8 @@ const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => {
|
||||
const { ref, slug } = useParams()
|
||||
const navLayoutV2 = useFlag('navigationLayoutV2')
|
||||
|
||||
const isLoggedIn = useIsLoggedIn()
|
||||
|
||||
/**
|
||||
* Array of urls/routes that should be ignored
|
||||
*/
|
||||
@@ -37,12 +38,14 @@ const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => {
|
||||
return excemptUrls.includes(router?.pathname)
|
||||
}
|
||||
|
||||
const { data: organizations, isSuccess: orgsInitialized } = useOrganizationsQuery()
|
||||
const { data: organizations, isSuccess: orgsInitialized } = useOrganizationsQuery({
|
||||
enabled: isLoggedIn,
|
||||
})
|
||||
const organizationsRef = useLatest(organizations)
|
||||
|
||||
useEffect(() => {
|
||||
// check if current route is excempted from route validation check
|
||||
if (isExceptUrl()) return
|
||||
if (isExceptUrl() || !isLoggedIn) return
|
||||
|
||||
if (orgsInitialized && slug) {
|
||||
// Check validity of organization that user is trying to access
|
||||
@@ -57,12 +60,14 @@ const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => {
|
||||
}
|
||||
}, [orgsInitialized])
|
||||
|
||||
const { data: projects, isSuccess: projectsInitialized } = useProjectsQuery()
|
||||
const { data: projects, isSuccess: projectsInitialized } = useProjectsQuery({
|
||||
enabled: isLoggedIn,
|
||||
})
|
||||
const projectsRef = useLatest(projects)
|
||||
|
||||
useEffect(() => {
|
||||
// check if current route is excempted from route validation check
|
||||
if (isExceptUrl()) return
|
||||
if (isExceptUrl() || !isLoggedIn) return
|
||||
|
||||
if (projectsInitialized && ref) {
|
||||
// Check validity of project that the user is trying to access
|
||||
|
||||
@@ -35,6 +35,7 @@ import { Project } from 'types'
|
||||
import DisabledStateForFreeTier from './DisabledStateForFreeTier'
|
||||
import { CATEGORY_OPTIONS, SERVICE_OPTIONS, SEVERITY_OPTIONS } from './Support.constants'
|
||||
import { formatMessage, uploadAttachments } from './SupportForm.utils'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
const MAX_ATTACHMENTS = 5
|
||||
const INCLUDE_DISCUSSIONS = ['Problem', 'Database_unresponsive']
|
||||
@@ -45,6 +46,7 @@ export interface SupportFormProps {
|
||||
|
||||
const SupportForm = ({ setSentCategory }: SupportFormProps) => {
|
||||
const { ui } = useStore()
|
||||
const { isReady } = useRouter()
|
||||
const { ref, subject, category, message } = useParams()
|
||||
|
||||
const uploadButtonRef = useRef()
|
||||
@@ -270,6 +272,21 @@ const SupportForm = ({ setSentCategory }: SupportFormProps) => {
|
||||
}
|
||||
}, [isSuccessProjects, isSuccessOrganizations])
|
||||
|
||||
// Populate fields when router is ready, required when navigating to
|
||||
// support form on a refresh browser session
|
||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||
useEffect(() => {
|
||||
if (isReady) {
|
||||
const updatedValues = {
|
||||
projectRef: ref,
|
||||
subject,
|
||||
category: selectedCategoryFromUrl?.value,
|
||||
message,
|
||||
}
|
||||
resetForm({ values: updatedValues, initialValues: updatedValues })
|
||||
}
|
||||
}, [isReady])
|
||||
|
||||
return (
|
||||
<div className="space-y-8 w-[620px]">
|
||||
<div className="px-6">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useParams, useTelemetryProps } from 'common'
|
||||
import { useIsLoggedIn, useParams, useTelemetryProps } from 'common'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useRouter } from 'next/router'
|
||||
import { PropsWithChildren, useEffect } from 'react'
|
||||
@@ -13,6 +13,8 @@ const PageTelemetry = ({ children }: PropsWithChildren<{}>) => {
|
||||
const telemetryProps = useTelemetryProps()
|
||||
const selectedOrganization = useSelectedOrganization()
|
||||
|
||||
const isLoggedIn = useIsLoggedIn()
|
||||
|
||||
useEffect(() => {
|
||||
function handleRouteChange(url: string) {
|
||||
handlePageTelemetry(url)
|
||||
@@ -59,14 +61,16 @@ const PageTelemetry = ({ children }: PropsWithChildren<{}>) => {
|
||||
},
|
||||
})
|
||||
|
||||
post(`${API_URL}/telemetry/pageview`, {
|
||||
...(ref && { projectRef: ref }),
|
||||
...(selectedOrganization && { orgSlug: selectedOrganization.slug }),
|
||||
referrer: referrer,
|
||||
title: document.title,
|
||||
path: router.route,
|
||||
location: router.asPath,
|
||||
})
|
||||
if (isLoggedIn) {
|
||||
post(`${API_URL}/telemetry/pageview`, {
|
||||
...(ref && { projectRef: ref }),
|
||||
...(selectedOrganization && { orgSlug: selectedOrganization.slug }),
|
||||
referrer: referrer,
|
||||
title: document.title,
|
||||
path: router.route,
|
||||
location: router.asPath,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query'
|
||||
import { useCallback } from 'react'
|
||||
|
||||
import { get } from 'lib/common/fetch'
|
||||
import { API_URL, IS_PLATFORM } from 'lib/constants'
|
||||
import { useCallback } from 'react'
|
||||
import { Permission, ResponseError } from 'types'
|
||||
import { permissionKeys } from './keys'
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'react-hot-toast'
|
||||
|
||||
import { organizationKeys } from 'data/organizations/keys'
|
||||
import { permissionKeys } from 'data/permissions/keys'
|
||||
import { post } from 'lib/common/fetch'
|
||||
import { API_URL } from 'lib/constants'
|
||||
import { ResponseError } from 'types'
|
||||
@@ -29,7 +31,11 @@ export const useProfileCreateMutation = ({
|
||||
|
||||
return useMutation<ProfileCreateData, ResponseError, void>(() => createProfile(), {
|
||||
async onSuccess(data, variables, context) {
|
||||
await queryClient.invalidateQueries(profileKeys.profile())
|
||||
await Promise.all([
|
||||
queryClient.invalidateQueries(profileKeys.profile()),
|
||||
queryClient.invalidateQueries(organizationKeys.list()),
|
||||
queryClient.invalidateQueries(permissionKeys.list()),
|
||||
])
|
||||
await onSuccess?.(data, variables, context)
|
||||
},
|
||||
async onError(data, variables, context) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query'
|
||||
import { useQuery, UseQueryOptions } from '@tanstack/react-query'
|
||||
|
||||
import { get } from 'lib/common/fetch'
|
||||
import { API_URL } from 'lib/constants'
|
||||
import { useCallback } from 'react'
|
||||
import { ResponseError } from 'types'
|
||||
import { profileKeys } from './keys'
|
||||
import { Profile } from './types'
|
||||
import { ResponseError } from 'types'
|
||||
|
||||
export type ProfileResponse = Profile
|
||||
|
||||
@@ -30,14 +30,7 @@ export const useProfileQuery = <TData = ProfileData>({
|
||||
{
|
||||
staleTime: 1000 * 60 * 30, // default good for 30 mins
|
||||
...options,
|
||||
enabled,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export const useProfilePrefetch = () => {
|
||||
const client = useQueryClient()
|
||||
|
||||
return useCallback(() => {
|
||||
client.prefetchQuery(profileKeys.profile(), ({ signal }) => getProfile(signal))
|
||||
}, [])
|
||||
}
|
||||
@@ -6,4 +6,5 @@ export * from './misc/useSelectedOrganization'
|
||||
export * from './misc/useSelectedProject'
|
||||
export * from './misc/useStore'
|
||||
export * from './misc/withAuth'
|
||||
export * from './misc/useLatest'
|
||||
export * from './ui'
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useIsLoggedIn } from 'common'
|
||||
import jsonLogic from 'json-logic-js'
|
||||
|
||||
import { usePermissionsQuery } from 'data/permissions/permissions-query'
|
||||
@@ -67,11 +68,15 @@ export function useCheckPermissions(
|
||||
organizationId?: number,
|
||||
permissions?: Permission[]
|
||||
) {
|
||||
const isLoggedIn = useIsLoggedIn()
|
||||
|
||||
const { permissions: allPermissions, organizationId: orgId } = useGetPermissions(
|
||||
permissions,
|
||||
organizationId
|
||||
organizationId,
|
||||
isLoggedIn
|
||||
)
|
||||
|
||||
if (!isLoggedIn) return false
|
||||
if (!IS_PLATFORM) return true
|
||||
|
||||
return doPermissionsCheck(allPermissions, action, resource, data, orgId)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useRef } from 'react'
|
||||
|
||||
const useLatest = <T>(value: T): { readonly current: T } => {
|
||||
export const useLatest = <T>(value: T): { readonly current: T } => {
|
||||
const ref = useRef(value)
|
||||
ref.current = value
|
||||
return ref
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { useParams } from 'common'
|
||||
import { useIsLoggedIn, useParams } from 'common'
|
||||
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { useSelectedProject } from './useSelectedProject'
|
||||
import { LOCAL_STORAGE_KEYS } from 'lib/constants'
|
||||
import { useSelectedProject } from './useSelectedProject'
|
||||
|
||||
export function useSelectedOrganization({ enabled = true } = {}) {
|
||||
const isLoggedIn = useIsLoggedIn()
|
||||
|
||||
const { slug } = useParams()
|
||||
const { data } = useOrganizationsQuery({ enabled })
|
||||
const { data } = useOrganizationsQuery({ enabled: isLoggedIn && enabled })
|
||||
const selectedProject = useSelectedProject()
|
||||
|
||||
const localStorageSlug = useMemo(() => {
|
||||
|
||||
@@ -16,7 +16,6 @@ import { clearLocalStorage, resetSignInClicks } from './local-storage'
|
||||
export const AuthContext = AuthContextInternal
|
||||
|
||||
export const AuthProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
const queryClient = useQueryClient()
|
||||
const { ui } = useStore()
|
||||
const router = useRouter()
|
||||
const telemetryProps = useTelemetryProps()
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { useRouter } from 'next/router'
|
||||
import { PropsWithChildren, createContext, useContext, useMemo } from 'react'
|
||||
|
||||
import { useTelemetryProps } from 'common'
|
||||
import { invalidateOrganizationsQuery } from 'data/organizations/organizations-query'
|
||||
import { useIsLoggedIn, useTelemetryProps } from 'common'
|
||||
import { usePermissionsQuery } from 'data/permissions/permissions-query'
|
||||
import { useProfileCreateMutation } from 'data/profile/profile-create-mutation'
|
||||
import { useProfileQuery } from 'data/profile/profile-query'
|
||||
@@ -29,11 +27,12 @@ export const ProfileContext = createContext<ProfileContextType>({
|
||||
})
|
||||
|
||||
export const ProfileProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
const queryClient = useQueryClient()
|
||||
const { ui } = useStore()
|
||||
const router = useRouter()
|
||||
const telemetryProps = useTelemetryProps()
|
||||
|
||||
const isLoggedIn = useIsLoggedIn()
|
||||
|
||||
const { mutate: createProfile, isLoading: isCreatingProfile } = useProfileCreateMutation({
|
||||
async onSuccess() {
|
||||
Telemetry.sendEvent(
|
||||
@@ -41,8 +40,6 @@ export const ProfileProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
telemetryProps,
|
||||
router
|
||||
)
|
||||
|
||||
await invalidateOrganizationsQuery(queryClient)
|
||||
},
|
||||
onError() {
|
||||
ui.setNotification({
|
||||
@@ -60,6 +57,7 @@ export const ProfileProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
isError,
|
||||
isSuccess,
|
||||
} = useProfileQuery({
|
||||
enabled: isLoggedIn,
|
||||
onSuccess(profile) {
|
||||
Telemetry.sendIdentify(profile, telemetryProps)
|
||||
},
|
||||
@@ -71,7 +69,7 @@ export const ProfileProvider = ({ children }: PropsWithChildren<{}>) => {
|
||||
},
|
||||
})
|
||||
|
||||
const { isInitialLoading: isLoadingPermissions } = usePermissionsQuery()
|
||||
const { isInitialLoading: isLoadingPermissions } = usePermissionsQuery({ enabled: isLoggedIn })
|
||||
|
||||
const value = useMemo(() => {
|
||||
const isLoading = isLoadingProfile || isCreatingProfile || isLoadingPermissions
|
||||
|
||||
Reference in new issue
Block a user