mirror of
https://github.com/labring/FastGPT.git
synced 2025-08-05 06:35:39 +00:00
Dataset Permission (#1786)
* feat: dataset controllers feat: dataset schema fix: add missing type to dataset schema Signed-off-by: FinleyGe <m13203533462@163.com> * feat: dataset list api Signed-off-by: FinleyGe <m13203533462@163.com> * chore: all dataset api Signed-off-by: FinleyGe <m13203533462@163.com> * feat: new auth dataset method Signed-off-by: FinleyGe <m13203533462@163.com> * chore: use new auth method in detail, paths. feat: add new param defaultPermission to create api Signed-off-by: FinleyGe <m13203533462@163.com> * chore: app auth params Signed-off-by: FinleyGe <m13203533462@163.com> * chore: use new auth method Signed-off-by: FinleyGe <m13203533462@163.com> * feat: new auth collection and file method Signed-off-by: FinleyGe <m13203533462@163.com> * chore: dataset collection api new auth Signed-off-by: FinleyGe <m13203533462@163.com> * chore: create/*.ts auth Signed-off-by: FinleyGe <m13203533462@163.com> * chore: dataset auth Signed-off-by: FinleyGe <m13203533462@163.com> * fix: import paths Signed-off-by: FinleyGe <m13203533462@163.com> * feat: dataset collaborator Signed-off-by: FinleyGe <m13203533462@163.com> * chore: dataset frontend feat: dataset list frontend feat: dataset detail Signed-off-by: FinleyGe <m13203533462@163.com> * feat: finish the dataset permission fix: ts errors Signed-off-by: FinleyGe <m13203533462@163.com> * fix: empty response of collection api Signed-off-by: FinleyGe <m13203533462@163.com> * chore: adjust the code * chore: adjust the code * chore: i18n * fix: ts error * fix: fe CollectionCard permission --------- Signed-off-by: FinleyGe <m13203533462@163.com>
This commit is contained in:
@@ -26,8 +26,6 @@ import EditFolderModal, { useEditFolder } from '../../../component/EditFolderMod
|
||||
import { TabEnum } from '../../index';
|
||||
import ParentPath from '@/components/common/ParentPaths';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
|
||||
import { ImportDataSourceEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
@@ -40,7 +38,6 @@ const Header = ({}: {}) => {
|
||||
const { t } = useTranslation();
|
||||
const theme = useTheme();
|
||||
const { setLoading } = useSystemStore();
|
||||
const { userInfo } = useUserStore();
|
||||
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
||||
|
||||
const router = useRouter();
|
||||
@@ -189,7 +186,7 @@ const Header = ({}: {}) => {
|
||||
)}
|
||||
|
||||
{/* diff collection button */}
|
||||
{userInfo?.team?.role !== TeamMemberRoleEnum.visitor && (
|
||||
{datasetDetail.permission.hasWritePer && (
|
||||
<>
|
||||
{datasetDetail?.type === DatasetTypeEnum.dataset && (
|
||||
<MyMenu
|
||||
|
@@ -37,8 +37,6 @@ import { useDrag } from '@/web/common/hooks/useDrag';
|
||||
import SelectCollections from '@/web/core/dataset/components/SelectCollections';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import { DatasetCollectionSyncResultEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import MyBox from '@fastgpt/web/components/common/MyBox';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
@@ -53,7 +51,6 @@ const CollectionCard = () => {
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const { t } = useTranslation();
|
||||
const { userInfo } = useUserStore();
|
||||
const { datasetDetail, loadDatasetDetail } = useContextSelector(DatasetPageContext, (v) => v);
|
||||
|
||||
const { openConfirm: openDeleteConfirm, ConfirmModal: ConfirmDeleteModal } = useConfirm({
|
||||
@@ -213,7 +210,7 @@ const CollectionCard = () => {
|
||||
}
|
||||
bg={dragTargetId === collection._id ? 'primary.100' : ''}
|
||||
userSelect={'none'}
|
||||
onDragStart={(e) => {
|
||||
onDragStart={() => {
|
||||
setDragStartId(collection._id);
|
||||
}}
|
||||
onDragOver={(e) => {
|
||||
@@ -296,7 +293,7 @@ const CollectionCard = () => {
|
||||
</Box>
|
||||
</Td>
|
||||
<Td onClick={(e) => e.stopPropagation()}>
|
||||
{collection.canWrite && userInfo?.team?.role !== TeamMemberRoleEnum.visitor && (
|
||||
{collection.permission.hasWritePer && (
|
||||
<MyMenu
|
||||
width={100}
|
||||
offset={[-70, 5]}
|
||||
|
@@ -35,8 +35,6 @@ import InputDataModal from '../components/InputDataModal';
|
||||
import RawSourceBox from '@/components/core/dataset/RawSourceBox';
|
||||
import type { DatasetDataListItemType } from '@/global/core/dataset/type.d';
|
||||
import { TabEnum } from '..';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { DatasetCollectionTypeMap, TrainingTypeMap } from '@fastgpt/global/core/dataset/constants';
|
||||
import { formatTime2YMDHM } from '@fastgpt/global/common/string/time';
|
||||
@@ -47,18 +45,21 @@ import { usePagination } from '@fastgpt/web/hooks/usePagination';
|
||||
import { getCollectionSourceData } from '@fastgpt/global/core/dataset/collection/utils';
|
||||
import { useI18n } from '@/web/context/I18n';
|
||||
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
|
||||
import { DatasetPageContext } from '@/web/core/dataset/context/datasetPageContext';
|
||||
import { useContextSelector } from 'use-context-selector';
|
||||
|
||||
const DataCard = () => {
|
||||
const BoxRef = useRef<HTMLDivElement>(null);
|
||||
const theme = useTheme();
|
||||
const lastSearch = useRef('');
|
||||
const router = useRouter();
|
||||
const { userInfo } = useUserStore();
|
||||
const { isPc } = useSystemStore();
|
||||
const { collectionId = '', datasetId } = router.query as {
|
||||
collectionId: string;
|
||||
datasetId: string;
|
||||
};
|
||||
const datasetDetail = useContextSelector(DatasetPageContext, (v) => v.datasetDetail);
|
||||
|
||||
const { Loading, setIsLoading } = useLoading({ defaultLoading: true });
|
||||
const { t } = useTranslation();
|
||||
const { datasetT } = useI18n();
|
||||
@@ -101,7 +102,7 @@ const DataCard = () => {
|
||||
getData(1);
|
||||
lastSearch.current = searchText;
|
||||
}, 300),
|
||||
[]
|
||||
[searchText]
|
||||
);
|
||||
|
||||
// get file info
|
||||
@@ -119,10 +120,7 @@ const DataCard = () => {
|
||||
}
|
||||
);
|
||||
|
||||
const canWrite = useMemo(
|
||||
() => userInfo?.team?.role !== TeamMemberRoleEnum.visitor && !!collection?.canWrite,
|
||||
[collection?.canWrite, userInfo?.team?.role]
|
||||
);
|
||||
const canWrite = useMemo(() => datasetDetail.permission.hasWritePer, [datasetDetail]);
|
||||
|
||||
const metadataList = useMemo(() => {
|
||||
if (!collection) return [];
|
||||
@@ -291,7 +289,7 @@ const DataCard = () => {
|
||||
gridTemplateColumns={['1fr', 'repeat(2,1fr)', 'repeat(3,1fr)', 'repeat(4,1fr)']}
|
||||
gridGap={4}
|
||||
>
|
||||
{datasetDataList.map((item, index) => (
|
||||
{datasetDataList.map((item) => (
|
||||
<Card
|
||||
key={item._id}
|
||||
cursor={'pointer'}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { Box, Flex, Button, IconButton, Input, Textarea, HStack } from '@chakra-ui/react';
|
||||
import { DeleteIcon } from '@chakra-ui/icons';
|
||||
@@ -11,7 +11,6 @@ import type { DatasetItemType } from '@fastgpt/global/core/dataset/type.d';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import PermissionRadio from '@/components/support/permission/Radio';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import { useRequest } from '@fastgpt/web/hooks/useRequest';
|
||||
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';
|
||||
@@ -25,10 +24,21 @@ import MyDivider from '@fastgpt/web/components/common/MyDivider/index';
|
||||
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
|
||||
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
|
||||
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
|
||||
import DefaultPermissionList from '@/components/support/permission/DefaultPerList';
|
||||
import {
|
||||
DatasetDefaultPermission,
|
||||
DatasetPermissionList
|
||||
} from '@fastgpt/global/support/permission/dataset/constant';
|
||||
import MemberManager from '../../component/MemberManager';
|
||||
import {
|
||||
getCollaboratorList,
|
||||
postUpdateDatasetCollaborators,
|
||||
deleteDatasetCollaborators
|
||||
} from '@/web/core/dataset/api/collaborator';
|
||||
|
||||
const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
const { t } = useTranslation();
|
||||
const { datasetT } = useI18n();
|
||||
const { datasetT, commonT } = useI18n();
|
||||
const { datasetDetail, loadDatasetDetail, updateDataset, rebuildingCount, trainingCount } =
|
||||
useContextSelector(DatasetPageContext, (v) => v);
|
||||
|
||||
@@ -44,7 +54,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
const avatar = watch('avatar');
|
||||
const vectorModel = watch('vectorModel');
|
||||
const agentModel = watch('agentModel');
|
||||
const permission = watch('permission');
|
||||
const defaultPermission = watch('defaultPermission');
|
||||
|
||||
const { datasetModelList, vectorModelList } = useSystemStore();
|
||||
|
||||
@@ -233,20 +243,46 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
<FormLabel flex={['0 0 90px', '0 0 160px']}>{t('common.Intro')}</FormLabel>
|
||||
<Textarea flex={[1, '0 0 320px']} {...register('intro')} placeholder={t('common.Intro')} />
|
||||
</Flex>
|
||||
{datasetDetail.isOwner && (
|
||||
<Flex mt={5} alignItems={'center'} w={'100%'} flexWrap={'wrap'}>
|
||||
<FormLabel flex={['0 0 90px', '0 0 160px']} w={0}>
|
||||
{t('user.Permission')}
|
||||
</FormLabel>
|
||||
<Box>
|
||||
<PermissionRadio
|
||||
value={permission}
|
||||
onChange={(e) => {
|
||||
setValue('permission', e);
|
||||
}}
|
||||
|
||||
{datasetDetail.permission.hasManagePer && (
|
||||
<>
|
||||
<Flex mt={5} alignItems={'center'} w={'100%'} flexWrap={'wrap'} maxW="500px">
|
||||
<FormLabel flex={['0 0 90px', '0 0 160px']} w={0}>
|
||||
{commonT('permission.Default permission')}
|
||||
</FormLabel>
|
||||
<DefaultPermissionList
|
||||
w="320px"
|
||||
per={defaultPermission}
|
||||
defaultPer={DatasetDefaultPermission}
|
||||
onChange={(v) => setValue('defaultPermission', v)}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</Flex>
|
||||
|
||||
<Flex mt={5} alignItems={'center'} w={'100%'} flexWrap={'wrap'} maxW="500px">
|
||||
<FormLabel flex={['0 0 90px', '0 0 160px']} w={0}>
|
||||
{commonT('permission.Collaborator')}
|
||||
</FormLabel>
|
||||
<Box flex={1}>
|
||||
<MemberManager
|
||||
managePer={{
|
||||
permission: datasetDetail.permission,
|
||||
onGetCollaboratorList: () => getCollaboratorList(datasetId),
|
||||
permissionList: DatasetPermissionList,
|
||||
onUpdateCollaborators: (body) =>
|
||||
postUpdateDatasetCollaborators({
|
||||
...body,
|
||||
datasetId
|
||||
}),
|
||||
onDelOneCollaborator: (tmbId) =>
|
||||
deleteDatasetCollaborators({
|
||||
datasetId,
|
||||
tmbId
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
</>
|
||||
)}
|
||||
|
||||
<Flex mt={5} w={'100%'} alignItems={'flex-end'}>
|
||||
@@ -259,7 +295,7 @@ const Info = ({ datasetId }: { datasetId: string }) => {
|
||||
>
|
||||
{t('common.Save')}
|
||||
</Button>
|
||||
{datasetDetail.isOwner && (
|
||||
{datasetDetail.permission.isOwner && (
|
||||
<IconButton
|
||||
isLoading={btnLoading}
|
||||
icon={<DeleteIcon />}
|
||||
|
@@ -365,9 +365,11 @@ const InputDataModal = ({
|
||||
<Button variant={'whiteBase'} mr={3} onClick={onClose}>
|
||||
{t('common.Close')}
|
||||
</Button>
|
||||
<MyTooltip label={collection.canWrite ? '' : t('dataset.data.Can not edit')}>
|
||||
<MyTooltip
|
||||
label={collection.permission.hasWritePer ? '' : t('dataset.data.Can not edit')}
|
||||
>
|
||||
<Button
|
||||
isDisabled={!collection.canWrite}
|
||||
isDisabled={!collection.permission.hasWritePer}
|
||||
// @ts-ignore
|
||||
onClick={handleSubmit(dataId ? onUpdateData : sureImportData)}
|
||||
>
|
||||
|
@@ -1,7 +1,5 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import { Box, Flex, IconButton, useTheme, Progress } from '@chakra-ui/react';
|
||||
import { useSystemStore } from '@/web/common/system/useSystemStore';
|
||||
import Avatar from '@/components/Avatar';
|
||||
@@ -29,7 +27,6 @@ const Slider = ({ currentTab }: { currentTab: TabEnum }) => {
|
||||
const { datasetT } = useI18n();
|
||||
const router = useRouter();
|
||||
const query = router.query;
|
||||
const { userInfo } = useUserStore();
|
||||
const { isPc } = useSystemStore();
|
||||
const { datasetDetail, vectorTrainingMap, agentTrainingMap, rebuildingCount } =
|
||||
useContextSelector(DatasetPageContext, (v) => v);
|
||||
@@ -41,7 +38,7 @@ const Slider = ({ currentTab }: { currentTab: TabEnum }) => {
|
||||
icon: 'common/overviewLight'
|
||||
},
|
||||
{ label: t('core.dataset.test.Search Test'), id: TabEnum.test, icon: 'kbTest' },
|
||||
...(userInfo?.team.permission.hasManagePer || datasetDetail.isOwner
|
||||
...(datasetDetail.permission.hasManagePer
|
||||
? [{ label: t('common.Config'), id: TabEnum.info, icon: 'common/settingLight' }]
|
||||
: [])
|
||||
];
|
||||
|
Reference in New Issue
Block a user