* add audit

* update audit

* update audit
This commit is contained in:
gggaaallleee
2025-06-03 21:28:26 +08:00
committed by GitHub
parent b974574157
commit 9fb5d05865
47 changed files with 1564 additions and 175 deletions

View File

@@ -26,6 +26,7 @@ import MultipleSelect, {
} from '@fastgpt/web/components/common/MySelect/MultipleSelect';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { getTeamMembers } from '@/web/support/user/team/api';
import { createMetadataProcessorMap, type MetadataProcessor } from './processors';
function OperationLogTable({ Tabs }: { Tabs: React.ReactNode }) {
const { t } = useTranslation();
@@ -58,6 +59,14 @@ function OperationLogTable({ Tabs }: { Tabs: React.ReactNode }) {
[t]
);
const processMetadataByEvent = useMemo(() => {
const metadataProcessorMap = createMetadataProcessorMap();
return (event: string, metadata: any) => {
const processor = metadataProcessorMap[event as OperationLogEventEnum];
return processor ? processor(metadata, t) : metadata;
};
}, [t]);
const {
data: operationLogs = [],
isLoading: loadingLogs,
@@ -159,17 +168,7 @@ function OperationLogTable({ Tabs }: { Tabs: React.ReactNode }) {
<Tbody>
{operationLogs?.map((log) => {
const i18nData = operationLogMap[log.event];
const metadata = { ...log.metadata };
if (log.event === OperationLogEventEnum.ASSIGN_PERMISSION) {
const permissionValue = parseInt(metadata.permission, 10);
const permission = new TeamPermission({ per: permissionValue });
metadata.appCreate = permission.hasAppCreatePer ? '✔' : '✘';
metadata.datasetCreate = permission.hasDatasetCreatePer ? '✔' : '✘';
metadata.apiKeyCreate = permission.hasApikeyCreatePer ? '✔' : '✘';
metadata.manage = permission.hasManagePer ? '✔' : '✘';
}
const metadata = processMetadataByEvent(log.event, { ...log.metadata });
return i18nData ? (
<Tr key={log._id} overflow={'unset'}>

View File

@@ -0,0 +1,17 @@
import { AppPermission } from '@fastgpt/global/support/permission/app/controller';
import { createSpecialProcessor } from './commonProcessor';
export const processUpdateAppCollaboratorSpecific = (metadata: any) => {
const permissionValue = parseInt(metadata.permission, 10);
const permission = new AppPermission({ per: permissionValue });
return {
...metadata,
readPermission: permission.hasReadPer ? '✔' : '✘',
writePermission: permission.hasWritePer ? '✔' : '✘',
managePermission: permission.hasManagePer ? '✔' : '✘'
};
};
export const createAppProcessors = () => ({
UPDATE_APP_COLLABORATOR: createSpecialProcessor(processUpdateAppCollaboratorSpecific)
});

View File

@@ -0,0 +1,43 @@
export interface CommonMetadataFields {
appType?: string;
datasetType?: string;
operationName?: string;
itemName?: string;
newItemNames?: string[] | string;
[key: string]: any;
}
export const defaultMetadataProcessor = (metadata: CommonMetadataFields, t: any): any => {
const result = { ...metadata };
const translatableFields = ['appType', 'datasetType', 'operationName', 'itemName'];
Object.entries(metadata)
.filter(([key, value]) => translatableFields.includes(key) && value)
.forEach(([key, value]) => {
result[key] = t(value as any);
});
if (metadata.newItemNames) {
if (Array.isArray(metadata.newItemNames)) {
result.newItemNames = metadata.newItemNames
.map((itemName: string) => t(itemName as any))
.join(',');
} else if (typeof metadata.newItemNames === 'string') {
result.newItemNames = metadata.newItemNames
.split(',')
.map((itemName: string) => t(itemName as any))
.join(',');
}
}
return result;
};
export const createSpecialProcessor = (specificProcessor: (metadata: any) => any) => {
return (metadata: any, t: any) => {
let processedMetadata = defaultMetadataProcessor(metadata, t);
processedMetadata = specificProcessor(processedMetadata);
return processedMetadata;
};
};

View File

@@ -0,0 +1,17 @@
import { DatasetPermission } from '@fastgpt/global/support/permission/dataset/controller';
import { createSpecialProcessor } from './commonProcessor';
export const processUpdateDatasetCollaboratorSpecific = (metadata: any) => {
const permissionValue = parseInt(metadata.permission, 10);
const permission = new DatasetPermission({ per: permissionValue });
return {
...metadata,
readPermission: permission.hasReadPer ? '✔' : '✘',
writePermission: permission.hasWritePer ? '✔' : '✘',
managePermission: permission.hasManagePer ? '✔' : '✘'
};
};
export const createDatasetProcessors = () => ({
UPDATE_DATASET_COLLABORATOR: createSpecialProcessor(processUpdateDatasetCollaboratorSpecific)
});

View File

@@ -0,0 +1,30 @@
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { defaultMetadataProcessor } from './commonProcessor';
import { createTeamProcessors } from './teamProcessors';
import { createAppProcessors } from './appProcessors';
import { createDatasetProcessors } from './datasetProcessors';
export type MetadataProcessor = (metadata: any, t: any) => any;
export const createMetadataProcessorMap = (): Record<OperationLogEventEnum, MetadataProcessor> => {
const specialProcessors: Partial<Record<OperationLogEventEnum, MetadataProcessor>> = {
...createTeamProcessors(),
...createAppProcessors(),
...createDatasetProcessors()
};
const processorMap = {} as Record<OperationLogEventEnum, MetadataProcessor>;
Object.values(OperationLogEventEnum).forEach((event) => {
processorMap[event] =
specialProcessors[event] ||
((metadata: any, t: any) => defaultMetadataProcessor(metadata, t));
});
return processorMap;
};
export * from './commonProcessor';
export * from './teamProcessors';
export * from './appProcessors';
export * from './datasetProcessors';

View File

@@ -0,0 +1,19 @@
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
import { createSpecialProcessor } from './commonProcessor';
export const processAssignPermissionSpecific = (metadata: any) => {
const permissionValue = parseInt(metadata.permission, 10);
const permission = new TeamPermission({ per: permissionValue });
return {
...metadata,
appCreate: permission.hasAppCreatePer ? '✔' : '✘',
datasetCreate: permission.hasDatasetCreatePer ? '✔' : '✘',
apiKeyCreate: permission.hasApikeyCreatePer ? '✔' : '✘',
manage: permission.hasManagePer ? '✔' : '✘'
};
};
export const createTeamProcessors = () => ({
ASSIGN_PERMISSION: createSpecialProcessor(processAssignPermissionSpecific)
});

View File

@@ -5,7 +5,10 @@ import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { onCreateApp } from './create';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
export type copyAppQuery = {};
export type copyAppBody = { appId: string };
@@ -18,7 +21,7 @@ async function handler(
req: ApiRequestProps<copyAppBody, copyAppQuery>,
res: ApiResponseType<any>
): Promise<copyAppResponse> {
const { app } = await authApp({
const { app, teamId } = await authApp({
req,
authToken: true,
per: WritePermissionVal,
@@ -42,6 +45,17 @@ async function handler(
tmbId,
pluginData: app.pluginData
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_APP_COPY,
params: {
appName: app.name,
appType: getI18nAppType(app.type)
}
});
})();
return { appId };
}

View File

@@ -19,6 +19,9 @@ import { checkTeamAppLimit } from '@fastgpt/service/support/permission/teamLimit
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { type ApiRequestProps } from '@fastgpt/service/type/next';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
export type CreateAppBody = {
parentId?: ParentIdType;
@@ -148,6 +151,17 @@ export const onCreateApp = async ({
{ session, ordered: true }
);
}
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_APP,
params: {
appName: name!,
appType: getI18nAppType(type!)
}
});
})();
await refreshSourceAvatar(avatar, undefined, session);

View File

@@ -19,7 +19,10 @@ import { deleteChatFiles } from '@fastgpt/service/core/chat/controller';
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
import { MongoOpenApi } from '@fastgpt/service/support/openapi/schema';
import { removeImageByPath } from '@fastgpt/service/common/file/image/controller';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string };
@@ -39,6 +42,17 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
teamId,
appId
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.DELETE_APP,
params: {
appName: app.name,
appType: getI18nAppType(app.type)
}
});
})();
// Tracks
pushTrack.countAppNodes({ teamId, tmbId, uid: userId, appId });

