* 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

232
dev.md
View File

@@ -1,114 +1,118 @@
## Premise
Since FastGPT is managed in the same way as monorepo, it is recommended to install make first during development.
monorepo Project Name:
- app: main project
-......
## Dev
```sh
# Give automatic script code execution permission (on non-Linux systems, you can manually execute the postinstall.sh file content)
chmod -R +x ./scripts/
# Executing under the code root directory installs all dependencies within the root package, projects, and packages
pnpm i
# Not make cmd
cd projects/app
pnpm dev
# Make cmd
make dev name=app
```
Note: If the Node version is >= 20, you need to pass the `--no-node-snapshot` parameter to Node when running `pnpm i`
```sh
NODE_OPTIONS=--no-node-snapshot pnpm i
```
### Jest
https://fael3z0zfze.feishu.cn/docx/ZOI1dABpxoGhS7xzhkXcKPxZnDL
## I18N
### Install i18n-ally Plugin
1. Open the Extensions Marketplace in VSCode, search for and install the `i18n Ally` plugin.
### Code Optimization Examples
#### Fetch Specific Namespace Translations in `getServerSideProps`
```typescript
// pages/yourPage.tsx
export async function getServerSideProps(context: any) {
return {
props: {
currentTab: context?.query?.currentTab || TabEnum.info,
...(await serverSideTranslations(context.locale, ['publish', 'user']))
}
};
}
```
#### Use useTranslation Hook in Page
```typescript
// pages/yourPage.tsx
import { useTranslation } from 'next-i18next';
const YourComponent = () => {
const { t } = useTranslation();
return (
<Button
variant="outline"
size="sm"
mr={2}
onClick={() => setShowSelected(false)}
>
{t('common:close')}
</Button>
);
};
export default YourComponent;
```
#### Handle Static File Translations
```typescript
// utils/i18n.ts
import { i18nT } from '@fastgpt/web/i18n/utils';
const staticContent = {
id: 'simpleChat',
avatar: 'core/workflow/template/aiChat',
name: i18nT('app:template.simple_robot'),
};
export default staticContent;
```
### Standardize Translation Format
- Use the t(namespace:key) format to ensure consistent naming.
- Translation keys should use lowercase letters and underscores, e.g., common.close.
## Build
```sh
# Docker cmd: Build image, not proxy
docker build -f ./projects/app/Dockerfile -t registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 . --build-arg name=app
# Make cmd: Build image, not proxy
make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1
# Docker cmd: Build image with proxy
docker build -f ./projects/app/Dockerfile -t registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 . --build-arg name=app --build-arg proxy=taobao
# Make cmd: Build image with proxy
make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 proxy=taobao
```
## Premise
Since FastGPT is managed in the same way as monorepo, it is recommended to install make first during development.
monorepo Project Name:
- app: main project
-......
## Dev
```sh
# Give automatic script code execution permission (on non-Linux systems, you can manually execute the postinstall.sh file content)
chmod -R +x ./scripts/
# Executing under the code root directory installs all dependencies within the root package, projects, and packages
pnpm i
# Not make cmd
cd projects/app
pnpm dev
# Make cmd
make dev name=app
```
Note: If the Node version is >= 20, you need to pass the `--no-node-snapshot` parameter to Node when running `pnpm i`
```sh
NODE_OPTIONS=--no-node-snapshot pnpm i
```
### Jest
https://fael3z0zfze.feishu.cn/docx/ZOI1dABpxoGhS7xzhkXcKPxZnDL
## I18N
### Install i18n-ally Plugin
1. Open the Extensions Marketplace in VSCode, search for and install the `i18n Ally` plugin.
### Code Optimization Examples
#### Fetch Specific Namespace Translations in `getServerSideProps`
```typescript
// pages/yourPage.tsx
export async function getServerSideProps(context: any) {
return {
props: {
currentTab: context?.query?.currentTab || TabEnum.info,
...(await serverSideTranslations(context.locale, ['publish', 'user']))
}
};
}
```
#### Use useTranslation Hook in Page
```typescript
// pages/yourPage.tsx
import { useTranslation } from 'next-i18next';
const YourComponent = () => {
const { t } = useTranslation();
return (
<Button
variant="outline"
size="sm"
mr={2}
onClick={() => setShowSelected(false)}
>
{t('common:close')}
</Button>
);
};
export default YourComponent;
```
#### Handle Static File Translations
```typescript
// utils/i18n.ts
import { i18nT } from '@fastgpt/web/i18n/utils';
const staticContent = {
id: 'simpleChat',
avatar: 'core/workflow/template/aiChat',
name: i18nT('app:template.simple_robot'),
};
export default staticContent;
```
### Standardize Translation Format
- Use the t(namespace:key) format to ensure consistent naming.
- Translation keys should use lowercase letters and underscores, e.g., common.close.
## audit
Please fill the OperationLogEventEnum and operationLog/audit function is added to the ts, and on the corresponding position to fill i18n, at the same time to add the location of the log using addOpearationLog function add function
## Build
```sh
# Docker cmd: Build image, not proxy
docker build -f ./projects/app/Dockerfile -t registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 . --build-arg name=app
# Make cmd: Build image, not proxy
make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1
# Docker cmd: Build image with proxy
docker build -f ./projects/app/Dockerfile -t registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 . --build-arg name=app --build-arg proxy=taobao
# Make cmd: Build image with proxy
make build name=app image=registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:v4.8.1 proxy=taobao
```

View File

