Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/access-control/group/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ Update the details of an existing group in an iTwin.
**Type:** `string` **Required:** No

- **`--ims-group`**
A list of IMS Groups to be linked to the group.
A list of IMS Groups to be linked to the group. Max amount of 50.
**Type:** `string` **Required:** No **Multiple:** Yes

- **`--member`**
A list of members (emails) to be assigned to the group.
A list of members (emails) to be assigned to the group. Max amount of 50.
**Type:** `string` **Required:** No **Multiple:** Yes

- **`-n, --name`**
Expand Down
2 changes: 1 addition & 1 deletion docs/access-control/member/group/add.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Add one or more groups as members to an iTwin.
## Options

- **`--groups`**
A list of groups to add, each with a groupId and roleIds.
A list of groups to add, each with a groupId and roleIds. A maximum of 50 role assignments can be performed.
**Type:** `string` **Required:** Yes

- **`-i, --itwin-id`**
Expand Down
2 changes: 1 addition & 1 deletion docs/access-control/member/group/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Update the role assignments for a group in an iTwin.
**Type:** `string` **Required:** Yes

- **`--role-id`**
A list of role IDs to assign to the group.
A list of role IDs to assign to the group. Max amount of 50.
**Type:** `string` **Required:** Yes **Multiple:** Yes

## Examples
Expand Down
2 changes: 1 addition & 1 deletion docs/access-control/member/user/add.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Add one or more user members to an iTwin.
**Type:** `string` **Required:** Yes

- **`--members`**
A list of members to add, each with an email and a list of role IDs.
A list of members to add, each with an email and a list of role IDs. A maximum of 50 role assignments can be performed.
**Type:** `string` **Required:** Yes

## Examples
Expand Down
2 changes: 1 addition & 1 deletion docs/access-control/member/user/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Update the role assignments for a user in an iTwin.
**Type:** `string` **Required:** Yes

- **`--role-id`**
A list of role IDs to assign to the user.
A list of role IDs to assign to the user. Max amount of 50.
**Type:** `string` **Required:** Yes **Multiple:** Yes

## Examples
Expand Down
2 changes: 1 addition & 1 deletion docs/user/info.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Retrieve information about specific users based on their user IDs.
## Options

- **`--user-id`**
User IDs to retrieve information for.
User IDs to retrieve information for. Max amount of 1000.
**Type:** `string` **Required:** Yes **Multiple:** Yes

## Examples
Expand Down
36 changes: 36 additions & 0 deletions integration-tests/access-control/group.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,42 @@ const tests = () => {
const groupInfo = await runCommand<group>(`access-control group info --itwin-id ${iTwinId} -g ${newGroup.result!.id}`);
expect(groupInfo.error?.message).to.contain('GroupNotFound')
});

it('Should fail to update group and return an error if too many members are provided', async () => {
const newGroup = await runCommand<group>(`access-control group create --itwin-id ${iTwinId} --name Test3 --description Description3`);
expect(newGroup.result).is.not.undefined;
expect(newGroup.result!.id).is.not.undefined;

let updateCommand = `access-control group update --itwin-id ${iTwinId} --group-id ${newGroup.result!.id}`
for (let i = 0; i < 51; i++) {
updateCommand += ` --member user${i}@bentley.m8r.co`
}

const updateGroup = await runCommand(updateCommand);
const deleteGroup = await runCommand(`access-control group delete --itwin-id ${iTwinId} --group-id ${newGroup.result!.id}`);
expect(deleteGroup.stdout).to.contain('deleted');

expect(updateGroup.error).to.not.be.undefined;
expect(updateGroup.error?.message).to.be.equal('A maximum of 50 members can be provided.');
});

it('Should fail to update group and return an error if too many ims-groups are provided', async () => {
const newGroup = await runCommand<group>(`access-control group create --itwin-id ${iTwinId} --name Test3 --description Description3`);
expect(newGroup.result).is.not.undefined;
expect(newGroup.result!.id).is.not.undefined;

let updateCommand = `access-control group update --itwin-id ${iTwinId} --group-id ${newGroup.result!.id}`
for (let i = 0; i < 51; i++) {
updateCommand += ` --ims-group IMS_Group_${i}`;
}

const updateGroup = await runCommand(updateCommand);
const deleteGroup = await runCommand(`access-control group delete --itwin-id ${iTwinId} --group-id ${newGroup.result!.id}`);
expect(deleteGroup.stdout).to.contain('deleted');

expect(updateGroup.error).to.not.be.undefined;
expect(updateGroup.error?.message).to.be.equal('A maximum of 50 ims groups can be provided.');
});
};

export default tests;
Expand Down
33 changes: 33 additions & 0 deletions integration-tests/access-control/member/group.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,39 @@ const tests = () => {
expect(resultDelete.error).to.be.undefined;
expect(resultDelete.stdout).to.contain('deleted');
});

