Remove listSaasUsers method and switch to paramterized getGroupMembers passing relations and update tests
Signed-off-by: Stephen Barry <sbarry@poppulo.com>
This commit is contained in:
@@ -398,12 +398,12 @@ describe('GitLabClient', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
describe('listSaasUsers', () => {
|
||||
describe('get gitlab.com users', () => {
|
||||
it('gets all users under group', async () => {
|
||||
server.use(
|
||||
graphql
|
||||
.link(`${MOCK_CONFIG.baseUrl}/api/graphql`)
|
||||
.query('listSaasUsers', async (_, res, ctx) =>
|
||||
.query('getGroupMembers', async (_, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
group: {
|
||||
@@ -436,7 +436,9 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
const saasMembers = (await client.listSaasUsers('group1')).items;
|
||||
const saasMembers = (
|
||||
await client.getGroupMembers('group1', 'DIRECT, DESCENDANTS')
|
||||
).items;
|
||||
const expectedSaasMember = [
|
||||
{
|
||||
id: 1,
|
||||
@@ -457,7 +459,7 @@ describe('GitLabClient', () => {
|
||||
server.use(
|
||||
graphql
|
||||
.link(`${MOCK_CONFIG.baseUrl}/api/graphql`)
|
||||
.query('listSaasUsers', async (_, res, ctx) =>
|
||||
.query('getGroupMembers', async (_, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
group: {},
|
||||
@@ -470,7 +472,9 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
const saasMembers = (await client.listSaasUsers('group1')).items;
|
||||
const saasMembers = (
|
||||
await client.getGroupMembers('group1', 'DIRECT, DESCENDANTS')
|
||||
).items;
|
||||
|
||||
expect(saasMembers).toEqual([]);
|
||||
});
|
||||
@@ -479,7 +483,7 @@ describe('GitLabClient', () => {
|
||||
server.use(
|
||||
graphql
|
||||
.link(`${MOCK_CONFIG.baseUrl}/api/graphql`)
|
||||
.query('listSaasUsers', async (_, res, ctx) =>
|
||||
.query('getGroupMembers', async (_, res, ctx) =>
|
||||
res(
|
||||
ctx.errors([
|
||||
{ message: 'Unexpected end of document', locations: [] },
|
||||
@@ -492,7 +496,9 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
await expect(() => client.listSaasUsers('group1')).rejects.toThrow(
|
||||
await expect(() =>
|
||||
client.getGroupMembers('group1', 'DIRECT, DESCENDANTS'),
|
||||
).rejects.toThrow(
|
||||
'GraphQL errors: [{"message":"Unexpected end of document","locations":[]}]',
|
||||
);
|
||||
});
|
||||
@@ -500,7 +506,7 @@ describe('GitLabClient', () => {
|
||||
server.use(
|
||||
graphql
|
||||
.link(`${MOCK_CONFIG.baseUrl}/api/graphql`)
|
||||
.query('listSaasUsers', async (req, res, ctx) =>
|
||||
.query('getGroupMembers', async (req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
group: {
|
||||
@@ -547,7 +553,9 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
const saasMembers = (await client.listSaasUsers('group1')).items;
|
||||
const saasMembers = (
|
||||
await client.getGroupMembers('group1', 'DIRECT, DESCENDANTS')
|
||||
).items;
|
||||
|
||||
const expectedSaasMember1 = {
|
||||
id: 1,
|
||||
@@ -751,7 +759,19 @@ describe('GitLabClient', () => {
|
||||
ctx.data({
|
||||
group: {
|
||||
groupMembers: {
|
||||
nodes: [{ user: { id: 'gid://gitlab/User/1' } }],
|
||||
nodes: [
|
||||
{
|
||||
user: {
|
||||
id: 'gid://gitlab/User/1',
|
||||
username: 'user1',
|
||||
publicEmail: 'user1@example.com',
|
||||
name: 'user1',
|
||||
state: 'active',
|
||||
webUrl: 'user1.com',
|
||||
avatarUrl: 'user1',
|
||||
},
|
||||
},
|
||||
],
|
||||
pageInfo: {
|
||||
endCursor: 'end',
|
||||
hasNextPage: false,
|
||||
@@ -767,9 +787,19 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
const members = await client.getGroupMembers('group1');
|
||||
const members = await client.getGroupMembers('group1', 'DIRECT');
|
||||
|
||||
expect(members).toEqual([1]);
|
||||
const user = {
|
||||
id: 1,
|
||||
username: 'user1',
|
||||
email: 'user1@example.com',
|
||||
name: 'user1',
|
||||
state: 'active',
|
||||
web_url: 'user1.com',
|
||||
avatar_url: 'user1',
|
||||
};
|
||||
|
||||
expect(members.items).toEqual([user]);
|
||||
});
|
||||
|
||||
it('gets member IDs with token without full permissions', async () => {
|
||||
@@ -789,9 +819,9 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
const members = await client.getGroupMembers('group1');
|
||||
const members = await client.getGroupMembers('group1', 'DIRECT');
|
||||
|
||||
expect(members).toEqual([]);
|
||||
expect(members.items).toEqual([]);
|
||||
});
|
||||
|
||||
it('rejects when GraphQL returns errors', async () => {
|
||||
@@ -811,7 +841,9 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
await expect(() => client.getGroupMembers('group1')).rejects.toThrow(
|
||||
await expect(() =>
|
||||
client.getGroupMembers('group1', 'DIRECT'),
|
||||
).rejects.toThrow(
|
||||
'GraphQL errors: [{"message":"Unexpected end of document","locations":[]}]',
|
||||
);
|
||||
});
|
||||
@@ -843,9 +875,10 @@ describe('GitLabClient', () => {
|
||||
logger: getVoidLogger(),
|
||||
});
|
||||
|
||||
const members = await client.getGroupMembers('group1');
|
||||
const members = await client.getGroupMembers('group1', 'DIRECT');
|
||||
|
||||
expect(members).toEqual([1, 2]);
|
||||
expect(members.items[0].id).toEqual(1);
|
||||
expect(members.items[1].id).toEqual(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -96,79 +96,6 @@ export class GitLabClient {
|
||||
return this.pagedRequest(`/groups`, options);
|
||||
}
|
||||
|
||||
async listSaasUsers(groupPath: string): Promise<PagedResponse<GitLabUser>> {
|
||||
const items: GitLabUser[] = [];
|
||||
let hasNextPage: boolean = false;
|
||||
let endCursor: string | null = null;
|
||||
|
||||
do {
|
||||
const response: GitLabGroupMembersResponse = await fetch(
|
||||
`${this.config.baseUrl}/api/graphql`,
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
...getGitLabRequestOptions(this.config).headers,
|
||||
['Content-Type']: 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
variables: { group: groupPath, endCursor },
|
||||
query: `query listSaasUsers($group: ID!, $endCursor: String) {
|
||||
group(fullPath: $group) {
|
||||
groupMembers(first: 100, relations: [DESCENDANTS], after: $endCursor) {
|
||||
nodes {
|
||||
user {
|
||||
id
|
||||
username
|
||||
publicEmail
|
||||
name
|
||||
state
|
||||
webUrl
|
||||
avatarUrl
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
endCursor
|
||||
hasNextPage
|
||||
}
|
||||
}
|
||||
}
|
||||
}`,
|
||||
}),
|
||||
},
|
||||
).then(r => r.json());
|
||||
if (response.errors) {
|
||||
throw new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`);
|
||||
}
|
||||
|
||||
if (!response.data.group?.groupMembers?.nodes) {
|
||||
this.logger.warn(
|
||||
`Couldn't get members under ${groupPath}. The provided token might not have sufficient permissions`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
const usersData = response.data.group.groupMembers.nodes;
|
||||
|
||||
for (let i = 0; i < usersData.length; i++) {
|
||||
const userItem = usersData[i];
|
||||
|
||||
const formattedUserResponse = {
|
||||
id: Number(userItem.user.id.replace(/^gid:\/\/gitlab\/User\//, '')),
|
||||
username: userItem.user.username,
|
||||
email: userItem.user.publicEmail,
|
||||
name: userItem.user.name,
|
||||
state: userItem.user.state,
|
||||
web_url: userItem.user.webUrl,
|
||||
avatar_url: userItem.user.avatarUrl,
|
||||
};
|
||||
|
||||
items.push(formattedUserResponse);
|
||||
}
|
||||
({ hasNextPage, endCursor } = response.data.group.groupMembers.pageInfo);
|
||||
} while (hasNextPage);
|
||||
return { items };
|
||||
}
|
||||
|
||||
async listDescendantGroups(
|
||||
groupPath: string,
|
||||
): Promise<PagedResponse<GitLabGroup>> {
|
||||
@@ -243,8 +170,11 @@ export class GitLabClient {
|
||||
return { items };
|
||||
}
|
||||
|
||||
async getGroupMembers(groupPath: string): Promise<number[]> {
|
||||
const memberIds = [];
|
||||
async getGroupMembers(
|
||||
groupPath: string,
|
||||
relations: string,
|
||||
): Promise<PagedResponse<GitLabUser>> {
|
||||
const items: GitLabUser[] = [];
|
||||
let hasNextPage: boolean = false;
|
||||
let endCursor: string | null = null;
|
||||
do {
|
||||
@@ -257,13 +187,19 @@ export class GitLabClient {
|
||||
['Content-Type']: 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
variables: { group: groupPath, endCursor },
|
||||
variables: { group: groupPath, relations: relations, endCursor },
|
||||
query: `query getGroupMembers($group: ID!, $endCursor: String) {
|
||||
group(fullPath: $group) {
|
||||
groupMembers(first: 100, relations: [DIRECT], after: $endCursor) {
|
||||
groupMembers(first: 100, relations: [$relations], after: $endCursor) {
|
||||
nodes {
|
||||
user {
|
||||
id
|
||||
username
|
||||
publicEmail
|
||||
name
|
||||
state
|
||||
webUrl
|
||||
avatarUrl
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
@@ -287,16 +223,26 @@ export class GitLabClient {
|
||||
continue;
|
||||
}
|
||||
|
||||
memberIds.push(
|
||||
...response.data.group.groupMembers.nodes
|
||||
.filter(n => n.user)
|
||||
.map(node =>
|
||||
Number(node.user.id.replace(/^gid:\/\/gitlab\/User\//, '')),
|
||||
),
|
||||
);
|
||||
const usersData = response.data.group.groupMembers.nodes;
|
||||
|
||||
for (let i = 0; i < usersData.length; i++) {
|
||||
const userItem = usersData[i];
|
||||
|
||||
const formattedUserResponse = {
|
||||
id: Number(userItem.user.id.replace(/^gid:\/\/gitlab\/User\//, '')),
|
||||
username: userItem.user.username,
|
||||
email: userItem.user.publicEmail,
|
||||
name: userItem.user.name,
|
||||
state: userItem.user.state,
|
||||
web_url: userItem.user.webUrl,
|
||||
avatar_url: userItem.user.avatarUrl,
|
||||
};
|
||||
|
||||
items.push(formattedUserResponse);
|
||||
}
|
||||
({ hasNextPage, endCursor } = response.data.group.groupMembers.pageInfo);
|
||||
} while (hasNextPage);
|
||||
return memberIds;
|
||||
return { items };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -550,7 +550,7 @@ describe('GitlabOrgDiscoveryEntityProvider', () => {
|
||||
),
|
||||
graphql
|
||||
.link('https://gitlab.com/api/graphql')
|
||||
.query('listSaasUsers', async (_, res, ctx) =>
|
||||
.query('getGroupMembers', async (_, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
group: {
|
||||
@@ -634,7 +634,7 @@ describe('GitlabOrgDiscoveryEntityProvider', () => {
|
||||
name: 'testuser1',
|
||||
},
|
||||
spec: {
|
||||
memberOf: ['group2'],
|
||||
memberOf: ['group2', 'group3'],
|
||||
profile: {
|
||||
displayName: 'Test User 1',
|
||||
email: 'testuser1@example.com',
|
||||
@@ -659,7 +659,7 @@ describe('GitlabOrgDiscoveryEntityProvider', () => {
|
||||
name: 'testuser2',
|
||||
},
|
||||
spec: {
|
||||
memberOf: ['group3'],
|
||||
memberOf: ['group2', 'group3'],
|
||||
profile: {
|
||||
displayName: 'Test User 2',
|
||||
email: 'testuser2@example.com',
|
||||
|
||||
+13
-4
@@ -190,8 +190,12 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider {
|
||||
});
|
||||
} else {
|
||||
groups = (await client.listDescendantGroups(this.config.group)).items;
|
||||
users = (await client.listSaasUsers(this.config.group.split('/')[0]))
|
||||
.items;
|
||||
users = (
|
||||
await client.getGroupMembers(
|
||||
this.config.group.split('/')[0],
|
||||
'DIRECT, DESCENDANTS',
|
||||
)
|
||||
).items;
|
||||
}
|
||||
|
||||
const idMappedUser: { [userId: number]: GitLabUser } = {};
|
||||
@@ -236,8 +240,13 @@ export class GitlabOrgDiscoveryEntityProvider implements EntityProvider {
|
||||
groupRes.scanned++;
|
||||
groupRes.matches.push(group);
|
||||
|
||||
for (const id of await client.getGroupMembers(group.full_path)) {
|
||||
const user = idMappedUser[id];
|
||||
const groupUsers = await client.getGroupMembers(
|
||||
group.full_path,
|
||||
'DIRECT',
|
||||
);
|
||||
|
||||
for (const groupUser of groupUsers.items) {
|
||||
const user = idMappedUser[groupUser.id];
|
||||
if (user) {
|
||||
user.groups = (user.groups ?? []).concat(group);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user