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

perf: org permission check #3500

Merged
merged 1 commit into from
Dec 30, 2024
Merged
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
107 changes: 44 additions & 63 deletions packages/service/support/permission/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { MemberGroupSchemaType } from '@fastgpt/global/support/permission/member
import { TeamMemberSchema } from '@fastgpt/global/support/user/team/type';
import { UserModelSchema } from '@fastgpt/global/support/user/type';
import { OrgSchemaType } from '@fastgpt/global/support/user/team/org/type';
import { getOrgsWithParentByTmbId } from './org/controllers';
import { getOrgIdSetWithParentByTmbId } from './org/controllers';

/** get resource permission for a team member
* If there is no permission for the team member, it will return undefined
Expand All @@ -41,15 +41,15 @@ export const getResourcePermission = async ({
teamId: string;
tmbId: string;
} & (
| {
| {
resourceType: 'team';
resourceId?: undefined;
}
| {
| {
resourceType: Omit<PerResourceTypeEnum, 'team'>;
resourceId: string;
}
)): Promise<PermissionValueType | undefined> => {
)): Promise<PermissionValueType | undefined> => {
// Personal permission has the highest priority
const tmbPer = (
await MongoResourcePermission.findOne(
Expand All @@ -69,61 +69,42 @@ export const getResourcePermission = async ({
}

// If there is no personal permission, get the group permission
const groupPer = await (async () => {
const groupIdList = (await getGroupsByTmbId({ tmbId, teamId })).map((item) => item._id);

if (groupIdList.length === 0) {
return undefined;
}

// get the maximum permission of the group
const pers = (
await MongoResourcePermission.find(
{
teamId,
resourceType,
groupId: {
$in: groupIdList
const [groupPers, orgPers] = await Promise.all([
getGroupsByTmbId({ tmbId, teamId })
.then((res) => res.map((item) => item._id))
.then((groupIdList) =>
MongoResourcePermission.find(
{
teamId,
resourceType,
groupId: {
$in: groupIdList
},
resourceId
},
resourceId
},
'permission'
).lean()
).map((item) => item.permission);

return getGroupPer(pers);
})();

const orgIds = await getOrgsWithParentByTmbId({ tmbId, teamId }).then((item) => Array.from(item));

if (orgIds.length === 0) {
return groupPer;
}

// get the maximum permission of the org
const orgPers = (
await MongoResourcePermission.find(
{
teamId,
resourceType,
orgId: {
$in: Array.from(orgIds)
},
resourceId
},
'permission'
).lean()
).map((item) => item.permission);

const orgPer = getGroupPer(orgPers);

if (groupPer === undefined) {
return orgPer;
} else if (orgPer === undefined) {
return groupPer;
}
'permission'
).lean()
)
.then((perList) => perList.map((item) => item.permission)),
getOrgIdSetWithParentByTmbId({ tmbId, teamId })
.then((item) => Array.from(item))
.then((orgIds) =>
MongoResourcePermission.find(
{
teamId,
resourceType,
orgId: {
$in: Array.from(orgIds)
},
resourceId
},
'permission'
).lean()
)
.then((perList) => perList.map((item) => item.permission))
]);

return new Permission().addPer(groupPer, orgPer).value;
return concatPer([...groupPers, ...orgPers]);
};

/* 仅取 members 不取 groups */
Expand All @@ -136,15 +117,15 @@ export async function getResourceAllClbs({
teamId: string;
session?: ClientSession;
} & (
| {
| {
resourceType: 'team';
resourceId?: undefined;
}
| {
| {
resourceType: Omit<PerResourceTypeEnum, 'team'>;
resourceId?: string | null;
}
)): Promise<ResourcePermissionType[]> {
)): Promise<ResourcePermissionType[]> {
return MongoResourcePermission.find(
{
resourceType: resourceType,
Expand Down Expand Up @@ -497,10 +478,10 @@ export const authFileToken = (token?: string) =>
});
});

