import {
memo,
useCallback,
useEffect,
useMemo,
useState,
} from 'react'
import type { ReactNode } from 'react'
import {
RiAddLine,
RiArrowDownSLine,
RiCheckLine,
RiEqualizer2Line,
RiKey2Line,
RiUserStarLine,
} from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import {
PortalToFollowElem,
PortalToFollowElemContent,
PortalToFollowElemTrigger,
} from '@/app/components/base/portal-to-follow-elem'
import { SimpleSelect } from '@/app/components/base/select'
import Authorize from './authorize'
import Authorized from './authorized'
import AddApiKeyButton from './authorize/add-api-key-button'
import AddOAuthButton from './authorize/add-oauth-button'
import Item from './authorized/item'
import type { PluginPayload } from './types'
import { usePluginAuth } from './hooks/use-plugin-auth'
import Switch from '@/app/components/base/switch'
import cn from '@/utils/classnames'
type PluginAuthProps = {
pluginPayload: PluginPayload
children?: React.ReactNode
className?: string
showConnectGuide?: boolean
endUserCredentialEnabled?: boolean
endUserCredentialType?: string
onEndUserCredentialTypeChange?: (type: string) => void
onEndUserCredentialChange?: (enabled: boolean) => void
}
const PluginAuth = ({
pluginPayload,
children,
className,
showConnectGuide,
endUserCredentialEnabled,
endUserCredentialType,
onEndUserCredentialTypeChange,
onEndUserCredentialChange,
}: PluginAuthProps) => {
const { t } = useTranslation()
const {
isAuthorized,
canOAuth,
canApiKey,
credentials,
disabled,
invalidPluginCredentialInfo,
notAllowCustomCredential,
} = usePluginAuth(pluginPayload, !!pluginPayload.provider)
const shouldShowGuide = !!showConnectGuide
const [showCredentialPanel, setShowCredentialPanel] = useState(false)
const [showAddMenu, setShowAddMenu] = useState(false)
const configuredDisabled = !!endUserCredentialEnabled
const availableEndUserTypes = useMemo(() => {
const list: { value: string; label: string; icon: ReactNode }[] = []
if (canOAuth) {
list.push({
value: 'oauth2',
label: t('plugin.auth.endUserCredentials.optionOAuth'),
icon: ,
})
}
if (canApiKey) {
list.push({
value: 'api-key',
label: t('plugin.auth.endUserCredentials.optionApiKey'),
icon: ,
})
}
return list
}, [canOAuth, canApiKey, t])
const endUserCredentialLabel = useMemo(() => {
const found = availableEndUserTypes.find(item => item.value === endUserCredentialType)
return found?.label || availableEndUserTypes[0]?.label || '-'
}, [availableEndUserTypes, endUserCredentialType])
useEffect(() => {
if (!endUserCredentialEnabled)
return
if (!availableEndUserTypes.length)
return
const isValid = availableEndUserTypes.some(item => item.value === endUserCredentialType)
if (!isValid)
onEndUserCredentialTypeChange?.(availableEndUserTypes[0].value)
}, [endUserCredentialEnabled, endUserCredentialType, availableEndUserTypes, onEndUserCredentialTypeChange])
const handleSelectEndUserType = useCallback((value: string) => {
onEndUserCredentialTypeChange?.(value)
}, [onEndUserCredentialTypeChange])
const containerClassName = useMemo(() => {
if (showConnectGuide)
return className
return !isAuthorized ? className : undefined
}, [isAuthorized, className, showConnectGuide])
useEffect(() => {
if (isAuthorized)
setShowCredentialPanel(false)
}, [isAuthorized])
const credentialList = useMemo(() => {
return (
{
credentials.length > 0
? (
{credentials.map(credential => (
))}
)
: null
}
)
}, [credentials, t])
const endUserSwitch = (
{t('plugin.auth.endUserCredentials.title')}
{t('plugin.auth.endUserCredentials.desc')}
{
endUserCredentialEnabled && availableEndUserTypes.length > 0 && (
{t('plugin.auth.endUserCredentials.typeLabel')}
({
value: item.value,
name: item.label,
icon: item.icon,
}))}
defaultValue={endUserCredentialType || availableEndUserTypes[0]?.value}
disabled={disabled}
onSelect={item => handleSelectEndUserType(item.value as string)}
renderTrigger={(value, open) => (
)}
renderOption={({ item, selected }) => (
{item.icon}
{item.name}
{selected &&
}
)}
optionWrapClassName='p-1'
optionClassName='px-3 py-2 rounded-lg'
hideChecked
/>
)
}
)
return (
{
shouldShowGuide && (
{t('plugin.auth.configuredCredentials.title')}
{t('plugin.auth.configuredCredentials.desc')}
{
canOAuth && (
{
setShowAddMenu(false)
invalidPluginCredentialInfo()
}}
/>
)
}
{
canApiKey && (
{
setShowAddMenu(false)
invalidPluginCredentialInfo()
}}
/>
)
}
{credentialList}
{
credentials.length === 0 && (
)
}
{endUserSwitch}
)
}
{
!shouldShowGuide && !isAuthorized && (
)
}
{
isAuthorized && !children && (
)
}
{
isAuthorized && children
}
)
}
export default memo(PluginAuth)