View File

@@ -18,7 +18,8 @@ import { syncCollaborators } from '@fastgpt/service/support/permission/inheritPe
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { type ApiRequestProps } from '@fastgpt/service/type/next';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
export type CreateAppFolderBody = {
parentId?: ParentIdType;
name: string;
@@ -83,6 +84,16 @@ async function handler(req: ApiRequestProps<CreateAppFolderBody>) {
);
}
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_APP_FOLDER,
params: {
folderName: name
}
});
})();
}
export default NextAPI(handler);

View File

@@ -13,6 +13,9 @@ import { parsePaginationRequest } from '@fastgpt/service/common/api/pagination';
import { type PaginationResponse } from '@fastgpt/web/common/fetch/type';
import { addSourceMember } from '@fastgpt/service/support/user/utils';
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
async function handler(
req: NextApiRequest,
@@ -33,7 +36,12 @@ async function handler(
}
// 凭证校验
const { teamId } = await authApp({ req, authToken: true, appId, per: WritePermissionVal });
const { teamId, tmbId, app } = await authApp({
req,
authToken: true,
appId,
per: WritePermissionVal
});
const where = {
teamId: new Types.ObjectId(teamId),
@@ -139,6 +147,18 @@ async function handler(
const listWithoutTmbId = list.filter((item) => !item.tmbId);
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.EXPORT_APP_CHAT_LOG,
params: {
appName: app.name,
appType: getI18nAppType(app.type)
}
});
})();
return {
list: listWithSourceMember.concat(listWithoutTmbId),
total

View File

@@ -24,6 +24,10 @@ import { TeamAppCreatePermissionVal } from '@fastgpt/global/support/permission/u
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
import { i18nT } from '@fastgpt/web/i18n/utils';
export type AppUpdateQuery = {
appId: string;
@@ -54,7 +58,7 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
// this step is to get the app and its permission, and we will check the permission manually for
// different cases
const { app, permission } = await authApp({
const { app, permission, teamId, tmbId } = await authApp({
req,
authToken: true,
appId,
@@ -65,11 +69,23 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
Promise.reject(AppErrEnum.unExist);
}
let targetName = '';
if (isMove) {
if (parentId) {
// move to a folder, check the target folder's permission
await authApp({ req, authToken: true, appId: parentId, per: ManagePermissionVal });
const { app: targetApp } = await authApp({
req,
authToken: true,
appId: parentId,
per: ManagePermissionVal
});
targetName = targetApp.name;
} else {
targetName = 'root';
}
if (app.parentId) {
// move from a folder, check the (old) folder's permission
await authApp({ req, authToken: true, appId: app.parentId, per: ManagePermissionVal });
@@ -160,6 +176,7 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
session
});
} else {
logAppMove({ tmbId, teamId, app, targetName });
// Not folder, delete all clb
await MongoResourcePermission.deleteMany(
{ resourceType: PerResourceTypeEnum.app, teamId: app.teamId, resourceId: app._id },
@@ -169,8 +186,85 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
return onUpdate(session);
});
} else {
logAppUpdate({ tmbId, teamId, app, name, intro });
return onUpdate();
}
}
export default NextAPI(handler);
const logAppMove = ({
tmbId,
teamId,
app,
targetName
}: {
tmbId: string;
teamId: string;
app: any;
targetName: string;
}) => {
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.MOVE_APP,
params: {
appName: app.name,
targetFolderName: targetName,
appType: getI18nAppType(app.type)
}
});
})();
};
const logAppUpdate = ({
tmbId,
teamId,
app,
name,
intro
}: {
tmbId: string;
teamId: string;
app: any;
name?: string;
intro?: string;
}) => {
(async () => {
const getUpdateItems = () => {
const names: string[] = [];
const values: string[] = [];
if (name !== undefined) {
names.push(i18nT('common:core.app.name'));
values.push(name);
}
if (intro !== undefined) {
names.push(i18nT('common:Intro'));
values.push(intro);
}
return {
names,
values
};
};
const { names: newItemNames, values: newItemValues } = getUpdateItems();
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_APP_INFO,
params: {
appName: app.name,
newItemNames: newItemNames,
newItemValues: newItemValues,
appType: getI18nAppType(app.type)
}
});
})();
};

