feat: team permission refine (#4494) (#4498)

* feat: team permission refine (#4402)

* chore: team permission extend

* feat: manage team permission

* chore: api auth

* fix: i18n

* feat: add initv493

* fix: test, org auth manager

* test: app test for refined permission

* update init sh

* fix: add/remove manage permission (#4427)

* fix: add/remove manage permission

* fix: github action fastgpt-test

* fix: mock create model

* fix: team write permission

* fix: ts

* account permission

---------

Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
This commit is contained in:
Archer
2025-04-10 11:11:54 +08:00
committed by GitHub
parent 80f41dd2a9
commit 199f454b6b
51 changed files with 1116 additions and 460 deletions

View File

@@ -13,12 +13,15 @@ export type CollaboratorItemType = {
orgId: string;
}>;
export type UpdateClbPermissionProps = {
export type UpdateClbPermissionProps<addOnly = false> = {
members?: string[];
groups?: string[];
orgs?: string[];
permission: PermissionValueType;
};
} & (addOnly extends true
? {}
: {
permission: PermissionValueType;
});
export type DeletePermissionQuery = RequireOnlyOne<{
tmbId?: string;

View File

@@ -5,15 +5,16 @@ export type PerConstructPros = {
per?: PermissionValueType;
isOwner?: boolean;
permissionList?: PermissionListType;
childUpdatePermissionCallback?: () => void;
};
// the Permission helper class
export class Permission {
value: PermissionValueType;
isOwner: boolean;
hasManagePer: boolean;
hasWritePer: boolean;
hasReadPer: boolean;
isOwner: boolean = false;
hasManagePer: boolean = false;
hasWritePer: boolean = false;
hasReadPer: boolean = false;
_permissionList: PermissionListType;
constructor(props?: PerConstructPros) {
@@ -24,11 +25,8 @@ export class Permission {
this.value = per;
}
this.isOwner = isOwner;
this._permissionList = permissionList;
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
this.updatePermissions();
}
// add permission(s)
@@ -68,10 +66,21 @@ export class Permission {
return (this.value & perm) === perm;
}
private updatePermissionCallback?: () => void;
setUpdatePermissionCallback(callback: () => void) {
callback();
this.updatePermissionCallback = callback;
}
private updatePermissions() {
this.isOwner = this.value === OwnerPermissionVal;
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
this.updatePermissionCallback?.();
}
toBinary() {
return this.value.toString(2);
}
}

View File

@@ -17,23 +17,23 @@ type GroupMemberSchemaType = {
role: `${GroupMemberRole}`;
};
type MemberGroupListItemType<T extends boolean | undefined> = MemberGroupSchemaType & {
members: T extends true
type MemberGroupListItemType<WithMembers extends boolean | undefined> = MemberGroupSchemaType & {
members: WithMembers extends true
? {
tmbId: string;
name: string;
avatar: string;
}[]
: undefined;
count: T extends true ? number : undefined;
owner?: T extends true
count: WithMembers extends true ? number : undefined;
owner?: WithMembers extends true
? {
tmbId: string;
name: string;
avatar: string;
}
: undefined;
permission: T extends true ? Permission : undefined;
permission: WithMembers extends true ? Permission : undefined;
};
type GroupMemberItemType = {

View File

@@ -1,22 +1,50 @@
import { PermissionKeyEnum } from '../constant';
import { PermissionListType } from '../type';
import { PermissionList } from '../constant';
export const TeamPermissionList: PermissionListType = {
import { i18nT } from '../../../../web/i18n/utils';
export enum TeamPermissionKeyEnum {
appCreate = 'appCreate',
datasetCreate = 'datasetCreate',
apikeyCreate = 'apikeyCreate'
}
export const TeamPermissionList: PermissionListType<TeamPermissionKeyEnum> = {
[PermissionKeyEnum.read]: {
...PermissionList[PermissionKeyEnum.read],
value: 0b100
value: 0b000100
},
[PermissionKeyEnum.write]: {
...PermissionList[PermissionKeyEnum.write],
value: 0b010
value: 0b000010
},
[PermissionKeyEnum.manage]: {
...PermissionList[PermissionKeyEnum.manage],
value: 0b001
value: 0b000001
},
[TeamPermissionKeyEnum.appCreate]: {
checkBoxType: 'multiple',
description: '',
name: i18nT('account_team:permission_appCreate'),
value: 0b001000
},
[TeamPermissionKeyEnum.datasetCreate]: {
checkBoxType: 'multiple',
description: '',
name: i18nT('account_team:permission_datasetCreate'),
value: 0b010000
},
[TeamPermissionKeyEnum.apikeyCreate]: {
checkBoxType: 'multiple',
description: '',
name: i18nT('account_team:permission_apikeyCreate'),
value: 0b100000
}
};
export const TeamReadPermissionVal = TeamPermissionList['read'].value;
export const TeamWritePermissionVal = TeamPermissionList['write'].value;
export const TeamManagePermissionVal = TeamPermissionList['manage'].value;
export const TeamAppCreatePermissionVal = TeamPermissionList['appCreate'].value;
export const TeamDatasetCreatePermissionVal = TeamPermissionList['datasetCreate'].value;
export const TeamApikeyCreatePermissionVal = TeamPermissionList['apikeyCreate'].value;
export const TeamDefaultPermissionVal = TeamReadPermissionVal;

View File

@@ -1,7 +1,15 @@
import { PerConstructPros, Permission } from '../controller';
import { TeamDefaultPermissionVal, TeamPermissionList } from './constant';
import {
TeamAppCreatePermissionVal,
TeamDefaultPermissionVal,
TeamPermissionList
} from './constant';
export class TeamPermission extends Permission {
hasAppCreatePer: boolean = false;
hasDatasetCreatePer: boolean = false;
hasApikeyCreatePer: boolean = false;
constructor(props?: PerConstructPros) {
if (!props) {
props = {
@@ -12,5 +20,11 @@ export class TeamPermission extends Permission {
}
props.permissionList = TeamPermissionList;
super(props);
this.setUpdatePermissionCallback(() => {
this.hasAppCreatePer = this.checkPer(TeamAppCreatePermissionVal);
this.hasDatasetCreatePer = this.checkPer(TeamAppCreatePermissionVal);
this.hasApikeyCreatePer = this.checkPer(TeamAppCreatePermissionVal);
});
}
}

View File

@@ -69,7 +69,7 @@ const addCommonMiddleware = (schema: mongoose.Schema) => {
export const getMongoModel = <T>(name: string, schema: mongoose.Schema) => {
if (connectionMongo.models[name]) return connectionMongo.models[name] as Model<T>;
console.log('Load model======', name);
if (process.env.NODE_ENV !== 'test') console.log('Load model======', name);
addCommonMiddleware(schema);
const model = connectionMongo.model<T>(name, schema);

View File

@@ -2,7 +2,7 @@ import { TeamPermission } from '@fastgpt/global/support/permission/user/controll
import { AuthModeType, AuthResponseType } from '../type';
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
import { authUserPer } from '../user/auth';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
import { TeamManagePermissionVal } from '@fastgpt/global/support/permission/user/constant';
/*
Team manager can control org
@@ -15,7 +15,7 @@ export const authOrgMember = async ({
} & AuthModeType): Promise<AuthResponseType> => {
const result = await authUserPer({
...props,
per: ManagePermissionVal
per: TeamManagePermissionVal
});
const { teamId, tmbId, isRoot, tmb } = result;

View File

@@ -61,5 +61,13 @@
"user_team_invite_member": "Invite members",
"user_team_leave_team": "Leave the team",
"user_team_leave_team_failed": "Failure to leave the team",
"waiting": "To be accepted"
"waiting": "To be accepted",
"permission_appCreate": "Create Application",
"permission_datasetCreate": "Create Knowledge Base",
"permission_apikeyCreate": "Create API Key",
"permission_appCreate_tip": "Can create applications in the root directory (creation permissions in folders are controlled by the folder)",
"permission_datasetCreate_Tip": "Can create knowledge bases in the root directory (creation permissions in folders are controlled by the folder)",
"permission_apikeyCreate_Tip": "Can create global APIKeys",
"permission_manage": "Admin",
"permission_manage_tip": "Can manage members, create groups, manage all groups, and assign permissions to groups and members"
}

View File

@@ -100,7 +100,6 @@
"team.group.manage_tip": "Can manage members, create groups, manage all groups, assign permissions to groups and members",
"team.group.members": "member",
"team.group.name": "Group name",
"team.group.permission.manage": "administrator",
"team.group.permission.write": "Workbench/knowledge base creation",
"team.group.permission_tip": "Members with individually configured permissions will follow the individual permission configuration and will no longer be affected by group permissions.\n\nIf a member is in multiple permission groups, the member's permissions are combined.",
"team.group.role.admin": "administrator",
@@ -112,5 +111,6 @@
"team.manage_collaborators": "Manage Collaborators",
"team.no_collaborators": "No Collaborators",
"team.org.org": "Organization",
"team.write_role_member": ""
"team.write_role_member": "Write Permission",
"team.collaborator.added": "Added"
}

View File

@@ -77,5 +77,13 @@
"user_team_invite_member": "邀请成员",
"user_team_leave_team": "离开团队",
"user_team_leave_team_failed": "离开团队失败",
"waiting": "待接受"
"waiting": "待接受",
"permission_appCreate": "创建应用",
"permission_datasetCreate": "创建知识库",
"permission_apikeyCreate": "创建 API 密钥",
"permission_appCreate_tip": "可以在根目录创建应用,(文件夹下的创建权限由文件夹控制)",
"permission_datasetCreate_Tip": "可以在根目录创建知识库,(文件夹下的创建权限由文件夹控制)",
"permission_apikeyCreate_Tip": "可以创建全局的 APIKey",
"permission_manage": "管理员",
"permission_manage_tip": "可以管理成员、创建群组、管理所有群组、为群组和成员分配权限"
}

View File

@@ -98,11 +98,9 @@
"team.group.keep_admin": "保留管理员权限",
"team.group.manage_member": "管理成员",
"team.group.manage_tip": "可以管理成员、创建群组、管理所有群组、为群组和成员分配权限",
"team.group.permission_tip": "单独配置权限的成员,将遵循个人权限配置,不再受群组权限影响。\n若成员在多个权限组则该成员的权限取并集。",
"team.group.members": "成员",
"team.group.name": "群组名称",
"team.group.permission.manage": "管理员",
"team.group.permission.write": "工作台/知识库创建",
"team.group.permission_tip": "单独配置权限的成员,将遵循个人权限配置,不再受群组权限影响。\n若成员在多个权限组则该成员的权限取并集。",
"team.group.role.admin": "管理员",
"team.group.role.member": "成员",
"team.group.role.owner": "所有者",
@@ -112,5 +110,6 @@
"team.manage_collaborators": "管理协作者",
"team.no_collaborators": "暂无协作者",
"team.org.org": "部门",
"team.write_role_member": "可写权限"
"team.write_role_member": "可写权限",
"team.collaborator.added": "已添加"
}

View File

@@ -61,5 +61,13 @@
"user_team_invite_member": "邀請成員",
"user_team_leave_team": "離開團隊",
"user_team_leave_team_failed": "離開團隊失敗",
"waiting": "待接受"
"waiting": "待接受",
"permission_appCreate": "建立應用",
"permission_datasetCreate": "建立知識庫",
"permission_apikeyCreate": "建立 API 密鑰",
"permission_appCreate_tip": "可以在根目錄建立應用,(資料夾下的建立權限由資料夾控制)",
"permission_datasetCreate_Tip": "可以在根目錄建立知識庫,(資料夾下的建立權限由資料夾控制)",
"permission_apikeyCreate_Tip": "可以建立全域的 APIKey",
"permission_manage": "管理員",
"permission_manage_tip": "可以管理成員、建立群組、管理所有群組、為群組和成員分配權限"
}

View File

@@ -100,7 +100,6 @@
"team.group.manage_tip": "可以管理成員、創建群組、管理所有群組、為群組和成員分配權限",
"team.group.members": "成員",
"team.group.name": "群組名稱",
"team.group.permission.manage": "管理員",
"team.group.permission.write": "工作臺/知識庫建立",
"team.group.permission_tip": "單獨設定權限的成員,將依照個人權限設定,不再受群組權限影響。\n若成員屬於多個權限群組該成員的權限將會合併。",
"team.group.role.admin": "管理員",
@@ -112,5 +111,6 @@
"team.manage_collaborators": "管理協作者",
"team.no_collaborators": "目前沒有協作者",
"team.org.org": "組織",
"team.write_role_member": "可寫入權限"
"team.write_role_member": "可寫入權限",
"team.collaborator.added": "已添加"
}