@@ -1,4 +1,5 @@
export enum OperationLogEventEnum {
//Team
LOGIN = 'LOGIN',
CREATE_INVITATION_LINK = 'CREATE_INVITATION_LINK',
JOIN_TEAM = 'JOIN_TEAM',
@@ -11,5 +12,52 @@ export enum OperationLogEventEnum {
RELOCATE_DEPARTMENT = 'RELOCATE_DEPARTMENT',
CREATE_GROUP = 'CREATE_GROUP',
DELETE_GROUP = 'DELETE_GROUP',
ASSIGN_PERMISSION = 'ASSIGN_PERMISSION'
ASSIGN_PERMISSION = 'ASSIGN_PERMISSION',
//APP
CREATE_APP = 'CREATE_APP',
UPDATE_APP_INFO = 'UPDATE_APP_INFO',
MOVE_APP = 'MOVE_APP',
DELETE_APP = 'DELETE_APP',
UPDATE_APP_COLLABORATOR = 'UPDATE_APP_COLLABORATOR',
DELETE_APP_COLLABORATOR = 'DELETE_APP_COLLABORATOR',
TRANSFER_APP_OWNERSHIP = 'TRANSFER_APP_OWNERSHIP',
CREATE_APP_COPY = 'CREATE_APP_COPY',
CREATE_APP_FOLDER = 'CREATE_APP_FOLDER',
UPDATE_PUBLISH_APP = 'UPDATE_PUBLISH_APP',
CREATE_APP_PUBLISH_CHANNEL = 'CREATE_APP_PUBLISH_CHANNEL',
UPDATE_APP_PUBLISH_CHANNEL = 'UPDATE_APP_PUBLISH_CHANNEL',
DELETE_APP_PUBLISH_CHANNEL = 'DELETE_APP_PUBLISH_CHANNEL',
EXPORT_APP_CHAT_LOG = 'EXPORT_APP_CHAT_LOG',
//Dataset
CREATE_DATASET = 'CREATE_DATASET',
UPDATE_DATASET = 'UPDATE_DATASET',
DELETE_DATASET = 'DELETE_DATASET',
MOVE_DATASET = 'MOVE_DATASET',
UPDATE_DATASET_COLLABORATOR = 'UPDATE_DATASET_COLLABORATOR',
DELETE_DATASET_COLLABORATOR = 'DELETE_DATASET_COLLABORATOR',
TRANSFER_DATASET_OWNERSHIP = 'TRANSFER_DATASET_OWNERSHIP',
EXPORT_DATASET = 'EXPORT_DATASET',
CREATE_DATASET_FOLDER = 'CREATE_DATASET_FOLDER',
//Collection
CREATE_COLLECTION = 'CREATE_COLLECTION',
UPDATE_COLLECTION = 'UPDATE_COLLECTION',
DELETE_COLLECTION = 'DELETE_COLLECTION',
RETRAIN_COLLECTION = 'RETRAIN_COLLECTION',
//Data
CREATE_DATA = 'CREATE_DATA',
UPDATE_DATA = 'UPDATE_DATA',
DELETE_DATA = 'DELETE_DATA',
//SearchTest
SEARCH_TEST = 'SEARCH_TEST',
//Account
CHANGE_PASSWORD = 'CHANGE_PASSWORD',
CHANGE_NOTIFICATION_SETTINGS = 'CHANGE_NOTIFICATION_SETTINGS',
CHANGE_MEMBER_NAME_ACCOUNT = 'CHANGE_MEMBER_NAME_ACCOUNT',
PURCHASE_PLAN = 'PURCHASE_PLAN',
EXPORT_BILL_RECORDS = 'EXPORT_BILL_RECORDS',
CREATE_INVOICE = 'CREATE_INVOICE',
SET_INVOICE_HEADER = 'SET_INVOICE_HEADER',
CREATE_API_KEY = 'CREATE_API_KEY',
UPDATE_API_KEY = 'UPDATE_API_KEY',
DELETE_API_KEY = 'DELETE_API_KEY'
}

View File

@@ -2,6 +2,7 @@ import { OperationLogEventEnum } from '@fastgpt/global/support/operationLog/cons
import { i18nT } from '../../../web/i18n/utils';
export const operationLogMap = {
//Team
[OperationLogEventEnum.LOGIN]: {
content: i18nT('account_team:log_login'),
typeLabel: i18nT('account_team:login'),
@@ -66,6 +67,309 @@ export const operationLogMap = {
content: i18nT('account_team:log_assign_permission'),
typeLabel: i18nT('account_team:assign_permission'),
params: {} as { name?: string; objectName: string; permission: string }
},
//APP
[OperationLogEventEnum.CREATE_APP]: {
content: i18nT('account_team:log_create_app'),
typeLabel: i18nT('account_team:create_app'),
params: {} as { name?: string; appName: string; appType: string }
},
[OperationLogEventEnum.UPDATE_APP_INFO]: {
content: i18nT('account_team:log_update_app_info'),
typeLabel: i18nT('account_team:update_app_info'),
params: {} as {
name?: string;
appName: string;
newItemNames: string[];
newItemValues: string[];
appType: string;
}
},
[OperationLogEventEnum.MOVE_APP]: {
content: i18nT('account_team:log_move_app'),
typeLabel: i18nT('account_team:move_app'),
params: {} as { name?: string; appName: string; targetFolderName: string; appType: string }
},
[OperationLogEventEnum.DELETE_APP]: {
content: i18nT('account_team:log_delete_app'),
typeLabel: i18nT('account_team:delete_app'),
params: {} as { name?: string; appName: string; appType: string }
},
[OperationLogEventEnum.UPDATE_APP_COLLABORATOR]: {
content: i18nT('account_team:log_update_app_collaborator'),
typeLabel: i18nT('account_team:update_app_collaborator'),
params: {} as {
name?: string;
appName: string;
appType: string;
tmbList: string[];
groupList: string[];
orgList: string[];
permission: string;
}
},
[OperationLogEventEnum.DELETE_APP_COLLABORATOR]: {
content: i18nT('account_team:log_delete_app_collaborator'),
typeLabel: i18nT('account_team:delete_app_collaborator'),
params: {} as {
name?: string;
appName: string;
appType: string;
itemName: string;
itemValueName: string;
}
},
[OperationLogEventEnum.TRANSFER_APP_OWNERSHIP]: {
content: i18nT('account_team:log_transfer_app_ownership'),
typeLabel: i18nT('account_team:transfer_app_ownership'),
params: {} as {
name?: string;
appName: string;
appType: string;
oldOwnerName: string;
newOwnerName: string;
}
},
[OperationLogEventEnum.CREATE_APP_COPY]: {
content: i18nT('account_team:log_create_app_copy'),
typeLabel: i18nT('account_team:create_app_copy'),
params: {} as { name?: string; appName: string; appType: string }
},
[OperationLogEventEnum.CREATE_APP_FOLDER]: {
content: i18nT('account_team:log_create_app_folder'),
typeLabel: i18nT('account_team:create_app_folder'),
params: {} as { name?: string; folderName: string }
},
[OperationLogEventEnum.UPDATE_PUBLISH_APP]: {
content: i18nT('account_team:log_update_publish_app'),
typeLabel: i18nT('account_team:update_publish_app'),
params: {} as {
name?: string;
operationName: string;
appName: string;
appId: string;
appType: string;
}
},
[OperationLogEventEnum.CREATE_APP_PUBLISH_CHANNEL]: {
content: i18nT('account_team:log_create_app_publish_channel'),
typeLabel: i18nT('account_team:create_app_publish_channel'),
params: {} as { name?: string; appName: string; channelName: string; appType: string }
},
[OperationLogEventEnum.UPDATE_APP_PUBLISH_CHANNEL]: {
content: i18nT('account_team:log_update_app_publish_channel'),
typeLabel: i18nT('account_team:update_app_publish_channel'),
params: {} as { name?: string; appName: string; channelName: string; appType: string }
},
[OperationLogEventEnum.DELETE_APP_PUBLISH_CHANNEL]: {
content: i18nT('account_team:log_delete_app_publish_channel'),
typeLabel: i18nT('account_team:delete_app_publish_channel'),
params: {} as { name?: string; appName: string; channelName: string; appType: string }
},
[OperationLogEventEnum.EXPORT_APP_CHAT_LOG]: {
content: i18nT('account_team:log_export_app_chat_log'),
typeLabel: i18nT('account_team:export_app_chat_log'),
params: {} as { name?: string; appName: string; appType: string }
},
//Dataset
[OperationLogEventEnum.CREATE_DATASET]: {
content: i18nT('account_team:log_create_dataset'),
typeLabel: i18nT('account_team:create_dataset'),
params: {} as { name?: string; datasetName: string; datasetType: string }
},
[OperationLogEventEnum.UPDATE_DATASET]: {
content: i18nT('account_team:log_update_dataset'),
typeLabel: i18nT('account_team:update_dataset'),
params: {} as { name?: string; datasetName: string; datasetType: string }
},
[OperationLogEventEnum.DELETE_DATASET]: {
content: i18nT('account_team:log_delete_dataset'),
typeLabel: i18nT('account_team:delete_dataset'),
params: {} as { name?: string; datasetName: string; datasetType: string }
},
[OperationLogEventEnum.MOVE_DATASET]: {
content: i18nT('account_team:log_move_dataset'),
typeLabel: i18nT('account_team:move_dataset'),
params: {} as {
name?: string;
datasetName: string;
targetFolderName: string;
datasetType: string;
}
},
[OperationLogEventEnum.UPDATE_DATASET_COLLABORATOR]: {
content: i18nT('account_team:log_update_dataset_collaborator'),
typeLabel: i18nT('account_team:update_dataset_collaborator'),
params: {} as {
name?: string;
datasetName: string;
datasetType: string;
tmbList: string[];
groupList: string[];
orgList: string[];
permission: string;
}
},
[OperationLogEventEnum.DELETE_DATASET_COLLABORATOR]: {
content: i18nT('account_team:log_delete_dataset_collaborator'),
typeLabel: i18nT('account_team:delete_dataset_collaborator'),
params: {} as {
name?: string;
datasetName: string;
datasetType: string;
itemName: string;
itemValueName: string;
}
},
[OperationLogEventEnum.TRANSFER_DATASET_OWNERSHIP]: {
content: i18nT('account_team:log_transfer_dataset_ownership'),
typeLabel: i18nT('account_team:transfer_dataset_ownership'),
params: {} as {
name?: string;
datasetName: string;
datasetType: string;
oldOwnerName: string;
newOwnerName: string;
}
},
[OperationLogEventEnum.EXPORT_DATASET]: {
content: i18nT('account_team:log_export_dataset'),
typeLabel: i18nT('account_team:export_dataset'),
params: {} as { name?: string; datasetName: string; datasetType: string }
},
[OperationLogEventEnum.CREATE_DATASET_FOLDER]: {
content: i18nT('account_team:log_create_dataset_folder'),
typeLabel: i18nT('account_team:create_dataset_folder'),
params: {} as { name?: string; folderName: string }
},
//Collection
[OperationLogEventEnum.CREATE_COLLECTION]: {
content: i18nT('account_team:log_create_collection'),
typeLabel: i18nT('account_team:create_collection'),
params: {} as {
name?: string;
collectionName: string;
datasetName: string;
datasetType: string;
}
},
[OperationLogEventEnum.UPDATE_COLLECTION]: {
content: i18nT('account_team:log_update_collection'),
typeLabel: i18nT('account_team:update_collection'),
params: {} as {
name?: string;
collectionName: string;
datasetName: string;
datasetType: string;
}
},
[OperationLogEventEnum.DELETE_COLLECTION]: {
content: i18nT('account_team:log_delete_collection'),
typeLabel: i18nT('account_team:delete_collection'),
params: {} as {
name?: string;
collectionName: string;
datasetName: string;
datasetType: string;
}
},
[OperationLogEventEnum.RETRAIN_COLLECTION]: {
content: i18nT('account_team:log_retrain_collection'),
typeLabel: i18nT('account_team:retrain_collection'),
params: {} as {
name?: string;
collectionName: string;
datasetName: string;
datasetType: string;
}
},
//Data
[OperationLogEventEnum.CREATE_DATA]: {
content: i18nT('account_team:log_create_data'),
typeLabel: i18nT('account_team:create_data'),
params: {} as {
name?: string;
collectionName: string;
datasetName: string;
datasetType: string;
}
},
[OperationLogEventEnum.UPDATE_DATA]: {
content: i18nT('account_team:log_update_data'),
typeLabel: i18nT('account_team:update_data'),
params: {} as {
name?: string;
collectionName: string;
datasetName: string;
datasetType: string;
}
},
[OperationLogEventEnum.DELETE_DATA]: {
content: i18nT('account_team:log_delete_data'),
typeLabel: i18nT('account_team:delete_data'),
params: {} as {
name?: string;
collectionName: string;
datasetName: string;
datasetType: string;
}
},
//SearchTest
[OperationLogEventEnum.SEARCH_TEST]: {
content: i18nT('account_team:log_search_test'),
typeLabel: i18nT('account_team:search_test'),
params: {} as { name?: string; datasetName: string; datasetType: string }
},
//Account
[OperationLogEventEnum.CHANGE_PASSWORD]: {
content: i18nT('account_team:log_change_password'),
typeLabel: i18nT('account_team:change_password'),
params: {} as { name?: string }
},
[OperationLogEventEnum.CHANGE_NOTIFICATION_SETTINGS]: {
content: i18nT('account_team:log_change_notification_settings'),
typeLabel: i18nT('account_team:change_notification_settings'),
params: {} as { name?: string }
},
[OperationLogEventEnum.CHANGE_MEMBER_NAME_ACCOUNT]: {
content: i18nT('account_team:log_change_member_name_self'),
typeLabel: i18nT('account_team:change_member_name_self'),
params: {} as { name?: string; oldName: string; newName: string }
},
[OperationLogEventEnum.PURCHASE_PLAN]: {
content: i18nT('account_team:log_purchase_plan'),
typeLabel: i18nT('account_team:purchase_plan'),
params: {} as { name?: string }
},
[OperationLogEventEnum.EXPORT_BILL_RECORDS]: {
content: i18nT('account_team:log_export_bill_records'),
typeLabel: i18nT('account_team:export_bill_records'),
params: {} as { name?: string }
},
[OperationLogEventEnum.CREATE_INVOICE]: {
content: i18nT('account_team:log_create_invoice'),
typeLabel: i18nT('account_team:create_invoice'),
params: {} as { name?: string }
},
[OperationLogEventEnum.SET_INVOICE_HEADER]: {
content: i18nT('account_team:log_set_invoice_header'),
typeLabel: i18nT('account_team:set_invoice_header'),
params: {} as { name?: string }
},
[OperationLogEventEnum.CREATE_API_KEY]: {
content: i18nT('account_team:log_create_api_key'),
typeLabel: i18nT('account_team:create_api_key'),
params: {} as { name?: string; keyName: string }
},
[OperationLogEventEnum.UPDATE_API_KEY]: {
content: i18nT('account_team:log_update_api_key'),
typeLabel: i18nT('account_team:update_api_key'),
params: {} as { name?: string; keyName: string }
},
[OperationLogEventEnum.DELETE_API_KEY]: {
content: i18nT('account_team:log_delete_api_key'),
typeLabel: i18nT('account_team:delete_api_key'),
params: {} as { name?: string; keyName: string }
}
} as const;

View File

@@ -0,0 +1,36 @@
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { i18nT } from '../../../web/i18n/utils';
export function getI18nAppType(type: AppTypeEnum): string {
if (type === AppTypeEnum.folder) return i18nT('account_team:type.Folder');
if (type === AppTypeEnum.simple) return i18nT('account_team:type.Simple bot');
if (type === AppTypeEnum.workflow) return i18nT('account_team:type.Workflow bot');
if (type === AppTypeEnum.plugin) return i18nT('account_team:type.Plugin');
if (type === AppTypeEnum.httpPlugin) return i18nT('account_team:type.Http plugin');
if (type === AppTypeEnum.toolSet) return i18nT('account_team:type.Tool set');
if (type === AppTypeEnum.tool) return i18nT('account_team:type.Tool');
return i18nT('common:UnKnow');
}
export function getI18nCollaboratorItemType(
tmbId: string | undefined,
groupId: string | undefined,
orgId: string | undefined
): string {
if (tmbId) return i18nT('account_team:member');
if (groupId) return i18nT('account_team:group');
if (orgId) return i18nT('account_team:department');
return i18nT('common:UnKnow');
}
export function getI18nDatasetType(type: DatasetTypeEnum | string): string {
if (type === DatasetTypeEnum.folder) return i18nT('account_team:dataset.folder_dataset');
if (type === DatasetTypeEnum.dataset) return i18nT('account_team:dataset.common_dataset');
if (type === DatasetTypeEnum.websiteDataset) return i18nT('account_team:dataset.website_dataset');
if (type === DatasetTypeEnum.externalFile) return i18nT('account_team:dataset.external_file');
if (type === DatasetTypeEnum.apiDataset) return i18nT('account_team:dataset.api_file');
if (type === DatasetTypeEnum.feishu) return i18nT('account_team:dataset.feishu_dataset');
if (type === DatasetTypeEnum.yuque) return i18nT('account_team:dataset.yuque_dataset');
return i18nT('common:UnKnow');
}

View File

@@ -8,6 +8,9 @@
"assign_permission": "Permission change",
"change_department_name": "Department Editor",
"change_member_name": "Member name change",
"change_member_name_self": "Change member name",
"change_notification_settings": "Change the way to receive notifications",
"change_password": "change password",
"confirm_delete_from_org": "Confirm to move {{username}} out of the department?",
"confirm_delete_from_team": "Confirm to move {{username}} out of the team?",
"confirm_delete_group": "Confirm to delete group?",
@@ -15,12 +18,29 @@
"confirm_forbidden": "Confirm forbidden",
"confirm_leave_team": "Confirmed to leave the team? \nAfter exiting, all your resources in the team are transferred to the team owner.",
"copy_link": "Copy link",
"create_api_key": "Create API key",
"create_app": "Create an application",
"create_app_copy": "Create a copy of the application",
"create_app_folder": "Create an application folder",
"create_app_publish_channel": "Create a sharing channel",
"create_data": "Insert data",
"create_dataset": "Create a knowledge base",
"create_dataset_folder": "Create a Knowledge Base Folder",
"create_department": "Create a sub-department",
"create_group": "Create group",
"create_invitation_link": "Create Invitation Link",
"create_invoice": "Issuing invoices",
"create_org": "Create organization",
"create_sub_org": "Create sub-organization",
"delete": "delete",
"delete_api_key": "Delete the API key",
"delete_app": "Delete the workbench application",
"delete_app_collaborator": "App permissions delete",
"delete_app_publish_channel": "Delete the publishing channel",
"delete_collection": "Delete a collection",
"delete_data": "Delete data",
"delete_dataset": "Delete the knowledge base",
"delete_dataset_collaborator": "Knowledge Base Permission Deletion",
"delete_department": "Delete sub-department",
"delete_from_org": "Move out of department",
"delete_from_team": "Move out of the team",
@@ -31,6 +51,9 @@
"edit_member_tip": "Name",
"edit_org_info": "Edit organization information",
"expires": "Expiration time",
"export_app_chat_log": "Export the app chat history",
"export_bill_records": "Export billing history",
"export_dataset": "Export knowledge base",
"export_members": "Export members",
"forbid_hint": "After forbidden, this invitation link will become invalid. This action is irreversible. Are you sure you want to deactivate?",
"forbid_success": "Forbid success",
@@ -56,24 +79,69 @@
"log_assign_permission": "[{{name}}] Updated the permissions of [{{objectName}}]: [Application creation: [{{appCreate}}], Knowledge Base: [{{datasetCreate}}], API Key: [{{apiKeyCreate}}], Management: [{{manage}}]]",
"log_change_department": "【{{name}}】Updated department【{{departmentName}}】",
"log_change_member_name": "【{{name}}】Rename member [{{memberName}}] to 【{{newName}}】",
"log_change_member_name_self": "【{{name}}】Change your member name to 【{{newName}}】",
"log_change_notification_settings": "【{{name}}】A change notification receiving method operation was carried out",
"log_change_password": "【{{name}}】The password change operation was performed",
"log_create_api_key": "【{{name}}】Create an API key named [{{keyName}}]",
"log_create_app": "【{{name}}】Created [{{appType}}] named [{{appName}}]",
"log_create_app_copy": "【{{name}}] Created a copy of [{{appType}}] named [{{appName}}]",
"log_create_app_folder": "【{{name}}】Create a folder named [{{folderName}}]",
"log_create_app_publish_channel": "[{{name}}] Created a channel named [{{channelName}}] for [{{appType}}] called [{{appName}}].",
"log_create_collection": "[{{name}}] Create a collection named [{{collectionName}}] in [{{datasetType}}] called [{{datasetName}}].",
"log_create_data": "[{{name}}] Insert data into a collection named [{{datasetName}}] in [{{datasetType}}] called [{{datasetName}}] into a collection named [{{collectionName}}]",
"log_create_dataset": "【{{name}}】Created 【{{datasetType}}】 named 【{{datasetName}}】",
"log_create_dataset_folder": "【{{name}}】Created a folder named {{folderName}}】",
"log_create_department": "【{{name}}】Department【{{departmentName}}】",
"log_create_group": "【{{name}}】Created group [{{groupName}}]",
"log_create_invitation_link": "【{{name}}】Created invitation link【{{link}}】",
"log_create_invoice": "【{{name}}】Invoice operation was carried out",
"log_delete_api_key": "【{{name}}】Deleted the API key named [{{keyName}}]",
"log_delete_app": "【{{name}}】Delete the [{{appType}}] named [{{appName}}]",
"log_delete_app_collaborator": "【{{name}}】Delete the [itemName] permission named [itemValueName] in [{{appType}}] named [{{appName}}] delete the [itemName] permission named [{{appName}}] named [{{appName}}] named [{{appName}}] deleted the [{{itemName}}] permission named [{{itemValueName}}] named [{{appType}}] named [{{appName}}].",
"log_delete_app_publish_channel": "[{{name}}] [{{appType}}] named [{{appName}}] deleted the channel named [{{channelName}}]",
"log_delete_collection": "[{{name}}] Deleted a collection named [{{collectionName}}] in [{{datasetType}}] named [{{datasetName}}].",
"log_delete_data": "[{{name}}] Delete data in a collection named [{{datasetName}}] in a collection named [{{datasetName}}]",
"log_delete_dataset": "【{{name}}】Deleted 【{{datasetType}}】 named [{{datasetName}}]",
"log_delete_dataset_collaborator": "【{{name}}】Updated the collaborators of 【{{appType}}】 named 【{{appName}}】 to: Organization: 【{{orgList}}】, Group: 【{{groupList}}】, Member 【{{tmbList}}】; updated the permissions to: Read permission: 【{{readPermission}}】, Write permission: 【{{writePermission}}】, Administrator permission: 【{{managePermission}}】",
"log_delete_department": "{{name}} deleted department {{departmentName}}",
"log_delete_group": "{{name}} deleted group {{groupName}}",
"log_details": "Details",
"log_export_app_chat_log": "【{{name}}】Export a chat history called [{{appName}}] called [{{appType}}]",
"log_export_bill_records": "【{{name}}】Export the billing record",
"log_export_dataset": "[{{name}}] Export [{{datasetType}}] called [{{datasetName}}]",
"log_join_team": "【{{name}}】Join the team through the invitation link 【{{link}}】",
"log_kick_out_team": "{{name}} removed member {{memberName}}",
"log_login": "【{{name}}】Logined in the system",
"log_move_app": "【{{name}}】Move [{{appType}}] named [{{appName}}] to [{{targetFolderName}}]",
"log_move_dataset": "【{{name}}】Move [{{datasetType}}] named [{{datasetName}}] to [{{targetFolderName}}]",
"log_recover_team_member": "【{{name}}】Restored member【{{memberName}}】",
"log_relocate_department": "【{{name}}】Displayed department【{{departmentName}}】",
"log_retrain_collection": "[{{name}}] Retrained the collection named [{{collectionName}}] in [{{datasetType}}] called [{{datasetName}}].",
"log_search_test": "【{{name}}】Perform a search test operation on [{{datasetType}}] named [{{datasetName}}]",
"log_set_invoice_header": "【{{name}}】The invoice header operation was set up",
"log_time": "Operation time",
"log_transfer_app_ownership": "【{{name}}] Transfer ownership of [{{appType}}] named [{{appName}}] from [{oldOwnerName}}] to [{{newOwnerName}}]",
"log_transfer_dataset_ownership": "[{{name}}] Transfer ownership of [{{datasetType}}] named [{{datasetName}}] from [{oldOwnerName}}] to [{{newOwnerName}}]",
"log_type": "Operation Type",
"log_update_api_key": "【{{name}}】Updated the API key named [{{keyName}}]",
"log_update_app_collaborator": "[{{name}}] Updated the collaborator named [{{appName}}] to: Organization: [{{orgList}}], Group: [{{groupList}}], Member [{{tmbList}}]; permissions updated to: Read permission: [{{readPermission}}], Write permission: [{{writePermission}}], Administrator permission: [{{managePermission}}]",
"log_update_app_info": "[{{name}}] updated [{{appType}}] named [{{appName}}]: [{{newItemNames}}] to [{{newItemValues}}]",
"log_update_app_publish_channel": "[{{name}}] Updated a channel named [{{channelName}}] for [{{appType}}] called [{{appName}}].",
"log_update_collection": "[{{name}}] Updated a collection named [{{collectionName}}] in [{{datasetType}}] called [{{datasetName}}].",
"log_update_data": "【{{name}}】Update data in a collection named 【{{datasetName}}】[{{datasetType}}] with [{{datasetType}}] with [{{collectionName}}]",
"log_update_dataset": "【{{name}}】Updated [{{datasetType}}] named [{{datasetName}}]",
"log_update_dataset_collaborator": "[{{name}}] Updated the collaborator named [{{datasetName}}] to: Organization: [{{orgList}}], Group: [{{groupList}}], Member [{{tmbList}}]; permissions updated to: [{{readPermission}}], [{{writePermission}}], [{{managePermission}}]",
"log_update_publish_app": "【{{name}}】【{{operationName}}】【{{appType}}】 named [{{appName}}】",
"log_user": "Operator",
"login": "Log in",
"manage_member": "Managing members",
"member": "member",
"department": "department",
"update": "update",
"save_and_publish": "save and publish",
"member_group": "Belonging to member group",
"move_app": "App location movement",
"move_dataset": "Mobile Knowledge Base",
"move_member": "Move member",
"move_org": "Move organization",
"notification_recieve": "Team notification reception",
@@ -92,6 +160,7 @@
"permission_manage": "Admin",
"permission_manage_tip": "Can manage members, create groups, manage all groups, and assign permissions to groups and members",
"please_bind_contact": "Please bind the contact information",
"purchase_plan": "Upgrade package",
"recover_team_member": "Member Recovery",
"relocate_department": "Department Mobile",
"remark": "remark",
@@ -99,21 +168,49 @@
"restore_tip": "Confirm to join the team {{username}}? \nOnly the availability and related permissions of this member account are restored, and the resources under the account cannot be restored.",
"restore_tip_title": "Recovery confirmation",
"retain_admin_permissions": "Keep administrator rights",
"retrain_collection": "Retrain the set",
"search_log": "Search log",
"search_member": "Search for members",
"search_member_group_name": "Search member/group name",
"search_org": "Search Department",
"search_test": "Search Test",
"set_invoice_header": "Set up invoice header",
"set_name_avatar": "Team avatar",
"sync_immediately": "Synchronize now",
"sync_member_failed": "Synchronization of members failed",
"sync_member_success": "Synchronize members successfully",
"total_team_members": "{{amount}} members in total",
"transfer_ownership": "transfer owner",
"total_team_members": "Total {{amount}} members",
"transfer_app_ownership": "Transfer app ownership",
"transfer_dataset_ownership": "Transfer dataset ownership",
"transfer_ownership": "Transfer ownership",
"type.Folder": "Folder",
"type.Http plugin": "HTTP Plugin",
"type.Plugin": "Plugin",
"type.Simple bot": "Simple App",
"type.Tool": "Tool",
"type.Tool set": "Toolset",
"type.Workflow bot": "Workflow",
"dataset.folder_dataset": "Folder",
"dataset.common_dataset": "Dataset",
"dataset.website_dataset": "Website Sync",
"dataset.external_file": "External File",
"dataset.api_file": "API Import",
"dataset.feishu_dataset": "Feishu Spreadsheet",
"dataset.yuque_dataset": "Yuque Knowledge Base",
"unlimited": "Unlimited",
"update_api_key": "Update API key",
"update_app_collaborator": "Apply permission changes",
"update_app_info": "Application information modification",
"update_app_publish_channel": "Update the release channel",
"update_collection": "Update the collection",
"update_data": "Update data",
"update_dataset": "Update the knowledge base",
"update_dataset_collaborator": "Knowledge Base Permission Changes",
"update_publish_app": "Application update",
"used_times_limit": "Limit",
"user_name": "username",
"user_team_invite_member": "Invite members",
"user_team_leave_team": "Leave the team",
"user_team_leave_team_failed": "Failure to leave the team",
"waiting": "To be accepted"
}
}

