diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx
index 0cf04315a69..e94da27828e 100644
--- a/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenu.tsx
@@ -50,7 +50,11 @@ const NavigationMenuHome = () => {
>
{link?.icon && }
{link.label}
- {link.community && Community}
+ {link.community && (
+
+ Community
+
+ )}
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 0835f6b7a86..5060991b108 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -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
diff --git a/packages/ui/src/lib/theme/defaultTheme.ts b/packages/ui/src/lib/theme/defaultTheme.ts
index 52376c4be5c..832713fae83 100644
--- a/packages/ui/src/lib/theme/defaultTheme.ts
+++ b/packages/ui/src/lib/theme/defaultTheme.ts
@@ -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`,
diff --git a/studio/components/interfaces/App/RouteValidationWrapper.tsx b/studio/components/interfaces/App/RouteValidationWrapper.tsx
index 3b82a9b1679..9689db2fdee 100644
--- a/studio/components/interfaces/App/RouteValidationWrapper.tsx
+++ b/studio/components/interfaces/App/RouteValidationWrapper.tsx
@@ -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
diff --git a/studio/components/interfaces/Support/SupportForm.tsx b/studio/components/interfaces/Support/SupportForm.tsx
index bf2bddef769..614b49cd147 100644
--- a/studio/components/interfaces/Support/SupportForm.tsx
+++ b/studio/components/interfaces/Support/SupportForm.tsx
@@ -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 (
diff --git a/studio/components/ui/PageTelemetry.tsx b/studio/components/ui/PageTelemetry.tsx
index ddba717617f..24fd0e4bea5 100644
--- a/studio/components/ui/PageTelemetry.tsx
+++ b/studio/components/ui/PageTelemetry.tsx
@@ -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,
+ })
+ }
}
}
diff --git a/studio/data/permissions/permissions-query.ts b/studio/data/permissions/permissions-query.ts
index b96a57c6698..d98a9a2a15b 100644
--- a/studio/data/permissions/permissions-query.ts
+++ b/studio/data/permissions/permissions-query.ts
@@ -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'
diff --git a/studio/data/profile/profile-create-mutation.ts b/studio/data/profile/profile-create-mutation.ts
index a6a3f358a4c..37ff0d23424 100644
--- a/studio/data/profile/profile-create-mutation.ts
+++ b/studio/data/profile/profile-create-mutation.ts
@@ -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
(() => 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) {
diff --git a/studio/data/profile/profile-query.ts b/studio/data/profile/profile-query.ts
index a11e5050e16..53ab747ba7f 100644
--- a/studio/data/profile/profile-query.ts
+++ b/studio/data/profile/profile-query.ts
@@ -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 = ({
{
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))
- }, [])
-}
diff --git a/studio/hooks/index.ts b/studio/hooks/index.ts
index c8c4d6b4db6..1f606782393 100644
--- a/studio/hooks/index.ts
+++ b/studio/hooks/index.ts
@@ -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'
diff --git a/studio/hooks/misc/useCheckPermissions.ts b/studio/hooks/misc/useCheckPermissions.ts
index f1228eda934..963f739a630 100644
--- a/studio/hooks/misc/useCheckPermissions.ts
+++ b/studio/hooks/misc/useCheckPermissions.ts
@@ -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)
diff --git a/studio/hooks/misc/useLatest.ts b/studio/hooks/misc/useLatest.ts
index 68577e65399..dd29313d4e8 100644
--- a/studio/hooks/misc/useLatest.ts
+++ b/studio/hooks/misc/useLatest.ts
@@ -1,6 +1,6 @@
import { useRef } from 'react'
-const useLatest = (value: T): { readonly current: T } => {
+export const useLatest = (value: T): { readonly current: T } => {
const ref = useRef(value)
ref.current = value
return ref
diff --git a/studio/hooks/misc/useSelectedOrganization.ts b/studio/hooks/misc/useSelectedOrganization.ts
index bc6be1b3710..ef7a1d6599c 100644
--- a/studio/hooks/misc/useSelectedOrganization.ts
+++ b/studio/hooks/misc/useSelectedOrganization.ts
@@ -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(() => {
diff --git a/studio/lib/auth.tsx b/studio/lib/auth.tsx
index a0e3e21ed7a..12fd3097c06 100644
--- a/studio/lib/auth.tsx
+++ b/studio/lib/auth.tsx
@@ -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()
diff --git a/studio/lib/profile.tsx b/studio/lib/profile.tsx
index d8feec8dcbc..41203d29913 100644
--- a/studio/lib/profile.tsx
+++ b/studio/lib/profile.tsx
@@ -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({
})
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