Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

pref: a sort of apis #3554

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions packages/global/common/system/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export type FastGPTConfigFileType = {

export type FastGPTFeConfigsType = {
show_emptyChat?: boolean;
register_method?: ['email' | 'phone'];
register_method?: ['email' | 'phone' | 'sync'];
login_method?: ['email' | 'phone']; // Attention: login method is diffrent with oauth
find_password_method?: ['email' | 'phone'];
bind_notification_method?: ['email' | 'phone'];
Expand Down Expand Up @@ -76,7 +76,6 @@ export type FastGPTFeConfigsType = {
wecom?: {
corpid?: string;
agentid?: string;
secret?: string;
};
microsoft?: {
clientId?: string;
Expand Down
2 changes: 2 additions & 0 deletions packages/global/core/app/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export type AppListItemType = {
permission: AppPermission;
inheritPermission?: boolean;
private?: boolean;
ownerName?: string;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

统一封装个 type: sourceMember: name,avatar,leaved

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

需要嵌套一下吗(

ownerAvatar?: string;
};

export type AppDetailType = AppSchema & {
Expand Down
4 changes: 4 additions & 0 deletions packages/global/core/app/version.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { TeamMemberStatusEnum } from 'support/user/team/constant';
import { StoreEdgeItemType } from '../workflow/type/edge';
import { AppChatConfigType, AppSchema } from './type';

Expand All @@ -20,4 +21,7 @@ export type VersionListItemType = {
time: Date;
isPublish: boolean | undefined;
tmbId: string;
memberAvatar: string;
memberName: string;
memberStatus: `${TeamMemberStatusEnum}`;
};
2 changes: 2 additions & 0 deletions packages/global/core/dataset/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ export type DatasetListItemType = {
vectorModel: VectorModelItemType;
inheritPermission: boolean;
private?: boolean;
ownerName: string;
ownerAvatar: string;
};

export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel'> & {
Expand Down
2 changes: 2 additions & 0 deletions packages/global/core/workflow/type/node.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ export type NodeTemplateListItemType = {
hasTokenFee?: boolean; // 是否配置积分
instructions?: string; // 使用说明
courseUrl?: string; // 教程链接
memberName?: string; // 作者名称
memberAvatar?: string; // 作者头像
};

export type NodeTemplateListType = {
Expand Down
1 change: 1 addition & 0 deletions packages/global/support/user/team/controller.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export type CreateTeamProps = {
avatar?: string;
defaultTeam?: boolean;
memberName?: string;
memberAvatar?: string;
};
export type UpdateTeamProps = Omit<ThirdPartyAccountType, 'externalWorkflowVariable'> & {
name?: string;
Expand Down
8 changes: 3 additions & 5 deletions packages/global/support/user/team/org/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ export const OrgMemberCollectionName = 'team_org_members';

export const getOrgChildrenPath = (org: OrgSchemaType) => `${org.path}/${org.pathId}`;

// export enum OrgMemberRole {
// owner = 'owner',
// admin = 'admin',
// member = 'member'
// }
export enum SyncOrgSourceEnum {
wecom = 'wecom'
}
1 change: 1 addition & 0 deletions packages/global/support/user/team/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export type TeamMemberSchema = {
name: string;
role: `${TeamMemberRoleEnum}`;
status: `${TeamMemberStatusEnum}`;
avatar: string;
defaultTeam: boolean;
};

Expand Down
3 changes: 1 addition & 2 deletions packages/global/support/user/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export type UserModelSchema = {
_id: string;
username: string;
password: string;
avatar: string;
promotionRate: number;
inviterId?: string;
openaiKey: string;
Expand All @@ -22,7 +21,7 @@ export type UserModelSchema = {
export type UserType = {
_id: string;
username: string;
avatar: string;
avatar: string; // it should be team member's avatar after 4.8.18
timezone: string;
promotionRate: UserModelSchema['promotionRate'];
team: TeamTmbItemType;
Expand Down
21 changes: 21 additions & 0 deletions packages/service/common/api/pagination.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { NextApiRequest } from 'next';

export function parsePaginationRequest(req: NextApiRequest) {
const {
pageSize = 10,
pageNum = 1,
offset = 0
} = Object.keys(req.body).includes('pageSize')
? req.body
: Object.keys(req.query).includes('pageSize')
? req.query
: {};
if (!pageSize || (pageNum === undefined && offset === undefined)) {
throw new Error(CommonErrEnum.missingParams);
}
return {
pageSize: Number(pageSize),
offset: offset ? Number(offset) : (Number(pageNum) - 1) * Number(pageSize)
};
}
2 changes: 1 addition & 1 deletion packages/service/common/middle/cors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { NextApiResponse, NextApiRequest } from 'next';
import NextCors from 'nextjs-cors';

export async function withNextCors(req: NextApiRequest, res: NextApiResponse) {
const methods = ['GET', 'eHEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];
const methods = ['GET', 'HEAD', 'PUT', 'PATCH', 'POST', 'DELETE'];

const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',');
const origin = req.headers.origin;
Expand Down
196 changes: 196 additions & 0 deletions packages/service/core/changeOwner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// import { ClientSession } from '@/service/common/mongo';
// import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
// import { findAppAndAllChildren } from '@fastgpt/service/core/app/controller';
// import { MongoApp } from '@fastgpt/service/core/app/schema';
// import { findDatasetAndAllChildren } from '@fastgpt/service/core/dataset/controller';
// import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
// import { MongoOpenApi } from '@fastgpt/service/support/openapi/schema';
// import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
// import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';

import { mongoSessionRun } from '../common/mongo/sessionRun';
import { ClientSession } from 'mongoose';
import { MongoOpenApi } from '../support/openapi/schema';
import { MongoOutLink } from '../support/outLink/schema';
import { MongoResourcePermission } from '../support/permission/schema';
import { findAppAndAllChildren } from './app/controller';
import { MongoApp } from './app/schema';
import { findDatasetAndAllChildren } from './dataset/controller';
import { MongoDataset } from './dataset/schema';

type changeOwnerParams = {
changeOwnerType: 'app' | 'dataset';
resourceId?: string;
newOwnerId: string;
oldOwnerId: string;
teamId: string;
session?: ClientSession;
};

/** change owner of a list of resources
* this function will change the owner of a list of resources.
* If it is not a folder, only the resource itself will be changed.
* If it is a folder, the resource and all its children will be changed.
* OwnerId of the resource and the collaborators table (resource_permission) will be changed.
*
* @param changeOwnerType 'app' | 'dataset'
* @param newOwnerId new owner id
* @param oldOwnerId old owner id
* @param teamId team id
* @param resourceId resource id (optional): when it is not passed, it will change all the resources' owner in the team
*/
export async function changeOwner({
changeOwnerType,
newOwnerId,
oldOwnerId,
teamId,
resourceId,
session
}: changeOwnerParams) {
const func = async (session: ClientSession) => {
// get the Model and all the resourceIdList
// Model: MongoApp | MongoDataset
// resourceIdList: string[]
const [Model, resourceList] = await (async () => {
switch (changeOwnerType) {
case 'app':
return [
MongoApp,
resourceId
? await findAppAndAllChildren({ teamId, appId: resourceId })
: await MongoApp.find({ teamId }).lean()
];
case 'dataset':
return [
MongoDataset,
resourceId
? await findDatasetAndAllChildren({ teamId, datasetId: resourceId })
: await MongoDataset.find({ teamId }).lean()
];
}
})();

if (!Model) {
return;
}

// 1. update resources' owner
if (resourceId) {
await Model.updateOne(
{
_id: resourceId
},
{
tmbId: newOwnerId,
inheritPermission: false
},
{
session
}
);
}

// 2. Update other resources' owner
await Model.updateMany(
{
_id: { $in: resourceList.filter((id) => String(id) !== String(resourceId)) },
teamId,
tmbId: oldOwnerId
},
{
tmbId: newOwnerId
},
{
session
}
);

// If is app, update outlinks' owner
if (changeOwnerType === 'app') {
await MongoOutLink.updateMany(
{
teamId,
tmbId: oldOwnerId,
appId: { $in: resourceList.map((item) => item._id) }
},
{
tmbId: newOwnerId
},
{ session }
);
await MongoOpenApi.updateMany(
{
teamId,
tmbId: oldOwnerId,
appId: { $in: resourceList.map((item) => item._id) }
},
{ tmbId: newOwnerId },
{ session }
);
}

/* Update permission
1. 有 oldOwner 有 newOwner 的 permission,取最大值(删除所有 newOwner 的per,然后把 newOwner 的 tmbId 和 per 都更新)
2. 有 oldOwner 没有 newOwner, 把 oldOwner 更新为 newOwner
3. 有 newOwner, 没有 oldOwner, 不变
*/
const clbs = await MongoResourcePermission.find({
resourceType: changeOwnerType,
teamId,
resourceId: { $in: resourceList },
tmbId: {
$in: [oldOwnerId, newOwnerId]
}
}).lean();

const oldOwnerClbs = clbs.filter((clb) => String(clb.tmbId) === String(oldOwnerId));
const newOwnerClbs = clbs.filter((clb) => String(clb.tmbId) === String(newOwnerId));

const deletePerIdList: string[] = [];
const updatePerList: { id: string; per: number }[] = [];
oldOwnerClbs.forEach((oldClb) => {
const newOwner = newOwnerClbs.find(
(item) => String(item.resourceId) === String(oldClb.resourceId)
);

if (newOwner) {
const maxPer = Math.max(oldClb.permission, newOwner.permission);
deletePerIdList.push(String(newOwner._id));
updatePerList.push({
id: String(oldClb._id),
per: maxPer
});
} else {
updatePerList.push({
id: String(oldClb._id),
per: oldClb.permission
});
}
});

// Delete the oldOwner's permission
await MongoResourcePermission.deleteMany({ _id: { $in: deletePerIdList } }, { session });

// Update permission
for await (const item of updatePerList) {
await MongoResourcePermission.updateOne(
{
_id: item.id
},
{
tmbId: newOwnerId,
permission: item.per
},
{
session
}
);
}
};

if (session) {
await func(session);
} else {
await mongoSessionRun(func);
}
}
6 changes: 1 addition & 5 deletions packages/service/support/permission/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,7 @@ export const getClbsAndGroupsWithInfo = async ({
})
.populate<{ tmb: TeamMemberSchema & { user: UserModelSchema } }>({
path: 'tmb',
select: 'name userId',
populate: {
path: 'user',
select: 'avatar'
}
select: 'name userId avatar'
})
.lean(),
MongoResourcePermission.find({
Expand Down
1 change: 0 additions & 1 deletion packages/service/support/permission/org/controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import type { ClientSession } from 'mongoose';
import { MongoOrgModel } from './orgSchema';
import { MongoOrgMemberModel } from './orgMemberSchema';
import { getOrgChildrenPath } from '@fastgpt/global/support/user/team/org/constant';
import { getNanoid } from '@fastgpt/global/common/string/tools';

export const getOrgsByTmbId = async ({ teamId, tmbId }: { teamId: string; tmbId: string }) =>
MongoOrgMemberModel.find({ teamId, tmbId }, 'orgId').lean();
Expand Down
2 changes: 1 addition & 1 deletion packages/service/support/user/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export async function getUserDetail({
return {
_id: user._id,
username: user.username,
avatar: user.avatar,
avatar: tmb.avatar,
timezone: user.timezone,
promotionRate: user.promotionRate,
team: tmb,
Expand Down
12 changes: 7 additions & 5 deletions packages/service/support/user/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ const UserSchema = new Schema({
type: Date,
default: () => new Date()
},
avatar: {
type: String,
default: defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)]
},

promotionRate: {
type: Number,
Expand All @@ -74,7 +70,13 @@ const UserSchema = new Schema({
ref: userCollectionName
},
fastgpt_sem: Object,
sourceDomain: String
sourceDomain: String,

/** @deprecated */
avatar: {
type: String,
default: defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)]
}
});

try {
Expand Down
Loading
Loading