View File

@@ -197,6 +197,9 @@
"type.MCP tools": "MCP Toolset",
"type.MCP_tools_url": "MCP Address",
"type.Plugin": "Plugin",
"type.Folder": "Folder",
"type.Tool set": "Toolset",
"type.Tool": "Tool",
"type.Simple bot": "Simple App",
"type.Workflow bot": "Workflow",
"type.error.Workflow data is empty": "No workflow data was obtained",
@@ -238,4 +241,4 @@
"workflow.user_file_input_desc": "Links to documents and images uploaded by users.",
"workflow.user_select": "User Select",
"workflow.user_select_tip": "This module can configure multiple options for selection during the dialogue. Different options can lead to different workflow branches."
}
}

View File

@@ -215,6 +215,7 @@
"core.app.Interval timer run": "Scheduled Execution",
"core.app.Interval timer tip": "Can Execute App on Schedule",
"core.app.Make a brief introduction of your app": "Give Your AI App an Introduction",
"core.app.name": "name",
"core.app.Name and avatar": "Avatar & Name",
"core.app.Publish": "Publish",
"core.app.Publish Confirm": "Confirm to Publish App? This Will Immediately Update the App Status on All Publishing Channels.",
@@ -1305,4 +1306,4 @@
"zoomin_tip_mac": "Zoom Out ⌘ -",
"zoomout_tip": "Zoom In ctrl +",
"zoomout_tip_mac": "Zoom In ⌘ +"
}
}

