feat: permission and security fixes (#5266)
This commit is contained in:
@@ -58,7 +58,7 @@ const DataSourceNotion: FC<Props> = ({
|
||||
type={DataSourceType.notion}
|
||||
isConfigured={connected}
|
||||
onConfigure={handleConnectNotion}
|
||||
readonly={!isCurrentWorkspaceManager}
|
||||
readOnly={!isCurrentWorkspaceManager}
|
||||
isSupportList
|
||||
configuredList={workspaces.map(workspace => ({
|
||||
id: workspace.id,
|
||||
|
@@ -11,7 +11,7 @@ import Button from '@/app/components/base/button'
|
||||
import type { FirecrawlConfig } from '@/models/common'
|
||||
import Field from '@/app/components/datasets/create/website/firecrawl/base/field'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { createFirecrawlApiKey } from '@/service/datasets'
|
||||
import { createDataSourceApiKeyBinding } from '@/service/datasets'
|
||||
import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general'
|
||||
type Props = {
|
||||
onCancel: () => void
|
||||
@@ -76,7 +76,7 @@ const ConfigFirecrawlModal: FC<Props> = ({
|
||||
}
|
||||
try {
|
||||
setIsSaving(true)
|
||||
await createFirecrawlApiKey(postData)
|
||||
await createDataSourceApiKeyBinding(postData)
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('common.api.success'),
|
||||
|
@@ -7,15 +7,15 @@ import cn from 'classnames'
|
||||
import Panel from '../panel'
|
||||
import { DataSourceType } from '../panel/types'
|
||||
import ConfigFirecrawlModal from './config-firecrawl-modal'
|
||||
import { fetchFirecrawlApiKey, removeFirecrawlApiKey } from '@/service/datasets'
|
||||
import { fetchDataSources, removeDataSourceApiKeyBinding } from '@/service/datasets'
|
||||
|
||||
import type {
|
||||
DataSourceWebsiteItem,
|
||||
DataSourceItem,
|
||||
} from '@/models/common'
|
||||
import { useAppContext } from '@/context/app-context'
|
||||
|
||||
import {
|
||||
WebsiteProvider,
|
||||
DataSourceProvider,
|
||||
} from '@/models/common'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
|
||||
@@ -24,11 +24,11 @@ type Props = {}
|
||||
const DataSourceWebsite: FC<Props> = () => {
|
||||
const { t } = useTranslation()
|
||||
const { isCurrentWorkspaceManager } = useAppContext()
|
||||
const [list, setList] = useState<DataSourceWebsiteItem[]>([])
|
||||
const [sources, setSources] = useState<DataSourceItem[]>([])
|
||||
const checkSetApiKey = useCallback(async () => {
|
||||
const res = await fetchFirecrawlApiKey() as any
|
||||
const list = res.settings.filter((item: DataSourceWebsiteItem) => item.provider === WebsiteProvider.fireCrawl && !item.disabled)
|
||||
setList(list)
|
||||
const res = await fetchDataSources() as any
|
||||
const list = res.sources
|
||||
setSources(list)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -46,23 +46,33 @@ const DataSourceWebsite: FC<Props> = () => {
|
||||
hideConfig()
|
||||
}, [checkSetApiKey, hideConfig])
|
||||
|
||||
const handleRemove = useCallback(async () => {
|
||||
await removeFirecrawlApiKey(list[0].id)
|
||||
setList([])
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('common.api.remove'),
|
||||
})
|
||||
}, [list, t])
|
||||
const getIdByProvider = (provider: string): string | undefined => {
|
||||
const source = sources.find(item => item.provider === provider)
|
||||
return source?.id
|
||||
}
|
||||
|
||||
const handleRemove = useCallback((provider: string) => {
|
||||
return async () => {
|
||||
const dataSourceId = getIdByProvider(provider)
|
||||
if (dataSourceId) {
|
||||
await removeDataSourceApiKeyBinding(dataSourceId)
|
||||
setSources(sources.filter(item => item.provider !== provider))
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('common.api.remove'),
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [sources, t])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Panel
|
||||
type={DataSourceType.website}
|
||||
isConfigured={list.length > 0}
|
||||
isConfigured={sources.length > 0}
|
||||
onConfigure={showConfig}
|
||||
readonly={!isCurrentWorkspaceManager}
|
||||
configuredList={list.map(item => ({
|
||||
readOnly={!isCurrentWorkspaceManager}
|
||||
configuredList={sources.map(item => ({
|
||||
id: item.id,
|
||||
logo: ({ className }: { className: string }) => (
|
||||
<div className={cn(className, 'flex items-center justify-center w-5 h-5 bg-white border border-gray-100 text-xs font-medium text-gray-500 rounded ml-3')}>🔥</div>
|
||||
@@ -70,7 +80,7 @@ const DataSourceWebsite: FC<Props> = () => {
|
||||
name: 'FireCrawl',
|
||||
isActive: true,
|
||||
}))}
|
||||
onRemove={handleRemove}
|
||||
onRemove={handleRemove(DataSourceProvider.fireCrawl)}
|
||||
/>
|
||||
{isShowConfig && (
|
||||
<ConfigFirecrawlModal onSaved={handleAdded} onCancel={hideConfig} />
|
||||
|
@@ -26,6 +26,7 @@ type Props = {
|
||||
notionActions?: {
|
||||
onChangeAuthorizedPage: () => void
|
||||
}
|
||||
readOnly: boolean
|
||||
}
|
||||
|
||||
const ConfigItem: FC<Props> = ({
|
||||
@@ -33,6 +34,7 @@ const ConfigItem: FC<Props> = ({
|
||||
payload,
|
||||
onRemove,
|
||||
notionActions,
|
||||
readOnly,
|
||||
}) => {
|
||||
const { t } = useTranslation()
|
||||
const isNotion = type === DataSourceType.notion
|
||||
@@ -65,7 +67,7 @@ const ConfigItem: FC<Props> = ({
|
||||
)}
|
||||
|
||||
{
|
||||
isWebsite && (
|
||||
isWebsite && !readOnly && (
|
||||
<div className='p-2 text-gray-500 cursor-pointer rounded-md hover:bg-black/5' onClick={onRemove} >
|
||||
<Trash03 className='w-4 h-4 ' />
|
||||
</div>
|
||||
|
@@ -14,7 +14,7 @@ type Props = {
|
||||
type: DataSourceType
|
||||
isConfigured: boolean
|
||||
onConfigure: () => void
|
||||
readonly: boolean
|
||||
readOnly: boolean
|
||||
isSupportList?: boolean
|
||||
configuredList: ConfigItemType[]
|
||||
onRemove: () => void
|
||||
@@ -27,7 +27,7 @@ const Panel: FC<Props> = ({
|
||||
type,
|
||||
isConfigured,
|
||||
onConfigure,
|
||||
readonly,
|
||||
readOnly,
|
||||
configuredList,
|
||||
isSupportList,
|
||||
onRemove,
|
||||
@@ -67,7 +67,7 @@ const Panel: FC<Props> = ({
|
||||
className={
|
||||
`flex items-center ml-3 px-3 h-7 bg-white border border-gray-200
|
||||
rounded-md text-xs font-medium text-gray-700
|
||||
${!readonly ? 'cursor-pointer' : 'grayscale opacity-50 cursor-default'}`
|
||||
${!readOnly ? 'cursor-pointer' : 'grayscale opacity-50 cursor-default'}`
|
||||
}
|
||||
onClick={onConfigure}
|
||||
>
|
||||
@@ -79,7 +79,7 @@ const Panel: FC<Props> = ({
|
||||
{isSupportList && <div
|
||||
className={
|
||||
`flex items-center px-3 py-1 min-h-7 bg-white border-[0.5px] border-gray-200 text-xs font-medium text-primary-600 rounded-md
|
||||
${!readonly ? 'cursor-pointer' : 'grayscale opacity-50 cursor-default'}`
|
||||
${!readOnly ? 'cursor-pointer' : 'grayscale opacity-50 cursor-default'}`
|
||||
}
|
||||
onClick={onConfigure}
|
||||
>
|
||||
@@ -96,10 +96,10 @@ const Panel: FC<Props> = ({
|
||||
<div
|
||||
className={
|
||||
`flex items-center ml-3 px-3 h-7 bg-white border border-gray-200
|
||||
rounded-md text-xs font-medium text-gray-700
|
||||
${!readonly ? 'cursor-pointer' : 'grayscale opacity-50 cursor-default'}`
|
||||
rounded-md text-xs font-medium text-gray-700
|
||||
${!readOnly ? 'cursor-pointer' : 'grayscale opacity-50 cursor-default'}`
|
||||
}
|
||||
onClick={onConfigure}
|
||||
onClick={!readOnly ? onConfigure : undefined}
|
||||
>
|
||||
{t('common.dataSource.configure')}
|
||||
</div>
|
||||
@@ -108,28 +108,28 @@ const Panel: FC<Props> = ({
|
||||
</div>
|
||||
{
|
||||
isConfigured && (
|
||||
<div className='flex items-center px-3 h-[18px]'>
|
||||
<div className='text-xs font-medium text-gray-500'>
|
||||
{isNotion ? t('common.dataSource.notion.connectedWorkspace') : t('common.dataSource.website.configuredCrawlers')}
|
||||
<>
|
||||
<div className='flex items-center px-3 h-[18px]'>
|
||||
<div className='text-xs font-medium text-gray-500'>
|
||||
{isNotion ? t('common.dataSource.notion.connectedWorkspace') : t('common.dataSource.website.configuredCrawlers')}
|
||||
</div>
|
||||
<div className='grow ml-3 border-t border-t-gray-100' />
|
||||
</div>
|
||||
<div className='grow ml-3 border-t border-t-gray-100' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
{
|
||||
isConfigured && (
|
||||
<div className='px-3 pt-2 pb-3'>
|
||||
{
|
||||
configuredList.map(item => (
|
||||
<ConfigItem
|
||||
key={item.id}
|
||||
type={type}
|
||||
payload={item}
|
||||
onRemove={onRemove}
|
||||
notionActions={notionActions} />
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div className='px-3 pt-2 pb-3'>
|
||||
{
|
||||
configuredList.map(item => (
|
||||
<ConfigItem
|
||||
key={item.id}
|
||||
type={type}
|
||||
payload={item}
|
||||
onRemove={onRemove}
|
||||
notionActions={notionActions}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user