fix(oauth): align custom binding response fields in frontend (#6818)
* fix(oauth): align custom binding response fields in frontend * fix(oauth): restore custom access policy guidance
This commit is contained in:
@@ -18,6 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import type { PermissionCatalog } from '@/lib/admin-permissions'
|
||||
import { api } from '@/lib/api'
|
||||
import type { CustomOAuthBinding } from '@/lib/oauth'
|
||||
|
||||
import type {
|
||||
User,
|
||||
@@ -178,19 +179,12 @@ export async function getPermissionCatalog(): Promise<PermissionCatalog> {
|
||||
// Admin Binding Management APIs
|
||||
// ============================================================================
|
||||
|
||||
export interface OAuthBinding {
|
||||
provider_id: string
|
||||
provider_name: string
|
||||
user_id?: number
|
||||
external_id?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user's custom OAuth bindings (admin)
|
||||
*/
|
||||
export async function getUserOAuthBindings(
|
||||
userId: number
|
||||
): Promise<ApiResponse<OAuthBinding[]>> {
|
||||
): Promise<ApiResponse<CustomOAuthBinding[]>> {
|
||||
const res = await api.get(`/api/user/${userId}/oauth/bindings`)
|
||||
return res.data
|
||||
}
|
||||
@@ -211,7 +205,7 @@ export async function adminClearUserBinding(
|
||||
*/
|
||||
export async function adminUnbindCustomOAuth(
|
||||
userId: number,
|
||||
providerId: string
|
||||
providerId: number
|
||||
): Promise<ApiResponse> {
|
||||
const res = await api.delete(
|
||||
`/api/user/${userId}/oauth/bindings/${providerId}`
|
||||
|
||||
@@ -45,13 +45,13 @@ import {
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip'
|
||||
import { api } from '@/lib/api'
|
||||
import { indexCustomOAuthBindings, type CustomOAuthBinding } from '@/lib/oauth'
|
||||
|
||||
import {
|
||||
getUser,
|
||||
getUserOAuthBindings,
|
||||
adminClearUserBinding,
|
||||
adminUnbindCustomOAuth,
|
||||
type OAuthBinding,
|
||||
} from '../../api'
|
||||
import type { User } from '../../types'
|
||||
|
||||
@@ -68,7 +68,7 @@ interface BindingItem {
|
||||
icon: React.ReactNode
|
||||
value: string
|
||||
type: 'builtin' | 'custom'
|
||||
providerId?: string
|
||||
providerId?: number
|
||||
isBound: boolean
|
||||
isEnabled: boolean
|
||||
}
|
||||
@@ -81,7 +81,7 @@ interface StatusInfo {
|
||||
telegram_oauth?: boolean
|
||||
linuxdo_oauth?: boolean
|
||||
custom_oauth_providers?: Array<{
|
||||
id: string
|
||||
id: number
|
||||
name: string
|
||||
icon?: string
|
||||
}>
|
||||
@@ -162,7 +162,7 @@ function CustomProviderIcon(props: { iconUrl?: string }) {
|
||||
export function UserBindingDialog(props: Props) {
|
||||
const { t } = useTranslation()
|
||||
const [user, setUser] = useState<User | null>(null)
|
||||
const [oauthBindings, setOauthBindings] = useState<OAuthBinding[]>([])
|
||||
const [oauthBindings, setOauthBindings] = useState<CustomOAuthBinding[]>([])
|
||||
const [statusInfo, setStatusInfo] = useState<StatusInfo>({})
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [showBoundOnly, setShowBoundOnly] = useState(true)
|
||||
@@ -191,7 +191,7 @@ export function UserBindingDialog(props: Props) {
|
||||
setUser(userRes.data)
|
||||
}
|
||||
if (oauthRes.success && oauthRes.data) {
|
||||
setOauthBindings(oauthRes.data as OAuthBinding[])
|
||||
setOauthBindings(oauthRes.data)
|
||||
}
|
||||
if (statusRes.success && statusRes.data) {
|
||||
setStatusInfo(statusRes.data as StatusInfo)
|
||||
@@ -236,37 +236,35 @@ export function UserBindingDialog(props: Props) {
|
||||
})
|
||||
}
|
||||
|
||||
const oauthBindingMap = new Map(
|
||||
oauthBindings.map((b) => [String(b.provider_id), b])
|
||||
)
|
||||
const oauthBindingMap = indexCustomOAuthBindings(oauthBindings)
|
||||
|
||||
const customProviders = statusInfo.custom_oauth_providers || []
|
||||
const seenProviderIds = new Set<string>()
|
||||
const seenProviderIds = new Set<number>()
|
||||
|
||||
for (const provider of customProviders) {
|
||||
seenProviderIds.add(String(provider.id))
|
||||
const binding = oauthBindingMap.get(String(provider.id))
|
||||
seenProviderIds.add(provider.id)
|
||||
const binding = oauthBindingMap.get(provider.id)
|
||||
items.push({
|
||||
key: `oauth_${provider.id}`,
|
||||
label: provider.name || provider.id,
|
||||
label: provider.name || String(provider.id),
|
||||
icon: <CustomProviderIcon iconUrl={provider.icon} />,
|
||||
value: binding?.external_id || '',
|
||||
value: binding?.provider_user_id || '',
|
||||
type: 'custom',
|
||||
providerId: String(provider.id),
|
||||
providerId: provider.id,
|
||||
isBound: !!binding,
|
||||
isEnabled: true,
|
||||
})
|
||||
}
|
||||
|
||||
for (const binding of oauthBindings) {
|
||||
if (!seenProviderIds.has(String(binding.provider_id))) {
|
||||
if (!seenProviderIds.has(binding.provider_id)) {
|
||||
items.push({
|
||||
key: `oauth_${binding.provider_id}`,
|
||||
label: binding.provider_name || binding.provider_id,
|
||||
label: binding.provider_name || String(binding.provider_id),
|
||||
icon: <Link2 className='h-4 w-4' />,
|
||||
value: binding.external_id || '-',
|
||||
value: binding.provider_user_id || '-',
|
||||
type: 'custom',
|
||||
providerId: String(binding.provider_id),
|
||||
providerId: binding.provider_id,
|
||||
isBound: true,
|
||||
isEnabled: false,
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user