View File

@@ -1,4 +1,5 @@
{
"account_team.delete_dataset": "删除知识库",
"active_model": "可用模型",
"add_default_model": "添加预设模型",
"api_key": "API 密钥",

View File

@@ -8,6 +8,9 @@
"assign_permission": "权限变更",
"change_department_name": "部门编辑",
"change_member_name": "成员改名",
"change_member_name_self": "变更成员名",
"change_notification_settings": "变更通知接收途径",
"change_password": "更改密码",
"confirm_delete_from_org": "确认将 {{username}} 移出部门?",
"confirm_delete_from_team": "确认将 {{username}} 移出团队?",
"confirm_delete_group": "确认删除群组?",
@@ -15,12 +18,30 @@
"confirm_forbidden": "确认停用",
"confirm_leave_team": "确认离开该团队? \n退出后您在该团队所有的资源均转让给团队所有者。",
"copy_link": "复制链接",
"create_api_key": "创建api密钥",
"create_app": "创建应用",
"create_app_copy": "创建应用副本",
"create_app_folder": "创建应用文件夹",
"create_app_publish_channel": "创建分享渠道",
"create_collection": "创建集合",
"create_data": "插入数据",
"create_dataset": "创建知识库",
"create_dataset_folder": "创建知识库文件夹",
"create_department": "创建子部门",
"create_group": "创建群组",
"create_invitation_link": "创建邀请链接",
"create_invoice": "开发票",
"create_org": "创建部门",
"create_sub_org": "创建子部门",
"delete": "删除",
"delete_api_key": "删除api密钥",
"delete_app": "删除工作台应用",
"delete_app_collaborator": "应用权限删除",
"delete_app_publish_channel": "删除发布渠道",
"delete_collection": "删除集合",
"delete_data": "删除数据",
"delete_dataset": "删除知识库",
"delete_dataset_collaborator": "知识库权限删除",
"delete_department": "删除子部门",
"delete_from_org": "移出部门",
"delete_from_team": "移出团队",
@@ -31,6 +52,9 @@
"edit_member_tip": "成员名",
"edit_org_info": "编辑部门信息",
"expires": "过期时间",
"export_app_chat_log": "导出应用聊天记录",
"export_bill_records": "导出账单记录",
"export_dataset": "导出知识库",
"export_members": "导出成员",
"forbid_hint": "停用后,该邀请链接将失效。 该操作不可撤销,是否确认停用?",
"forbid_success": "停用成功",
@@ -56,24 +80,70 @@
"log_assign_permission": "【{{name}}】更新了【{{objectName}}】的权限:[应用创建:【{{appCreate}}】, 知识库:【{{datasetCreate}}】, API密钥:【{{apiKeyCreate}}】, 管理:【{{manage}}】]",
"log_change_department": "【{{name}}】更新了部门【{{departmentName}}】",
"log_change_member_name": "【{{name}}】将成员【{{memberName}}】重命名为【{{newName}}】",
"log_change_member_name_self": "【{{name}}】把自己的成员名从【{{oldName}}】变更为【{{newName}}】",
"log_change_notification_settings": "【{{name}}】进行了变更通知接收途径操作",
"log_change_password": "【{{name}}】进行了变更密码操作",
"log_create_api_key": "【{{name}}】创建了名为【{{keyName}}】的api密钥",
"log_create_app": "【{{name}}】创建了名为【{{appName}}】的【{{appType}}】",
"log_create_app_copy": "【{{name}}】给名为【{{appName}}】的【{{appType}}】创建了一个副本",
"log_create_app_folder": "【{{name}}】创建了名为【{{folderName}}】的文件夹",
"log_create_app_publish_channel": "【{{name}}】给名为【{{appName}}】的【{{appType}}】创建了名为【{{channelName}}】的渠道",
"log_create_collection": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】创建了名为【{{collectionName}}】的集合",
"log_create_data": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】往名为【{{collectionName}}】的集合插入数据",
"log_create_dataset": "【{{name}}】创建了名为【{{datasetName}}】的【{{datasetType}}】",
"log_create_dataset_folder": "【{{name}}】创建了名为{{folderName}}】的文件夹",
"log_create_department": "【{{name}}】创建了部门【{{departmentName}}】",
"log_create_group": "【{{name}}】创建了群组【{{groupName}}】",
"log_create_invitation_link": "【{{name}}】创建了邀请链接【{{link}}】",
"log_create_invoice": "【{{name}}】进行了开发票操作",
"log_delete_api_key": "【{{name}}】删除了名为【{{keyName}}】的api密钥",
"log_delete_app": "【{{name}}】将名为【{{appName}}】的【{{appType}}】删除",
"log_delete_app_collaborator": "【{{name}}】将名为【{{appName}}】的【{{appType}}】中名为【{{itemValueName}}】的【{{itemName}}】权限删除",
"log_delete_app_publish_channel": "【{{name}}】名为【{{appName}}】的【{{appType}}】删除了名为【{{channelName}}】的渠道",
"log_delete_collection": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】删除了名为【{{collectionName}}】的集合",
"log_delete_data": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】在名为【{{collectionName}}】的集合删除数据",
"log_delete_dataset": "【{{name}}】删除了名为【{{datasetName}}】的【{{datasetType}}】",
"log_delete_dataset_collaborator": "【{{name}}】将名为【{{datasetName}}】的【{{datasetType}}】中名为【itemValueName】的【itemName】权限删除",
"log_delete_department": "【{{name}}】删除了部门【{{departmentName}}】",
"log_delete_group": "【{{name}}】删除了群组【{{groupName}}】",
"log_details": "详情",
"log_export_app_chat_log": "【{{name}}】导出了名为【{{appName}}】的【{{appType}}】的聊天记录",
"log_export_bill_records": "【{{name}}】导出了账单记录",
"log_export_dataset": "【{{name}}】导出了名为【{{datasetName}}】的【{{datasetType}}】",
"log_join_team": "【{{name}}】通过邀请链接【{{link}}】加入团队",
"log_kick_out_team": "【{{name}}】移除了成员【{{memberName}}】",
"log_login": "【{{name}}】登录了系统",
"log_move_app": "【{{name}}】将名为【{{appName}}】的【{{appType}}】移动到【{{targetFolderName}}】",
"log_move_dataset": "【{{name}}】将名为【{{datasetName}}】的【{{datasetType}}】移动到【{{targetFolderName}}】",
"log_purchase_plan": "【{{name}}】购买了套餐",
"log_recover_team_member": "【{{name}}】恢复了成员【{{memberName}}】",
"log_relocate_department": "【{{name}}】移动了部门【{{departmentName}}】",
"log_retrain_collection": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】重新训练了名为【{{collectionName}}】的集合",
"log_search_test": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】执行搜索测试操作",
"log_set_invoice_header": "【{{name}}】进行了设置发票抬头操作",
"log_time": "操作时间",
"log_transfer_app_ownership": "【{{name}}】将名为【{{appName}}】的【{{appType}}】的所有权从【{{oldOwnerName}}】转移到【{{newOwnerName}}】",
"log_transfer_dataset_ownership": "【{{name}}】将名为【{{datasetName}}】的【{{datasetType}}】的所有权从【{{oldOwnerName}}】转移到【{{newOwnerName}}】",
"log_type": "操作类型",
"log_update_api_key": "【{{name}}】更新了名为【{{keyName}}】的api密钥",
"log_update_app_collaborator": "【{{name}}】将名为【{{appName}}】的【{{appType}}】的合作者更新为:组织:【{{orgList}}】,群组:【{{groupList}}】,成员【{{tmbList}}】;权限更新为:读权限:【{{readPermission}}】,写权限:【{{writePermission}}】,管理员权限:【{{managePermission}}】",
"log_update_app_info": "【{{name}}】更新了名为【{{appName}}】的【{{appType}}】:【{{newItemNames}}】为【{{newItemValues}}】",
"log_update_app_publish_channel": "【{{name}}】给名为【{{appName}}】的【{{appType}}】更新了名为【{{channelName}}】的渠道",
"log_update_collection": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】更新了名为【{{collectionName}}】的集合",
"log_update_data": "【{{name}}】在名为【{{datasetName}}】的【{{datasetType}}】在名为【{{collectionName}}】的集合更新数据",
"log_update_dataset": "【{{name}}】更新了名为【{{datasetName}}】的【{{datasetType}}】",
"log_update_dataset_collaborator": "【{{name}}】将名为【{{datasetName}}】的【{{datasetType}}】的合作者更新为:组织:【{{orgList}}】,群组:【{{groupList}}】,成员【{{tmbList}}】;权限更新为:【{{readPermission}}】,【{{writePermission}}】,【{{managePermission}}】",
"log_update_publish_app": "【{{name}}】【{{operationName}}】名为【{{appName}}】的【{{appType}}】",
"log_user": "操作人员",
"login": "登录",
"manage_member": "管理成员",
"member": "成员",
"department": "部门",
"update": "更新",
"save_and_publish": "保存并发布",
"member_group": "所属群组",
"move_app": "应用位置移动",
"move_dataset": "移动知识库",
"move_member": "移动成员",
"move_org": "移动部门",
"notification_recieve": "团队通知接收",
@@ -92,6 +162,7 @@
"permission_manage": "管理员",
"permission_manage_tip": "可以管理成员、创建群组、管理所有群组、为群组和成员分配权限",
"please_bind_contact": "请绑定联系方式",
"purchase_plan": "升级套餐",
"recover_team_member": "成员恢复",
"relocate_department": "部门移动",
"remark": "备注",
@@ -99,21 +170,49 @@
"restore_tip": "确认将 {{username}} 加入团队吗?仅恢复该成员账号可用性及相关权限,无法恢复账号下资源。",
"restore_tip_title": "恢复确认",
"retain_admin_permissions": "保留管理员权限",
"retrain_collection": "重新训练集合",
"search_log": "搜索日志",
"search_member": "搜索成员",
"search_member_group_name": "搜索成员/群组名称",
"search_org": "搜索部门",
"search_test": "搜索测试",
"set_invoice_header": "设置发票抬头",
"set_name_avatar": "团队头像 & 团队名",
"sync_immediately": "立即同步",
"sync_member_failed": "同步成员失败",
"sync_member_success": "同步成员成功",
"total_team_members": "共 {{amount}} 名成员",
"transfer_app_ownership": "转移应用所有权",
"transfer_dataset_ownership": "转移知识库所有权",
"transfer_ownership": "转让所有者",
"type.Folder": "文件夹",
"type.Http plugin": "HTTP 插件",
"type.Plugin": "插件",
"type.Simple bot": "简易应用",
"type.Tool": "工具",
"type.Tool set": "工具集",
"type.Workflow bot": "工作流",
"dataset.folder_dataset": "文件夹",
"dataset.common_dataset": "知识库",
"dataset.website_dataset": "网站同步",
"dataset.external_file": "外部文件",
"dataset.api_file": "API导入",
"dataset.feishu_dataset": "飞书多维表格",
"dataset.yuque_dataset": "语雀知识库",
"unlimited": "无限制",
"update_api_key": "更新api密钥",
"update_app_collaborator": "应用权限更改",
"update_app_info": "应用信息修改",
"update_app_publish_channel": "更新发布渠道",
"update_collection": "更新集合",
"update_data": "更新数据",
"update_dataset": "更新知识库",
"update_dataset_collaborator": "知识库权限更改",
"update_publish_app": "应用更新",
"used_times_limit": "有效人数",
"user_name": "用户名",
"user_team_invite_member": "邀请成员",
"user_team_leave_team": "离开团队",
"user_team_leave_team_failed": "离开团队失败",
"waiting": "待接受"
}
}