View File

@@ -11,12 +11,20 @@ import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'
import { type ApiRequestProps } from '@fastgpt/service/type/next';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { rewriteAppWorkflowToSimple } from '@fastgpt/service/core/app/utils';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
import { i18nT } from '@fastgpt/web/i18n/utils';
async function handler(req: ApiRequestProps<PostPublishAppProps>, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string };
const { nodes = [], edges = [], chatConfig, isPublish, versionName, autoSave } = req.body;
const { app, tmbId } = await authApp({ appId, req, per: WritePermissionVal, authToken: true });
const { app, tmbId, teamId } = await authApp({
appId,
req,
per: WritePermissionVal,
authToken: true
});
const { nodes: formatNodes } = beforeUpdateAppFormat({
nodes,
@@ -26,12 +34,26 @@ async function handler(req: ApiRequestProps<PostPublishAppProps>, res: NextApiRe
await rewriteAppWorkflowToSimple(formatNodes);
if (autoSave) {
return MongoApp.findByIdAndUpdate(appId, {
await MongoApp.findByIdAndUpdate(appId, {
modules: formatNodes,
edges,
chatConfig,
updateTime: new Date()
});
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_PUBLISH_APP,
params: {
appName: app.name,
operationName: i18nT('account_team:update'),
appId,
appType: getI18nAppType(app.type)
}
});
return;
}
await mongoSessionRun(async (session) => {
@@ -79,6 +101,22 @@ async function handler(req: ApiRequestProps<PostPublishAppProps>, res: NextApiRe
}
);
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_PUBLISH_APP,
params: {
appName: app.name,
operationName: isPublish
? i18nT('account_team:save_and_publish')
: i18nT('account_team:update'),
appId,
appType: getI18nAppType(app.type)
}
});
})();
}
export default NextAPI(handler);

