dify/web/service/access-control/use-app-access-control.ts

101 lines
3.4 KiB
TypeScript

import type { AccessControlAccount, AccessControlGroup, AccessMode, Subject } from '@/models/access-control'
import type { App } from '@/types/app'
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { systemFeaturesQueryOptions } from '@/service/system-features'
import { get, post } from '../base'
import { getUserCanAccess } from '../share'
const NAME_SPACE = 'access-control'
export const useAppWhiteListSubjects = (appId: string | undefined, enabled: boolean) => {
return useQuery({
queryKey: [NAME_SPACE, 'app-whitelist-subjects', appId],
queryFn: () => get<{ groups: AccessControlGroup[], members: AccessControlAccount[] }>(`/enterprise/webapp/app/subjects?appId=${appId}`),
enabled: !!appId && enabled,
staleTime: 0,
gcTime: 0,
})
}
type SearchResults = {
currPage: number
totalPages: number
subjects: Subject[]
hasMore: boolean
}
type SearchForWhiteListCandidatesQuery = {
keyword?: string
groupId?: AccessControlGroup['id']
resultsPerPage?: number
}
export const useSearchForWhiteListCandidates = (query: SearchForWhiteListCandidatesQuery, enabled: boolean) => {
const { keyword, groupId, resultsPerPage } = query
return useInfiniteQuery({
queryKey: [NAME_SPACE, 'app-whitelist-candidates', keyword, groupId, resultsPerPage],
queryFn: ({ pageParam }) => {
const params = new URLSearchParams()
if (keyword)
params.append('keyword', keyword)
if (groupId)
params.append('groupId', groupId)
if (resultsPerPage)
params.append('resultsPerPage', `${resultsPerPage}`)
params.append('pageNumber', `${pageParam}`)
return get<SearchResults>(`/enterprise/webapp/app/subject/search?${new URLSearchParams(params).toString()}`)
},
initialPageParam: 1,
getNextPageParam: (lastPage) => {
if (lastPage.hasMore)
return lastPage.currPage + 1
return undefined
},
gcTime: 0,
staleTime: 0,
enabled,
})
}
type UpdateAccessModeParams = {
appId: App['id']
subjects?: Pick<Subject, 'subjectId' | 'subjectType'>[]
accessMode: AccessMode
}
export const useUpdateAccessMode = () => {
const queryClient = useQueryClient()
return useMutation({
mutationKey: [NAME_SPACE, 'update-access-mode'],
mutationFn: (params: UpdateAccessModeParams) => {
return post('/enterprise/webapp/app/access-mode', { body: params })
},
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: [NAME_SPACE, 'app-whitelist-subjects'],
})
},
})
}
export const useGetUserCanAccessApp = ({ appId, isInstalledApp = true, enabled }: { appId?: string, isInstalledApp?: boolean, enabled?: boolean }) => {
// useQuery (not useSuspenseQuery) to keep this service hook's call contract
// unchanged from the zustand era: callers should not need a Suspense boundary.
// First-fetch undefined is bridged via `?? false` so the inner queryKey is stable.
const { data: systemFeatures } = useQuery(systemFeaturesQueryOptions())
const webappAuthEnabled = systemFeatures?.webapp_auth.enabled ?? false
return useQuery({
queryKey: [NAME_SPACE, 'user-can-access-app', appId, webappAuthEnabled, isInstalledApp],
queryFn: () => {
if (webappAuthEnabled)
return getUserCanAccess(appId!, isInstalledApp)
else
return { result: true }
},
enabled: enabled !== undefined ? enabled : !!appId,
staleTime: 0,
gcTime: 0,
})
}