View File

@@ -189,6 +189,7 @@
"type.Create simple bot tip": "通过填表单形式,创建简单的 AI 应用,适合新手",
"type.Create workflow bot": "创建工作流",
"type.Create workflow tip": "通过低代码的方式,构建逻辑复杂的多轮对话 AI 应用,推荐高级玩家使用",
"type.Folder": "文件夹",
"type.Http plugin": "HTTP 插件",
"type.Import from json": "导入 JSON 配置",
"type.Import from json tip": "通过 JSON 配置文件,直接创建应用",
@@ -198,6 +199,8 @@
"type.MCP_tools_url": "MCP 地址",
"type.Plugin": "插件",
"type.Simple bot": "简易应用",
"type.Tool": "工具",
"type.Tool set": "工具集",
"type.Workflow bot": "工作流",
"type.error.Workflow data is empty": "没有获取到工作流数据",
"type.error.workflowresponseempty": "响应内容为空",
@@ -238,4 +241,4 @@
"workflow.user_file_input_desc": "用户上传的文档和图片链接",
"workflow.user_select": "用户选择",
"workflow.user_select_tip": "该模块可配置多个选项,以供对话时选择。不同选项可导向不同工作流支线"
}
}

View File

@@ -215,6 +215,7 @@
"core.app.Interval timer run": "定时执行",
"core.app.Interval timer tip": "可定时执行应用",
"core.app.Make a brief introduction of your app": "给你的 AI 应用一个介绍",
"core.app.name": "名称",
"core.app.Name and avatar": "头像 & 名称",
"core.app.Publish": "发布",
"core.app.Publish Confirm": "确认发布应用?会立即更新所有发布渠道的应用状态。",
@@ -1305,4 +1306,4 @@
"zoomin_tip_mac": "缩小 ⌘ -",
"zoomout_tip": "放大 ctrl +",
"zoomout_tip_mac": "放大 ⌘ +"
}
}