View File

@@ -4,11 +4,14 @@ import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { createOneCollection } from '@fastgpt/service/core/dataset/collection/controller';
import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: NextApiRequest) {
const body = req.body as CreateDatasetCollectionParams;
const { teamId, tmbId } = await authDataset({
const { teamId, tmbId, dataset } = await authDataset({
req,
authToken: true,
authApiKey: true,
@@ -21,6 +24,20 @@ async function handler(req: NextApiRequest) {
teamId,
tmbId
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_COLLECTION,
params: {
collectionName: body.name,
datasetName: dataset.name,
datasetType: getI18nDatasetType(dataset.type)
}
});
})();
return _id;
}

View File

@@ -14,6 +14,9 @@ import { authDatasetCollection } from '@fastgpt/service/support/permission/datas
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { i18nT } from '@fastgpt/web/i18n/utils';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
type RetrainingCollectionResponse = {
collectionId: string;
@@ -124,6 +127,19 @@ async function handler(
}
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.RETRAIN_COLLECTION,
params: {
collectionName: collection.name,
datasetName: collection.dataset?.name || '',
datasetType: getI18nDatasetType(collection.dataset?.type || '')
}
});
})();
return { collectionId };
});
}

View File

@@ -6,7 +6,9 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: NextApiRequest) {
const { id: collectionId } = req.query as { id: string };
@@ -14,7 +16,7 @@ async function handler(req: NextApiRequest) {
return Promise.reject(CommonErrEnum.missingParams);
}
const { teamId, collection } = await authDatasetCollection({
const { teamId, collection, tmbId } = await authDatasetCollection({
req,
authToken: true,
authApiKey: true,
@@ -39,6 +41,19 @@ async function handler(req: NextApiRequest) {
session
})
);
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.DELETE_COLLECTION,
params: {
collectionName: collection.name,
datasetName: collection.dataset?.name || '',
datasetType: getI18nDatasetType(collection.dataset?.type || '')
}
});
})();
}
export default NextAPI(handler);