export const getGroupPer = (groups: PermissionValueType[] = []) => {
if (groups.length === 0) {
export const concatPer = (perList: PermissionValueType[] = []) => {
if (perList.length === 0) {
return undefined;
}

return new Permission().addPer(...groups).value;
return new Permission().addPer(...perList).value;
};
45 changes: 1 addition & 44 deletions packages/service/support/permission/memberGroup/controllers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { MemberGroupSchemaType } from '@fastgpt/global/support/permission/memberGroup/type';
import { MongoGroupMemberModel } from './groupMemberSchema';
import { TeamMemberSchema } from '@fastgpt/global/support/user/team/type';
import { PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
import { MongoResourcePermission } from '../schema';
import { getGroupPer, parseHeaderCert } from '../controller';
import { parseHeaderCert } from '../controller';
import { MongoMemberGroupModel } from './memberGroupSchema';
import { DefaultGroupName } from '@fastgpt/global/support/user/team/group/constant';
import { ClientSession } from 'mongoose';
Expand Down Expand Up @@ -79,46 +76,6 @@ export const getGroupMembersByGroupId = async (groupId: string) => {
}).lean();
};

/**
* Get tmb's group permission: the maximum permission of the group
* @param tmbId
* @param resourceId
* @param resourceType
* @returns the maximum permission of the group
*/
export const getGroupPermission = async ({
tmbId,
resourceId,
teamId,
resourceType
}: {
tmbId: string;
teamId: string;
} & (
| {
resourceId?: undefined;
resourceType: 'team';
}
| {
resourceId: string;
resourceType: Omit<PerResourceTypeEnum, 'team'>;
}
)) => {
const groupIds = (await getGroupsByTmbId({ tmbId, teamId })).map((item) => item._id);
const groupPermissions = (
await MongoResourcePermission.find({
groupId: {
$in: groupIds
},
resourceType,
resourceId,
teamId
})
).map((item) => item.permission);

return getGroupPer(groupPermissions);
};

// auth group member role
export const authGroupMemberRole = async ({
groupId,
Expand Down
146 changes: 28 additions & 118 deletions packages/service/support/permission/org/controllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,50 +4,34 @@ import type { ClientSession } from 'mongoose';
import { MongoOrgModel } from './orgSchema';
import { MongoOrgMemberModel } from './orgMemberSchema';

// if role1 > role2, return 1
// if role1 < role2, return -1
// else return 0
// export const compareRole = (role1: OrgMemberRole, role2: OrgMemberRole) => {
// if (role1 === OrgMemberRole.owner) {
// if (role2 === OrgMemberRole.owner) {
// return 0;
// }
// return 1;
// }
// if (role2 === OrgMemberRole.owner) {
// return -1;
// }
// if (role1 === OrgMemberRole.admin) {
// if (role2 === OrgMemberRole.admin) {
// return 0;
// }
// return 1;
// }
// if (role2 === OrgMemberRole.admin) {
// return -1;
// }
// return 0;
// };

// export const checkOrgRole = (role: OrgMemberRole, targetRole: OrgMemberRole) => {
// return compareRole(role, targetRole) >= 0;
// };

export const getOrgsByTmbId = async ({ teamId, tmbId }: { teamId: string; tmbId: string }) =>
MongoOrgMemberModel.find({ teamId, tmbId }, 'orgId').lean();

export const getOrgsWithParentByTmbId = async ({ teamId, tmbId }: { teamId: string; tmbId: string }) =>
MongoOrgMemberModel.find({ teamId, tmbId }, 'orgId').lean().then((orgs) => {
const orgIds = new Set<string>();
for (const org of orgs) {
const orgId = String(org.orgId);
const parentIds = orgId.split('/').filter((id) => id);
for (const parentId of parentIds) {
orgIds.add(parentId);
}
export const getOrgIdSetWithParentByTmbId = async ({
teamId,
tmbId
}: {
teamId: string;
tmbId: string;
}) => {
const orgMembers = await MongoOrgMemberModel.find({ teamId, tmbId }, 'orgId')
.populate<{ org: { path: string } }>('org', 'path')
.lean();

const orgIds = new Set<string>();

for (const orgMember of orgMembers) {
orgIds.add(String(orgMember.orgId));

// Add parent org
const parentIds = orgMember.org.path.split('/').filter(Boolean);
for (const parentId of parentIds) {
orgIds.add(parentId);
}
return orgIds;
});
}

return orgIds;
};

export const getChildrenByOrg = async ({
org,
Expand All @@ -58,14 +42,9 @@ export const getChildrenByOrg = async ({
teamId: string;
session?: ClientSession;
}) => {
const children = await MongoOrgModel.find(
{ teamId, path: { $regex: `^${org.path}/${org._id}` } },
undefined,
{
session
}
).lean();
return children;
return MongoOrgModel.find({ teamId, path: { $regex: `^${org.path}/${org._id}` } }, undefined, {
session
}).lean();
};

export const getOrgAndChildren = async ({
Expand All @@ -92,8 +71,7 @@ export async function createRootOrg({
teamId: string;
session?: ClientSession;
}) {
// Create the root org
const [org] = await MongoOrgModel.create(
return MongoOrgModel.create(
[
{
teamId,
Expand All @@ -103,72 +81,4 @@ export async function createRootOrg({
],
{ session }
);
// Find the team's owner
// const owner = await MongoTeamMember.findOne({ teamId, role: 'owner' }, undefined);
// if (!owner) {
// return Promise.reject(TeamErrEnum.unAuthTeam);
// }

// Set the owner as the org admin
// await MongoOrgMemberModel.create(
// [
// {
// orgId: org._id,
// tmbId: owner._id

// }
// ],
// { session }
// );
}

// export const getOrgMemberRole = async ({
// orgId,
// tmbId
// }: {
// orgId: string;
// tmbId: string;
// }): Promise<OrgMemberRole | undefined> => {
// let role: OrgMemberRole | undefined;
// const orgMember = await MongoOrgMemberModel.findOne({
// orgId,
// tmbId
// })
// .populate('orgId')
// .lean();
// if (orgMember) {
// role = OrgMemberRole[orgMember.role];
// } else {
// return role;
// }
// if (role === OrgMemberRole.owner) {
// return role;
// }
// // Check the parent orgs
// const org = orgMember.orgId as unknown as OrgSchemaType;
// if (!org) {
// return Promise.reject(TeamErrEnum.orgNotExist);
// }
// const parentIds = org.path.split('/').filter((id) => id);
// if (parentIds.length === 0) {
// return role;
// }
// const parentOrgMembers = await MongoOrgMemberModel.find({
// orgId: {
// $in: parentIds
// },
// tmbId
// }).lean();
// // Update the role to the highest role
// for (const parentOrgMember of parentOrgMembers) {
// const parentRole = OrgMemberRole[parentOrgMember.role];
// if (parentRole === OrgMemberRole.owner) {
// role = parentRole;
// break;
// }
// if (parentRole === OrgMemberRole.admin && role === OrgMemberRole.member) {
// role = parentRole;
// }
// }
// return role;
// };
Loading
Loading