it('Should fail to add iTwin group members, when there are too many role assignments', async () => {
const groups: {groupId: string, roleIds:string[]}[] = [];
for(let i = 0; i < 11; i++) {
groups.push({
groupId: crypto.randomUUID(),
roleIds: [
crypto.randomUUID(),
crypto.randomUUID(),
crypto.randomUUID(),
crypto.randomUUID(),
crypto.randomUUID(),
]
})
}

const serializedGroupsInfo = JSON.stringify(groups);

const result = await runCommand<GroupMemberInfo[]>(`access-control member group add --itwin-id ${iTwinId} --groups ${serializedGroupsInfo}`);
expect(result.error).to.not.be.undefined;
expect(result.error?.message).to.be.equal('A maximum of 50 role assignments can be performed.');
});

it('Should fail to update iTwin group, when there are too many roles assigned', async () => {
let command = `access-control member group update --itwin-id ${iTwinId} --group-id ${groupId}`;

for(let i = 0; i < 51; i++)
command += ` --role-id role${i}`

const result = await runCommand<GroupMemberInfo[]>(command);
expect(result.error).to.not.be.undefined;
expect(result.error?.message).to.be.equal('A maximum of 50 roles can be assigned.');
});
};

export default tests;
Expand Down
35 changes: 35 additions & 0 deletions integration-tests/access-control/member/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,41 @@ const tests = () => {
expect(updateMemberResult.result!.roles.some(role => role.id === usersInfo.result![0].roles[0].id)).to.be.true;
});

it('Should fail to add iTwin user members, when there are too many role assignments', async () => {
const members: {email: string, roleIds:string[]}[] = [];
for(let i = 0; i < 11; i++) {
members.push({
email: `email${i}@bentley.m8r.co`,
roleIds: [
crypto.randomUUID(),
crypto.randomUUID(),
crypto.randomUUID(),
crypto.randomUUID(),
crypto.randomUUID(),
]
})
}

const serializedMembersInfo = JSON.stringify(members);

const result = await runCommand<membersResponse>(`access-control member user add --itwin-id ${iTwinId} --members ${serializedMembersInfo}`);
expect(result.error).to.not.be.undefined;
expect(result.error?.message).to.be.equal('A maximum of 50 role assignments can be performed.');
});

it('Should fail to update iTwin group, when there are too many roles assigned', async () => {
const usersInfo = await runCommand<member[]>(`access-control member user list --itwin-id ${iTwinId}`);
expect(usersInfo.result).is.not.undefined;
expect(usersInfo.result!.length).to.be.equal(1);

let command = `access-control member user update --itwin-id ${iTwinId} --member-id ${usersInfo.result![0].id}`;
for(let i = 0; i < 51; i++)
command += ` --role-id role${i}`

const result = await runCommand<membersResponse>(command);
expect(result.error).to.not.be.undefined;
expect(result.error?.message).to.be.equal('A maximum of 50 roles can be assigned.');
});
};

export default tests;
Expand Down
11 changes: 11 additions & 0 deletions integration-tests/user/info.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ const tests = () => describe('info', () => {
expect(result.error).to.be.not.undefined;
expect(result.error!.message).to.include('Invalid request body');
});

it('should return an error for too many user IDs', async () => {
let command = "user info"
for(let i = 0; i < 1001; i++) {
command += ` --user-id ${crypto.randomUUID()}`
}

const result = await runCommand(command);
expect(result.error).to.be.not.undefined;
expect(result.error?.message).to.be.equal('A maximum of 1000 user IDs can be provided.')
});
});