View File

@@ -12,7 +12,9 @@ import { DatasetCollectionTypeEnum } from '@fastgpt/global/core/dataset/constant
import { type ClientSession } from '@fastgpt/service/common/mongo';
import { type CollectionWithDatasetType } from '@fastgpt/global/core/dataset/type';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
export type UpdateDatasetCollectionParams = {
id?: string;
parentId?: string;
@@ -88,7 +90,7 @@ async function handler(req: ApiRequestProps<UpdateDatasetCollectionParams>) {
}
// 凭证校验
const { collection, teamId } = await authDatasetCollection({
const { collection, teamId, tmbId } = await authDatasetCollection({
req,
authToken: true,
authApiKey: true,
@@ -131,6 +133,19 @@ async function handler(req: ApiRequestProps<UpdateDatasetCollectionParams>) {
});
}
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_COLLECTION,
params: {
collectionName: collection.name,
datasetName: collection.dataset?.name || '',
datasetType: getI18nDatasetType(collection.dataset?.type || '')
}
});
})();
}
export default NextAPI(handler);

View File

@@ -18,6 +18,9 @@ import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { checkTeamDatasetLimit } from '@fastgpt/service/support/permission/teamLimit';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
export type DatasetCreateQuery = {};
export type DatasetCreateBody = CreateDatasetParams;
@@ -102,6 +105,18 @@ async function handler(
uid: userId
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_DATASET,
params: {
datasetName: name,
datasetType: getI18nDatasetType(type)
}
});
})();
return datasetId;
}
export default NextAPI(handler);

View File

@@ -4,7 +4,9 @@ import { deleteDatasetData } from '@/service/core/dataset/data/controller';
import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: NextApiRequest) {
const { id: dataId } = req.query as {
id: string;
@@ -15,7 +17,7 @@ async function handler(req: NextApiRequest) {
}
// 凭证校验
const { datasetData } = await authDatasetData({
const { datasetData, tmbId, teamId, collection } = await authDatasetData({
req,
authToken: true,
authApiKey: true,
@@ -24,7 +26,18 @@ async function handler(req: NextApiRequest) {
});
await deleteDatasetData(datasetData);
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.DELETE_DATA,
params: {
collectionName: collection.name,
datasetName: collection.dataset?.name || '',
datasetType: getI18nDatasetType(collection.dataset?.type || '')
}
});
})();
return 'success';
}

View File