View File

@@ -8,6 +8,9 @@
"assign_permission": "權限變更",
"change_department_name": "部門編輯",
"change_member_name": "成員改名",
"change_member_name_self": "變更成員名",
"change_notification_settings": "變更通知接收途徑",
"change_password": "更改密碼",
"confirm_delete_from_org": "確認將 {{username}} 移出部門?",
"confirm_delete_from_team": "確認將 {{username}} 移出團隊?",
"confirm_delete_group": "確認刪除群組?",
@@ -15,12 +18,29 @@
"confirm_forbidden": "確認停用",
"confirm_leave_team": "確認離開該團隊? \n結束後您在該團隊所有的資源轉讓給團隊所有者。",
"copy_link": "複製連結",
"create_api_key": "創建api密鑰",
"create_app": "創建應用",
"create_app_copy": "創建應用副本",
"create_app_folder": "創建應用文件夾",
"create_app_publish_channel": "創建分享渠道",
"create_data": "插入數據",
"create_dataset": "創建知識庫",
"create_dataset_folder": "創建知識庫文件夾",
"create_department": "創建子部門",
"create_group": "建立群組",
"create_invitation_link": "建立邀請連結",
"create_invoice": "開發票",
"create_org": "建立部門",
"create_sub_org": "建立子部門",
"delete": "刪除",
"delete_api_key": "刪除api密鑰",
"delete_app": "刪除工作台應用",
"delete_app_collaborator": "應用權限刪除",
"delete_app_publish_channel": "刪除發布渠道",
"delete_collection": "刪除集合",
"delete_data": "刪除數據",
"delete_dataset": "刪除知識庫",
"delete_dataset_collaborator": "知識庫權限刪除",
"delete_department": "刪除子部門",
"delete_from_org": "移出部門",
"delete_from_team": "移出團隊",
@@ -31,6 +51,9 @@
"edit_member_tip": "成員名",
"edit_org_info": "編輯部門資訊",
"expires": "過期時間",
"export_app_chat_log": "導出應用聊天記錄",
"export_bill_records": "導出賬單記錄",
"export_dataset": "導出知識庫",
"export_members": "導出成員",
"forbid_hint": "停用後,該邀請連結將失效。該操作不可撤銷,是否確認停用?",
"forbid_success": "停用成功",
@@ -56,24 +79,69 @@
"log_assign_permission": "【{{name}}】更新了【{{objectName}}】的權限:[應用創建:【{{appCreate}}】, 知識庫:【{{datasetCreate}}】, API密鑰:【{{apiKeyCreate}}】, 管理:【{{manage}}】]",
"log_change_department": "【{{name}}】更新了部門【{{departmentName}}】",
"log_change_member_name": "【{{name}}】將成員【{{memberName}}】重命名為【{{newName}}】",
"log_change_member_name_self": "【{{name}}】變更自己的成員名為【{{newName}}】",
"log_change_notification_settings": "【{{name}}】進行了變更通知接收途徑操作",
"log_change_password": "【{{name}}】進行了變更密碼操作",
"log_create_api_key": "【{{name}}】創建了名為【{{keyName}}】的api密鑰",
"log_create_app": "【{{name}}】創建了名為【{{appName}}】的【{{appType}}】",
"log_create_app_copy": "【{{name}}】給名為【{{appName}}】的【{{appType}}】創建了一個副本",
"log_create_app_folder": "【{{name}}】創建了名為【{{folderName}}】的文件夾",
"log_create_app_publish_channel": "【{{name}}】給名為【{{appName}}】的【{{appType}}】創建了名為【{{channelName}}】的渠道",
"log_create_collection": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】創建了名為【{{collectionName}}】的集合",
"log_create_data": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】往名為【{{collectionName}}】的集合插入數據",
"log_create_dataset": "【{{name}}】創建了名為【{{datasetName}}】的【{{datasetType}}】",
"log_create_dataset_folder": "【{{name}}】創建了名為{{folderName}}】的文件夾",
"log_create_department": "【{{name}}】創建了部門【{{departmentName}}】",
"log_create_group": "【{{name}}】創建了群組【{{groupName}}】",
"log_create_invitation_link": "【{{name}}】創建了邀請鏈接【{{link}}】",
"log_create_invoice": "【{{name}}】進行了開發票操作",
"log_delete_api_key": "【{{name}}】刪除了名為【{{keyName}}】的api密鑰",
"log_delete_app": "【{{name}}】將名為【{{appName}}】的【{{appType}}】刪除",
"log_delete_app_collaborator": "【{{name}}】將名為【{{appName}}】的【{{appType}}】中名為【{{itemValueName}}】的【{{itemName}}】權限刪除",
"log_delete_app_publish_channel": "【{{name}}】名為【{{appName}}】的【{{appType}}】刪除了名為【{{channelName}}】的渠道",
"log_delete_collection": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】刪除了名為【{{collectionName}}】的集合",
"log_delete_data": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】在名為【{{collectionName}}】的集合刪除數據",
"log_delete_dataset": "【{{name}}】刪除了名為【{{datasetName}}】的【{{datasetType}}】",
"log_delete_dataset_collaborator": "【{{name}}】將名為【{{datasetName}}】的【{{datasetType}}】中名為【itemValueName】的【itemName】權限刪除",
"log_delete_department": "{{name}} 刪除了部門 {{departmentName}}",
"log_delete_group": "{{name}} 刪除了群組 {{groupName}}",
"log_details": "詳情",
"log_export_app_chat_log": "【{{name}}】導出了名為【{{appName}}】的【{{appType}}】的聊天記錄",
"log_export_bill_records": "【{{name}}】導出了賬單記錄",
"log_export_dataset": "【{{name}}】導出了名為【{{datasetName}}】的【{{datasetType}}】",
"log_join_team": "【{{name}}】通過邀請鏈接【{{link}}】加入團隊",
"log_kick_out_team": "{{name}} 移除了成員 {{memberName}}",
"log_login": "【{{name}}】登錄了系統",
"log_move_app": "【{{name}}】將名為【{{appName}}】的【{{appType}}】移動到【{{targetFolderName}}】",
"log_move_dataset": "【{{name}}】將名為【{{datasetName}}】的【{{datasetType}}】移動到【{{targetFolderName}}】",
"log_recover_team_member": "【{{name}}】恢復了成員【{{memberName}}】",
"log_relocate_department": "【{{name}}】移動了部門【{{departmentName}}】",
"log_retrain_collection": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】重新訓練了名為【{{collectionName}}】的集合",
"log_search_test": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】執行搜索測試操作",
"log_set_invoice_header": "【{{name}}】進行了設置發票抬頭操作",
"log_time": "操作時間",
"log_transfer_app_ownership": "【{{name}}】將名為【{{appName}}】的【{{appType}}】的所有權從【{{oldOwnerName}}】轉移到【{{newOwnerName}}】",
"log_transfer_dataset_ownership": "【{{name}}】將名為【{{datasetName}}】的【{{datasetType}}】的所有權從【{{oldOwnerName}}】轉移到【{{newOwnerName}}】",
"log_type": "操作類型",
"log_update_api_key": "【{{name}}】更新了名為【{{keyName}}】的api密鑰",
"log_update_app_collaborator": "【{{name}}】將名為【{{appName}}】的【{{appType}}】的合作者更新為:組織:【{{orgList}}】,群組:【{{groupList}}】,成員【{{tmbList}}】;權限更新為:讀權限:【{{readPermission}}】,寫權限:【{{writePermission}}】,管理員權限:【{{managePermission}}】",
"log_update_app_info": "【{{name}}】更新了名為【{{appName}}】的【{{appType}}】:【{{newItemNames}}】為【{{newItemValues}}】",
"log_update_app_publish_channel": "【{{name}}】給名為【{{appName}}】的【{{appType}}】更新了名為【{{channelName}}】的渠道",
"log_update_collection": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】更新了名為【{{collectionName}}】的集合",
"log_update_data": "【{{name}}】在名為【{{datasetName}}】的【{{datasetType}}】在名為【{{collectionName}}】的集合更新數據",
"log_update_dataset": "【{{name}}】更新了名為【{{datasetName}}】的【{{datasetType}}】",
"log_update_dataset_collaborator": "【{{name}}】將名為【{{datasetName}}】的【{{datasetType}}】的合作者更新為:組織:【{{orgList}}】,群組:【{{groupList}}】,成員【{{tmbList}}】;權限更新為:【{{readPermission}}】,【{{writePermission}}】,【{{managePermission}}】",
"log_update_publish_app": "【{{name}}】【{{operationName}}】名為【{{appName}}】的【{{appType}}】",
"log_user": "操作人員",
"login": "登入",
"manage_member": "管理成員",
"member": "成員",
"department": "部門",
"update": "更新",
"save_and_publish": "儲存並發布",
"member_group": "所屬成員組",
"move_app": "應用位置移動",
"move_dataset": "移動知識庫",
"move_member": "移動成員",
"move_org": "行動部門",
"notification_recieve": "團隊通知接收",
@@ -92,6 +160,7 @@
"permission_manage": "管理員",
"permission_manage_tip": "可以管理成員、建立群組、管理所有群組、為群組和成員分配權限",
"please_bind_contact": "請綁定聯繫方式",
"purchase_plan": "升級套餐",
"recover_team_member": "成員恢復",
"relocate_department": "部門移動",
"remark": "備註",
@@ -99,21 +168,49 @@
"restore_tip": "確認將 {{username}} 加入團隊嗎?\n僅恢復該成員賬號可用性及相關權限無法恢復賬號下資源。",
"restore_tip_title": "恢復確認",
"retain_admin_permissions": "保留管理員權限",
"retrain_collection": "重新訓練集合",
"search_log": "搜索日誌",
"search_member": "搜索成員",
"search_member_group_name": "搜尋成員/群組名稱",
"search_org": "搜索部門",
"search_test": "搜索測試",
"set_invoice_header": "設置發票抬頭",
"set_name_avatar": "團隊頭像",
"sync_immediately": "立即同步",
"sync_member_failed": "同步成員失敗",
"sync_member_success": "同步成員成功",
"total_team_members": "共 {{amount}} 名成員",
"transfer_app_ownership": "轉移應用程式所有權",
"transfer_dataset_ownership": "轉移知識庫所有權",
"transfer_ownership": "轉讓所有者",
"type.Folder": "資料夾",
"type.Http plugin": "HTTP 外掛",
"type.Plugin": "外掛",
"type.Simple bot": "簡易應用程式",
"type.Tool": "工具",
"type.Tool set": "工具集",
"type.Workflow bot": "工作流程",
"dataset.folder_dataset": "資料夾",
"dataset.common_dataset": "知識庫",
"dataset.website_dataset": "網站同步",
"dataset.external_file": "外部文件",
"dataset.api_file": "API 匯入",
"dataset.feishu_dataset": "飛書多維表格",
"dataset.yuque_dataset": "語雀知識庫",
"unlimited": "無限制",
"update_api_key": "更新api密鑰",
"update_app_collaborator": "應用權限更改",
"update_app_info": "應用信息修改",
"update_app_publish_channel": "更新發布渠道",
"update_collection": "更新集合",
"update_data": "更新數據",
"update_dataset": "更新知識庫",
"update_dataset_collaborator": "知識庫權限更改",
"update_publish_app": "應用更新",
"used_times_limit": "有效人數",
"user_name": "使用者名稱",
"user_team_invite_member": "邀請成員",
"user_team_leave_team": "離開團隊",
"user_team_leave_team_failed": "離開團隊失敗",
"waiting": "待接受"
}
}

