Skip to content

Commit 583d61e

Browse files
committed
fix: test, org auth manager
1 parent b6d7b3c commit 583d61e

File tree

11 files changed

+293
-62
lines changed

11 files changed

+293
-62
lines changed

Diff for: package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,15 @@
1818
},
1919
"devDependencies": {
2020
"@chakra-ui/cli": "^2.4.1",
21-
"@vitest/coverage-v8": "^3.0.2",
21+
"@vitest/coverage-v8": "^3.0.9",
2222
"husky": "^8.0.3",
2323
"i18next": "23.16.8",
2424
"lint-staged": "^13.3.0",
2525
"next-i18next": "15.4.2",
2626
"prettier": "3.2.4",
2727
"react-i18next": "14.1.2",
28-
"vitest": "^3.0.2",
29-
"vitest-mongodb": "^1.0.1",
28+
"vitest": "^3.0.9",
29+
"mongodb-memory-server": "^10.1.4",
3030
"zhlint": "^0.7.4"
3131
},
3232
"lint-staged": {

Diff for: 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 = {

Diff for: packages/global/support/permission/user/constant.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,29 @@ export const TeamPermissionList: PermissionListType<TeamPermissionKeyEnum> = {
1515
},
1616
[PermissionKeyEnum.write]: {
1717
...PermissionList[PermissionKeyEnum.write],
18-
value: 0b000010
18+
value: 0b000110
1919
},
2020
[PermissionKeyEnum.manage]: {
2121
...PermissionList[PermissionKeyEnum.manage],
22-
value: 0b000001
22+
value: 0b000101
2323
},
2424
[TeamPermissionKeyEnum.appCreate]: {
2525
checkBoxType: 'multiple',
2626
description: '',
2727
name: i18nT('account_team:permission_appCreate'),
28-
value: 0b001000
28+
value: 0b001100
2929
},
3030
[TeamPermissionKeyEnum.datasetCreate]: {
3131
checkBoxType: 'multiple',
3232
description: '',
3333
name: i18nT('account_team:permission_datasetCreate'),
34-
value: 0b010000
34+
value: 0b010100
3535
},
3636
[TeamPermissionKeyEnum.apikeyCreate]: {
3737
checkBoxType: 'multiple',
3838
description: '',
3939
name: i18nT('account_team:permission_apikeyCreate'),
40-
value: 0b100000
40+
value: 0b100100
4141
}
4242
};
4343

Diff for: packages/service/common/mongo/index.ts

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

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

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

Diff for: 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

Diff for: test/datas/users.ts

+124-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
1+
import { AuthUserTypeEnum, PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
2+
import { MemberGroupSchemaType } from '@fastgpt/global/support/permission/memberGroup/type';
3+
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
4+
import { TeamManagePermissionVal } from '@fastgpt/global/support/permission/user/constant';
5+
import { DefaultGroupName } from '@fastgpt/global/support/user/team/group/constant';
6+
import { OrgSchemaType, OrgType } from '@fastgpt/global/support/user/team/org/type';
7+
import { MongoMemberGroupModel } from '@fastgpt/service/support/permission/memberGroup/memberGroupSchema';
8+
import { MongoOrgModel } from '@fastgpt/service/support/permission/org/orgSchema';
9+
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
210
import { MongoUser } from '@fastgpt/service/support/user/schema';
311
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
412
import { MongoTeam } from '@fastgpt/service/support/user/team/teamSchema';
@@ -33,22 +41,40 @@ export async function getRootUser(): Promise<parseHeaderCertRet> {
3341
};
3442
}
3543

36-
export async function getUser(username: string): Promise<parseHeaderCertRet> {
44+
export async function getUser(username: string, teamId?: string): Promise<parseHeaderCertRet> {
3745
const user = await MongoUser.create({
3846
username,
3947
password: '123456'
4048
});
4149

42-
const team = await MongoTeam.create({
43-
name: 'test team',
44-
ownerId: user._id
45-
});
50+
const tmb = await (async () => {
51+
if (!teamId) {
52+
const team = await MongoTeam.create({
53+
name: username,
54+
ownerId: user._id
55+
});
56+
const tmb = await MongoTeamMember.create({
57+
name: username,
58+
teamId: team._id,
59+
userId: user._id,
60+
status: 'active',
61+
role: 'owner'
62+
});
4663

47-
const tmb = await MongoTeamMember.create({
48-
teamId: team._id,
49-
userId: user._id,
50-
status: 'active'
51-
});
64+
await MongoMemberGroupModel.create({
65+
teamId: team._id,
66+
name: DefaultGroupName,
67+
avatar: team.avatar
68+
});
69+
70+
return tmb;
71+
}
72+
return MongoTeamMember.create({
73+
teamId,
74+
userId: user._id,
75+
status: 'active'
76+
});
77+
})();
5278

5379
return {
5480
userId: user._id,
@@ -61,3 +87,90 @@ export async function getUser(username: string): Promise<parseHeaderCertRet> {
6187
tmbId: tmb?._id
6288
};
6389
}
90+
91+
let fakeUsers: Record<string, parseHeaderCertRet> = {};
92+
93+
async function getFakeUser(username: string) {
94+
if (username === 'Owner') {
95+
if (!fakeUsers[username]) {
96+
fakeUsers[username] = await getUser(username);
97+
}
98+
return fakeUsers[username];
99+
}
100+
const owner = await getFakeUser('Owner');
101+
const ownerTeamId = owner.teamId;
102+
if (!fakeUsers[username]) {
103+
fakeUsers[username] = await getUser(username, ownerTeamId);
104+
}
105+
return fakeUsers[username];
106+
}
107+
108+
async function addPermission({
109+
user,
110+
permission
111+
}: {
112+
user: parseHeaderCertRet;
113+
permission: PermissionValueType;
114+
}) {
115+
const { teamId, tmbId } = user;
116+
await MongoResourcePermission.updateOne({
117+
resourceType: PerResourceTypeEnum.team,
118+
teamId,
119+
resourceId: null,
120+
tmbId,
121+
permission
122+
});
123+
}
124+
125+
export async function getFakeUsers(num: number = 10) {
126+
const owner = await getFakeUser('Owner');
127+
const manager = await getFakeUser('Manager');
128+
await MongoResourcePermission.create({
129+
resourceType: PerResourceTypeEnum.team,
130+
teamId: owner.teamId,
131+
resourceId: null,
132+
tmbId: manager.tmbId,
133+
permission: TeamManagePermissionVal
134+
});
135+
const members = (await Promise.all(
136+
Array.from({ length: num }, (_, i) => `member${i + 1}`) // 团队 member1, member2, ..., member10
137+
.map((username) => getFakeUser(username))
138+
)) as parseHeaderCertRet[];
139+
return {
140+
owner,
141+
manager,
142+
members
143+
};
144+
}
145+
146+
export async function getFakeGroups(num: number = 5) {
147+
// create 5 groups
148+
const teamId = (await getFakeUser('Owner')).teamId;
149+
return MongoMemberGroupModel.create([
150+
...Array(num)
151+
.keys()
152+
.map((i) => ({
153+
name: `group${i + 1}`,
154+
teamId
155+
}))
156+
]) as Promise<MemberGroupSchemaType[]>;
157+
}
158+
159+
export async function getFakeOrgs() {
160+
// create 5 orgs
161+
const pathIds = ['root', 'org1', 'org2', 'org3', 'org4', 'org5'];
162+
const paths = ['', '/root', '/root', '/root', '/root/org1', '/root/org1/org4'];
163+
const teamId = (await getFakeUser('Owner')).teamId;
164+
return MongoOrgModel.create(
165+
pathIds.map((pathId, i) => ({
166+
pathId,
167+
name: pathId,
168+
path: paths[i],
169+
teamId
170+
}))
171+
) as Promise<OrgSchemaType[]>;
172+
}
173+
174+
export async function clean() {
175+
fakeUsers = {};
176+
}

Diff for: test/globalSetup.ts

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { MongoMemoryReplSet } from 'mongodb-memory-server';
2+
import type { TestProject } from 'vitest/node';
3+
4+
export default async function setup(project: TestProject) {
5+
const replset = await MongoMemoryReplSet.create({ replSet: { count: 1 } });
6+
const uri = replset.getUri();
7+
project.provide('MONGODB_URI', uri);
8+
9+
return async () => {
10+
await replset.stop();
11+
};
12+
}
13+
14+
declare module 'vitest' {
15+
export interface ProvidedContext {
16+
MONGODB_URI: string;
17+
}
18+
}

Diff for: test/mocks/request.ts

+63
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
12
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
3+
import { TeamPermission } from '@fastgpt/global/support/permission/user/controller';
4+
import { MongoGroupMemberModel } from '@fastgpt/service/support/permission/memberGroup/groupMemberSchema';
5+
import { getTmbInfoByTmbId } from '@fastgpt/service/support/user/team/controller';
26
import { vi } from 'vitest';
37

48
// vi.mock(import('@/service/middleware/entry'), async () => {
@@ -87,3 +91,62 @@ vi.mock(import('@fastgpt/service/support/permission/controller'), async (importO
8791
parseHeaderCert
8892
};
8993
});
94+
95+
vi.mock(
96+
import('@fastgpt/service/support/permission/memberGroup/controllers'),
97+
async (importOriginal) => {
98+
const mod = await importOriginal();
99+
const parseHeaderCert = vi.fn(
100+
({
101+
req,
102+
authToken = false,
103+
authRoot = false,
104+
authApiKey = false
105+
}: {
106+
req: MockReqType;
107+
authToken?: boolean;
108+
authRoot?: boolean;
109+
authApiKey?: boolean;
110+
}) => {
111+
const { auth } = req;
112+
if (!auth) {
113+
return Promise.reject(Error('unAuthorization(mock)'));
114+
}
115+
return Promise.resolve(auth);
116+
}
117+
);
118+
const authGroupMemberRole = vi.fn(async ({ groupId, role, ...props }: any) => {
119+
const result = await parseHeaderCert(props);
120+
const { teamId, tmbId, isRoot } = result;
121+
if (isRoot) {
122+
return {
123+
...result,
124+
permission: new TeamPermission({
125+
isOwner: true
126+
}),
127+
teamId,
128+
tmbId
129+
};
130+
}
131+
const [groupMember, tmb] = await Promise.all([
132+
MongoGroupMemberModel.findOne({ groupId, tmbId }),
133+
getTmbInfoByTmbId({ tmbId })
134+
]);
135+
136+
// Team admin or role check
137+
if (tmb.permission.hasManagePer || (groupMember && role.includes(groupMember.role))) {
138+
return {
139+
...result,
140+
permission: tmb.permission,
141+
teamId,
142+
tmbId
143+
};
144+
}
145+
return Promise.reject(TeamErrEnum.unAuthTeam);
146+
});
147+
return {
148+
...mod,
149+
authGroupMemberRole
150+
};
151+
}
152+
);

0 commit comments

Comments
 (0)