diff --git a/studio/data/auth/auth-config-query.ts b/studio/data/auth/auth-config-query.ts new file mode 100644 index 00000000000..f1b8dc60235 --- /dev/null +++ b/studio/data/auth/auth-config-query.ts @@ -0,0 +1,61 @@ +import { useQuery, useQueryClient, UseQueryOptions } from '@tanstack/react-query' +import { components } from 'data/api' +import { get, isResponseOk } from 'lib/common/fetch' +import { API_URL } from 'lib/constants' +import { useCallback } from 'react' +import { authKeys } from './keys' + +export type AuthConfigVariables = { + projectRef?: string +} + +export type AuthConfigResponse = components['schemas']['GetGoTrueConfigResponse'] + +export async function getProjectAuthConfig( + { projectRef }: AuthConfigVariables, + signal?: AbortSignal +) { + if (!projectRef) { + throw new Error('projectRef is required') + } + + const response = await get(`${API_URL}/auth/${projectRef}/config`, { + signal, + }) + if (!isResponseOk(response)) { + throw response.error + } + + return response +} + +export type ProjectAuthConfigData = Awaited> +export type ProjectAuthConfigError = unknown + +export const useAuthConfigQuery = ( + { projectRef }: AuthConfigVariables, + { + enabled = true, + ...options + }: UseQueryOptions = {} +) => + useQuery( + authKeys.authConfig(projectRef), + ({ signal }) => getProjectAuthConfig({ projectRef }, signal), + { + enabled: enabled && typeof projectRef !== 'undefined', + ...options, + } + ) + +export const useAuthConfigPrefetch = ({ projectRef }: AuthConfigVariables) => { + const client = useQueryClient() + + return useCallback(() => { + if (projectRef) { + client.prefetchQuery(authKeys.authConfig(projectRef), ({ signal }) => + getProjectAuthConfig({ projectRef }, signal) + ) + } + }, [client, projectRef]) +} diff --git a/studio/data/auth/auth-config-update-mutation.ts b/studio/data/auth/auth-config-update-mutation.ts new file mode 100644 index 00000000000..908d9d1365f --- /dev/null +++ b/studio/data/auth/auth-config-update-mutation.ts @@ -0,0 +1,58 @@ +import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query' +import toast from 'react-hot-toast' + +import { components } from 'data/api' +import { patch } from 'lib/common/fetch' +import { API_URL } from 'lib/constants' +import { ResponseError } from 'types' +import { authKeys } from './keys' + +export type AuthConfigUpdateVariables = { + projectRef: string + config: Partial +} + +export type UpdateAuthConfigResponse = components['schemas']['GoTrueConfig'] + +export async function updateAuthConfig({ projectRef, config }: AuthConfigUpdateVariables) { + const response = await patch(`${API_URL}/auth/${projectRef}/config`, { ...config }) + if (response.error) { + throw response.error + } + + return response as UpdateAuthConfigResponse +} + +type AuthConfigUpdateData = Awaited> + +export const useAuthConfigUpdateMutation = ({ + onSuccess, + onError, + ...options +}: Omit< + UseMutationOptions, + 'mutationFn' +> = {}) => { + const queryClient = useQueryClient() + + return useMutation( + (vars) => updateAuthConfig(vars), + { + async onSuccess(data, variables, context) { + const { projectRef } = variables + + await Promise.all([queryClient.invalidateQueries(authKeys.authConfig(projectRef))]) + + await onSuccess?.(data, variables, context) + }, + async onError(data, variables, context) { + if (onError === undefined) { + toast.error(`Failed to mutate: ${data.message}`) + } else { + onError(data, variables, context) + } + }, + ...options, + } + ) +} diff --git a/studio/data/auth/keys.ts b/studio/data/auth/keys.ts index 052713f52ff..9dbece0ae3c 100644 --- a/studio/data/auth/keys.ts +++ b/studio/data/auth/keys.ts @@ -1,3 +1,4 @@ export const authKeys = { + authConfig: (projectRef: string | undefined) => ['auth', projectRef, 'config'] as const, accessToken: () => ['access-token'] as const, }