Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add dataset edit permissions #13223

Merged
merged 3 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const Item: FC<ItemProps> = ({
config,
onSave,
onRemove,
readonly,
}) => {
const media = useBreakpoints()
const isMobile = media === MediaType.mobile
Expand Down Expand Up @@ -68,26 +69,28 @@ const Item: FC<ItemProps> = ({
<div className='flex items-center h-[18px]'>
<div className='grow text-[13px] font-medium text-gray-800 truncate' title={config.name}>{config.name}</div>
{config.provider === 'external'
? <Badge text={t('dataset.externalTag')}></Badge>
? <Badge text={t('dataset.externalTag') as string} />
: <Badge
text={formatIndexingTechniqueAndMethod(config.indexing_technique, config.retrieval_model_dict?.search_method)}
/>}
</div>
</div>
<div className='hidden rounded-lg group-hover:flex items-center justify-end absolute right-0 top-0 bottom-0 pr-2 w-[124px] bg-gradient-to-r from-white/50 to-white to-50%'>
<div
className='flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer'
onClick={() => setShowSettingsModal(true)}
>
<RiEditLine className='w-4 h-4 text-gray-500' />
</div>
<div
className='group/action flex items-center justify-center w-6 h-6 hover:bg-[#FEE4E2] rounded-md cursor-pointer'
onClick={() => onRemove(config.id)}
>
<RiDeleteBinLine className='w-4 h-4 text-gray-500 group-hover/action:text-[#D92D20]' />
{!readonly && (
<div className='hidden rounded-lg group-hover:flex items-center justify-end absolute right-0 top-0 bottom-0 pr-2 w-[124px] bg-gradient-to-r from-white/50 to-white to-50%'>
<div
className='flex items-center justify-center mr-1 w-6 h-6 hover:bg-black/5 rounded-md cursor-pointer'
onClick={() => setShowSettingsModal(true)}
>
<RiEditLine className='w-4 h-4 text-gray-500' />
</div>
<div
className='group/action flex items-center justify-center w-6 h-6 hover:bg-[#FEE4E2] rounded-md cursor-pointer'
onClick={() => onRemove(config.id)}
>
<RiDeleteBinLine className='w-4 h-4 text-gray-500 group-hover/action:text-[#D92D20]' />
</div>
</div>
</div>
)}
<Drawer isOpen={showSettingsModal} onClose={() => setShowSettingsModal(false)} footer={null} mask={isMobile} panelClassname='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'>
<SettingsModal
currentDataset={config}
Expand Down
22 changes: 20 additions & 2 deletions web/app/components/app/configuration/dataset-config/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import React, { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector'
import produce from 'immer'
Expand All @@ -19,6 +19,8 @@ import {
} from '@/app/components/workflow/nodes/knowledge-retrieval/utils'
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import { ModelTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
import { useSelector as useAppContextSelector } from '@/context/app-context'
import { hasEditPermissionForDataset } from '@/utils/permission'

const Icon = (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
Expand All @@ -29,6 +31,7 @@ const Icon = (

const DatasetConfig: FC = () => {
const { t } = useTranslation()
const userProfile = useAppContextSelector(s => s.userProfile)
const {
mode,
dataSets: dataSet,
Expand Down Expand Up @@ -105,6 +108,20 @@ const DatasetConfig: FC = () => {
setModelConfig(newModelConfig)
}

const formattedDataset = useMemo(() => {
return dataSet.map((item) => {
const datasetConfig = {
createdBy: item.created_by,
partialMemberList: item.partial_member_list as string[],
permission: item.permission,
}
return {
...item,
readonly: !hasEditPermissionForDataset(userProfile?.id as string, datasetConfig),
}
})
}, [dataSet, userProfile?.id])

return (
<FeaturePanel
className='mt-2'
Expand All @@ -122,12 +139,13 @@ const DatasetConfig: FC = () => {
{hasData
? (
<div className='flex flex-wrap mt-1 px-3 pb-3 justify-between'>
{dataSet.map(item => (
{formattedDataset.map(item => (
<CardItem
key={item.id}
config={item}
onRemove={onRemove}
onSave={handleSave}
readonly={item.readonly}
/>
))}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ const DatasetItem: FC<Props> = ({
{
payload.provider === 'external' && <Badge
className='group-hover/dataset-item:hidden shrink-0'
text={t('dataset.externalTag')}
text={t('dataset.externalTag') as string}
/>
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import React, { useCallback, useMemo } from 'react'
import produce from 'immer'
import { useTranslation } from 'react-i18next'
import Item from './dataset-item'
import type { DataSet } from '@/models/datasets'
import { useSelector as useAppContextSelector } from '@/context/app-context'
import { hasEditPermissionForDataset } from '@/utils/permission'

type Props = {
list: DataSet[]
onChange: (list: DataSet[]) => void
Expand All @@ -17,6 +20,7 @@ const DatasetList: FC<Props> = ({
readonly,
}) => {
const { t } = useTranslation()
const userProfile = useAppContextSelector(s => s.userProfile)

const handleRemove = useCallback((index: number) => {
return () => {
Expand All @@ -35,17 +39,32 @@ const DatasetList: FC<Props> = ({
onChange(newList)
}
}, [list, onChange])

const formattedList = useMemo(() => {
return list.map((item) => {
const datasetConfig = {
createdBy: item.created_by,
partialMemberList: item.partial_member_list as string[],
permission: item.permission,
}
return {
...item,
readonly: !hasEditPermissionForDataset(userProfile?.id as string, datasetConfig),
}
})
}, [list, userProfile?.id])

return (
<div className='space-y-1'>
{list.length
? list.map((item, index) => {
{formattedList.length
? formattedList.map((item, index) => {
return (
<Item
key={index}
payload={item}
onRemove={handleRemove(index)}
onChange={handleChange(index)}
readonly={readonly}
readonly={readonly || item.readonly}
/>
)
})
Expand Down
18 changes: 18 additions & 0 deletions web/utils/permission.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { DatasetPermission } from '@/models/datasets'

type DatasetConfig = {
createdBy: string
partialMemberList: string[]
permission: DatasetPermission
}

export const hasEditPermissionForDataset = (userId: string, datasetConfig: DatasetConfig) => {
const { createdBy, partialMemberList, permission } = datasetConfig
if (permission === 'only_me')
crazywoola marked this conversation as resolved.
Show resolved Hide resolved
return userId === createdBy
if (permission === 'all_team_members')
return true
if (permission === 'partial_members')
return partialMemberList.includes(userId)
return false
}
Loading