Perf/web app authrozation (#22524)

This commit is contained in:
NFish
2025-07-17 10:52:10 +08:00
committed by GitHub
parent a3ced1b5a6
commit a324d3942e
35 changed files with 592 additions and 441 deletions

View File

@@ -1,8 +1,9 @@
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { get, post } from './base'
import { getAppAccessMode, getUserCanAccess } from './share'
import { getUserCanAccess } from './share'
import type { AccessControlAccount, AccessControlGroup, AccessMode, Subject } from '@/models/access-control'
import type { App } from '@/types/app'
import { useGlobalPublicStore } from '@/context/global-public-context'
const NAME_SPACE = 'access-control'
@@ -69,25 +70,18 @@ export const useUpdateAccessMode = () => {
})
}
export const useGetAppAccessMode = ({ appId, isInstalledApp = true, enabled }: { appId?: string; isInstalledApp?: boolean; enabled: boolean }) => {
return useQuery({
queryKey: [NAME_SPACE, 'app-access-mode', appId],
queryFn: () => getAppAccessMode(appId!, isInstalledApp),
enabled: !!appId && enabled,
staleTime: 0,
gcTime: 0,
})
}
export const useGetUserCanAccessApp = ({ appId, isInstalledApp = true, enabled }: { appId?: string; isInstalledApp?: boolean; enabled: boolean }) => {
export const useGetUserCanAccessApp = ({ appId, isInstalledApp = true }: { appId?: string; isInstalledApp?: boolean; }) => {
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
return useQuery({
queryKey: [NAME_SPACE, 'user-can-access-app', appId],
queryFn: () => getUserCanAccess(appId!, isInstalledApp),
enabled: !!appId && enabled,
queryFn: () => {
if (systemFeatures.webapp_auth.enabled)
return getUserCanAccess(appId!, isInstalledApp)
else
return { result: true }
},
enabled: !!appId,
staleTime: 0,
gcTime: 0,
initialData: {
result: !enabled,
},
})
}

View File

@@ -413,7 +413,7 @@ export const ssePost = async (
if (data.code === 'unauthorized') {
removeAccessToken()
globalThis.location.reload()
requiredWebSSOLogin()
}
}
})
@@ -507,7 +507,7 @@ export const request = async<T>(url: string, options = {}, otherOptions?: IOther
} = otherOptionsForBaseFetch
if (isPublicAPI && code === 'unauthorized') {
removeAccessToken()
globalThis.location.reload()
requiredWebSSOLogin()
return Promise.reject(err)
}
if (code === 'init_validate_failed' && IS_CE_EDITION && !silent) {

View File

@@ -1,5 +1,6 @@
import { del, get, patch, post } from './base'
import type { App, AppCategory } from '@/models/explore'
import type { AccessMode } from '@/models/access-control'
export const fetchAppList = () => {
return get<{
@@ -39,3 +40,7 @@ export const updatePinStatus = (id: string, isPinned: boolean) => {
export const getToolProviders = () => {
return get('/workspaces/current/tool-providers')
}
export const getAppAccessModeByAppId = (appId: string) => {
return get<{ accessMode: AccessMode }>(`/enterprise/webapp/app/access-mode?appId=${appId}`)
}

View File

@@ -296,13 +296,6 @@ export const fetchAccessToken = async ({ appCode, userId, webAppAccessToken }: {
return get(url, { headers }) as Promise<{ access_token: string }>
}
export const getAppAccessMode = (appId: string, isInstalledApp: boolean) => {
if (isInstalledApp)
return consoleGet<{ accessMode: AccessMode }>(`/enterprise/webapp/app/access-mode?appId=${appId}`)
return get<{ accessMode: AccessMode }>(`/webapp/access-mode?appId=${appId}`)
}
export const getUserCanAccess = (appId: string, isInstalledApp: boolean) => {
if (isInstalledApp)
return consoleGet<{ result: boolean }>(`/enterprise/webapp/permission?appId=${appId}`)

View File

@@ -0,0 +1,81 @@
import { useGlobalPublicStore } from '@/context/global-public-context'
import { AccessMode } from '@/models/access-control'
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
import { fetchInstalledAppList, getAppAccessModeByAppId, uninstallApp, updatePinStatus } from './explore'
import { fetchAppMeta, fetchAppParams } from './share'
const NAME_SPACE = 'explore'
export const useGetInstalledApps = () => {
return useQuery({
queryKey: [NAME_SPACE, 'installedApps'],
queryFn: () => {
return fetchInstalledAppList()
},
})
}
export const useUninstallApp = () => {
const client = useQueryClient()
return useMutation({
mutationKey: [NAME_SPACE, 'uninstallApp'],
mutationFn: (appId: string) => uninstallApp(appId),
onSuccess: () => {
client.invalidateQueries({ queryKey: [NAME_SPACE, 'installedApps'] })
},
})
}
export const useUpdateAppPinStatus = () => {
const client = useQueryClient()
return useMutation({
mutationKey: [NAME_SPACE, 'updateAppPinStatus'],
mutationFn: ({ appId, isPinned }: { appId: string; isPinned: boolean }) => updatePinStatus(appId, isPinned),
onSuccess: () => {
client.invalidateQueries({ queryKey: [NAME_SPACE, 'installedApps'] })
},
})
}
export const useGetInstalledAppAccessModeByAppId = (appId: string | null) => {
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
return useQuery({
queryKey: [NAME_SPACE, 'appAccessMode', appId],
queryFn: () => {
if (systemFeatures.webapp_auth.enabled === false) {
return {
accessMode: AccessMode.PUBLIC,
}
}
if (!appId || appId.length === 0)
return Promise.reject(new Error('App code is required to get access mode'))
return getAppAccessModeByAppId(appId)
},
enabled: !!appId,
})
}
export const useGetInstalledAppParams = (appId: string | null) => {
return useQuery({
queryKey: [NAME_SPACE, 'appParams', appId],
queryFn: () => {
if (!appId || appId.length === 0)
return Promise.reject(new Error('App ID is required to get app params'))
return fetchAppParams(true, appId)
},
enabled: !!appId,
})
}
export const useGetInstalledAppMeta = (appId: string | null) => {
return useQuery({
queryKey: [NAME_SPACE, 'appMeta', appId],
queryFn: () => {
if (!appId || appId.length === 0)
return Promise.reject(new Error('App ID is required to get app meta'))
return fetchAppMeta(true, appId)
},
enabled: !!appId,
})
}

View File

@@ -1,17 +1,52 @@
import { useGlobalPublicStore } from '@/context/global-public-context'
import { AccessMode } from '@/models/access-control'
import { useQuery } from '@tanstack/react-query'
import { getAppAccessModeByAppCode } from './share'
import { fetchAppInfo, fetchAppMeta, fetchAppParams, getAppAccessModeByAppCode } from './share'
const NAME_SPACE = 'webapp'
export const useAppAccessModeByCode = (code: string | null) => {
export const useGetWebAppAccessModeByCode = (code: string | null) => {
const systemFeatures = useGlobalPublicStore(s => s.systemFeatures)
return useQuery({
queryKey: [NAME_SPACE, 'appAccessMode', code],
queryFn: () => {
if (!code)
return null
if (systemFeatures.webapp_auth.enabled === false) {
return {
accessMode: AccessMode.PUBLIC,
}
}
if (!code || code.length === 0)
return Promise.reject(new Error('App code is required to get access mode'))
return getAppAccessModeByAppCode(code)
},
enabled: !!code,
})
}
export const useGetWebAppInfo = () => {
return useQuery({
queryKey: [NAME_SPACE, 'appInfo'],
queryFn: () => {
return fetchAppInfo()
},
})
}
export const useGetWebAppParams = () => {
return useQuery({
queryKey: [NAME_SPACE, 'appParams'],
queryFn: () => {
return fetchAppParams(false)
},
})
}
export const useGetWebAppMeta = () => {
return useQuery({
queryKey: [NAME_SPACE, 'appMeta'],
queryFn: () => {
return fetchAppMeta(false)
},
})
}