@@ -17,6 +17,9 @@ import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { getLLMMaxChunkSize } from '@fastgpt/global/core/dataset/training/utils';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: NextApiRequest) {
const { collectionId, q, a, indexes } = req.body as InsertOneDatasetDataProps;
@@ -30,7 +33,7 @@ async function handler(req: NextApiRequest) {
}
// 凭证校验
const { teamId, tmbId } = await authDatasetCollection({
const { teamId, tmbId, collection } = await authDatasetCollection({
req,
authToken: true,
authApiKey: true,
@@ -96,6 +99,18 @@ async function handler(req: NextApiRequest) {
model: vectorModelData.model
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_DATA,
params: {
collectionName: collection.name,
datasetName: collection.dataset?.name || '',
datasetType: getI18nDatasetType(collection.dataset?.type || '')
}
});
})();
return insertId;
}

View File

@@ -5,7 +5,9 @@ import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { authDatasetData } from '@fastgpt/service/support/permission/dataset/auth';
import { type ApiRequestProps } from '@fastgpt/service/type/next';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: ApiRequestProps<UpdateDatasetDataProps>) {
const { dataId, q, a, indexes = [] } = req.body;
@@ -15,7 +17,8 @@ async function handler(req: ApiRequestProps<UpdateDatasetDataProps>) {
dataset: { vectorModel }
},
teamId,
tmbId
tmbId,
collection
} = await authDatasetData({
req,
authToken: true,
@@ -39,6 +42,19 @@ async function handler(req: ApiRequestProps<UpdateDatasetDataProps>) {
inputTokens: tokens,
model: vectorModel
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_DATA,
params: {
collectionName: collection.name,
datasetName: collection.dataset?.name || '',
datasetType: getI18nDatasetType(collection.dataset?.type || '')
}
});
})();
} else {
// await MongoDatasetData.findByIdAndUpdate(dataId, {
// ...(forbid !== undefined && { forbid })

View File

@@ -11,6 +11,9 @@ import { MongoDatasetCollectionTags } from '@fastgpt/service/core/dataset/tag/sc
import { removeImageByPath } from '@fastgpt/service/common/file/image/controller';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { removeWebsiteSyncJobScheduler } from '@fastgpt/service/core/dataset/websiteSync';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: NextApiRequest) {
const { id: datasetId } = req.query as {
@@ -22,7 +25,7 @@ async function handler(req: NextApiRequest) {
}
// auth owner
const { teamId } = await authDataset({
const { teamId, tmbId, dataset } = await authDataset({
req,
authToken: true,
authApiKey: true,
@@ -66,6 +69,18 @@ async function handler(req: NextApiRequest) {
await removeImageByPath(dataset.avatar, session);
}
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.DELETE_DATASET,
params: {
datasetName: dataset.name,
datasetType: getI18nDatasetType(dataset.type)
}
});
})();
}
export default NextAPI(handler);

View File

@@ -17,6 +17,8 @@ import { syncCollaborators } from '@fastgpt/service/support/permission/inheritPe
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
export type DatasetFolderCreateQuery = {};
export type DatasetFolderCreateBody = {
parentId?: string;
@@ -92,6 +94,16 @@ async function handler(
);
}
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_DATASET_FOLDER,
params: {
folderName: name
}
});
})();
return {};
}

View File

@@ -14,7 +14,9 @@ import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { useIPFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit';
import { type ApiRequestProps } from '@fastgpt/service/type/next';
import { getRerankModel } from '@fastgpt/service/core/ai/model';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: ApiRequestProps<SearchTestProps>): Promise<SearchTestResponse> {
const {
datasetId,
@@ -130,6 +132,17 @@ async function handler(req: ApiRequestProps<SearchTestProps>): Promise<SearchTes
totalPoints: embeddingTotalPoints + reRankTotalPoints
});
}
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.SEARCH_TEST,
params: {
datasetName: dataset.name,
datasetType: getI18nDatasetType(dataset.type)
}
});
})();
return {
list: searchRes,

View File

@@ -37,6 +37,9 @@ import {
} from '@fastgpt/service/core/dataset/websiteSync';
import { delDatasetRelevantData } from '@fastgpt/service/core/dataset/controller';
import { isEqual } from 'lodash';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
export type DatasetUpdateQuery = {};
export type DatasetUpdateResponse = any;
@@ -79,16 +82,27 @@ async function handler(
const isMove = parentId !== undefined;
const { dataset, permission } = await authDataset({
const { dataset, permission, tmbId, teamId } = await authDataset({
req,
authToken: true,
datasetId: id,
per: ReadPermissionVal
});
let targetName = '';
if (isMove) {
if (parentId) {
// move to a folder, check the target folder's permission
await authDataset({ req, authToken: true, datasetId: parentId, per: ManagePermissionVal });
const { dataset: targetDataset } = await authDataset({
req,
authToken: true,
datasetId: parentId,
per: ManagePermissionVal
});
targetName = targetDataset.name;
} else {
targetName = 'root';
}
if (dataset.parentId) {
// move from a folder, check the (old) folder's permission
@@ -221,7 +235,9 @@ async function handler(
collaborators: parentClbsAndGroups,
session
});
logDatasetMove({ tmbId, teamId, dataset, targetName });
} else {
logDatasetMove({ tmbId, teamId, dataset, targetName });
// Not folder, delete all clb
await MongoResourcePermission.deleteMany(
{ resourceId: id, teamId: dataset.teamId, resourceType: PerResourceTypeEnum.dataset },
@@ -230,6 +246,7 @@ async function handler(
}
return onUpdate(session);
} else {
logDatasetUpdate({ tmbId, teamId, dataset });
return onUpdate(session);
}
});
@@ -315,3 +332,50 @@ const updateSyncSchedule = async ({
}
}
};
const logDatasetMove = ({
tmbId,
teamId,
dataset,
targetName
}: {
tmbId: string;
teamId: string;
dataset: any;
targetName: string;
}) => {
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.MOVE_DATASET,
params: {
datasetName: dataset.name,
targetFolderName: targetName,
datasetType: getI18nDatasetType(dataset.type)
}
});
})();
};
const logDatasetUpdate = ({
tmbId,
teamId,
dataset
}: {
tmbId: string;
teamId: string;
dataset: any;
}) => {
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_DATASET,
params: {
datasetName: dataset.name,
datasetType: getI18nDatasetType(dataset.type)
}
});
})();
};

