Skip to content

Commit

Permalink
Group role (#2993)
Browse files Browse the repository at this point in the history
* feat: app/dataset support group (#2898)

* pref: member-group (#2862)

* feat: group list ordered by updateTime

* fix: transfer ownership of group when deleting member

* fix: i18n fix

* feat: can not set member as admin/owner when user is not active

* fix: GroupInfoModal hover input do not change color

* fix(fe): searchinput do not scroll

* feat: app collaborator with group, remove default permission

* feat: dataset collaborator with group, remove default permission

* chore(test): pref mock

* chore: remove useless code

* chore: adjust

* fix: add self as collaborator when creating folder

* fix(fe): folder manage menu do not show when user has write permission
only

* fix: dataset folder create

* feat: Add code comment

* Pref: app move (#2952)

* perf: app schema

* doc

---------

Co-authored-by: Finley Ge <[email protected]>
  • Loading branch information
c121914yu and FinleyGe authored Oct 25, 2024
1 parent 74d58d5 commit f89452a
Show file tree
Hide file tree
Showing 60 changed files with 1,145 additions and 1,097 deletions.
10 changes: 6 additions & 4 deletions docSite/content/zh-cn/docs/development/upgrading/4812.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ weight: 812
9. 新增 - 数据库连接和操作插件
10. 新增 - Cookie 隐私协议提示
11. 新增 - HTTP 节点支持 JSONPath 表达式
12. 修复 - 文件后缀判断,去除 query 影响。
13. 修复 - AI 响应为空时,会造成 LLM 历史记录合并。
14. 修复 - 用户交互节点未阻塞流程。
15. 修复 - 新建 APP,有时候会导致空指针报错。
12. 新增 - 应用和知识库支持成员组配置权限
13. 优化 - 循环节点支持选择外部节点的变量
14. 修复 - 文件后缀判断,去除 query 影响。
15. 修复 - AI 响应为空时,会造成 LLM 历史记录合并。
16. 修复 - 用户交互节点未阻塞流程。
17. 修复 - 新建 APP,有时候会导致空指针报错。
10 changes: 8 additions & 2 deletions packages/global/core/app/collaborator.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { UpdateClbPermissionProps } from '../../support/permission/collaborator';
import { RequireOnlyOne } from '../../common/type/utils';
import {
UpdateClbPermissionProps,
UpdatePermissionBody
} from '../../support/permission/collaborator';
import { PermissionValueType } from '../../support/permission/type';

export type UpdateAppCollaboratorBody = UpdateClbPermissionProps & {
Expand All @@ -7,5 +11,7 @@ export type UpdateAppCollaboratorBody = UpdateClbPermissionProps & {

export type AppCollaboratorDeleteParams = {
appId: string;
} & RequireOnlyOne<{
tmbId: string;
};
groupId: string;
}>;
11 changes: 8 additions & 3 deletions packages/global/core/app/type.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { SelectedDatasetType } from '../workflow/api';
import { DatasetSearchModeEnum } from '../dataset/constants';
import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d';
import { StoreEdgeItemType } from '../workflow/type/edge';
import { PermissionSchemaType, PermissionValueType } from '../../support/permission/type';
import { AppPermission } from '../../support/permission/app/controller';
import { ParentIdType } from '../../common/parentFolder/type';
import { FlowNodeInputTypeEnum } from 'core/workflow/node/constant';
Expand Down Expand Up @@ -45,7 +44,11 @@ export type AppSchema = {

inited?: boolean;
teamTags: string[];
} & PermissionSchemaType;
inheritPermission?: boolean;

// abandon
defaultPermission?: number;
};

export type AppListItemType = {
_id: string;
Expand All @@ -57,7 +60,9 @@ export type AppListItemType = {
updateTime: Date;
pluginData?: AppSchema['pluginData'];
permission: AppPermission;
} & PermissionSchemaType;
inheritPermission?: boolean;
private?: boolean;
};

export type AppDetailType = AppSchema & {
permission: AppPermission;
Expand Down
5 changes: 4 additions & 1 deletion packages/global/core/dataset/collaborator.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { UpdateClbPermissionProps } from '../../support/permission/collaborator';
import { PermissionValueType } from '../../support/permission/type';
import { RequireOnlyOne } from '../../common/type/utils';

export type UpdateDatasetCollaboratorBody = UpdateClbPermissionProps & {
datasetId: string;
};

export type DatasetCollaboratorDeleteParams = {
datasetId: string;
} & RequireOnlyOne<{
tmbId: string;
};
groupId: string;
}>;
12 changes: 8 additions & 4 deletions packages/global/core/dataset/type.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { PermissionSchemaType } from '../../support/permission/type';
import type { LLMModelItemType, VectorModelItemType } from '../../core/ai/model.d';
import { PermissionTypeEnum } from '../../support/permission/constant';
import { PushDatasetDataChunkProps } from './api';
Expand Down Expand Up @@ -32,8 +31,11 @@ export type DatasetSchemaType = {
selector: string;
};
externalReadUrl?: string;
} & PermissionSchemaType;
// } & PermissionSchemaType;
inheritPermission: boolean;

// abandon
defaultPermission?: number;
};

export type DatasetCollectionSchemaType = {
_id: string;
Expand Down Expand Up @@ -146,7 +148,9 @@ export type DatasetListItemType = {
type: `${DatasetTypeEnum}`;
permission: DatasetPermission;
vectorModel: VectorModelItemType;
} & PermissionSchemaType;
inheritPermission: boolean;
private?: boolean;
};

export type DatasetItemType = Omit<DatasetSchemaType, 'vectorModel' | 'agentModel'> & {
vectorModel: VectorModelItemType;
Expand Down
6 changes: 4 additions & 2 deletions packages/global/support/permission/collaborator.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import { PermissionValueType } from './type';

export type CollaboratorItemType = {
teamId: string;
tmbId: string;
permission: Permission;
name: string;
avatar: string;
};
} & RequireOnlyOne<{
tmbId: string;
groupId: string;
}>;

export type UpdateClbPermissionProps = {
members?: string[];
Expand Down
1 change: 0 additions & 1 deletion packages/global/support/permission/constant.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Permission } from './controller';
import { PermissionListType } from './type';
import { i18nT } from '../../../web/i18n/utils';
export enum AuthUserTypeEnum {
Expand Down
5 changes: 5 additions & 0 deletions packages/global/support/permission/type.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { RequireOnlyOne } from '../../common/type/utils';
import { TeamMemberWithUserSchema } from '../user/team/type';
import { AuthUserTypeEnum, PermissionKeyEnum, PerResourceTypeEnum } from './constant';
import { MemberGroupSchemaType } from './memberGroup/type';

// PermissionValueType, the type of permission's value is a number, which is a bit field actually.
// It is spired by the permission system in Linux.
Expand Down Expand Up @@ -33,6 +34,10 @@ export type ResourcePerWithTmbWithUser = Omit<ResourcePermissionType, 'tmbId'> &
tmbId: TeamMemberWithUserSchema;
};

export type ResourcePerWithGroup = Omit<ResourcePermissionType, 'groupId'> & {
groupId: MemberGroupSchemaType;
};

export type PermissionSchemaType = {
defaultPermission: PermissionValueType;
inheritPermission: boolean;
Expand Down
9 changes: 6 additions & 3 deletions packages/service/core/app/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import {
TeamCollectionName,
TeamMemberCollectionName
} from '@fastgpt/global/support/user/team/constant';
import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/constant';
import { getPermissionSchema } from '@fastgpt/global/support/permission/utils';

export const AppCollectionName = 'apps';

Expand Down Expand Up @@ -111,8 +109,13 @@ const AppSchema = new Schema({
inited: {
type: Boolean
},
inheritPermission: {
type: Boolean,
default: true
},

...getPermissionSchema(AppDefaultPermissionVal)
// abandoned
defaultPermission: Number
});

AppSchema.index({ teamId: 1, updateTime: -1 });
Expand Down
10 changes: 7 additions & 3 deletions packages/service/core/dataset/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import {
TeamCollectionName,
TeamMemberCollectionName
} from '@fastgpt/global/support/user/team/constant';
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
import { getPermissionSchema } from '@fastgpt/global/support/permission/utils';
import type { DatasetSchemaType } from '@fastgpt/global/core/dataset/type.d';

export const DatasetCollectionName = 'datasets';
Expand Down Expand Up @@ -88,7 +86,13 @@ const DatasetSchema = new Schema({
externalReadUrl: {
type: String
},
...getPermissionSchema(DatasetDefaultPermissionVal)
inheritPermission: {
type: Boolean,
default: true
},

// abandoned
defaultPermission: Number
});

try {
Expand Down
13 changes: 5 additions & 8 deletions packages/service/support/permission/app/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import { splitCombinePluginId } from '../../../core/app/plugin/controller';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { AuthModeType, AuthResponseType } from '../type';
import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/constant';

export const authPluginByTmbId = async ({
tmbId,
Expand Down Expand Up @@ -60,7 +61,6 @@ export const authAppByTmbId = async ({
if (isRoot) {
return {
...app,
defaultPermission: app.defaultPermission,
permission: new AppPermission({ isOwner: true })
};
}
Expand All @@ -71,7 +71,7 @@ export const authAppByTmbId = async ({

const isOwner = tmbPer.isOwner || String(app.tmbId) === String(tmbId);

const { Per, defaultPermission } = await (async () => {
const { Per } = await (async () => {
if (
AppFolderTypeList.includes(app.type) ||
app.inheritPermission === false ||
Expand All @@ -86,10 +86,9 @@ export const authAppByTmbId = async ({
resourceId: appId,
resourceType: PerResourceTypeEnum.app
});
const Per = new AppPermission({ per: rp ?? app.defaultPermission, isOwner });
const Per = new AppPermission({ per: rp ?? AppDefaultPermissionVal, isOwner });
return {
Per,
defaultPermission: app.defaultPermission
Per
};
} else {
// is not folder and inheritPermission is true and is not root folder.
Expand All @@ -104,8 +103,7 @@ export const authAppByTmbId = async ({
isOwner
});
return {
Per,
defaultPermission: parent.defaultPermission
Per
};
}
})();
Expand All @@ -116,7 +114,6 @@ export const authAppByTmbId = async ({

return {
...app,
defaultPermission,
permission: Per
};
})();
Expand Down
85 changes: 82 additions & 3 deletions packages/service/support/permission/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ import { MongoResourcePermission } from './schema';
import { ClientSession } from 'mongoose';
import {
PermissionValueType,
ResourcePermissionType
ResourcePermissionType,
ResourcePerWithGroup,
ResourcePerWithTmbWithUser
} from '@fastgpt/global/support/permission/type';
import { bucketNameMap } from '@fastgpt/global/common/file/constants';
import { addMinutes } from 'date-fns';
import { getGroupsByTmbId } from './memberGroup/controllers';
import { Permission } from '@fastgpt/global/support/permission/controller';
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import { RequireOnlyOne } from '@fastgpt/global/common/type/utils';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';

/** get resource permission for a team member
* If there is no permission for the team member, it will return undefined
Expand Down Expand Up @@ -123,20 +128,94 @@ export async function getResourceAllClbs({
).lean();
}

export async function getResourceClbsAndGroups({
resourceId,
resourceType,
teamId,
session
}: {
resourceId: ParentIdType;
resourceType: Omit<`${PerResourceTypeEnum}`, 'team'>;
teamId: string;
session: ClientSession;
}) {
return MongoResourcePermission.find(
{
resourceId,
resourceType,
teamId
},
undefined,
{ session }
).lean();
}

export const getClbsAndGroupsWithInfo = async ({
resourceId,
resourceType,
teamId
}: {
resourceId: ParentIdType;
resourceType: Omit<`${PerResourceTypeEnum}`, 'team'>;
teamId: string;
}) =>
Promise.all([
(await MongoResourcePermission.find({
teamId,
resourceId,
resourceType,
tmbId: {
$exists: true
}
}).populate({
path: 'tmbId',
select: 'name userId',
populate: {
path: 'userId',
select: 'avatar'
}
})) as ResourcePerWithTmbWithUser[],
(await MongoResourcePermission.find({
teamId,
resourceId,
resourceType,
groupId: {
$exists: true
}
}).populate({
path: 'groupId',
select: 'name avatar'
})) as ResourcePerWithGroup[]
]);

export const delResourcePermissionById = (id: string) => {
return MongoResourcePermission.findByIdAndRemove(id);
};
export const delResourcePermission = ({
session,
tmbId,
groupId,
...props
}: {
resourceType: PerResourceTypeEnum;
teamId: string;
resourceId: string;
tmbId: string;
session?: ClientSession;
tmbId?: string;
groupId?: string;
}) => {
return MongoResourcePermission.deleteOne(props, { session });
// tmbId or groupId only one and not both
if (!!tmbId === !!groupId) {
return Promise.reject(CommonErrEnum.missingParams);
}
return MongoResourcePermission.deleteOne(
{
...(tmbId ? { tmbId } : {}),
...(groupId ? { groupId } : {}),
...props
},
{ session }
);
};

/* 下面代码等迁移 */
Expand Down
Loading

0 comments on commit f89452a

Please sign in to comment.