export default tests;
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/utils/run-suite-if-main-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { isNativeAuthAccessTokenCached } from './helpers';
*/
function isMainModule(meta: {url: string}) {
for (const arg of process.argv) {
if(arg.match(/integration-tests\/.*\.test\.ts/) === null) {
if(arg.match(/integration-tests(\/|\\).*\.test\.ts/) === null) {
continue;
}

Expand Down
16 changes: 12 additions & 4 deletions src/commands/access-control/group/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ export default class UpdateAccessControlGroup extends BaseCommand {
required: true,
}),
"ims-group": Flags.string({
description: 'A list of IMS Groups to be linked to the group.',
description: 'A list of IMS Groups to be linked to the group. Max amount of 50.',
helpValue: '<string>',
multiple: true,
}),
"itwin-id": CustomFlags.iTwinIDFlag({
description: 'The ID of the iTwin where the group exists.'
}),
member: Flags.string({
description: 'A list of members (emails) to be assigned to the group.',
description: 'A list of members (emails) to be assigned to the group. Max amount of 50.',
helpValue: '<string>',
multiple: true,
}),
Expand All @@ -62,7 +62,15 @@ export default class UpdateAccessControlGroup extends BaseCommand {

async run() {
const { flags } = await this.parse(UpdateAccessControlGroup);


if(flags['ims-group'] !== undefined && flags["ims-group"]!.length > 50) {
this.error("A maximum of 50 ims groups can be provided.");
}

if(flags.member !== undefined && flags.member!.length > 50) {
this.error("A maximum of 50 members can be provided.");
}

const client = await this.getAccessControlApiClient();

const response = await client.updateGroup(flags["itwin-id"], flags["group-id"], {
Expand All @@ -71,7 +79,7 @@ export default class UpdateAccessControlGroup extends BaseCommand {
members: flags.member,
name: flags.name,
});

return this.logAndReturnResult(response.group);
}
}
15 changes: 11 additions & 4 deletions src/commands/access-control/member/group/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default class AddGroupMembers extends BaseCommand {

static flags = {
groups: Flags.string({
description: 'A list of groups to add, each with a groupId and roleIds.',
description: 'A list of groups to add, each with a groupId and roleIds. A maximum of 50 role assignments can be performed.',
helpValue: '<string>',
required: true
}),
Expand All @@ -41,11 +41,18 @@ export default class AddGroupMembers extends BaseCommand {

const client = await this.getAccessControlMemberClient();

const members = JSON.parse(flags.groups);
const parsed = members as GroupMember[];
const members = JSON.parse(flags.groups) as GroupMember[];

let roleAssignmentCount = 0;
for (const member of members)
roleAssignmentCount += member.roleIds.length;

if(roleAssignmentCount > 50) {
this.error("A maximum of 50 role assignments can be performed.");
}

const response = await client.addGroupMember(flags["itwin-id"], {
members: parsed,
members,
});

return this.logAndReturnResult(response.members);
Expand Down
6 changes: 5 additions & 1 deletion src/commands/access-control/member/group/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export default class UpdateGroupMember extends BaseCommand {
description: 'The ID of the iTwin to which the groups will be added.'
}),
"role-id": Flags.string({
description: 'A list of role IDs to assign to the group.',
description: 'A list of role IDs to assign to the group. Max amount of 50.',
helpValue: '<string>',
multiple: true,
required: true,
Expand All @@ -45,6 +45,10 @@ export default class UpdateGroupMember extends BaseCommand {
async run() {
const { flags } = await this.parse(UpdateGroupMember);

if(flags['role-id'] !== undefined && flags["role-id"]!.length > 50) {
this.error("A maximum of 50 roles can be assigned.");
}

const client = await this.getAccessControlMemberClient();

const response = await client.updateGroupMember(flags["itwin-id"], flags["group-id"], flags["role-id"]);
Expand Down
11 changes: 10 additions & 1 deletion src/commands/access-control/member/user/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class AddUserMembers extends BaseCommand {
description: 'The ID of the iTwin to which the users will be added.'
}),
members: Flags.string({
description: 'A list of members to add, each with an email and a list of role IDs.',
description: 'A list of members to add, each with an email and a list of role IDs. A maximum of 50 role assignments can be performed.',
helpValue: '<string>',
required: true,
}),
Expand All @@ -42,6 +42,15 @@ export default class AddUserMembers extends BaseCommand {
const client = await this.getAccessControlMemberClient();

const members = JSON.parse(flags.members) as addMember[];

let roleAssignmentCount = 0;
for (const member of members)
roleAssignmentCount += member.roleIds.length;

if(roleAssignmentCount > 50) {
this.error("A maximum of 50 role assignments can be performed.");
}

const response = await client.addUserMembers(flags["itwin-id"], {
members,
});
Expand Down
6 changes: 5 additions & 1 deletion src/commands/access-control/member/user/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default class UpdateUserMember extends BaseCommand {
required: true,
}),
"role-id": Flags.string({
description: 'A list of role IDs to assign to the user.',
description: 'A list of role IDs to assign to the user. Max amount of 50.',
helpValue: '<string>',
multiple: true,
required: true,
Expand All @@ -44,6 +44,10 @@ export default class UpdateUserMember extends BaseCommand {
async run() {
const { flags } = await this.parse(UpdateUserMember);

if(flags['role-id'] !== undefined && flags["role-id"]!.length > 50) {
this.error("A maximum of 50 roles can be assigned.");
}

const client = await this.getAccessControlMemberClient();

const response = await client.updateUserMember(flags["itwin-id"], flags["member-id"], flags["role-id"]);
Expand Down
6 changes: 5 additions & 1 deletion src/commands/user/info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default class UserInfo extends BaseCommand {

static flags = {
"user-id": Flags.string({
description: "User IDs to retrieve information for.",
description: "User IDs to retrieve information for. Max amount of 1000.",
helpValue: '<string>',
multiple: true,
required: true
Expand All @@ -35,6 +35,10 @@ export default class UserInfo extends BaseCommand {
async run() {
const { flags } = await this.parse(UserInfo);

if(flags["user-id"] !== undefined && flags["user-id"]!.length > 1000) {
this.error("A maximum of 1000 user IDs can be provided.");
}

const client = await this.getUserApiClient();
const response = await client.getUsers(flags["user-id"]);

Expand Down
12 changes: 6 additions & 6 deletions src/extensions/custom-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ export class CustomFlags {
});

static iTwinIDFlag = (config : CustomFlagConfig) => Flags.string({
char: 'i',
description: config.description,
env: 'ITP_ITWIN_ID',
helpValue: '<string>',
required: true
})
char: 'i',
description: config.description,
env: 'ITP_ITWIN_ID',
helpValue: '<string>',
required: true
})
}

export type CustomFlagConfig = {
Expand Down