View File

@@ -8,7 +8,8 @@ import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { OpenApiErrEnum } from '@fastgpt/global/common/error/code/openapi';
import { TeamApikeyCreatePermissionVal } from '@fastgpt/global/support/permission/user/constant';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
async function handler(req: ApiRequestProps<EditApiKeyProps>): Promise<string> {
const { appId, name, limit } = req.body;
const { tmbId, teamId } = await (async () => {
@@ -48,6 +49,18 @@ async function handler(req: ApiRequestProps<EditApiKeyProps>): Promise<string> {
name,
limit
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_API_KEY,
params: {
keyName: name
}
});
})();
return apiKey;
}

View File

@@ -4,7 +4,8 @@ import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant'
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
export type OpenAPIDeleteQuery = { id: string };
export type OpenAPIDeleteBody = {};
export type OpenAPIDeleteResponse = {};
@@ -19,9 +20,26 @@ async function handler(
return Promise.reject(CommonErrEnum.missingParams);
}
await authOpenApiKeyCrud({ req, authToken: true, id, per: OwnerPermissionVal });
const { tmbId, teamId, openapi } = await authOpenApiKeyCrud({
req,
authToken: true,
id,
per: OwnerPermissionVal
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.DELETE_API_KEY,
params: {
keyName: openapi.name
}
});
})();
await MongoOpenApi.deleteOne({ _id: id });
return {};
}

View File

@@ -4,11 +4,28 @@ import { authOpenApiKeyCrud } from '@fastgpt/service/support/permission/auth/ope
import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
async function handler(req: ApiRequestProps<EditApiKeyProps & { _id: string }>): Promise<void> {
const { _id, name, limit } = req.body;
await authOpenApiKeyCrud({ req, authToken: true, id: _id, per: OwnerPermissionVal });
const { tmbId, teamId } = await authOpenApiKeyCrud({
req,
authToken: true,
id: _id,
per: OwnerPermissionVal
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_API_KEY,
params: {
keyName: name
}
});
})();
await MongoOpenApi.findByIdAndUpdate(_id, {
...(name && { name }),

View File

@@ -6,7 +6,9 @@ import type { PublishChannelEnum } from '@fastgpt/global/support/outLink/constan
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
/* create a shareChat */
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
@@ -23,7 +25,7 @@ async function handler(
): Promise<OutLinkCreateResponse> {
const { appId, ...props } = req.body;
const { teamId, tmbId } = await authApp({
const { teamId, tmbId, app } = await authApp({
req,
authToken: true,
appId,
@@ -39,6 +41,19 @@ async function handler(
...props
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CREATE_APP_PUBLISH_CHANNEL,
params: {
appName: app.name,
channelName: props.name,
appType: getI18nAppType(app.type)
}
});
})();
return shareId;
}

View File

@@ -3,6 +3,9 @@ import { authOutLinkCrud } from '@fastgpt/service/support/permission/publish/aut
import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
export type OutLinkDeleteQuery = {
id: string;
@@ -15,8 +18,28 @@ async function handler(
req: ApiRequestProps<OutLinkDeleteBody, OutLinkDeleteQuery>
): Promise<OutLinkDeleteResponse> {
const { id } = req.query;
await authOutLinkCrud({ req, outLinkId: id, authToken: true, per: OwnerPermissionVal });
const { tmbId, teamId, outLink, app } = await authOutLinkCrud({
req,
outLinkId: id,
authToken: true,
per: OwnerPermissionVal
});
await MongoOutLink.findByIdAndDelete(id);
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.DELETE_APP_PUBLISH_CHANNEL,
params: {
appName: app.name,
channelName: outLink.name,
appType: getI18nAppType(app.type)
}
});
})();
return {};
}

