V4.8.18 feature (#3565)
* feat: org CRUD (#3380) * feat: add org schema * feat: org manage UI * feat: OrgInfoModal * feat: org tree view * feat: org management * fix: init root org * feat: org permission for app * feat: org support for dataset * fix: disable org role control * styles: opt type signatures * fix: remove unused permission * feat: delete org collaborator * perf: Team org ui (#3499) * perf: org ui * perf: org ui * feat: org auth for app & dataset (#3498) * feat: auth org resource permission * feat: org auth support for app & dataset * perf: org permission check (#3500) * i18n (#3501) * name * i18n * feat: support dataset changeOwner (#3483) * feat: support dataset changeOwner * chore: update dataset change owner api * feat: permission manage UI for org (#3503) * perf: password check;perf: image upload check;perf: sso login check (#3509) * perf: password check * perf: image upload check * perf: sso login check * force show update notification modal & fix login page text (#3512) * fix login page English text * update notification modal * perf: notify account (#3515) * perf(plugin): improve searXNG empty result handling and documentation (#3507) * perf(plugin): improve searXNG empty result handling and documentation * 修改了文档和代码部分无搜索的结果的反馈 * refactor: org pathId (#3516) * optimize payment process (#3517) * feat: support wecom sso (#3518) * feat: support wecom sso * chore: remove unused wecom js-sdk dependency * fix qrcode script (#3520) * fix qrcode script * i18n * perf: full text collection and search code;perf: rename function (#3519) * perf: full text collection and search code * perf: rename function * perf: notify modal * remove invalid code * perf: sso login * perf: pay process * 4.8.18 test (#3524) * perf: remove local token * perf: index * perf: file encoding;perf: leave team code;@c121914yu perf: full text search code (#3528) * perf: text encoding * perf: leave team code * perf: full text search code * fix: http status * perf: embedding search and vector avatar * perf: async read file (#3531) * refactor: team permission manager (#3535) * perf: classify org, group and member * refactor: team per manager * fix: missing functions * 4.8.18 test (#3543) * perf: login check * doc * perf: llm model config * perf: team clb config * fix: MemberModal UI (#3553) * fix: adapt MemberModal title and icon * fix: adapt member modal * fix: search input placeholder * fix: add button text * perf: org permission (#3556) * docs:用户答疑的官方文档补充 (#3540) * docs:用户答疑的官方文档补充 * 问题回答的内容修补 * share link random avatar (#3541) * share link random avatar * fix * delete unused code * share page avatar (#3558) * feat: init 4818 * share page avatar * feat: tmp upgrade code (#3559) * feat: tmp upgrade code * fulltext search test * update action * full text tmp code (#3561) * full text tmp code * fix: init * fix: init * remove tmp code * remove tmp code * 4818-alpha * 4.8.18 test (#3562) * full text tmp code * fix: init * upgrade code * account log * account log * perf: dockerfile * upgrade code * chore: update docs app template submission (#3564) --------- Co-authored-by: a.e. <49438478+I-Info@users.noreply.github.com> Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: Jiangween <145003935+Jiangween@users.noreply.github.com>
This commit is contained in:
123
projects/app/src/pages/api/admin/initv4818.ts
Normal file
123
projects/app/src/pages/api/admin/initv4818.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { delay } from '@fastgpt/global/common/system/utils';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
import { jiebaSplit } from '@fastgpt/service/common/string/jieba';
|
||||
import { MongoDatasetDataText } from '@fastgpt/service/core/dataset/data/dataTextSchema';
|
||||
import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { NextApiRequest, NextApiResponse } from 'next';
|
||||
|
||||
/*
|
||||
简单版迁移:直接升级到最新镜像,会去除 MongoDatasetData 里的索引。直接执行这个脚本。
|
||||
无缝迁移:
|
||||
1. 先用 4.8.18-tmp 版本,会同时有 MongoDatasetData 和 MongoDatasetDataText 两个表和索引,依然是 MongoDatasetData 生效。会同步更新两张表数据。
|
||||
2. 执行升级脚本,不要删除 MongoDatasetData 里的数据。
|
||||
3. 切换正式版镜像,让 MongoDatasetDataText 生效。
|
||||
4. 删除 MongoDatasetData 里的索引和多余字段。(4819 再删
|
||||
*/
|
||||
let success = 0;
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
await authCert({ req, authRoot: true });
|
||||
|
||||
const batchSize = req.body.batchSize || 500;
|
||||
success = 0;
|
||||
|
||||
const start = Date.now();
|
||||
await initData(batchSize);
|
||||
// await restore();
|
||||
console.log('Init data time:', Date.now() - start);
|
||||
|
||||
success = 0;
|
||||
|
||||
// batchUpdateFields();
|
||||
|
||||
return { success: true };
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
||||
|
||||
const restore = async () => {
|
||||
try {
|
||||
const data = await MongoDatasetData.findOne({ fullTextToken: { $exists: false } });
|
||||
if (!data) return;
|
||||
|
||||
data.fullTextToken = jiebaSplit({ text: `${data.q}\n${data.a}`.trim() });
|
||||
await data.save();
|
||||
|
||||
success++;
|
||||
console.log('Success:', success);
|
||||
|
||||
await restore();
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
await delay(500);
|
||||
await restore();
|
||||
}
|
||||
};
|
||||
|
||||
const initData = async (batchSize: number) => {
|
||||
while (true) {
|
||||
try {
|
||||
// 找到没有初始化的数据
|
||||
const dataList = await MongoDatasetData.find(
|
||||
{
|
||||
initFullText: { $exists: false }
|
||||
},
|
||||
'_id teamId datasetId collectionId fullTextToken'
|
||||
)
|
||||
.limit(batchSize)
|
||||
.lean();
|
||||
|
||||
if (dataList.length === 0) break;
|
||||
|
||||
try {
|
||||
await MongoDatasetDataText.insertMany(
|
||||
dataList.map((item) => ({
|
||||
teamId: item.teamId,
|
||||
datasetId: item.datasetId,
|
||||
collectionId: item.collectionId,
|
||||
dataId: item._id,
|
||||
fullTextToken: item.fullTextToken
|
||||
})),
|
||||
{ ordered: false, lean: true }
|
||||
);
|
||||
} catch (error: any) {
|
||||
if (error.code === 11000) {
|
||||
console.log('Duplicate key error');
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 把成功插入的新数据的 dataId 更新为已初始化
|
||||
await MongoDatasetData.updateMany(
|
||||
{ _id: { $in: dataList.map((item) => item._id) } },
|
||||
// FullText tmp
|
||||
// { $set: { initFullText: true } }
|
||||
{ $set: { initFullText: true }, $unset: { fullTextToken: 1 } }
|
||||
);
|
||||
|
||||
success += dataList.length;
|
||||
console.log('Success:', success);
|
||||
|
||||
// await initData(batchSize);
|
||||
} catch (error: any) {
|
||||
console.log(error, '===');
|
||||
await delay(500);
|
||||
// await initData(batchSize);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const batchUpdateFields = async (batchSize = 2000) => {
|
||||
// Update in batches
|
||||
await MongoDatasetData.updateMany(
|
||||
{ initFullText: { $exists: true } },
|
||||
{
|
||||
$unset: {
|
||||
initFullText: 1,
|
||||
fullTextToken: 1
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
@@ -89,7 +89,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
path: file.path,
|
||||
filename: file.originalname,
|
||||
contentType: file.mimetype,
|
||||
encoding: file.encoding,
|
||||
metadata: metadata
|
||||
});
|
||||
|
||||
|
||||
@@ -1,38 +1,30 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { uploadMongoImg } from '@fastgpt/service/common/file/image/controller';
|
||||
import { UploadImgProps } from '@fastgpt/global/common/file/api';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
|
||||
/*
|
||||
Upload avatar image
|
||||
*/
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
const body = req.body as UploadImgProps;
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse): Promise<string> {
|
||||
await connectToDatabase();
|
||||
const body = req.body as UploadImgProps;
|
||||
|
||||
const { teamId } = await authCert({ req, authToken: true });
|
||||
const { teamId } = await authCert({ req, authToken: true });
|
||||
|
||||
const imgId = await uploadMongoImg({
|
||||
teamId,
|
||||
...body
|
||||
});
|
||||
|
||||
jsonRes(res, { data: imgId });
|
||||
} catch (error) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error
|
||||
});
|
||||
}
|
||||
return uploadMongoImg({
|
||||
teamId,
|
||||
...body
|
||||
});
|
||||
}
|
||||
export default NextAPI(handler);
|
||||
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: {
|
||||
sizeLimit: '16mb'
|
||||
sizeLimit: '12mb'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
25
projects/app/src/pages/api/common/system/writefile.ts
Normal file
25
projects/app/src/pages/api/common/system/writefile.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import * as fs from 'fs';
|
||||
import { authCert } from '@fastgpt/service/support/permission/auth/common';
|
||||
|
||||
export type writefileQuery = {};
|
||||
|
||||
export type writefileBody = {
|
||||
name: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type writefileResponse = {};
|
||||
|
||||
async function handler(
|
||||
req: ApiRequestProps<writefileBody, writefileQuery>,
|
||||
res: ApiResponseType<any>
|
||||
): Promise<writefileResponse> {
|
||||
await authCert({ req, authRoot: true });
|
||||
const { name, content } = req.body;
|
||||
await fs.promises.writeFile(`public/${name}`, content);
|
||||
return {};
|
||||
}
|
||||
|
||||
export default NextAPI(handler);
|
||||
@@ -15,8 +15,8 @@ import { ClientSession } from '@fastgpt/service/common/mongo';
|
||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
|
||||
import { MongoUser } from '@fastgpt/service/support/user/schema';
|
||||
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
|
||||
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
|
||||
|
||||
export type CreateAppBody = {
|
||||
parentId?: ParentIdType;
|
||||
@@ -148,6 +148,8 @@ export const onCreateApp = async ({
|
||||
);
|
||||
}
|
||||
|
||||
await refreshSourceAvatar(avatar, undefined, session);
|
||||
|
||||
return appId;
|
||||
};
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import { ClientSession } from '@fastgpt/service/common/mongo';
|
||||
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';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
const { appId } = req.query as { appId: string };
|
||||
@@ -57,7 +58,7 @@ export const onDelOneApp = async ({
|
||||
const apps = await findAppAndAllChildren({
|
||||
teamId,
|
||||
appId,
|
||||
fields: '_id'
|
||||
fields: '_id avatar'
|
||||
});
|
||||
|
||||
const del = async (session: ClientSession) => {
|
||||
@@ -109,6 +110,8 @@ export const onDelOneApp = async ({
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
|
||||
await removeImageByPath(app.avatar, session);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { MongoApp } from '@fastgpt/service/core/app/schema';
|
||||
import { isEqual } from 'lodash';
|
||||
import { onCreateApp } from '../create';
|
||||
import { onDelOneApp } from '../del';
|
||||
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
|
||||
|
||||
export type UpdateHttpPluginBody = {
|
||||
appId: string;
|
||||
@@ -49,13 +50,15 @@ async function handler(req: ApiRequestProps<UpdateHttpPluginBody>, res: NextApiR
|
||||
await MongoApp.findByIdAndUpdate(
|
||||
appId,
|
||||
{
|
||||
name,
|
||||
avatar,
|
||||
intro,
|
||||
...(name && { name }),
|
||||
...(avatar && { avatar }),
|
||||
...(intro !== undefined && { intro }),
|
||||
pluginData
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
|
||||
await refreshSourceAvatar(avatar, app.avatar, session);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,9 @@ import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/
|
||||
import { authApp } from '@fastgpt/service/support/permission/app/auth';
|
||||
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
|
||||
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
|
||||
import { getGroupPer } from '@fastgpt/service/support/permission/controller';
|
||||
import { concatPer } from '@fastgpt/service/support/permission/controller';
|
||||
import { getGroupsByTmbId } from '@fastgpt/service/support/permission/memberGroup/controllers';
|
||||
import { getOrgIdSetWithParentByTmbId } from '@fastgpt/service/support/permission/org/controllers';
|
||||
|
||||
export type ListAppBody = {
|
||||
parentId?: ParentIdType;
|
||||
@@ -25,7 +26,7 @@ export type ListAppBody = {
|
||||
searchKey?: string;
|
||||
};
|
||||
|
||||
/*
|
||||
/*
|
||||
获取 APP 列表权限
|
||||
1. 校验 folder 权限和获取 team 权限(owner 单独处理)
|
||||
2. 获取 team 下所有 app 权限。获取我的所有组。并计算出我所有的app权限。
|
||||
@@ -60,7 +61,7 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
]);
|
||||
|
||||
// Get team all app permissions
|
||||
const [perList, myGroupMap] = await Promise.all([
|
||||
const [perList, myGroupMap, myOrgSet] = await Promise.all([
|
||||
MongoResourcePermission.find({
|
||||
resourceType: PerResourceTypeEnum.app,
|
||||
teamId,
|
||||
@@ -77,11 +78,18 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
map.set(String(item._id), 1);
|
||||
});
|
||||
return map;
|
||||
}),
|
||||
getOrgIdSetWithParentByTmbId({
|
||||
teamId,
|
||||
tmbId
|
||||
})
|
||||
]);
|
||||
// Get my permissions
|
||||
const myPerList = perList.filter(
|
||||
(item) => String(item.tmbId) === String(tmbId) || myGroupMap.has(String(item.groupId))
|
||||
(item) =>
|
||||
String(item.tmbId) === String(tmbId) ||
|
||||
myGroupMap.has(String(item.groupId)) ||
|
||||
myOrgSet.has(String(item.orgId))
|
||||
);
|
||||
|
||||
const findAppsQuery = (() => {
|
||||
@@ -151,9 +159,11 @@ async function handler(req: ApiRequestProps<ListAppBody>): Promise<AppListItemTy
|
||||
const tmbPer = myPerList.find(
|
||||
(item) => String(item.resourceId) === appId && !!item.tmbId
|
||||
)?.permission;
|
||||
const groupPer = getGroupPer(
|
||||
const groupPer = concatPer(
|
||||
myPerList
|
||||
.filter((item) => String(item.resourceId) === appId && !!item.groupId)
|
||||
.filter(
|
||||
(item) => String(item.resourceId) === appId && (!!item.groupId || !!item.orgId)
|
||||
)
|
||||
.map((item) => item.permission)
|
||||
);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import { getResourceClbsAndGroups } from '@fastgpt/service/support/permission/co
|
||||
import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
|
||||
import { TeamWritePermissionVal } from '@fastgpt/global/support/permission/user/constant';
|
||||
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
|
||||
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
|
||||
|
||||
export type AppUpdateQuery = {
|
||||
appId: string;
|
||||
@@ -95,6 +96,8 @@ async function handler(req: ApiRequestProps<AppUpdateBody, AppUpdateQuery>) {
|
||||
isPlugin: app.type === AppTypeEnum.plugin
|
||||
});
|
||||
|
||||
await refreshSourceAvatar(avatar, app.avatar, session);
|
||||
|
||||
return MongoApp.findByIdAndUpdate(
|
||||
appId,
|
||||
{
|
||||
|
||||
@@ -12,18 +12,16 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controlle
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { UserModelSchema } from '@fastgpt/global/support/user/type';
|
||||
import { getRandomUserAvatar } from '@fastgpt/global/support/user/utils';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
let { chatId, shareId, outLinkUid } = req.query as InitOutLinkChatProps;
|
||||
|
||||
// auth link permission
|
||||
const { outLinkConfig, uid, appId } = await authOutLink({ shareId, outLinkUid });
|
||||
const { uid, appId } = await authOutLink({ shareId, outLinkUid });
|
||||
|
||||
// auth app permission
|
||||
const [tmb, chat, app] = await Promise.all([
|
||||
MongoTeamMember.findById(outLinkConfig.tmbId, '_id userId')
|
||||
.populate<{ user: UserModelSchema }>('user', 'avatar')
|
||||
.lean(),
|
||||
const [chat, app] = await Promise.all([
|
||||
MongoChat.findOne({ appId, chatId, shareId }).lean(),
|
||||
MongoApp.findById(appId).lean()
|
||||
]);
|
||||
@@ -48,7 +46,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
chatId,
|
||||
appId: app._id,
|
||||
title: chat?.title,
|
||||
userAvatar: tmb?.user?.avatar,
|
||||
userAvatar: getRandomUserAvatar(),
|
||||
variables: chat?.variables,
|
||||
app: {
|
||||
chatConfig: getAppChatConfig({
|
||||
|
||||
@@ -64,7 +64,6 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>): CreateCo
|
||||
path: file.path,
|
||||
filename: file.originalname,
|
||||
contentType: file.mimetype,
|
||||
encoding: file.encoding,
|
||||
metadata: fileMetadata
|
||||
});
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import type { ApiRequestProps } from '@fastgpt/service/type/next';
|
||||
import { parseParentIdInMongo } from '@fastgpt/global/common/parentFolder/utils';
|
||||
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
|
||||
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
|
||||
|
||||
export type DatasetCreateQuery = {};
|
||||
export type DatasetCreateBody = CreateDatasetParams;
|
||||
@@ -63,19 +65,29 @@ async function handler(
|
||||
// check limit
|
||||
await checkTeamDatasetLimit(teamId);
|
||||
|
||||
const { _id } = await MongoDataset.create({
|
||||
...parseParentIdInMongo(parentId),
|
||||
name,
|
||||
intro,
|
||||
teamId,
|
||||
tmbId,
|
||||
vectorModel,
|
||||
agentModel,
|
||||
avatar,
|
||||
type,
|
||||
apiServer,
|
||||
feishuServer,
|
||||
yuqueServer
|
||||
const datasetId = await mongoSessionRun(async (session) => {
|
||||
const [{ _id }] = await MongoDataset.create(
|
||||
[
|
||||
{
|
||||
...parseParentIdInMongo(parentId),
|
||||
name,
|
||||
intro,
|
||||
teamId,
|
||||
tmbId,
|
||||
vectorModel,
|
||||
agentModel,
|
||||
avatar,
|
||||
type,
|
||||
apiServer,
|
||||
feishuServer,
|
||||
yuqueServer
|
||||
}
|
||||
],
|
||||
{ session }
|
||||
);
|
||||
await refreshSourceAvatar(avatar, undefined, session);
|
||||
|
||||
return _id;
|
||||
});
|
||||
|
||||
pushTrack.createDataset({
|
||||
@@ -85,6 +97,6 @@ async function handler(
|
||||
uid: userId
|
||||
});
|
||||
|
||||
return _id;
|
||||
return datasetId;
|
||||
}
|
||||
export default NextAPI(handler);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { NextAPI } from '@/service/middleware/entry';
|
||||
import { OwnerPermissionVal } from '@fastgpt/global/support/permission/constant';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { MongoDatasetCollectionTags } from '@fastgpt/service/core/dataset/tag/schema';
|
||||
import { removeImageByPath } from '@fastgpt/service/common/file/image/controller';
|
||||
|
||||
async function handler(req: NextApiRequest) {
|
||||
const { id: datasetId } = req.query as {
|
||||
@@ -51,6 +52,10 @@ async function handler(req: NextApiRequest) {
|
||||
},
|
||||
{ session }
|
||||
);
|
||||
|
||||
for await (const dataset of datasets) {
|
||||
await removeImageByPath(dataset.avatar, session);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,8 @@ import { ApiRequestProps } from '@fastgpt/service/type/next';
|
||||
import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
|
||||
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
|
||||
import { getGroupsByTmbId } from '@fastgpt/service/support/permission/memberGroup/controllers';
|
||||
import { getGroupPer } from '@fastgpt/service/support/permission/controller';
|
||||
import { concatPer } from '@fastgpt/service/support/permission/controller';
|
||||
import { getOrgIdSetWithParentByTmbId } from '@fastgpt/service/support/permission/org/controllers';
|
||||
|
||||
export type GetDatasetListBody = {
|
||||
parentId: ParentIdType;
|
||||
@@ -50,7 +51,7 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
|
||||
]);
|
||||
|
||||
// Get team all app permissions
|
||||
const [perList, myGroupMap] = await Promise.all([
|
||||
const [perList, myGroupMap, myOrgSet] = await Promise.all([
|
||||
MongoResourcePermission.find({
|
||||
resourceType: PerResourceTypeEnum.dataset,
|
||||
teamId,
|
||||
@@ -67,10 +68,17 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
|
||||
map.set(String(item._id), 1);
|
||||
});
|
||||
return map;
|
||||
}),
|
||||
getOrgIdSetWithParentByTmbId({
|
||||
teamId,
|
||||
tmbId
|
||||
})
|
||||
]);
|
||||
const myPerList = perList.filter(
|
||||
(item) => String(item.tmbId) === String(tmbId) || myGroupMap.has(String(item.groupId))
|
||||
(item) =>
|
||||
String(item.tmbId) === String(tmbId) ||
|
||||
myGroupMap.has(String(item.groupId)) ||
|
||||
myOrgSet.has(String(item.orgId))
|
||||
);
|
||||
|
||||
const findDatasetQuery = (() => {
|
||||
@@ -122,9 +130,11 @@ async function handler(req: ApiRequestProps<GetDatasetListBody>) {
|
||||
const tmbPer = myPerList.find(
|
||||
(item) => String(item.resourceId) === datasetId && !!item.tmbId
|
||||
)?.permission;
|
||||
const groupPer = getGroupPer(
|
||||
const groupPer = concatPer(
|
||||
myPerList
|
||||
.filter((item) => String(item.resourceId) === datasetId && !!item.groupId)
|
||||
.filter(
|
||||
(item) => String(item.resourceId) === datasetId && (!!item.groupId || !!item.orgId)
|
||||
)
|
||||
.map((item) => item.permission)
|
||||
);
|
||||
return new DatasetPermission({
|
||||
|
||||
@@ -28,6 +28,7 @@ import { DatasetErrEnum } from '@fastgpt/global/common/error/code/dataset';
|
||||
import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema';
|
||||
import { MongoDatasetCollection } from '@fastgpt/service/core/dataset/collection/schema';
|
||||
import { addDays } from 'date-fns';
|
||||
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
|
||||
|
||||
export type DatasetUpdateQuery = {};
|
||||
export type DatasetUpdateResponse = any;
|
||||
@@ -144,6 +145,8 @@ async function handler(
|
||||
autoSync,
|
||||
session
|
||||
});
|
||||
|
||||
await refreshSourceAvatar(avatar, dataset.avatar, session);
|
||||
};
|
||||
|
||||
await mongoSessionRun(async (session) => {
|
||||
|
||||
@@ -7,12 +7,14 @@ import { UserStatusEnum } from '@fastgpt/global/support/user/constant';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { useReqFrequencyLimit } from '@fastgpt/service/common/middle/reqFrequencyLimit';
|
||||
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
|
||||
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
|
||||
import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
|
||||
|
||||
async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
const { username, password } = req.body as PostLoginProps;
|
||||
|
||||
if (!username || !password) {
|
||||
throw new Error('缺少参数');
|
||||
return Promise.reject(CommonErrEnum.invalidParams);
|
||||
}
|
||||
|
||||
// 检测用户是否存在
|
||||
@@ -23,11 +25,11 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
'status'
|
||||
);
|
||||
if (!authCert) {
|
||||
throw new Error('用户未注册');
|
||||
return Promise.reject(UserErrEnum.account_psw_error);
|
||||
}
|
||||
|
||||
if (authCert.status === UserStatusEnum.forbidden) {
|
||||
throw new Error('账号已停用,无法登录');
|
||||
return Promise.reject('Invalid account!');
|
||||
}
|
||||
|
||||
const user = await MongoUser.findOne({
|
||||
@@ -36,7 +38,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
throw new Error('密码错误');
|
||||
return Promise.reject(UserErrEnum.account_psw_error);
|
||||
}
|
||||
|
||||
const userDetail = await getUserDetail({
|
||||
@@ -68,4 +70,4 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
};
|
||||
}
|
||||
|
||||
export default NextAPI(useReqFrequencyLimit(120, 10), handler);
|
||||
export default NextAPI(useReqFrequencyLimit(120, 10, true), handler);
|
||||
|
||||
@@ -6,6 +6,9 @@ import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSc
|
||||
/* update user info */
|
||||
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
|
||||
import { NextAPI } from '@/service/middleware/entry';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
import { getUserDetail } from '@fastgpt/service/support/user/controller';
|
||||
import { refreshSourceAvatar } from '@fastgpt/service/common/file/image/controller';
|
||||
export type UserAccountUpdateQuery = {};
|
||||
export type UserAccountUpdateBody = UserUpdateParams;
|
||||
export type UserAccountUpdateResponse = {};
|
||||
@@ -16,22 +19,22 @@ async function handler(
|
||||
const { avatar, timezone } = req.body;
|
||||
|
||||
const { tmbId } = await authCert({ req, authToken: true });
|
||||
const tmb = await MongoTeamMember.findById(tmbId);
|
||||
if (!tmb) {
|
||||
throw new Error('can not find it');
|
||||
}
|
||||
const userId = tmb.userId;
|
||||
const user = await getUserDetail({ tmbId });
|
||||
|
||||
// 更新对应的记录
|
||||
await MongoUser.updateOne(
|
||||
{
|
||||
_id: userId
|
||||
},
|
||||
{
|
||||
...(avatar && { avatar }),
|
||||
...(timezone && { timezone })
|
||||
}
|
||||
);
|
||||
await mongoSessionRun(async (session) => {
|
||||
await MongoUser.updateOne(
|
||||
{
|
||||
_id: user._id
|
||||
},
|
||||
{
|
||||
...(avatar && { avatar }),
|
||||
...(timezone && { timezone })
|
||||
}
|
||||
).session(session);
|
||||
|
||||
await refreshSourceAvatar(avatar, user.avatar, session);
|
||||
});
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user