Skip to content

Commit c0c90c9

Browse files
c121914yuFinleyGe
andcommitted
feat: team permission refine (#4494)
* 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>
1 parent 80f41dd commit c0c90c9

File tree

51 files changed

+1113
-457
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1113
-457
lines changed

.github/workflows/fastgpt-test.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ jobs:
1515

1616
steps:
1717
- uses: actions/checkout@v4
18+
with:
19+
ref: ${{ github.event.pull_request.head.ref }}
20+
repository: ${{ github.event.pull_request.head.repo.full_name }}
1821
- uses: pnpm/action-setup@v4
1922
with:
2023
version: 10

package.json

+4-5
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,20 @@
1212
"previewIcon": "node ./scripts/icon/index.js",
1313
"api:gen": "tsc ./scripts/openapi/index.ts && node ./scripts/openapi/index.js && npx @redocly/cli build-docs ./scripts/openapi/openapi.json -o ./projects/app/public/openapi/index.html",
1414
"create:i18n": "node ./scripts/i18n/index.js",
15-
"test": "vitest run --exclude 'test/cases/spec'",
16-
"test:all": "vitest run",
15+
"test": "vitest run",
1716
"test:workflow": "vitest run workflow"
1817
},
1918
"devDependencies": {
2019
"@chakra-ui/cli": "^2.4.1",
21-
"@vitest/coverage-v8": "^3.0.2",
20+
"@vitest/coverage-v8": "^3.0.9",
2221
"husky": "^8.0.3",
2322
"i18next": "23.16.8",
2423
"lint-staged": "^13.3.0",
2524
"next-i18next": "15.4.2",
2625
"prettier": "3.2.4",
2726
"react-i18next": "14.1.2",
28-
"vitest": "^3.0.2",
29-
"vitest-mongodb": "^1.0.1",
27+
"vitest": "^3.0.9",
28+
"mongodb-memory-server": "^10.1.4",
3029
"zhlint": "^0.7.4"
3130
},
3231
"lint-staged": {

packages/global/support/permission/collaborator.d.ts

+6-3
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ export type CollaboratorItemType = {
1313
orgId: string;
1414
}>;
1515

16-
export type UpdateClbPermissionProps = {
16+
export type UpdateClbPermissionProps<addOnly = false> = {
1717
members?: string[];
1818
groups?: string[];
1919
orgs?: string[];
20-
permission: PermissionValueType;
21-
};
20+
} & (addOnly extends true
21+
? {}
22+
: {
23+
permission: PermissionValueType;
24+
});
2225

2326
export type DeletePermissionQuery = RequireOnlyOne<{
2427
tmbId?: string;

packages/global/support/permission/controller.ts

+17-8
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@ export type PerConstructPros = {
55
per?: PermissionValueType;
66
isOwner?: boolean;
77
permissionList?: PermissionListType;
8+
childUpdatePermissionCallback?: () => void;
89
};
910

1011
// the Permission helper class
1112
export class Permission {
1213
value: PermissionValueType;
13-
isOwner: boolean;
14-
hasManagePer: boolean;
15-
hasWritePer: boolean;
16-
hasReadPer: boolean;
14+
isOwner: boolean = false;
15+
hasManagePer: boolean = false;
16+
hasWritePer: boolean = false;
17+
hasReadPer: boolean = false;
1718
_permissionList: PermissionListType;
1819

1920
constructor(props?: PerConstructPros) {
@@ -24,11 +25,8 @@ export class Permission {
2425
this.value = per;
2526
}
2627

27-
this.isOwner = isOwner;
2828
this._permissionList = permissionList;
29-
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
30-
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
31-
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
29+
this.updatePermissions();
3230
}
3331

3432
// add permission(s)
@@ -68,10 +66,21 @@ export class Permission {
6866
return (this.value & perm) === perm;
6967
}
7068

69+
private updatePermissionCallback?: () => void;
70+
setUpdatePermissionCallback(callback: () => void) {
71+
callback();
72+
this.updatePermissionCallback = callback;
73+
}
74+
7175
private updatePermissions() {
7276
this.isOwner = this.value === OwnerPermissionVal;
7377
this.hasManagePer = this.checkPer(this._permissionList['manage'].value);
7478
this.hasWritePer = this.checkPer(this._permissionList['write'].value);
7579
this.hasReadPer = this.checkPer(this._permissionList['read'].value);
80+
this.updatePermissionCallback?.();
81+
}
82+
83+
toBinary() {
84+
return this.value.toString(2);
7685
}
7786
}

packages/global/support/permission/memberGroup/type.d.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,23 @@ type GroupMemberSchemaType = {
1717
role: `${GroupMemberRole}`;
1818
};
1919

20-
type MemberGroupListItemType<T extends boolean | undefined> = MemberGroupSchemaType & {
21-
members: T extends true
20+
type MemberGroupListItemType<WithMembers extends boolean | undefined> = MemberGroupSchemaType & {
21+
members: WithMembers extends true
2222
? {
2323
tmbId: string;
2424
name: string;
2525
avatar: string;
2626
}[]
2727
: undefined;
28-
count: T extends true ? number : undefined;
29-
owner?: T extends true
28+
count: WithMembers extends true ? number : undefined;
29+
owner?: WithMembers extends true
3030
? {
3131
tmbId: string;
3232
name: string;
3333
avatar: string;
3434
}
3535
: undefined;
36-
permission: T extends true ? Permission : undefined;
36+
permission: WithMembers extends true ? Permission : undefined;
3737
};
3838

3939
type GroupMemberItemType = {
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,50 @@
11
import { PermissionKeyEnum } from '../constant';
22
import { PermissionListType } from '../type';
33
import { PermissionList } from '../constant';
4-
export const TeamPermissionList: PermissionListType = {
4+
import { i18nT } from '../../../../web/i18n/utils';
5+
export enum TeamPermissionKeyEnum {
6+
appCreate = 'appCreate',
7+
datasetCreate = 'datasetCreate',
8+
apikeyCreate = 'apikeyCreate'
9+
}
10+
11+
export const TeamPermissionList: PermissionListType<TeamPermissionKeyEnum> = {
512
[PermissionKeyEnum.read]: {
613
...PermissionList[PermissionKeyEnum.read],
7-
value: 0b100
14+
value: 0b000100
815
},
916
[PermissionKeyEnum.write]: {
1017
...PermissionList[PermissionKeyEnum.write],
11-
value: 0b010
18+
value: 0b000010
1219
},
1320
[PermissionKeyEnum.manage]: {
1421
...PermissionList[PermissionKeyEnum.manage],
15-
value: 0b001
22+
value: 0b000001
23+
},
24+
[TeamPermissionKeyEnum.appCreate]: {
25+
checkBoxType: 'multiple',
26+
description: '',
27+
name: i18nT('account_team:permission_appCreate'),
28+
value: 0b001000
29+
},
30+
[TeamPermissionKeyEnum.datasetCreate]: {
31+
checkBoxType: 'multiple',
32+
description: '',
33+
name: i18nT('account_team:permission_datasetCreate'),
34+
value: 0b010000
35+
},
36+
[TeamPermissionKeyEnum.apikeyCreate]: {
37+
checkBoxType: 'multiple',
38+
description: '',
39+
name: i18nT('account_team:permission_apikeyCreate'),
40+
value: 0b100000
1641
}
1742
};
1843

1944
export const TeamReadPermissionVal = TeamPermissionList['read'].value;
2045
export const TeamWritePermissionVal = TeamPermissionList['write'].value;
2146
export const TeamManagePermissionVal = TeamPermissionList['manage'].value;
47+
export const TeamAppCreatePermissionVal = TeamPermissionList['appCreate'].value;
48+
export const TeamDatasetCreatePermissionVal = TeamPermissionList['datasetCreate'].value;
49+
export const TeamApikeyCreatePermissionVal = TeamPermissionList['apikeyCreate'].value;
2250
export const TeamDefaultPermissionVal = TeamReadPermissionVal;

packages/global/support/permission/user/controller.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
import { PerConstructPros, Permission } from '../controller';
2-
import { TeamDefaultPermissionVal, TeamPermissionList } from './constant';
2+
import {
3+
TeamAppCreatePermissionVal,
4+
TeamDefaultPermissionVal,
5+
TeamPermissionList
6+
} from './constant';
37

48
export class TeamPermission extends Permission {
9+
hasAppCreatePer: boolean = false;
10+
hasDatasetCreatePer: boolean = false;
11+
hasApikeyCreatePer: boolean = false;
12+
513
constructor(props?: PerConstructPros) {
614
if (!props) {
715
props = {
@@ -12,5 +20,11 @@ export class TeamPermission extends Permission {
1220
}
1321
props.permissionList = TeamPermissionList;
1422
super(props);
23+
24+
this.setUpdatePermissionCallback(() => {
25+
this.hasAppCreatePer = this.checkPer(TeamAppCreatePermissionVal);
26+
this.hasDatasetCreatePer = this.checkPer(TeamAppCreatePermissionVal);
27+
this.hasApikeyCreatePer = this.checkPer(TeamAppCreatePermissionVal);
28+
});
1529
}
1630
}

packages/service/common/mongo/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const addCommonMiddleware = (schema: mongoose.Schema) => {
6969

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

7575
const model = connectionMongo.model<T>(name, schema);

packages/service/support/permission/auth/org.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { TeamPermission } from '@fastgpt/global/support/permission/user/controll
22
import { AuthModeType, AuthResponseType } from '../type';
33
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
44
import { authUserPer } from '../user/auth';
5-
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
5+
import { TeamManagePermissionVal } from '@fastgpt/global/support/permission/user/constant';
66

77
/*
88
Team manager can control org
@@ -15,7 +15,7 @@ export const authOrgMember = async ({
1515
} & AuthModeType): Promise<AuthResponseType> => {
1616
const result = await authUserPer({
1717
...props,
18-
per: ManagePermissionVal
18+
per: TeamManagePermissionVal
1919
});
2020
const { teamId, tmbId, isRoot, tmb } = result;
2121

packages/web/i18n/en/account_team.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,13 @@
6161
"user_team_invite_member": "Invite members",
6262
"user_team_leave_team": "Leave the team",
6363
"user_team_leave_team_failed": "Failure to leave the team",
64-
"waiting": "To be accepted"
64+
"waiting": "To be accepted",
65+
"permission_appCreate": "Create Application",
66+
"permission_datasetCreate": "Create Knowledge Base",
67+
"permission_apikeyCreate": "Create API Key",
68+
"permission_appCreate_tip": "Can create applications in the root directory (creation permissions in folders are controlled by the folder)",
69+
"permission_datasetCreate_Tip": "Can create knowledge bases in the root directory (creation permissions in folders are controlled by the folder)",
70+
"permission_apikeyCreate_Tip": "Can create global APIKeys",
71+
"permission_manage": "Admin",
72+
"permission_manage_tip": "Can manage members, create groups, manage all groups, and assign permissions to groups and members"
6573
}

packages/web/i18n/en/user.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@
100100
"team.group.manage_tip": "Can manage members, create groups, manage all groups, assign permissions to groups and members",
101101
"team.group.members": "member",
102102
"team.group.name": "Group name",
103-
"team.group.permission.manage": "administrator",
104103
"team.group.permission.write": "Workbench/knowledge base creation",
105104
"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.",
106105
"team.group.role.admin": "administrator",
@@ -112,5 +111,6 @@
112111
"team.manage_collaborators": "Manage Collaborators",
113112
"team.no_collaborators": "No Collaborators",
114113
"team.org.org": "Organization",
115-
"team.write_role_member": ""
114+
"team.write_role_member": "Write Permission",
115+
"team.collaborator.added": "Added"
116116
}

packages/web/i18n/zh-CN/account_team.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,13 @@
7777
"user_team_invite_member": "邀请成员",
7878
"user_team_leave_team": "离开团队",
7979
"user_team_leave_team_failed": "离开团队失败",
80-
"waiting": "待接受"
80+
"waiting": "待接受",
81+
"permission_appCreate": "创建应用",
82+
"permission_datasetCreate": "创建知识库",
83+
"permission_apikeyCreate": "创建 API 密钥",
84+
"permission_appCreate_tip": "可以在根目录创建应用,(文件夹下的创建权限由文件夹控制)",
85+
"permission_datasetCreate_Tip": "可以在根目录创建知识库,(文件夹下的创建权限由文件夹控制)",
86+
"permission_apikeyCreate_Tip": "可以创建全局的 APIKey",
87+
"permission_manage": "管理员",
88+
"permission_manage_tip": "可以管理成员、创建群组、管理所有群组、为群组和成员分配权限"
8189
}

packages/web/i18n/zh-CN/user.json

+3-4
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,9 @@
9898
"team.group.keep_admin": "保留管理员权限",
9999
"team.group.manage_member": "管理成员",
100100
"team.group.manage_tip": "可以管理成员、创建群组、管理所有群组、为群组和成员分配权限",
101+
"team.group.permission_tip": "单独配置权限的成员,将遵循个人权限配置,不再受群组权限影响。\n若成员在多个权限组,则该成员的权限取并集。",
101102
"team.group.members": "成员",
102103
"team.group.name": "群组名称",
103-
"team.group.permission.manage": "管理员",
104-
"team.group.permission.write": "工作台/知识库创建",
105-
"team.group.permission_tip": "单独配置权限的成员,将遵循个人权限配置,不再受群组权限影响。\n若成员在多个权限组,则该成员的权限取并集。",
106104
"team.group.role.admin": "管理员",
107105
"team.group.role.member": "成员",
108106
"team.group.role.owner": "所有者",
@@ -112,5 +110,6 @@
112110
"team.manage_collaborators": "管理协作者",
113111
"team.no_collaborators": "暂无协作者",
114112
"team.org.org": "部门",
115-
"team.write_role_member": "可写权限"
113+
"team.write_role_member": "可写权限",
114+
"team.collaborator.added": "已添加"
116115
}

packages/web/i18n/zh-Hant/account_team.json

+9-1
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,13 @@
6161
"user_team_invite_member": "邀請成員",
6262
"user_team_leave_team": "離開團隊",
6363
"user_team_leave_team_failed": "離開團隊失敗",
64-
"waiting": "待接受"
64+
"waiting": "待接受",
65+
"permission_appCreate": "建立應用",
66+
"permission_datasetCreate": "建立知識庫",
67+
"permission_apikeyCreate": "建立 API 密鑰",
68+
"permission_appCreate_tip": "可以在根目錄建立應用,(資料夾下的建立權限由資料夾控制)",
69+
"permission_datasetCreate_Tip": "可以在根目錄建立知識庫,(資料夾下的建立權限由資料夾控制)",
70+
"permission_apikeyCreate_Tip": "可以建立全域的 APIKey",
71+
"permission_manage": "管理員",
72+
"permission_manage_tip": "可以管理成員、建立群組、管理所有群組、為群組和成員分配權限"
6573
}

packages/web/i18n/zh-Hant/user.json

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

0 commit comments

Comments
 (0)