View File

@@ -5,7 +5,9 @@ import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant
import type { ApiRequestProps } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nAppType } from '@fastgpt/service/support/operationLog/util';
export type OutLinkUpdateQuery = {};
// {
@@ -30,7 +32,17 @@ async function handler(
return Promise.reject(CommonErrEnum.missingParams);
}
await authOutLinkCrud({ req, outLinkId: _id, authToken: true, per: ManagePermissionVal });
const {
tmbId,
teamId,
outLink,
app: logApp
} = await authOutLinkCrud({
req,
outLinkId: _id,
authToken: true,
per: ManagePermissionVal
});
await MongoOutLink.findByIdAndUpdate(_id, {
name,
@@ -41,6 +53,19 @@ async function handler(
limit,
app
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.UPDATE_APP_PUBLISH_CHANNEL,
params: {
appName: logApp.name,
channelName: outLink.name,
appType: getI18nAppType(logApp.type)
}
});
})();
return {};
}
export default NextAPI(handler);

View File

@@ -5,7 +5,8 @@ import { MongoUser } from '@fastgpt/service/support/user/schema';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { i18nT } from '@fastgpt/web/i18n/utils';
import { NextAPI } from '@/service/middleware/entry';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { oldPsw, newPsw } = req.body as { oldPsw: string; newPsw: string };
@@ -13,7 +14,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
return Promise.reject('Params is missing');
}
const { tmbId } = await authCert({ req, authToken: true });
const { tmbId, teamId } = await authCert({ req, authToken: true });
const tmb = await MongoTeamMember.findById(tmbId);
if (!tmb) {
return Promise.reject('can not find it');
@@ -39,6 +40,14 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
passwordUpdateTime: new Date()
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.CHANGE_PASSWORD,
params: {}
});
})();
return user;
}

View File

@@ -3,6 +3,9 @@ import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { checkExportDatasetLimit } from '@fastgpt/service/support/user/utils';
import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { addOperationLog } from '@fastgpt/service/support/operationLog/addOperationLog';
import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/constants';
import { getI18nDatasetType } from '@fastgpt/service/support/operationLog/util';
async function handler(req: NextApiRequest) {
const { datasetId } = req.query as {
@@ -14,7 +17,7 @@ async function handler(req: NextApiRequest) {
}
// 凭证校验
const { teamId } = await authDataset({
const { teamId, tmbId, dataset } = await authDataset({
req,
authToken: true,
datasetId,
@@ -25,6 +28,18 @@ async function handler(req: NextApiRequest) {
teamId,
limitMinutes: global.feConfigs?.limit?.exportDatasetLimitMinutes
});
(async () => {
addOperationLog({
tmbId,
teamId,
event: OperationLogEventEnum.EXPORT_DATASET,
params: {
datasetName: dataset.name,
datasetType: getI18nDatasetType(dataset.type)
}
});
})();
}
export default NextAPI(handler);