mirror of
https://github.com/labring/FastGPT.git
synced 2026-05-05 01:02:59 +08:00
2e18f1ebc2
* next 15 * lock * feat: rename .d.ts to .ts for Next 15 compatibility - Rename 104 .d.ts files to .ts (Next 15 no longer supports .d.ts in src) - Remove 5 redundant .d.ts files that had .ts counterparts - Update all import paths: remove .d suffix from 100 import statements - Update tsconfig.json include patterns across all packages - Add pnpm overrides to unify react@18.3.1 across monorepo - Fix react version mismatch (packages/global and packages/service were resolving to react@19.1.1) * fix: resolve 61 TypeScript errors from .d.ts to .ts migration - Fix broken imports using non-relative module paths (e.g. 'support/user/team/type' → relative paths) - Remove unused/dead imports referencing deleted modules - Fix duplicate identifiers (show_emptyChat, concatMd, TrainingModeEnum) - Add missing imports (BoxProps, GroupMemberRole, UsageSourceEnum, dashboard_evaluation) - Fix generic type constraints (OutLinkEditType, createShareChat) - Replace removed types with correct alternatives (ChatModelItemType → LLMModelItemType) - Delete 5 dead code files with 0 references - Add global type declaration for countTrackQueue - Fix nullable type narrowing (sourceMember, ParentIdType, optional app fields) * refactor: replace as ClientSession assertion with proper type narrowing via Omit & intersection * fix: remove experimental.workerThreads to fix DataCloneError in Next 15 static generation Next 15 worker threads attempt to structuredClone the config object, which fails on the webpack function. workerThreads is not needed for the build to work correctly. * Update document/content/docs/upgrading/4-14/4148.mdx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: ts * update next config * update next * fix: dockerfile * fix: comment --------- Co-authored-by: Archer <c121914yu@gmail.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
241 lines
6.4 KiB
TypeScript
241 lines
6.4 KiB
TypeScript
import type { ClientSession, AnyBulkWriteOperation } from '../../common/mongo';
|
|
import type { PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
|
|
import { ManageRoleVal, OwnerRoleVal } from '@fastgpt/global/support/permission/constant';
|
|
import { MongoResourcePermission } from './schema';
|
|
import type { ResourcePermissionType } from '@fastgpt/global/support/permission/type';
|
|
import { type PermissionValueType } from '@fastgpt/global/support/permission/type';
|
|
import { getGroupsByTmbId } from './memberGroup/controllers';
|
|
import { Permission } from '@fastgpt/global/support/permission/controller';
|
|
import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type';
|
|
import { getOrgIdSetWithParentByTmbId } from './org/controllers';
|
|
import { getCollaboratorId, sumPer } from '@fastgpt/global/support/permission/utils';
|
|
import { type SyncChildrenPermissionResourceType } from './inheritPermission';
|
|
import { pickCollaboratorIdFields } from './utils';
|
|
import type {
|
|
CollaboratorItemDetailType,
|
|
CollaboratorItemType
|
|
} from '@fastgpt/global/support/permission/collaborator';
|
|
import { MongoTeamMember } from '../../support/user/team/teamMemberSchema';
|
|
import { MongoOrgModel } from './org/orgSchema';
|
|
import { MongoMemberGroupModel } from './memberGroup/memberGroupSchema';
|
|
import { DEFAULT_ORG_AVATAR, DEFAULT_TEAM_AVATAR } from '@fastgpt/global/common/system/constants';
|
|
|
|
/** get resource permission for a team member
|
|
* If there is no permission for the team member, it will return undefined
|
|
* @param resourceType: PerResourceTypeEnum
|
|
* @param teamId
|
|
* @param tmbId
|
|
* @param resourceId
|
|
* @returns PermissionValueType | undefined
|
|
*/
|
|
export const getTmbPermission = async ({
|
|
resourceType,
|
|
teamId,
|
|
tmbId,
|
|
resourceId
|
|
}: {
|
|
teamId: string;
|
|
tmbId: string;
|
|
} & (
|
|
| {
|
|
resourceType: 'team';
|
|
resourceId?: undefined;
|
|
}
|
|
| {
|
|
resourceType: Omit<PerResourceTypeEnum, 'team'>;
|
|
resourceId: string;
|
|
}
|
|
)): Promise<PermissionValueType | undefined> => {
|
|
// Personal permission has the highest priority
|
|
const tmbPer = (
|
|
await MongoResourcePermission.findOne(
|
|
{
|
|
resourceType,
|
|
teamId,
|
|
resourceId,
|
|
tmbId
|
|
},
|
|
'permission'
|
|
).lean()
|
|
)?.permission;
|
|
|
|
// could be 0
|
|
if (tmbPer !== undefined) {
|
|
return tmbPer;
|
|
}
|
|
|
|
// If there is no personal permission, get the group permission
|
|
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
|
|
},
|
|
'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 sumPer(...groupPers, ...orgPers);
|
|
};
|
|
|
|
/**
|
|
* Only get resource's owned clbs, not including parents'.
|
|
*/
|
|
export async function getResourceOwnedClbs({
|
|
resourceType,
|
|
teamId,
|
|
resourceId,
|
|
session
|
|
}: {
|
|
teamId: string;
|
|
session?: ClientSession;
|
|
} & (
|
|
| {
|
|
resourceType: 'team';
|
|
resourceId?: undefined;
|
|
}
|
|
| {
|
|
resourceType: Omit<PerResourceTypeEnum, 'team'>;
|
|
resourceId: ParentIdType;
|
|
}
|
|
)) {
|
|
return MongoResourcePermission.find(
|
|
{
|
|
resourceId,
|
|
resourceType,
|
|
teamId
|
|
},
|
|
undefined,
|
|
{ ...(session ? { session } : {}) }
|
|
).lean();
|
|
}
|
|
|
|
export const getClbsInfo = async ({
|
|
clbs,
|
|
teamId,
|
|
ownerTmbId
|
|
}: {
|
|
clbs: CollaboratorItemType[];
|
|
teamId: string;
|
|
ownerTmbId?: string;
|
|
}): Promise<CollaboratorItemDetailType[]> => {
|
|
const tmbIds = [];
|
|
const orgIds = [];
|
|
const groupIds = [];
|
|
|
|
for (const clb of clbs) {
|
|
if (clb.tmbId) tmbIds.push(clb.tmbId);
|
|
if (clb.orgId) orgIds.push(clb.orgId);
|
|
if (clb.groupId) groupIds.push(clb.groupId);
|
|
}
|
|
|
|
const infos = (
|
|
await Promise.all([
|
|
MongoTeamMember.find({ _id: { $in: tmbIds }, teamId }, '_id name avatar').lean(),
|
|
MongoOrgModel.find({ _id: { $in: orgIds }, teamId }, '_id name avatar').lean(),
|
|
MongoMemberGroupModel.find({ _id: { $in: groupIds }, teamId }, '_id name avatar').lean()
|
|
])
|
|
).flat();
|
|
|
|
return clbs.map((clb) => {
|
|
const info = infos.find((info) => info._id === getCollaboratorId(clb));
|
|
|
|
return {
|
|
...clb,
|
|
teamId,
|
|
permission: new Permission({
|
|
role: clb.permission,
|
|
isOwner: Boolean(ownerTmbId && clb.tmbId && ownerTmbId === clb.tmbId)
|
|
}),
|
|
name: info?.name ?? 'Unknown name',
|
|
avatar: info?.avatar || (clb.orgId ? DEFAULT_ORG_AVATAR : DEFAULT_TEAM_AVATAR)
|
|
};
|
|
});
|
|
};
|
|
|
|
export const createResourceDefaultCollaborators = async ({
|
|
resource,
|
|
resourceType,
|
|
session,
|
|
tmbId
|
|
}: {
|
|
resource: SyncChildrenPermissionResourceType;
|
|
resourceType: PerResourceTypeEnum;
|
|
|
|
// should be provided when inheritPermission is true
|
|
session: ClientSession;
|
|
tmbId: string;
|
|
}) => {
|
|
const parentClbs = await getResourceOwnedClbs({
|
|
resourceId: resource.parentId,
|
|
resourceType,
|
|
teamId: resource.teamId,
|
|
session
|
|
});
|
|
// 1. add owner into the permission list with owner per
|
|
// 2. remove parent's owner permission, instead of manager
|
|
|
|
const collaborators: CollaboratorItemType[] = [
|
|
...parentClbs
|
|
.filter((item) => item.tmbId !== tmbId)
|
|
.map((clb) => {
|
|
if (clb.permission === OwnerRoleVal) {
|
|
clb.permission = ManageRoleVal;
|
|
}
|
|
return clb;
|
|
}),
|
|
{
|
|
tmbId,
|
|
permission: OwnerRoleVal
|
|
}
|
|
];
|
|
|
|
const ops: AnyBulkWriteOperation<ResourcePermissionType>[] = [];
|
|
|
|
for (const clb of collaborators) {
|
|
ops.push({
|
|
updateOne: {
|
|
filter: {
|
|
...pickCollaboratorIdFields(clb),
|
|
teamId: resource.teamId,
|
|
resourceId: resource._id,
|
|
resourceType
|
|
},
|
|
update: {
|
|
$set: {
|
|
permission: clb.permission
|
|
}
|
|
},
|
|
upsert: true
|
|
}
|
|
});
|
|
}
|
|
|
|
await MongoResourcePermission.bulkWrite(ops, { session });
|
|
};
|