View File

@@ -198,6 +198,9 @@
"type.MCP_tools_url": "MCP 地址",
"type.Plugin": "外掛",
"type.Simple bot": "簡易應用程式",
"type.Folder": "資料夾",
"type.Tool set": "工具集",
"type.Tool": "工具",
"type.Workflow bot": "工作流程",
"type.error.Workflow data is empty": "沒有獲取到工作流數據",
"type.error.workflowresponseempty": "響應內容為空",
@@ -238,4 +241,4 @@
"workflow.user_file_input_desc": "使用者上傳的檔案和圖片連結",
"workflow.user_select": "使用者選擇",
"workflow.user_select_tip": "這個模組可以設定多個選項,供對話時選擇。不同選項可以導向不同的工作流程支線"
}
}

View File

@@ -215,6 +215,7 @@
"core.app.Interval timer run": "排程執行",
"core.app.Interval timer tip": "可排程執行應用程式",
"core.app.Make a brief introduction of your app": "為您的 AI 應用程式寫一段介紹",
"core.app.name": "名稱",
"core.app.Name and avatar": "頭像與名稱",
"core.app.Publish": "發布",
"core.app.Publish Confirm": "確認發布應用程式?這將立即更新所有發布管道的應用程式狀態。",
@@ -1305,4 +1306,4 @@
"zoomin_tip_mac": "縮小 ⌘ -",
"zoomout_tip": "放大 ctrl +",
"zoomout_tip_mac": "放大 ⌘ +"
}
}

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);